.workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  flex: 1;
  min-height: 0;
}
.canvasShell, .panel {
  background:
    linear-gradient(180deg, rgba(255,255,255,.36), rgba(255,255,255,.05)),
    var(--surface);
  border: 1px solid var(--line);
  border-radius: 0;
  box-shadow: var(--shadow);
}
.canvasShell {
  position: relative;
  overflow: auto;
  min-height: 0;
  height: 100%;
  background-color: #f3eee6;
  background-image: none;
  cursor: grab;
}
body:not(.viewerMode) .canvasShell {
  background-image:
    linear-gradient(rgba(83, 70, 50, .08) 1px, transparent 1px),
    linear-gradient(90deg, rgba(83, 70, 50, .08) 1px, transparent 1px),
    linear-gradient(rgba(201, 155, 69, .13) 1px, transparent 1px),
    linear-gradient(90deg, rgba(201, 155, 69, .13) 1px, transparent 1px);
  background-size: 32px 32px, 32px 32px, 160px 160px, 160px 160px;
  /* local: paint across the whole scrollable tree, not just the one
     viewport-sized frame `scroll` (the default) would confine it to -- a
     tall org chart or family tab would otherwise scroll into blank canvas
     past that frame. */
  background-attachment: local;
}
body.viewerMode .canvasShell {
  background-color: #f8efd9;
  background-image:
    linear-gradient(rgba(248, 239, 217, .30), rgba(248, 239, 217, .30)),
    url("/assets/canvas-backgrounds/hanji-familymap-01.webp");
  /* The hanji artwork is a single framed illustration (corner leaves/flowers
     around a plain center), sized for one screen -- `cover`-ing it across a
     tall, multi-screen org chart or family tab would stretch those corners
     far apart and leave an even larger plain gap between them. Pin its width
     to the canvas and repeat it vertically instead, so each screen's worth
     of scroll gets its own framed corners. */
  background-size: 100% 100%, 100% auto;
  background-position: center, top center;
  background-repeat: no-repeat, repeat-y;
  background-attachment: local;
}
.canvasShell.panning { cursor: grabbing; }
.treeToolbar {
  position: fixed;
  top: var(--float-top, 18px);
  z-index: 45;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}
.treeToolbarLeft {
  left: var(--float-left, 18px);
}
.treeToolbarRight {
  right: var(--float-right, 18px);
}
.treeToolbar.offCanvas { display: none; }
.addPersonBtn {
  position: relative;
  width: auto;
  min-height: 42px;
  border-radius: 18px;
  padding: 0 8px 0 4px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .70), rgba(255, 252, 244, .36)),
    rgba(255, 255, 255, .36);
  border: 1px solid rgba(255, 255, 255, .62);
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--green);
  font-size: 13px;
  font-weight: 900;
  white-space: nowrap;
  overflow: visible;
  box-shadow: 0 14px 30px rgba(42, 34, 22, .16), inset 0 1px 0 rgba(255,255,255,.80);
  backdrop-filter: blur(20px) saturate(1.24);
  -webkit-backdrop-filter: blur(20px) saturate(1.24);
  text-shadow: 0 1px 0 rgba(255, 248, 232, .92), 0 3px 8px rgba(42, 34, 22, .14);
}
.addPersonPaw {
  position: relative;
  display: block;
  width: 28px;
  height: 28px;
  color: var(--green);
  filter: drop-shadow(0 4px 7px rgba(42, 34, 22, .15));
}
.addPersonPawIcon {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
  opacity: .96;
}
.addPersonBtn:hover,
.addPersonBtn:focus-visible {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .82), rgba(224, 238, 213, .46)),
    rgba(255, 255, 255, .44);
  color: var(--green);
}
.addPersonBtn:hover .addPersonPaw,
.addPersonBtn:focus-visible .addPersonPaw {
  transform: translateY(-1px);
  filter: drop-shadow(0 6px 9px rgba(42, 34, 22, .18));
}
.addPersonBtn.dragging {
  opacity: .62;
}
.addPersonDragProxy {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 90;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(1.02);
  opacity: .88;
  filter: drop-shadow(0 14px 20px rgba(42, 34, 22, .26));
}
.addPersonBtn[hidden] { display: none; }
.modeToggleBtn {
  width: auto;
  min-height: 42px;
  padding: 0 12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 18px;
  font-size: 14px;
  font-weight: 900;
  white-space: nowrap;
}
body:not(.viewerMode) .modeToggleBtn {
  background: var(--dancheong-red);
  border-color: rgba(111, 30, 30, .26);
  color: #fff8e8;
  box-shadow: 0 10px 26px rgba(183, 72, 72, .28);
}
body:not(.viewerMode) .modeToggleBtn:hover,
body:not(.viewerMode) .modeToggleBtn:focus-visible {
  background: #c95454;
}
body.viewerMode .modeToggleBtn {
  display: none;
}
.modeToggleBtn[hidden] { display: none; }
.zoomMenuBtn {
  width: auto;
  min-height: 42px;
  padding: 0 11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-color: rgba(255, 255, 255, .62);
  border-radius: 18px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .70), rgba(255, 252, 244, .36)),
    rgba(255, 255, 255, .36);
  box-shadow: 0 14px 30px rgba(42, 34, 22, .16), inset 0 1px 0 rgba(255,255,255,.80);
  backdrop-filter: blur(20px) saturate(1.24);
  -webkit-backdrop-filter: blur(20px) saturate(1.24);
  font-size: 13px;
  font-weight: 900;
  white-space: nowrap;
}
.zoomMenuBtn:hover,
.zoomMenuBtn:focus-visible {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .82), rgba(224, 238, 213, .46)),
    rgba(255, 255, 255, .44);
}
.zoomMenuBtn[hidden] { display: none; }
.zoomMenuBtn {
  display: none;
}
.desktopTreeMenuBtn {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  border-radius: 18px;
}
.desktopTreeMenuBtn .bootstrapIcon {
  width: 20px;
  height: 20px;
  filter: invert(30%) sepia(23%) saturate(947%) hue-rotate(105deg) brightness(89%) contrast(88%);
}
.desktopTreeMenu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 230;
  width: min(310px, calc(100vw - 290px));
  max-height: calc(100dvh - 96px);
  display: grid;
  gap: 10px;
  padding: 9px;
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid rgba(83, 70, 50, .18);
  border-radius: 18px;
  background: rgba(255, 252, 244, .98);
  box-shadow: 0 18px 42px rgba(42, 34, 22, .20);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.desktopTreeMenu[hidden] {
  display: none;
}
.desktopTreeMenuSection {
  display: grid;
  gap: 5px;
  padding: 6px;
  border: 1px solid rgba(83, 70, 50, .10);
  border-radius: 15px;
  background: rgba(255, 255, 255, .34);
}
.desktopTreeMenuSection:not(:has(button:not([hidden]))) {
  display: none;
}
.desktopTreeMenuSectionLabel {
  margin: 0;
  padding: 2px 6px 3px;
  color: rgba(40, 96, 74, .78);
  font-size: 11px;
  font-weight: 950;
  line-height: 1.2;
}
.desktopTreeMenu button:not(.desktopTreeMenuBtn) {
  min-height: 52px;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  padding: 8px 12px 8px 10px;
  border: 1px solid rgba(83, 70, 50, .13);
  border-radius: 13px;
  background: rgba(255, 255, 255, .72);
  color: var(--text);
  text-align: left;
}
.desktopTreeMenu button[hidden] {
  display: none;
}
.desktopTreeMenu button:hover,
.desktopTreeMenu button:focus-visible {
  background: rgba(40, 96, 74, .10);
  color: var(--green);
}
.desktopTreeMenuIcon {
  width: 19px;
  height: 19px;
  justify-self: center;
  opacity: .88;
  filter: invert(30%) sepia(23%) saturate(947%) hue-rotate(105deg) brightness(89%) contrast(88%);
}
.desktopTreeMenuCopy {
  min-width: 0;
  display: grid;
  gap: 3px;
}
.desktopTreeMenuCopy > span {
  font-size: 14px;
  font-weight: 950;
  line-height: 1.2;
}
.desktopTreeMenuCopy > small {
  color: var(--muted);
  font-size: 11px;
  font-weight: 750;
  line-height: 1.35;
}
.canvasThemeBtn {
  width: 42px;
  min-height: 42px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 18px;
}
.canvasThemeBtn .bootstrapIcon {
  width: 18px;
  height: 18px;
}
.canvasThemeBtn[hidden] { display: none; }
.canvasThemeMenu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 376px;
  max-width: min(376px, calc(100vw - 32px));
  max-height: min(78vh, 720px);
  overflow: auto;
  padding: 12px;
  border: 1px solid rgba(83, 70, 50, .18);
  border-radius: 18px;
  background: rgba(255, 252, 244, .98);
  box-shadow: 0 18px 42px rgba(42, 34, 22, .18);
  backdrop-filter: blur(10px);
}
.canvasThemeMenu[hidden] { display: none; }
.canvasThemeMenuHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 2px 2px 10px;
  color: var(--text);
  font-size: 13px;
}
.canvasThemeGrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.canvasSettingGroup {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid rgba(83, 70, 50, .12);
}
.canvasSettingLabel {
  margin: 0 0 8px;
  color: #6f6a61;
  font-size: 12px;
  font-weight: 900;
}
.canvasSegmented {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
  padding: 4px;
  border-radius: 14px;
  background: rgba(83, 70, 50, .07);
}
.canvasSegmented label {
  display: grid;
  place-items: center;
  min-height: 34px;
  border-radius: 11px;
  color: #6f6a61;
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
}
.canvasSegmented label.active {
  background: #fffaf0;
  color: var(--text);
  box-shadow: 0 2px 8px rgba(42, 34, 22, .10);
}
.canvasSegmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.canvasInfoFieldGrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.canvasInfoField {
  min-height: 40px;
  display: grid;
  grid-template-columns: 18px 1fr;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid rgba(83, 70, 50, .15);
  border-radius: 12px;
  background: rgba(255, 255, 255, .58);
  color: #6f6a61;
  font-size: 12px;
  font-weight: 900;
  cursor: pointer;
}
.canvasInfoField.active {
  border-color: rgba(183, 72, 72, .34);
  background: #fffaf0;
  color: var(--text);
}
.canvasInfoField input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.canvasInfoField .nodeInfoIcon {
  width: 16px;
  height: 16px;
  opacity: .9;
}
.canvasThemeOption {
  display: grid;
  grid-template-columns: 42px 1fr;
  align-items: center;
  gap: 8px;
  min-height: 58px;
  padding: 7px;
  border: 1px solid rgba(83, 70, 50, .16);
  border-radius: 14px;
  background: rgba(255, 255, 255, .68);
  text-align: left;
  cursor: pointer;
}
.canvasThemeOption:hover,
.canvasThemeOption:focus-visible {
  border-color: rgba(183, 72, 72, .28);
  background: #fffaf0;
}
.canvasThemeOption.active {
  border-color: var(--dancheong-red);
  box-shadow: inset 0 0 0 2px rgba(183, 72, 72, .12);
}
.canvasThemeOption img {
  width: 42px;
  height: 42px;
  border-radius: 10px;
  object-fit: cover;
  border: 2px solid white;
  box-shadow: 0 3px 8px rgba(38, 31, 24, .14);
}
.canvasThemeOption span {
  display: grid;
  gap: 3px;
  min-width: 0;
}
.canvasThemeOption b {
  color: var(--text);
  font-size: 12.5px;
}
.canvasThemeOption small {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.25;
}
.exportTreeBtn {
  width: auto;
  min-height: 42px;
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  border-radius: 18px;
  font-size: 13px;
  font-weight: 900;
  white-space: nowrap;
}
.exportTreeBtn[hidden] { display: none; }
.canvas {
  position: relative; min-width: 100%; min-height: 100%;
  background: transparent;
}
.treeContent {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  transform-origin: 0 0;
}
.orgChartHeading {
  position: absolute;
  top: 30px;
  left: 34px;
  z-index: 32;
  max-width: min(620px, calc(100% - 68px));
  padding-left: 16px;
  border-left: 5px solid #c99535;
  color: #30271f;
  pointer-events: auto;
}
.orgChartHeadingKicker {
  display: block;
  margin-bottom: 4px;
  color: #8a6a31;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .14em;
}
.orgChartHeading h1,
.orgChartNameButton strong {
  display: block;
  margin: 0;
  font-family: inherit;
  font-size: clamp(32px, 3.5vw, 44px);
  font-weight: 950;
  line-height: 1.08;
  letter-spacing: -.055em;
  text-shadow: 0 2px 0 rgba(255,255,255,.58);
}
.orgChartHeading.besideLeader {
  max-width: min(420px, calc(100% - 48px));
  padding-left: 42px;
  border-left: 0;
}
.orgChartHeading.besideLeader::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 30px;
  height: 3px;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(40, 96, 74, .35), #c99535);
  transform: translateY(-50%);
}
.orgChartHeading.besideLeader h1,
.orgChartHeading.besideLeader .orgChartNameButton strong {
  font-size: clamp(25px, 2.6vw, 34px);
  line-height: 1.08;
}
.orgChartHeading.besideLeader.onLeaderLeft {
  padding-right: 42px;
  padding-left: 0;
  text-align: right;
}
.orgChartHeading.besideLeader.onLeaderLeft::before {
  right: 0;
  left: auto;
  background: linear-gradient(90deg, #c99535, rgba(40, 96, 74, .35));
}
.orgChartHeading.besideLeader.onLeaderLeft .orgChartNameButton {
  flex-direction: row-reverse;
  text-align: right;
}
.treeToolbarRight.treeActionControls {
  top: var(--float-top, 18px);
  right: var(--float-right, 18px);
  bottom: auto;
  display: grid;
  grid-template-columns: max-content max-content;
  grid-template-areas: "mode menu";
  align-items: center;
  justify-items: end;
  gap: 8px;
}
.treeToolbarRight.treeActionControls .modeToggleBtn {
  position: static;
  inset: auto;
  grid-area: mode;
}
.treeToolbarRight.treeActionControls .zoomMenuBtn {
  display: none;
}
.treeToolbarRight.treeActionControls .zoomMenuBtn:not([hidden]) {
  display: none;
}
.treeToolbarRight.treeActionControls .desktopTreeMenuBtn {
  grid-area: menu;
}

@media (max-width: 1280px) {
  .desktopTreeMenuBtn,
  .desktopTreeMenu {
    display: none !important;
  }
}
.treeToolbarRight.treeActionControls .zoomControls {
  top: calc(100% + 10px);
  right: 0;
  bottom: auto;
}
.orgChartNameButton {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.orgChartNameButton strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.orgChartNameButton .bootstrapIcon {
  width: 19px;
  height: 19px;
  flex: 0 0 auto;
  padding: 7px;
  box-sizing: content-box;
  border-radius: 50%;
  background: rgba(255,255,255,.72);
  box-shadow: 0 4px 14px rgba(66,49,27,.12);
  opacity: .72;
}
.orgChartNameButton:hover .bootstrapIcon,
.orgChartNameButton:focus-visible .bootstrapIcon {
  opacity: 1;
  background: #fff8e8;
}
.orgChartNameForm {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.orgChartNameForm input {
  width: min(430px, 56vw);
  min-width: 210px;
  padding: 10px 12px;
  border: 2px solid #c99535;
  border-radius: 14px;
  background: rgba(255,255,255,.94);
  color: #30271f;
  font-size: 22px;
  font-weight: 900;
  outline: none;
}
.orgChartNameForm input:focus {
  box-shadow: 0 0 0 4px rgba(201,149,53,.18);
}
.orgChartNameForm button {
  min-height: 42px;
  white-space: nowrap;
}
.deleteDropZone {
  position: fixed;
  left: 50%;
  bottom: var(--drop-bottom, 22px);
  z-index: 46;
  width: min(300px, calc(100% - 44px));
  min-height: 82px;
  transform: translate(-50%, 18px);
  display: grid;
  grid-template-columns: 44px 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  column-gap: 12px;
  padding: 14px 18px;
  border: 2px dashed rgba(183, 72, 72, .44);
  background: rgba(255, 248, 232, .94);
  color: #783333;
  box-shadow: 0 16px 34px rgba(42, 34, 22, .18);
  opacity: 0;
  pointer-events: none;
  transition: opacity .16s ease, transform .16s ease, background .16s ease, border-color .16s ease;
}
.deleteDropZone.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
.deleteDropZone.offCanvas { display: none; }
.deleteDropZone.over {
  border-color: var(--dancheong-red);
  background: #fff1eb;
  color: #7c1e19;
  box-shadow: 0 0 0 8px rgba(183, 72, 72, .14), 0 18px 38px rgba(42, 34, 22, .24);
}
.deleteDropIcon {
  grid-row: 1 / span 2;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--dancheong-red);
  color: #fff8e8;
  font-size: 26px;
  font-weight: 900;
  line-height: 1;
}
.deleteDropIcon .bootstrapIcon {
  width: 23px;
  height: 23px;
  filter: invert(96%) sepia(8%) saturate(664%) hue-rotate(331deg) brightness(106%) contrast(101%);
}
.deleteDropZone strong {
  font-size: 15px;
  line-height: 1.2;
}
.deleteDropZone small {
  color: inherit;
  font-size: 12px;
  font-weight: 800;
  opacity: .78;
}
#treeLines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 6;
}
.spouseHeart {
  fill: #c74872;
  stroke: #f3eee6;
  stroke-width: 5px;
  paint-order: stroke;
  font-size: 18px;
  font-weight: 900;
  text-anchor: middle;
  dominant-baseline: middle;
}
.node {
  position: absolute; width: 122px; height: 182px;
  border: 0; background: transparent;
  padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); justify-items: center; align-content: start; gap: 5px;
  touch-action: none;
  cursor: grab;
  caret-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  z-index: 2;
}
.node:focus { outline: 0; }
.node:focus-visible .avatar { outline: 3px solid rgba(39, 98, 75, .32); }
.node.me { filter: drop-shadow(0 0 0 rgba(0, 0, 0, 0)); }
.coreCoupleArea {
  position: absolute;
  box-sizing: border-box;
  border: 2px dotted rgba(183, 72, 72, .66);
  border-radius: 10px;
  background: rgba(183, 72, 72, .045);
  pointer-events: none;
  z-index: 0;
}
.bridgeAnchorArea.paternal {
  border-color: rgba(201, 145, 53, .72);
  background: rgba(201, 145, 53, .055);
}
.bridgeAnchorArea.maternal {
  border-color: rgba(143, 165, 177, .78);
  background: rgba(143, 165, 177, .06);
}
/* Shown while dragging a connected card between two siblings, to signal
   "drop here to reorder" without widening the gap itself -- the box sits
   inside the existing gapX space so the connect-onto-a-card gesture doesn't
   get any harder to land. Styled like the "인물 추가" placeholder box
   (.node.placeholder below) -- same dashed-zone-with-glow language -- so
   it reads as "drop here" instead of a barely-visible thin line.
   See attemptSiblingReorder/siblingGapIndicatorTarget in app.js. */
@keyframes reorderGapGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 155, 69, 0); border-color: rgba(201, 155, 69, .55); }
  50% { box-shadow: 0 0 0 8px rgba(201, 155, 69, .18); border-color: rgba(201, 155, 69, .95); }
}
.reorderGapIndicator {
  position: absolute;
  box-sizing: border-box;
  border: 3px dashed rgba(201, 155, 69, .55);
  border-radius: 16px;
  background: rgba(201, 155, 69, .12);
  pointer-events: none;
  z-index: 20;
  animation: reorderGapGlow 1s ease-in-out infinite;
}
.node.dragging {
  cursor: grabbing;
  z-index: 50;
  opacity: .7;
  filter: drop-shadow(0 10px 18px rgba(38, 31, 24, .35));
}
.nodeMenuBtn {
  position: absolute;
  top: -6px;
  right: 2px;
  width: 28px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(83, 70, 50, .18);
  border-radius: 999px;
  background: rgba(255, 250, 240, .94);
  color: #56605a;
  font-size: 17px;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 3px 8px rgba(38, 31, 24, .16);
  z-index: 9;
}
.nodeMenuBtn .bootstrapIcon {
  width: 17px;
  height: 17px;
  filter: invert(36%) sepia(9%) saturate(514%) hue-rotate(91deg) brightness(89%) contrast(87%);
}
.nodeMenuBtn:hover,
.nodeMenuBtn:focus-visible {
  background: #fffaf0;
  color: #8a2f4c;
  outline: 2px solid rgba(199, 72, 114, .25);
}
body:not(.viewerMode) .node:not(.placeholder) .avatar { outline: 2px dashed rgba(83, 70, 50, .38); outline-offset: 3px; }
.unconnectedBadge {
  position: absolute;
  top: -18px;
  left: 50%;
  transform: translateX(-50%);
  padding: 3px 11px;
  background: var(--dancheong-gold, #c99b45);
  color: #2a2013;
  font-size: 11px;
  font-weight: 900;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(38, 31, 24, .22);
  z-index: 8;
}
.unconnectedBadge.moveRank-0 { background: #b74848; color: #fff8e8; }
.unconnectedBadge.moveRank-1 { background: #c99b45; color: #2a2013; }
.unconnectedBadge.moveRank-2 { background: #28604a; color: #fff8e8; }
.unconnectedBadge.moveRank-3 { background: #4d6d8f; color: #fff8e8; }
.unconnectedBadge.moveRank-4 { background: #8a4f77; color: #fff8e8; }
.unconnectedBadge.moveRank-5 { background: #6b6258; color: #fff8e8; }
/* The drop target needs to read as unmistakably "hovered" at a glance --
   it's the one state that actually matters mid-drag, so it gets the
   strongest, most saturated treatment on the page (everything else nearby
   is deliberately calmer, see .node.placeholder below). */
/* Deliberately no z-index or transform/size change here: this class gets
   toggled every pointermove tick while dragging, and both of those caused
   real misbehavior -- z-index popped the target above its siblings
   (jarring), and scaling the avatar changed its own getBoundingClientRect()
   on the very next tick, feeding back into the overlap calculation in
   updateDropTarget() and making the highlight (and sometimes the drop
   itself) flicker/misfire. Outline and color changes don't affect layout,
   so they're safe to toggle rapidly. */
.node.dropTarget .avatar {
  outline: 4px solid #c74872;
  outline-offset: 5px;
  box-shadow: 0 0 0 10px rgba(199, 72, 114, .24), 0 8px 18px rgba(38, 31, 24, .3);
}
.node.dropTarget .nodeName { background: #c74872; }
@keyframes badgePulse {
  0%, 100% { transform: translateX(-50%) scale(1); }
  50% { transform: translateX(-50%) scale(1.08); }
}
@keyframes placeholderGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(199, 72, 114, 0); border-color: rgba(199, 72, 114, .4); }
  50% { box-shadow: 0 0 0 10px rgba(199, 72, 114, .10); border-color: rgba(199, 72, 114, .75); }
}
@keyframes placeholderNewSparkle {
  0%, 100% { box-shadow: 0 0 0 0 rgba(201, 155, 69, 0), 0 0 0 0 rgba(199, 72, 114, 0); filter: brightness(1); }
  18% { box-shadow: 0 0 0 8px rgba(201, 155, 69, .22), 0 0 24px rgba(255, 248, 232, .72); filter: brightness(1.12); }
  38% { box-shadow: 0 0 0 3px rgba(199, 72, 114, .20), 0 0 20px rgba(199, 72, 114, .24); filter: brightness(1.02); }
  62% { box-shadow: 0 0 0 10px rgba(201, 155, 69, .16), 0 0 26px rgba(255, 248, 232, .64); filter: brightness(1.10); }
}
/* The placeholder's dashed guide and drag/drop hit box share the same card
   footprint (see PLACEHOLDER_HIT_W/H in app.js), so the visible spacing is
   the actual grabbable spacing. */
.node.placeholder {
  z-index: 5;
  position: absolute;
  width: 152px;
  height: 184px;
  box-sizing: border-box;
  padding: 28px 0 10px;
  border: 2px dashed rgba(199, 72, 114, .4);
  border-radius: 22px;
  background: rgba(255, 250, 240, .35);
  animation: placeholderGlow 1.8s ease-in-out infinite;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
.node.placeholder.placeholderNew {
  animation: placeholderNewSparkle .55s ease-in-out 4, placeholderGlow 1.8s ease-in-out infinite;
  border-color: rgba(201, 155, 69, .78);
  background: rgba(255, 248, 232, .58);
}
.node.placeholder.dragging { animation: none; border-color: rgba(199, 72, 114, .7); }
.placeholderCard {
  position: relative;
  width: 152px;
  height: auto;
  box-sizing: border-box;
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 6px;
}
.node.placeholder .avatar {
  outline: 2px dashed rgba(83, 70, 50, .5);
  outline-offset: 3px;
  opacity: .88;
}
.node.placeholder .nodeName { background: #8a8378; }
.node.placeholder .nodeRel {
  width: 142px;
  max-width: 142px;
  min-height: 22px;
}
.node.placeholder .unconnectedBadge {
  top: -18px;
  font-size: 13px;
  padding: 5px 14px;
  animation: badgePulse 1.5s ease-in-out infinite;
}
.node.placeholder.dragging .unconnectedBadge { animation: none; }
/* Sits on the dashed box's own top-right corner (a sibling of
   .placeholderCard, not nested in it), half in/half out of the border, like
   a standard card dismiss button -- not tucked inside the card's margin. */
.placeholderCancel {
  position: absolute;
  top: -11px;
  right: -11px;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 2px solid #fffaf0;
  border-radius: 999px;
  background: #56605a;
  color: #fffaf0;
  font-size: 14px;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(38, 31, 24, .3);
  z-index: 7;
}
.placeholderCancel .bootstrapIcon {
  width: 12px;
  height: 12px;
  filter: invert(96%) sepia(8%) saturate(664%) hue-rotate(331deg) brightness(106%) contrast(101%);
}

.relationPicker {
  position: fixed;
  z-index: 200;
  display: grid;
  gap: 4px;
  min-width: 180px;
  padding: 8px;
  background: #fffaf0;
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 16px 34px rgba(38, 31, 24, .30);
}
.relationPickerHead {
  padding: 2px 6px 6px;
  font-size: 12px;
  font-weight: 900;
  color: #6f6a61;
  border-bottom: 1px solid var(--line);
  margin-bottom: 2px;
}
.relationPicker button {
  text-align: left;
  padding: 8px 10px;
  border-radius: 8px;
  border: 0;
  background: transparent;
  font-weight: 700;
  font-size: 13px;
  color: #2a2013;
  cursor: pointer;
}
.relationPicker button:hover { background: rgba(39, 98, 75, .12); }
.relationPicker button.ghost { color: #8a8378; font-weight: 600; }
.relationPicker button.ghost:hover { background: rgba(83, 70, 50, .10); }
.personCardMenu {
  position: fixed;
  z-index: 210;
  width: min(430px, calc(100vw - 24px));
  display: grid;
  gap: 12px;
  padding: 12px;
  background:
    linear-gradient(180deg, rgba(255, 253, 247, .98), rgba(255, 247, 231, .97));
  border: 1px solid rgba(83, 70, 50, .18);
  border-radius: 20px;
  box-shadow: 0 18px 42px rgba(38, 31, 24, .24);
  color: var(--text);
  backdrop-filter: blur(8px);
}
.personCardMenuHead {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) auto;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 7px 12px;
  border-bottom: 1px solid rgba(111, 63, 36, .14);
}
.personCardMenuHead > div {
  min-width: 0;
  display: grid;
  gap: 4px;
}
.personCardMenuHead.orgPersonCardMenuHead {
  grid-template-columns: minmax(0, 1fr) auto;
}
.personViewer .personCardMenuHead { padding-right: 36px; }
.personCardMenuAvatar {
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 3px solid white;
  border-radius: 18px;
  background: var(--photo-bg, #fff8ed);
  box-shadow: 0 6px 14px rgba(42, 34, 22, .16);
}
.personCardMenuAvatar img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}
.personCardMenuKicker {
  color: rgba(40, 96, 74, .78);
  font-size: 11px;
  font-weight: 950;
}
.photoEditBtn {
  flex: 0 0 auto;
  min-width: 104px;
  height: 38px;
  padding: 0 13px;
  border: 1px solid rgba(28, 76, 57, .38);
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  background: #28604a;
  color: #fffaf0;
  box-shadow: 0 7px 16px rgba(40, 96, 74, .22);
  font-size: 12px;
  font-weight: 900;
  line-height: 1;
  cursor: pointer;
}
.photoEditBtn:hover,
.photoEditBtn:focus-visible {
  background: #34765d;
  outline: 2px solid rgba(39, 98, 75, .18);
}
.photoEditBtn .bootstrapIcon {
  width: 14px;
  height: 14px;
  filter: brightness(0) invert(1);
}
.personCardMenuHead .photoEditBtn .photoEditLabel {
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
}
.personViewerClose {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  line-height: 1;
}
.personCardMenuHead strong {
  font-size: 18px;
  line-height: 1.2;
}
.personCardMenuHead em {
  justify-self: start;
  min-width: 0;
  max-width: 100%;
  padding: 4px 9px;
  border-radius: 999px;
  background: rgba(40, 96, 74, .10);
  color: var(--green);
  font-size: 12px;
  font-style: normal;
  font-weight: 900;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.personCardMenuHead span:not(.personCardMenuAvatar):not(.personCardMenuKicker) {
  color: #6f6a61;
  font-size: 12px;
  font-weight: 900;
}
.personCardMenuRows {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
}
.personCardMenuRows div {
  display: grid;
  gap: 4px;
  min-width: 0;
  padding: 10px;
  border: 1px solid rgba(111, 63, 36, .11);
  background: rgba(255, 253, 246, .70);
  border-radius: 14px;
  font-size: 13px;
  line-height: 1.35;
}
.personCardMenuRows div.wide {
  grid-column: 1 / -1;
}
.personCardMenuRows span {
  color: rgba(40, 96, 74, .72);
  font-weight: 900;
  font-size: 12px;
}
.personCardMenuRows b {
  min-width: 0;
  color: #2f2a24;
  font-weight: 800;
  font-size: 14px;
  overflow-wrap: anywhere;
}
.personCardCompact {
  min-height: 36px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid rgba(111, 63, 36, .12);
  background: rgba(255, 253, 246, .72);
  font-size: 13px;
}
.personCardCompact input {
  width: auto;
}
.personCardMenuActions {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(72px, 1fr);
  gap: 8px;
}
.personCardMenu .primary,
.personCardMenu .ghost,
.personCardMenu .danger {
  min-height: 36px;
  padding: 8px 12px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.15;
}
.avatar {
  position: relative;
  width: 101px; height: 104px; border-radius: 10px;
  display: grid; place-items: center;
  background: #fff8ed;
  border: 4px solid white;
  box-shadow: 0 5px 12px rgba(38, 31, 24, .24);
  overflow: visible;
}
.customPhotoBg {
  background: var(--photo-bg, #fff8ed) !important;
}
.avatar.F { background: #fff6ee; }
.avatar.M { border-color: #dbe8f4; }
.avatar.F { border-color: #f6d9e3; }
.node.me { z-index: 4; }
.node.me .avatar {
  width: 101px;
  height: 104px;
  border-color: #fffaf0;
  box-shadow:
    0 0 0 3px rgba(39, 98, 75, .72),
    0 5px 12px rgba(38, 31, 24, .24);
}
.node.friendEmphasis { z-index: 3; }
.node.orgPerson { z-index: 8; }
.node.friendEmphasis .avatar {
  width: 115px;
  height: 119px;
  border-color: var(--dancheong-gold);
  box-shadow: 0 0 0 3px rgba(201, 155, 69, .3), 0 7px 16px rgba(38, 31, 24, .28);
}
.node.friendEmphasis .nodeName {
  background: rgba(171, 126, 48, .90);
  color: #fff8e8;
  font-size: 15px;
}
.avatar img {
  width: 100%;
  height: 100%;
  border-radius: 6px;
  object-fit: cover;
  display: block;
  pointer-events: none;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}
.age-baby img, .age-toddler img { object-position: center 46%; }
.age-senior img, .age-elder img { object-position: center 50%; }
.spouseBadge {
  position: absolute;
  right: -14px;
  bottom: -14px;
  width: 46px;
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: 3px 3px 4px;
  border: 2px solid #fffaf0;
  border-radius: 8px;
  background: rgba(255, 250, 240, .96);
  box-shadow: 0 5px 12px rgba(38, 31, 24, .24);
  z-index: 2;
}
.miniAvatar {
  width: 34px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 2px solid #f6d9e3;
  border-radius: 8px;
  background: #fff6ee;
  overflow: hidden;
}
.miniAvatar img {
  width: 100%;
  height: 100%;
  border-radius: 5px;
  object-fit: cover;
}
.miniName {
  max-width: 42px;
  min-height: 15px;
  padding: 2px 6px;
  color: white;
  background: #56605a;
  border-radius: 999px;
  font-size: 9px;
  font-weight: 900;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  box-shadow: 0 1px 3px rgba(38, 31, 24, .18);
}
.nodeTop { position: relative; display: grid; justify-items: center; gap: 0; min-width: 0; }
.nodeName {
  max-width: 128px; font-weight: 900; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: #fff8e8; background: rgba(83, 70, 50, .90); border-radius: 999px; padding: 5px 13px; font-size: 14px;
  box-shadow: 0 4px 10px rgba(38, 31, 24, .26), 0 1px 2px rgba(255, 250, 240, .38) inset;
  margin-top: -16px;
  position: relative;
  z-index: 2;
}
.node.me .nodeName {
  background: rgba(70, 89, 60, .90);
  box-shadow: 0 4px 10px rgba(38, 55, 35, .28), 0 1px 2px rgba(255, 250, 240, .38) inset;
  font-size: 14px;
  padding: 5px 13px;
}
.nodeRel {
  width: 152px;
  max-width: 152px;
  min-height: 26px;
  color: #6f6a61;
  font-size: 12px;
  font-weight: 900;
  line-height: 1.35;
  text-align: center;
  white-space: normal;
  overflow-wrap: anywhere;
}
.nodeInfoIcons {
  width: 152px;
  max-width: 152px;
  min-height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}
.nodeInfoIcon {
  width: 17px;
  height: 17px;
  display: block;
  opacity: .88;
  background: var(--node-info-color, #c99135);
  -webkit-mask: var(--icon-url) center / contain no-repeat;
  mask: var(--icon-url) center / contain no-repeat;
  filter: drop-shadow(0 1px 1px rgba(38, 31, 24, .18));
}
.nodeInfoText {
  width: 152px;
  max-width: 152px;
  min-height: 26px;
  display: grid;
  place-items: center;
  padding: 0 8px;
  color: #6f5f43;
  font-size: 12px;
  font-weight: 900;
  line-height: 1.25;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.node.compactSummary {
  align-content: start;
}
.node.compactSummary .nodeRel {
  display: none;
}
.node.compactSummary .nodeChildren {
  position: absolute;
  left: 50%;
  top: 150px;
  transform: translateX(-50%);
}
.nodeChildren {
  width: 150px;
  max-width: 150px;
  min-height: 22px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 4px;
}
.nodeChildCat {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  overflow: hidden;
  border: 2px solid #a9c6dd;
  background: #eef5fb;
}
.nodeChildCat.F {
  border-color: #e6a9bf;
  background: #fdf1f5;
}
.nodeChildCat img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.node.selected .avatar { box-shadow: 0 0 0 4px rgba(199, 72, 114, .20), 0 5px 12px rgba(38, 31, 24, .24); }

.node.dropTarget .avatar {
  outline: 7px solid #c74872;
  outline-offset: 8px;
  box-shadow: 0 0 0 14px rgba(199, 72, 114, .28), 0 14px 26px rgba(38, 31, 24, .36);
}
.node.dropTarget .nodeName {
  background: #c74872;
  color: #fff8e8;
  box-shadow: 0 0 0 4px rgba(199, 72, 114, .18), 0 6px 14px rgba(38, 31, 24, .28);
}
