/* ============================================
   DESIGN TOKENS
   Palette inspired by traditional Chinese genealogy
   scrolls (族谱): aged paper, ink, and seal-stamp red.
   ============================================ */
:root {
  --paper: #f3ede1;
  --paper-deep: #e8dfc9;
  --ink: #2b2622;
  --ink-soft: #5c5347;
  --seal-red: #a3342a;
  --seal-red-soft: #c25c4f;
  --gold: #b08d3f;
  --line: #c9bea3;
  --white: #fffdf8;
  --gender-male: #2c5f8a;
  --gender-female: #a83e5e;

  --font-display: "Noto Serif SC", "Noto Serif", serif;
  --font-body: "Noto Serif", serif;
  --font-ui: "Inter", sans-serif;
  /* Sans-serif CJK, used specifically for small dense text (tree box
     names, detail panel headings) where Noto Serif SC's fine serif
     strokes get hard to read at small sizes. Noto Serif SC is kept
     for larger decorative/branding text (the seal mark, page title)
     where serif still reads cleanly and fits the genealogy-scroll
     aesthetic. */
  --font-ui-cjk: "Noto Sans SC", "Inter", sans-serif;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
}

/* Subtle paper texture via layered gradients, no image asset needed */
body {
  background-image:
    radial-gradient(circle at 20% 20%, rgba(176, 141, 63, 0.04), transparent 40%),
    radial-gradient(circle at 80% 60%, rgba(163, 52, 42, 0.03), transparent 45%);
}

/* ============================================
   TOP BAR
   ============================================ */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 18px 28px;
  background: var(--paper-deep);
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}

.topbar-title {
  display: flex;
  align-items: center;
  gap: 14px;
}

.topbar-mark {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 700;
  color: var(--white);
  background: var(--seal-red);
  width: 44px;
  height: 44px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  box-shadow: 1px 1px 0 rgba(43, 38, 34, 0.25);
}

.topbar .subtitle {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--ink);
  margin: 0;
  letter-spacing: 0.03em;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
}

/* ============================================
   ACCOUNT INDICATOR
   Logged out: a simple "Log in" link.
   Logged in: email + role badge + logout button.
   ============================================ */
.account-indicator {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-ui);
  font-size: 13px;
  flex-shrink: 0;
}

.contact-link {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  flex-shrink: 0;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 5px;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.contact-link:hover {
  background: var(--paper-deep);
  color: var(--ink);
  border-color: var(--ink-soft);
}

.requests-link {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--seal-red);
  text-decoration: none;
  flex-shrink: 0;
  padding: 6px 12px;
  border: 1px solid var(--seal-red-soft);
  border-radius: 5px;
  transition: background 0.15s ease;
}

.requests-link:hover {
  background: rgba(163, 52, 42, 0.08);
}

.login-link {
  color: var(--seal-red);
  text-decoration: none;
  font-weight: 500;
  padding: 6px 12px;
  border: 1px solid var(--seal-red-soft);
  border-radius: 5px;
  transition: background 0.15s ease;
}

.login-link:hover {
  background: rgba(163, 52, 42, 0.08);
}

.account-email {
  color: var(--ink-soft);
}

.account-role-badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 10px;
  color: var(--white);
}

.account-role-badge.role-admin {
  background: var(--seal-red);
}

.account-role-badge.role-editor {
  background: var(--gender-male);
}

.account-role-badge.role-viewer {
  background: var(--ink-soft);
}

.logout-btn {
  font-family: var(--font-ui);
  font-size: 12px;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 5px 10px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.logout-btn:hover {
  background: var(--paper-deep);
}

/* ============================================
   GENDER LEGEND
   Matches the corner accents drawn on tree boxes:
   blue square = male, rose circle = female.
   ============================================ */
.legend-strip {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 8px 28px;
  background: var(--paper);
  flex-wrap: wrap;
}

.lang-tabs {
  display: flex;
  gap: 4px;
}

.lang-tab {
  font-family: var(--font-ui-cjk);
  font-size: 12px;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 4px 10px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.lang-tab:hover {
  background: var(--paper-deep);
}

.lang-tab.active {
  background: var(--seal-red);
  border-color: var(--seal-red);
  color: var(--white);
}

.zoom-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}

.zoom-btn {
  font-family: var(--font-ui);
  font-size: 18px;
  font-weight: 600;
  color: var(--ink-soft);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 8px 16px;
  cursor: pointer;
  line-height: 1;
  transition: background 0.15s ease, color 0.15s ease;
}

.zoom-btn:hover {
  background: var(--paper-deep);
  color: var(--ink);
}

.zoom-btn-reset {
  font-size: 14px;
  letter-spacing: 0.02em;
}

.gender-legend {
  display: flex;
  align-items: center;
  gap: 16px;
  font-family: var(--font-ui-cjk);
  font-size: 18px;
  color: var(--ink-soft);
  flex-shrink: 0;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}

.legend-swatch {
  width: 14px;
  height: 14px;
  display: inline-block;
  flex-shrink: 0;
}

.legend-swatch-male {
  background: var(--gender-male);
  border-radius: 2px;
}

.legend-swatch-female {
  background: var(--gender-female);
  border-radius: 50%;
}

/* ============================================
   SEARCH
   ============================================ */
.search-wrap {
  position: relative;
  width: min(340px, 100%);
}

#search-input {
  width: 100%;
  padding: 10px 14px;
  font-family: var(--font-ui-cjk);
  font-size: 14px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--white);
  color: var(--ink);
  outline: none;
  transition: border-color 0.15s ease;
}

#search-input::placeholder {
  color: #a39a89;
}

#search-input:focus {
  border-color: var(--seal-red-soft);
}

.search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 6px;
  max-height: 320px;
  overflow-y: auto;
  z-index: 20;
  box-shadow: 0 8px 24px rgba(43, 38, 34, 0.12);
}

.search-results.hidden {
  display: none;
}

.search-result-item {
  padding: 10px 14px;
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: 14px;
  border-bottom: 1px solid var(--paper-deep);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.search-result-item:last-child {
  border-bottom: none;
}

.search-result-item:hover,
.search-result-item.active {
  background: var(--paper);
}

.search-result-name {
  font-family: var(--font-ui-cjk);
  font-weight: 600;
  color: var(--ink);
}

.search-result-sub {
  font-size: 12px;
  color: var(--ink-soft);
}

.search-no-results {
  padding: 14px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  text-align: center;
}

/* ============================================
   TREE CANVAS
   ============================================ */
#tree-container {
  position: relative;
  width: 100%;
  /* Fallback only — actual height is set dynamically by JS
     (updateTreeContainerHeight) based on the real rendered height of
     both header rows, since their combined height varies with
     content rather than being a fixed value. */
  height: calc(100vh - 81px);
  overflow: auto;
}

#generation-labels {
  position: fixed;
  left: 0;
  width: 140px;
  /* top and height are set in JS to match #tree-container's actual
     position, since the header's height is also dynamic. */
  pointer-events: none; /* labels never block clicks/scroll on the tree underneath */
  overflow: hidden;
  z-index: 5;
}

.generation-label {
  position: absolute;
  left: 16px;
  transform: translateY(-50%);
  font-family: var(--font-ui-cjk);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
}

#tree-svg {
  display: block;
}

.loading,
.empty-state {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-ui);
  color: var(--ink-soft);
  text-align: center;
}

.loading.hidden,
.empty-state.hidden {
  display: none;
}

.empty-sub {
  font-size: 13px;
  margin-top: 6px;
  color: #a39a89;
}

/* ============================================
   TREE NODES (rendered via D3, styled here)
   ============================================ */
.link {
  fill: none;
  stroke: #8a8a8a;
  stroke-width: 1.5px;
}

.generation-line {
  stroke: var(--line);
  stroke-width: 1px;
  pointer-events: none;
}

/* Spouse lines (mother→child) are hidden by default — only the
   anchor's lines show. They appear when a child or spouse is clicked
   (spouse-link-revealed) or when they're part of a lineage highlight. */
.spouse-link {
  opacity: 0;
  pointer-events: none;
}

.spouse-link.spouse-link-revealed,
.spouse-link.lineage-highlighted {
  opacity: 1;
  pointer-events: auto;
}

.node {
  cursor: pointer;
}

.node-box {
  fill: var(--white);
  stroke: var(--ink-soft);
  stroke-width: 1.2px;
  transition: stroke 0.15s ease, fill 0.15s ease;
}

.gender-accent {
  pointer-events: none;
}

.gender-male {
  fill: var(--gender-male);
}

.gender-female {
  fill: var(--gender-female);
}

.info-btn {
  cursor: pointer;
}

.info-btn-circle {
  fill: var(--paper-deep);
  stroke: var(--ink-soft);
  stroke-width: 1px;
  transition: fill 0.15s ease;
}

.info-btn:hover .info-btn-circle {
  fill: var(--seal-red-soft);
  stroke: var(--seal-red-soft);
}

.info-btn-text {
  font-family: var(--font-display);
  font-size: 11px;
  font-style: italic;
  font-weight: 700;
  fill: var(--ink-soft);
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
}

.info-btn:hover .info-btn-text {
  fill: var(--white);
}

.node.has-children .node-box {
  stroke: var(--seal-red-soft);
}

.node.has-children .node-box.node-box-private,
.node-box.node-box-private {
  fill: var(--paper-deep);
  stroke: var(--line);
  stroke-dasharray: 4 3;
}

.person-box:hover .node-box {
  fill: var(--paper-deep);
}

.person-box.highlighted .node-box {
  stroke: var(--seal-red);
  stroke-width: 3.4px;
  fill: #fff6ee;
}

/* Lineage trace: ancestors (all generations up) and one generation
   of descendants, shown with a soft yellow glow behind the box —
   distinct from the red border reserved for the specifically
   clicked/searched person. */
.person-box.lineage-glow .node-box {
  fill: #fff3c4;
  stroke: #d4a017;
  stroke-width: 1.8px;
}

/* When the clicked person is ALSO included in their own lineage glow,
   the red border must win for the stroke — higher specificity (two
   classes) ensures this rule beats .lineage-glow regardless of source
   order — but the yellow fill should still show through underneath. */
.person-box.highlighted.lineage-glow .node-box {
  stroke: var(--seal-red);
  stroke-width: 3.4px;
  fill: #fff3c4;
}

.link.lineage-highlighted {
  stroke: var(--seal-red) !important;
  stroke-width: 3px;
}

.couple-connector {
  stroke: var(--ink-soft);
  stroke-width: 1.5px;
}

.couple-connector.former {
  stroke-dasharray: 4, 3;
  stroke: var(--line);
}

.couple-connector.lineage-highlighted {
  stroke: var(--seal-red);
  stroke-width: 3px;
}

.node-name {
  font-family: var(--font-ui-cjk);
  font-size: 18px;
  font-weight: 500;
  fill: var(--ink);
  text-anchor: middle;
  user-select: text;
  cursor: text;
}

.node-name-order {
  font-size: 13px;
  font-weight: 400;
  fill: var(--ink-soft);
}

.node-highlight-text {
  font-family: var(--font-ui);
  font-size: 11px;
  fill: var(--seal-red-soft);
  text-anchor: middle;
  user-select: text;
  cursor: text;
}

.node-toggle {
  fill: var(--seal-red);
  stroke: none;
}

.node-toggle-text {
  fill: var(--white);
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  text-anchor: middle;
  dominant-baseline: central;
  pointer-events: none;
}

/* ============================================
   LEVEL EXPAND/COLLAPSE PANEL
   Fixed floating panel on the right side —
   stays visible regardless of scroll position.
   ============================================ */
.level-panel {
  position: fixed;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 8px;
  box-shadow: 0 4px 16px rgba(43, 38, 34, 0.12);
  z-index: 25;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 64px;
}

#level-buttons {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.level-panel-title {
  font-family: var(--font-ui);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
  text-align: center;
  margin-bottom: 4px;
}

.level-btn {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 5px 8px;
  cursor: pointer;
  text-align: center;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
  white-space: nowrap;
}

.level-btn:hover {
  background: var(--paper-deep);
  color: var(--ink);
}

.level-btn.level-collapsed {
  color: var(--seal-red);
  border-color: var(--seal-red-soft);
  background: rgba(163, 52, 42, 0.06);
}

/* ============================================
   DETAIL PANEL (click a person to see more)
   ============================================ */
.detail-panel {
  position: fixed;
  top: 0;
  right: 0;
  width: min(340px, 90vw);
  height: 100%;
  background: var(--white);
  border-left: 1px solid var(--line);
  box-shadow: -8px 0 24px rgba(43, 38, 34, 0.10);
  padding: 24px;
  overflow-y: auto;
  z-index: 30;
  transition: transform 0.25s ease;
}

.detail-panel.hidden {
  transform: translateX(100%);
}

.detail-close {
  position: absolute;
  top: 16px;
  right: 16px;
  background: none;
  border: none;
  font-size: 22px;
  color: var(--ink-soft);
  cursor: pointer;
  line-height: 1;
}

.detail-close:hover {
  color: var(--seal-red);
}

.detail-name {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 2px;
}

.detail-chinese {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink-soft);
  margin: 0 0 16px;
}

.detail-row {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.detail-row strong {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--gold);
}

.detail-notes {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--paper-deep);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
}

/* ============================================
   DETAIL PANEL ACTIONS (edit / add child / add
   spouse / delete) AND THE EDIT/ADD FORMS
   ============================================ */
.detail-actions {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--paper-deep);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.detail-action-btn {
  font-family: var(--font-ui);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 7px 12px;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.detail-action-btn:hover {
  background: var(--paper-deep);
}

.detail-action-primary {
  color: var(--white);
  background: var(--seal-red);
  border-color: var(--seal-red);
}

.detail-action-primary:hover {
  background: var(--seal-red-soft);
}

.detail-action-danger {
  color: var(--seal-red);
  border-color: var(--seal-red-soft);
}

.detail-action-danger:hover {
  background: rgba(163, 52, 42, 0.08);
}

.detail-action-error {
  margin-top: 12px;
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--seal-red);
  background: rgba(163, 52, 42, 0.07);
  border: 1px solid rgba(163, 52, 42, 0.2);
  border-radius: 6px;
  padding: 8px 10px;
}

.detail-action-error.hidden {
  display: none;
}

.detail-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 8px;
}

.detail-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
}

.detail-form input,
.detail-form select,
.detail-form textarea {
  font-family: var(--font-ui);
  font-size: 14px;
  color: var(--ink);
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--paper);
  outline: none;
}

.detail-form input:focus,
.detail-form select:focus,
.detail-form textarea:focus {
  border-color: var(--seal-red-soft);
}

.detail-form textarea {
  min-height: 70px;
  resize: vertical;
  font-family: var(--font-body);
}

.detail-form-context {
  font-family: var(--font-ui);
  font-size: 13px;
  color: var(--ink-soft);
  margin: -4px 0 8px;
}

.detail-form-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

/* ============================================
   ACCESSIBILITY
   ============================================ */
:focus-visible {
  outline: 2px solid var(--seal-red-soft);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* ============================================
   RESPONSIVE
   ============================================ */
@media (max-width: 640px) {
  .topbar {
    flex-direction: column;
    align-items: stretch;
  }
  .topbar-right {
    flex-direction: column;
    align-items: stretch;
  }
  .search-wrap {
    width: 100%;
  }
  .legend-strip {
    justify-content: center;
  }
}

.node-name-hao {
  font-size: 16px;
  font-weight: 800;
  fill: var(--ink, #2b2622);
  font-family: var(--font-display);
}

