/* Ancestree — a warm, papery family-tree workspace. */

:root {
  --ink:        #2c2620;
  --ink-soft:   #6b6154;
  --ink-faint:  #9a9084;
  --paper:      #f6f1e7;
  --paper-2:    #fffdf8;
  --line:       #d8cbb4;
  --line-soft:  #e7ddca;
  --walnut:     #8a5637;
  --walnut-dk:  #6d422a;
  --sage:       #7c8a6c;
  --gold:       #b3903f;
  --rose:       #b4645f;
  --shadow:     0 1px 2px rgba(58,44,28,.10), 0 6px 18px rgba(58,44,28,.10);
  --shadow-lg:  0 24px 70px rgba(40,30,18,.34);
  --card-w:     180px;
  --card-h:     92px;
  --ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }

/* The browser's own `[hidden] { display: none }` lives in the UA stylesheet, and
   ANY author `display` beats it — origin wins over specificity. Several
   components below set display: flex/grid, which silently resurrects them when
   hidden: the overlays then cover the page at opacity 0 and eat every click.
   Keep this rule, and keep it !important. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  font-family: var(--ui);
  color: var(--ink);
  background: var(--paper);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}


/* --------------------------------------------------------------- top bar */

.topbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 16px;
  background: linear-gradient(180deg, #fffdf8, #f4eee1);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(255,255,255,.7) inset;
  z-index: 30;
}

.brand {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--serif);
  font-size: 19px;
  letter-spacing: .01em;
  color: var(--walnut-dk);
  flex: 0 0 auto;
}

.tree-title {
  flex: 0 1 300px;
  min-width: 120px;
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 7px;
  padding: 6px 9px;
  text-overflow: ellipsis;
}
.tree-title:hover:not(:disabled) { border-color: var(--line-soft); background: rgba(255,255,255,.6); }
.tree-title:focus { outline: none; border-color: var(--gold); background: #fff; }
.tree-title:disabled { color: var(--ink-soft); }

.tools {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.tool-group { display: flex; gap: 6px; }

/* --------------------------------------------------- tree picker + menus */

.tree-id { position: relative; display: flex; align-items: center; gap: 2px; flex: 0 1 auto; }

.tree-menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 9px;
  font-size: 12px;
  color: var(--ink-soft);
}
.tree-menu-btn svg { display: block; }

.tree-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  width: 336px;
  max-height: 70vh;
  overflow-y: auto;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 16px 40px rgba(58,44,28,.22);
  z-index: 50;
  padding: 6px;
}
.tree-menu-head,
.tree-menu-foot {
  display: flex;
  gap: 6px;
  padding: 6px 8px;
  font-family: var(--serif);
  font-size: 11px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.tree-menu-foot { border-top: 1px solid var(--line-soft); margin-top: 4px; padding-top: 8px; }

.tree-list { list-style: none; margin: 0; padding: 0; }
.tree-list li { display: flex; align-items: stretch; gap: 2px; }
.tree-empty { padding: 10px 8px; font-size: 13px; color: var(--ink-faint); font-style: italic; }

.tree-row {
  flex: 1 1 auto;
  min-width: 0;
  text-align: left;
  font: inherit;
  padding: 8px 9px;
  border: none;
  border-radius: 7px;
  background: transparent;
  cursor: pointer;
  color: var(--ink);
}
.tree-row:hover { background: rgba(180,150,90,.12); }
.tree-row.current { background: rgba(180,150,90,.18); }
.tree-row-name {
  display: block;
  font-family: var(--serif);
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tree-row-meta { display: block; font-size: 11px; color: var(--ink-faint); margin-top: 2px; }

.tree-row-del {
  flex: 0 0 auto;
  width: 28px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--ink-faint);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.tree-row-del:hover { background: #f6e2e0; color: #8f3f3a; }

.menu-wrap { position: relative; }
#exportBtn { display: inline-flex; align-items: center; gap: 6px; }
#exportBtn svg { display: block; }

.dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: 250px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 16px 40px rgba(58,44,28,.22);
  z-index: 50;
  padding: 6px;
}
.dropdown.menu-list button {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 8px 10px;
  border: none;
  border-radius: 7px;
  background: transparent;
  cursor: pointer;
  color: var(--ink);
}
.dropdown.menu-list button:hover { background: rgba(180,150,90,.12); }
.dropdown.menu-list strong { display: block; font-weight: 600; font-size: 13px; }
.dropdown.menu-list span {
  display: block;
  font-size: 11.5px;
  color: var(--ink-faint);
  margin-top: 1px;
}

/* ---------------------------------------------------------------- buttons */

.btn {
  font: inherit;
  font-size: 13px;
  padding: 7px 13px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, #fffefb, #f5efe3);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background .13s, border-color .13s, transform .06s, box-shadow .13s;
}
.btn:hover { border-color: var(--gold); box-shadow: 0 1px 3px rgba(58,44,28,.12); }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.btn.primary {
  background: linear-gradient(180deg, #9c6440, var(--walnut));
  border-color: var(--walnut-dk);
  color: #fdf8ef;
}
.btn.primary:hover { background: linear-gradient(180deg, #a86e47, #7c4d31); }
.btn.primary:disabled { opacity: .55; cursor: default; }
/* inline-grid so a glyph and an inline SVG centre identically */
.btn.icon {
  display: inline-grid;
  place-items: center;
  padding: 7px 10px;
  min-width: 34px;
  height: 32px;
  font-size: 14px;
  line-height: 1;
}
.btn.icon svg { display: block; }
.btn.small { font-size: 12px; padding: 5px 10px; }
.zoom-level {
  min-width: 52px;
  height: 32px;
  padding: 7px 6px;
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}
.btn.with-icon { display: inline-flex; align-items: center; gap: 6px; height: 32px; }
.btn.with-icon svg { display: block; }
.btn:disabled {
  opacity: .4;
  cursor: default;
  border-color: var(--line);
  box-shadow: none;
}
.btn:disabled:hover { border-color: var(--line); box-shadow: none; }
.btn.ghost { background: transparent; border-color: transparent; color: var(--ink-soft); }
.btn.ghost:hover { border-color: var(--line); color: var(--ink); box-shadow: none; }

/* ----------------------------------------------------------------- stage */

.stage {
  position: relative;
  flex: 1 1 auto;
  overflow: hidden;
  cursor: grab;
  touch-action: none;
  background-color: var(--paper);
  background-image: radial-gradient(circle at 1px 1px, rgba(120,100,70,.16) 1px, transparent 0);
  background-size: 20px 20px;
}
.stage.panning { cursor: grabbing; }
.stage.linking { cursor: crosshair; }
.stage.linking .card { cursor: crosshair; }

.viewport {
  position: absolute;
  left: 0; top: 0;
  width: 0; height: 0;
  transform-origin: 0 0;
}

.edges, .guides {
  position: absolute;
  left: 0; top: 0;
  width: 1px; height: 1px;
  overflow: visible;
  pointer-events: none;
}

.edge {
  fill: none;
  stroke: #b6a483;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  transition: stroke .12s, stroke-width .12s;
}
/* A couple who could not share a row — one is an ancestor of the other. */
.edge.cross-gen { stroke-dasharray: 7 5; stroke: #a8917a; }

.edge.selected {
  stroke: var(--walnut);
  stroke-width: 3.5;
}

/* Fat invisible twin of each line: a 2px stroke is far too thin to click. */
.edge-hit {
  fill: none;
  stroke: transparent;
  stroke-width: 16;
  stroke-linejoin: round;
  stroke-linecap: round;
  pointer-events: stroke;
  cursor: pointer;
}

.union-mark { fill: var(--gold); opacity: .85; }
.union-mark.cross-gen { fill: #a8917a; }
.guide {
  stroke: var(--rose);
  stroke-width: 1;
  stroke-dasharray: 5 5;
  vector-effect: non-scaling-stroke;
  opacity: .85;
}

.nodes { position: absolute; left: 0; top: 0; }
.nodes.settling .card { transition: transform .42s cubic-bezier(.22,1,.36,1); }

/* ----------------------------------------------------------------- cards */

.card {
  position: absolute;
  left: 0; top: 0;
  width: var(--card-w);
  height: var(--card-h);
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(180deg, var(--paper-2), #f7f1e4);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  cursor: grab;
  user-select: none;
  transition: box-shadow .15s, border-color .15s;
}
.card::before {                    /* the tinted spine down the left edge */
  content: "";
  position: absolute;
  left: 0; top: 10px; bottom: 10px;
  width: 3px;
  border-radius: 3px;
  background: var(--ink-faint);
}
.card[data-gender="f"]::before { background: #b07f9a; }
.card[data-gender="m"]::before { background: #6f8aa8; }
.card[data-gender="x"]::before { background: var(--sage); }

.card:hover { border-color: var(--gold); box-shadow: 0 2px 4px rgba(58,44,28,.12), 0 10px 24px rgba(58,44,28,.14); }
.card:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.card.selected {
  border-color: var(--walnut);
  box-shadow: 0 0 0 2px rgba(138,86,55,.28), var(--shadow);
}
.card.dragging {
  cursor: grabbing;
  box-shadow: 0 10px 30px rgba(58,44,28,.28);
  z-index: 5;
}

.avatar {
  flex: 0 0 auto;
  width: 42px; height: 42px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-size: 15px;
  letter-spacing: .02em;
  color: #fffdf7;
  background: linear-gradient(150deg, #a5744f, #7d4e32);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28);
}
.card[data-gender="f"] .avatar { background: linear-gradient(150deg, #b5849e, #8d5c78); }
.card[data-gender="m"] .avatar { background: linear-gradient(150deg, #7590ad, #4f6c8a); }

/* Initials are uppercase, so they carry no descender — but the line box still
   reserves descender space, which parks the visible letters about a pixel low
   in the circle. Nudge by a font-relative amount so every size is centred. */
.initials {
  display: block;
  transform: translateY(-0.067em);
}

.avatar.has-photo { background: #e6dcc8; overflow: hidden; }
.avatar.has-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}

/* a card lit up as the drop target for a dragged photo */
.card.drop-target {
  border-color: var(--walnut);
  border-style: dashed;
  box-shadow: 0 0 0 3px rgba(138,86,55,.20), var(--shadow);
}
.card.drop-target .avatar { opacity: .5; }

/* Clip as a backstop: a name, a birth surname and a lifespan is a lot for a
   92px card, and a substituted font must not push text out of it. */
.meta { min-width: 0; overflow: hidden; }
.name {
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
/* The surname someone carried before marrying. One line — the card has 72px of
   content height and a two-line name already claims most of it. */
.born {
  font-size: 10px;
  line-height: 1.2;
  color: var(--ink-faint);
  font-style: italic;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 1px;
}
.dates { font-size: 11.5px; color: var(--ink-soft); margin-top: 1px; letter-spacing: .02em; }

.book-btn {
  position: absolute;
  right: 7px; bottom: 7px;
  width: 26px; height: 26px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, color .15s, background .15s;
}
.card:hover .book-btn, .card.selected .book-btn { opacity: 1; }
.book-btn:hover { color: var(--walnut); background: #fff; border-color: var(--line); }


/* ------------------------------------------------------------------ pill */

.pill {
  position: fixed;
  transform: translate(-50%, -100%);
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  background: #fffdf7;
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 8px 22px rgba(58,44,28,.20);
  z-index: 40;
  animation: pop .14s ease-out;
}
@keyframes pop { from { opacity: 0; transform: translate(-50%, -92%); } }
.pill button {
  font: inherit;
  font-size: 12px;
  padding: 5px 9px;
  border: none;
  background: transparent;
  color: var(--ink);
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.pill button:hover { background: #f1e8d6; }
.pill button.danger:hover { background: #f6e2e0; color: #8f3f3a; }
.pill-sep { width: 1px; height: 18px; background: var(--line-soft); margin: 0 3px; }

.edge-pill { transform: translate(-50%, -50%); }
.edge-label {
  padding: 0 6px;
  font-size: 12px;
  color: var(--ink-soft);
  max-width: 190px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ------------------------------------------------------------- statusbar */

.statusbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 7px 16px;
  font-size: 11.5px;
  color: var(--ink-soft);
  background: linear-gradient(180deg, #f4eee1, #efe7d6);
  border-top: 1px solid var(--line);
  z-index: 20;
}
.legend { display: flex; align-items: center; gap: 6px; }
.swatch {
  width: 9px; height: 9px;
  border-radius: 3px;
  display: inline-block;
  margin-left: 6px;
}
.swatch.f { background: #b07f9a; }
.swatch.m { background: #6f8aa8; }
.swatch.x { background: var(--sage); }
.tips { margin-left: auto; text-align: right; }
.statusbar .btn.small { flex: 0 0 auto; }

/* The claim that nothing leaves your browser is only worth making if you can
   go and check it, so the way to the source lives in the app, not just in a
   README nobody opens. */
.source-link {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 1px solid transparent;
  border-radius: 7px;
  color: var(--ink-soft);
  text-decoration: none;
  transition: color .13s, border-color .13s, background .13s;
}
.source-link svg { display: block; }
.source-link:hover {
  color: var(--walnut-dk);
  border-color: var(--line);
  background: #fffdf7;
}
.source-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* ------------------------------------------------------------------ hint */

.hint {
  position: fixed;
  left: 50%;
  bottom: 58px;
  transform: translate(-50%, 12px);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px 9px 16px;
  background: #33291c;
  color: #f7efe0;
  font-size: 13px;
  border-radius: 20px;
  box-shadow: 0 10px 30px rgba(30,22,12,.34);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 60;
}
.hint.show { opacity: 1; transform: translate(-50%, 0); }
/* The toast itself ignores clicks; only the action inside it takes them. */
.hint.show .hint-undo { pointer-events: auto; }

.hint-undo {
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  padding: 4px 12px;
  border: 1px solid rgba(247,239,224,.35);
  border-radius: 14px;
  background: transparent;
  color: #f0c987;
  cursor: pointer;
  white-space: nowrap;
}
.hint-undo:hover { background: rgba(240,201,135,.16); border-color: #f0c987; }

/* ------------------------------------------------------------------ book */

.book-overlay {
  position: fixed;
  inset: 0;
  background: rgba(35,26,16,.55);
  backdrop-filter: blur(3px);
  display: grid;
  place-items: center;
  padding: 24px;
  z-index: 80;
  opacity: 0;
  transition: opacity .22s;
}
.book-overlay.open { opacity: 1; }

.book {
  position: relative;
  display: flex;
  width: min(1000px, 100%);
  height: min(660px, 88vh);
  background: #efe6d2;
  border-radius: 8px;
  box-shadow: var(--shadow-lg);
  padding: 12px;
  gap: 0;
  transform: scale(.94) rotateX(6deg);
  transform-origin: center 65%;
  transition: transform .28s cubic-bezier(.2,1,.3,1);
}
.book-overlay.open .book { transform: none; }

.page {
  flex: 1 1 50%;
  min-width: 0;
  background:
    linear-gradient(180deg, #fffdf6, #fbf6ea);
  padding: 30px 34px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.page-left {
  border-radius: 5px 0 0 5px;
  box-shadow: inset -14px 0 22px -18px rgba(80,60,30,.5);
}
.page-right {
  border-radius: 0 5px 5px 0;
  box-shadow: inset 14px 0 22px -18px rgba(80,60,30,.5);
  transform-origin: left center;
}
.page-right.flip { animation: pageflip .42s ease-out; }
@keyframes pageflip {
  0%   { transform: perspective(1400px) rotateY(-38deg); opacity: .35; }
  100% { transform: perspective(1400px) rotateY(0); opacity: 1; }
}

.spine {
  flex: 0 0 14px;
  background: linear-gradient(90deg, #d9cdb2, #bda98a 45%, #d9cdb2);
  box-shadow: inset 0 0 8px rgba(70,50,25,.35);
}

.close-book {
  position: absolute;
  top: -14px; right: -14px;
  width: 34px; height: 34px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: #fffdf7;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow);
  z-index: 2;
}
.close-book:hover { color: var(--ink); border-color: var(--gold); }

/* left page contents */

.portrait-wrap {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 16px;
}

.portrait {
  position: relative;
  flex: 0 0 auto;
  width: 76px; height: 76px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  overflow: hidden;
  font-family: var(--serif);
  font-size: 25px;
  color: #fffdf7;
  background: linear-gradient(150deg, #a5744f, #7d4e32);
  box-shadow: 0 3px 10px rgba(80,55,30,.28), inset 0 1px 0 rgba(255,255,255,.3);
}
.portrait[data-gender="f"] { background: linear-gradient(150deg, #b5849e, #8d5c78); }
.portrait[data-gender="m"] { background: linear-gradient(150deg, #7590ad, #4f6c8a); }

.portrait-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.portrait.editable { cursor: pointer; }
.portrait-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--ui);
  font-size: 11px;
  letter-spacing: .04em;
  color: #fff;
  background: rgba(45,32,18,.58);
  opacity: 0;
  transition: opacity .15s;
}
.portrait.editable:hover .portrait-overlay,
.portrait.editable:focus-within .portrait-overlay { opacity: 1; }

.portrait-remove {
  font: inherit;
  font-size: 12px;
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fffdf7;
  color: var(--ink-soft);
  cursor: pointer;
}
.portrait-remove:hover { border-color: #c98f8b; color: #93413c; background: #fdf4f3; }

.portrait-tip {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-faint);
  max-width: 130px;
}

.person-name {
  font-family: var(--serif);
  font-size: 26px;
  line-height: 1.2;
  margin: 0 0 18px;
  width: 100%;
  border: none;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--ink);
  padding: 2px 0;
}
input.person-name:hover { border-bottom-color: var(--line); }
input.person-name:focus { outline: none; border-bottom-color: var(--gold); }

.person-fields { display: grid; gap: 3px; margin-bottom: 26px; }
.pf {
  display: grid;
  grid-template-columns: 82px 1fr;
  align-items: center;
  gap: 8px;
  font-size: 13.5px;
}
.pf-label {
  font-family: var(--serif);
  font-size: 12px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.pf-input {
  font: inherit;
  font-size: 13.5px;
  padding: 5px 6px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: var(--ink);
  width: 100%;
}
.pf-input:hover { background: rgba(180,150,90,.09); }
.pf-input:focus { outline: none; background: #fff; border-color: var(--gold); }
.pf-input::placeholder { color: #c3b8a5; }

/* Born / Died date pickers */
.pf-datewrap { display: flex; align-items: center; gap: 6px; min-width: 0; }
.pf-datepick { flex: 0 1 auto; font-variant-numeric: tabular-nums; }
.pf-datetext { flex: 1 1 auto; min-width: 0; font-style: italic; }
.pf-legacy {
  flex: 0 1 auto;
  font-size: 11.5px;
  color: var(--ink-faint);
  font-style: italic;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: 1px dotted var(--line);
  cursor: help;
}

/* Switch a date field between the picker and free text. */
.date-mode {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  margin-left: auto;
  padding: 0;
  font: inherit;
  font-size: 13px;
  line-height: 1;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, color .15s, border-color .15s;
}
.pf:hover .date-mode,
.date-mode:focus-visible { opacity: 1; }
.date-mode:hover { color: var(--walnut); border-color: var(--line); background: #fffdf7; }

/* "Known for": two lines, then ellipsis, with the full text on hover. */
.pf.pf-tall { align-items: start; }
.pf.pf-tall .pf-label { padding-top: 6px; }

.pf-clampwrap {
  font-size: 13.5px;
  line-height: 1.45;
  min-height: calc(2 * 1.45em + 10px);
  padding: 4px 6px;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--ink);
}
/* The clamp itself. Must stay a plain inline child — as a grid/flex item its
   display would be blockified and -webkit-box (which line-clamp needs) lost. */
.pf-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-height: calc(2 * 1.45em);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.pf-clampwrap.editable { cursor: text; }
.pf-clampwrap.editable:hover { background: rgba(180,150,90,.09); }
.pf-clampwrap.editable:focus-visible { outline: none; background: #fff; border-color: var(--gold); }
.pf-clampwrap.empty { color: #c3b8a5; }

textarea.pf-multiline {
  font-family: inherit;
  line-height: 1.45;
  height: calc(2 * 1.45em + 10px);
  resize: vertical;
  min-height: calc(2 * 1.45em + 10px);
}

.toc-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 7px;
  border-bottom: 1px solid var(--line-soft);
  font-family: var(--serif);
  font-size: 12px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.mini-btn {
  font: inherit;
  font-family: var(--ui);
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  padding: 4px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fffdf7;
  color: var(--walnut-dk);
  cursor: pointer;
}
.mini-btn:hover { border-color: var(--gold); background: #fff; }
.mini-btn.danger { color: #93413c; }
.mini-btn.danger:hover { border-color: #c98f8b; background: #fdf4f3; }

.toc { list-style: none; margin: 8px 0 0; padding: 0; }
.toc-empty { font-size: 13px; color: var(--ink-faint); font-style: italic; padding: 8px 0; }
.toc-item {
  display: flex;
  gap: 10px;
  align-items: baseline;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 7px 8px;
  border: none;
  border-left: 2px solid transparent;
  border-radius: 0 5px 5px 0;
  background: transparent;
  cursor: pointer;
  color: var(--ink);
}
.toc-item:hover { background: rgba(180,150,90,.11); }
.toc-item.current { border-left-color: var(--walnut); background: rgba(180,150,90,.15); }
.toc-date { flex: 0 0 auto; font-size: 11.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.toc-title {
  font-family: var(--serif);
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* right page contents */

.entry-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.entry-dates {
  display: flex;
  align-items: center;
  gap: 5px;
  flex-wrap: wrap;
  min-width: 0;
}
.entry-date, .entry-end {
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink-soft);
  letter-spacing: .04em;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 5px;
  padding: 4px 6px;
}
.entry-date:hover, .entry-end:hover { background: rgba(180,150,90,.1); }
.entry-date:focus, .entry-end:focus { outline: none; background: #fff; border-color: var(--gold); }

.date-dash { color: var(--ink-faint); font-family: var(--serif); }

.date-add, .date-clear {
  font: inherit;
  font-family: var(--ui);
  font-size: 11.5px;
  padding: 3px 7px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: var(--ink-faint);
  cursor: pointer;
}
.date-add:hover { color: var(--walnut-dk); border-color: var(--line); background: #fffdf7; }
.date-clear { font-size: 14px; line-height: 1; padding: 2px 6px; }
.date-clear:hover { color: #93413c; border-color: #c98f8b; background: #fdf4f3; }

.entry-warn {
  margin: -6px 0 10px;
  font-size: 12px;
  color: #93413c;
  background: #fdf4f3;
  border: 1px solid #e4c4c1;
  border-radius: 6px;
  padding: 5px 9px;
}

.toc-span { margin-left: 3px; color: var(--gold); font-size: 10px; }

.entry-title {
  font-family: var(--serif);
  font-size: 23px;
  line-height: 1.25;
  margin: 0 0 4px;
  width: 100%;
  border: none;
  border-bottom: 1px solid transparent;
  background: transparent;
  color: var(--ink);
  padding: 2px 0;
}
input.entry-title:hover { border-bottom-color: var(--line); }
input.entry-title:focus { outline: none; border-bottom-color: var(--gold); }
.entry-title::placeholder { color: #cfc4b0; }

.entry-body {
  width: 100%;
  margin-top: 14px;
  font-family: var(--serif);
  font-size: 15.5px;
  line-height: 30px;   /* matches the ruled-line spacing below */
  color: #3b332a;
  background: repeating-linear-gradient(
    transparent, transparent 29px, rgba(150,125,80,.16) 29px, rgba(150,125,80,.16) 30px);
  border: none;
  resize: none;
  overflow: hidden;
  padding: 0;
}
.entry-body:focus { outline: none; }
.entry-body::placeholder { color: #cfc4b0; font-style: italic; }
.page-empty {
  height: 100%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 10px;
  text-align: center;
  color: var(--ink-soft);
  font-family: var(--serif);
}
.page-empty .flourish { font-size: 30px; color: var(--gold); opacity: .6; }
.page-empty p { margin: 0; font-size: 16px; }
/* ---------------------------------------------------------------- dialog */

.dialog-overlay {
  position: fixed;
  inset: 0;
  background: rgba(35,26,16,.5);
  backdrop-filter: blur(2px);
  display: grid;
  place-items: center;
  padding: 24px;
  z-index: 90;
  opacity: 0;
  transition: opacity .18s;
}
.dialog-overlay.open { opacity: 1; }

.dialog {
  width: min(560px, 100%);
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 26px 26px 20px;
  box-shadow: var(--shadow-lg);
}
.dialog-narrow { width: min(420px, 100%); }
.dialog-foot-right { justify-content: flex-end; }
.btn.danger-btn {
  background: linear-gradient(180deg, #b0574f, #91423b);
  border-color: #7d3831;
  color: #fdf5f4;
}
.btn.danger-btn:hover { background: linear-gradient(180deg, #bd6159, #823933); }

.dialog h2 { font-family: var(--serif); font-size: 22px; margin: 0 0 6px; font-weight: 500; }
.dialog-sub { margin: 0 0 18px; font-size: 13.5px; color: var(--ink-soft); line-height: 1.5; }

.dialog-foot {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
}

/* --------------------------------------------------------------- narrow */

@media (max-width: 820px) {
  .tree-title { flex-basis: 150px; }
  .tips { display: none; }
  /* The mark alone still reads, and the anchor keeps its aria-label. */
  .source-link span { display: none; }
  .source-link { padding: 4px 6px; }
  /* .tips was doing the pushing; without it, keep the group on the right. */
  .statusbar .btn.small { margin-left: auto; }
  .book { flex-direction: column; height: 90vh; }
  .spine { display: none; }
  .page-left { border-radius: 5px 5px 0 0; box-shadow: none; border-bottom: 1px solid var(--line); }
  .page-right { border-radius: 0 0 5px 5px; box-shadow: none; }
}

/* Without a mouse there is no hover, so anything revealed by it is invisible.
   Show those controls outright on touch devices. */
@media (hover: none) {
  .book-btn { opacity: 1; }
  .date-mode { opacity: 1; }
  .portrait-overlay {
    opacity: 1;
    inset: auto 0 0 0;
    height: 20px;
    font-size: 9.5px;
    background: rgba(45,32,18,.62);
  }
  .tips { display: none; }
}

/* Phone width: the colour key is the first thing that can go — the card tints
   are legible without it, and the book spells the field out anyway. */
@media (max-width: 600px) {
  .legend { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

.storage-foot { align-items: center; justify-content: space-between; flex-wrap: nowrap; }
.storage-foot .mini-btn { white-space: nowrap; }
.storage-use {
  font-size: 10.5px;
  letter-spacing: 0;
  text-transform: none;
  text-align: right;
  line-height: 1.3;
}

/* ------------------------------------------------------------ zoom menu */

.zoom-menu { width: 224px; right: auto; left: 50%; transform: translateX(-50%); }

.zoom-form {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px 8px;
}
.zoom-form label {
  flex: 0 0 auto;
  white-space: nowrap;
  font-family: var(--serif);
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.zoom-form .mini-btn { flex: 0 0 auto; }
.zoom-input-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
}
.zoom-input-wrap input {
  width: 100%;
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  padding: 5px 20px 5px 7px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fffdf7;
  color: var(--ink);
}
.zoom-input-wrap input:focus { outline: none; border-color: var(--gold); background: #fff; }
.zoom-pct {
  position: absolute;
  right: 7px;
  font-size: 11.5px;
  color: var(--ink-faint);
  pointer-events: none;
}

.zoom-presets {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  padding: 6px 8px 8px;
  border-top: 1px solid var(--line-soft);
}
.zoom-presets button {
  font: inherit;
  font-size: 12px;
  padding: 5px 4px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.zoom-presets button:hover { background: rgba(180,150,90,.14); border-color: var(--line); }

/* ------------------------------------------------------- union states */

/* An unmarried partnership: the usual genealogical dashed line. */
.edge.unwed { stroke-dasharray: 6 4; }

.union-break {
  fill: none;
  stroke: #a8917a;
  stroke-width: 1.8;
  stroke-linecap: round;
}

.union-label {
  font-family: var(--ui);
  font-size: 10px;
  letter-spacing: .03em;
  fill: var(--ink-faint);
  pointer-events: none;
  paint-order: stroke;
  stroke: var(--paper);
  stroke-width: 3px;
  stroke-linejoin: round;
}

.edge-union { display: flex; align-items: center; gap: 4px; }
.edge-union select,
.edge-union .union-date {
  font: inherit;
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fffdf7;
  color: var(--ink);
}
.edge-union .union-date { width: 62px; }
.edge-union select:focus,
.edge-union .union-date:focus { outline: none; border-color: var(--gold); background: #fff; }

/* Naming a card in place, straight after it is created. */
.name-edit {
  display: block;
  width: 100%;
  font-family: var(--serif);
  font-size: 15px;
  line-height: 1.2;
  color: var(--ink);
  padding: 1px 4px;
  margin: -1px -4px;
  border: 1px solid var(--gold);
  border-radius: 5px;
  background: #fff;
}
.name-edit:focus { outline: none; box-shadow: 0 0 0 2px rgba(179,144,63,.25); }

/* Relationships, listed in the book so they are findable without knowing to
   click a connector on the canvas. */
.rel-list { list-style: none; margin: 8px 0 22px; padding: 0; }
.rel {
  padding: 8px 10px;
  margin-bottom: 6px;
  /* Set apart from the page so each relationship reads as its own block. */
  background: rgba(180,150,90,.09);
  border-left: 2px solid var(--line);
  border-radius: 0 7px 7px 0;
}
.rel-who {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--serif);
  font-size: 14px;
  color: var(--ink);
}
.rel-none { color: var(--ink-faint); font-style: italic; }
.rel-kids { font-family: var(--ui); font-size: 11px; color: var(--ink-faint); }
.rel-fields { display: flex; gap: 5px; margin-top: 5px; }
.rel-fields select,
.rel-fields input {
  font: inherit;
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: #fffdf7;
  color: var(--ink);
  min-width: 0;
}
.rel-fields input { width: 68px; }
.rel-fields select:focus,
.rel-fields input:focus { outline: none; border-color: var(--gold); background: #fff; }

.toc-export {
  margin: 10px 0 4px;
  padding-top: 9px;
  border-top: 1px solid var(--line-soft);
  font-size: 11.5px;
  color: var(--ink-faint);
}
.link-btn {
  font: inherit;
  font-size: 11.5px;
  padding: 0;
  border: none;
  background: none;
  color: var(--walnut);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.link-btn:hover { color: var(--walnut-dk); }
.toc-export .dot { margin: 0 5px; }

/* ------------------------------------------------------ printing a life */

.print-root { display: none; }

@media print {
  /* Only the chapters go on paper. */
  body.printing > *:not(.print-root) { display: none !important; }
  body.printing {
    display: block;
    overflow: visible;
    background: #fff;
  }
  body.printing .print-root {
    display: block;
    font-family: var(--serif);
    color: #1c1a17;
    max-width: 100%;
  }
  .pr-head { margin-bottom: 28px; }
  .pr-head h1 { font-size: 26pt; font-weight: 500; margin: 0 0 6px; }
  .pr-sub { margin: 0 0 8px; font-size: 10pt; color: #555; letter-spacing: .03em; }
  .pr-known { margin: 0; font-size: 11pt; font-style: italic; color: #333; }

  .pr-chapter {
    /* Never split a chapter heading from the paragraph it belongs to. */
    break-inside: avoid-page;
    margin-bottom: 22px;
  }
  .pr-chapter h2 {
    font-size: 15pt;
    font-weight: 500;
    margin: 0 0 3px;
    break-after: avoid-page;
  }
  .pr-when {
    margin: 0 0 10px;
    font-family: var(--ui);
    font-size: 9pt;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #777;
    break-after: avoid-page;
  }
  .pr-body { font-size: 11.5pt; line-height: 1.65; }
  .pr-body p { margin: 0 0 10px; }
  .pr-foot {
    margin-top: 30px;
    padding-top: 10px;
    border-top: 1px solid #ccc;
    font-size: 9pt;
    color: #777;
  }
  @page { margin: 20mm 18mm; }
}

/* ----------------------------------------------------- the empty board */

/* Hidden by default; FT.render adds .board-empty to <body> when the open tree
   has nobody in it. Deliberately not tied to what is on screen — someone who
   has panned away from their tree still has a tree. */
.empty-state {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 24px;
  text-align: center;
  /* The board underneath stays draggable; only the two actions take clicks. */
  pointer-events: none;
}
body.board-empty .empty-state { display: flex; }

.empty-mark { color: var(--line); margin-bottom: 14px; }

.empty-lead {
  margin: 0;
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.45;
  color: var(--ink);
  max-width: 30ch;
}
.empty-sub {
  margin: 0 0 22px;
  font-size: 13.5px;
  /* The strongest thing this app has to say — not a footnote. */
  color: var(--ink-soft);
}

/* Two deliberate lines rather than one wrapping sentence: an inline button
   makes line breaking unpredictable, and at some widths it stranded two words
   on a line of their own. */
.empty-actions {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 10px;
  font-size: 13.5px;
  color: var(--ink-soft);
}
.empty-alt {
  margin: 0;
  font-size: 13px;
  color: var(--ink-faint);
  max-width: 40ch;
  line-height: 1.7;
}

/* The words you read are the things you click, so nothing has to describe
   where a button lives — a claim that would go stale as the bar reflows. */
.empty-btn,
.empty-link {
  font: inherit;
  cursor: pointer;
  pointer-events: auto;
  white-space: nowrap;
}
.empty-btn {
  padding: 6px 13px;
  border-radius: 8px;
  border: 1px solid var(--walnut-dk);
  background: linear-gradient(180deg, #9c6440, var(--walnut));
  color: #fdf8ef;
  box-shadow: 0 1px 3px rgba(58,44,28,.16);
}
.empty-btn:hover { background: linear-gradient(180deg, #a86e47, #7c4d31); }
.empty-btn:active { transform: translateY(1px); }

.empty-link {
  padding: 0;
  border: none;
  background: none;
  color: var(--walnut);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.empty-link:hover { color: var(--walnut-dk); }

.empty-btn:focus-visible,
.empty-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

@media (max-width: 600px) {
  .empty-lead { font-size: 17px; }
}
