:root {
  --ink: #1e2430;
  --dim: #67707f;
  --bg: #faf9f6;
  --card: #ffffff;
  --line: #e4e1d8;
  --accent: #7a5c2e;
  --biblical: #dbeafe;   --biblical-ink: #1d4ed8;
  --rabbinic: #dcfce7;   --rabbinic-ink: #15803d;
  --tradition: #fef9c3;  --tradition-ink: #a16207;
  --external: #ffedd5;   --external-ink: #c2410c;
  --archaeology: #fee2e2; --archaeology-ink: #b91c1c;
  --reconstruction: #f1f5f9; --reconstruction-ink: #475569;
}

* { box-sizing: border-box; }
body {
  margin: 0;
  font: 17px/1.65 Georgia, 'Times New Roman', 'SBL Hebrew', 'David Libre', serif;
  color: var(--ink);
  background: var(--bg);
}
main { max-width: 880px; margin: 0 auto; padding: 2rem 1.25rem 4rem; }

.site-header {
  display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: .5rem;
  padding: 1rem 1.5rem; border-bottom: 2px solid var(--accent); background: var(--card);
}
.brand { font-weight: bold; font-size: 1.15rem; color: var(--accent); text-decoration: none; letter-spacing: .02em; }
.site-header nav a { margin-left: 1rem; color: var(--dim); text-decoration: none; }
.site-header nav a:hover { color: var(--accent); }

a { color: var(--accent); }
h1 { font-size: 2rem; margin: .2rem 0 .6rem; }
h2 { font-size: 1.05rem; text-transform: uppercase; letter-spacing: .08em; color: var(--dim); border-bottom: 1px solid var(--line); padding-bottom: .3rem; margin-top: 2.2rem; }
.kicker { text-transform: uppercase; letter-spacing: .1em; font-size: .8rem; color: var(--dim); margin-bottom: 0; }
.summary { font-size: 1.1rem; }
.hebrew { font-size: 1.05em; direction: rtl; unicode-bidi: isolate; }
.dim { color: var(--dim); }

dl.facts { display: grid; grid-template-columns: max-content 1fr; gap: .25rem 1.25rem; margin: .75rem 0; }
dl.facts dt { color: var(--dim); }
dl.facts dd { margin: 0; }

table.claims { width: 100%; border-collapse: collapse; font-size: .95rem; }
/* Desktop-first: let the evidence table breathe beyond the prose column */
@media (min-width: 1080px) {
  table.claims { width: min(1240px, calc(100vw - 6rem)); position: relative; left: 50%; transform: translateX(-50%); }
  .claim-text { max-width: 36rem; }
}
table.claims th { text-align: left; color: var(--dim); font-weight: normal; text-transform: uppercase; font-size: .75rem; letter-spacing: .06em; padding: .4rem .6rem; }
table.claims td { border-top: 1px solid var(--line); padding: .6rem; vertical-align: top; background: var(--card); }
.claim-text { max-width: 24rem; }
.stars { white-space: nowrap; color: var(--accent); }
.sources { font-size: .88rem; }
.note { color: var(--dim); font-size: .88rem; margin-top: .35rem; }

/* Claim sources: links are unmistakable, bare citations are calm */
.source-list { list-style: none; margin: 0; padding: 0; }
.source-list li { margin: .18rem 0; }
.source-link {
  color: var(--accent); text-decoration: underline;
  text-decoration-color: #cdbfa4; text-underline-offset: 2px;
}
.source-link:hover { text-decoration-color: var(--accent); }
.source-link .source-ext { font-size: .8em; }
.source-cite { color: var(--dim); font-style: italic; }

/* Small screens: each claim row becomes a stacked card */
@media (max-width: 640px) {
  table.claims thead { display: none; }
  table.claims tr { display: block; border-top: 1px solid var(--line); padding: .45rem 0; }
  table.claims td { display: block; border-top: none; padding: .2rem .6rem; }
  .claim-text { max-width: none; }
}

.chip { display: inline-block; padding: .05rem .55rem; border-radius: 999px; font-size: .75rem; white-space: nowrap; }
.cat-biblical { background: var(--biblical); color: var(--biblical-ink); }
.cat-rabbinic { background: var(--rabbinic); color: var(--rabbinic-ink); }
.cat-tradition { background: var(--tradition); color: var(--tradition-ink); }
.cat-external { background: var(--external); color: var(--external-ink); }
.cat-archaeology { background: var(--archaeology); color: var(--archaeology-ink); }
.cat-reconstruction { background: var(--reconstruction); color: var(--reconstruction-ink); }

.badge { font-size: .75rem; padding: .05rem .5rem; border-radius: 4px; vertical-align: middle; }
.badge-draft { background: var(--reconstruction); color: var(--reconstruction-ink); }
.badge-flagged { background: var(--archaeology); color: var(--archaeology-ink); }

ul.entity-list { list-style: none; padding: 0; columns: 2; }
ul.entity-list li { margin: .3rem 0; break-inside: avoid; }
@media (max-width: 640px) { ul.entity-list { columns: 1; } }

.backrefs { color: var(--dim); font-size: .9rem; margin-top: 2rem; border-top: 1px solid var(--line); padding-top: .8rem; }
.site-footer { max-width: 880px; margin: 0 auto; padding: 1rem 1.25rem 3rem; color: var(--dim); font-size: .8rem; }

.viz { overflow-x: auto; background: var(--card); border: 1px solid var(--line); padding: 1rem; }
.viz svg { display: block; }
svg a { text-decoration: none; }

/* ---- Mesorah Map — full-bleed desktop canvas ---- */
body.page-wide { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }
body.page-wide .site-header { padding: .55rem 1.25rem; }
body.page-wide .site-footer { display: none; }
main.wide { flex: 1; min-height: 0; max-width: none; margin: 0; padding: 0; }
#map-shell { position: relative; height: 100%; min-height: 420px; }

.map-controls {
  position: absolute; top: .8rem; left: .9rem; z-index: 5;
  display: flex; flex-wrap: wrap; gap: 1.1rem; align-items: center;
  padding: .3rem .9rem; background: rgba(255, 255, 255, .93);
  border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 1px 6px rgba(30, 36, 48, .08);
  font-size: .92rem;
}
.map-controls .mode-toggle label { margin-right: .8rem; color: var(--dim); cursor: pointer; }
.map-controls button { font: inherit; padding: .05rem .65rem; border: 1px solid var(--line); background: var(--card); border-radius: 6px; cursor: pointer; }
.map-controls button:hover { border-color: var(--accent); color: var(--accent); }

/* Layer chips (Apple-Maps style): pressed = layer shown */
.map-controls .layer-chips { display: inline-flex; gap: .35rem; }
.map-controls .layer-chip {
  font-size: .82rem; padding: .05rem .65rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--dim); cursor: pointer;
}
.map-controls .layer-chip[aria-pressed="true"] { background: #f4eddc; border-color: var(--accent); color: var(--accent); }
.map-controls .layer-chip[aria-pressed="false"] { opacity: .55; }
.map-controls .layer-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

#loupe-mode[aria-pressed="true"] { background: #f4eddc; border-color: var(--accent); color: var(--accent); }

/* Magnifier loupes: floating, fully interactive viewports onto a clone of
   the once-rendered canvas. Rubber band while selecting; window chrome with
   drag handle, resize grip, close button. */
.loupe-band {
  position: absolute; z-index: 18; pointer-events: none;
  border: 1.5px dashed var(--accent); background: rgba(122, 92, 46, .07);
  border-radius: 4px;
}
.loupe {
  position: absolute; z-index: 20; display: flex; flex-direction: column;
  min-width: 220px; min-height: 160px; max-width: 90%; max-height: 85%;
  background: var(--card); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 6px 28px rgba(30, 36, 48, .25);
  resize: both; overflow: hidden;
}
.loupe-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: .15rem .3rem .15rem .7rem; cursor: move; user-select: none;
  background: #f6f2e8; border-bottom: 1px solid var(--line);
  font-size: .8rem; color: var(--dim);
}
.loupe-close {
  font: inherit; font-size: 1rem; line-height: 1; padding: .05rem .45rem;
  border: none; background: none; color: var(--dim); cursor: pointer; border-radius: 6px;
}
.loupe-close:hover { color: var(--accent); background: #efe8d8; }
.loupe-body { flex: 1; min-height: 0; overflow: hidden; background: var(--bg); cursor: grab; touch-action: none; }
.loupe-body svg { width: 100%; height: 100%; display: block; user-select: none; }

/* Layer visibility: the client toggles hide-* classes on the SVG root.
   Pure show/hide of build-time content — nothing reflows, nothing re-renders.
   Texts: book nodes, author/based_on edges, and written edges with a TEXT
   endpoint (edge-wtext). Person↔person written edges are mesorah — never
   hidden here. Archaeology: dig badges + event markers. Rulers: royal bands,
   ruler-only king nodes, their edges, and crown badges on dual-citizen kings. */
svg.hide-texts .node-text, svg.hide-texts .edge-author,
svg.hide-texts .edge-basedon, svg.hide-texts .edge-wtext { display: none; }
svg.hide-arch .arch-badge, svg.hide-arch .layer-events { display: none; }
svg.hide-rulers .swim-royal, svg.hide-rulers .node-ruler,
svg.hide-rulers .crown-badge, svg.hide-rulers .edge-ruler { display: none; }
/* Help popover: the whole legend behind one "?" — closed by default */
#help-pop[hidden] { display: none; }
#help-pop {
  position: absolute; top: 3.4rem; left: .9rem; z-index: 9; width: 380px; max-width: calc(100% - 2rem);
  max-height: 70%; overflow-y: auto; padding: .6rem .9rem; font-size: .78rem;
}
#help-pop h3 { margin: .4rem 0 .15rem; font-size: .72rem; color: var(--accent); text-transform: uppercase; letter-spacing: .08em; }
#help-pop ul { margin: 0 0 .3rem; padding-left: 1.1rem; }
#help-pop li { margin: .12rem 0; line-height: 1.4; }
.help-legend { list-style: none; padding-left: .2rem !important; }
.hl-swatch { display: inline-block; width: 26px; height: 0; border-top: 3px solid; margin-right: .5rem; vertical-align: middle; }
.hl-spine { border-color: var(--accent); }
.hl-written { border-color: var(--accent); border-top-style: dashed; }
.hl-inferred { border-color: #8b8fa0; border-top-style: dotted; }
.hl-semicha { border-color: #5b3a8e; }
.hl-semicha-x { border-color: #b8860b; border-top-style: dashed; }
.hl-cord { border-top-width: 4px; border-image: linear-gradient(90deg, #b5442c, #2a6f8e, #7a8c2e, #8a5aa8) 1; }

#canvas { position: absolute; inset: 0; overflow: hidden; background: var(--bg); cursor: grab; touch-action: none; }
#canvas svg { width: 100%; height: 100%; display: block; user-select: none; }
/* The camera group is the only thing that moves. Deliberately NOT
   will-change/layer-promoted: measured on this canvas, promotion forces a
   full re-raster of a huge texture at every scale change (33.7ms/frame vs
   12.7ms without — see the round notes). Chrome re-rasterizes the vectors
   either way; unpromoted transform matches the old viewBox path (~80fps). */

#mesorah-map text { user-select: none; -webkit-user-select: none; }

/* Nodes — pure geometric zoom: everything below is fixed canvas-space */
.node rect { fill: #ffffff; stroke: #b3a58a; stroke-width: 1.2; transition: fill .15s ease, stroke .15s ease; }
.node.spine rect { fill: #fdf6e7; stroke: var(--accent); stroke-width: 2.2; }
.node-inst rect { stroke-dasharray: 6 3; }
.node .node-name { fill: var(--ink); }
.node .node-dates { fill: var(--dim); }
.node:hover rect { fill: #f6eeda; stroke: var(--accent); }
.node.spine:hover rect { fill: #f4e8cb; }

/* Transmission restrictions, two tiers:
   sole (strict cut vertex — no parallel line): double ring;
   dominant (majority of paths, a thinner rail runs beside): single strong ring */
.node-bn rect { stroke-width: 3; fill: #fcf3dc; }
.node-sole .bn-ring { stroke: var(--accent); stroke-width: 1.8; opacity: .5; stroke-dasharray: none; fill: none; }
.node-dom rect { stroke-dasharray: none; }
.node-carrier { fill: var(--accent); font-style: italic; opacity: .85; }

/* Written works — book boxes in a cool slate "book tone" against the warm
   person field; the spine-notch line reads as a book cover. Monumental works
   (Torah, Mishnah, the Bavli…) are drawn bigger at build time — static
   canvas-space prominence, nothing here depends on zoom. */
.node-text rect.book-cover { fill: #eef1f6; stroke: #64748b; stroke-width: 1.6; transition: fill .15s ease, stroke .15s ease; }
.node-text .book-spine { stroke: #64748b; stroke-width: 1.3; opacity: .55; }
.node-text .node-name { fill: #33415c; }
.node-text .node-heb { fill: #64748b; }
.node-text:hover rect.book-cover { fill: #e3e9f2; stroke: #3d4f6b; }
.node-monu rect.book-cover { stroke-width: 2.6; }
.layer-nodes a.lit-self rect.book-cover { stroke: #3d4f6b; stroke-width: 3; }

/* Lineage cord — colored strands of living person-to-person lineages,
   behind everything; a parchment-gray braid continues below the break */
.layer-cord { pointer-events: none; }
.cord-strand { fill: none; stroke-width: 3; stroke-linecap: round; opacity: .55; }
.cord-tail { fill: none; stroke-width: 2.2; stroke-linecap: round; opacity: .22; }
.cord-gray { stroke: none; }

/* Named restrictions in the right gutter (far + mid; near has box captions) */
.restrict-note text { fill: var(--accent); }
.restrict-note .rn-title { font-style: italic; }

/* Era furniture — all fixed canvas-space, drawn once (wall-poster model) */
.era-rule { stroke: #ddd6c6; stroke-width: 1.5; }
.era-rule-label { fill: #a89f8d; }
.era-watermark { font-size: 130px; fill: #ded7c5; letter-spacing: .3em; opacity: .55; pointer-events: none; }

/* Geographic region labels (vertical, named by the data's own places) */
.region-label { fill: #c4bba6; letter-spacing: .35em; font-size: 84px; opacity: .6; pointer-events: none; }

/* Academy swimlanes */
.swim-band { fill: #fbf7ec; stroke: #b3a58a; stroke-width: 1.2; stroke-dasharray: 6 3; transition: fill .15s ease; }
.swim-inst:hover .swim-band { fill: #f6efdd; stroke: var(--accent); }
.swim-bn .swim-band { stroke: var(--accent); stroke-width: 2; }
.swim-head { fill: #6b6254; }
.swim-side { fill: #b6ad99; font-size: 40px; letter-spacing: .25em; opacity: .6; pointer-events: none; }
.tenure rect { fill: #f5ecd5; stroke: #c9b992; stroke-width: 1; transition: fill .15s ease, stroke .15s ease; }
.tenure:hover rect { fill: #eee0bc; stroke: var(--accent); }
.tenure-name { fill: var(--ink); }
.tenure-years { fill: var(--dim); }
/* Year-less heads: hatched uncertain-span blocks — occupied, dates unknown.
   The diagonal hatch (one pattern def in the SVG) is the whole statement;
   hover and spotlight keep the hatch and speak through the stroke alone. */
.tenure-uncertain rect { fill: url(#hatch-uncertain); stroke-dasharray: 4 3; }
.tenure-uncertain:hover rect { fill: url(#hatch-uncertain); stroke: var(--accent); }
.tenure-uncertain .tenure-years { font-style: italic; }

/* Royal dynasty bands: distinct from academies — muted rose tint + crown header */
.swim-royal .swim-band { fill: #f8f0f2; stroke: #a06a78; }
.swim-royal .swim-inst:hover .swim-band { fill: #f2e4e8; stroke: #7c4a56; }
.swim-royal .swim-head { fill: #7c4a56; }
.swim-royal .swim-side { fill: #cfb2ba; }
.swim-royal .tenure rect { fill: #f3e6ea; stroke: #c79fab; }
.swim-royal .tenure:hover rect { fill: #ecd8de; stroke: #7c4a56; }

/* Crown badge on chain-member kings (dual citizens): only this hides with
   the Rulers layer — the figure itself stays on the mesorah chain */
.crown-badge { fill: #8a6d1d; opacity: .9; pointer-events: none; }

/* Archaeology dig-mark badge: a small trowel-triangle on the node corner */
.arch-badge { fill: var(--archaeology-ink); opacity: .8; }
.arch-badge:hover { opacity: 1; }

/* Event markers: slim clickable diamonds at the event's AM year */
.event-marker .event-diamond { fill: var(--archaeology-ink); opacity: .7; stroke: #7f1d1d; stroke-width: 1; }
.event-marker .event-label { fill: #96524a; font-style: italic; }
.event-marker:hover .event-diamond { opacity: 1; }
.event-marker:hover .event-label { fill: var(--archaeology-ink); }
svg.spot .layer-events { opacity: .25; }

.swim-undated text { fill: var(--dim); font-style: italic; }
.tenure-undated:hover text { fill: var(--accent); }
.layer-swim a { transition: opacity .15s ease; }
svg.spot .layer-swim a.swim-inst:not(.lit):not(.line) { opacity: .35; }

/* Edges & grid */
.edge { pointer-events: none; }
.edge-spine { stroke: var(--accent); stroke-width: 3.5; }
/* written transmission — the Torah traveled by letter here, not by hand */
.edge-written { stroke: var(--accent); stroke-width: 2.5; stroke-dasharray: 9 6; }
.edge-branch { stroke: #a2947a; stroke-width: 1.4; opacity: .5; }
/* author → book: short solid link in the book tone */
.edge-author { stroke: #64748b; stroke-width: 2; opacity: .75; }
/* book → book lineage (based_on): dashed, book tone */
.edge-basedon { stroke: #64748b; stroke-width: 2.2; stroke-dasharray: 4 4; opacity: .8; }
/* inferred reception — deduced from era and academy, not attested:
   unmistakably conjectural (fine dotted, neutral, faint). Joins the
   spotlight like any edge; the dots keep it readable as conjecture. */
.edge-inferred { stroke: #8b8fa0; stroke-width: 1.6; stroke-dasharray: 2 5; stroke-linecap: round; opacity: .55; }
.grid { stroke: #e9e6db; stroke-width: 1.2; }
/* Century gridlines: static build-time full-width hairlines, first content
   layer (under the cord, edges, bands and nodes) — very low contrast, no
   labels (the screen-space year ruler carries those) */
.layer-gridlines { pointer-events: none; }
.gridline-century { stroke: #ddd6c6; stroke-width: 1; opacity: .35; }

/* Graduated lineage spotlight (hover or sticky selection), three tiers:
   tier 0 — the figure + direct teachers/students: full-saturation olive
            (incoming) / brick (outgoing) edges with arrowheads;
   tier 1 — the whole transmission line, transitively up and down: muted
            green/red threads; node/edge opacity carries a distance falloff
            (inline, set by the client);
   tier 2 — everything off the line fades far back.
   Background layers are untouched. */
.layer-nodes a, .edge { transition: opacity .15s ease; }
svg.spot .layer-nodes a:not(.lit):not(.line) { opacity: .2; }
svg.spot .edge:not(.lit):not(.line-e) { opacity: .1; }
.edge.lit-t { stroke: #5c6e3d; opacity: 1; stroke-width: 2.6; }
.edge.lit-s { stroke: #a04432; opacity: 1; stroke-width: 2.6; }
.edge.line-t { stroke: #8a9668; stroke-width: 1.7; }
.edge.line-s { stroke: #b3826f; stroke-width: 1.7; }
.layer-nodes a.lit-self rect { stroke: var(--accent); stroke-width: 2.8; }

/* Membership tethers: dual citizens' node↔tenure-block link — resting canvas
   stays calm; the client toggles .ton while that person is hovered/selected */
.tether { stroke: #7a5c2e; stroke-width: 1.7; stroke-dasharray: 3 5; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
.tether.ton { opacity: .85; }
.layer-swim a.tenure.lit rect { stroke: var(--accent); stroke-width: 2; fill: #eee0bc; }
.layer-swim a.tenure-uncertain.lit rect { fill: url(#hatch-uncertain); }
/* in-band succession connectors between tenure blocks */
.edge-inband { stroke-width: 1.8; }

/* Trace navigation: current position ring + landing pulse.
   The pulse is an OBVIOUS grow-and-shrink of the whole element (both
   dual-presence representations get it synchronously), purely cosmetic:
   it never gates input — pan/zoom/hover during a pulse just work. */
.trace-here rect:not(.bn-ring) { stroke: #1e2430 !important; stroke-width: 3.4; }
.pulse {
  animation: dual-pulse 1.2s ease-in-out;
  transform-box: fill-box; transform-origin: center;
  pointer-events: auto;
}
@keyframes dual-pulse {
  0%, 100% { transform: scale(1); }
  18% { transform: scale(1.12); }
  40% { transform: scale(1); }
  58% { transform: scale(1.12); }
  80% { transform: scale(1); }
  90% { transform: scale(1.05); }
}
#trace-nav[hidden], #lineage-strip[hidden], #minimap[hidden] { display: none; }
#trace-nav {
  position: absolute; top: 3.4rem; right: .9rem; z-index: 6;
  display: flex; align-items: center; gap: .3rem;
  padding: .25rem .6rem; background: rgba(255, 255, 255, .93);
  border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 1px 6px rgba(30, 36, 48, .08); font-size: .85rem;
}
#trace-nav button {
  font: inherit; padding: 0 .5rem; border: 1px solid var(--line);
  background: var(--card); border-radius: 6px; cursor: pointer;
}
#trace-nav button:hover { border-color: var(--accent); color: var(--accent); }
#trace-label { color: var(--dim); max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Lineage strip: the selected figure's whole line as a readable list */
#lineage-strip {
  position: absolute; top: 6.2rem; right: .9rem; bottom: 14.5rem; z-index: 6; /* clears the minimap */
  width: 240px; display: flex; flex-direction: column;
  background: rgba(255, 255, 255, .96); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 2px 14px rgba(30, 36, 48, .14);
}
#lineage-strip .strip-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: .3rem .4rem .3rem .8rem; border-bottom: 1px solid var(--line);
  font-size: .85rem; color: var(--accent);
}
#strip-close { font: inherit; border: none; background: none; color: var(--dim); cursor: pointer; padding: 0 .4rem; border-radius: 6px; }
#strip-close:hover { color: var(--accent); }
#strip-list { flex: 1; min-height: 0; overflow-y: auto; list-style: none; margin: 0; padding: .4rem .7rem .8rem; }
.strip-row { padding: .15rem .4rem; border-radius: 6px; cursor: pointer; line-height: 1.25; }
.strip-row:hover { background: #f4eddc; }
.strip-row .strip-name { display: block; font-size: .85rem; color: var(--ink); }
.strip-row .strip-meta { display: block; font-size: .7rem; color: var(--dim); }
.strip-row.strip-self { background: #f4eddc; border: 1px solid var(--accent); }
.strip-row.strip-sib .strip-name { color: #6b6254; }
.strip-row.strip-here { outline: 2px solid #1e2430; }
.strip-icon { color: #64748b; }
.strip-link { padding: 0 .9rem; font-size: .8rem; line-height: .9; user-select: none; }
.strip-link.k-solid { color: var(--accent); }
.strip-link.k-branch { color: #a2947a; }
.strip-link.k-dash { color: var(--accent); }
.strip-link.k-book { color: #64748b; }
.strip-link.k-dot { color: #8b8fa0; }
.strip-link.k-sem { color: #5b3a8e; }
.strip-link.k-semx { color: #b8860b; }
.strip-more button {
  font: inherit; font-size: .72rem; color: var(--dim); background: none;
  border: 1px dashed var(--line); border-radius: 999px; padding: 0 .5rem;
  cursor: pointer; margin: .1rem 0 .1rem .4rem;
}
.strip-more button:hover { color: var(--accent); border-color: var(--accent); }
.strip-dual {
  font-size: .72rem; color: #7c4a56; font-style: italic;
  padding: .1rem .4rem .3rem; border-bottom: 1px dashed var(--line); margin-bottom: .25rem;
}

/* Clickable lines: invisible wide hit twins above the edge artwork.
   Boxes/bands (later layers) still win the pointer where they overlap. */
.edge-hit { stroke: transparent; stroke-width: 10; fill: none; pointer-events: stroke; cursor: pointer; }
/* Edge selection: the chosen line brightens, the rest of the canvas dims —
   mutually exclusive with the node spotlight (selecting one clears the other) */
svg.espot .edge:not(.esel) { opacity: .12; }
svg.espot .layer-nodes a, svg.espot .layer-swim .swim, svg.espot .layer-cord, svg.espot .layer-semicha { opacity: .35; }
.edge.esel { opacity: 1 !important; stroke-width: 4.2; filter: drop-shadow(0 0 2px rgba(122, 92, 46, .55)); }

/* ONE VISUAL DIALECT for every popover — gloss cards, edge chip, help —
   anchored to the institution hover card's material: warm white, hairline
   border, 10px radius, soft shadow, and a thin KIND-COLORED accent rule
   along the top edge (--pop-accent: gold persons, slate texts, rose rulers,
   purple semicha holders, the institution tone for academies). */
#edge-chip[hidden], #gloss-card[hidden], #chip-note[hidden] { display: none; }
.pop {
  background: rgba(255, 255, 255, .98); border: 1px solid var(--line); border-radius: 10px;
  border-top: 3px solid var(--pop-accent, var(--accent));
  box-shadow: 0 4px 18px rgba(30, 36, 48, .18);
  font-size: .8rem; line-height: 1.4; color: var(--ink);
}
#edge-chip {
  position: absolute; z-index: 8; width: 300px; padding: .5rem .65rem;
}
.ec-head { font-weight: bold; color: var(--ink); display: flex; align-items: center; gap: .4rem; }
.ec-swatch { width: .8em; height: .8em; border-radius: 3px; flex: none; display: inline-block; }
.ec-basis { margin: .3rem 0; color: var(--dim); font-size: .74rem; line-height: 1.35; }
.ec-basis.ec-standing { font-style: italic; }
.ec-note { display: block; font-size: .7rem; margin-top: .1rem; }
.ec-fromto, .ec-follow { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .3rem; align-items: center; }
.ec-jump {
  font: inherit; font-size: .74rem; color: var(--accent); background: var(--card);
  border: 1px solid var(--line); border-radius: 999px; padding: .05rem .55rem; cursor: pointer;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ec-jump:hover { border-color: var(--accent); }

/* Hover gloss cards: two-phase entrance — fast fade to ~0.92 (gc-in), then
   solidify to 1.0 + shadow ~250ms later (gc-solid); quick fade-out. */
#gloss-card {
  position: absolute; z-index: 7; width: 320px;
  padding: .55rem .7rem;
  opacity: 0; box-shadow: 0 1px 4px rgba(30, 36, 48, .08);
  transition: opacity .16s ease, box-shadow .25s ease;
}
#gloss-card.gc-in { opacity: .92; }
#gloss-card.gc-solid { opacity: 1; box-shadow: 0 4px 18px rgba(30, 36, 48, .22); }
.gc-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.gc-name { font-weight: bold; color: var(--ink); font-size: .92rem; }
.gc-heb { color: var(--accent); text-align: right; }
.gc-era { margin-top: .15rem; }
.gc-rule { border-top: 1px solid var(--line); margin: .4rem 0 .3rem; }
.gc-meta { color: var(--dim); font-size: .72rem; }
.gc-sum {
  margin: .35rem 0; color: var(--ink); font-size: .76rem;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.gc-sum.gc-fade { /* soft fade at the clamp, never an abrupt cut */
  -webkit-mask-image: linear-gradient(180deg, #000 62%, transparent 99%);
  mask-image: linear-gradient(180deg, #000 62%, transparent 99%);
}
.gc-ref { padding: 0 .35rem; }
.gc-foot { margin-top: .25rem; border-top: 1px solid var(--line); padding-top: .25rem; }
.gc-badges { display: flex; flex-wrap: wrap; gap: .25rem; margin: .3rem 0; }
.gc-badge {
  font-size: .68rem; color: var(--dim); border: 1px solid var(--line);
  border-radius: 999px; padding: 0 .5rem; background: #f6f3ea;
}
.gc-badge.gc-sem { color: #5b3a8e; }
.gc-badge.gc-rg { color: #7c4a56; }
/* year-less head: the honest word on the hatched placement */
.gc-line.gc-uncertain { font-style: italic; }
.gc-line { font-size: .72rem; color: var(--dim); margin: .25rem 0; }
/* open page ↗ — the one sanctioned navigation path, on EVERY node card
   (person / text / event / institution): a full-width padded row, ≥32px
   tall, never bare text (a comfortable target, same dialect everywhere). */
.gc-open {
  display: flex; align-items: center; min-height: 32px;
  margin: .05rem -.35rem -.3rem; padding: .15rem .35rem;
  font-size: .74rem; color: var(--accent); border-radius: 6px;
}
.gc-open:hover, .gc-open:focus-visible { background: rgba(122, 92, 46, .08); }

/* Dual-presence wording rides visibly on the open-page chip — and turns the
   chip into the shared light card material (the dark pill stays only for the
   plain one-line "open page" affordance). Rose accent = the duality tone. */
#chip-note { display: block; font-size: .72rem; color: #7c4a56; font-style: italic; margin-bottom: .1rem; }
#open-chip.has-note {
  background: rgba(255, 255, 255, .98); color: var(--ink);
  border: 1px solid var(--line); border-top: 3px solid #7c4a56; border-radius: 10px;
  padding: .35rem .75rem; text-align: left; white-space: normal;
  width: max-content; max-width: 280px;
  box-shadow: 0 4px 18px rgba(30, 36, 48, .18);
}
#open-chip.has-note:hover { background: #fdfcf8; }
#open-chip.has-note .chip-open { color: var(--accent); font-size: .78rem; }

/* CONJECTURE VIEW: everything below is pre-rendered at build and hidden;
   the chip only flips svg.conj — the strict canvas never changes. Inferred
   edges get promoted to chain prominence (still dotted, never solid). */
svg .layer-conj { display: none; }
svg.conj .layer-conj { display: inline; }
svg.conj .edge-inferred { stroke: #4d5470; stroke-width: 2.8; opacity: .95; }
.cord-ghost { fill: none; stroke-width: 4.5; opacity: .3; stroke-dasharray: 3 7; stroke-linecap: round; }
.conj-rule { stroke: #4d5470; stroke-width: 1.6; stroke-dasharray: 4 6; opacity: .55; }
.conj-note text { fill: #5a6070; font-style: italic; }
.conj-note .conj-title { font-weight: bold; font-style: normal; }
.conj-ring { stroke: #4d5470; stroke-width: 2; stroke-dasharray: 4 5; opacity: .8; }
.conj-caption { fill: #4d5470; font-style: italic; }
.map-controls .layer-chip-conj[aria-pressed="true"] { background: #4d5470; color: #f4efe2; border-color: #4d5470; }
#conj-banner[hidden] { display: none; }
#conj-banner {
  position: absolute; top: 5.7rem; left: 50%; transform: translateX(-50%); z-index: 10;
  padding: .22rem 1.1rem; border-radius: 999px; white-space: nowrap;
  background: #3f4658; color: #f4efe2; font-size: .74rem; font-weight: bold;
  letter-spacing: .08em; box-shadow: 0 2px 10px rgba(30, 36, 48, .3);
}
#conj-panel[hidden] { display: none; }
#conj-panel {
  position: absolute; top: 8rem; left: 50%; transform: translateX(-50%); z-index: 8;
  width: 420px; max-width: calc(100% - 2rem); padding: .5rem .8rem;
  --pop-accent: #4d5470; font-size: .76rem;
}
#conj-panel p { margin: .25rem 0; }
.cj-head { font-weight: bold; display: flex; justify-content: space-between; align-items: center; }
#conj-close { border: none; background: none; color: var(--dim); cursor: pointer; font: inherit; padding: 0 .3rem; }
#conj-close:hover { color: var(--accent); }

/* Minimap: static silhouette + live viewport box */
#minimap {
  position: absolute; right: .9rem; bottom: 2.6rem; z-index: 5;
  width: 148px; background: rgba(255, 255, 255, .92);
  border: 1px solid var(--line); border-radius: 8px;
  box-shadow: 0 1px 6px rgba(30, 36, 48, .12);
  overflow: hidden; cursor: crosshair; touch-action: none;
}
#minimap .mini-svg { display: block; width: 100%; height: auto; max-height: 190px; }
#mini-view {
  position: absolute; border: 1.5px solid var(--accent);
  background: rgba(122, 92, 46, .12); border-radius: 2px; pointer-events: none;
}

/* Year ruler: a slim screen-space gutter pinned to the viewport's left edge.
   Overlay chrome (like the era HUD) — NOT part of the pannable canvas: it
   never intercepts the pointer and never eats content width. The client
   rebuilds ticks only when the visible set changes and repositions them
   with cheap transforms on every render frame. */
#year-ruler {
  position: absolute; top: 0; bottom: 0; left: 0; width: 64px;
  z-index: 4; pointer-events: none; overflow: hidden;
}
.yr-tick { position: absolute; top: 0; left: 0; width: 100%; will-change: transform; }
.yr-tick::before { content: ''; position: absolute; left: 0; top: 0; height: 1.5px; background: #b3a58a; opacity: .75; }
.yr-minor::before { width: 7px; opacity: .45; }
.yr-major::before { width: 13px; }
.yr-am, .yr-civil {
  display: block; width: max-content; max-width: 64px;
  padding: 0 .3rem 0 2px; margin-left: 1px; border-radius: 3px;
  background: rgba(250, 249, 246, .85);
}
.yr-am { font-size: .72rem; line-height: 1.25; color: var(--dim); margin-top: 2px; }
.yr-civil { font-size: .6rem; line-height: 1.2; color: #a89f8d; font-style: italic; }
/* narrow containers (<700px): AM-only labels — the ruler never widens */
#year-ruler.yr-narrow .yr-civil { display: none; }

/* Era HUD: which stretch of history is under the viewport center */
#era-hud {
  position: absolute; top: 3.4rem; left: 50%; transform: translateX(-50%);
  z-index: 5; padding: .3rem 1.1rem;
  background: rgba(255, 255, 255, .93); border: 1px solid var(--line);
  border-radius: 999px; box-shadow: 0 1px 6px rgba(30, 36, 48, .08);
  font-size: .98rem; color: #6b6254; white-space: nowrap;
}
#era-hud .hebrew { margin-left: .55rem; color: #a89f8d; }
/* the year at the viewport's vertical center — prominent, seam-aware */
#era-hud-year { font-weight: bold; color: var(--ink); margin-right: .6rem; padding-right: .6rem; border-right: 1px solid var(--line); }
#era-hud.hud-in { animation: hud-in .15s ease; }
@keyframes hud-in {
  from { opacity: .15; transform: translate(-50%, -4px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

#open-chip {
  position: absolute; z-index: 6; transform: translateX(-50%);
  padding: .1rem .7rem; font-size: .82rem; text-decoration: none;
  color: var(--card); background: var(--accent);
  border-radius: 999px; box-shadow: 0 1px 5px rgba(30, 36, 48, .25);
  white-space: nowrap;
}
#open-chip:hover { background: #5f4722; }

/* Axis & right-gutter annotations */
.axis-label { fill: var(--dim); }
.axis-ce { fill: #a89f8d; }
/* pre-seam civil sub-labels: SO conversion + re-anchored ≈ estimate */
.axis-sub { fill: #b5ad9b; font-style: italic; }
.era-corner .era-name { fill: #a89f8d; }
.era-corner .era-heb { fill: #bcb4a2; }
.seam-note text { fill: #c2410c; }

/* Semicha — the third chain: ordination, a chain of hands, not of teaching.
   Deep purple = accepted; amber slightly-dashed = performed but not accepted
   (Sanhedrin 14a). The Semicha layer chip hides everything here. */
.edge-semicha { stroke: #5b3a8e; stroke-width: 2.4; opacity: .8; }
.edge-semicha-x { stroke: #b8860b; stroke-width: 2.2; stroke-dasharray: 10 5; opacity: .85; }
.layer-semicha { pointer-events: none; }
.layer-semicha a { pointer-events: auto; }
.semicha-trunk-label { fill: #8a76a8; letter-spacing: .18em; opacity: .7; }
.semicha-band { fill: #5b3a8e; opacity: .06; }
.semicha-band-label { fill: #5b3a8e; opacity: .75; font-style: italic; }
.semicha-spark, .semicha-badge text { fill: #5b3a8e; }
.semicha-revival-label { fill: #5b3a8e; font-style: italic; opacity: .8; }
.semicha-badge circle { fill: #5b3a8e; }
.semicha-traditional circle { fill: none; stroke: #5b3a8e; stroke-width: 1.4; }
.semicha-revival-mark:hover .semicha-spark { fill: #3d2465; }

svg.hide-semicha .edge-semicha, svg.hide-semicha .edge-semicha-x,
svg.hide-semicha .semicha-badge, svg.hide-semicha .layer-semicha { display: none; }

/* Sof hora'ah — end of direct person-to-person transmission: a quiet
   threshold in the ink tone (base layer; never hidden by mode or layers) */
.layer-sof { pointer-events: none; }
.sof-rule { stroke: #3f4658; stroke-width: 1.3; stroke-dasharray: 12 7; opacity: .5; }
.sof-note text { fill: #3f4658; opacity: .85; }
.sof-note .sof-title { font-style: italic; }
.layer-seam a { cursor: pointer; }

/* Traditional mode hides academic labels and the seam */
svg.mode-traditional .axis-ce,
svg.mode-traditional .node-dates-ce,
svg.mode-traditional .layer-seam { display: none; }

/* Mesorah chain rows on entity pages */
dl.mesorah-chain { border-left: 3px solid var(--accent); padding-left: .8rem; }
dl.mesorah-chain dt { color: var(--accent); font-weight: bold; }

/* ---- Teachings tab (mined dicta on person pages) ---- */
.t-counts { margin-bottom: .4rem; }
.t-formulas { line-height: 2; }
.t-formulas .dim { font-size: .78rem; margin: 0 .5rem 0 .15rem; }
.formula-chip { background: #efe9db; color: var(--accent); }
h3.t-book { font-size: .95rem; margin: 1.6rem 0 .4rem; color: var(--ink); }
ol.teaching-list { list-style: none; margin: 0; padding: 0; }
li.teaching { background: var(--card); border: 1px solid var(--line); border-radius: 6px; padding: .55rem .8rem; margin: .5rem 0; }
.t-head { font-size: .88rem; margin-bottom: .3rem; }
.t-tradent { color: var(--dim); font-style: italic; margin-left: .4rem; }
.t-flag { background: var(--reconstruction); color: var(--reconstruction-ink); }
.t-ambiguous { background: var(--archaeology); color: var(--archaeology-ink); }
.t-class { background: var(--rabbinic); color: var(--rabbinic-ink); }
.t-summary { color: var(--dim); font-size: .88rem; margin-top: .2rem; }
li.teaching .hebrew { display: block; text-align: right; }
details.t-more summary { cursor: pointer; }
details.t-more summary .hebrew { display: inline; }
details.t-more[open] summary { display: none; }

/* Confluence monuments — where the oral river becomes a book. Warm parchment
   plaques (against the cool slate of ordinary books) with a double border:
   "a BOOK was born here" at any zoom. Static build-time geometry; the Texts
   layer hides them along with every other text (they carry node-text). */
.node-monument rect.book-cover { fill: #f6efdc; stroke: #6b5a33; stroke-width: 2.8; }
.node-monument .monument-ring { stroke: #6b5a33; stroke-width: 1.3; opacity: .55; }
.node-monument .node-name { fill: #3d3423; font-weight: bold; }
.node-monument .node-heb { fill: #6b5a33; }
.node-monument:hover rect.book-cover { fill: #efe4c8; stroke: #4a3d20; }
.layer-nodes a.node-monument.lit-self rect.book-cover { stroke: #4a3d20; stroke-width: 3.6; }

/* Confluence cord connectors: feeding strands converge into a monument's top
   edge (in), continuing feeders flow out beneath it (out), and the strands
   that die at sof-hora'ah wind INTO the Bavli instead of merely stopping
   (wind). Strand-colored, behind the plaques; hidden with the Texts layer. */
.layer-confluence { pointer-events: none; }
.cord-conf { fill: none; stroke-linecap: round; }
.cord-conf-in { stroke-width: 3; opacity: .55; }
.cord-conf-wind { stroke-width: 3.2; opacity: .65; }
.cord-conf-out { stroke-width: 2.6; opacity: .4; }
svg.hide-texts .layer-confluence { display: none; }

/* Rambam's numbered links: a circled generation number riding each chain
   node's top-center — a bead where the incoming reception edge lands.
   Plain circle+text: zooms geometrically, always in the DOM. */
.gen-badge circle { fill: #fdf6e7; stroke: var(--accent); stroke-width: 1.6; }
.gen-badge text { fill: var(--accent); font-weight: bold; }

/* The gloss card's foundation line for texts ("stands on N transmitters
   across M generations") — computed at build, printed verbatim */
.gc-found { font-style: italic; color: var(--accent); }

/* The Sefarim rail — the dedicated left-shore band all texts live in
   (mirrored two-shores: people fan right, books and institutions left).
   Book-toned cousin of the academy bands; hides with the Texts layer. */
.layer-serail { pointer-events: none; }
.serail-band { fill: #eef1f6; stroke: #64748b; stroke-width: 1.2; stroke-dasharray: 6 3; opacity: .75; }
.serail-head { fill: #55617a; }
.serail-side { fill: #aab6c9; font-size: 40px; letter-spacing: .25em; opacity: .55; }
svg.hide-texts .layer-serail { display: none; }

/* Lineage cord: chip visibility + strand identity.
   The "Lineage cord" chip flips svg.hide-cord like every other layer chip;
   the confluence connectors and conjecture ghost strands live INSIDE
   .layer-cord, so the whole cord hides as one. The cord itself stays
   pointer-events: none — only the transparent .cord-hit twins (same
   geometry, wide invisible stroke) take pointer events, and only for the
   HOVER gloss: they are not anchors and not .edge-hit, so a click on a
   strand behaves exactly like empty canvas, and every interactive layer
   paints above the cord, so clicks over nodes and edges land there. */
svg.hide-cord .layer-cord { display: none; }
.cord-hit { fill: none; stroke: #000; stroke-opacity: 0; stroke-width: 16; stroke-linecap: round; pointer-events: stroke; }

/* ---- Anchor-event banners (scope: banner): faint repeating-text tapes -----------
   A thin watermark-opacity hairline across the full canvas at the event's
   AM, the event's name · year · Hebrew name repeating along the whole line
   in equally light text — light and transparent, but present and obvious:
   a boundary you notice at any zoom, never a heavy divider. Tones stay but
   pale: churban red-brown, founding bronze/gold, neutral dark. The wide
   transparent hit line makes the tape clickable — clicks open the event's
   gloss card, never navigate. */
.layer-event-banners a { cursor: pointer; }
.event-banner-line { stroke-width: 1.2; opacity: .3; pointer-events: none; }
.event-banner-hit { stroke: #000; stroke-opacity: 0; stroke-width: 18; pointer-events: stroke; }
.event-banner-tape { font-style: italic; letter-spacing: .06em; opacity: .35; pointer-events: none; white-space: nowrap; }
.banner-churban .event-banner-line { stroke: #7d3325; }
.banner-churban .event-banner-tape { fill: #7d3325; }
.banner-founding .event-banner-line { stroke: #8a6d1d; }
.banner-founding .event-banner-tape { fill: #8a6d1d; }
.banner-neutral .event-banner-line { stroke: #474c57; }
.banner-neutral .event-banner-tape { fill: #474c57; }
.event-banner:hover .event-banner-line { opacity: .65; }
.event-banner:hover .event-banner-tape { opacity: .7; }
svg.spot .layer-event-banners { opacity: .25; }

/* ---- Anchor-event spans (scope: span): full-width shaded washes ------------------
   A very low-contrast gray-blue tint — a distinct hue from the warm era
   wash — painted with the era layer, so the band sits UNDER all content.
   Name label at the band's left inside edge; click opens the gloss card. */
.layer-event-spans a { cursor: pointer; }
.event-span-band { fill: #64748b; opacity: .07; }
.event-span:hover .event-span-band { opacity: .12; }
.event-span-label { fill: #64748b; font-style: italic; opacity: .8; }

/* banners & spans toggle with the events/archaeology layer chip, exactly
   like the diamond markers (hide-arch already owns .layer-events) */
svg.hide-arch .layer-event-banners, svg.hide-arch .layer-event-spans { display: none; }

/* event gloss cards: the claims themselves ride the card (summary above),
   scrollable when long, each with its sources beneath */
.gc-claims { max-height: 200px; overflow-y: auto; margin: .3rem 0; border-top: 1px dashed var(--line); padding-top: .25rem; }
.gc-claim { font-size: .72rem; color: var(--ink); margin: 0 0 .35rem; }
.gc-claim-src { display: block; font-size: .68rem; color: var(--dim); font-style: italic; margin-top: .1rem; }

/* ---- HUD time bar: screen-space scrubber attached below the era HUD --------------
   The black track IS the full canvas AM range; the handle marks the
   viewport's center with a compact seam-aware date label riding beside it.
   Era boundaries segment the track as whisper-subtle ticks — the line reads
   black. Chrome, not canvas: pointer events live on the bar alone. */
#time-bar[hidden] { display: none; }
#time-bar {
  position: absolute; top: 5.55rem; left: 50%; transform: translateX(-50%); z-index: 5;
  width: 340px; max-width: calc(100% - 2rem);
  padding: 8px 0 16px; cursor: pointer; touch-action: none;
}
#time-bar .tb-track { position: relative; height: 2px; background: #1e2430; border-radius: 1px; }
.tb-era-tick { position: absolute; top: -2px; width: 1px; height: 6px; background: #1e2430; opacity: .3; }
.tb-handle {
  position: absolute; top: -4px; left: 0; width: 10px; height: 10px; border-radius: 50%;
  background: #1e2430; transform: translateX(-50%);
  box-shadow: 0 1px 3px rgba(30, 36, 48, .4), 0 0 0 2px rgba(250, 249, 246, .8);
}
.tb-label {
  position: absolute; top: 9px; left: 0; transform: translateX(-50%); white-space: nowrap;
  font-size: .66rem; line-height: 1.2; color: var(--ink);
  background: rgba(250, 249, 246, .92); padding: 0 .35rem; border-radius: 3px;
}
/* the conjecture chrome steps below the time bar */
#conj-banner { top: 7.6rem; }
#conj-panel { top: 9.8rem; }

/* ---- Exilarchs in the Davidic column: one royal-continuity band -------------------
   The exilarchate's tenure blocks merge into Malchut Beit David's band —
   the kings run to the churban, the exilarchs begin in Bavel. Exilarch
   blocks read as DIGNIFIED DEEP RED (distinct from the royal band's rose
   tones): the office is the headline, the individual's name in small type
   beneath — and by the degrade ladder the name is the last thing standing. */
.tenure-exilarch rect, .swim-royal .tenure.tenure-exilarch rect { fill: #7a2621; stroke: #4f1713; }
.tenure-exilarch:hover rect, .swim-royal .tenure.tenure-exilarch:hover rect { fill: #8c332c; stroke: #2f0d0b; }
.tenure-exilarch .tenure-title { fill: #f3e2d0; letter-spacing: .02em; }
.tenure-exilarch .tenure-name { fill: #f8ece1; }
.tenure-exilarch .tenure-years { fill: #dcb9a9; }
.layer-swim a.tenure.tenure-exilarch.lit rect { fill: #8c332c; stroke: var(--accent); stroke-width: 2; }

/* The in-band divider where the exilarchate begins: a fine red rule with a
   two-line label — it IS the exilarchate's band anchor now (hover/click open
   its gloss card, which states the continuity claim; never navigation). */
.swim-divider { cursor: pointer; }
.swim-divider-hit { fill: transparent; }
.swim-divider-rule { stroke: #7a2621; stroke-width: 1.6; stroke-dasharray: 2 4; opacity: .8; }
.swim-divider-label { fill: #7a2621; }
.swim-divider-sub { fill: #7a2621; font-style: italic; opacity: .85; }
.swim-divider:hover .swim-divider-rule { opacity: 1; stroke-width: 2; }
.swim-divider:hover .swim-divider-label, .swim-divider:hover .swim-divider-sub { fill: #4f1713; }
/* the continuity line on the gloss card */
.gc-line.gc-cont { color: #7a2621; font-style: italic; }

/* ---- Monarch time-slice spotlight -------------------------------------------------
   Reuses the lineage spotlight's dim (svg.spot); svg.slice additionally dims
   the tenure blocks, which the lineage spotlight leaves alone. Contemporary
   tenure blocks carry .sl — full presence WITHOUT the lineage highlight's
   repaint (an exilarch block must stay red when it is merely contemporary). */
svg.slice .layer-swim a.tenure:not(.sl):not(.lit),
svg.slice .layer-swim a.tenure-undated:not(.sl) { opacity: .2; }

/* The time-slice status strip: the trace-nav pill's material (it replaces
   trace-nav in that corner — the two are mutually exclusive states). */
#slice-strip[hidden] { display: none; }
#slice-strip {
  position: absolute; top: 3.4rem; right: .9rem; z-index: 6;
  display: flex; align-items: center; gap: .45rem;
  padding: .25rem .45rem .25rem .8rem; background: rgba(255, 255, 255, .93);
  border: 1px solid var(--line); border-radius: 999px;
  box-shadow: 0 1px 6px rgba(30, 36, 48, .08);
  font-size: .82rem; color: #7c4a56; max-width: min(60%, 34rem);
}
#slice-strip #slice-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#slice-strip #slice-close {
  font: inherit; font-size: 1rem; line-height: 1; padding: 0 .4rem;
  border: none; background: none; color: var(--dim); cursor: pointer; border-radius: 999px;
}
#slice-strip #slice-close:hover { color: var(--accent); }

/* ---- Cord hue families: major/minor split ------------------------------------------
   Strand hue now carries meaning (strandColorMap in lib/map.js: trunk green,
   Nasi purple, prophets blue, Bavel warm, Eretz olive, west warm-neutral).
   Only the ~10 MAJOR strands keep saturated ink; every minor strand ships
   with .cord-minor — muted gray at reduced opacity, texture not competition. */
.cord-strand.cord-minor { opacity: .4; }
.cord-tail.cord-minor { opacity: .14; }

/* ---- Events chip split ---------------------------------------------------------------
   Anchor-event banners, span washes, and diamond markers move OFF the
   Archaeology chip onto their own Events chip (data-layer="events"; missing
   stored key = ON, like every chip). This stylesheet is append-only, so the
   two earlier hide-arch bindings above are NEUTRALIZED here (later
   equal-specificity rules win; g/a elements default to display:inline) and
   the layers re-bind to hide-events. Archaeology keeps only the dig badges. */
svg.hide-arch .layer-event-banners, svg.hide-arch .layer-event-spans { display: inline; }
svg.hide-arch .layer-events { display: inline; }
svg.hide-events .layer-event-banners, svg.hide-events .layer-event-spans { display: none; }
svg.hide-events .layer-events { display: none; }

/* ---- Living-lineages roster (screen-space chrome, .pop material) ---------------------
   One row per MAJOR strand founder in founding order: swatch (the cord's
   actual ink), name, founding AM. Liveness flips client-side against the
   viewport-center year: alive lit · ended strikethrough+dark · not-yet faint. */
#roster-panel[hidden] { display: none; }
#roster-panel {
  position: absolute; top: 3.4rem; left: .9rem; z-index: 6;
  width: 300px; max-width: calc(100% - 2rem); max-height: 62%;
  overflow-y: auto; padding: .45rem .6rem .5rem; font-size: .78rem;
}
#roster-panel .roster-head {
  display: flex; justify-content: space-between; align-items: center;
  font-weight: bold; color: var(--ink); margin-bottom: .3rem;
}
#roster-panel .roster-head button {
  font: inherit; font-size: 1rem; line-height: 1; padding: 0 .35rem;
  border: none; background: none; color: var(--dim); cursor: pointer;
}
#roster-panel .roster-head button:hover { color: var(--accent); }
#roster-list { list-style: none; margin: 0; padding: 0; }
.roster-row {
  display: flex; align-items: baseline; gap: .45rem;
  padding: .18rem .3rem; border-radius: 6px; cursor: pointer;
}
.roster-row:hover { background: #f4eddc; }
.roster-row.roster-sel { background: #efe5cc; outline: 1px solid var(--accent); }
.roster-sw { width: .7em; height: .7em; border-radius: 3px; flex: none; align-self: center; }
.roster-name { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-am { color: var(--dim); font-size: .68rem; flex: none; margin-left: auto; }
.roster-note { color: var(--dim); font-size: .66rem; font-style: italic; flex: none; }
.roster-row.roster-ended .roster-name { text-decoration: line-through; color: #4a4438; }
.roster-row.roster-ended .roster-sw { opacity: .45; }
.roster-row.roster-future { opacity: .45; }
.roster-row.roster-alive .roster-name { font-weight: bold; }
.roster-foot { margin-top: .35rem; color: var(--dim); font-size: .68rem; font-style: italic; }

/* Strand spotlight (roster row click): the chosen founder's strand — its
   cord ink ([data-founder]) and its member nodes (data-strand, stamped at
   build) — stays lit while everything else dims at the lineage spotlight's
   levels. Pure class flips on every svg root; Esc or a second click exits. */
svg.sspot .layer-nodes a:not(.ssel) { opacity: .2; }
svg.sspot .edge { opacity: .1; }
svg.sspot .layer-swim a.swim-inst { opacity: .35; }
svg.sspot .layer-swim a.tenure, svg.sspot .layer-swim a.tenure-undated { opacity: .35; }
svg.sspot .layer-events, svg.sspot .layer-event-banners { opacity: .25; }
svg.sspot .layer-cord .cord-strand:not(.ssel), svg.sspot .layer-cord .cord-tail:not(.ssel),
svg.sspot .layer-cord .cord-conf:not(.ssel), svg.sspot .layer-cord .cord-ghost:not(.ssel) { opacity: .07; }
svg.sspot .cord-strand.ssel { opacity: .95; stroke-width: 5; }
svg.sspot .cord-tail.ssel { opacity: .6; }
svg.sspot .cord-conf.ssel { opacity: .85; }
svg.sspot .layer-nodes a.ssel { opacity: 1; }
svg.sspot .layer-nodes a.ssel rect:not(.bn-ring) { stroke: var(--accent); stroke-width: 2.4; }

/* ---- Search (⌘K / slash): map-chrome field + as-you-type dropdown --------------------
   Screen-space chrome in the top bar area (its own top-right pill — the
   controls bar keeps its width, the era HUD keeps its clear center);
   results glide the camera and pulse the landing — the URL never changes. */
#map-search { position: absolute; top: .95rem; right: .9rem; z-index: 6; display: inline-flex; }
#map-search-input {
  font: inherit; font-size: .82rem; width: 150px;
  padding: .18rem .7rem; border: 1px solid var(--line); border-radius: 999px;
  background: rgba(255, 255, 255, .93); color: var(--ink);
  box-shadow: 0 1px 6px rgba(30, 36, 48, .08);
}
#map-search-input:focus { outline: 2px solid var(--accent); outline-offset: 1px; width: 240px; }
#map-search-results[hidden] { display: none; }
#map-search-results {
  position: absolute; top: calc(100% + .45rem); right: 0; z-index: 9;
  width: 300px; max-height: 330px; overflow-y: auto;
  list-style: none; margin: 0; padding: .25rem;
  background: rgba(255, 255, 255, .98); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 4px 18px rgba(30, 36, 48, .18); font-size: .78rem;
}
#map-search-results li {
  display: flex; align-items: baseline; gap: .4rem;
  padding: .22rem .45rem; border-radius: 6px; cursor: pointer;
}
#map-search-results li:hover, #map-search-results li.ms-act { background: #f4eddc; }
#map-search-results .ms-name { color: var(--ink); font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#map-search-results .ms-heb { color: var(--accent); flex: none; }
#map-search-results .ms-meta { color: var(--dim); font-size: .66rem; margin-left: auto; flex: none; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- mined transmission weights (chains.yaml) --------------------------------
   Weighted strict reception edges carry an inline stroke-width from the
   documented build-time curve (edgeWeightWidth in lib/map.js) — the class
   here only marks them; color and spotlight behavior stay the spine's own.
   .ec-mined is the edge card's honest attested-transmissions line. */
.ec-mined { margin: .3rem 0 0; color: var(--accent); font-size: .7rem; font-style: italic; line-height: 1.35; }

/* ---- Named-lineages roster: the line spotlight -----------------------------------
   Roster rows now name LINEAGES (lib/map.js namedLines: curated founders +
   the auto-derived post-sof-hora'ah restarts), and a row click lights the
   LINE — member nodes, members' tenure blocks, and every edge BETWEEN two
   members — on the existing sspot dim machinery; these two rules lift the
   line's own edges and blocks out of the dim. */
svg.sspot .edge.ssel { opacity: .9; }
svg.sspot .layer-swim a.tenure.ssel { opacity: 1; }

/* ---- Hover time crosshair (screen-space chrome) -----------------------------------
   A thin horizontal guide across the viewport at the pointer's y — overlay
   chrome like the ruler and time bar, pointer-events: none EVERYWHERE, so
   node hovers and clicks pass through untouched. The compact label rides
   beside the cursor (offset, flipping near the right edge, never under the
   pointer) with the HUD's seam-aware wording; the small accent tick echoes
   the height on the left year ruler. */
#time-crosshair[hidden] { display: none; }
#time-crosshair { position: absolute; left: 0; right: 0; top: 0; height: 0; z-index: 4; pointer-events: none; }
#time-crosshair .tc-line { position: absolute; left: 0; right: 0; top: 0; height: 1px; background: #8a7a5c; opacity: .45; }
#time-crosshair .tc-tick { position: absolute; left: 0; top: -1px; width: 15px; height: 2.5px; background: var(--accent); opacity: .85; }
#time-crosshair .tc-label {
  position: absolute; top: -1.5rem; white-space: nowrap;
  font-size: .68rem; line-height: 1.3; color: var(--ink);
  background: rgba(250, 249, 246, .92); border: 1px solid var(--line);
  border-radius: 3px; padding: 0 .35rem;
}
#time-crosshair .tc-label.tc-flip { transform: translateX(-100%); }

/* ---- Analysis tab + site analysis page (appended by the analysis layer) ---- */
.a-stats { display: flex; flex-wrap: wrap; gap: .6rem; margin: .8rem 0 1.2rem; }
.a-stat {
  background: var(--card); border: 1px solid var(--line); border-radius: 6px;
  padding: .5rem .8rem; min-width: 8.5rem; flex: 1 1 8.5rem;
}
.a-stat-value { font-size: 1.25rem; font-weight: bold; color: var(--accent); }
.a-stat-label { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.a-stat-sub { font-size: .78rem; color: var(--dim); }
.a-topic-bars { max-width: 100%; height: auto; display: block; margin: .4rem 0 1rem; }
.a-bar { fill: var(--accent); opacity: .82; }
a:hover .a-bar { opacity: 1; }
.a-bar-other { fill: var(--dim); opacity: .45; }
.a-bar-tannaim { fill: var(--rabbinic-ink); opacity: .75; }
.a-bar-amoraim { fill: var(--biblical-ink); opacity: .75; }
.a-bar-label, .a-bar-count { font: 12px Georgia, serif; fill: var(--ink); }
.a-bar-count { fill: var(--dim); }
.a-bar-sub { font-size: 10px; }
.a-tables { display: flex; flex-wrap: wrap; gap: 1.2rem; align-items: flex-start; }
.a-tables > div { flex: 1 1 15rem; }
.a-tables h3 { margin: .8rem 0 .3rem; font-size: .95rem; }
table.a-table td { font-size: .88rem; }
ul.a-count-list { list-style: none; margin: .2rem 0; padding: 0; }
ul.a-count-list li { padding: .1rem 0; font-size: .92rem; }
table.a-compare td, table.a-compare th { font-size: .88rem; }

/* Portrait: interpretive reconstruction — wears the reconstruction colors so the
   category is visible at a glance, like conjecture styling elsewhere. */
.a-portrait {
  background: var(--reconstruction); border: 1px dashed var(--reconstruction-ink);
  border-radius: 8px; padding: 1rem 1.2rem; margin-top: 1.6rem;
}
.a-portrait h3 { margin: 0 0 .4rem; color: var(--reconstruction-ink); }
.a-portrait-disclaimer {
  font-size: .82rem; font-style: italic; color: var(--reconstruction-ink);
  border-bottom: 1px dashed var(--reconstruction-ink); padding-bottom: .5rem; margin: 0 0 .8rem;
}
.a-portrait p { font-size: .95rem; }
.a-portrait-basis { font-size: .78rem; margin-bottom: 0; }

/* ---- The Person — דמותו (appended by the person layer) ---- */
.person-section .p-intro { color: var(--dim); font-size: .92rem; }
.person-section h3.p-sub { margin: 1.2rem 0 .4rem; font-size: 1rem; }
.person-item .p-summary { font-size: .95rem; margin-bottom: .15rem; }
.person-section .p-more { margin: .3rem 0 .8rem; }
details.p-more { margin: .3rem 0 .8rem; }
details.p-more > summary { cursor: pointer; color: var(--dim); font-size: .88rem; }

/* ---- Person-section category filter (appended) --------------------------------
   Chips mirror the map's layer chips (.map-controls .layer-chip above) —
   same pill geometry, same pressed/unpressed states — but single-select:
   assets/person.js keeps exactly one chip pressed. .p-hidden is the filter's
   only display hook, on items, subsection wrappers, and overflow disclosures. */
.p-filter { display: flex; flex-wrap: wrap; gap: .35rem; margin: .6rem 0 1rem; }
.p-filter-chip {
  font: inherit; font-size: .82rem; padding: .05rem .65rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--card); color: var(--dim); cursor: pointer;
}
.p-filter-chip[aria-pressed="true"] { background: #f4eddc; border-color: var(--accent); color: var(--accent); }
.p-filter-chip[aria-pressed="false"] { opacity: .55; }
.p-filter-chip:hover { border-color: var(--accent); color: var(--accent); }
.p-filter-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.p-filter-count { font-size: .75rem; opacity: .75; }
.person-section .p-hidden { display: none; }

/* ---- Landing page (index.html; appended by the landing layer) ----------------
   The front door. The hero is deliberately dark (deep ink #141210 family)
   regardless of the site's parchment theme; the lineage-cord SVG sits behind
   the text at low opacity, text stays parchment #f1efe8 for contrast. */
body.landing main { max-width: none; padding: 0; }

.hero {
  position: relative; overflow: hidden; text-align: center;
  background: linear-gradient(180deg, #141210 0%, #1b1813 62%, #141210 100%);
  color: #f1efe8; padding: 5.5rem 1.5rem 6.5rem;
}
.hero-cord {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: .4; pointer-events: none;
}
.hero-inner { position: relative; max-width: 46rem; margin: 0 auto; }
.hero-overline {
  text-transform: uppercase; letter-spacing: .35em; font-size: .8rem;
  color: #c9b98a; margin: 0 0 1.5rem;
}
.hero-overline .hebrew { letter-spacing: normal; }
.hero-title {
  font-size: clamp(2.1rem, 6.5vw, 3.6rem); line-height: 1.12;
  margin: 0 0 1.1rem; color: #f1efe8;
}
.hero-sub {
  font-size: clamp(1rem, 2.4vw, 1.15rem); line-height: 1.7;
  color: #d9d3c3; max-width: 38rem; margin: 0 auto 2.2rem;
}
.hero-ctas { display: flex; gap: 1.3rem; justify-content: center; align-items: center; flex-wrap: wrap; margin: 0; }
.hero-cta {
  display: inline-block; background: #c07f28; color: #141210; font-weight: bold;
  padding: .7rem 1.5rem; border-radius: 6px; text-decoration: none; letter-spacing: .02em;
}
.hero-cta:hover { background: #d3922f; }
.hero-alt {
  color: #c9b98a; text-decoration: underline;
  text-decoration-color: rgba(201, 185, 138, .5); text-underline-offset: 3px;
}
.hero-alt:hover { color: #f1efe8; text-decoration-color: #f1efe8; }

/* Stats band: four live numbers computed at build; hairline grid via 1px gaps */
.stats-band {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
  background: var(--line); border-bottom: 1px solid var(--line);
}
.stats-band .stat { background: var(--card); text-align: center; padding: 1.7rem 1rem 1.5rem; }
.stat-value { font-size: 2.1rem; font-weight: bold; color: var(--accent); line-height: 1.15; }
.stat-label {
  font-size: .74rem; text-transform: uppercase; letter-spacing: .07em;
  color: var(--dim); margin-top: .3rem;
}
@media (max-width: 760px) { .stats-band { grid-template-columns: repeat(2, 1fr); } }

/* Feature cards: three doors into the atlas */
.feature-cards {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem;
  max-width: 1100px; margin: 0 auto; padding: 3rem 1.25rem 4.5rem;
}
.feature-card {
  display: block; background: var(--card); border: 1px solid var(--line);
  border-radius: 10px; padding: 1.5rem 1.4rem 1.6rem;
  text-decoration: none; color: var(--ink);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.feature-card:hover { border-color: var(--accent); box-shadow: 0 3px 14px rgba(122, 92, 46, .14); }
.feature-card .feature-icon { color: var(--accent); display: block; }
.feature-card h2 {
  font-size: 1.12rem; text-transform: none; letter-spacing: 0; border-bottom: none;
  color: var(--accent); margin: .7rem 0 .35rem; padding: 0;
}
.feature-card p { font-size: .93rem; line-height: 1.6; margin: 0; color: var(--ink); }
@media (max-width: 820px) { .feature-cards { grid-template-columns: 1fr; } }
