/* Editor and account pages. Same calm palette as the public archive. */
:root {
  --bg: #f5f7f6;
  --surface: #fff;
  --surface-2: #eef2f0;
  --ink: #1e2a2c;
  --ink-2: #4b5c5e;
  --ink-3: #78898a;
  --line: #d9e2df;
  --line-2: #c2cfca;
  --accent: #2f6f6b;
  --accent-ink: #245a57;
  --accent-soft: #e2eeeb;
  --amber: #8b6a2a;
  --amber-soft: #f6f0e2;
  --amber-line: #d8c69a;
  --rose: #8d4a40;
  --bar: 56px;
  --radius: 10px;
  --radius-s: 6px;
  --shadow: 0 2px 6px rgba(22, 40, 38, 0.08), 0 16px 40px rgba(22, 40, 38, 0.1);
  --font-serif: "Iowan Old Style", Palatino, Georgia, serif;
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color-scheme: light;
}
* { box-sizing: border-box; }
html { background: var(--bg); color: var(--ink); font: 15px/1.6 var(--font-sans); }
body { margin: 0; min-height: 100dvh; }
/* Sign-in forms keep the site bar on top, so a guest always has a way back to the open archive.
   The single column is minmax(0, 1fr), never max-content: otherwise the bar's navigation — wider
   than a phone once it lists the archive, the support page and the two account links — would
   stretch the whole page and scroll it sideways instead of scrolling inside its own strip. */
body.centered { display: grid; grid-template-rows: auto 1fr; grid-template-columns: minmax(0, 1fr); }
body.centered > main { display: grid; place-items: center; padding: 24px; }
body.editor-page { overflow: hidden; }
a { color: var(--accent-ink); }
h1, h2 { font-family: var(--font-serif); font-weight: 500; margin: 0 0 12px; }
h1 { font-size: 28px; }
h2 { font-size: 20px; margin-top: 28px; }
.muted { color: var(--ink-2); }
.small { font-size: 13px; }
.error { color: var(--rose); background: #f7ebe8; border: 1px solid #e3c5bf; border-radius: var(--radius-s); padding: 8px 12px; }
code { font-size: 12px; background: var(--surface-2); padding: 2px 6px; border-radius: 4px; }

.bar { display: flex; align-items: center; gap: 16px; height: var(--bar); padding: 0 20px; background: var(--surface); border-bottom: 1px solid var(--line); }
.brand { display: flex; align-items: baseline; gap: 8px; text-decoration: none; color: var(--ink); }
.brand b { font: 500 22px var(--font-serif); }
.brand span { font-size: 12px; color: var(--ink-3); }
.bar nav { margin-left: auto; display: flex; gap: 4px; }
.bar nav a { padding: 8px 12px; border-radius: var(--radius-s); text-decoration: none; color: var(--ink-2); }
.bar nav a:hover { background: var(--surface-2); color: var(--ink); }
/* the way back to the archive's start page: always the first item, so it is on screen before the
   nav strip needs to scroll on a phone (see the max-width: 719px rule below) */
.home-link { display: inline-flex; align-items: center; gap: 6px; }
/* the language switch looks as on the open archive: the code of the other language in a small frame */
.lang-switch { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; min-height: 36px; padding: 0 10px; border: 1px solid var(--line); border-radius: var(--radius-s);
  color: var(--ink-2); text-decoration: none; font-size: 13px; font-weight: 600; letter-spacing: 0.04em; white-space: nowrap; }
.lang-switch:hover { background: var(--surface-2); color: var(--ink); }
.link { border: 0; background: none; color: var(--ink-2); cursor: pointer; font: inherit; padding: 8px; }

.page { max-width: 900px; margin: 0 auto; padding: 28px 20px 60px; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 24px; box-shadow: var(--shadow); }
.form { width: min(400px, 100%); display: flex; flex-direction: column; gap: 12px; }
.form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--ink-2); }
input, select { font: inherit; color: var(--ink); padding: 9px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s); background-color: var(--surface); min-height: 40px; }
input::placeholder { color: var(--ink-3); opacity: 1; }
input:focus, select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(47, 111, 107, 0.2); }
/* The list keeps the page's look, not the operating system's: same frame as a text field, a quiet arrow. */
select { appearance: none; -webkit-appearance: none; padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%234b5c5e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center; background-size: 12px 8px; }
select::-ms-expand { display: none; }
/* the browser's autofill paints fields pale blue or yellow; keep the page's own surface */
input:-webkit-autofill, input:-webkit-autofill:hover { -webkit-text-fill-color: var(--ink); box-shadow: 0 0 0 40px var(--surface) inset; caret-color: var(--ink); }
input:-webkit-autofill:focus { box-shadow: 0 0 0 40px var(--surface) inset, 0 0 0 3px rgba(47, 111, 107, 0.2); }
/* a field the server sent back: a red frame and the reason right under it, in the page's language */
[aria-invalid="true"] { border-color: var(--rose); }
[aria-invalid="true"]:focus { border-color: var(--rose); box-shadow: 0 0 0 3px rgba(141, 74, 64, 0.18); }
.field-error { display: block; color: var(--rose); font-size: 13px; line-height: 1.4; }
/* a date typed as day, month and year: never the browser's calendar, which speaks the browser's language */
.date-parts { border: 0; margin: 0; padding: 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.date-parts legend { padding: 0 0 4px; font-size: 13px; color: var(--ink-2); }
/* same text size as the other fields of the form, which take it from their label */
.date-row { display: grid; grid-template-columns: 68px minmax(0, 1fr) 84px; gap: 8px; font-size: 13px; }
.date-row input, .date-row select { width: 100%; min-width: 0; }
.date-row input { text-align: center; font-variant-numeric: tabular-nums; }
/* an unchosen month reads like the placeholders beside it; the list itself stays dark */
.date-row select:has(option[value=""]:checked) { color: var(--ink-3); }
.date-row option { color: var(--ink); }
.button { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 38px; padding: 6px 14px; border: 1px solid var(--line-2); border-radius: var(--radius-s); background: var(--surface); color: var(--ink); font: inherit; cursor: pointer; white-space: nowrap; }
.button:hover:not(:disabled) { border-color: var(--accent); color: var(--accent-ink); }
.button:disabled { opacity: 0.45; cursor: default; }
.button.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.edit-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 12px; margin-bottom: 12px; }
.edit-grid label { display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--ink-3); }
.edit-grid input, .edit-grid select { min-height: 34px; padding: 5px 8px; font-size: 14px; }
.edit-grid select { padding-right: 28px; background-position: right 9px center; }
/* the account forms keep the larger fields of the form around them */
.form .edit-grid { margin-bottom: 0; }
.form .edit-grid label { font-size: 13px; color: var(--ink-2); gap: 4px; }
.form .edit-grid input { min-height: 40px; padding: 9px 11px; font-size: inherit; width: 100%; min-width: 0; }
.button.danger { border-color: #e3c5bf; color: var(--rose); }
.button.danger:hover { border-color: var(--rose); color: var(--rose); }
.row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.scroll-x { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 13px; margin-top: 12px; }
.table th, .table td { text-align: left; padding: 8px 12px 8px 0; border-bottom: 1px solid var(--line); }
.table th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-3); }
.table tr.off { opacity: 0.55; }
.table td.actions { display: flex; gap: 10px; flex-wrap: wrap; }
.table td.actions form { display: inline; }
.tag { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); }
.notice { background: var(--accent-soft); border: 1px solid var(--accent); color: var(--accent-ink); border-radius: var(--radius-s); padding: 8px 12px; }
.form.narrow { max-width: 340px; }
/* "Passwort vergessen?" sits right under the password it is about, not stretched across the form */
.form .forgot-link { align-self: flex-end; margin-top: -6px; }
/* the account a reset link is for: shown, not typed */
input[readonly] { background-color: var(--surface-2); color: var(--ink-2); }
.kin { border: 1px solid var(--line); border-radius: var(--radius-s); padding: 10px 14px 14px; margin: 0 0 10px; }
.kin legend { font-size: 12px; color: var(--ink-3); padding: 0 6px; }
.kin-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); margin-bottom: 0; }
.page form section { margin-bottom: 28px; }
.page section { margin-bottom: 36px; }
/* a message from the contact form keeps its own line breaks and never widens the table */
.message-text { white-space: pre-wrap; max-width: 46ch; }

/* ---------------------------------------------------------------- writing to the owner
   The support page and the floating button that leads to it. The button sits in the bottom right
   corner of every server page except that page itself; it is a plain link, because the server sends
   `script-src 'self'` and a link needs no script. */
.card.support { width: min(520px, 100%); }
.card.support h1 { margin-bottom: 8px; }
.card.support .form { width: 100%; margin-top: 16px; }
.card.support .row { margin-top: 18px; }
textarea { font: inherit; color: var(--ink); padding: 9px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-s);
  background-color: var(--surface); width: 100%; resize: vertical; min-height: 120px; }
textarea:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(47, 111, 107, 0.2); }
/* the honeypot: out of sight and out of the tab order, but not display:none, which a machine reads as "skip me" */
.trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.support-fab { position: fixed; z-index: 25; right: max(16px, env(safe-area-inset-right)); bottom: max(16px, env(safe-area-inset-bottom));
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px 0 14px; border: 1px solid var(--line-2);
  border-radius: 999px; background: var(--surface); color: var(--ink); font-size: 14px; text-decoration: none; box-shadow: var(--shadow); }
.support-fab svg { color: var(--accent); flex: none; }
.support-fab:hover { border-color: var(--accent); color: var(--accent-ink); }
.support-fab:focus-visible { outline: 3px solid rgba(47, 111, 107, 0.28); outline-offset: 2px; }
/* On the editor the canvas is the page: the button shrinks to its icon, and steps aside entirely
   while the details panel is open, which covers that corner. */
.editor-page .support-fab { width: 48px; min-height: 48px; padding: 0; justify-content: center; border-radius: 50%; }
.editor-page .support-fab span { display: none; }
.editor-page:has(#side:not([hidden])) .support-fab { display: none; }
/* room under a centred form so the button never sits on its last line */
body.centered > main { padding-bottom: 84px; }
/* on a phone only the icon stays: the word would lie across the page the button floats over */
@media (max-width: 559px) {
  .support-fab { width: 48px; min-height: 48px; padding: 0; justify-content: center; border-radius: 50%; }
  .support-fab span { display: none; }
}

/* ---------------------------------------------------------------- editor canvas */
.editor { position: relative; height: calc(100dvh - var(--bar)); overflow: hidden; touch-action: none; cursor: grab; outline: none; isolation: isolate; user-select: none;
  background-image: radial-gradient(rgba(70, 100, 95, 0.16) 1px, transparent 1px); background-size: 24px 24px; }
.editor.dragging { cursor: grabbing; }
.world { position: absolute; inset: 0 auto auto 0; transform-origin: 0 0; will-change: transform; }
#lines { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.ln { fill: none; stroke: #8fa9a3; stroke-width: 2; vector-effect: non-scaling-stroke; stroke-linecap: round; stroke-linejoin: round; }
.ln.dashed { stroke-dasharray: 6 5; stroke: #b3a98a; }
.ln.probable { stroke-dasharray: 1.5 5; stroke-width: 2.5; }
.ln.inferred { stroke: #adc0bb; stroke-width: 1.5; }
.ln.partial { stroke: #a9bdb8; stroke-width: 1.5; }
.ln.cross { stroke: #b0c3be; stroke-width: 1.5; }
.ln.active { stroke: var(--accent); stroke-width: 3; }

.pc { position: absolute; left: 0; top: 0; width: 224px; height: 74px; padding: 10px 12px; display: flex; flex-direction: column; gap: 2px;
  align-items: flex-start; text-align: left; border: 1px solid var(--line-2); border-radius: 10px; background: var(--surface);
  box-shadow: 0 1px 2px rgba(22, 40, 38, 0.05); transform-origin: 0 0; will-change: transform; overflow: hidden; font: inherit; }
.pc.can-drag { cursor: grab; }
.pc.is-dragging { cursor: grabbing; box-shadow: 0 8px 24px rgba(22, 40, 38, 0.18); z-index: 5; }
.pc:hover { border-color: var(--accent); }
.pc.selected { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(47, 111, 107, 0.25); z-index: 4; }
.pc.related { border-color: #7ea59f; }
.pc.moved { border-left: 3px solid var(--amber); padding-left: 11px; }
.pc.picked { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft), 0 0 0 3px var(--accent); }
/* rubber band: drawn over the canvas in screen coordinates, never catching the pointer */
.band { position: absolute; left: 0; top: 0; z-index: 6; transform-origin: 0 0; pointer-events: none;
  border: 1px solid var(--accent); background: rgba(47, 111, 107, 0.08); border-radius: 4px; }
.pc.dl { border-left: 3px solid var(--accent); padding-left: 11px; }
.pc.ghost { height: 44px; border-style: dashed; background: var(--surface-2); }
.pc .n { font-size: 14px; font-weight: 600; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.pc .m { font-size: 12px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; font-variant-numeric: tabular-nums; }
.pc .lv { position: absolute; right: 8px; bottom: 7px; min-width: 24px; height: 17px; padding: 0 5px; border-radius: 999px; font-size: 10px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; background: var(--surface-2); color: var(--ink-3); }
.pc .lv.l1, .pc .lv.l2 { background: var(--accent); color: #fff; }
.pc .lv.l3 { background: var(--amber-soft); color: var(--amber); border: 1px solid var(--amber-line); }

.ui { position: absolute; z-index: 10; cursor: default; touch-action: auto; user-select: text; }
.ui.top { top: 14px; left: 16px; right: 16px; display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; pointer-events: none; }
.ui.top > * { pointer-events: auto; }
.panel { display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: rgba(255, 255, 255, 0.94); border: 1px solid var(--line); border-radius: var(--radius); backdrop-filter: blur(6px); }
.panel.title { flex-direction: column; align-items: flex-start; gap: 2px; }
.panel.tools { flex-wrap: wrap; }
.panel label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); }
.panel label.check input { width: 15px; height: 15px; min-height: 0; accent-color: var(--accent); }
.pc.private { border-style: dashed; border-color: var(--amber-line); background: #fffdf8; }
.pc.gap { height: 44px; border: 1px dashed var(--line-2); background: transparent; box-shadow: none; align-items: center; justify-content: center; color: var(--ink-3); }
.pc.gap:hover { border-color: var(--accent); background: rgba(255, 255, 255, 0.7); color: var(--accent-ink); }
.pc.gap .n { font-size: 12px; font-weight: 500; }
#search { margin-left: auto; width: min(280px, 100%); background: rgba(255, 255, 255, 0.95); }
.ui.bottom { left: 0; right: 0; bottom: 16px; display: flex; justify-content: center; align-items: center; gap: 10px; flex-wrap: wrap; pointer-events: none; }
/* Brothers and sisters are not ancestors, so they sit in a list beside the chart. */
.panel.kin-strip { max-width: min(520px, 46vw); gap: 8px; }
.panel.kin-strip > b { font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.04em; white-space: nowrap; }
.panel.kin-strip ul { display: flex; gap: 4px; margin: 0; padding: 0; list-style: none; overflow-x: auto; scrollbar-width: none; }
.panel.kin-strip ul::-webkit-scrollbar { display: none; }
.panel.kin-strip button { display: inline-flex; align-items: baseline; gap: 6px; min-height: 32px; padding: 4px 10px; border: 1px solid var(--line-2); border-radius: 999px; background: var(--surface); color: var(--ink); font: inherit; font-size: 13px; white-space: nowrap; cursor: pointer; }
.panel.kin-strip button:hover { border-color: var(--accent); color: var(--accent-ink); }
.panel.kin-strip button small { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.ui.bottom > * { pointer-events: auto; }
.panel.zoom button { min-width: 36px; min-height: 34px; border: 0; background: none; border-radius: var(--radius-s); cursor: pointer; font: inherit; color: var(--ink-2); }
.panel.zoom button:hover { background: var(--surface-2); color: var(--ink); }
.panel.zoom output { min-width: 46px; text-align: center; font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.panel.zoom .sep { width: 1px; height: 20px; background: var(--line); }

.ui.side { top: 0; right: 0; bottom: 0; width: min(380px, 100%); background: var(--surface); border-left: 1px solid var(--line); box-shadow: -8px 0 30px rgba(22, 40, 38, 0.08); padding: 20px; overflow: auto; }
.ui.side .close { position: absolute; top: 14px; right: 14px; width: 34px; height: 34px; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--surface); font-size: 20px; cursor: pointer; }
.ui.side h2 { margin-right: 44px; }
.ui.side dl { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: 14px; margin: 0 0 16px; }
.ui.side dt { color: var(--ink-3); font-size: 12px; }
.ui.side dd { margin: 0; }
.rel { list-style: none; padding: 0; margin: 0 0 16px; }
.rel li { display: flex; align-items: center; gap: 8px; min-height: 34px; border-bottom: 1px solid var(--line); font-size: 14px; }
.rel button { margin-left: auto; }

dialog { border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); padding: 22px; max-width: 420px; color: var(--ink); background: var(--surface); }
#confirm-dialog p { margin: 0 0 4px; font-size: 15px; }
#confirm-dialog .row { justify-content: flex-end; }
dialog::backdrop { background: rgba(22, 40, 38, 0.28); }
@media (max-width: 719px) {
  /* Header wraps: brand, language switch and the logout button on top, navigation on its own row. */
  :root { --bar: 96px; }
  .bar { flex-wrap: wrap; align-content: center; padding: 0 12px; gap: 0 10px; }
  .brand { flex: 1 1 auto; height: 48px; align-items: center; }
  .bar form { order: 2; }
  .bar nav { order: 3; flex-basis: 100%; margin-left: 0; height: 44px; align-items: center; overflow-x: auto; scrollbar-width: none; }
  .bar nav::-webkit-scrollbar { display: none; }
  .bar nav a { white-space: nowrap; }

  /* The canvas is the point of the page, so the overlays stay thin. */
  .ui.top { top: 8px; left: 8px; right: 8px; gap: 6px; }
  .panel { padding: 6px 10px; }
  .panel.title { flex: 1 1 100%; flex-direction: row; align-items: baseline; gap: 8px; }
  .panel.title b { white-space: nowrap; }
  .panel.title .muted { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* the tools scroll sideways; the fade on the right edge says there is more */
  .panel.tools { flex: 1 1 100%; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent); }
  .panel.tools::-webkit-scrollbar { display: none; }
  .panel.tools label, .panel.tools select { flex: none; }
  #search { margin-left: 0; width: 100%; }
  .ui.bottom { bottom: 10px; }
  .panel.zoom #hint { display: none; }
  /* the bottom sheet would cover the zoom bar; pinch still works */
  .editor:has(#side:not([hidden])) .ui.bottom { display: none; }
  .panel.kin-strip { max-width: 100%; }
  .panel.kin-strip > b { display: none; }
  .panel.kin-strip button { min-height: 40px; }

  /* Touch targets. */
  .button { min-height: 44px; }
  .panel.zoom button { min-width: 44px; min-height: 44px; }
  .panel label.check input { width: 20px; height: 20px; }

  /* The details panel becomes a bottom sheet. */
  .ui.side { width: 100%; top: auto; max-height: 66dvh; height: auto; border-left: 0; border-top: 1px solid var(--line); border-radius: 16px 16px 0 0;
    box-shadow: 0 -8px 30px rgba(22, 40, 38, 0.14); padding: 16px 16px calc(16px + env(safe-area-inset-bottom)); overscroll-behavior: contain; }
  .ui.side::before { content: ""; position: absolute; top: 7px; left: 50%; transform: translateX(-50%); width: 40px; height: 4px; border-radius: 2px; background: var(--line-2); }
  .ui.side h2 { margin-top: 10px; }
  .ui.side .close { top: 12px; width: 44px; height: 44px; }
  .rel li { min-height: 44px; }
  dialog { width: min(420px, calc(100vw - 24px)); padding: 18px; }
  /* the user table keeps its columns and scrolls inside its own box */
  .table { min-width: 420px; }
  .page { padding: 20px 16px 48px; }
  /* centred forms must not be wider than the screen; the last 84px keep the support button clear */
  body.centered > main { padding: 16px 16px 84px; align-content: start; }
  body.centered > main > * { width: 100%; max-width: 420px; }
  .form { width: 100%; }
  .edit-grid { grid-template-columns: 1fr; }
  .kin-grid { grid-template-columns: 1fr; }
  input, select, .edit-grid input, .edit-grid select { min-height: 44px; }
}
