/* ── Design tokens ──────────────────────────────────────────────
   Every grey in this file used to be its own hex literal — ~150 of
   them, most within a shade or two of each other. They are now a
   14-step cool-neutral ramp: --c-0 is the deepest background,
   --c-13 pure white. Change the ramp here, the whole app follows. */
:root {
  --c-0:  #07090c;
  --c-1:  #0d1015;
  --c-2:  #12161c;
  --c-3:  #181d25;
  --c-4:  #20262f;
  --c-5:  #2a313c;
  --c-6:  #353d4a;
  --c-7:  #434d5c;
  --c-8:  #5b6675;
  --c-9:  #7d8794;
  --c-10: #9ba4b0;
  --c-11: #b9c1cb;
  --c-12: #e3e7ec;
  --c-13: #ffffff;

  /* Interactive accent: focus rings, active states, slider thumbs. */
  --accent:              #7aa2f7;
  --accent-hover:        #96b6f9;
  --accent-text:         #a8c3fb;
  --accent-soft:         #1a2436;
  --accent-solid:        #3d6bd6;
  --accent-solid-hover:  #4d7ce6;
  --accent-solid-border: #5b8bf0;

  --warn:        #e0b64f;
  --warn-bright: #f0cd74;
  --warn-dim:    #6b5620;

  --r-xs: 4px;
  --r-sm: 7px;
  --r-md: 10px;
  --r-lg: 14px;

  --sh-1: 0 1px 2px rgba(0, 0, 0, 0.4);
  --sh-2: 0 4px 14px rgba(0, 0, 0, 0.45);
  --sh-3: 0 12px 40px rgba(0, 0, 0, 0.55);

  --ring: 0 0 0 2px rgba(122, 162, 247, 0.45);
  --t: 140ms cubic-bezier(0.4, 0, 0.2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--c-1);
  color: var(--c-12);
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Keyboard users get a ring; mouse users never see one. Applied once
   here instead of per-control — the old sheet had none at all. */
:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-xs);
}

button, input, select, textarea, summary { font-family: inherit; }
button { transition: background var(--t), color var(--t), border-color var(--t), opacity var(--t); }

#settle-bar {
  position: fixed;
  top: 0; left: 0;
  height: 3px;
  width: 0%;
  background: linear-gradient(90deg, var(--c-8), var(--accent));
  z-index: 9999;
  transition: width linear;
  pointer-events: none;
  opacity: 0;
}

#topbar {
  background: var(--c-2);
  border-bottom: 1px solid var(--c-4);
  padding: 9px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  z-index: 10;
  flex-wrap: wrap;
  box-shadow: var(--sh-1);
}

#topbar h1 img { vertical-align: -4px; }

#topbar h1 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--c-12);
  white-space: nowrap;
  margin-right: 4px;
}

/* One look for every top-bar control. Direct children of the bar and of its
   two split-button wrappers — the dropdowns hanging off those wrappers are a
   level deeper and keep their own menu-item styling. */
#topbar > button:not(#sidebar-toggle-btn),
#topbar > #dl-wrap > button,
#topbar > #tools-wrap > button {
  height: 30px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 13px;
  font-weight: 500;
}
#topbar > button:not(#sidebar-toggle-btn):active:not(:disabled),
#topbar > #dl-wrap > button:active:not(:disabled),
#topbar > #tools-wrap > button:active { transform: translateY(1px); }

#lang-switcher {
  margin-left: auto;
  appearance: none;
  background: var(--c-4)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%237d8794' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E")
    no-repeat right 8px center;
  padding-right: 24px;
  color: var(--c-11);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 5px 8px;
  font-size: 12px;
  height: 30px;
  cursor: pointer;
}
#lang-switcher:hover { background: var(--c-5); }

#status {
  font-size: 12px;
  color: var(--c-9);
  flex: 1 1 100%;
  min-width: 0;
  order: 20;
  padding-top: 2px;
}

#file-input { display: none; }

/* Hamburger button — hidden on desktop */
#sidebar-toggle-btn {
  display: none;
  background: var(--c-4);
  color: var(--c-12);
  border: 1px solid var(--c-6);
  padding: 5px 10px;
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: 20px;
  line-height: 1;
  flex-shrink: 0;
}

/* Sidebar overlay backdrop — hidden by default */
#sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 199;
}
#sidebar-overlay.visible { display: block; }

#main-layout {
  display: grid;
  grid-template-columns: 220px 1fr 0px;
  flex: 1;
  overflow: hidden;
  transition: grid-template-columns 0.3s ease;
  position: relative;
}
#main-layout.panel-open {
  grid-template-columns: 220px 1fr 300px;
}
/* Nothing in the sidebar does anything to a tree with nobody in it — searching,
   surname filters, fitting, highlighting, physics all act on an empty set. So
   the first thing a new arrival sees is the canvas and the empty-state card,
   not two dozen dead controls. showDataUI() adds and removes the class.

   Collapsed to a zero-width column rather than `display: none` — taking a grid
   item out of the flow shifts everything after it one column to the left, which
   handed the canvas's 1fr to the detail panel. */
#main-layout.no-data { grid-template-columns: 0px 1fr 0px; }
/* ...but the detail panel still has to open, because "add the first person" is
   one of the two things the empty state offers, and that form lives in it.
   Without this the panel opened into a zero-width column: the form was built
   and focusable but nothing was on screen, so the button looked broken. */
#main-layout.no-data.panel-open { grid-template-columns: 0px 1fr 300px; }
#main-layout.no-data > #sidebar {
  padding: 0;
  border-right: none;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* ── SIDEBAR ── */
#sidebar {
  background: var(--c-2);
  border-right: 1px solid var(--c-4);
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

#search-input {
  flex-shrink: 0;
  width: 100%;
  background: var(--c-4);
  border: 1px solid var(--c-6);
  color: var(--c-12);
  padding: 6px 8px;
  border-radius: var(--r-sm);
  font-size: 13px;
}
#search-input::placeholder { color: var(--c-7); }
#search-input:focus { outline: none; border-color: var(--accent); }

/* The sidebar is a flex column, so anything left shrinkable gets squeezed to
   nothing once the fixed sections no longer fit — and a list of results that is
   present but zero pixels tall cannot be clicked, it just passes the click to
   whatever is drawn behind it. Every section keeps its size; the sidebar
   scrolls instead. */
#search-results {
  flex-shrink: 0;
  max-height: 140px;
  overflow-y: auto;
  font-size: 12px;
}
.result-item {
  padding: 4px 6px;
  cursor: pointer;
  border-radius: var(--r-xs);
  color: var(--c-10);
}
.result-item:hover { background: var(--c-4); color: var(--c-12); }

.sidebar-label {
  font-size: 10px;
  font-weight: 600;
  color: var(--c-8);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 4px;
  flex-shrink: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.surname-color-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  color: var(--c-9);
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
}
.surname-color-toggle input[type="checkbox"] {
  cursor: pointer;
}
.surname-color-toggle:hover {
  color: var(--c-11);
}

/* Takes the spare room on a tall window and scrolls within itself on a short
   one, but never below a height you can actually use. `min-height: 0` let it
   collapse to nothing the moment the panels above grew. */
.sidebar-select {
  width: 100%;
  appearance: none;
  background: var(--c-4)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%237d8794' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E")
    no-repeat right 8px center;
  color: var(--c-12);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 5px 24px 5px 8px;
  font-size: 12px;
  cursor: pointer;
  transition: border-color var(--t), background-color var(--t);
}
.sidebar-select:hover { border-color: var(--c-7); }
.sidebar-num {
  width: 60px;
  padding: 2px 4px;
  font-size: 11px;
  color: var(--c-12);
  background: var(--c-3);
  border: 1px solid var(--c-6);
  border-radius: var(--r-xs);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.sidebar-num:focus {
  outline: none;
  border-color: var(--accent);
}

#surname-list {
  overflow-y: auto;
  font-size: 12px;
  flex: 1 1 auto;
  min-height: 140px;
  max-height: 40vh;
}

.surname-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 0;
  cursor: pointer;
  user-select: none;
}
.surname-item input[type=checkbox] { cursor: pointer; flex-shrink: 0; }
.surname-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  cursor: pointer;
}
.surname-color-picker {
  width: 18px;
  height: 18px;
  border: none;
  border-radius: var(--r-xs);
  cursor: pointer;
  background: transparent;
  padding: 0;
  flex-shrink: 0;
}
.surname-color-picker::-webkit-color-swatch-wrapper { padding: 0; }
.surname-color-picker::-webkit-color-swatch { border: 1px solid var(--c-5); border-radius: var(--r-xs); }
.surname-label { flex: 1; color: var(--c-11); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.surname-count { color: var(--c-7); font-size: 11px; flex-shrink: 0; }

#surname-shown-count {
  font-size: 11px;
  color: var(--c-8);
  padding: 4px 2px;
  border-top: 1px solid var(--c-4);
  flex-shrink: 0;
}

/* ── 2D FOCUS PANEL ── */
#focus-panel {
  flex-shrink: 0;
  padding: 6px 0 8px;
  border-top: 1px solid var(--c-4);
  border-bottom: 1px solid var(--c-4);
  margin-bottom: 4px;
}

#focus-current {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 4px 0 6px;
}

#focus-current-name {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  color: var(--c-12);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#focus-current-name.focus-none { color: var(--c-7); font-weight: 400; font-style: italic; }

#focus-clear-btn {
  background: none;
  border: 1px solid var(--c-6);
  color: var(--c-9);
  border-radius: var(--r-xs);
  font-size: 10px;
  line-height: 1;
  padding: 3px 5px;
  cursor: pointer;
  flex-shrink: 0;
}
#focus-clear-btn:hover { background: var(--c-5); color: var(--c-12); }

.focus-layout-toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--c-10);
  cursor: pointer;
  user-select: none;
  margin-bottom: 7px;
}
.focus-layout-toggle input { cursor: pointer; flex-shrink: 0; accent-color: var(--accent); }

.focus-limit-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  color: var(--c-8);
  margin-bottom: 3px;
}
.focus-limit-row #focus-limit-val,
.focus-limit-row #gen-range-val,
.focus-limit-row #cousin-degree-val { color: var(--c-11); font-variant-numeric: tabular-nums; }

/* Two-handle range. There is no native one, and two separate sliders read as
   two settings rather than as one span — so stack two native inputs in the
   same box and let each contribute nothing but its thumb. The track is drawn
   once, by the container, which is also the only way to shade the part of it
   that lies between the handles. */
.dual-range {
  position: relative;
  height: 18px;
  --gen-lo: 0%;
  --gen-hi: 100%;
}
.dual-range::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 3px;
  margin-top: -1.5px;
  border-radius: var(--r-xs);
  background: linear-gradient(to right,
    var(--c-4) 0, var(--c-4) var(--gen-lo),
    var(--accent) var(--gen-lo), var(--accent) var(--gen-hi),
    var(--c-4) var(--gen-hi), var(--c-4) 100%);
}
.dual-range input[type="range"] {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  height: 18px;
  margin: 0;
  background: none;
  -webkit-appearance: none;
  appearance: none;
  /* Only the thumbs take the mouse; anywhere else the click reaches the input
     underneath, so the handle nearer the pointer is always the one grabbed. */
  pointer-events: none;
}
.dual-range input[type="range"]::-webkit-slider-runnable-track { background: none; height: 18px; }
.dual-range input[type="range"]::-moz-range-track { background: none; height: 18px; }
.dual-range input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  cursor: pointer;
  width: 12px; height: 12px;
  margin-top: 3px;              /* webkit will not centre a thumb on its track */
  border-radius: 50%;
  background: var(--accent);
  border: 1px solid var(--c-2);
}
.dual-range input[type="range"]::-moz-range-thumb {
  pointer-events: auto;
  cursor: pointer;
  width: 12px; height: 12px;
  border: 1px solid var(--c-2);
  border-radius: 50%;
  background: var(--accent);
}

#focus-limit-slider,
#cousin-degree-slider {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Tick marks come from the <datalist>. Browsers render them, but the default
   labels sit in the page's text colour, which is unreadable on this panel. */
#cousin-degree-slider { margin-bottom: 0; }
#cousin-degree-ticks,
#gen-range-ticks {
  display: flex;
  justify-content: space-between;
  width: 100%;
  padding: 0 2px;
  font-size: 9px;
  color: var(--c-7);
  font-variant-numeric: tabular-nums;
}
#cousin-degree-ticks option,
#gen-range-ticks option { padding: 0; }

#focus-hidden-info {
  font-size: 11px;
  color: var(--c-8);
  margin-top: 5px;
}

.focus-hint {
  font-size: 10px;
  color: var(--c-7);
  line-height: 1.4;
  margin-top: 5px;
}

#sidebar-buttons {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding-top: 8px;
  border-top: 1px solid var(--c-4);
  flex-shrink: 0;
}

.sidebar-btn {
  background: var(--c-3);
  color: var(--c-10);
  border: 1px solid var(--c-5);
  padding: 6px 10px;
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: 12px;
  width: 100%;
  text-align: left;
}
.sidebar-btn:hover { background: var(--c-5); color: var(--c-12); border-color: var(--c-7); }
.sidebar-btn:active { transform: translateY(1px); }

.sidebar-toggle {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--c-10);
  cursor: pointer;
  user-select: none;
  padding: 4px 2px;
  border-top: 1px solid var(--c-4);
  margin-top: 2px;
}
.sidebar-toggle input { cursor: pointer; flex-shrink: 0; }
.sidebar-toggle:hover { color: var(--c-11); }

/* ── LINK COLOR PANEL ── */
/* Every collapsible sidebar section (stats, colours, 3D, physics) shares one
   look — this used to be the same five declarations repeated per #id, which is
   how the physics header drifted into a different size and its own <i> arrow. */
#sidebar details {
  flex-shrink: 0;
  border-top: 1px solid var(--c-4);
  margin-top: 4px;
  padding-top: 4px;
}
#sidebar details > summary {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 500;
  color: var(--c-10);
  cursor: pointer;
  user-select: none;
  list-style: none;
  padding: 6px 8px;
  margin: 0 -8px;
  border-radius: var(--r-sm);
  transition: background var(--t), color var(--t);
}
#sidebar details > summary::-webkit-details-marker { display: none; }
#sidebar details > summary::before {
  content: '';
  flex-shrink: 0;
  width: 0; height: 0;
  border-left: 4px solid currentColor;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  transition: transform var(--t);
}
#sidebar details[open] > summary::before { transform: rotate(90deg); }
#sidebar details > summary:hover { background: var(--c-3); color: var(--c-12); }
.link-color-row {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 0;
  font-size: 12px;
  color: var(--c-10);
}
.link-color-row input[type=color] {
  width: 28px;
  height: 20px;
  border: 1px solid var(--c-6);
  border-radius: var(--r-xs);
  background: none;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}
#link-colors-reset, #node-colors-reset {
  margin-top: 4px;
  width: 100%;
  font-size: 11px;
  background: var(--c-4);
  color: var(--c-10);
  border: 1px solid var(--c-6);
  border-radius: var(--r-xs);
  padding: 4px 0;
  cursor: pointer;
}
#link-colors-reset:hover, #node-colors-reset:hover { background: var(--c-5); color: var(--c-11); }

/* ── GRAPH ── */
#graph-wrapper {
  position: relative;
  overflow: hidden;
  min-width: 0;
  min-height: 0;
}

#graph-container,
#graph-3d-container {
  position: absolute;
  inset: 0;
  background: var(--c-0);
}
#graph-container { display: none; }
#graph-3d-container { display: block; }

/* ── EMPTY STATE ──
   Shown over whichever view is up until the tree has somebody in it. The two
   things a new arrival can actually do, said once, instead of an empty black
   rectangle and a sentence in the status bar. */
#empty-state {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--c-1);
  z-index: 5;
}
.empty-card {
  max-width: 420px;
  text-align: center;
  color: var(--c-11);
}
.empty-icon { font-size: 44px; line-height: 1; margin-bottom: 12px; }
.empty-card h2 {
  margin: 0 0 8px;
  font-size: 19px;
  font-weight: 600;
  color: var(--c-12);
}
.empty-card p {
  margin: 0 0 18px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--c-9);
}
.empty-actions {
  display: flex;
  gap: 8px;
  justify-content: center;
  flex-wrap: wrap;
}
.empty-btn {
  background: var(--c-4);
  color: var(--c-12);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 9px 16px;
  font-size: 13px;
  cursor: pointer;
}
.empty-btn:hover { background: var(--c-5); color: var(--c-13); }
.empty-btn--primary {
  background: var(--accent-solid);
  border-color: var(--accent-solid-border);
  color: var(--c-13);
}
.empty-btn--primary:hover { background: var(--accent-solid-hover); }
.empty-hint {
  margin-top: 16px;
  font-size: 11px;
  color: var(--c-7);
}

/* ── AUTOSAVE BAR ──
   Sits over whichever view is up, same as #empty-state. Replaces a blocking
   confirm() on load: it names the session and lets it be dismissed instead of
   forcing an answer before the graph is drawn. */
#autosave-bar {
  position: absolute;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 10px 14px;
  background: var(--c-3);
  border: 1px solid var(--c-6);
  border-radius: var(--r-md);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
  font-size: 13px;
  color: var(--c-12);
}
#autosave-bar-text { white-space: normal; }
.autosave-bar-btn {
  background: var(--c-4);
  color: var(--c-12);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 6px 12px;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.autosave-bar-btn:hover { background: var(--c-5); color: var(--c-13); }
.autosave-bar-btn--primary {
  background: var(--accent-solid);
  border-color: var(--accent-solid-border);
  color: var(--c-13);
}
.autosave-bar-btn--primary:hover { background: var(--accent-solid-hover); }

#graph-svg {
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
/* The overview layer sits under the SVG and never takes a pointer event: the
   zoom/pan behaviour is bound to the SVG above it, and both are painted from
   the same transform, so they stay registered without the canvas taking part. */
#graph-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}
#graph-svg .main-g {
  will-change: transform;
}

#graph-3d-container,
#graph-3d-container canvas {
  touch-action: none;
  /* A press-and-hold on the canvas otherwise raises iOS's share/copy callout
     mid-orbit, which cancels the gesture and leaves the camera stuck. */
  -webkit-touch-callout: none;
  user-select: none;
  -webkit-user-select: none;
}

/* Drag handle for mobile bottom sheet */
.panel-drag-handle {
  display: none;
  width: 36px;
  height: 4px;
  border-radius: var(--r-xs);
  background: var(--c-6);
  margin: 6px auto 8px;
}

#view-toggle-btn {
  background: var(--c-4);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  padding: 6px 12px;
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: 13px;
  white-space: nowrap;
}
#view-toggle-btn:hover:not(:disabled) { background: var(--c-5); color: var(--c-11); }
#view-toggle-btn:disabled { opacity: 0.4; cursor: not-allowed; }
#view-toggle-btn.active-3d { background: var(--c-5); color: var(--c-12); border-color: var(--accent); }

/* ── DETAIL PANEL ── */
#detail-panel {
  background: var(--c-2);
  border-left: 1px solid var(--c-4);
  box-shadow: -8px 0 24px rgba(0, 0, 0, 0.35);
  overflow: hidden;
  padding: 12px;
  font-size: 13px;
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}

#detail-content {
  flex: 1 1 auto;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0;
}

#detail-panel h2 {
  font-size: 15px;
  color: var(--c-12);
  margin-bottom: 10px;
  word-break: break-word;
  padding-right: 24px;
}

.detail-section { margin-bottom: 10px; }
.detail-label {
  color: var(--c-8);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 2px;
}
.detail-value { color: var(--c-11); line-height: 1.4; }

.detail-marriage {
  background: var(--c-4);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.5;
}
.detail-fam-card {
  cursor: pointer;
  border: 1px solid transparent;
  transition: background 0.15s, border-color 0.15s;
}
.detail-fam-card:hover {
  background: var(--c-5);
  border-color: var(--c-8);
}
.clickable-name {
  color: var(--c-9);
  cursor: pointer;
}
.clickable-name:hover { text-decoration: underline; }


/* Two rows: three highlight-mode toggles on top, focus/clear actions below.
   This keeps all five buttons visible without scrolling and gives each row
   enough width for its label. */
#detail-buttons {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 5px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--c-4);
  flex-shrink: 0;
}
#detail-buttons > #btn-ancestors,
#detail-buttons > #btn-descendants,
#detail-buttons > #btn-both { grid-column: span 2; }
#detail-buttons > #btn-focus-2d,
#detail-buttons > #btn-clear-hl { grid-column: span 3; }
#detail-buttons > #hl-count-info { grid-column: 1 / -1; }

.highlight-btn {
  background: var(--c-3);
  color: var(--c-10);
  border: 1px solid var(--c-5);
  padding: 7px 6px;
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: 12px;
  text-align: center;
  width: 100%;
  min-width: 0;
  overflow-wrap: break-word;
  white-space: normal;
}
.highlight-btn:hover:not(:disabled) { background: var(--c-5); color: var(--c-12); border-color: var(--c-7); }
.highlight-btn.active { background: var(--accent); color: var(--c-1); border-color: var(--accent); }
.highlight-btn:disabled { opacity: 0.4; cursor: not-allowed; }
#hl-count-info {
  font-size: 11px;
  color: var(--c-9);
  text-align: center;
  padding: 3px 4px;
  letter-spacing: 0.02em;
}

#close-panel-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: transparent;
  color: var(--c-8);
  border: none;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  width: 24px;
  height: 24px;
}
#close-panel-btn:hover { color: var(--c-12); }

/* ── TOOLTIP ── */
#tooltip {
  position: fixed;
  background: rgba(31, 31, 31, 0.97);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  font-size: 12px;
  color: var(--c-12);
  pointer-events: none;
  z-index: 1000;
  max-width: 260px;
  display: none;
  line-height: 1.5;
}
.tt-name { font-weight: bold; font-size: 13px; color: var(--c-13); margin-bottom: 3px; }
.tt-detail { color: var(--c-10); }

/* ── LOADING OVERLAY ── */
#loading-overlay {
  position: absolute;
  inset: 0;
  background: rgba(28, 28, 28, 0.88);
  display: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 10px;
  font-size: 16px;
  color: var(--c-12);
  z-index: 50;
}
.spinner {
  width: 36px; height: 36px;
  border: 3px solid var(--c-4);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── RESET VIEW BUTTON ── */
#reset-view-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--c-6);
  background: rgba(25, 25, 25, 0.9);
  color: var(--c-9);
  font-size: 16px;
  cursor: pointer;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
}
#reset-view-btn:hover {
  background: var(--c-5);
  color: var(--c-13);
  border-color: var(--c-8);
}

#zoom-controls {
  position: absolute;
  bottom: 20px;
  right: 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  z-index: 40;
}
#zoom-controls button {
  width: 36px;
  height: 36px;
  border-radius: var(--r-md);
  border: 1px solid var(--c-6);
  background: rgba(25, 25, 25, 0.9);
  color: var(--c-9);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
}
#zoom-controls button:hover {
  background: var(--c-5);
  color: var(--c-13);
  border-color: var(--c-8);
}
#zoom-controls button:active {
  background: var(--c-4);
  transform: scale(0.95);
}

/* On desktop, hide zoom buttons (keyboard / scroll wheel works fine) */
@media (hover: hover) and (pointer: fine) {
  #zoom-controls { display: none; }
}

/* ── SCROLLBARS ── */
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--c-6);
  border-radius: 99px;
  border: 2px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--c-8); background-clip: content-box; }

/* ── SVG STYLES ── */
.node-label {
  pointer-events: none;
  text-anchor: middle;
  dominant-baseline: auto;
  /* fill, font-size, font-weight, fill-opacity all set via SVG attrs in JS */
}

/* Ring around the focus person — here rather than as an SVG attribute so it
   tracks the accent colour. */
.focus-ring { stroke: var(--accent); }

/* ── PHYSICS PANEL ── */
/* Header styling comes from the shared `#sidebar details` rules above. */
#physics-panel { margin-bottom: 4px; }

.phys-group {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 8px;
}
.phys-section-label {
  font-size: 10px;
  color: var(--c-7);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-top: 4px;
  margin-bottom: -2px;
}
.phys-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* What the scene budgets above are actually doing right now — a line of plain
   figures under the sliders, so the numbers are not set blind. */
.phys-hint {
  font-size: 10px;
  color: var(--c-8);
  line-height: 1.45;
  margin: 2px 0 4px;
  font-variant-numeric: tabular-nums;
}
.phys-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.phys-label {
  font-size: 11px;
  color: var(--c-10);
}
.phys-value {
  font-size: 11px;
  color: var(--c-12);
  font-variant-numeric: tabular-nums;
  min-width: 34px;
  text-align: right;
}
.phys-num {
  width: 56px;
  padding: 2px 4px;
  font-size: 11px;
  color: var(--c-12);
  background: var(--c-3);
  border: 1px solid var(--c-6);
  border-radius: var(--r-xs);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.phys-num:focus {
  outline: none;
  border-color: #7e8fa8;
}
.phys-slider {
  width: 100%;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  background: var(--c-4);
  border-radius: var(--r-xs);
  outline: none;
  cursor: pointer;
}
.phys-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  border: none;
}
.phys-slider::-moz-range-thumb {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--accent);
  cursor: pointer;
  border: none;
}
.phys-slider:hover { background: var(--c-5); }

#phys-reheat-btn {
  margin-top: 6px;
  background: var(--c-5);
  color: var(--c-11);
  border: 1px solid var(--c-6);
  padding: 5px 8px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 12px;
  width: 100%;
  text-align: center;
}
#phys-reheat-btn:hover { background: var(--accent); color: var(--c-1); border-color: var(--accent); }
#phys-reset-btn {
  background: var(--c-4);
  color: var(--c-8);
  border: 1px solid var(--c-6);
  padding: 4px 8px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 11px;
  width: 100%;
  text-align: center;
  margin-top: 3px;
}
#phys-reset-btn:hover { color: var(--c-11); }

/* ── PHYSICS PRESETS ── */
#preset-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 4px;
  max-height: 110px;
  overflow-y: auto;
}
.preset-row {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--c-3);
  border-radius: var(--r-xs);
  padding: 3px 5px;
}
.preset-row.builtin { border-left: 2px solid var(--c-8); }
.preset-row.user    { border-left: 2px solid var(--accent); }
.preset-name {
  flex: 1;
  font-size: 11px;
  color: var(--c-9);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.preset-name:hover { color: var(--c-11); text-decoration: underline; }
.preset-del {
  background: transparent;
  border: none;
  color: var(--c-6);
  cursor: pointer;
  font-size: 11px;
  line-height: 1;
  padding: 0 2px;
  flex-shrink: 0;
}
.preset-del:hover { color: var(--c-8); }
.preset-save-row {
  display: flex;
  gap: 4px;
  margin-top: 5px;
}
.preset-name-input {
  flex: 1;
  min-width: 0;
  background: var(--c-4);
  border: 1px solid var(--c-6);
  color: var(--c-12);
  padding: 4px 6px;
  border-radius: var(--r-xs);
  font-size: 11px;
}
.preset-name-input:focus { outline: none; border-color: var(--accent); }
.preset-name-input::placeholder { color: var(--c-6); }
.preset-save-btn {
  background: var(--c-4);
  border: 1px solid var(--accent);
  color: var(--c-12);
  padding: 4px 8px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 12px;
  flex-shrink: 0;
}
.preset-save-btn:hover { background: var(--accent); color: var(--c-1); }

/* ── EDIT FORM ── */
#detail-edit-bar {
  display: none;
  margin-bottom: 8px;
}
.edit-bar-btn {
  background: var(--c-4);
  color: var(--c-10);
  border: 1px solid var(--c-6);
  padding: 4px 10px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 12px;
}
.edit-bar-btn:hover { background: var(--c-6); color: var(--c-12); }
.edit-bar-btn--danger { color: var(--c-8); border-color: var(--c-5); }
.edit-bar-btn--danger:hover { background: var(--c-5); color: var(--c-9); }
#delete-confirm-bar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 6px 0; border-top: 1px solid var(--c-5); margin-top: 6px;
  font-size: 12px; color: var(--c-8);
}
#delete-confirm-msg { flex: 1; min-width: 0; }
.edit-section { margin-bottom: 8px; }
.edit-label {
  font-size: 10px;
  color: var(--c-8);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 3px;
}
.edit-input, .edit-select {
  width: 100%;
  background: var(--c-4);
  border: 1px solid var(--c-6);
  color: var(--c-12);
  padding: 5px 7px;
  border-radius: var(--r-xs);
  font-size: 12px;
  font-family: inherit;
}
.edit-input:focus, .edit-select:focus { outline: none; border-color: var(--accent); }
.ef-fam-block {
  background: var(--c-2);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  margin-bottom: 6px;
}
.ef-fam-header {
  font-size: 12px;
  font-weight: 600;
  color: var(--c-9);
  margin-bottom: 6px;
}
.gd-widget {
  display: flex; gap: 4px; align-items: center;
}
.gd-prefix, .gd-month {
  background: var(--c-4); border: 1px solid var(--c-6); color: var(--c-12);
  padding: 5px 4px; border-radius: var(--r-xs); font-size: 12px; font-family: inherit;
  cursor: pointer;
}
.gd-prefix { flex: 0 0 58px; }
.gd-month  { flex: 0 0 62px; }
.gd-prefix option, .gd-month option { background: var(--c-4); }
.gd-prefix:focus, .gd-month:focus { outline: none; border-color: var(--accent); }
.gd-day, .gd-year {
  background: var(--c-4); border: 1px solid var(--c-6); color: var(--c-12);
  padding: 5px 5px; border-radius: var(--r-xs); font-size: 12px; font-family: inherit;
  -moz-appearance: textfield; appearance: textfield;
}
.gd-day  { flex: 0 0 44px; }
.gd-year { flex: 1; min-width: 0; }
.gd-day::-webkit-inner-spin-button,
.gd-year::-webkit-inner-spin-button,
.gd-day::-webkit-outer-spin-button,
.gd-year::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.gd-day:focus, .gd-year:focus { outline: none; border-color: var(--accent); }
.edit-select option { background: var(--c-4); }
.edit-textarea {
  width: 100%;
  background: var(--c-4);
  border: 1px solid var(--c-6);
  color: var(--c-12);
  padding: 5px 7px;
  border-radius: var(--r-xs);
  font-size: 12px;
  font-family: inherit;
  resize: vertical;
  min-height: 55px;
}
.edit-textarea:focus { outline: none; border-color: var(--accent); }
.edit-checkbox-row {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--c-11);
  margin-bottom: 6px;
  cursor: pointer;
}
.edit-checkbox-row input { cursor: pointer; }
.edit-form-buttons {
  display: flex;
  gap: 6px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--c-4);
}
.edit-save-btn {
  flex: 1;
  background: var(--accent);
  color: var(--c-1);
  border: none;
  padding: 6px 10px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 12px;
}
.edit-save-btn:hover { background: var(--c-12); }
.edit-cancel-btn {
  flex: 1;
  background: var(--c-4);
  color: var(--c-11);
  border: 1px solid var(--c-6);
  padding: 6px 10px;
  cursor: pointer;
  border-radius: var(--r-xs);
  font-size: 12px;
}
.edit-cancel-btn:hover { background: var(--c-5); }

/* ── Relationship linking (edit form) ── */
.ef-rel-add-row {
  display: flex;
  gap: 4px;
  align-items: center;
  flex-wrap: wrap;
}
.ef-rel-add-row .edit-input {
  flex: 1;
  min-width: 100px;
}
.ef-rel-add-btn {
  background: var(--accent);
  color: var(--c-1);
  border: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-sm);
  font-size: 18px;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.ef-rel-add-btn:hover { background: var(--c-12); }

.ef-rel-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 0;
  font-size: 12px;
  color: var(--c-10);
}
.ef-rel-type {
  color: var(--c-9);
  font-size: 11px;
  white-space: nowrap;
}
.ef-rel-name {
  flex: 1;
  color: var(--c-12);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ef-rel-remove {
  background: none;
  border: none;
  color: var(--c-8);
  cursor: pointer;
  font-size: 14px;
  padding: 2px 5px;
  border-radius: var(--r-xs);
  flex-shrink: 0;
}
.ef-rel-remove:hover {
  background: var(--c-3);
}

.ef-existing-rel {
  background: var(--c-2);
  border-color: var(--c-4);
}
.ef-existing-rel .ef-rel-type { color: var(--c-8); }

/* ── Family edit extras ── */
.fam-type-checks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
  margin-top: 4px;
}
.fam-type-check {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--c-10);
  cursor: pointer;
}
.ef-toggle-new-btn {
  background: none;
  border: 1px dashed var(--c-6);
  color: var(--c-9);
  font-size: 12px;
  padding: 3px 8px;
  border-radius: var(--r-sm);
  cursor: pointer;
  width: 100%;
  text-align: left;
}
.ef-toggle-new-btn:hover { background: var(--c-3); }

.fam-marr-block {
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 8px;
  margin-bottom: 6px;
}
.fam-marr-block-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 11px;
  color: var(--c-9);
  font-weight: 600;
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.ef-new-person-btn {
  width: 100%;
  margin-top: 6px;
  padding: 5px;
  background: var(--c-3);
  border: 1px dashed var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-8);
  font-size: 11px;
  cursor: pointer;
}
.ef-new-person-btn:hover {
  background: var(--c-4);
  color: var(--c-10);
  border-style: solid;
}

.ef-rel-new-badge {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 4px;
  background: var(--c-4);
  border: 1px solid var(--c-9);
  border-radius: var(--r-xs);
  color: var(--c-9);
  font-size: 9px;
  vertical-align: middle;
}

#center-view-btn, #center-person-btn {
  background: var(--c-4);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  padding: 6px 12px;
  cursor: pointer;
  border-radius: var(--r-sm);
  font-size: 13px;
  white-space: nowrap;
  display: none;
}
#center-view-btn:hover:not(:disabled), #center-person-btn:hover:not(:disabled) {
  background: var(--c-5); color: var(--c-11);
}
#center-view-btn:disabled, #center-person-btn:disabled {
  opacity: 0.4; cursor: not-allowed;
}
#center-person-btn.has-selection {
  color: var(--c-12); border-color: var(--accent);
}

/* ── Save / Export split button ─────────────────────────────── */
#dl-wrap {
  display: none; /* shown after a file is loaded */
  align-items: stretch;
  position: relative;
}
#dl-btn {
  background: var(--c-4);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  border-right: none;
  border-radius: var(--r-sm) 0 0 var(--r-sm);
  padding: 6px 12px;
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
  position: relative;
}
#dl-btn:hover { background: var(--c-5); color: var(--c-11); }
#dl-btn.has-unsaved {
  color: var(--c-11);
  border-color: var(--c-9);
  animation: dl-pulse 2.5s ease-in-out infinite;
}
#dl-btn.has-unsaved::after {
  content: '';
  position: absolute;
  top: 4px;
  right: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c-8);
}
@keyframes dl-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(240, 240, 240, 0); }
  50%       { box-shadow: 0 0 0 4px rgba(240, 240, 240, 0.35); }
}
#dl-format-btn {
  background: var(--c-4);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  border-left-color: var(--c-5);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 6px 8px;
  cursor: pointer;
  font-size: 11px;
  line-height: 1;
}
#dl-format-btn:hover { background: var(--c-5); color: var(--c-11); }
#export-dropdown, #tools-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  background: var(--c-3);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  z-index: 200;
  min-width: 160px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
#export-dropdown.open, #tools-dropdown.open { display: block; }
#export-dropdown button, #tools-dropdown button {
  display: block;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--c-5);
  color: var(--c-9);
  padding: 9px 14px;
  text-align: left;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
#export-dropdown button:last-child, #tools-dropdown button:last-child { border-bottom: none; }
#export-dropdown button:hover, #tools-dropdown button:hover { background: var(--c-5); color: var(--c-11); }

/* ── Node context menu (right-click on a graph node) ── */
#node-context-menu {
  position: fixed;
  z-index: 1300;
  background: var(--c-3);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  min-width: 180px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  overflow: hidden;
}
#node-context-menu button {
  display: block;
  width: 100%;
  background: none;
  border: none;
  border-bottom: 1px solid var(--c-5);
  color: var(--c-10);
  padding: 9px 14px;
  text-align: left;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
#node-context-menu button:last-child { border-bottom: none; }
#node-context-menu button:hover { background: var(--c-5); color: var(--c-12); }
/* Reviewing the changes is not a fourth export format; the heavier rule keeps
   it from being read as one by someone aiming for GEDCOM. */
#export-dropdown .dd-review { border-bottom: 1px solid var(--c-7); color: var(--c-11); }

/* ── Tools menu ──────────────────────────────────────────────
   Look comes from the export dropdown's rules above; only the anchoring
   differs. It sits far enough right that a left-anchored menu of full tool
   names would run off the end of the bar. */
#tools-wrap {
  display: none;   /* showDataUI() shows it once there is a tree to act on */
  position: relative;
  align-items: stretch;
}
#tools-btn {
  background: var(--c-4);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 6px 12px;
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
}
#tools-btn:hover { background: var(--c-5); color: var(--c-11); }
#tools-btn[aria-expanded="true"] {
  background: var(--c-5);
  color: var(--c-11);
  border-color: var(--c-7);
}
.tools-caret { font-size: 10px; opacity: 0.7; transition: transform var(--t); }
#tools-btn[aria-expanded="true"] .tools-caret { transform: rotate(180deg); }
#tools-dropdown {
  left: auto;
  right: 0;
  min-width: 230px;
}

/* ══════════════════════════════════════
   MOBILE RESPONSIVE  (≤ 768px)
══════════════════════════════════════ */
@media (max-width: 768px) {
  #sidebar-toggle-btn {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  #topbar {
    padding: 6px 10px;
    gap: 6px;
  }

  #topbar h1 {
    font-size: 13px;
  }

  #import-btn, #new-person-btn, #view-toggle-btn, #dl-btn, #dl-format-btn,
  #center-view-btn, #center-person-btn, #tools-btn {
    padding: 5px 10px;
    font-size: 12px;
  }

  /* Status moves to its own row */
  #status {
    width: 100%;
    order: 10;
    font-size: 11px;
    flex: none;
  }

  /* Main layout: single column, sidebar and detail-panel no longer in grid */
  #main-layout {
    grid-template-columns: 1fr !important;
  }

  #main-layout.panel-open {
    grid-template-columns: 1fr !important;
  }

  /* Sidebar: slide-in drawer from left */
  #sidebar {
    position: fixed;
    top: 0;
    left: -270px;
    bottom: 0;
    width: 260px;
    z-index: 200;
    transition: left 0.3s ease;
    box-shadow: 4px 0 16px rgba(0, 0, 0, 0.6);
    overflow-y: auto;
  }

  #sidebar.sidebar-open {
    left: 0;
  }

  /* Detail panel: bottom sheet */
  #detail-panel {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-height: 65vh;
    border-left: none;
    border-top: 2px solid var(--c-4);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    z-index: 150;
    transform: translateY(100%);
    transition: transform 0.3s ease;
    padding-bottom: env(safe-area-inset-bottom, 12px);
    overscroll-behavior: contain;
  }

  #detail-panel.panel-visible {
    transform: translateY(0);
  }

  /* Show drag handle on mobile bottom sheet */
  .panel-drag-handle {
    display: block;
  }

  /* Close button — bigger touch target on mobile */
  #close-panel-btn {
    width: 40px;
    height: 40px;
    font-size: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* Graph takes full layout column */
  #graph-wrapper {
    grid-column: 1;
  }

  /* Zoom controls: always visible on touch devices, larger targets */
  #zoom-controls {
    display: flex;
    bottom: 24px;
    right: 12px;
    gap: 6px;
  }
  #zoom-controls button {
    width: 44px;
    height: 44px;
    font-size: 22px;
    border-radius: var(--r-lg);
  }

  /* Larger touch targets for surname checkboxes */
  .surname-item {
    padding: 5px 0;
    min-height: 36px;
  }

  .sidebar-btn {
    padding: 8px 10px;
    font-size: 13px;
    min-height: 40px;
  }

  .highlight-btn {
    padding: 10px 10px;
    font-size: 13px;
    min-height: 40px;
  }

  .edit-bar-btn {
    padding: 8px 12px;
    min-height: 40px;
  }

  /* Slightly larger sliders on mobile */
  .phys-slider {
    height: 6px;
  }

  .phys-slider::-webkit-slider-thumb {
    width: 20px;
    height: 20px;
  }

  .phys-slider::-moz-range-thumb {
    width: 20px;
    height: 20px;
  }

  /* Highlight buttons: two rows on mobile */
  #detail-buttons {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 5px;
    flex-shrink: 0;
  }

  #detail-buttons > #btn-ancestors,
  #detail-buttons > #btn-descendants,
  #detail-buttons > #btn-both { grid-column: span 2; }
  #detail-buttons > #btn-focus-2d,
  #detail-buttons > #btn-clear-hl { grid-column: span 3; }
  #detail-buttons > #hl-count-info { grid-column: 1 / -1; }

  .highlight-btn {
    min-width: 0;
    overflow-wrap: break-word;
    white-space: normal;
  }

  /* Clickable names — bigger touch targets */
  .clickable-name {
    display: inline-block;
    padding: 3px 0;
    min-height: 28px;
    line-height: 22px;
  }

  /* Tooltip: hide on touch (covered by the detail panel) */
  @media (hover: none) {
    #tooltip { display: none !important; }
  }

  /* Bigger touch targets: the map's colour picker/reset pair, and the
     right-click/long-press context menu rows. */
  #map-dot-color-row input[type=color], #map-dot-color-reset {
    width: 38px;
    height: 38px;
  }
  #node-context-menu button {
    padding: 12px 14px;
    font-size: 14px;
  }
}

/* Reopen pill — floating at bottom when panel is minimized */
#reopen-panel-pill {
  position: fixed;
  bottom: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 140;
  background: rgba(20, 20, 20, 0.92);
  color: var(--c-9);
  border: 1px solid var(--c-6);
  border-radius: 20px;
  padding: 8px 20px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  max-width: 80vw;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
#reopen-panel-pill:active {
  background: rgba(46, 46, 46, 0.95);
}

@media (max-width: 400px) {
  #topbar h1 { display: none; }
}

/* Icon-only top bar on a phone: the label text is what pushed half these
   buttons onto a second (sometimes third) row, eating vertical space the 3D
   scene and the map could otherwise use. The icon plus the existing title=""
   tooltip is still enough to identify each button. */
@media (max-width: 480px) {
  #import-btn span[data-i18n], #open-recent-btn span[data-i18n],
  #new-person-btn span[data-i18n], #view-toggle-btn span[data-i18n],
  #dl-btn span[data-i18n], #center-view-btn span[data-i18n],
  #center-person-btn span[data-i18n], #tools-btn span[data-i18n] {
    display: none;
  }
  #import-btn, #open-recent-btn, #new-person-btn, #view-toggle-btn, #dl-btn, #dl-format-btn,
  #center-view-btn, #center-person-btn, #tools-btn {
    padding: 6px 9px;
  }
}

/* ── Relation tool panel ── */
#relation-panel {
  display: none;
  position: fixed;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 400;
  background: var(--c-3);
  border: 1px solid var(--c-4);
  border-radius: var(--r-lg);
  padding: 14px 16px 16px;
  width: 320px;
  max-width: calc(100vw - 32px);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.6);
  font-size: 13px;
  color: var(--c-11);
}
#relation-panel.panel-visible { display: block; }

.rel-close-btn {
  position: absolute;
  top: 8px; right: 10px;
  background: none; border: none;
  color: var(--c-8); font-size: 14px; cursor: pointer;
}
.rel-close-btn:hover { color: var(--c-13); }

.rel-title {
  font-size: 14px;
  color: var(--c-12);
  margin: 0 0 12px;
}

.rel-slots {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.rel-slot {
  flex: 1;
  background: var(--c-3);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  padding: 8px;
  min-width: 0;
}
.rel-slot-label {
  font-size: 10px;
  color: var(--c-7);
  text-transform: uppercase;
  letter-spacing: 0.8px;
  margin-bottom: 3px;
}
.rel-slot-name {
  font-size: 12px;
  color: var(--c-10);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 6px;
  min-height: 16px;
}
.rel-search-wrap {
  position: relative;
  margin-bottom: 5px;
}
.rel-search {
  width: 100%;
  box-sizing: border-box;
  background: var(--c-3);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 4px 7px;
  font-size: 11px;
  color: var(--c-11);
  outline: none;
}
.rel-search:focus { border-color: var(--accent); }
.rel-dropdown {
  display: none;
  position: absolute;
  left: 0; right: 0;
  top: calc(100% + 2px);
  background: var(--c-3);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  z-index: 500;
  max-height: 160px;
  overflow-y: auto;
}
.rel-drop-item {
  padding: 5px 8px;
  font-size: 11px;
  color: var(--c-10);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rel-drop-item:hover { background: var(--c-4); color: var(--c-11); }

.rel-pick-btn {
  width: 100%;
  padding: 3px 0;
  font-size: 13px;
  background: var(--c-4);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-9);
  cursor: pointer;
}
.rel-pick-btn:hover { background: var(--c-5); color: var(--c-11); }
.rel-pick-btn.rel-picking {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--c-1);
  animation: rel-pulse 1s ease-in-out infinite;
}
@keyframes rel-pulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.6; }
}
.rel-divider {
  font-size: 18px;
  color: var(--c-6);
  flex-shrink: 0;
}
#rel-result {
  background: var(--c-3);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  min-height: 36px;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--c-12);
}
#rel-result:empty { display: none; }
.rel-icon { font-size: 18px; flex-shrink: 0; }
.rel-text { font-weight: 600; color: var(--c-12); }

.rel-common {
  margin-top: 8px;
  font-size: 11px;
  color: var(--c-9);
}

.rel-hl-btn {
  width: 100%;
  margin-top: 10px;
  padding: 5px 0;
  font-size: 12px;
  background: var(--c-4);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-9);
  cursor: pointer;
}
.rel-hl-btn:hover { background: var(--c-5); color: var(--c-11); }

/* Cursor hint when picking */
body.relation-picking * { cursor: crosshair !important; }

/* Hide reopen pill on desktop — only for mobile */
@media (min-width: 769px) {
  #reopen-panel-pill { display: none !important; }
}

/* ── Text Import Modal ────────────────────────────────────────────────────── */
#import-btn {
  background: var(--c-5);
  color: var(--c-12);
  border: 1px solid var(--c-7);
  border-radius: var(--r-sm);
  padding: 6px 14px;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
}
#import-btn:hover { background: var(--c-6); }

/* Working-file buttons. Both carry a filename, which can be long, so they get a
   ceiling and ellipsis rather than pushing the rest of the topbar off-screen. */
#open-recent-btn, #save-file-btn {
  background: var(--c-5);
  color: var(--c-12);
  border: 1px solid var(--c-7);
  border-radius: var(--r-sm);
  padding: 6px 12px;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}
#open-recent-btn span, #save-file-btn span {
  display: inline-block;
  max-width: 160px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
}
#open-recent-btn:hover, #save-file-btn:hover { background: var(--c-6); }
/* Unsaved work makes the save-in-place button the one to reach for — same cue
   the download button already uses. */
#save-file-btn.has-unsaved {
  color: var(--c-11);
  border-color: var(--c-9);
  animation: dl-pulse 2.5s ease-in-out infinite;
}

#new-person-btn {
  background: var(--accent);
  color: var(--c-1);
  border: 1px solid var(--accent);
  border-radius: var(--r-sm);
  padding: 6px 14px;
  font-size: 14px;
  cursor: pointer;
  white-space: nowrap;
}
#new-person-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

#import-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#import-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
}
#import-modal-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(1180px, 96vw);   /* the diff table wants the room */
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.7);
}
#import-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px 10px;
  border-bottom: 1px solid var(--c-4);
  flex-shrink: 0;
}
#import-modal-header h2 {
  margin: 0;
  font-size: 17px;
  color: var(--c-12);
  font-weight: 600;
}
#import-close-btn {
  background: none;
  border: none;
  color: var(--c-8);
  font-size: 18px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  line-height: 1;
}
#import-close-btn:hover { color: var(--c-12); background: var(--c-4); }

/* Step containers */
#import-step-input,
#import-step-review {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
  padding: 14px 18px;
  gap: 10px;
}
/* The panel is sized for the review table; a drop zone that wide reads as a
   mistake, so step 1 keeps its old measure. */
#import-step-input { max-width: 800px; width: 100%; margin: 0 auto; }
.import-hint {
  margin: 0;
  font-size: 12.5px;
  color: var(--c-8);
  line-height: 1.5;
}
.import-file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.import-file-label {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-10);
  padding: 5px 12px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
}
.import-file-label:hover { background: var(--c-4); }
#import-file-input { display: none; }
.import-file-name-lbl {
  font-size: 12px;
  color: var(--c-6);
  font-style: italic;
}
#import-drop-zone {
  border: 2px dashed var(--c-5);
  border-radius: var(--r-md);
  padding: 18px;
  text-align: center;
  cursor: pointer;
  color: var(--c-8);
  font-size: 13px;
  background: var(--c-2);
  transition: border-color .15s, background .15s;
  flex-shrink: 0;
}
#import-drop-zone:hover, #import-drop-zone.drag-over {
  border-color: var(--c-8);
  background: var(--c-2);
  color: var(--c-11);
}
#import-drop-filename { font-weight: 600; color: var(--c-11); }
#import-image-preview {
  max-width: 100%;
  max-height: 220px;
  display: block;
  margin: 8px auto 0;
  border-radius: var(--r-sm);
}
#import-image-options {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  flex-shrink: 0;
}
.import-ocr-status {
  font-size: 12px;
  color: var(--c-9);
  font-style: italic;
}
#import-error-msg {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-11);
  padding: 8px 12px;
  border-radius: var(--r-sm);
  font-size: 12.5px;
  flex-shrink: 0;
}
#import-text-area {
  flex: 1;
  min-height: 180px;
  background: var(--c-1);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  color: var(--c-11);
  font-family: 'Consolas', 'Courier New', monospace;
  font-size: 12px;
  padding: 10px 12px;
  resize: vertical;
  line-height: 1.5;
}
#import-text-area:focus { outline: none; border-color: var(--c-6); }

/* Footer buttons */
.import-step-footer {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
  padding-top: 4px;
}
.import-step-footer--review {
  border-top: 1px solid var(--c-4);
  padding-top: 10px;
  margin-top: 0;
}

#import-progress-overlay {
  position: absolute;
  inset: 0;
  background: var(--c-1);
  border-radius: var(--r-lg);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  z-index: 10;
  padding: 32px;
}
#import-progress-label {
  font-size: 14px;
  color: var(--c-12);
  font-weight: 600;
}
#import-progress-track {
  width: 100%;
  max-width: 420px;
  height: 10px;
  background: var(--c-4);
  border-radius: var(--r-sm);
  overflow: hidden;
}
#import-progress-bar {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--c-7), var(--c-8));
  border-radius: var(--r-sm);
  transition: width 0.12s ease;
}
#import-progress-count {
  font-size: 12px;
  color: var(--c-6);
}
.import-action-btn {
  padding: 6px 14px;
  border-radius: var(--r-sm);
  font-size: 13px;
  cursor: pointer;
  border: 1px solid var(--c-5);
  background: var(--c-3);
  color: var(--c-10);
}
.import-action-btn:hover { background: var(--c-4); }
.import-action-btn--primary {
  background: var(--c-5);
  border-color: var(--c-6);
  color: var(--c-12);
  font-weight: 600;
}
.import-action-btn--primary:hover { background: var(--c-6); }

/* Review step */
#import-step-review {
  padding-bottom: 0;
  min-height: 0;
}
.import-summary-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  font-size: 12.5px;
  padding: 8px 0 4px;
}
.import-stat { color: var(--c-8); }
.import-stat b { color: var(--c-11); }
.import-stat--person  b, .import-stat--person  { color: var(--c-9); }
.import-stat--update   b, .import-stat--update   { color: var(--c-10); }
.import-stat--marriage b, .import-stat--marriage { color: var(--c-9); }
.import-stat--approved b, .import-stat--approved { color: var(--c-8); }
.import-stat--skipped  b, .import-stat--skipped  { color: var(--c-9); }
.import-stat--pending  b, .import-stat--pending  { color: var(--c-9); }

.import-bulk-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 4px 0 8px;
}
.import-bulk-btn {
  padding: 4px 11px;
  border-radius: var(--r-sm);
  font-size: 12px;
  cursor: pointer;
  border: 1px solid transparent;
}
.import-bulk-btn--approve { background: var(--c-4); border-color: var(--c-6); color: var(--c-10); }
.import-bulk-btn--approve:hover { background: var(--c-5); }
.import-bulk-btn--skip    { background: var(--c-3); border-color: var(--c-5); color: var(--c-9); }
.import-bulk-btn--skip:hover    { background: var(--c-4); }
.import-bulk-btn--reset   { background: var(--c-4); border-color: var(--c-5); color: var(--c-9); }
.import-bulk-btn--reset:hover   { background: var(--c-4); }

#import-actions-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 4px;
  padding-bottom: 6px;
}

/* Filter chips + view switch */
.import-spacer { flex: 1; }
.import-view-btn {
  padding: 3px 10px;
  border-radius: var(--r-sm);
  font-size: 12px;
  cursor: pointer;
  background: var(--c-3);
  border: 1px solid var(--c-4);
  color: var(--c-9);
}
.import-view-btn--on { background: var(--c-4); border-color: var(--c-6); color: var(--c-12); }

.import-filter-bar {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  padding: 2px 0 6px;
}
.import-filter-chip {
  padding: 3px 10px;
  border-radius: var(--r-lg);
  font-size: 11.5px;
  cursor: pointer;
  background: var(--c-2);
  border: 1px solid var(--c-4);
  color: var(--c-8);
}
.import-filter-chip b { color: var(--c-11); }
.import-filter-chip:hover { background: var(--c-3); }
.import-filter-chip--on { background: var(--c-5); border-color: var(--c-6); color: var(--c-12); }
.import-filter-chip--warn   { border-color: var(--warn-dim); color: var(--warn); }
.import-filter-chip--warn b { color: var(--warn-bright); }

.import-connect-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-left: auto;
  font-size: 12px;
  color: var(--c-9);
  cursor: pointer;
  user-select: none;
}

.import-empty-filter {
  padding: 24px 8px;
  text-align: center;
  color: var(--c-8);
  font-size: 13px;
}

/* Diff table */
.import-diff-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
.import-diff-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--c-2);
  color: var(--c-8);
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid var(--c-4);
}
.import-dth-exp    { width: 26px; }
.import-dth-status { width: 68px; }

.import-drow > td {
  padding: 7px 8px;
  border-bottom: 1px solid var(--c-3);
  vertical-align: top;
}
.import-drow--approved > td { background: var(--c-2); }
.import-drow--skipped  > td { background: var(--c-1); opacity: 0.55; }
.import-drow--loose    > td { box-shadow: inset 3px 0 0 -1px var(--warn-dim); }
.import-drow:hover > td { background: var(--c-3); }

.import-dexp {
  background: none;
  border: none;
  color: var(--c-8);
  cursor: pointer;
  font-size: 12px;
  padding: 0 2px;
}
.import-dexp:hover { color: var(--c-12); }

.import-dcell-name { min-width: 150px; }
.import-dname  { color: var(--c-12); font-weight: 600; }
.import-dyears { color: var(--c-8); font-size: 11px; }

.import-dcell-diff { width: 46%; }
.import-dpair {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 1px 0;
  flex-wrap: wrap;
}
.import-dpair--pick { cursor: pointer; border-radius: var(--r-xs); }
.import-dpair--pick:hover { background: var(--c-3); }
.import-dlabel {
  min-width: 92px;
  color: var(--c-8);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.import-dold, .import-dnew {
  padding: 1px 6px;
  border-radius: var(--r-xs);
  border: 1px solid transparent;
  color: var(--c-7);
}
.import-darrow { color: var(--c-7); }
.import-dside--on { color: var(--c-12); background: var(--c-4); border-color: var(--c-6); }
.import-dnew.import-dside--on { border-color: var(--c-7); }
.import-dsame { color: var(--c-7); font-style: italic; }
.import-dnote { color: var(--c-9); font-size: 11.5px; padding-bottom: 2px; }

.import-badge--same { background: var(--c-2); color: var(--c-8); border: 1px solid var(--c-3); }

.import-dlinked { color: var(--c-10); }
.import-dnewtag {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--c-8);
}
.import-dbtn {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-9);
  border-radius: var(--r-xs);
  cursor: pointer;
  font-size: 11px;
  padding: 1px 6px;
  margin-left: 4px;
}
.import-dbtn:hover { background: var(--c-4); color: var(--c-12); }
.import-dbtn--link { border-color: var(--warn-dim); color: var(--warn); margin-left: 0; margin-top: 3px; }

.import-conn { font-size: 11px; display: inline-block; margin-top: 2px; }
.import-conn--ok      { color: var(--c-7); }
.import-conn--warn    { color: var(--warn); font-weight: 600; }
.import-conn--pending { color: var(--accent-text); font-weight: 600; }
.import-drow--loose.import-drow--approved > td { box-shadow: inset 3px 0 0 -1px var(--warn-dim); }

.import-dstatus {
  background: var(--c-3);
  border: 1px solid var(--c-4);
  color: var(--c-9);
  border-radius: var(--r-xs);
  cursor: pointer;
  font-size: 12px;
  padding: 2px 7px;
}
.import-dstatus:hover { background: var(--c-4); color: var(--c-12); }
.import-dstatus.import-btn--active { background: var(--c-5); border-color: var(--c-7); color: var(--c-12); }

.import-drow-details > td { padding: 0 8px 10px 34px; background: var(--c-1); border-bottom: 1px solid var(--c-3); }
.import-drow-details .import-action-card { flex-shrink: 1; }

.import-same-body { padding: 10px 12px; font-size: 12.5px; color: var(--c-9); }
.import-match-hint { color: var(--warn); font-size: 12px; padding-top: 6px; }

/* Six columns do not fit a phone; let the table scroll sideways rather than
   squeezing the diff into something unreadable. */
@media (max-width: 768px) {
  #import-actions-list { overflow-x: auto; }
  .import-diff-table   { min-width: 620px; }
  .import-dlabel       { min-width: 70px; }
  .import-dcell-diff   { width: auto; }
}

/* Action cards */
.import-action-card {
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  background: var(--c-2);
  overflow: hidden;
  transition: border-color 0.15s;
  flex-shrink: 0;
}
.import-action-card--approved { border-color: var(--c-6); background: var(--c-2); }
.import-action-card--skipped  { border-color: var(--c-4); background: var(--c-1); opacity: 0.6; }

.import-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 12px;
  border-bottom: 1px solid var(--c-4);
  background: var(--c-2);
}
.import-action-card--approved .import-card-header { background: var(--c-2); border-color: var(--c-6); }
.import-action-card--skipped  .import-card-header { background: var(--c-1); border-color: var(--c-4); }

.import-badge {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 2px 8px;
  border-radius: var(--r-xs);
  text-transform: uppercase;
}
.import-badge--person   { background: var(--c-3); color: var(--c-9); border: 1px solid var(--c-5); }
.import-badge--marriage { background: var(--c-2); color: var(--c-9); border: 1px solid var(--c-4); }
.import-badge--update   { background: var(--c-3); color: var(--c-10); border: 1px solid var(--c-5); }

.import-status {
  font-size: 11.5px;
  font-weight: 600;
}
.import-status--pending  { color: var(--c-9); }
.import-status--approved { color: var(--c-8); }
.import-status--skipped  { color: var(--c-9); }

/* Fields grid */
.import-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 6px 12px;
  padding: 10px 12px 8px;
}
.import-field-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.import-field-label {
  font-size: 10.5px;
  color: var(--c-8);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.import-field-input {
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-12);
  font-size: 12.5px;
  padding: 4px 7px;
  width: 100%;
  box-sizing: border-box;
}
.import-field-input:focus { outline: none; border-color: var(--c-7); background: var(--c-2); }
.import-field-input::placeholder { color: var(--c-7); font-style: italic; }

/* Children field spans full width */
.import-field-row--wide {
  grid-column: 1 / -1;
}

/* Source details */
.import-source-details {
  margin: 0 12px 6px;
}
.import-source-details summary {
  font-size: 11px;
  color: var(--c-6);
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
}
.import-source-details summary:hover { color: var(--c-7); }
.import-source-text {
  font-size: 11px;
  color: var(--c-6);
  font-family: 'Consolas', 'Courier New', monospace;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--c-1);
  border-radius: var(--r-sm);
  padding: 6px 8px;
  margin-top: 4px;
  max-height: 100px;
  overflow-y: auto;
}

/* Card action buttons */
.import-card-actions {
  display: flex;
  gap: 6px;
  padding: 0 12px 10px;
}
.import-btn {
  padding: 4px 12px;
  border-radius: var(--r-sm);
  font-size: 12px;
  cursor: pointer;
  border: 1px solid transparent;
  font-weight: 500;
}
.import-btn--approve {
  background: var(--c-4);
  border-color: var(--c-6);
  color: var(--c-10);
}
.import-btn--approve:hover,
.import-btn--approve.import-btn--active {
  background: var(--c-5);
  border-color: var(--c-7);
  color: var(--c-11);
}
.import-btn--skip {
  background: var(--c-3);
  border-color: var(--c-5);
  color: var(--c-9);
}
.import-btn--skip:hover,
.import-btn--skip.import-btn--active {
  background: var(--c-4);
  border-color: var(--c-6);
  color: var(--c-10);
}

/* Apply result alert styling via confirm dialog */
#import-apply-result {
  padding: 10px 12px;
  background: var(--c-2);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  color: var(--c-10);
  font-size: 13px;
  margin-top: 4px;
}

/* ── Inline GEDCOM search on import cards ─────────────────────────── */
.import-inline-match {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 8px;
  border-top: 1px solid var(--c-3);
  flex-wrap: wrap;
}
/* Linked state */
.import-linked-label {
  font-size: 11px;
  color: var(--c-8);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
  white-space: nowrap;
}
.import-linked-name {
  font-size: 12.5px;
  color: var(--c-10);
  font-weight: 600;
}
.import-linked-year {
  color: var(--c-8);
  font-weight: 400;
}
.import-btn-unlink {
  background: none;
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  color: var(--c-7);
  font-size: 11px;
  padding: 2px 8px;
  cursor: pointer;
  margin-left: auto;
}
.import-btn-unlink:hover { background: var(--c-2); color: var(--c-9); border-color: var(--c-4); }
/* Person-field autocomplete wrapper (Name, Father, Mother, Husband, Wife, Children) */
.import-name-ac-wrap {
  position: relative;
  flex: 1;
}
.import-name-drop {
  display: none;
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-top: none;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  z-index: 200;
  max-height: 220px;
  overflow-y: auto;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
}
.import-sdrop-maiden {
  font-size: 11px;
  color: var(--c-9);
  font-weight: 400;
  margin-left: 4px;
}
.import-sdrop-item--pending .import-sdrop-name { color: var(--c-9); }
.import-sdrop-item--pending .import-sdrop-detail { color: var(--c-7); }

/* Linked person badge (shown when a field is linked to a GEDCOM/import person) */
.import-field-linked {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  background: var(--c-2);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 4px 8px;
  flex: 1;
}
/* ── Import: a field the two sources disagree about ── */
.import-conflict {
  display: flex;
  gap: 4px;
  flex: 1;
  cursor: pointer;
}
.import-conflict-side {
  flex: 1;
  min-width: 0;
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 3px 7px;
  opacity: 0.5;
  transition: opacity .12s, border-color .12s;
}
.import-conflict-side--on {
  opacity: 1;
  border-color: var(--accent);
  background: var(--accent-soft);
}
.import-conflict-tag {
  display: block;
  font-size: 9.5px;
  color: var(--c-8);
  letter-spacing: .02em;
}
.import-conflict-side--on .import-conflict-tag { color: var(--accent-text); }
.import-conflict-val {
  display: block;
  font-size: 12.5px;
  color: var(--c-12);
  overflow-wrap: anywhere;
}
/* A field only the tree answers: shown so the card is complete, but there is
   nothing to decide, so it stays quiet. */
.import-field-kept {
  flex: 1;
  background: var(--c-2);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  padding: 4px 8px;
  font-size: 12.5px;
  color: var(--c-9);
}
.import-field-kept-tag { font-size: 9.5px; color: var(--c-7); margin-left: 6px; }

.import-field-linked-name {
  font-size: 12.5px;
  color: var(--c-10);
  font-weight: 600;
}
.import-linked-year {
  font-size: 11.5px;
  color: var(--c-8);
}
.import-linked-tag {
  font-size: 10px;
  color: var(--c-9);
  background: var(--c-3);
  border: 1px solid var(--c-5);
  border-radius: var(--r-xs);
  padding: 1px 5px;
}
.import-field-unlink-btn {
  margin-left: auto;
  background: none;
  border: 1px solid var(--c-4);
  border-radius: var(--r-xs);
  color: var(--c-7);
  font-size: 11px;
  padding: 1px 6px;
  cursor: pointer;
  line-height: 1.4;
}
.import-field-unlink-btn:hover { background: var(--c-2); color: var(--c-9); border-color: var(--c-4); }
.import-field-change-btn {
  margin-left: auto;
  background: none;
  border: 1px solid var(--c-5);
  border-radius: var(--r-xs);
  color: var(--c-9);
  font-size: 11px;
  padding: 1px 6px;
  cursor: pointer;
  line-height: 1.4;
}
.import-field-change-btn + .import-field-unlink-btn { margin-left: 0; }
.import-field-change-btn:hover { background: var(--c-3); color: var(--c-11); border-color: var(--c-7); }

.import-btn-change {
  margin-left: auto;
  background: var(--c-3);
  border: 1px solid var(--c-5);
  border-radius: var(--r-xs);
  color: var(--c-10);
  font-size: 11px;
  padding: 2px 8px;
  cursor: pointer;
}
.import-btn-change:hover { background: var(--c-4); color: var(--c-11); }
.import-btn-change + .import-btn-unlink { margin-left: 0; }

/* Rich hover tooltip for linked person badges */
.import-field-linked { position: relative; }
.import-linked-tip {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  z-index: 50;
  min-width: 240px;
  max-width: 360px;
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.6);
  font-size: 11.5px;
  color: var(--c-11);
  line-height: 1.5;
  display: none;
  pointer-events: none;
}
.import-field-linked:hover .import-linked-tip,
.import-field-linked:focus-within .import-linked-tip { display: block; }
.import-tt-name { font-weight: 600; color: var(--c-12); font-size: 12.5px; }
.import-tt-sub  { color: var(--c-8); font-size: 11px; margin-bottom: 4px; }
.import-tt-line { color: var(--c-10); }
.import-tt-line b { color: var(--c-9); font-weight: 500; }
.import-tt-note { color: var(--c-9); font-style: italic; margin-top: 4px; border-top: 1px solid var(--c-4); padding-top: 4px; }
.import-tt-id   { color: var(--c-6); font-size: 10px; margin-top: 4px; font-family: monospace; }

.import-btn--link {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-10);
}
.import-btn--link:hover { background: var(--c-5); color: var(--c-12); }

/* Children rows */
.import-child-row {
  align-items: center;
}
.import-child-rm-btn {
  background: none;
  border: 1px solid var(--c-4);
  border-radius: var(--r-xs);
  color: var(--c-7);
  font-size: 11px;
  padding: 2px 6px;
  cursor: pointer;
  flex-shrink: 0;
  margin-left: 4px;
}
.import-child-rm-btn:hover { background: var(--c-2); color: var(--c-9); }
.import-child-add-btn {
  background: none;
  border: 1px dashed var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-8);
  font-size: 12px;
  padding: 3px 10px;
  cursor: pointer;
}
.import-child-add-btn:hover { background: var(--c-2); color: var(--c-10); }

/* Search input */
.import-search-wrap { flex: 1; min-width: 200px; }
.import-search-inline {
  width: 100%;
  background: var(--c-1);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  color: var(--c-11);
  font-size: 12.5px;
  padding: 5px 9px;
  outline: none;
}
.import-search-inline:focus { border-color: var(--c-6); }
.import-search-inline::placeholder { color: var(--c-6); }
/* Dropdown */
.import-search-drop {
  display: none;
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-top: none;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  z-index: 200;
  max-height: 220px;
  overflow-y: auto;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
}
.import-sdrop-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 10px;
  cursor: pointer;
  border-bottom: 1px solid var(--c-3);
}
.import-sdrop-item:last-child { border-bottom: none; }
.import-sdrop-item:hover { background: var(--c-4); }
.import-sdrop-name {
  font-size: 12.5px;
  color: var(--c-12);
  font-weight: 500;
}
.import-sdrop-detail {
  font-size: 11.5px;
  color: var(--c-8);
  white-space: nowrap;
}

/* Match Selection Dialog */
#import-match-dialog {
  position: fixed;
  inset: 0;
  z-index: 1300;
  display: flex;
  align-items: center;
  justify-content: center;
}
#import-match-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
}
#import-match-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: 90%;
  max-width: 600px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 12px 50px rgba(0, 0, 0, 0.8);
}
#import-match-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  background: var(--c-2);
  border-bottom: 1px solid var(--c-4);
  flex-shrink: 0;
}
#import-match-header h3 {
  margin: 0;
  font-size: 15px;
  color: var(--c-12);
}
#import-match-close {
  background: transparent;
  border: none;
  color: var(--c-8);
  font-size: 18px;
  cursor: pointer;
  padding: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
}
#import-match-close:hover {
  background: var(--c-4);
  color: var(--c-10);
}
#import-match-current {
  padding: 12px 18px;
  background: var(--c-2);
  border-bottom: 1px solid var(--c-4);
}
.import-match-section-title {
  font-size: 11px;
  color: var(--c-8);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: 6px;
}
#import-match-current-content {
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 10px 14px;
}
.import-match-person {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.import-match-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--c-12);
}
.import-match-details {
  font-size: 12px;
  color: var(--c-8);
}
#import-match-search {
  padding: 12px 18px;
  border-bottom: 1px solid var(--c-4);
}
#import-match-search-input {
  width: 100%;
  padding: 8px 12px;
  background: var(--c-2);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  color: var(--c-12);
  font-size: 13px;
  outline: none;
}
#import-match-search-input:focus {
  border-color: var(--c-6);
}
#import-match-candidates {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 18px;
}
#import-match-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.import-match-empty {
  text-align: center;
  color: var(--c-7);
  font-size: 13px;
  padding: 20px;
}
.import-match-candidate {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--c-2);
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: all 0.15s;
}
.import-match-candidate:hover {
  background: var(--c-2);
  border-color: var(--c-6);
}
.import-match-candidate-type {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: var(--r-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  flex-shrink: 0;
}
.import-match-candidate-type.type-existing {
  background: var(--c-4);
  color: var(--c-10);
}
.import-match-candidate-type.type-pending {
  background: var(--c-4);
  color: var(--c-10);
}
.import-match-candidate-info {
  flex: 1;
  min-width: 0;
}
.import-match-candidate-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--c-12);
  margin-bottom: 2px;
}
.import-match-candidate-details {
  font-size: 11px;
  color: var(--c-8);
}
.import-match-candidate-score {
  font-size: 11px;
  color: var(--c-9);
  background: var(--c-2);
  padding: 2px 6px;
  border-radius: var(--r-xs);
  flex-shrink: 0;
}
#import-match-actions {
  padding: 12px 18px;
  background: var(--c-2);
  border-top: 1px solid var(--c-4);
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  flex-shrink: 0;
}

/* ── Autocomplete dropdown ───────────────────────────────────── */
#ac-dropdown {
  position: fixed;
  background: var(--c-2);
  border: 1px solid var(--c-6);
  border-radius: var(--r-sm);
  max-height: 200px;
  overflow-y: auto;
  z-index: 99999;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.6);
  display: none;
}
.ac-item {
  padding: 7px 12px;
  font-size: 13px;
  color: var(--c-12);
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ac-item:hover,
.ac-item.ac-active {
  background: var(--c-4);
  color: var(--c-13);
}

/* ── Statistics window ── */
#stats-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#stats-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.65); }
#stats-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(760px, 94vw);
  height: min(88vh, 900px);
  display: flex;
  flex-direction: column;
  padding: 0 18px 16px;
  overflow: hidden;
  box-shadow: var(--sh-3);
}
/* The figures were written for a 220px sidebar; with the room a window gives,
   two columns keep the whole report readable instead of one long scroll.
   A CSS grid, not `columns:` — a multi-column layout balances its column
   heights *before* it knows the box will scroll, and a `column-span: all`
   element (the tiles row, the sex bar, the timeline) in the middle of that
   is exactly the combination that miscalculates the balance: everything
   below the span used to come out squeezed into far less height than its
   own content needed. Grid just flows each row at its natural height. */
#stats-body {
  flex: 1;
  min-height: 0;
  padding: 10px 4px 6px 0;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 16px;
  align-content: start;
}
@media (max-width: 620px) {
  #stats-body { grid-template-columns: 1fr; }
}

/* Headline numbers, read before any of the detail — the four figures anyone
   opening the window is really here for. */
.stat-tiles {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 4px;
}
.stat-tile {
  background: var(--c-2);
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  padding: 10px 8px;
  text-align: center;
}
.stat-tile-value {
  font-size: 20px;
  font-weight: 600;
  color: var(--c-13);
  font-variant-numeric: proportional-nums;
  line-height: 1.15;
}
.stat-tile-label {
  font-size: 10px;
  color: var(--c-8);
  margin-top: 2px;
}
@media (max-width: 480px) {
  .stat-tiles { grid-template-columns: repeat(2, 1fr); }
}

/* Sex split as one bar, so the shape of the tree reads before the numbers do. */
.stat-bar {
  grid-column: 1 / -1;
  display: flex;
  height: 6px;
  border-radius: var(--r-xs);
  overflow: hidden;
  margin: 2px 0 12px;
}
.stat-seg-M { background: #4a90d9; }
.stat-seg-F { background: #e0608a; }
.stat-seg-U { background: #7e8fa8; }
.stat-bar span { cursor: pointer; }
.stat-bar span:hover { filter: brightness(1.25); }

/* One card per topic, instead of a running list broken up by rules — the
   grouping is what makes a two-column report scannable rather than a wall of
   rows to hunt through. */
.stat-card {
  background: var(--c-2);
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  padding: 8px 10px 4px;
  margin: 0 0 10px;
}
.stat-card-title {
  font-size: 11px;
  font-weight: 600;
  color: var(--c-11);
  margin-bottom: 2px;
}

.stat-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  font-size: 11px;
  padding: 4px 2px;
  margin: 0 -2px;
  border-radius: var(--r-xs);
  color: var(--c-9);
}
/* A row that opens the people behind it reads as a button, not as one more
   line of text — the whole point of making the figures clickable is lost if
   nothing on screen says which ones are. */
.stat-row--clickable { cursor: pointer; }
.stat-row--clickable:hover, .stat-row--clickable:focus-visible {
  background: var(--c-4);
  color: var(--c-12);
  outline: none;
}
.stat-row--clickable:hover .stat-label,
.stat-row--clickable:focus-visible .stat-label { color: var(--c-12); }
.stat-label { flex: 1; min-width: 0; }
.stat-value {
  color: var(--c-11);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}
/* The qualifier that keeps a figure honest — the subset an average rests on,
   who the record belongs to — set quietly under the number it belongs to. */
.stat-hint {
  display: block;
  font-size: 10px;
  color: var(--c-7);
  font-weight: normal;
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.stat-group-title, .stat-group .stat-group-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-7);
  margin: 6px 0 2px;
}
.stat-list { list-style: none; margin: 0; padding: 0; }
.stat-list li {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  padding: 3px 4px;
  margin: 0 -4px;
  border-radius: var(--r-xs);
  color: var(--c-9);
}
.stat-list li.stat-row--clickable:hover,
.stat-list li.stat-row--clickable:focus-visible { background: var(--c-3); }
.stat-list li span:first-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The count is the point of the row, so a long name has to eat into its own
   ellipsis rather than push the number off the edge. `.stat-hint` carries
   `overflow: hidden`, which lets a flex item shrink below its content width —
   the ranks past fifth are exactly where the long place names live, so this
   showed up the moment the lists went to ten. */
.stat-list li .stat-hint { flex: none; max-width: none; }
.stat-empty { font-size: 11px; color: var(--c-7); padding: 6px 0; }

/* Births-per-decade column chart. One series, so one flat colour per column —
   height alone carries the magnitude, nothing is shaded by it — and no
   legend box (the group title already says what is plotted). Spans both
   #stats-body columns: a timeline squeezed into 240px is unreadable. */
.stat-timeline { grid-column: 1 / -1; }
.stat-timeline-chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 64px;
  padding-bottom: 16px;
  overflow-x: auto;
}
.stat-timeline-bar {
  position: relative;
  flex: 1 0 6px;
  min-width: 6px;
  max-width: 22px;
  min-height: 2px;
  background: var(--accent);
  border-radius: 3px 3px 0 0;
  cursor: pointer;
  transition: filter 0.1s ease;
}
.stat-timeline-bar:hover { filter: brightness(1.3); }
.stat-timeline-bar--empty { cursor: default; }
.stat-timeline-bar--empty:hover { filter: none; }
.stat-timeline-label {
  position: absolute;
  bottom: -15px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 9px;
  color: var(--c-7);
  white-space: nowrap;
}

/* ── Stat detail list — the people behind one figure ──
   Replaces #stats-body in place, same modal, same close/back affordance as
   the rest of the app's drill-down panels. */
#stats-detail {
  display: none;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  padding-top: 8px;
}
#stats-detail-header {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-shrink: 0;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--c-4);
  margin-bottom: 8px;
}
#stats-detail-back {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-10);
  border-radius: var(--r-sm);
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  cursor: pointer;
  font-size: 13px;
}
#stats-detail-back:hover { background: var(--c-5); color: var(--c-12); }
#stats-detail-title { font-size: 13px; font-weight: 600; color: var(--c-12); flex: 1; min-width: 0; }
#stats-detail-count { font-size: 11px; color: var(--c-8); flex-shrink: 0; }
#stats-detail-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  background: var(--c-2);
  padding: 6px;
}

/* ══════════════════════════════════════
   PLACE-NAME CLEANUP DIALOG
══════════════════════════════════════ */
#places-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#places-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
}
#places-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(620px, 94vw);
  height: min(88vh, 900px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0 18px 16px;
  overflow: hidden;
  box-shadow: var(--sh-3);
}
#places-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0 10px;
  border-bottom: 1px solid var(--c-4);
  flex-shrink: 0;
}
#places-header h2 { margin: 0; font-size: 17px; font-weight: 600; color: var(--c-12); }
#places-close-btn, .modal-close-btn {
  background: none;
  border: none;
  color: var(--c-8);
  font-size: 18px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  line-height: 1;
}
#places-close-btn:hover, .modal-close-btn:hover { color: var(--c-12); background: var(--c-4); }

.pl-hint { margin: 0; font-size: 12.5px; color: var(--c-8); line-height: 1.5; flex-shrink: 0; }
#places-summary {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-8);
  flex-shrink: 0;
}
#places-bulk { display: flex; gap: 6px; flex-shrink: 0; }
.pl-bulk-btn {
  background: var(--c-3);
  color: var(--c-10);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  padding: 4px 10px;
  font-size: 12px;
  cursor: pointer;
}
.pl-bulk-btn:hover { background: var(--c-5); color: var(--c-12); }

/* The one scrolling part of the dialog: everything above and below it stays
   put no matter how many groups a file turns up. */
#places-groups {
  /* Takes what its groups need and no more — a file with two groups should
     spend the rest of the dialog on the place list, not on empty space. */
  flex: 0 1 auto;
  min-height: 110px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-right: 4px;
}
.pl-empty { font-size: 13px; color: var(--c-8); padding: 18px 2px; }

.pl-group {
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  background: var(--c-2);
  padding: 10px;
}
.pl-group-head { display: flex; align-items: center; gap: 8px; }
.pl-canon { flex: 1; min-width: 0; font-weight: 600; }
.pl-total {
  font-size: 11px;
  color: var(--c-8);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.pl-variants { display: flex; flex-direction: column; gap: 1px; margin-top: 8px; }
.pl-variant {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--c-10);
  padding: 4px 6px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.pl-variant:hover { background: var(--c-3); }
.pl-variant input { accent-color: var(--accent); cursor: pointer; flex-shrink: 0; }
.pl-variant input:disabled { cursor: default; }
.pl-value { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-count { font-size: 11px; color: var(--c-8); font-variant-numeric: tabular-nums; }
.pl-tag {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--c-8);
  border: 1px solid var(--c-5);
  border-radius: 99px;
  padding: 1px 7px;
  flex-shrink: 0;
}
/* Matches joined by a typo or an extra qualifier, not just by case and
   punctuation — they start unticked, and the amber says why. */
.pl-tag--loose { color: var(--warn); border-color: var(--warn-dim); }
.pl-variant--loose .pl-value { color: var(--c-9); }

#places-tidy-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--c-10);
  cursor: pointer;
  flex-shrink: 0;
  padding-top: 8px;
  border-top: 1px solid var(--c-4);
}
#places-tidy-row input { accent-color: var(--accent); cursor: pointer; }

/* Hand-merging: the list of places the heuristics left alone, and the controls
   for putting some of them together anyway. */
#places-bulk { align-items: center; }
#places-filter {
  flex: 1;
  min-width: 0;
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-12);
  border-radius: var(--r-sm);
  padding: 4px 9px;
  font-size: 12px;
}
#places-filter::placeholder { color: var(--c-8); }
#places-filter:focus { outline: none; border-color: var(--accent); }

.pl-others-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--c-4);
}
.pl-others-title {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-8);
}
/* The two lists each get their own scroll area and a floor they cannot be
   squeezed below. Nested inside the group list, this one collapsed to a few
   rows on exactly the trees that need it. */
#places-all-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex: 1 1 auto;
  min-height: 240px;
}
#places-all {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  background: var(--c-2);
  padding: 6px;
}
/* Which group this place already belongs to — merging it takes the group. */
.pl-in-group {
  font-size: 10px;
  color: var(--c-9);
  background: var(--c-4);
  border-radius: 99px;
  padding: 1px 8px;
  max-width: 40%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}
.pl-merge-row { display: flex; gap: 6px; align-items: center; }
.pl-merge-row .sidebar-select { flex: 1; min-width: 0; }
.pl-merge-row .pl-bulk-btn { flex-shrink: 0; }
/* A grouping the user made themselves, rather than one that was proposed. */
.pl-tag--forced { color: var(--accent-text); border-color: var(--accent-solid); }

/* ══════════════════════════════════════
   FIND PEOPLE
══════════════════════════════════════ */
#find-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#find-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
}
#find-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(660px, 94vw);
  /* Grows with the results instead of standing at full height over a single
     hit, and stops before it runs off the screen. */
  max-height: min(88vh, 900px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0 18px 16px;
  overflow: hidden;
  box-shadow: var(--sh-3);
}
#find-close-btn {
  background: none;
  border: none;
  color: var(--c-8);
  font-size: 18px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  line-height: 1;
}
#find-close-btn:hover { color: var(--c-12); background: var(--c-4); }

/* Two columns of criteria; the free-text ones get the full width because a
   place like "Luterbach, Solothurn" needs the room to be read back. */
#find-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 10px;
  flex-shrink: 0;
}
.find-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.find-field--wide { grid-column: 1 / -1; }
.find-field > span {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-8);
}
.find-field input[type="text"],
.find-field input[type="number"] {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-12);
  border-radius: var(--r-sm);
  padding: 6px 9px;
  font-size: 13px;
  min-width: 0;
}
.find-field input::placeholder { color: var(--c-8); }
.find-field input:focus { outline: none; border-color: var(--accent); }
.find-range { display: flex; gap: 6px; }
.find-range input { flex: 1; min-width: 0; }

#find-count {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-8);
  flex-shrink: 0;
  padding-top: 8px;
  border-top: 1px solid var(--c-4);
}
#find-results {
  flex: 1;
  min-height: 120px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  border: 1px solid var(--c-4);
  border-radius: var(--r-md);
  background: var(--c-2);
  padding: 6px;
}
.find-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--c-11);
  font-size: 13px;
  padding: 6px 8px;
  border-radius: var(--r-sm);
  cursor: pointer;
}
.find-row:hover { background: var(--c-4); color: var(--c-12); }
.find-row-name { flex-shrink: 0; }
.find-row-years {
  font-size: 11px;
  color: var(--c-9);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.find-row-place {
  font-size: 11px;
  color: var(--c-8);
  margin-left: auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Map ──────────────────────────────────────────────────────────────────
   Nearly full-screen: a map that is not big enough to pan around in is a
   picture, and the whole point of this one is that it can be explored. */
#map-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#map-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.65); }
#map-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(1240px, 96vw);
  height: min(92vh, 940px);
  display: flex;
  flex-direction: column;
  padding: 0 18px 14px;
  overflow: hidden;
  box-shadow: var(--sh-3);
}
#map-body {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 12px;
  padding: 10px 0;
}
#map-canvas {
  position: relative;
  flex: 1;
  min-width: 0;
  border: 1px solid var(--c-5);
  border-radius: var(--r-md);
  overflow: hidden;
  /* Shows through wherever tiles have not loaded — offline, or over the sea. */
  background: var(--c-0);
}
#map-svg { width: 100%; height: 100%; display: block; cursor: grab; }
#map-svg:active { cursor: grabbing; }
/* Attribution is a condition of using the tiles, so it is not optional chrome. */
#map-attrib {
  position: absolute;
  right: 0;
  bottom: 0;
  font-size: 10px;
  padding: 2px 6px;
  color: var(--c-10);
  background: rgba(7, 9, 12, 0.72);
  border-top-left-radius: var(--r-xs);
}
#map-attrib a { color: var(--accent-text); }

.map-dot {
  fill: var(--accent);   /* fallback only — renderMap() sets the real fill inline from state.mapDotColor */
  fill-opacity: 0.8;
  stroke: #0a0a0a;
  stroke-width: 1.5;
  stroke-opacity: 0.85;
  cursor: pointer;
}
.map-dot:hover { fill-opacity: 1; stroke: #fff; }
.map-dot--sel { fill: var(--warn-bright); fill-opacity: 0.95; stroke: #0a0a0a; stroke-width: 2; }

#map-side {
  width: 260px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
}
#map-summary {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-8);
  line-height: 1.5;
}
#map-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.map-list-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-12);
  padding: 4px 2px;
  position: sticky;
  top: 0;
  background: var(--c-1);
}
.map-back {
  background: none;
  border: none;
  color: var(--accent-text);
  font-size: 12px;
  text-align: left;
  padding: 2px;
  cursor: pointer;
}
.map-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  background: none;
  border: none;
  border-radius: var(--r-xs);
  color: var(--c-11);
  font-size: 12px;
  text-align: left;
  padding: 4px 6px;
  cursor: pointer;
}
.map-row:hover { background: var(--c-3); color: var(--c-13); }
/* A place with no coordinates is still in the list — it is how you find out
   which ones the lookup has not reached. */
.map-row--unlocated { color: var(--c-8); font-style: italic; }
.map-row-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.map-row-year { color: var(--c-8); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.map-row-type { font-size: 10px; color: var(--c-9); flex-shrink: 0; }
.map-row-type--birth { color: #6fbf73; }
.map-row-type--death { color: var(--c-9); }
.map-row-type--marriage { color: #b07cd6; }

#map-status { font-size: 11px; color: var(--c-9); min-height: 14px; line-height: 1.4; }

#map-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  border-top: 1px solid var(--c-4);
  padding-top: 10px;
  flex-wrap: wrap;
}
#map-play-btn {
  background: var(--c-3);
  color: var(--c-11);
  border: 1px solid var(--c-5);
  border-radius: var(--r-sm);
  width: 32px;
  height: 30px;
  font-size: 13px;
  cursor: pointer;
}
#map-play-btn:hover { background: var(--c-5); color: var(--c-13); }
/* Two sliders stacked rather than side by side: they share one scale, and a
   split scale makes "1820–1890" impossible to read off at a glance. */
#map-years { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 2px; }
#map-years input[type=range] { width: 100%; }
#map-year-label {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  color: var(--c-12);
  min-width: 108px;
  text-align: center;
}
#map-dot-color-row { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
#map-dot-color-row input[type=color] { width: 28px; height: 28px; padding: 0; border: 1px solid var(--c-5); border-radius: var(--r-xs); cursor: pointer; background: none; }
#map-dot-color-reset {
  background: var(--c-3);
  border: 1px solid var(--c-5);
  color: var(--c-9);
  border-radius: var(--r-xs);
  width: 28px;
  height: 28px;
  cursor: pointer;
  font-size: 13px;
}
#map-dot-color-reset:hover { background: var(--c-5); color: var(--c-11); }
#map-types { display: flex; gap: 12px; flex-wrap: wrap; }
#map-types label {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--c-10);
  cursor: pointer;
}

@media (max-width: 820px) {
  #map-body { flex-direction: column; }
  #map-side { width: auto; max-height: 34%; }
  #map-canvas { min-height: 240px; }
}

/* A place whose coordinates are not in the records yet: the tick is the
   approval, so it sits outside the row button rather than inside it. */
.map-row-wrap { display: flex; align-items: center; gap: 6px; }
.map-row-wrap .map-row { flex: 1; min-width: 0; }
.map-tick { flex-shrink: 0; cursor: pointer; }
.pl-bulk-btn--primary {
  background: var(--accent-solid);
  border-color: var(--accent-solid-border);
  color: var(--c-13);
}
.pl-bulk-btn--primary:hover { background: var(--accent-solid-hover); color: var(--c-13); }

/* Correcting one place's coordinates, inside its own event list. */
.map-fix {
  border: 1px solid var(--c-4);
  border-radius: var(--r-sm);
  padding: 8px;
  margin: 4px 0 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--c-2);
}
.map-fix-here { display: flex; align-items: baseline; gap: 8px; }
.map-coord { font-size: 11.5px; font-variant-numeric: tabular-nums; color: var(--c-11); }
.map-coord--none { color: var(--c-8); font-style: italic; }
.map-fix-clear {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--c-9);
  font-size: 11px;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
}
.map-fix-clear:hover { color: var(--warn-bright); }
.map-fix-row { display: flex; gap: 6px; }
.map-fix-row .edit-input { flex: 1; min-width: 0; }
.map-fix-hint { margin: 0; font-size: 11px; color: var(--c-8); line-height: 1.45; }
.map-fix-note { font-size: 11.5px; color: var(--c-9); padding: 2px 0; }
.map-fix-note--err { color: var(--warn-bright); }
/* Candidates wrap rather than ellipsise: a Nominatim display_name is the whole
   administrative chain, and the tail is exactly what tells two apart. */
.map-cand {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  text-align: left;
  background: var(--c-1);
  border: 1px solid var(--c-4);
  border-radius: var(--r-xs);
  color: var(--c-11);
  font-size: 11.5px;
  line-height: 1.35;
  padding: 5px 7px;
  cursor: pointer;
}
.map-cand:hover { background: var(--c-3); border-color: var(--accent-solid-border); color: var(--c-13); }
.map-cand-ll { color: var(--c-8); font-variant-numeric: tabular-nums; font-size: 10.5px; }

/* ── Changes since the file was opened ── */
#changes-modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: center;
  justify-content: center;
}
#changes-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.65); }
#changes-panel {
  position: relative;
  background: var(--c-1);
  border: 1px solid var(--c-5);
  border-radius: var(--r-lg);
  width: min(680px, 94vw);
  height: min(88vh, 900px);
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 0 18px 16px;
  overflow: hidden;
  box-shadow: var(--sh-3);
}
#changes-summary {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--c-8);
  flex-shrink: 0;
}
#changes-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-right: 4px;
}
.ch-section-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--c-12);
  padding: 10px 2px 2px;
  position: sticky;
  top: 0;
  background: var(--c-1);
}
.ch-rec {
  border: 1px solid var(--c-4);
  border-left: 3px solid var(--c-6);
  border-radius: var(--r-sm);
  padding: 7px 9px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ch-rec--added   { border-left-color: #6fbf73; }
.ch-rec--removed { border-left-color: #d06a6a; }
.ch-rec--changed { border-left-color: var(--accent); }
.ch-rec-head { display: flex; align-items: baseline; gap: 8px; }
.ch-rec-name { font-size: 13px; color: var(--c-12); font-weight: 600; }
.ch-badge {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 999px;
  flex-shrink: 0;
}
.ch-badge--added   { background: #1d3a22; color: #8fd694; }
.ch-badge--removed { background: #3a1d1d; color: #e08d8d; }
.ch-badge--changed { background: var(--accent-soft); color: var(--accent-text); }
/* Old and new side by side. They wrap rather than truncate: a note is often the
   thing that changed, and an ellipsised note says nothing at all. */
.ch-field {
  display: grid;
  grid-template-columns: minmax(90px, 0.8fr) 1fr auto 1fr;
  gap: 8px;
  align-items: baseline;
  font-size: 12px;
  padding: 1px 0;
}
.ch-key { color: var(--c-9); }
.ch-val { overflow-wrap: anywhere; }
.ch-val--before { color: var(--c-9); text-decoration: line-through; text-decoration-color: var(--c-7); }
.ch-val--after  { color: var(--c-12); }
.ch-val--empty  { font-style: italic; color: var(--c-7); text-decoration: none; }
.ch-arrow { color: var(--c-7); }

@media (max-width: 620px) {
  .ch-field { grid-template-columns: 1fr; gap: 1px; }
  .ch-arrow { display: none; }
}
