/* ============================================================
   SIMEXDB — simexdb.css
   ============================================================ */

/* ── STRUCTURAL CLASSES — required by simexdb.js ──────────
   These classes are added/removed by JS at runtime.
   If embedding into another project and providing your own CSS,
   you must cover every class/selector listed here.
   See CLAUDE.md → Integration guide for the full reference.

   Selector                         Effect required
   ────────────────────────────────────────────────
   [data-enabled="false"]           display: none !important  (disabled panels)
   .sel                             selected row / card highlight
   .sorted                          active sort column header indicator
   .active                          active state on toggle buttons
   .tbl-group-hidden                display: none !important  (collapsed table group rows)
   .cards-group-hidden              display: none !important  (collapsed card group items)
   .facet-collapsed .facet-body     display: none             (collapsed facet list)
   .drawer-open                     sidebar visible on mobile (slide in from left)
   #drawer-backdrop.visible         backdrop shown (display: block)
   .viewport-filtering              amber left-border on timeline panel (filter active)
   .skeleton-row / .skeleton-cell   loading skeleton rows
   ──────────────────────────────────────────────────────── */

/* ── TOKENS ─────────────────────────────────────────────── */
:root {
  --font-display : 'Libre Baskerville', Georgia, serif;
  --font-body    : 'DM Sans', sans-serif;

  --c-bg         : #F7F4EF;
  --c-surface    : #FFFFFF;
  --c-border     : #E2DDD6;
  --c-border-mid : #CCC7BE;
  --c-text       : #1A1714;
  --c-text-mid   : #5C5650;
  --c-text-soft  : #736D67;
  --c-accent     : #1A1714;
  --c-info-bg    : #EEF5FF;
  --c-info-border: #BFDBFE;

  --shadow-sm    : 0 1px 3px rgba(0,0,0,.06);
  --shadow-md    : 0 4px 12px rgba(0,0,0,.08);
  --shadow-lg    : 0 8px 24px rgba(0,0,0,.12);
  --r            : 6px;
  --r-lg         : 10px;

  /* Amber — warning / active-filter tint */
  --c-warning-bg    : #FEF3C7;
  --c-warning-border: #FDE68A;
  --c-warning-text  : #92400E;

  /* Load-bar gradient */
  --c-progress-start: #3578B5;
  --c-progress-end  : #5BA3D9;

  /* Timeline inactive-overlay tint */
  --c-tl-overlay    : rgba(150, 150, 200, 0.45);
}

/* ── RESET ──────────────────────────────────────────────── */
/* Scoped to the engine's own regions (#72) — .dash, plus #main-panels, each
   panel ([data-component]) and #lb-dialog for hosts whose .dash doesn't wrap
   the panels (TheWidjiWay puts each panel in its own .card) — so
   a host page's markup keeps its
   margins and padding. :where() adds no specificity: every rule here keeps the
   specificity it had unscoped, so existing overrides still win. */
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover), :where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) *, :where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) *::before, :where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) *::after { box-sizing: border-box; margin: 0; padding: 0; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) svg.icon { display: inline-block; vertical-align: middle; overflow: visible; flex-shrink: 0; }
/* Page-level only on standalone pages (.dash straight under <body>) — never a host page's own */
:where(html:has(> body > .dash)) { scrollbar-gutter: stable; }
:where(body:has(> .dash)) {
  margin      : 0;   /* the scoped reset no longer reaches <body> */
  font-family : var(--font-body);
  font-size   : 13px;
  color       : var(--c-text);
  background  : var(--c-bg);
  line-height : 1.5;
}
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) a { color: inherit; }

/* ── LAYOUT ─────────────────────────────────────────────── */
.dash {
  display            : grid;
  grid-template-rows : auto auto 1fr auto;
  min-height         : 100vh;
}

/* ── TOPBAR ─────────────────────────────────────────────── */
.topbar {
  display         : flex;
  align-items     : center;
  justify-content : space-between;
  padding         : 11px 16px;
  border-bottom   : 1px solid var(--c-border);
  background      : var(--c-surface);
  box-shadow      : var(--shadow-sm);
  position        : sticky;
  top             : 0;
  z-index         : 1100;
}
.topbar-title {
  font-family    : var(--font-display);
  font-size      : 16px;
  font-weight    : 700;
  letter-spacing : -.01em;
}
.topbar-title #dash-subtitle {
  font-weight  : 400;
  font-style   : italic;
  color        : var(--c-text-mid);
  font-size    : 13px;
  margin-left  : 8px;
  font-family  : var(--font-display);
}
.topbar-right { display: flex; align-items: center; gap: 8px; }

/* ── LOADING PROGRESS BAR ───────────────────────────────── */
#load-bar-wrap {
  height     : 3px;
  background : var(--c-border);
  overflow   : hidden;
}
#load-bar {
  height     : 3px;
  width      : 100%;
  background : linear-gradient(90deg, var(--c-progress-start), var(--c-progress-end));
  transform  : scaleX(0);              /* progress via transform, not width — no layout per frame */
  transform-origin: left;
  transition : transform 1.2s ease;
  display    : none;
}

/* Feed badge */
.feed-badge {
  font-size     : 11px;
  padding       : 2px 8px;
  border-radius : 10px;
  border        : 1px solid var(--c-border);
  color         : var(--c-text-soft);
  background    : var(--c-bg);
  white-space   : nowrap;
  transition    : all .3s;
}
.feed-badge.live   { border-color:#86EFAC; color:#15803D; background:#F0FDF4; }
.feed-badge.sample { border-color:var(--c-warning-border); color:var(--c-warning-text); background:#FFFBEB; }
.feed-badge.error  { border-color:#FECACA; color:#991B1B; background:#FEF2F2; }

.feed-source-link { text-decoration: none; }
.feed-source-link[aria-disabled="true"] { opacity: .5; pointer-events: none; cursor: default; }

/* ── TWO-COLUMN SHELL ───────────────────────────────────── */
.layout {
  display               : grid;
  grid-template-columns : 214px 1fr;
  flex                  : 1;
}

/* ── SIDEBAR ────────────────────────────────────────────── */
.sidebar {
  border-right    : 1px solid var(--c-border);
  padding         : 12px;
  overflow-y      : auto;
  background      : var(--c-surface);
  display         : flex;
  flex-direction  : column;
  gap             : 10px;
  max-height      : calc(100vh - 48px);  /* topbar + load bar */
  position        : sticky;
  top             : 48px;
}

/* Search */
.search-wrap { position: relative; }
.search-wrap .si-icon {
  position       : absolute;
  left           : 8px;
  top            : 50%;
  transform      : translateY(-50%);
  font-size      : 13px;
  color          : var(--c-text-soft);
  pointer-events : none;
}
.search-wrap input {
  width         : 100%;
  padding       : 6px 26px 6px 26px;
  font-size     : 12px;
  font-family   : var(--font-body);
  border        : 1px solid var(--c-border);
  border-radius : var(--r);
  background    : var(--c-bg);
  color         : var(--c-text);
  transition    : border-color .15s;
}
.search-wrap input:focus { outline: none; border-color: var(--c-border-mid); background: var(--c-surface); }
.search-wrap input:focus-visible { outline: 2px solid var(--c-text); outline-offset: 1px; }
.search-wrap input::placeholder { color: var(--c-text-soft); }
.clear-x {
  position   : absolute;
  right      : 7px;
  top        : 50%;
  transform  : translateY(-50%);
  font-size  : 12px;
  color      : var(--c-text-soft);
  cursor     : pointer;
  background : none;
  border     : none;
  padding    : 0;
  display    : none;
}
.search-wrap input:not(:placeholder-shown) ~ .clear-x { display: block; }

/* ── SITE FOOTER ────────────────────────────────────────────
   Demo-repo scaffolding: a row of links (GitHub, Data source, engine version;
   on the main demo also "Examples" → the examples hub). #feed-source and
   #simexdb-version are filled by the engine; the rest is plain page HTML. */
.site-footer {
  border-top : 1px solid var(--c-border);
  padding    : 12px 16px;
  background : var(--c-surface);
}
.site-footer-top {
  display      : flex;
  flex-wrap    : wrap;
  align-items  : center;
  gap          : 6px 14px;
}
.site-footer-link {
  display         : inline-flex;
  align-items     : center;
  gap             : 5px;
  padding         : 5px 9px;
  font-size       : 11px;
  color           : var(--c-text-mid);
  background      : var(--c-bg);
  border          : 1px solid var(--c-border);
  border-radius   : var(--r);
  text-decoration : none;
  transition      : border-color .15s, color .15s, background .15s;
}
.site-footer-link:hover { border-color: var(--c-border-mid); color: var(--c-text); background: var(--c-surface); }
.site-footer-link .icon { flex-shrink: 0; font-size: 12px; }

/* Facets */
.facet-section { display: flex; flex-direction: column; gap: 6px; }
.facet-group   { border: 1px solid var(--c-border); border-radius: var(--r); overflow: hidden; }
.facet-hd {
  display         : flex;
  align-items     : center;
  justify-content : space-between;
  padding         : 6px 8px;
  background      : var(--c-bg);
  border-bottom   : 1px solid var(--c-border);
}
.facet-hd-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--c-text-mid); }
.facet-hd-count { font-size: 10px; color: var(--c-text-soft); }
.facet-body     { padding: 4px 0; }   /* long lists: "Show all" + a filter box (setupLongList(), #78), not a scroll box; CONFIG.facets[].height still sets one */.facet-group.collapsible .facet-hd { cursor: pointer; user-select: none; }
.facet-group.facet-collapsed .facet-body { display: none; }
.facet-chevron  { font-size: 12px; color: var(--c-text-soft); transition: transform 0.2s ease; flex-shrink: 0; }
.facet-group.facet-collapsed .facet-chevron { transform: rotate(-90deg); }
/* 24px rows: the label is the click target, and WCAG 2.5.8 asks for 24px (#68) */
.facet-item     { display: flex; align-items: center; justify-content: space-between; padding: 0 8px; min-height: 24px; }
.facet-item[hidden], .facet-empty[hidden], .facet-more[hidden] { display: none; }
/* Long value lists (#78): filter box above the values, Show all / Show fewer below */
.facet-filter-wrap { padding: 2px 8px 6px; }
.facet-filter {
  width         : 100%;
  padding       : 4px 8px;
  font          : inherit;
  font-size     : 12px;
  color         : var(--c-text);
  background    : var(--c-surface);
  border        : 1px solid var(--c-border-mid);
  border-radius : var(--r);
}
.facet-more {
  display         : block;
  margin          : 4px 8px 2px;
  padding         : 2px 0;
  font            : inherit;
  font-size       : 11px;
  color           : var(--c-text-mid);
  background      : none;
  border          : 0;
  text-decoration : underline;
  cursor          : pointer;
}
.facet-more:hover { color: var(--c-text); }
.facet-filter:focus-visible, .facet-more:focus-visible { outline: 2px solid var(--c-text); outline-offset: 1px; }
.facet-item label { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px; color: var(--c-text); flex: 1; align-self: stretch; }
.facet-item input[type=checkbox] { width: 12px; height: 12px; cursor: pointer; accent-color: var(--c-accent); flex-shrink: 0; }
.facet-count { font-size: 10px; color: var(--c-text-soft); background: var(--c-bg); padding: 1px 5px; border-radius: 10px; border: 1px solid var(--c-border); flex-shrink: 0; }
.color-swatch { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
/* Nested facets (CONFIG.facets[].groups): a group row with a fold chevron,
   then its children indented under it. */
.facet-parent { padding-left: 2px; }
.facet-parent label { font-weight: 600; }
.facet-nest-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; margin: 0 6px 0 -4px; padding: 0;   /* 24px target with clear space before the checkbox (#68) */
  border: 0; background: none; color: var(--c-text-soft); cursor: pointer; flex-shrink: 0;
}
.facet-nest-toggle .icon { font-size: 12px; transition: transform 0.2s ease; }
.facet-nest-folded .facet-nest-toggle .icon { transform: rotate(-90deg); }
.facet-children { padding-left: 26px; }   /* under the parent row's checkbox */
.facet-nest-folded .facet-children { display: none; }
.result-count { font-size: 11px; color: var(--c-text-soft); margin-top: auto; padding-top: 4px; text-align: center; }

/* ── FACET SLIDER ────────────────────────────────────────── */
.facet-slider            { padding: 4px 8px 8px; }
.facet-slider-label      { font-size: 11px; font-weight: 600; color: var(--c-text-mid); text-align: center; margin-bottom: 10px; }
.facet-slider-track-wrap { position: relative; height: 24px; display: flex; align-items: center; }
.facet-slider-track      { position: absolute; left: 7px; right: 7px; height: 4px; background: var(--c-border); border-radius: 2px; }
.facet-slider-fill       { position: absolute; top: 0; bottom: 0; background: var(--c-progress-start); border-radius: 2px; transition: left .05s, right .05s; }
.facet-slider-thumb {
  position: absolute; width: 100%; height: 24px; margin: 0;   /* 24px tall: the thumbs' touch target (#68) */
  pointer-events: none; touch-action: none; background: transparent; outline: none;
  -webkit-appearance: none; appearance: none;
}
.facet-slider-thumb::-webkit-slider-thumb {
  -webkit-appearance: none; pointer-events: all; cursor: pointer;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--c-progress-start); border: 2px solid var(--c-surface);
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.facet-slider-thumb::-moz-range-thumb {
  pointer-events: all; cursor: pointer; border: 2px solid var(--c-surface);
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--c-progress-start); box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.facet-slider-thumb:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 4px var(--c-text); }
.facet-slider-thumb:focus-visible::-moz-range-thumb     { box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 4px var(--c-text); }
.facet-slider-bounds { display: flex; justify-content: space-between; font-size: 10px; color: var(--c-text-soft); margin-top: 6px; padding: 0 4px; }

/* ── MAIN PANELS ────────────────────────────────────────── */
.main { display: grid; }

.panel[data-enabled="false"] { display: none !important; }
.panel {
  border          : 1px solid var(--c-border);
  border-radius   : var(--r);
  overflow        : hidden;
  display         : flex;
  flex-direction  : column;
  background      : var(--c-surface);
  position        : relative;
}

.panel-hd {
  display         : flex;
  align-items     : flex-start;   /* rows, not a single centred line — see .panel-hd-right */
  justify-content : space-between;
  padding         : 0 12px;
  height          : 30px;
  min-height      : 30px;
  overflow        : hidden;       /* clips the wrapped second row until .hd-expanded */
  border-bottom   : 1px solid var(--c-border);
  background      : var(--c-bg);
  font-size       : 11px;
  font-weight     : 600;
  color           : var(--c-text-mid);
  text-transform  : uppercase;
  letter-spacing  : .05em;
  flex-shrink     : 0;
}
.panel-hd-left  { display: flex; align-items: center; gap: 6px; flex-shrink: 0; height: 29px; }
/* Header overflow (layoutPanelHeaders() in simexdb.js): the controls wrap, but
   the header stays one 30px row high, so anything that didn't fit sits on a
   clipped second line. A "⋯ N" toggle (.panel-hd-more) then appears and
   .hd-expanded opens the header to show it. Priority = page order: the last
   controls are the first to wrap. Each line is 29px (30px header − border),
   controls centred in it.
   Expanded, .panel-hd-right steps out of the box (display: contents) so the
   wrapped rows use the header's full width, under the label too — not just
   the right-hand column. layoutPanelHeader() sets `order` so the first row
   is unchanged: label, the controls that fit, then the toggle. */
.panel-hd-right {
  display         : flex;
  flex            : 1 1 0;
  min-width       : 0;
  flex-wrap       : wrap;
  justify-content : flex-end;
  align-items     : center;
  align-content   : flex-start;
  gap             : 0 4px;
  margin-left     : 8px;
}
.panel-hd-right > * { margin-block: 3px; }           /* ~23px controls + 3+3 = one 29px line */
.panel-hd-more {
  display         : none;
  align-items     : center;
  gap             : 3px;
  flex-shrink     : 0;
  height          : 23px;
  margin          : 3px 0 3px 4px;
  padding         : 0 6px;
  font            : inherit;
  font-weight     : 400;
  text-transform  : none;
  letter-spacing  : normal;
  color           : var(--c-text-mid);
  background      : transparent;
  border          : 1px solid var(--c-border);
  border-radius   : var(--r);
  cursor          : pointer;
}
.panel-hd-more:hover          { background: var(--c-surface); }
.panel-hd.hd-overflowing .panel-hd-more { display: flex; }
.panel-hd:not(.hd-expanded) .hd-clipped { visibility: hidden; }   /* clipped controls: not focusable or announced until ⋯ opens the header */
.panel-hd.hd-expanded         { height: auto; flex-wrap: wrap; justify-content: flex-end; column-gap: 4px; }
.panel-hd.hd-expanded .panel-hd-right { display: contents; }
.panel-hd.hd-expanded .panel-hd-left  { margin-right: auto; padding-right: 4px; }   /* + 4px gap = the collapsed 8px */
.panel-hd.hd-expanded .panel-hd-more  { margin-left: 0; }                           /* the 4px gap replaces it */

/* ── MAP ────────────────────────────────────────────────── */
/* isolation: the map is its own stacking context, so the map library's
   internal z-indexes (Leaflet's control corners are 1000, panes 400–700) stay
   inside it instead of competing with the page — otherwise the zoom /
   fullscreen / basemap buttons draw over a host's fixed header or a pinned
   filter bar as the page scrolls (seen on TheWidjiWay). */
#leaflet-map { flex: 1; min-height: 0; isolation: isolate; }

/* Cluster icon — replaces Leaflet.markercluster default styling */
/* Timeline panel full screen (#67, toggleTimelineFullscreen()): its own
   surface over the browser's black backdrop; the detail band's height is
   raised to fill the screen by the fullscreenchange handler. */
#panel-timeline:fullscreen { background: var(--c-surface); overflow: auto; border-radius: 0; }

/* In-map fullscreen control (Leaflet adapter) — same 30px .leaflet-bar
   button as zoom +/− directly above it; centres the inline SVG icon. */
.leaflet-control-fullscreen a {
  display         : flex;
  align-items     : center;
  justify-content : center;
  font-size       : 15px;
}
.cluster-icon { background: transparent; }
/* Spider legs for co-located records (spiderLegPolylineOptions in the Leaflet
   adapter) — CSS stroke beats the SVG presentation attribute, so the color
   follows the theme; dashed so a leg never reads as a route line. */
.cluster-spider-leg { stroke: var(--c-text-soft); }
.cluster-icon .cluster-count {
  width         : 30px;
  height        : 30px;
  border-radius : 50%;
  background    : var(--c-surface);
  border        : 2px solid var(--c-border-mid);
  color         : var(--c-text);
  font          : 600 11px / 26px var(--font-body, system-ui);
  text-align    : center;
  box-shadow    : 0 1px 5px rgba(0,0,0,.25);
  box-sizing    : border-box;
}

.dash-tooltip {
  background    : var(--c-surface);
  border        : 1px solid var(--c-border);
  border-radius : var(--r);
  box-shadow    : var(--shadow-md);
  padding       : 8px 10px;
  font-family   : var(--font-body);
  font-size     : 12px;
  width         : 250px;
  white-space   : normal;
  overflow-wrap : break-word;
  pointer-events: none;
}
.dash-tooltip strong  { font-size: 13px; display: block; margin-bottom: 3px; font-family: var(--font-display); }
.dash-tooltip .tt-meta   { color: var(--c-text-mid); font-size: 11px; line-height: 1.6; }
/* ── TIMELINE ───────────────────────────────────────────── */

.vis-timeline                { border: none !important; font-family: var(--font-body) !important; }
.vis-time-axis .vis-text     { font-size: 10px !important; color: var(--c-text-soft) !important; font-family: var(--font-body) !important; }
.vis-current-time            { background: #C53030 !important; width: 2px !important; opacity: .7; }
.vis-panel.vis-center,
.vis-panel.vis-left          { border-color: var(--c-border) !important; }
.vis-label                   { font-size: 11px !important; color: var(--c-text-mid) !important; font-family: var(--font-body) !important; }
.vis-tooltip {
  background    : var(--c-surface) !important;
  border        : 1px solid var(--c-border) !important;
  border-radius : var(--r) !important;
  box-shadow    : var(--shadow-md) !important;
  font-family   : var(--font-body) !important;
  font-size     : 12px !important;
  color         : var(--c-text) !important;
  padding       : 0 !important;
  max-width     : 260px !important;
  white-space   : normal !important;
  overflow-wrap : break-word !important;
}

/* ── LIGHTBOX / INLINE RECORD PANEL ────────────────────── */

/* Record detail panel — shown inside #lb-dialog (mobile) and #detail-pane (desktop) */
.lb-wrap {
  width         : 100%;
  background    : var(--c-surface);
  border-radius : var(--r-lg);
  overflow      : hidden;
  font-family   : var(--font-body);
}
.lb-body         { padding: 16px 18px 18px; }
.lb-name {
  font-family   : var(--font-display);
  font-size     : 17px;
  font-weight   : 700;
  margin-bottom : 8px;
  line-height   : 1.3;
}
.lb-name a       { color: var(--c-text); text-decoration: none; }
.lb-name a:hover { text-decoration: underline; }
.lb-meta {
  display      : grid;
  gap          : 5px;
  margin-bottom: 12px;
  padding-top  : 10px;
  padding-left : 8px;
  border-top   : 1px solid var(--c-border);
  border-left  : 3px solid var(--detail-color, transparent);
}
.lb-meta-row     { display: flex; justify-content: space-between; gap: 10px; font-size: 12px; }
.lb-meta-row span:first-child { color: var(--c-text-soft); }
.lb-meta-val     { font-weight: 500; text-align: right; color: var(--c-text); }
.lb-desc {
  font-size    : 12px;
  color        : var(--c-text-mid);
  line-height  : 1.6;
  margin-bottom: 10px;
  padding-top  : 10px;
  border-top   : 1px solid var(--c-border);
}
.lb-links   { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid var(--c-border); }
.lb-detail-btn {
  display    : block;
  margin-top : 12px;
  padding    : 10px 16px;
  background : var(--detail-color, var(--c-accent));
  color      : var(--detail-text, var(--c-surface));   /* readableText(--detail-color), set with it */
  text-align : center;
  border-radius: 6px;
  font-size  : 13px;
  font-weight: 600;
  text-decoration: none;
  transition : opacity .15s;
}
.lb-detail-btn:hover { opacity: .88; }

/* ── MOBILE DETAIL DIALOG ───────────────────────────────────── */
dialog#lb-dialog {
  border        : none;
  border-radius : var(--r-lg);
  padding       : 0;
  width         : min(420px, calc(100vw - 32px));
  max-height    : 85vh;
  overflow      : hidden;
  background    : var(--c-surface);
  box-shadow    : var(--shadow-lg);
  margin        : auto;
}
dialog#lb-dialog::backdrop { background: rgba(0, 0, 0, .5); }
#lb-content {
  max-height : 85vh;
  overflow-y : auto;
}
/* Close ✕ sits over the record's photo, so it carries its own solid disc —
   readable on any image, light or dark (was bare soft-grey text). */
.lb-close {
  position   : absolute;
  top        : 10px;
  right      : 10px;
  display    : inline-flex;
  align-items: center;
  justify-content: center;
  width      : 34px;
  height     : 34px;
  padding    : 0;
  font-size  : 18px;
  line-height: 1;
  color      : var(--c-text);
  background : var(--c-surface);
  border     : 1px solid var(--c-border-mid);
  border-radius: 50%;
  box-shadow : 0 1px 4px rgba(0, 0, 0, .25);
  cursor     : pointer;
  z-index    : 1;
}
.lb-close:hover { background: var(--c-bg); }
.lb-close:focus-visible { outline: 2px solid var(--c-text); outline-offset: 2px; }

/* ── RECORDS ────────────────────────────────────────────── */
.records-outer {
  flex            : 1;
  min-height      : 0;
  overflow        : auto;
  display         : flex;
  flex-direction  : column;
}
.table-wrap { flex: 1; }
table:where(#records-table)       { width: 100%; border-collapse: collapse; font-size: 11px; table-layout: fixed; }
:where(#records-table) thead       { position: sticky; top: 0; z-index: 10; }
:where(#records-table) th {
  padding        : 5px 10px;
  text-align     : left;
  font-weight    : 600;
  font-size      : 10px;
  text-transform : uppercase;
  letter-spacing : .04em;
  color          : var(--c-text-mid);
  border-bottom  : 1px solid var(--c-border);
  background     : var(--c-bg);
  white-space    : nowrap;
  cursor         : pointer;
  user-select    : none;
  overflow       : hidden;
  text-overflow  : ellipsis;
}
:where(#records-table) th:hover            { background: var(--c-border); }
:where(#records-table) th .si              { margin-left: 3px; color: var(--c-text-mid); font-size: 10px; }
:where(#records-table) th.sorted .si       { color: var(--c-text); }
:where(#records-table) td {
  padding        : 5px 10px;
  border-bottom  : 1px solid var(--c-border);
  overflow       : hidden;
  text-overflow  : ellipsis;
  white-space    : nowrap;
  vertical-align : middle;
}
:where(#records-table) tr:hover:not(.sel):not(.tbl-group-hdr) td { background: var(--c-bg); cursor: pointer; }
:where(#records-table) tr.sel td             { background: var(--c-info-bg); }
.tbl-group-hidden     { display: none !important; }

/* ── TABLE GROUP HEADERS ──────────────────────────────────── */
.tbl-group-hdr td {
  background    : var(--c-bg);
  border-top    : 1px solid var(--c-border-mid);
  border-bottom : 1px solid var(--c-border);
  padding       : 0;
  cursor        : pointer;
  user-select   : none;
}
.tbl-group-hdr td > * { pointer-events: none; }
.tbl-group-hdr-inner {
  display        : flex;
  align-items    : center;
  gap            : 6px;
  padding        : 5px 10px;
  /* a <button> (#68) — reset to look like the plain bar it replaced */
  box-sizing     : border-box;
  width          : 100%;
  margin         : 0;
  border         : 0;
  background     : none;
  font           : inherit;
  color          : inherit;
  text-align     : left;
  cursor         : pointer;
}
.tbl-group-swatch {
  width          : 8px;
  height         : 8px;
  border-radius  : 2px;
  flex-shrink    : 0;
  display        : inline-block;
}
.tbl-group-label {
  font-size      : 10px;
  font-weight    : 600;
  text-transform : uppercase;
  letter-spacing : .06em;
  color          : var(--c-text-mid);
}
.tbl-group-count {
  font-size      : 10px;
  color          : var(--c-text-soft);
  font-weight    : 400;
}
.tbl-group-chevron {
  margin-left    : auto;
  font-size      : 11px;
  color          : var(--c-text-soft);
  transition     : transform 0.15s ease;
}
.tbl-group-hdr.collapsed .tbl-group-chevron { transform: rotate(-90deg); }

/* ── SKELETON LOADING ───────────────────────────────────── */
@keyframes shimmer {
  0%   { background-position: -400px 0; }
  100% { background-position: 400px 0; }
}
.skeleton-cell {
  border-radius: 3px;
  background   : linear-gradient(90deg, var(--c-border) 25%, var(--c-bg) 50%, var(--c-border) 75%);
  background-size: 800px 100%;
  animation    : shimmer 1.4s infinite linear;
}
.skeleton-cell   { height: 12px; width: 80%; display: block; }
.skeleton-row td { padding: 8px 10px; }

/* ── PAGINATION ─────────────────────────────────────────── */
.pagination {
  display         : flex;
  align-items     : center;
  justify-content : space-between;
  padding         : 6px 10px;
  border-top      : 1px solid var(--c-border);
  background      : var(--c-bg);
  font-size       : 11px;
  color           : var(--c-text-mid);
  flex-shrink     : 0;
}
.page-btns { display: flex; align-items: center; gap: 4px; }
.page-btn  {
  padding       : 2px 8px;
  border-radius : var(--r);
  border        : 1px solid var(--c-border);
  background    : var(--c-surface);
  color         : var(--c-text-mid);
  font-size     : 11px;
  cursor        : pointer;
  font-family   : var(--font-body);
}
.page-btn:hover:not(:disabled) { border-color: var(--c-border-mid); color: var(--c-text); }
.page-btn:disabled              { opacity: .4; cursor: not-allowed; }
.page-btn.active                { background: var(--c-text); color: var(--c-surface); border-color: var(--c-text); }
.page-info { font-size: 11px; color: var(--c-text-soft); }

/* ── CARDS ──────────────────────────────────────────────── */
.cards-grid {
  display               : grid;
  grid-template-columns : repeat(auto-fill, minmax(200px, 1fr));
  gap                   : 10px;
  padding               : 12px;
  align-content         : start;
}
:where(#cards-grid) .card {
  background    : var(--c-surface);
  border        : 1px solid var(--c-border);
  border-radius : var(--r-lg);
  overflow      : hidden;
  cursor        : pointer;
  box-shadow    : var(--shadow-sm);
  transition    : box-shadow .15s, border-color .15s, transform .1s;
}
:where(#cards-grid) .card:hover                { box-shadow: var(--shadow-md); border-color: var(--c-border-mid); transform: translateY(-1px); }
:where(#cards-grid) .card.sel                  { border-color: var(--c-info-border); box-shadow: 0 0 0 3px rgba(59,130,246,.12); }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-img-placeholder {
  width           : 100%;
  height          : 80px;
  background      : linear-gradient(135deg, var(--c-bg) 0%, var(--c-border) 100%);
  display         : flex;
  align-items     : center;
  justify-content : center;
  color           : var(--c-text-soft);
  font-size       : 11px;
  font-style      : italic;
}
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-img     { width: 100%; height: 80px; object-fit: cover; display: block; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-body    { padding: 9px 11px 10px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-name    { font-family: var(--font-display); font-size: 12px; font-weight: 700; line-height: 1.3; margin-bottom: 5px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-name a  { color: var(--c-text); text-decoration: none; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-name a:hover { text-decoration: underline; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-tags    { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-bottom: 6px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-meta    { display: flex; flex-direction: column; gap: 3px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-meta-row{ display: flex; justify-content: space-between; font-size: 10px; color: var(--c-text-mid); gap: 6px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-meta-val{ color: var(--c-text); font-weight: 500; text-align: right; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-desc    { font-size: 10px; color: var(--c-text-mid); margin-top: 5px; line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-links   { display: flex; gap: 6px; margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--c-border); flex-wrap: wrap; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-link    { font-size: 10px; color: var(--c-text-mid); text-decoration: none; display: flex; align-items: center; gap: 3px; }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .card-link:hover { color: var(--c-text); }

/* ── CARDS GROUP HEADERS ────────────────────────────────────── */
.cards-group-hidden { display: none !important; }
.cards-group-hdr {
  grid-column   : 1 / -1;
  background    : var(--c-bg);
  border        : 1px solid var(--c-border);
  border-radius : var(--r-md);
  cursor        : pointer;
  user-select   : none;
}
.cards-group-hdr > * { pointer-events: none; }
.cards-group-hdr.collapsed .tbl-group-chevron { transform: rotate(-90deg); }

/* ── SHARED PILLS ───────────────────────────────────────── */
.tag-pill {
  font-size     : 10px;
  padding       : 2px 7px;
  border-radius : 10px;
  font-weight   : 500;
  color         : #fff;   /* default only — templates should pass Dashboard.readableText(bg) (#71) */
  white-space   : nowrap;
  display       : inline-block;
}
.item-link       { color: var(--c-text); text-decoration: none; font-weight: 500; }
.item-link:hover { text-decoration: underline; }

/* ── BUTTONS ────────────────────────────────────────────── */
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .btn {
  display       : inline-flex;
  align-items   : center;
  gap           : 4px;
  font-size     : 11px;
  padding       : 3px 9px;
  border-radius : var(--r);
  border        : 1px solid var(--c-border);
  background    : var(--c-surface);
  color         : var(--c-text-mid);
  cursor        : pointer;
  font-family   : var(--font-body);
  white-space   : nowrap;
  line-height   : 1;
}
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .btn:hover  { background: var(--c-bg); }
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) .btn.active { background: var(--c-text); color: var(--c-surface); border-color: var(--c-text); }
/* Details button: the selected record's colour (--detail-color, set inline by
   applyDetailsButton()) on the border, with a ring on hover — never as text
   or fill, since an arbitrary record colour can't be relied on for contrast
   (#71). `.btn.btn-details` rather than `.btn-details`, and an explicit
   background/border, so a host page's own `.btn` rules (a site stylesheet
   loaded after this one, e.g. a filled brand-colour button) can't override
   it — they'd win a same-specificity tie on load order. */
.btn.btn-details { background: var(--c-surface); border: 1.5px solid var(--detail-color, #3B82F6); color: var(--c-text); }
.btn.btn-details:hover { background: var(--c-surface); color: var(--c-text); box-shadow: 0 0 0 2px var(--detail-color, #3B82F6); }
.btn-details-label {
  display       : inline-block;
  max-width     : 110px;
  overflow      : hidden;
  text-overflow : ellipsis;
  white-space   : nowrap;
  vertical-align: bottom;
}
/* Floating alone at the bottom of the screen, the FAB has room for a longer name. */
.btn-details-fab .btn-details-label { max-width: 200px; }
@keyframes btn-details-pulse {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(59, 130, 246, .55); }
  30%  { transform: scale(1.08); box-shadow: 0 0 0 6px rgba(59, 130, 246, 0); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); }
}
.btn-details.pulse { animation: btn-details-pulse .5s ease-out; }

.view-toggle          { display: flex; border: 1px solid var(--c-border); border-radius: var(--r); overflow: hidden; }
.view-btn             { display: flex; align-items: center; gap: 4px; padding: 3px 9px; font-size: 11px; font-family: var(--font-body); background: transparent; border: none; color: var(--c-text-mid); cursor: pointer; white-space: nowrap; }
.view-btn:first-child { border-right: 1px solid var(--c-border); }
.view-btn:hover       { background: var(--c-bg); }
.view-btn.active      { background: var(--c-text); color: var(--c-surface); }

/* "N not shown — no date / no location" header notices (CONFIG.timeline.undatedNotice,
   CONFIG.map.unlocatedNotice). Status text, not a button — muted, no hover.
   The bare count (.panel-notice-count) only shows on phones, where the
   .view-btn-label text is hidden (see the <480px block below). */
.panel-notice       { display: flex; align-items: center; gap: 4px; padding: 3px 6px; font-size: 11px; font-family: var(--font-body); font-weight: 400; text-transform: none; letter-spacing: normal; color: var(--c-text-soft); white-space: nowrap; background: transparent; border: none; border-radius: var(--r); cursor: pointer; }
.panel-notice:hover,
.panel-notice[aria-expanded="true"] { background: var(--c-bg); color: var(--c-text-mid); }
.panel-notice-count { display: none; }

/* The records behind a notice — see toggleNoticePopover(). Appended to <body>,
   positioned by script; above Leaflet (≤1000) and below the sticky topbar (1100). */
.notice-popover      { position: absolute; z-index: 1080; min-width: 220px; max-width: 320px; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--r); box-shadow: var(--shadow-lg); font-family: var(--font-body); font-size: 12px; }
.notice-popover-hd   { padding: 8px 10px; border-bottom: 1px solid var(--c-border); color: var(--c-text-soft); font-size: 11px; line-height: 1.35; }
.notice-popover-list { list-style: none; margin: 0; padding: 4px 0; max-height: 260px; overflow-y: auto; }
.notice-popover-list button { display: flex; align-items: center; gap: 8px; width: 100%; padding: 5px 10px; background: transparent; border: none; color: var(--c-text); font: inherit; text-align: left; cursor: pointer; }
.notice-popover-list button:hover,
.notice-popover-list button:focus-visible { background: var(--c-bg); outline: none; }
.notice-popover-list button.active { font-weight: 600; }
.tbl-group-select     { padding: 3px 6px; font-size: 11px; font-family: var(--font-body); background: transparent; border: none; border-left: 1px solid var(--c-border); color: var(--c-text-mid); cursor: pointer; outline: none; }
.tbl-group-select:hover  { background: var(--c-bg); }
.tbl-group-select:focus-visible { outline: 2px solid var(--c-text); outline-offset: -2px; }
.tbl-group-select.active { background: var(--c-text); color: var(--c-surface); }
#btn-tbl-fold .icon     { font-size: 13px; }   /* match the other header icons (inline 13px in the page markup) */

.tile-select {
  font-size     : 11px;
  padding       : 3px 6px;
  border        : 1px solid var(--c-border);
  border-radius : var(--r);
  background    : var(--c-surface);
  color         : var(--c-text);
  font-family   : var(--font-body);
  cursor        : pointer;
}

/* ── HIGHLIGHT ──────────────────────────────────────────── */
:where(.dash, #main-panels, [data-component], #lb-dialog, .facet-group, .notice-popover) mark { background: #FEF9C3; color: inherit; border-radius: 2px; padding: 0 1px; }

/* ── TIMELINE ITEM LABEL FIXES ──────────────────────────── */
/* Min width: keeps short-duration trips visible at wide zoom levels.
   Value comes from CONFIG.timeline.itemMinWidth via CSS custom property.
   height (not just min-height) is explicit here so both
   CONFIG.timeline.rangeLabelPosition modes below render an identical bar
   size — an 'inside' label sits in normal flow and would otherwise grow the
   box taller via its own line-height/padding, while a 'trailing' label is
   taken out of flow (position:absolute) and contributes nothing to
   auto-height, so without a fixed height the two modes visibly disagree on
   how tall a bar is. This also gives vis-timeline's own
   .vis-item-overflow{height:100%} (its stock CSS) a *definite* height to
   resolve against — with only min-height that chain stays "auto", which
   breaks any percentage/positioning math done against it (see 'trailing'
   below). */
.vis-item.vis-range { min-width: var(--tl-item-min-width, 30px); height: 16px !important; overflow: visible; }
/* Allow range item labels to extend beyond the bar, matching point item behaviour */
#timeline-detail .vis-item.vis-range .vis-item-overflow { overflow: visible !important; }
/* vis-timeline JS sets inline width on .vis-item-content equal to the bar pixel width,
   which clips labels on narrow bars even when overflow is visible on the parent.
   display/align-items/height center the label vertically within the now-fixed-height
   bar (mirroring the point-item flex layout below) — !important throughout because
   vis-timeline's own JS sets several inline styles directly on this same element
   (marginLeft, marginRight, maxWidth, transform, for its "keep the label visible
   while the bar is panned partway offscreen" behaviour), and an inline style beats
   a plain stylesheet rule of any specificity.
   color is forced dark (matching the point-item label below, not
   tlItemStyle()'s white-for-contrast-against-the-bar default) because an
   'inside' label wider than its bar spills past the bar's edge onto the page
   background (that's the whole reason width is forced to max-content here),
   where white text is invisible in light theme; var(--c-text) keeps it legible
   in both themes and both CONFIG.timeline.rangeLabelPosition modes — a
   'trailing' label is *always* on the page background, never the bar's own
   fill, so it needs exactly the same treatment. */
#timeline-detail .vis-item.vis-range .vis-item-content {
  width      : max-content !important;
  max-width  : none !important;
  height     : 100% !important;
  display    : flex !important;
  align-items: center !important;
  color      : var(--c-text) !important;
}
/* …and on the bar itself (the default 'inside' position) that dark text sat
   on the bar's own colour — unreadable on dark bars (#68). A light backing
   chip, inset 2px so the bar still frames it, keeps 4.5:1 on any bar colour
   in either theme. */
#timeline-detail:not(.tl-range-label-trailing) .vis-item.vis-range .vis-item-content {
  height       : calc(100% - 4px) !important;
  margin-top   : 2px;
  background   : color-mix(in srgb, var(--c-surface) 88%, transparent);
  border-radius: 2px;
}

/* CONFIG.timeline.rangeLabelPosition: 'trailing' — bar keeps its own
   true-duration fill untouched (tlItemStyle()'s background/border are on
   the .vis-item element itself, never touched here); the label moves to
   just past the bar's right edge instead of sitting inside it. Toggled by
   the .tl-range-label-trailing class initTimeline() puts on #timeline-detail
   (see simexdb.js) — tlItemContentHTML()'s markup is identical to 'inside',
   only this positioning differs.
   Centered via top/bottom:0 + the shared height/display/align-items above,
   NOT top:50%+transform:translateY(-50%) — vis-timeline's own JS sets an
   inline transform on this same element (see the comment above), and
   reusing transform for centering would either lose that fight outright, or
   (with !important) permanently pin the label in place and silently break
   vis-timeline's pan-follow behaviour. Avoiding transform for centering
   sidesteps the conflict entirely. */
#timeline-detail.tl-range-label-trailing .vis-item.vis-range .vis-item-content {
  position   : absolute !important;
  left       : 100% !important;
  top        : 0 !important;
  bottom     : 0 !important;
  margin-left: 4px !important;
  padding    : 0 !important; /* the shared rule's 1px/4px padding would stack with margin-left above, doubling the gap */
  white-space: nowrap;
}

/* Allow item content to be visible even when bar is narrow. padding needs
   !important — vis-timeline's own stylesheet (loaded after this one, see
   index.html) declares the same selector at equal specificity, so without it
   the library's stock 5px padding silently wins and items render ~10px
   taller than intended. */
.vis-item .vis-item-content {
  white-space   : nowrap;
  overflow      : visible !important;
  padding       : 1px 4px !important;
  font-size     : 10px;
  line-height   : 1.4;
  pointer-events: none;
}

/* Detail band's point items (records with no duration, plus ranged records
   collapsed to points by CONFIG.timeline.minBarPx) render as TWO elements —
   the outer .vis-point (carries our per-record color via tlItemStyle()) plus
   an inner .vis-dot vis-timeline draws itself and never themes, always its own
   stock blue. Hide that dot — we draw our own record-colored dot inside
   .vis-item-content instead (tlItemContentHTML() in simexdb.js). */
#timeline-detail .vis-item.vis-dot { display: none !important; }

/* Point items in the detail band render as "● label" — a small record-colored
   dot with the label beside it — so a record with no duration (and a ranged
   record collapsed to a point by CONFIG.timeline.minBarPx) reads as a marker
   at its date, visibly distinct from a range bar whose width carries meaning.
   The dot is an empty leading <span> from tlItemContentHTML(); the filled-chip
   look tlItemStyle() would give the .vis-point element is stripped here (that
   fill is reserved for bars). The dot's color comes from the --tl-dot-color
   custom property tlItemStyle() sets on the item (an inline style/class on the
   span itself would be eaten by vis-timeline's content sanitizer). */
#timeline-detail .vis-item.vis-point {
  background   : transparent !important;
  border-color : transparent !important;
  color        : var(--c-text) !important;
}
#timeline-detail .vis-item.vis-point .vis-item-content {
  display     : flex;
  align-items : center;
  gap         : 4px;
}
#timeline-detail .vis-item.vis-point .vis-item-content > span:first-child {
  flex          : none;
  width         : 7px;
  height        : 7px;
  border-radius : 50%;
  background    : var(--tl-dot-color, currentColor);
}
/* Viewport filter active indicator — timeline and map */
#panel-timeline.viewport-filtering,
#panel-map.viewport-filtering { border-left: 3px solid var(--c-warning-border); }

/* ── SELECTED ITEM — DETAIL BAND ───────────────────────────── */
#timeline-detail .vis-item.vis-selected {
  box-shadow     : 0 0 0 2px #fff, 0 0 0 4px rgba(0, 0, 0, 0.55);
  filter         : brightness(1.2);
  border-width   : 2px;
  z-index        : 10 !important;
}

/* Ensure items have enough height to show text */
.vis-item {
  min-height : 16px !important;
  font-size  : 10px;
  transition : none !important;
}
/* clickToUse overlay — dashed border when timeline is inactive, disappears once activated */
.vis-timeline:not(.vis-active) .vis-overlay {
  outline        : 2px dashed var(--c-tl-overlay);
  outline-offset : -4px;
  cursor         : pointer;
}

/* ── DUAL-BAND TIMELINE ─────────────────────────────────── */
.tl-band {
  width      : 100%;
  flex-shrink: 0;
  overflow   : hidden !important;
}
/* Overview band — fixed short height, acts as scrubber */
.tl-band-overview {
  min-height    : 40px;
  border-top    : 1px solid var(--c-border);
  background    : var(--c-bg);
  cursor        : ew-resize;
}

/* Overview items — render as colored dots, no labels. Stacked (one row per
   overlapping trip) so height grows with the timeline's own stack layout —
   see .tl-band-overview min-height / maxHeight in initTimeline(). */
#timeline-overview .vis-item {
  width         : var(--bin-size, 5px) !important;
  height        : var(--bin-size, 5px) !important;
  border-radius : 50%    !important;
  min-height    : 5px    !important;
  border-width  : 0      !important;
  padding       : 0      !important;
  opacity       : 0.75;
  transition    : opacity .15s, transform .15s;
}
#timeline-overview .vis-item:hover {
  opacity   : 1;
  transform : scale(1.4);
}
#timeline-overview .vis-item.vis-selected {
  opacity   : 1;
  transform : scale(1.6);
  box-shadow: 0 0 0 2px #fff, 0 0 0 3px currentColor;
}
#timeline-overview .vis-item .vis-item-content { display: none !important; }
#timeline-overview .vis-item .vis-item-overflow{ display: none !important; }

/* vis-timeline's PointItem renders TWO elements per point: the outer .vis-point
   container (which carries our per-record color via inline style, set in
   buildTimeline()) and an inner .vis-dot child (which only ever gets vis-timeline's
   default un-colored styling). Both match the .vis-item rule above and render as
   overlapping 5px circles — most visible on selection, where vis-timeline's own
   .vis-selected CSS turns the dot bright yellow next to our correctly-colored,
   ringed point. Hide the redundant dot so only the colored point shows. */
#timeline-overview .vis-item.vis-dot { display: none !important; }

/* Hide group labels in overview — not enough height */
#timeline-overview .vis-labelset { display: none !important; }
#timeline-overview .vis-panel.vis-left { display: none !important; }

/* Viewport highlight window in overview */
.tl-overview-window {
  position        : absolute;
  top             : 0;
  bottom          : 0;
  background      : rgba(53, 120, 181, 0.10);
  border-left     : 1px solid rgba(53, 120, 181, 0.35);
  border-right    : 1px solid rgba(53, 120, 181, 0.35);
  pointer-events  : none;
  z-index         : 1;
  transition      : left .1s, width .1s;
}

/* ── RULER BANDS (CONFIG.timeline.bands) ───────────────────
   Additional fixed-scale bands stacked below the overview, each showing a
   "padded" window centered on the detail band's current midpoint. Omitted
   when CONFIG.timeline.bands is unconfigured — see docs/engine.md →
   "Ruler bands" for the full design rationale and limitations. */
.tl-band-row {
  position: relative;
}
.tl-band-ruler {
  border-top   : 1px solid var(--c-border);
  background   : var(--c-bg);
  cursor       : ew-resize;
  touch-action : pan-y;
}
/* Items render as thin ticks, not labeled bars — labels/left axis would
   crowd out a ~54px-tall band; the ruler is a navigation aid, not a reader. */
.tl-band-ruler .vis-item {
  cursor     : pointer;
  min-height : 12px !important;
  height     : 12px !important;
  min-width  : 4px  !important;
}
.tl-band-ruler .vis-item .vis-item-content { display: none !important; }
.tl-band-ruler .vis-labelset,
.tl-band-ruler .vis-panel.vis-left { display: none !important; }
/* Overlay label lives inside .tl-band-row (a descendant of nothing vis-timeline
   observes) so it never risks tripping the MutationObserver redraw-loop guard
   that watches the timeline container itself. */
.tl-band-label {
  position       : absolute;
  left           : 6px;
  top            : 2px;
  z-index        : 2;
  pointer-events : none;
  font-size      : 9.5px;
  text-transform : uppercase;
  letter-spacing : .05em;
  color          : var(--c-text-soft);
}
@media (max-width: 899px) {
  .tl-band-row[data-hide-mobile="true"] { display: none; }
}

/* Cluster items in detail band */
.vis-cluster {
  background    : var(--c-bg) !important;
  border        : 1.5px solid var(--c-border-mid) !important;
  border-radius : 10px !important;
  color         : var(--c-text-mid) !important;
  font-size     : 10px !important;
  font-weight   : 600 !important;
  padding       : 1px 6px !important;
}

/* Detail band focus outline */
#timeline-detail:focus {
  outline        : 2px solid var(--c-info-border);
  outline-offset : -2px;
}

/* ── PER-FACET CLEAR BUTTON ─────────────────────────────── */
.facet-hd {
  /* Override the existing rule to allow right side flex    */
  justify-content : space-between;
}
.facet-hd-right {
  display     : flex;
  align-items : center;
  gap         : 4px;
  flex-shrink : 0;
}
/* Active count — amber tint when selections are present    */
.facet-hd-count--active {
  background    : var(--c-warning-bg);
  color         : var(--c-warning-text);
  border        : 1px solid var(--c-warning-border);
  border-radius : 10px;
  padding       : 0 5px;
  font-weight   : 600;
}
/* ✕ clear button — only appears when facet has selections  */
.facet-clear-btn {
  display         : flex;
  align-items     : center;
  justify-content : center;
  width           : 16px;
  height          : 16px;
  border-radius   : 3px;
  border          : 1px solid var(--c-warning-border);
  background      : var(--c-warning-bg);
  color           : var(--c-warning-text);
  cursor          : pointer;
  padding         : 0;
  font-size       : 10px;
  line-height     : 1;
  flex-shrink     : 0;
  transition      : background .12s, border-color .12s;
}
.facet-clear-btn:hover {
  background   : var(--c-warning-border);
  border-color : #F59E0B;
}

/* ── LEGEND — per-component horizontal strips ────────────── */

.legend-bar {
  display        : flex;
  flex-wrap      : wrap;
  gap            : 6px 16px;
  align-items    : center;
  padding        : 6px 12px;
}
#map-legend-bar {
  border-top     : 1px solid var(--c-border);
}
#tl-legend-bar {
  border-bottom  : 1px solid var(--c-border);
}

/* Timeline scale control (CONFIG.timeline.scaleControl) — the last control in
   the timeline header, so it's the first to wrap to the overflow row.
   .compact (fitTlScaleControl()) swaps the buttons for the <select> when the
   button group is wider than the whole header row. */
.tl-scale        { display: flex; align-items: center; }
.tl-scale-btns .view-btn:first-child   { border-right: none; }
.tl-scale-btns .view-btn + .view-btn   { border-left: 1px solid var(--c-border); }
.tl-scale-select { display: none; }
.tl-scale.compact .tl-scale-btns   { display: none; }
.tl-scale.compact .tl-scale-select { display: inline-block; }
.leg-entry {
  display        : flex;
  align-items    : center;
  gap            : 5px;
}
.leg-swatch-h {
  width          : 10px;
  height         : 10px;
  border-radius  : 2px;
  flex-shrink    : 0;
  display        : inline-block;
}
.leg-label {
  font-size      : 11px;
  color          : var(--c-text);
  font-weight    : 500;
}
.leg-sub {
  display        : flex;
  align-items    : center;
  gap            : 2px;
  margin-left    : 2px;
}
.leg-sub-swatch {
  width          : 8px;
  height         : 8px;
  border-radius  : 50%;
  display        : inline-block;
  flex-shrink    : 0;
}

/* What drives the colours (#82): a "?" button ends the legend; it opens
   one full-width row under the entries — "Colour: Category · Shade: Status
   ● Active ● Pending ● Archived". .leg-key-open on the bar shows it. */
.leg-key-toggle {
  width          : 18px;
  height         : 18px;
  padding        : 0;
  font           : inherit;
  font-size      : 11px;
  font-weight    : 600;
  line-height    : 16px;
  color          : var(--c-text-mid);
  background     : transparent;
  border         : 1px solid var(--c-border-mid);
  border-radius  : 50%;
  cursor         : pointer;
}
.leg-key-toggle:hover,
.leg-key-toggle[aria-expanded="true"] {
  color          : var(--c-text);
  border-color   : var(--c-text-mid);
}
.leg-key {
  display        : none;
  flex-basis     : 100%;
  flex-wrap      : wrap;
  align-items    : center;
  gap            : 4px 18px;
  font-size      : 11px;
  color          : var(--c-text-mid);
}
.legend-bar.leg-key-open .leg-key { display: flex; }
.leg-key-item {
  display        : inline-flex;
  align-items    : center;
  flex-wrap      : wrap;
  gap            : 4px 8px;
}
.leg-key-item strong {
  font-weight    : 600;
  color          : var(--c-text);
  margin-left    : -4px;
}
.leg-shade {
  display        : inline-flex;
  align-items    : center;
  gap            : 4px;
  color          : var(--c-text);
}
.leg-shade .leg-sub-swatch {
  box-shadow     : 0 0 0 1px var(--c-border-mid);   /* the dark end stays visible on a dark ground */
}

/* ── INLINE DETAIL PANE ─────────────────────────────────── */
#detail-pane {
  flex          : 1;
  min-height    : 0;
  display       : flex;
  flex-direction: column;
  overflow      : hidden;
}
.dp-toolbar {
  padding      : 6px 10px;
  border-bottom: 1px solid var(--c-border);
  background   : var(--c-bg);
  flex-shrink  : 0;
}
#dp-body {
  flex    : 1;
  overflow: auto;
}
#dp-body .lb-wrap { border-radius: 0; }

/* Selected record no longer in the results (updateDetailPane()) */
.dp-stale-note {
  display      : flex;
  flex-wrap    : wrap;
  align-items  : center;
  justify-content: space-between;
  gap          : 6px 10px;
  padding      : 8px 12px;
  font-size    : 12px;
  color        : var(--c-warning-text);
  background   : var(--c-warning-bg);
  border-bottom: 1px solid var(--c-warning-border);
}

/* No records match (updateRecordsEmpty()) — replaces the table/cards */
.records-outer.is-empty > .table-wrap,
.records-outer.is-empty > .cards-grid,
.records-outer.is-empty > .pagination { display: none !important; }
.records-empty {
  padding    : 28px 16px;
  text-align : center;
  color      : var(--c-text-mid);
  font-size  : 12px;
}
.records-empty-title { margin: 0 0 4px; font-size: 14px; font-weight: 600; color: var(--c-text); }
.records-empty-hint  { margin: 0 0 12px; }
.records-empty-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin-bottom: 12px; }
/* Removable filter chip — the empty state and #active-filters (filterChipButton()) */
.filter-chip {
  display      : inline-flex;
  align-items  : center;
  gap          : 6px;
  min-height   : 28px;
  padding      : 3px 8px 3px 10px;
  font         : inherit;
  color        : var(--c-text);
  background   : var(--c-surface);
  border       : 1px solid var(--c-border-mid);
  border-radius: 999px;
  cursor       : pointer;
}
.filter-chip:hover { border-color: var(--c-text-mid); }
.filter-chip .icon { color: var(--c-text-mid); }
.filter-chip:focus-visible, .active-filters-clear:focus-visible { outline: 2px solid var(--c-text); outline-offset: 2px; }

/* Active filters row — optional #active-filters, filled by updateActiveFiltersBar().
   Explicit font/size so it reads the same on host pages. */
#active-filters {
  display     : flex;
  flex-wrap   : wrap;
  align-items : center;
  gap         : 6px;
  font-family : var(--font-body);
  font-size   : 12px;
}
#active-filters[hidden] { display: none; }
.active-filters-clear {
  padding         : 3px 4px;
  font            : inherit;
  color           : var(--c-text-mid);
  background      : none;
  border          : 0;
  text-decoration : underline;
  cursor          : pointer;
}
.active-filters-clear:hover { color: var(--c-text); }

/* Facet with no values left in the current results (buildFacets()) */
.facet-empty { padding: 4px 10px; font-size: 11px; color: var(--c-text-soft); font-style: italic; }

/* ── MOBILE DRAWER ──────────────────────────────────────── */

/* Backdrop behind the open drawer — JS adds .visible */
#drawer-backdrop {
  display    : none;
  position   : fixed;
  inset      : 0;
  background : rgba(0, 0, 0, 0.35);
  z-index    : 1150;
}
#drawer-backdrop.visible { display: block; }

/* Mobile-only elements hidden on desktop by default */
.btn-filter-mobile { display: none; }

/* Share (#58): #btn-share in the topbar, #btn-dp-share in the detail pane
   toolbar, #btn-lb-share beside the record dialog's ✕. Each opens
   #share-panel (appended to <body>, or into the dialog) — so it carries its
   own box model rather than relying on the engine's regions. */
.lb-close.lb-share { right: 52px; }
.share-panel {
  position      : fixed;
  z-index       : 1200;
  box-sizing    : border-box;
  display       : flex;
  flex-direction: column;
  gap           : 10px;
  width         : min(380px, calc(100vw - 16px));
  padding       : 12px 14px 14px;
  font-family   : var(--font-body);
  font-size     : 12px;
  color         : var(--c-text);
  background    : var(--c-surface);
  border        : 1px solid var(--c-border-mid);
  border-radius : 8px;
  box-shadow    : var(--shadow-lg);
}
.share-panel *, .share-panel *::before, .share-panel *::after { box-sizing: border-box; }
.share-hd       { display: flex; align-items: center; justify-content: space-between; font-size: 13px; font-weight: 600; }
.share-close    { padding: 2px; font-size: 15px; line-height: 0; color: var(--c-text-mid); background: none; border: none; cursor: pointer; }
.share-close:hover { color: var(--c-text); }
.share-desc     { margin: 0; color: var(--c-text-mid); line-height: 1.4; }
.share-link     { display: flex; gap: 6px; }
.share-link input {
  flex          : 1;
  min-width     : 0;
  padding       : 6px 8px;
  font          : inherit;
  color         : var(--c-text);
  background    : var(--c-bg);
  border        : 1px solid var(--c-border-mid);
  border-radius : 4px;
}
.share-panel .btn {
  display       : inline-flex;
  align-items   : center;
  gap           : 5px;
  padding       : 5px 10px;
  font          : inherit;
  font-weight   : 500;
  color         : var(--c-text);
  text-decoration: none;
  white-space   : nowrap;
  background    : var(--c-surface);
  border        : 1px solid var(--c-border-mid);
  border-radius : 4px;
  cursor        : pointer;
}
.share-panel .btn:hover   { background: var(--c-bg); }
.share-panel .btn.primary { color: var(--c-surface); background: var(--c-text); border-color: var(--c-text); }
.share-panel .btn svg.icon { flex-shrink: 0; }
.share-opts     { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0; padding: 0; border: none; }
.share-opts legend { float: left; margin-right: 2px; padding: 0; color: var(--c-text-mid); }
.share-opts label  { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.share-actions  { display: flex; flex-wrap: wrap; gap: 6px; }
.sidebar-close-btn { display: none; }

/* Active filter count badge on the Filters button */
.filter-badge {
  background    : var(--c-warning-bg);
  color         : var(--c-warning-text);
  border        : 1px solid var(--c-warning-border);
  border-radius : 10px;
  font-size     : 10px;
  font-weight   : 600;
  padding       : 0 5px;
  margin-left   : 4px;
  line-height   : 1.6;
  display       : none;
}

/* ── RESPONSIVE LAYOUT ──────────────────────────────────── */

/* Desktop ≥900px: 2-column master-detail layout.
   .col-left  — content-height flex column (map + legend + timeline stack naturally).
   .col-right — sticky viewport-height panel (records scroll internally). */
@media (min-width: 900px) {
  /* Switch .layout from grid to flex — eliminates grid-row height inflation from sidebar */
  .layout {
    display        : flex;
    flex-direction : row;
    align-items    : flex-start;
    padding-top    : 8px;
  }
  .sidebar {
    flex-shrink    : 0;
    width          : 214px;
  }
  #main-panels {
    display        : flex !important;
    flex-direction : row;
    align-items    : flex-start;
    flex           : 1;
    gap            : 10px;
    padding        : 0 10px 8px;
  }
  .col-left {
    flex           : 1;
    display        : flex;
    flex-direction : column;
    gap            : 8px;
    min-width      : 0;
  }
  .col-right {
    flex           : 1;
    position       : sticky;
    top            : 56px;
    align-self     : flex-start;
    display        : flex;
    flex-direction : column;
    overflow       : visible;
    min-width      : 0;
  }
  /* Map panel needs an explicit height (no grid row to provide it anymore) */
  #panel-map {
    height     : 380px;
    flex-shrink: 0;
  }
  /* overflow-x:hidden contains item label blowout on width. No vertical cap needed —
     detail and overview bands each self-limit height via their own minHeight/maxHeight
     (see initTimeline()); a second cap here just clips the overview band once both
     bands grow toward their maxes. */
  #panel-timeline { overflow-x: hidden; }
  /* Records panel: content-height, no stretching */
  #panel-records {
    border-bottom: none;
    overflow     : visible;
  }
  /* records-outer, table, cards all size to content so pagination follows immediately */
  .records-outer { flex: none; overflow: visible; }
  .table-wrap    { flex: none; }
  .cards-grid    { flex: none; }
}

/* Mobile <900px: single-column stacked, sidebar becomes a slide-in drawer. */
@media (max-width: 899px) {
  /* overflow-x crops vis-timeline's min-content width (see docs/engine.md →
     Layout system). clip, not hidden: hidden makes .layout a scroll container,
     so position:sticky children (a pinned tab bar, a page toolbar) would stick
     to .layout instead of the viewport. hidden stays as the fallback for
     browsers without clip (Safari < 16). */
  .layout   { display: block; min-width: 0; overflow-x: hidden; overflow-x: clip; }
  /* Flex column so col-left/col-right stack naturally */
  #main-panels { display: flex !important; flex-direction: column; gap: 8px; padding: 8px; }
  /* Unwrap the desktop column wrappers — panels become direct flex items */
  .col-left, .col-right { display: contents; }
  /* Restore map height (desktop rule doesn't apply here) */
  #panel-map { height: 300px; flex-shrink: 0; }

  /* Topbar: wrap instead of clipping/overflowing once the Details label grows */
  .topbar-right { flex-wrap: wrap; justify-content: flex-end; row-gap: 4px; }


  /* Records table: scroll horizontally instead of squeezing columns unreadably thin.
     table-layout:auto lets a column grow past its configured % width when its own
     content needs more room (long names, multi-value lists) instead of clipping it —
     the % widths still act as a floor, min-width is just a floor for all-short-value tables. */
  .table-wrap    { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #records-table { min-width: 640px; table-layout: auto; }

  /* Detail pane meta rows: stack label above value instead of squeezing them together */
  .lb-meta-row {
    flex-direction: column;
    align-items   : flex-start;
    gap           : 2px;
  }
  .lb-meta-val { text-align: left; }

  /* Details button, bottom-anchored variant (CONFIG.display.recordDetailsButtonPlacement) —
     thumb-reach placement instead of/alongside the topbar button. */
  .btn.btn-details-fab {
    position   : fixed;
    right      : 16px;
    bottom     : calc(16px + env(safe-area-inset-bottom, 0px));
    z-index    : 1090;
    padding    : 9px 16px;
    font-size  : 13px;
    border-radius: 999px;
    background : var(--c-surface);
    box-shadow : var(--shadow-lg);
  }
  .btn.btn-details-fab:hover { box-shadow: 0 0 0 2px var(--detail-color, #3B82F6), var(--shadow-lg); }

  /* Sidebar: fixed off-screen left; slides in when JS adds .drawer-open */
  .sidebar {
    position     : fixed;
    top          : 0;
    left         : -270px;
    width        : 254px;
    height       : 100%;
    z-index      : 1200;
    background   : var(--c-surface);
    border-right : 1px solid var(--c-border);
    overflow-y   : auto;
    transition   : left 0.25s ease;
    box-shadow   : var(--shadow-md);
  }
  .sidebar.drawer-open { left: 0; }

  /* Show mobile-only elements */
  .btn-filter-mobile { display: flex; }
  .sidebar-close-btn {
    display         : flex;
    align-items     : center;
    justify-content : flex-end;
    gap             : 6px;
    width           : 100%;
    padding         : 10px 12px;
    border          : none;
    border-bottom   : 1px solid var(--c-border);
    background      : none;
    cursor          : pointer;
    color           : var(--c-text-mid);
    font-size       : 13px;
    box-sizing      : border-box;
  }
}

/* Phones <480px: icon-only component-header controls. The .panel-hd-right
   buttons keep their icons; their text labels (wrapped in .view-btn-label)
   are hidden so the header stays on one 30px row without clipping. Each
   button carries a title/aria-label for its accessible name. The left-side
   panel labels (Map / Timeline / Items) stay as text.
   Deliberately narrower than the 900px layout breakpoint: measured with
   labels showing, the widest header (Items) needs ~362px, so tablets and
   large phones — full-width stacked panels below 900px — have room for the
   text. (Was inside the 899px block until 2026-09-23.) */
@media (max-width: 479px) {
  .panel-hd .view-btn-label { display: none; }
  .btn-share-label { display: none; }
  .panel-hd .panel-notice-count { display: inline; }
  .notice-popover { max-width: none; }   /* full-width — toggleNoticePopover() sets left/width */
}

/* ── DARK MODE ──────────────────────────────────────────────
   Activated by data-theme="dark" on <html>.
   The 11ty project sets this via its own themeToggle — no
   extra wiring needed when embedded. The standalone index.html
   uses Dashboard.toggleTheme() + #btn-theme-toggle.
   ────────────────────────────────────────────────────────── */
:root          { color-scheme: light; }
[data-theme="dark"] { color-scheme: dark; }

[data-theme="dark"] {
  --c-bg         : #1C1917;
  --c-surface    : #28251F;
  --c-border     : #3C3834;
  --c-border-mid : #524E48;
  --c-text       : #EDE8E1;
  --c-text-mid   : #C0B8B0;
  --c-text-soft  : #B0A8A0;
  --c-accent     : #EDE8E1;
  --c-info-bg    : #1A2840;
  --c-info-border: #2C4A72;

  --shadow-sm    : 0 1px 3px rgba(0,0,0,.35);
  --shadow-md    : 0 4px 12px rgba(0,0,0,.50);
  --shadow-lg    : 0 8px 24px rgba(0,0,0,.70);

  /* Amber — warning / active-filter tint (inverted for dark bg) */
  --c-warning-bg    : #3D1F00;
  --c-warning-border: #92400E;
  --c-warning-text  : #FDE68A;

  /* Timeline inactive-overlay — slightly lighter against dark bg */
  --c-tl-overlay    : rgba(100, 120, 180, 0.30);
}

/* Feed status badges */
[data-theme="dark"] .feed-badge.live   { border-color:#166534; color:#4ADE80; background:#052E16; }
[data-theme="dark"] .feed-badge.sample { border-color:var(--c-warning-border); color:var(--c-warning-text); background:var(--c-warning-bg); }
[data-theme="dark"] .feed-badge.error  { border-color:#7F1D1D; color:#FCA5A5; background:#1C0606; }

/* Search highlight */
[data-theme="dark"] mark { background: #78350F; color: #FEF9C3; }

/* Details button */
[data-theme="dark"] .btn.btn-details       { background: var(--c-surface); border-color: var(--detail-color, #60A5FA); color: var(--c-text); }
[data-theme="dark"] .btn.btn-details:hover { background: var(--c-surface); color: var(--c-text); box-shadow: 0 0 0 2px var(--detail-color, #60A5FA); }

/* Card selected ring */
[data-theme="dark"] :where(#cards-grid) .card.sel { border-color:#1E3A5F; box-shadow: 0 0 0 3px rgba(59,130,246,.20); }

/* Table row selected */
[data-theme="dark"] :where(#records-table) tr.sel td { background: var(--c-info-bg); }

/* Overview viewport window — more visible on dark bg */
[data-theme="dark"] .tl-overview-window {
  background   : rgba(53, 120, 181, 0.18);
  border-color : rgba(53, 120, 181, 0.55);
}

/* vis-timeline — override hardcoded light backgrounds */
[data-theme="dark"] .vis-timeline,
[data-theme="dark"] .vis-panel.vis-background,
[data-theme="dark"] .vis-panel.vis-center  { background: var(--c-surface) !important; }
[data-theme="dark"] .vis-panel.vis-top,
[data-theme="dark"] .vis-panel.vis-bottom  { background: var(--c-bg) !important; }
[data-theme="dark"] .vis-current-time      { background: #F87171 !important; }
[data-theme="dark"] .tl-band-overview      { background: var(--c-bg); }

/* Vis-cluster dark */
[data-theme="dark"] .vis-cluster {
  background : var(--c-surface) !important;
  border-color: var(--c-border-mid) !important;
  color      : var(--c-text-mid) !important;
}

/* Timeline detail focus ring */
[data-theme="dark"] #timeline-detail:focus { outline-color: var(--c-info-border); }

/* Selected item ring — softer against dark bg */
[data-theme="dark"] #timeline-detail .vis-item.vis-selected {
  box-shadow: 0 0 0 2px var(--c-surface), 0 0 0 4px rgba(255,255,255,.30);
}

/* Leaflet tooltip — overrides Leaflet's hardcoded white bg; also covers Google Maps
   tooltip which reuses .leaflet-tooltip class for consistent styling */
[data-theme="dark"] .leaflet-tooltip {
  background-color : var(--c-surface) !important;
  border-color     : var(--c-border) !important;
  color            : var(--c-text) !important;
}
[data-theme="dark"] .leaflet-tooltip-top::before    { border-top-color:    var(--c-border) !important; }
[data-theme="dark"] .leaflet-tooltip-bottom::before { border-bottom-color: var(--c-border) !important; }
[data-theme="dark"] .leaflet-tooltip-left::before   { border-left-color:   var(--c-border) !important; }
[data-theme="dark"] .leaflet-tooltip-right::before  { border-right-color:  var(--c-border) !important; }

/* Leaflet controls */
[data-theme="dark"] .leaflet-bar a,
[data-theme="dark"] .leaflet-control-zoom a {
  background-color : var(--c-surface) !important;
  border-color     : var(--c-border) !important;
  color            : var(--c-text) !important;
}
[data-theme="dark"] .leaflet-bar a:hover { background-color: var(--c-bg) !important; }
/* Google provider (#36): the overlays' "Layers" button + panel (right,
   under the map-type menu) and the credits line for overlays / custom
   basemaps. Google's controls are plain white boxes; match them. */
/* Google's map-type dropdown is sized to its button, which clips longer
   custom basemap names (googleTileProviders) — let the list fit them. */
.gm-style-mtc ul[role="menu"] { min-width: max-content; }
.gmap-layers { margin: 10px; font-family: var(--font-body); font-size: 12px; color: #1f1f1f; }
.gmap-layers-btn {
  display       : inline-flex;
  align-items   : center;
  gap           : 5px;
  min-height    : 40px;
  padding       : 0 12px;
  font          : inherit;
  font-weight   : 500;
  color         : inherit;
  background    : #fff;
  border        : none;
  border-radius : 2px;
  box-shadow    : rgba(0,0,0,.3) 0 1px 4px -1px;
  cursor        : pointer;
  float         : right;
}
.gmap-layers-btn:hover { background: #ebebeb; }
.gmap-layers-btn:focus-visible { outline: 2px solid #1f1f1f; outline-offset: 2px; }
.gmap-layers-panel {
  clear         : both;
  margin-top    : 6px;
  padding       : 8px 10px 4px;
  background    : #fff;
  border-radius : 2px;
  box-shadow    : rgba(0,0,0,.3) 0 1px 4px -1px;
}
.gmap-layers-row { display: flex; align-items: center; gap: 6px; padding: 2px 0; cursor: pointer; }
.gmap-credits {
  max-width     : 60vw;
  margin        : 0 4px 2px 0;
  padding       : 0 5px;
  font-family   : Roboto, Arial, sans-serif;
  font-size     : 10px;
  line-height   : 14px;
  color         : #444;
  background    : rgba(255,255,255,.75);
  white-space   : nowrap;
  overflow      : hidden;
  text-overflow : ellipsis;
}
.gmap-credits:hover { white-space: normal; }
.gmap-credits a { color: #444; }

/* Map credits (attribution line, bottom-right). One small line with an
   ellipsis that opens to the full text on hover or keyboard focus, so a
   long provider credit never covers the map. The bottom-right corner spans
   the map's width (right-aligned) so the line's max-width is the map's. */
.leaflet-container .leaflet-bottom.leaflet-right {
  left           : 0;
  display        : flex;
  flex-direction : column;
  align-items    : flex-end;
  pointer-events : none;          /* the empty part of the strip stays click-through */
}
.leaflet-container .leaflet-bottom.leaflet-right > * { pointer-events: auto; }
.leaflet-container .leaflet-control-attribution {
  max-width     : calc(100% - 52px);   /* clear of the map's bottom-left */
  font-size     : 10px;
  line-height   : 1.6;
  white-space   : nowrap;
  overflow      : hidden;
  text-overflow : ellipsis;
}
.leaflet-container .leaflet-control-attribution:hover,
.leaflet-container .leaflet-control-attribution:focus-within { white-space: normal; }
[data-theme="dark"] .leaflet-control-attribution {
  background : rgba(28, 25, 23, 0.80) !important;
  color      : var(--c-text-soft) !important;
}
[data-theme="dark"] .leaflet-control-attribution a { color: var(--c-text-mid) !important; }
/* Basemap picker (L.control.layers) — the expanded list follows the theme;
   the collapsed toggle is Leaflet's own dark-on-transparent PNG, inverted so
   it stays visible on the dark surface. */
/* Map overlays (#36): an opacity slider under each overlay's checkbox in
   the layers control (SimexdbLayersControl). */
.overlay-opacity-row { padding: 0 0 4px 20px; }
.overlay-opacity {
  width        : 120px;
  height       : 24px;   /* a comfortable touch target (WCAG 2.5.8) */
  margin       : 0;
  accent-color : var(--c-text-mid);
  cursor       : pointer;
}
[data-theme="dark"] .leaflet-control-layers {
  background : var(--c-surface) !important;
  color      : var(--c-text) !important;
}
[data-theme="dark"] .leaflet-control-layers-toggle { filter: invert(1); }
[data-theme="dark"] .leaflet-control-layers-separator { border-top-color: var(--c-border) !important; }

/* Theme toggle icons — moon shown in light mode, sun shown in dark mode */
/* svg.icon.… so these outrank the generic `svg.icon { display: inline-block }`
   — with plain class selectors the sun never hid in light mode. */
:where(#btn-theme-toggle) svg.icon.theme-icon-sun                       { display: none; }
[data-theme="dark"] :where(#btn-theme-toggle) svg.icon.theme-icon-moon  { display: none; }
[data-theme="dark"] :where(#btn-theme-toggle) svg.icon.theme-icon-sun   { display: inline-block; }

/* ── ACCESSIBILITY (#68) ─────────────────────────────────── */

/* Screen-reader-only text (the result-count live region, page headings) */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* "Skip to results" — first in the page, visible only when focused */
:where(body:has(> .dash)) > .skip-link {
  box-sizing: border-box;
  position: absolute; left: 8px; top: -100px; z-index: 1000;
  padding: 6px 12px; font-size: 13px; font-weight: 600;
  color: var(--c-surface); background: var(--c-text); border-radius: var(--r);
  text-decoration: none;
}
:where(body:has(> .dash)) > .skip-link:focus { top: 8px; }

/* Collapsible facet title as a real button — looks like the plain label */
.facet-hd-toggle {
  font: inherit; color: inherit; letter-spacing: inherit; text-transform: inherit;
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
}

/* Visible keyboard focus on the engine's focusable non-button elements */
.facet-hd-toggle:focus-visible,
:where(#records-table) th[tabindex]:focus-visible,
:where(#records-table) tr[tabindex]:focus-visible,
:where(#cards-grid) .card:focus-visible,
.tbl-group-hdr-inner:focus-visible,
#panel-records:focus-visible,
#dp-body:focus-visible {
  outline: 2px solid var(--c-text); outline-offset: -2px; border-radius: 2px;
}
:where(#cards-grid) .card:focus-visible { outline-offset: 2px; }

/* Desktop shows the sidebar's own "Clear filters"; the copy in the records
   panel header is for phones, where the sidebar is a closed drawer. */
@media (min-width: 900px) {
  .panel-hd .btn-clear { display: none !important; }
}

/* ── FILTER SHEET (#69) ─────────────────────────────────────
   html.facets-sheet (set by updateFacetLayout(): below 900px, or always with
   CONFIG.display.facetLayout: 'sheet') turns the .sidebar into a sheet:
   full screen on phones, a side sheet over the dimmed page on wider screens.
   It scrolls as one; the engine-injected header and footer stick. */
.facet-sheet-hd, .facet-sheet-ft { display: none; }

html.facets-sheet .btn-filter-mobile { display: flex; }
html.facets-sheet .sidebar {
  position      : fixed;
  top           : 0;
  bottom        : 0;
  left          : 0;
  height        : auto;
  max-height    : none;
  width         : min(360px, 100vw);
  z-index       : 1200;
  padding       : 0 14px;
  gap           : 12px;
  overflow-y    : auto;
  overscroll-behavior: contain;
  background    : var(--c-surface);
  border-right  : 1px solid var(--c-border);
  box-shadow    : var(--shadow-lg);
  transform     : translateX(-105%);
  visibility    : hidden;
  transition    : transform .25s ease, visibility 0s linear .25s;
}
html.facets-sheet .sidebar.drawer-open {
  transform     : none;
  visibility    : visible;
  transition    : transform .25s ease;
}
@media (max-width: 899px) {
  html.facets-sheet .sidebar { width: 100vw; border-right: 0; }
}
@media (prefers-reduced-motion: reduce) {
  html.facets-sheet .sidebar, html.facets-sheet .sidebar.drawer-open { transition: none; }
}
/* Reduced motion everywhere else (#68): no Details-button pulse or loading
   shimmer, and folds/chevrons snap. Map and timeline movement is handled in
   simexdb.js (reduceMotion()). */
@media (prefers-reduced-motion: reduce) {
  .btn-details.pulse, .skeleton-cell { animation: none !important; }
  .facet-chevron, .facet-nest-toggle .icon, .tbl-group-chevron, .facet-slider-fill { transition: none !important; }
}

/* Sheet chrome replaces the page's drawer close button, in-body Clear filters
   and result count (the footer button carries the count) */
html.facets-sheet .sidebar-close-btn,
html.facets-sheet .sidebar > .btn-clear,
html.facets-sheet .sidebar > .result-count { display: none !important; }

/* The sheet's Clear all keeps the .btn-clear class (updateClearButton() shows
   and hides every .btn-clear) but styles itself fully, so a host page's own
   .btn / .btn-clear rules (a site button style, a full-width clear button)
   can't restyle it. */
html.facets-sheet .btn.facet-sheet-clear {
  width         : auto;
  margin        : 0;
  padding       : 4px 10px;
  font-family   : var(--font-body);
  font-size     : 12px;
  line-height   : 1.4;
  color         : var(--c-text-mid);
  background    : transparent;
  border        : 1px solid var(--c-border-mid);
  border-radius : var(--r);
  box-shadow    : none;
  transform     : none;
}
html.facets-sheet .btn.facet-sheet-clear:hover { color: var(--c-text); border-color: var(--c-text-mid); background: transparent; }

html.facets-sheet .facet-sheet-hd {
  display       : flex;
  align-items   : center;
  gap           : 8px;
  position      : sticky;
  top           : 0;
  z-index       : 2;
  margin        : 0 -14px;
  padding       : 10px 10px 10px 14px;
  background    : var(--c-surface);
  border-bottom : 1px solid var(--c-border);
}
.facet-sheet-title { flex: 1; margin: 0; font-size: 15px; font-weight: 600; color: var(--c-text); }
.facet-sheet-close {
  display       : inline-flex;
  align-items   : center;
  justify-content: center;
  width         : 36px;
  height        : 36px;
  font-size     : 18px;
  color         : var(--c-text-mid);
  background    : none;
  border        : 0;
  border-radius : var(--r);
  cursor        : pointer;
}
.facet-sheet-close:hover { background: var(--c-bg); color: var(--c-text); }

html.facets-sheet .facet-sheet-ft {
  display       : block;
  position      : sticky;
  bottom        : 0;
  z-index       : 2;
  margin        : auto -14px 0;   /* auto top: sits at the bottom when the facets are short */
  padding       : 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  background    : var(--c-surface);
  border-top    : 1px solid var(--c-border);
}
.facet-sheet-done {
  width         : 100%;
  min-height    : 44px;
  font          : inherit;
  font-size     : 14px;
  font-weight   : 600;
  color         : var(--c-surface);
  background    : var(--c-text);
  border        : 0;
  border-radius : var(--r);
  cursor        : pointer;
}
.facet-sheet-done:hover { opacity: .9; }
.facet-sheet-close:focus-visible, .facet-sheet-done:focus-visible { outline: 2px solid var(--c-text); outline-offset: 2px; }

/* In the sheet, facets grow instead of scrolling inside a scrolling sheet */
html.facets-sheet .facet-body { max-height: none !important; overflow: visible; }

/* Touch: roomier rows and checkboxes */
@media (pointer: coarse) {
  html.facets-sheet .facet-item { min-height: 40px; }
  html.facets-sheet .facet-more { min-height: 36px; font-size: 13px; }
  html.facets-sheet .facet-filter { font-size: 16px; padding: 8px 10px; }   /* 16px: no iOS zoom on focus */
  html.facets-sheet .facet-item input[type="checkbox"] { width: 18px; height: 18px; }
}
