/* family-tree v1 — single stylesheet, dark theme (Agentic Apples family), mobile-first */

:root {
  --bg: #0d1117;
  --bg-raised: #141a22;
  --panel: #1a212b;
  --panel-2: #1f2833;
  --border: #2d3644;
  --text: #e6edf3;
  --muted: #97a3b0;
  --accent: #d4a94e;          /* heritage gold */
  --accent-soft: rgba(212, 169, 78, .13);
  --grade-a: #3fb950;
  --grade-b: #d29922;
  --grade-c: #f85149;
  --link: #6cb6ff;
  --serif: Georgia, 'Iowan Old Style', 'Times New Roman', serif;
  --sans: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --nav-h: 52px;
  --shadow: 0 8px 28px rgba(0, 0, 0, .45);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  /* v14: sticky footer — the page is at least a full viewport tall and the
     footer is pushed to the bottom, so on short pages it never floats mid-screen
     right under the content (which read as "cramped"); on long pages the footer
     keeps a clear gap via its own padding + the content's bottom padding. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.25; }
img { max-width: 100%; }
button { font: inherit; }
mark { background: var(--accent-soft); color: var(--accent); border-radius: 3px; padding: 0 2px; }

/* ---------- nav ---------- */
.site-nav {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 4px;
  height: var(--nav-h);
  padding: 0 12px;
  background: rgba(13, 17, 23, .88);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
}
.site-nav::-webkit-scrollbar { display: none; }
.site-nav .brand {
  font-family: var(--serif);
  font-size: 17px;
  color: var(--accent);
  margin-right: 10px;
  display: flex; align-items: center; gap: 7px;
  flex: 0 0 auto;
  text-decoration: none;
}
.site-nav a.brand:hover { text-decoration: none; opacity: .85; }
.site-nav .brand svg { flex: 0 0 auto; }
.site-nav a.nav-link {
  color: var(--muted);
  padding: 5px 10px;
  border-radius: 7px;
  font-size: 14px;
  flex: 0 0 auto;
}
.site-nav a.nav-link:hover { color: var(--text); text-decoration: none; background: var(--bg-raised); }
.site-nav a.nav-link.active { color: var(--accent); background: var(--accent-soft); }
.site-nav .nav-version {
  flex: 0 0 auto;
  color: var(--muted); font-size: 11px; font-family: var(--sans);
  border: 1px solid var(--border); border-radius: 6px;
  padding: 0 6px; line-height: 16px;
}
/* Log out (v15) — pushed to the far right of the nav; on mobile the nav scrolls
   horizontally so it just sits last. Subtle danger tint on hover. */
.site-nav a.nav-logout { margin-left: auto; }
.site-nav a.nav-logout:hover { color: var(--grade-c); background: var(--bg-raised); }
/* "signed in as {name}" chip (v16) — sits at the right end of the nav, just left
   of the logout gap. Muted; the role is in its title tooltip. */
.site-nav .nav-user { flex: 0 0 auto; color: var(--muted); font-size: 12px; padding: 0 4px; opacity: .85; white-space: nowrap; }
/* The Agentic Apples badge is the real footer block; give it clear breathing
   room ABOVE it (v15 — was 10px, which read as butted against the grade line). */
.site-footer .footer-badge { display: block; margin-top: 30px; }

/* ---------- layout ---------- */
.container { max-width: 980px; margin: 0 auto; padding: 20px 16px 56px; }
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
}
.muted { color: var(--muted); }
.small { font-size: 13px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: var(--panel-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 13px;
  cursor: pointer;
  font-size: 14px;
  user-select: none;
}
.btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
.btn:disabled { opacity: .4; cursor: default; pointer-events: none; }
.btn.primary { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* ---------- grade badges ---------- */
.badge-grade {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px;
  padding: 0 6px;
  border-radius: 6px;
  font-size: 12px; font-weight: 700;
  letter-spacing: .02em;
}
.badge-grade.g-a { background: rgba(63, 185, 80, .15); color: var(--grade-a); border: 1px solid rgba(63, 185, 80, .4); }
.badge-grade.g-b { background: rgba(210, 153, 34, .15); color: var(--grade-b); border: 1px solid rgba(210, 153, 34, .4); }
.badge-grade.g-c { background: rgba(248, 81, 73, .13); color: var(--grade-c); border: 1px solid rgba(248, 81, 73, .4); }

/* ---------- home ---------- */
.hero { text-align: center; padding: 34px 8px 10px; }
.hero h1 { font-size: clamp(30px, 7vw, 44px); margin: 0 0 6px; color: var(--accent); }
.hero .sub { color: var(--muted); font-size: 15px; max-width: 560px; margin: 0 auto; }
.stats-row {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  margin: 26px 0;
}
.stat {
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 8px; text-align: center;
}
.stat .num { font-family: var(--serif); font-size: 26px; color: var(--accent); }
.stat .lbl { color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.quick-links { display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 26px; }
.quick-links a.card { display: block; color: var(--text); }
.quick-links a.card:hover { border-color: var(--accent); text-decoration: none; }
.quick-links h3 { margin: 0 0 4px; color: var(--accent); font-size: 17px; }
.quick-links p { margin: 0; color: var(--muted); font-size: 13.5px; }

/* ---------- search ---------- */
.search-box { position: relative; max-width: 560px; margin: 24px auto 0; }
.search-box input {
  width: 100%;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 13px 16px;
  font-size: 16px;
  outline: none;
}
.search-box input:focus { border-color: var(--accent); }
.search-meta { color: var(--muted); font-size: 13px; margin: 14px 2px 8px; }
.results { display: flex; flex-direction: column; gap: 8px; margin-top: 6px; }
.result-item {
  display: block;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 11px 13px;
  color: var(--text);
}
.result-item:hover { border-color: var(--accent); text-decoration: none; }
.result-item .r-title { display: flex; align-items: center; gap: 8px; font-weight: 600; }
.result-item .r-kind { font-size: 11.5px; color: var(--muted); border: 1px solid var(--border); border-radius: 5px; padding: 1px 6px; }
.result-item .r-snip { color: var(--muted); font-size: 13px; margin-top: 3px; overflow-wrap: break-word; }

/* ---------- chart ---------- */
.chart-wrap {
  position: relative;
  height: calc(100dvh - var(--nav-h));
  overflow: hidden;
  flex: 0 0 auto; /* v14: keep its exact height inside the flex-column body */
  display: flex; flex-direction: column; /* v12.1: Key bar on top, canvas below */
  background:
    radial-gradient(1200px 500px at 50% -100px, rgba(212, 169, 78, .05), transparent),
    var(--bg);
}
/* the chart canvas fills the space UNDER the legend bar (scoped to #chart-svg so
   the tiny legend swatch <svg>s keep their own size) */
#chart-svg { flex: 1 1 auto; min-height: 0; display: block; width: 100%; height: auto; touch-action: none; cursor: grab; }
#chart-svg.panning { cursor: grabbing; }

.n-box { fill: var(--panel); stroke: var(--border); stroke-width: 1.2; rx: 9; }
.n-g { cursor: pointer; }
/* v26: ANCESTORS of the selected person (their line UP) = violet tint. Placed
   before :hover/.selected/.focus-node so those win when they land on the same
   node (e.g. the focus person is also an ancestor of the tapped descendant). */
.n-g.ancestor-hl .n-box { fill: rgba(163, 113, 247, .18); stroke: rgba(163, 113, 247, .8); stroke-width: 2; }
/* v35 relationship modes — placed here (before hover/selected/focus) so those win
   on a shared node. FILTER (Mode 2) = teal; FINDER picks (Mode 1) = bright pink. */
.n-g.rel-hl .n-box { fill: rgba(45, 183, 170, .20); stroke: rgba(45, 183, 170, .9); stroke-width: 2; }
.n-g.finder-pick .n-box { fill: rgba(232, 121, 198, .28); stroke: rgba(232, 121, 198, .95); stroke-width: 2.6; }
.n-g:hover .n-box { stroke: var(--accent); }
.n-g.selected .n-box { stroke: var(--link); stroke-width: 2.5; } /* SELECTED (clicked) = blue */
.n-name { fill: var(--text); font-size: 12.5px; font-weight: 600; }
.n-dates { fill: var(--muted); font-size: 10.5px; }
.n-grade-a { fill: var(--grade-a); }
.n-grade-b { fill: var(--grade-b); }
.n-grade-c { fill: var(--grade-c); }
.n-book { fill: var(--accent); font-size: 9.5px; }
.edge { stroke: #3d4a5c; stroke-width: 1.4; fill: none; }
.edge-partner { stroke: #55647a; stroke-width: 1.6; }
/* ended unions render dashed (v17 adds 'separated'); active ones (married,
   unmarried, partners) stay solid. */
.edge-partner.divorced, .edge-partner.former-partners, .edge-partner.separated { stroke-dasharray: 5 4; }
.union-dot { fill: #55647a; }

.chart-controls {
  position: absolute; right: 12px; bottom: 14px; z-index: 10;
  display: flex; flex-direction: column; gap: 7px;
}
.chart-controls .btn { width: 40px; height: 40px; padding: 0; font-size: 17px; }
/* v12.1/v13: the Key + view controls sit in an in-flow bar at the TOP of the
   chart (not a floating overlay), so nothing here can EVER overlap chart
   nodes/edges in any state. Collapsible "Key" chip on the left; Home + view
   toggle on the right. */
.chart-topbar {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 8px;
  flex-wrap: wrap; /* v29: search sits between Key and the mode buttons; wraps on mobile */
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
/* v29: find-a-person search on the chart. The dropdown overlays the canvas
   (z-index above nodes/panel) and is anchored to the input, well within the
   chart-wrap bounds so overflow:hidden never clips it. */
.chart-search { position: relative; flex: 1 1 180px; max-width: 260px; padding: 6px 4px; }
.chart-search input {
  width: 100%; background: var(--bg-raised); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 5px 10px; font: inherit; font-size: 13px;
}
.chart-search input:focus { outline: none; border-color: var(--accent); }
.chart-search-results {
  position: absolute; top: 100%; left: 4px; right: 4px; margin-top: 3px; z-index: 40;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow); max-height: 264px; overflow-y: auto;
}
.csr-item {
  display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  background: none; border: 0; border-bottom: 1px solid var(--border); color: var(--text);
  padding: 7px 10px; cursor: pointer; font: inherit; font-size: 13px;
}
.csr-item:last-child { border-bottom: 0; }
.csr-item:hover, .csr-item.csr-active { background: var(--bg-raised); }
.csr-name { font-weight: 600; }
.csr-nee { font-style: italic; }
.csr-life { margin-left: auto; white-space: nowrap; }
.csr-empty { padding: 9px 11px; color: var(--muted); font-size: 12.5px; }
.chart-legend {
  flex: 1 1 auto; min-width: 0;
  font-size: 12px;
  color: var(--muted);
}
.chart-modes { flex: 0 0 auto; display: flex; gap: 6px; padding: 6px 10px; }
.chart-mode-btn {
  background: var(--bg-raised); border: 1px solid var(--border); color: var(--muted);
  border-radius: 8px; padding: 5px 11px; font-size: 12px; cursor: pointer; white-space: nowrap;
}
.chart-mode-btn:hover { border-color: var(--accent); color: var(--accent); }
/* v35 relationship-mode controls (finder button + filter select + result line) */
.chart-rel { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 6px 10px; }
#rel-finder.armed { background: var(--accent); color: var(--bg); border-color: var(--accent); }
.rel-filter-lbl { font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 5px; }
.rel-filter { background: var(--bg-raised); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 4px 6px; font-size: 12px; }
.rel-filter:disabled { opacity: .55; }
.rel-filter:focus { outline: none; border-color: var(--accent); }
.chart-rel-status { flex: 1 1 100%; padding: 4px 10px 2px; font-size: 12.5px; color: var(--text); }
.chart-rel-status strong { color: var(--accent); }
/* v37 (J): a finder RESULT is a card you read, not a passing status line — boxed,
   dismissible, one row per direction. Prompts ("tap the second person…") keep the
   plain line: only .has-result gets the card treatment. */
.chart-rel-status.has-result {
  position: relative; margin: 2px 8px 6px; padding: 8px 30px 8px 10px;
  background: var(--bg-raised); border: 1px solid var(--border); border-radius: 8px;
}
.rel-status-x {
  position: absolute; top: 2px; right: 4px;
  background: none; border: 0; color: var(--muted); font-size: 17px; line-height: 1;
  padding: 2px 5px; cursor: pointer;
}
.rel-status-x:hover { color: var(--text); }
.rr-line { padding: 2px 0; line-height: 1.5; }
.rr-line + .rr-line { border-top: 1px solid var(--border); margin-top: 3px; padding-top: 5px; }
.rr-rel { color: var(--accent); font-style: normal; font-weight: 700; }
.rr-life { color: var(--muted); font-size: 11px; }
/* FOCUS/ROOT (the person the chart is centered on) = gold: tinted fill, gold
   border, soft glow. Distinct from a SELECTED (clicked) node, which is blue.
   When a node is BOTH, gold wins so the root always reads as the root. */
.n-g.focus-node .n-box { stroke: var(--accent); stroke-width: 2.5; fill: var(--accent-soft); }
.n-g.focus-node.selected .n-box { stroke: var(--accent); }
.n-g.focus-node { filter: drop-shadow(0 0 3px rgba(212, 169, 78, .6)); }
/* on-node "◎ center here" control — hidden until you hover the node (desktop) or
   select it (touch); clicking it re-roots the chart on this person */
.n-center { opacity: 0; cursor: pointer; transition: opacity .12s; }
.n-g:hover .n-center, .n-g.selected .n-center { opacity: 1; }
.n-center .n-center-bg { fill: var(--bg-raised); stroke: var(--accent); stroke-width: 1.2; }
.n-center:hover .n-center-bg { fill: var(--accent); }
.n-center .n-center-ico { fill: var(--accent); font-size: 11px; pointer-events: none; }
.n-center:hover .n-center-ico { fill: #12161c; }
/* 🚩 research follow-up marker (admin-only) — pinned to the node's top-left
   corner, above the box, never covering the name. Decorative: no pointer events
   so it can't steal clicks from the node. */
.n-flag { pointer-events: none; }
.n-flag-ico { font-size: 15px; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .55)); }
/* v37: ★ home-person marker — the bottom-left corner mirrors the 🚩 top-left one,
   clear of the name (y 19) and dates (y 35). Decorative, so no pointer events. */
.n-home { pointer-events: none; }
.n-home-ico { fill: var(--accent); font-size: 13px; filter: drop-shadow(0 1px 1px rgba(0, 0, 0, .55)); }
/* panel: the re-root actions get a little separation */
.detail-panel .dp-focus { margin: 6px 0 10px; align-items: center; }
/* v37 (K): home set-state — a badge (not a button) when this person already IS
   home, so the state reads as a fact and only the actions look tappable. */
.dp-homeflag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 8px 6px 10px; border-radius: 8px; font-size: 12.5px; font-weight: 600;
  color: var(--accent); background: var(--accent-soft); border: 1px solid var(--accent);
}
/* Clear lives INSIDE the badge — it undoes the state the badge reports, so it
   belongs to it rather than sitting beside "Center on this person" as an equal. */
.dp-homeclear {
  background: none; border: 1px solid var(--accent); border-radius: 6px;
  color: var(--accent); font: inherit; font-size: 11px; font-weight: 600;
  padding: 2px 7px; cursor: pointer; opacity: .85;
}
.dp-homeclear:hover { opacity: 1; background: var(--accent); color: var(--bg); }
.dp-homedefault { color: var(--muted); font-weight: 400; font-size: 11px; }
.chart-legend summary {
  list-style: none; cursor: pointer; user-select: none;
  padding: 7px 14px;
  color: var(--accent); font-weight: 600; font-size: 12.5px;
}
.chart-legend summary::-webkit-details-marker { display: none; }
.chart-legend summary::before { content: '▸ '; }
.chart-legend[open] summary::before { content: '▾ '; }
.chart-legend .lg-body {
  display: flex; flex-flow: row wrap; align-items: center;
  gap: 4px 20px;
  padding: 0 14px 9px;
}
.chart-legend .lg-row { display: flex; align-items: center; gap: 7px; }
.chart-legend svg { flex: 0 0 auto; }

.chart-hint {
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 10;
  background: rgba(20, 26, 34, .9);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--muted);
  font-size: 12px;
  padding: 5px 12px;
  pointer-events: none;
  transition: opacity .5s;
  white-space: nowrap;
}

/* detail panel: bottom sheet on mobile, right panel on desktop */
.detail-panel {
  position: absolute; z-index: 20;
  left: 0; right: 0; bottom: 0;
  /* v27: mobile bottom sheet capped at 40% so the ancestor lineage (which
     renders UP, above the tapped person) stays visible above it. Desktop
     (@media min-width:800px, below) overrides this to max-height:none — byte-
     unchanged. Panel is overflow-y:auto, so the buttons just sit lower. */
  max-height: 40%;
  background: var(--bg-raised);
  border-top: 1px solid var(--border);
  border-radius: 14px 14px 0 0;
  box-shadow: var(--shadow);
  overflow-y: auto;
  padding: 14px 16px 22px;
  transform: translateY(105%);
  transition: transform .22s ease;
}
.detail-panel.open { transform: translateY(0); }
.dp-close {
  position: absolute; top: 8px; right: 10px;
  background: none; border: 0; color: var(--muted);
  font-size: 22px; cursor: pointer; line-height: 1; padding: 4px 8px;
}
.detail-panel h2 { margin: 2px 0 2px; font-size: 20px; padding-right: 30px; }
.detail-panel .dp-sub { color: var(--muted); font-size: 13px; margin-bottom: 10px; }
.dp-row { margin: 7px 0; font-size: 14px; }
.dp-row .lbl { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .05em; display: block; }
.dp-links { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
/* v34: a second Save at the TOP of a long form (edit-person) so it can be saved
   without scrolling down to the bottom Save. */
.ct-topsave { display: flex; margin: 0 0 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.ct-topsave .btn { flex: 1 1 auto; }

@media (min-width: 800px) {
  .stats-row { grid-template-columns: repeat(4, 1fr); }
  .quick-links { grid-template-columns: repeat(2, 1fr); }
  .detail-panel {
    left: auto; top: 12px; right: 12px; bottom: 12px;
    width: 360px; max-height: none;
    border: 1px solid var(--border);
    border-radius: 14px;
    transform: translateX(112%);
  }
  .detail-panel.open { transform: translateX(0); }
}

/* ---------- person page ---------- */
.person-head { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.person-head h1 { margin: 0; font-size: clamp(24px, 6vw, 34px); }
/* birth/maiden name appendage (v18) — lighter + italic, e.g. "…, née Lambert" */
.person-nee { font-weight: 400; font-style: italic; color: var(--muted); font-size: 0.6em; }
.person-head .badge-grade { margin-top: 10px; }
.person-sub { color: var(--muted); margin-bottom: 18px; }
.fact-grid { display: grid; grid-template-columns: 1fr; gap: 10px; margin: 16px 0; }
@media (min-width: 640px) { .fact-grid { grid-template-columns: 1fr 1fr; } }
.fact { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 11px 13px; }
.fact .lbl { color: var(--muted); font-size: 11.5px; text-transform: uppercase; letter-spacing: .06em; }
.fact .val { margin-top: 2px; font-size: 14.5px; overflow-wrap: break-word; }
.person-section { margin-top: 22px; }
.person-section h2 { font-size: 18px; color: var(--accent); margin: 0 0 10px; }
.rel-list { display: flex; flex-direction: column; gap: 7px; }
.rel-item {
  display: flex; align-items: center; gap: 9px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 9px 12px; color: var(--text);
}
.rel-item:hover { border-color: var(--accent); text-decoration: none; }
.rel-item .rel-tag { font-size: 11.5px; color: var(--muted); margin-left: auto; flex: 0 0 auto; text-align: right; }
.note-block {
  background: var(--panel); border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
  padding: 12px 14px; font-size: 14px;
  white-space: pre-wrap; overflow-wrap: break-word;
}
.source-list { margin: 0; padding-left: 20px; font-size: 14px; }
.source-list li { margin: 4px 0; }
.rq-block {
  background: rgba(248, 81, 73, .07);
  border: 1px solid rgba(248, 81, 73, .25);
  border-radius: 10px;
  padding: 12px 14px; font-size: 14px;
}
.rq-block .rq-title { color: var(--grade-c); font-weight: 700; font-size: 12.5px; text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px; }
/* v38: a flag title can now be the reporter's own sentence (OTHER), so it must keep the
   case they typed. person.js upper-cases the legacy single-key values itself, so those
   still read as labels. */
.rq-block .rq-title.flag-title { text-transform: none; }

/* ---------- research follow-ups (admin, v14) ---------- */
/* profile panel + the standalone Follow-ups task list share these. Gold-tinted
   (research/admin), distinct from the red family flag-a-fact blocks. */
.rf-card { margin: 10px 0 16px; border-color: rgba(212, 169, 78, .3); }
/* v20: collapsed by default — summary shows 🚩 + open count, expands on click */
.rf-summary { cursor: pointer; color: var(--accent); font-weight: 600; list-style: none; display: flex; align-items: center; gap: 8px; }
.rf-summary::-webkit-details-marker { display: none; }
.rf-summary::before { content: '▸'; color: var(--muted); font-weight: 400; transition: transform .12s; }
.rf-card[open] > .rf-summary::before { transform: rotate(90deg); }
.rf-count { background: var(--accent); color: #12161c; font-size: 12px; font-weight: 700; border-radius: 999px; padding: 1px 8px; }
.rf-body { margin-top: 4px; }
.rf-card:not([open]) > .rf-body { display: none; } /* guarantee collapse regardless of UA <details> quirks */
.rf-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.rf-item {
  background: rgba(212, 169, 78, .07);
  border: 1px solid rgba(212, 169, 78, .28);
  border-radius: 10px; padding: 10px 12px;
  display: grid; grid-template-columns: 1fr auto; grid-template-areas: "note btn" "meta btn";
  gap: 2px 10px; align-items: start; font-size: 14px;
}
.rf-item .rf-note { grid-area: note; white-space: pre-wrap; }
.rf-item .rf-meta { grid-area: meta; }
.rf-item .rf-resolve { grid-area: btn; align-self: center; white-space: nowrap; }
.rf-add textarea {
  width: 100%; resize: vertical; min-height: 46px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px;
  font: inherit; font-size: 14px; margin-bottom: 8px;
}
.rf-add textarea:focus { outline: none; border-color: var(--accent); }
.rf-msg { align-self: center; }

/* ---------- users admin page (v16) ---------- */
.u-add-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.u-add-form input, .u-add-form select {
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 8px 10px; font: inherit; font-size: 14px;
}
.u-add-form input:focus, .u-add-form select:focus, .u-role:focus { outline: none; border-color: var(--accent); }
.u-add-form input[name="name"] { flex: 1 1 130px; }
.u-add-form input[name="pin"] { flex: 1 1 170px; }
.u-add-msg, .u-msg { min-height: 16px; margin-top: 6px; }
.u-card { margin: 10px 0; }
.u-head { font-size: 16px; margin-bottom: 8px; }
.u-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 6px; }
.u-role { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px; font: inherit; font-size: 13px; margin-left: 4px; }
/* v31: optional admin-typed PIN on Reset (blank = generate) — matches the add-form input */
.u-reset-pin { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 6px 9px; font: inherit; font-size: 13px; flex: 1 1 150px; min-width: 120px; }
.u-reset-pin:focus { outline: none; border-color: var(--accent); }
/* v20: PIN shown in plain text in each user card (admin-only screen) */
.u-pin-line { margin: 2px 0 8px; }
.u-pincode { font-size: 16px; letter-spacing: 2px; color: var(--accent); background: var(--bg-raised); border: 1px solid var(--border); border-radius: 6px; padding: 1px 8px; }

/* ---------- unified Admin page tabs (v30) ---------- */
.admin-tabs {
  display: flex; flex-wrap: wrap; gap: 6px;
  border-bottom: 1px solid var(--border); margin: 0 0 18px; padding-bottom: 10px;
}
.admin-tab {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--bg-raised); color: var(--muted);
  border: 1px solid var(--border); border-radius: 9px;
  padding: 7px 14px; font: inherit; font-size: 14px; cursor: pointer;
}
.admin-tab:hover { border-color: var(--accent); color: var(--text); }
.admin-tab.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.admin-tab-count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 999px; font-size: 11px; font-weight: 700;
  background: var(--panel-2); color: var(--muted);
}
.admin-tab.active .admin-tab-count { background: var(--accent); color: var(--bg); }
/* the count sets display:inline-flex, which would defeat the plain [hidden]
   attribute — so hide the un-counted (Users) / not-yet-loaded badge explicitly */
.admin-tab-count[hidden] { display: none; }
.admin-pane[hidden] { display: none; }

/* ---------- memories / tributes (v21) — deceased profiles only ---------- */
.mem-section { margin-top: 8px; }
.mem-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.mem-item {
  background: var(--bg-raised); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: 10px; padding: 12px 14px; font-size: 14.5px;
}
.mem-text { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55; }
.mem-meta { margin-top: 8px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mem-del { border: 0; background: transparent; color: var(--muted); cursor: pointer; font-size: 12px; padding: 0; text-decoration: underline; }
.mem-del:hover { color: var(--grade-c); }
.mem-form textarea {
  width: 100%; resize: vertical; min-height: 60px;
  background: var(--panel); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 9px 11px; font: inherit; font-size: 14.5px; margin-bottom: 8px;
}
.mem-form textarea:focus { outline: none; border-color: var(--accent); }
.mem-msg { align-self: center; }

/* ---------- document intake (v22) ---------- */
/* family submit form reuses .card + .f-row; admin page = .in-card list */
.in-card { margin: 12px 0; }
.in-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.in-file { font-size: 15.5px; overflow-wrap: anywhere; }
.in-note { white-space: normal; overflow-wrap: anywhere; line-height: 1.5; margin: 2px 0 8px; font-size: 14.5px; }
.in-meta { margin-bottom: 10px; }
.in-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.in-row .in-status { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 8px; padding: 5px 8px; font: inherit; font-size: 13px; margin-left: 4px; }
.in-row .in-status:focus { outline: none; border-color: var(--accent); }
.in-del:hover { border-color: var(--grade-c); color: var(--grade-c); }
.in-msg { min-height: 16px; margin-top: 6px; }
/* status pill — new stands out (needs attention); done reads complete */
.badge-status {
  display: inline-flex; align-items: center; height: 20px; padding: 0 9px;
  border-radius: 999px; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.badge-status.s-new { background: var(--accent-soft); color: var(--accent); border: 1px solid rgba(212, 169, 78, .4); }
.badge-status.s-reviewed { background: rgba(210, 153, 34, .15); color: var(--grade-b); border: 1px solid rgba(210, 153, 34, .4); }
.badge-status.s-sent { background: var(--bg-raised); color: var(--muted); border: 1px solid var(--border); }
.badge-status.s-done { background: rgba(63, 185, 80, .15); color: var(--grade-a); border: 1px solid rgba(63, 185, 80, .4); }

/* ---------- book viewer ---------- */
.book-toolbar {
  position: sticky; top: var(--nav-h); z-index: 30;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  background: rgba(13, 17, 23, .92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.book-toolbar .pg-input {
  width: 64px; text-align: center;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 6px 4px; font-size: 14px;
}
.book-toolbar .spacer { flex: 1; }
.view-toggle { display: flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.view-toggle button {
  background: var(--panel); color: var(--muted); border: 0;
  padding: 6px 11px; cursor: pointer; font-size: 13px;
}
.view-toggle button.active { background: var(--accent-soft); color: var(--accent); }
.book-split { display: grid; grid-template-columns: 1fr; gap: 12px; padding: 12px; max-width: 1500px; margin: 0 auto; }
.book-pane { min-width: 0; }
.book-pane.image-pane img {
  width: 100%; border: 1px solid var(--border); border-radius: 8px;
  background: #fff;
}
.book-pane.text-pane .ocr {
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  padding: 16px 18px;
  font-family: var(--serif);
  font-size: 15px; line-height: 1.65;
  white-space: pre-wrap; overflow-wrap: break-word;
  min-height: 200px;
}
.ocr-note { color: var(--muted); font-size: 12px; margin: 6px 2px; }
.book-split.mode-image .text-pane { display: none; }
.book-split.mode-text .image-pane { display: none; }
@media (min-width: 900px) {
  .book-split.mode-both { grid-template-columns: 1fr 1fr; }
}

/* ---------- docs ---------- */
.doc-list { display: grid; grid-template-columns: 1fr; gap: 10px; }
.doc-list a.card { color: var(--text); display: block; }
.doc-list a.card:hover { border-color: var(--accent); text-decoration: none; }
.doc-list h3 { margin: 0 0 4px; font-size: 16.5px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.doc-list p { margin: 0; color: var(--muted); font-size: 13.5px; }
.unverified-banner {
  background: rgba(248, 81, 73, .09);
  border: 1px solid rgba(248, 81, 73, .35);
  border-radius: 10px;
  padding: 11px 14px;
  font-size: 13.5px;
  margin-bottom: 14px;
}
.unverified-banner strong { color: var(--grade-c); }
.doc-text {
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 18px 20px; font-size: 14.5px;
}
.doc-text h3 { color: var(--accent); margin: 18px 0 6px; }
.doc-text p { margin: 8px 0; }

/* ---------- v38 (I): flag-a-fact checkboxes ---------- */
/* Wrapping chips, each a whole-row tap target on a phone — the label IS the hit area,
   so a one-handed tick doesn't need to find a 13px box. */
.flag-items { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.flag-item {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 11px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg); color: var(--text);
  font-size: 12.5px; font-weight: 600; letter-spacing: .04em;
  cursor: pointer; user-select: none;
}
.flag-item:hover { border-color: var(--accent); }
/* NOTE the specificity: these boxes live inside a .f-row, and `.f-row input` (declared
   further down, so it wins at equal weight) would otherwise make every checkbox a
   full-width padded block. Two classes + the element outrank it. */
.flag-items .flag-item input[type="checkbox"] {
  display: inline-block; width: 15px; height: 15px; flex: 0 0 auto;
  margin: 0; padding: 0; border-radius: 3px; background: none;
  accent-color: var(--accent); cursor: pointer;
}
/* ticked reads as ticked without relying on the box alone */
.flag-item:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.flag-other { display: block; width: 100%; margin-top: 8px; }
.flag-other[hidden] { display: none; }

/* ---------- v39 (H): Users-tab person link ---------- */
.u-person { margin: 8px 0; }
.u-person-cur { margin-bottom: 4px; }
.u-person-cur a { color: var(--link); }
.u-unlink { padding: 2px 8px; font-size: 11px; }
.pp-mini { max-width: 340px; }

/* ---------- v37 (L): searchable person picker ---------- */
/* The results list is absolutely positioned under the input, so it overlays the
   form instead of pushing it around as you type. .modal has position:relative and
   no overflow clip, so the list is free to hang below the field. */
/* flex-grow matters: .rel-add is a flex row (it used to hold a content-sized
   <select>), so without this the picker shrinks to its placeholder's width instead
   of filling the field. Ignored where .pp isn't a flex item (the link pane). */
.pp { position: relative; margin-top: 4px; flex: 1 1 auto; }
.pp-input {
  display: block; width: 100%;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 11px; font-size: 14.5px; font-family: inherit;
}
.pp-input:focus { outline: none; border-color: var(--accent); }
.pp-results {
  position: absolute; top: 100%; left: 0; right: 0; margin-top: 3px; z-index: 5;
  max-height: 240px; overflow-y: auto;
  background: var(--bg-raised); border: 1px solid var(--accent); border-radius: 8px;
  box-shadow: var(--shadow);
}
.pp-item {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 8px 10px; background: none; border: 0; border-bottom: 1px solid var(--border);
  color: var(--text); font-size: 13.5px; font-family: inherit; text-align: left; cursor: pointer;
}
.pp-item:last-child { border-bottom: 0; }
.pp-item:hover, .pp-item.pp-active { background: var(--accent-soft); }
.pp-name { font-weight: 600; }
.pp-nee, .pp-life { color: var(--muted); }
.pp-life { margin-left: auto; white-space: nowrap; }
.pp-empty { padding: 9px 11px; color: var(--muted); font-size: 13px; }

/* ---------- v37 (G): save-and-close confirmation toast ---------- */
/* Bottom-CENTRE, above the chat FAB's corner (FAB: bottom 20px + 54px tall, or
   16 + 50 on mobile) so the two never collide. z-index clears the modal layer
   (100) — a toast is the answer to an action and must never sit behind one. */
#ft-toasts {
  position: fixed; z-index: 110;
  bottom: 88px; left: 50%; transform: translateX(-50%);
  width: min(92vw, 460px);
  display: flex; flex-direction: column; gap: 8px;
  pointer-events: none;
}
.ft-toast {
  pointer-events: auto;
  display: flex; align-items: flex-start; gap: 8px;
  background: var(--bg-raised); border: 1px solid var(--accent);
  border-radius: 10px; padding: 10px 8px 10px 12px;
  box-shadow: var(--shadow); font-size: 13.5px; color: var(--text);
  animation: ft-toast-in .18s ease-out;
}
@keyframes ft-toast-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .ft-toast { animation: none; } }
.ft-toast-body { flex: 1 1 auto; line-height: 1.45; }
.ft-toast-x {
  flex: 0 0 auto; background: none; border: 0; color: var(--muted);
  font-size: 17px; line-height: 1; padding: 2px 5px; cursor: pointer;
}
.ft-toast-x:hover { color: var(--text); }

/* ---------- v3: contribute modal + forms ---------- */
.modal-wrap {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(5, 8, 12, .7);
  display: flex; align-items: flex-start; justify-content: center;
  overflow-y: auto; padding: 24px 12px;
}
.modal {
  position: relative;
  width: min(94vw, 560px);
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 20px 20px 18px;
  box-shadow: var(--shadow);
}
.modal h2 { margin: 0 0 12px; font-size: 19px; color: var(--accent); padding-right: 28px; }
.f-row { display: block; margin: 10px 0; font-size: 13px; color: var(--muted); }
.f-row input, .f-row textarea, .f-row select {
  display: block; width: 100%; margin-top: 4px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 9px 11px; font-size: 14.5px; font-family: inherit;
}
.f-row input:focus, .f-row textarea:focus, .f-row select:focus { outline: none; border-color: var(--accent); }
.f-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.f-msg { min-height: 18px; font-size: 13px; margin: 8px 0 2px; }

/* partial-date picker (year + optional month/day + circa) */
.date-field .df-label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 4px; }
.date-field .df-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.date-field .df-row input, .date-field .df-row select { margin-top: 0; }
.date-field .df-year { width: 90px; }
.date-field .df-month, .date-field .df-day { width: auto; min-width: 64px; }
.date-field .df-circa { display: inline-flex; align-items: center; gap: 5px; margin: 0; font-size: 12.5px; color: var(--muted); }
.date-field .df-circa input { width: auto; margin: 0; }

/* ---------- v3: admin queue ---------- */
.q-item, .q-batch { margin-bottom: 12px; }
.q-batch .q-item { margin: 10px 0 0; background: var(--bg-raised); }
.q-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-bottom: 8px; }
.q-meta { color: var(--muted); font-size: 12.5px; margin-left: auto; }
.q-type {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  border-radius: 5px; padding: 2px 7px;
}
.q-add { background: rgba(63, 185, 80, .15); color: var(--grade-a); }
.q-edit { background: rgba(108, 182, 255, .15); color: var(--link); }
.q-flag, .q-rejected { background: rgba(248, 81, 73, .13); color: var(--grade-c); }
.q-upload, .q-gedcom { background: var(--accent-soft); color: var(--accent); }
.q-approved { background: rgba(63, 185, 80, .15); color: var(--grade-a); }
.q-actions { display: flex; gap: 8px; margin-top: 10px; }
.q-decided { padding: 7px 4px; border-bottom: 1px solid var(--border); display: flex; gap: 7px; align-items: center; flex-wrap: wrap; }
div.q-upload img { max-width: min(100%, 320px); border-radius: 8px; border: 1px solid var(--border); }
.diff-table { width: 100%; border-collapse: collapse; font-size: 13.5px; margin: 6px 0; }
.diff-table th { text-align: left; color: var(--muted); font-size: 11.5px; text-transform: uppercase; letter-spacing: .05em; padding: 4px 8px; }
.diff-table td { border-top: 1px solid var(--border); padding: 6px 8px; vertical-align: top; overflow-wrap: anywhere; }
.diff-table .d-field { color: var(--muted); font-size: 12px; white-space: nowrap; }
.diff-table .d-before { color: var(--grade-c); }
.diff-table .d-after { color: var(--grade-a); }

/* ---------- v3: person photos ---------- */
.photo-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.photo-grid figure { margin: 0; }
.photo-grid img { width: 100%; border-radius: 8px; border: 1px solid var(--border); }

/* ---------- v10: AI chat ---------- */
.chat-wrap {
  display: flex; flex-direction: column;
  height: calc(100dvh - var(--nav-h));
  max-width: 780px; margin: 0 auto; width: 100%;
}
.chat-scroll { flex: 1; overflow-y: auto; padding: 18px 16px 8px; }
.chat-intro { text-align: center; padding: 24px 6px; }
.chat-intro h1 { color: var(--accent); font-size: clamp(24px, 6vw, 32px); margin: 0 0 8px; }
.chat-intro .sub, .chat-intro p { max-width: 560px; margin: 0 auto; }
.chat-suggestions { display: flex; flex-direction: column; gap: 8px; margin: 22px auto 0; max-width: 460px; }
.chat-suggestions .chip {
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 11px 14px; font-size: 14px; text-align: left; cursor: pointer;
}
.chat-suggestions .chip:hover { border-color: var(--accent); color: var(--accent); }

.chat-msg { max-width: 84%; margin: 10px 0; padding: 11px 15px; border-radius: 14px; font-size: 15px; line-height: 1.55; overflow-wrap: break-word; }
.chat-msg p { margin: 0 0 8px; }
.chat-msg p:last-child { margin-bottom: 0; }
.chat-msg.user { margin-left: auto; background: var(--accent-soft); border: 1px solid rgba(212,169,78,.4); color: var(--text); border-bottom-right-radius: 5px; }
.chat-msg.assistant { margin-right: auto; background: var(--panel); border: 1px solid var(--border); border-bottom-left-radius: 5px; }
.chat-msg.assistant.error { border-color: rgba(248,81,73,.4); color: var(--grade-c); }
.chat-msg a { color: var(--link); }

.chat-typing { display: inline-flex; gap: 4px; padding: 2px 0; }
.chat-typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: chat-blink 1.2s infinite ease-in-out; }
.chat-typing span:nth-child(2) { animation-delay: .2s; }
.chat-typing span:nth-child(3) { animation-delay: .4s; }
@keyframes chat-blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }

.chat-bar {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  background: rgba(13, 17, 23, .92); backdrop-filter: blur(8px);
}
.chat-bar textarea {
  flex: 1; resize: none; overflow-y: auto;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 12px;
  padding: 11px 13px; font: inherit; font-size: 15px; line-height: 1.4; outline: none;
}
.chat-bar textarea:focus { border-color: var(--accent); }
.chat-bar .btn { flex: 0 0 auto; height: 44px; }
.chat-bar .btn:disabled { opacity: .5; }

/* ---------- footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
  padding: 34px 12px 30px; /* generous top pad = the long-page gap */
  margin-top: auto; /* v14: pushed to the bottom of the flex-column body (sticky footer) */
}
/* v20: grading legend on its own line (reads as part of the page), then the
   site/version line as fine-print, then the badge (v15 spacing below preserved). */
.footer-legend { font-size: 13px; color: var(--text); margin-bottom: 12px; line-height: 1.8; }
.footer-site { font-size: 12px; color: var(--muted); }

/* ---------- v11: nickname, relationship editor, AI proposals ---------- */
.person-nick { color: var(--accent); font-family: var(--serif); font-style: italic; font-size: 16px; margin: -4px 0 8px; }
.detail-panel .dp-nick { color: var(--accent); font-style: italic; font-size: 13px; margin-bottom: 4px; }

.btn.small { padding: 4px 10px; font-size: 12.5px; }

/* relationship editor inside the edit modal */
.rel-box {
  border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 12px 12px; margin: 14px 0 4px;
}
.rel-box legend { color: var(--accent); font-size: 13px; padding: 0 6px; font-family: var(--serif); }
.rel-list-edit { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.rel-list-edit:empty { display: none; }
/* v17: roomier partner/parent chips — the inline status select had too little
   air, so multi-partner rows read as cramped. */
.rel-chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--bg-raised); border: 1px solid var(--border); border-radius: 999px;
  padding: 5px 8px 5px 13px; font-size: 12.5px; line-height: 1.4; color: var(--text);
}
.rel-chip .rel-status {
  background: var(--panel); color: var(--muted); border: 1px solid var(--border);
  border-radius: 6px; font-size: 12px; padding: 3px 6px; margin: 0;
}
.rel-chip .rel-x {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 16px; line-height: 1; padding: 0 4px;
}
.rel-chip .rel-x:hover { color: var(--grade-c); }
.rel-add { display: flex; gap: 6px; align-items: center; margin-top: 4px; }
.rel-add select { flex: 1 1 auto; }
/* v18: on a phone the pill can't fit name + a type <select> + × on one line, so
   each chip becomes a full-width block — name (+ ×) on top, the type select on its
   own row below. Desktop keeps the inline pill. */
@media (max-width: 400px) {
  .rel-list-edit { gap: 10px; }
  .rel-chip {
    display: flex; flex-wrap: wrap; align-items: center; width: 100%;
    border-radius: 10px; padding: 8px 12px; gap: 6px 8px;
  }
  .rel-chip .rel-name { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
  .rel-chip .rel-x { flex: 0 0 auto; margin-left: auto; }
  .rel-chip .rel-status { order: 9; flex: 1 0 100%; width: 100%; } /* type drops to its own full-width row */
}

/* create-or-link toggle (v17) — Link existing / Create new, in one modal */
.col-toggle { display: flex; gap: 6px; margin: 4px 0 12px; }
.col-tab {
  flex: 1 1 0; background: var(--bg-raised); color: var(--muted);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px;
  font: inherit; font-size: 13px; cursor: pointer;
}
.col-tab:hover { color: var(--text); }
.col-tab.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.col-pane[hidden] { display: none; }

/* AI proposed-changes card (ask.html) */
.chat-msg .proposal {
  border: 1px solid var(--accent); border-radius: 12px;
  background: var(--accent-soft); padding: 12px 14px; margin-top: 2px;
}
.proposal .prop-head { color: var(--accent); font-weight: 600; font-size: 14px; margin-bottom: 8px; }
.proposal .prop-row {
  display: flex; gap: 9px; align-items: flex-start;
  padding: 6px 0; border-top: 1px solid var(--border); font-size: 13.5px; color: var(--text);
}
.proposal .prop-row input[type="checkbox"] { width: auto; margin-top: 3px; flex: 0 0 auto; }
.proposal .prop-row.prop-disabled { opacity: .55; }
.proposal .prop-name input { width: 100%; }
.proposal .prop-actions { margin-top: 10px; }
.proposal .prop-msg { margin-top: 8px; min-height: 16px; }

/* ---------- v12: family-historian chat FAB + panel (DBL Portal spec) ---------- */
/* The FAB is anchored to the right edge of the 980px content column
   (right: 50vw - 490px), clamped to 20px on narrow screens — so it sits with
   the content, never floating alone in a wide-screen margin. */
.ftc-fab {
  position: fixed; z-index: 60;
  bottom: 20px; right: max(20px, calc(50vw - 490px));
  width: 54px; height: 54px; border-radius: 50%;
  border: 1px solid var(--accent); background: var(--accent); color: #12161c;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: var(--shadow);
  transition: transform .15s ease, filter .15s ease;
  -webkit-user-select: none; user-select: none;
}
.ftc-fab:hover { transform: translateY(-2px); filter: brightness(1.07); }
.ftc-fab svg { width: 25px; height: 25px; }
.ftc-fab.ftc-fab-open { background: var(--bg-raised); color: var(--accent); }

.ftc-panel {
  position: fixed; z-index: 61;
  bottom: 86px; right: max(20px, calc(50vw - 490px));
  width: 400px; max-width: calc(100vw - 24px);
  height: 560px; max-height: calc(100dvh - 130px);
  display: flex; flex-direction: column;
  background: var(--bg-raised); border: 1px solid var(--border);
  border-radius: 16px; overflow: hidden; box-shadow: var(--shadow);
}
.ftc-panel[hidden] { display: none; }
.ftc-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  padding: 10px 8px 10px 15px; border-bottom: 1px solid var(--border); background: var(--panel);
}
.ftc-title { color: var(--accent); font-family: var(--serif); font-size: 15.5px; font-weight: 600; }
.ftc-head-btns { display: flex; gap: 1px; }
.ftc-icon {
  border: none; background: none; color: var(--muted); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 6px 8px; border-radius: 7px;
}
.ftc-icon:hover { color: var(--text); background: var(--bg-raised); }
.ftc-msgs { flex: 1 1 auto; overflow-y: auto; padding: 14px 15px 8px; -webkit-overflow-scrolling: touch; }
/* messages are selectable — long-press to copy on mobile */
.ftc-msgs, .ftc-msgs .chat-msg, .ftc-msgs .chat-msg * { -webkit-user-select: text; user-select: text; }
.ftc-msgs .chat-msg { max-width: 88%; font-size: 14.5px; margin: 9px 0; }
.ftc-intro { padding: 4px 2px 2px; }
.ftc-intro .muted { font-size: 13.5px; line-height: 1.55; }
.ftc-chips { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.ftc-chip {
  text-align: left; background: var(--panel); border: 1px solid var(--border);
  color: var(--text); border-radius: 10px; padding: 9px 12px; font-size: 13px; cursor: pointer; line-height: 1.4;
}
.ftc-chip:hover { border-color: var(--accent); color: var(--accent); }
.ftc-input {
  flex: 0 0 auto; display: flex; gap: 8px; align-items: flex-end;
  padding: 10px 12px; border-top: 1px solid var(--border); background: var(--panel);
}
.ftc-input textarea {
  flex: 1 1 auto; resize: none; overflow-y: hidden; /* v19: no Windows scrollbar arrows on the empty box */
  background: var(--bg); border: 1px solid var(--border); border-radius: 11px; padding: 9px 12px;
  color: var(--text); font-family: inherit; font-size: 15px; line-height: 1.4;
  min-height: 40px; max-height: 120px; outline: none;
}
.ftc-input textarea:focus { border-color: var(--accent); }
.ftc-input .btn { flex: 0 0 auto; height: 40px; }

@media (max-width: 560px) {
  .chart-controls { bottom: 78px; } /* keep the chart zoom controls clear of the FAB */
  .ftc-fab { bottom: 16px; width: 50px; height: 50px; }
  .ftc-panel { bottom: 74px; max-height: calc(100dvh - 92px); }
}
