.notice.error {
  background: #fff0ee !important;
  border-color: #dfaaa4;
  color: #922d25;
}

.form-error {
  padding: 10px 12px;
  border: 1px solid #dfaaa4;
  border-radius: 6px;
  background: #fff2f0;
  color: #8f2d24;
}

.form-error.success {
  border-color: #9db9a8;
  background: #edf6f0;
  color: #285b45;
}

.required {
  color: #a63428;
  font-size: 11px;
}

.field-hint {
  float: right;
  color: var(--ink-faint);
  font-size: 11px;
}

input[aria-invalid="true"],
select[aria-invalid="true"],
textarea[aria-invalid="true"] {
  border-color: #b83b31;
  box-shadow: 0 0 0 2px #f8d9d5;
}

button.busy {
  cursor: wait;
}

#bookInfoForm {
  margin-top: 18px;
}

.dialog-close {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  width: 28px;
  height: 28px;
  margin: 0;
  padding: 0;
  border: 1px solid #d5d9d3;
  border-radius: 4px;
  background: #fff;
  color: var(--ink);
  font-size: 20px;
  line-height: 1;
}

.dialog-close:hover {
  background: #f0f3ef;
}

.hanja-control,
.date-control {
  display: flex;
  gap: 7px;
  margin-top: 6px;
}

.hanja-control input,
.date-control input {
  min-width: 0;
  margin: 0;
  flex: 1;
}

.hanja-control button,
.date-control button {
  flex: none;
  padding: 8px 11px;
  white-space: nowrap;
}

.hanja-picker {
  grid-column: 1 / -1;
  max-height: 280px;
  overflow: auto;
  margin: 0 0 16px;
  padding: 14px;
  border: 1px solid #9db9a8;
  border-radius: 8px;
  background: #f7fbf7;
}

.hanja-picker > div:first-child {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.hanja-picker p {
  margin: 8px 0;
  color: var(--ink-faint);
}

.hanja-picker #closeHanja {
  padding: 4px 9px;
}

.hanja-candidates {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
  gap: 6px;
}

.hanja-candidates button {
  padding: 8px 4px;
  border-color: #cad5c7;
  background: #fff;
  color: var(--ink);
  font-family: "Batang", serif;
  font-size: 21px;
}

.hanja-candidates button:hover,
.hanja-candidates button:focus-visible {
  background: #285b45;
  color: #fff;
}

.hanja-candidates p {
  grid-column: 1 / -1;
  margin: 0;
}

.search-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid #cdb98a;
  border-radius: 8px;
  background: #fbf5e6;
  font-size: 13px;
}

.search-notice strong {
  font-weight: 700;
}

.search-notice button {
  padding: 5px 12px;
  font-size: 12px;
}

.tree-options {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  margin-bottom: 14px;
  padding: 12px 15px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: #fff;
}

.tree-options strong {
  color: var(--green);
  font-size: 11px;
  letter-spacing: 2px;
}

.tree-options label {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  font-size: 13px;
  cursor: pointer;
}

.tree-options input {
  width: auto;
  margin: 0;
  padding: 0;
  accent-color: var(--green);
}

/* The sizer is the scrollable box; the body inside it is what gets scaled. */
/* The bar floats with the page so the controls stay in reach part way down a
   three-sheet book. */
.zoom-bar {
  position: sticky;
  top: 64px;
  z-index: 6;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  width: max-content;
  max-width: 100%;
  margin-bottom: 10px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fffdf8f2;
  box-shadow: var(--shadow);
}

.zoom-bar button {
  min-width: 36px;
  padding: 4px 10px;
  font-size: 13px;
}

.zoom-level {
  min-width: 54px;
  color: var(--ink-soft);
  font-size: 13px;
  text-align: center;
}

.zoom-bar small {
  color: var(--ink-faint);
  font-size: 12px;
}

.zoom-scroll {
  overflow: auto;
  /* A bounded window is what makes dragging mean anything; fitFrame sizes it
     to the window under the search box and the tabs. */
  max-height: 74vh;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-raised);
  cursor: grab;
  touch-action: pan-x pan-y;
}

/* The sheet's prose keeps a text cursor; the rest of the canvas is a handle. */
.zoom-scroll .genealogy-person,
.zoom-scroll .genealogy-side,
.zoom-scroll .genealogy-branch,
.zoom-scroll .genealogy-generation h3,
.tree-card strong,
.tree-card small,
.tree-line {
  cursor: text;
}

.zoom-scroll img {
  -webkit-user-drag: none;
}

.zoom-scroll.panning {
  cursor: grabbing;
  /* Only while a drag is actually under way. */
  user-select: none;
}

/* The hairline under the view; the grab area is wider than what is drawn, as
   with the side panel's rule. */
.frame-resizer {
  position: relative;
  height: 6px;
  margin-top: 2px;
  border-radius: 3px;
  background: var(--line);
  cursor: row-resize;
  touch-action: none;
}

.frame-resizer::before {
  content: "";
  position: absolute;
  inset: -5px 0;
}

.frame-resizer:hover,
.frame-resizer:focus-visible,
body.resizing-rows .frame-resizer {
  outline: 0;
  background: var(--green);
}

body.resizing-rows {
  cursor: row-resize;
  user-select: none;
}

/* 전체 화면: the zoom bar and the view take the whole browser window. */
body.view-full {
  overflow: hidden;
}

body.view-full .zoom-bar {
  position: fixed;
  z-index: 41;
  top: 10px;
  left: 50%;
  margin: 0;
  transform: translateX(-50%);
}

body.view-full .zoom-scroll {
  position: fixed;
  z-index: 40;
  inset: 0;
  height: auto !important;
  max-height: none !important;
  padding-top: 58px;
  border: 0;
  border-radius: 0;
}

body.view-full .frame-resizer {
  display: none;
}

/* The 한글/한자 switch on the zoom bar is for 전체 화면 only; elsewhere the one
   beside the view tabs is in reach. */
.zoom-bar .zoom-script {
  display: none;
}

body.view-full .zoom-bar .zoom-script {
  display: inline-block;
}

.zoom-sizer {
  position: relative;
}

.zoom-body {
  width: max-content;
  transform-origin: 0 0;
}

.tree-canvas {
  position: relative;
  background: var(--paper-raised);
}

.family-tree {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
}

.parent-line,
.spouse-line {
  fill: none;
  stroke: #527b64;
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
}

.level-label {
  fill: #6d776f;
  font-size: 12px;
  font-weight: 700;
}

.tree-node {
  position: absolute;
}

.tree-node:hover,
.tree-node:focus-within {
  z-index: 5;
}

.tree-card {
  position: absolute;
  inset: 0;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  overflow: hidden;
  padding: 8px 9px;
  border: 1.5px solid #aebfaf;
  border-radius: 10px;
  background: #fffef9;
  box-shadow: 0 2px 2px #1b372316;
  color: var(--ink);
  font: inherit;
  text-align: center;
}

.tree-card.male {
  border-color: #a7bcd6;
  background: #eaf1fa;
}

.tree-card.female {
  border-color: #dcabb6;
  background: #fbeaee;
}

.tree-card:hover,
.tree-card:focus-visible {
  border-color: #285b45;
  box-shadow: 0 0 0 2px #285b4533;
}

.tree-card strong {
  font-size: 16px;
  line-height: 1.3;
}

.tree-card span {
  max-width: 100%;
  overflow: hidden;
  color: #5d675f;
  font-size: 11.5px;
  line-height: 1.35;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* The record is clamped to two lines so one card height still fits every person. */
.tree-card small {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  margin-top: 2px;
  color: #6d776f;
  font-size: 11px;
  line-height: 1.35;
  text-align: left;
}

/* Quick add handles sit on the card edge that matches the relationship, so the
   family can be built from the tree instead of from the form far below it. */
.tree-add {
  position: absolute;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1.5px solid #cbd6cb;
  border-radius: 50%;
  background: #fff;
  color: var(--green);
  font-size: 15px;
  line-height: 1;
  opacity: 0;
  transition: opacity .12s;
}

.tree-node:hover .tree-add,
.tree-node:focus-within .tree-add {
  opacity: 1;
}

.tree-add:hover,
.tree-add:focus-visible {
  border-color: var(--green);
  background: var(--green);
  color: #fff;
  opacity: 1;
}

.tree-add.off {
  border-style: dashed;
  color: var(--ink-faint);
}

.tree-add.parent {
  top: -13px;
  left: 50%;
  translate: -50% 0;
}

.tree-add.child {
  bottom: -13px;
  left: 50%;
  translate: -50% 0;
}

.tree-add.spouse {
  top: 50%;
  right: -13px;
  translate: 0 -50%;
}

.tree-add.sibling {
  top: 50%;
  left: -13px;
  translate: 0 -50%;
}

.relative-banner {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid #9db9a8;
  border-radius: 8px;
  background: #f2f8f3;
}

.relative-banner p {
  margin: 0 0 10px;
  font-size: 13px;
}

.relative-banner label {
  margin: 0 0 10px;
  font-size: 12px;
}

.relative-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
}

.relative-actions label {
  flex: 1;
  min-width: 160px;
  margin: 0;
}

.relative-actions button {
  padding: 9px 12px;
  font-size: 13px;
}

.tree-photo {
  flex: none;
  width: 78px;
  height: 94px;
  overflow: hidden;
  border: 1px solid #cfd6cd;
  border-radius: 4px;
  background: #f1f2ee;
}

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

@media print {
  .tree-options,
  .zoom-bar,
  .frame-resizer {
    display: none;
  }

  /* Paper prints at full size whatever the screen is zoomed to. */
  .zoom-scroll,
  body.view-full .zoom-scroll {
    position: static;
    padding-top: 0;
    max-height: none;
    overflow: visible;
    border: 0;
    background: none;
  }

  .zoom-sizer {
    width: auto !important;
    height: auto !important;
  }

  .zoom-body {
    transform: none !important;
  }
}

/* The sheet is one A4 page at 96dpi, so the preview is laid out exactly as it
   prints — same columns, same type, same line breaks. */
.traditional-book {
  display: grid;
  /* The book's name at the far right is as narrow as the column the later
     sheets carry at their left. */
  grid-template-columns: minmax(0, 1fr) 44px 46px;
  grid-template-rows: 1fr;
  width: 680px;
  height: 945px;
  padding: 0;
  overflow: hidden;
  border: 4px double #555747;
  background: #fffdf4;
  color: #1f241f;
}

.traditional-book + .traditional-book,
.book-sheet + .book-sheet {
  margin-top: 26px;
}

/* On screen too each sheet shows the printed book's page above it and its place
   among the sheets below; the time of printing is filled in only for paper. */
.sheet-head,
.sheet-foot {
  display: flex;
  justify-content: space-between;
  width: 680px;
  color: var(--ink-soft);
  font: 12px/1.6 var(--sans);
}

.sheet-head .sheet-page {
  font: 15px/1.6 var(--serif);
  letter-spacing: 1px;
}

.sheet-foot {
  justify-content: center;
  margin-top: 4px;
}

.genealogy-side,
.genealogy-branch {
  writing-mode: vertical-rl;
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  padding: 18px 7px;
  border-left: 1px solid #77796a;
  letter-spacing: 2px;
}

.genealogy-side {
  grid-column: 3;
  grid-row: 1;
  gap: 16px;
  font-family: "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
}

/* Batang has no bold face; asking it for one makes the browser overprint the
   glyph a pixel to the side, which reads as a smeared double outline. The bold
   names come from a Myeongjo that ships a real bold, and synthesis stays off so a
   machine with none of them shows clean regular type rather than the smear. */
.genealogy-side strong {
  font-family: "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
  font-size: 21px;
  font-weight: 700;
  font-synthesis: none;
}

.genealogy-side span {
  font-size: 14px;
}

.genealogy-side small {
  color: #5f655f;
  font-size: 12px;
  letter-spacing: 1px;
}

.genealogy-branch {
  grid-column: 2;
  grid-row: 1;
  font: 700 18px/1 "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
  font-synthesis: none;
}

/* Every sheet after the first has the book's name and 파 at its left, in one
   narrow column. The entries are set from the right, so the room it leaves
   only widens the space at their left. */
.traditional-book.margin-left {
  grid-template-columns: 46px minmax(0, 1fr);
}

.traditional-book.margin-left .genealogy-body {
  grid-column: 2;
}

.genealogy-margin {
  grid-column: 1;
  grid-row: 1;
  writing-mode: vertical-rl;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 18px 0;
  border-right: 1px solid #77796a;
  letter-spacing: 2px;
  font-family: "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
}

.genealogy-margin strong {
  font-size: 21px;
  font-weight: 700;
  font-synthesis: none;
}

.genealogy-margin b {
  font-size: 18px;
  font-weight: 700;
  font-synthesis: none;
}

.genealogy-margin span {
  font-size: 14px;
}

.genealogy-margin small {
  color: #5f655f;
  font-size: 12px;
  letter-spacing: 1px;
}

.genealogy-body {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Six equal 世 rows on every sheet, so the horizontal rules and the 世 column rule
   run edge to edge even where a generation has no entry yet. */
.genealogy-generation {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 40px;
  flex: 1 1 0;
  min-height: 0;
  border-bottom: 1px solid #77796a;
}

.genealogy-generation:last-child {
  border-bottom: 0;
}

.genealogy-generation h3 {
  grid-column: 2;
  grid-row: 1;
  writing-mode: vertical-rl;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 8px 5px;
  border-left: 1px solid #77796a;
  font: 400 14px/1.3 "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
  letter-spacing: 1px;
}

.genealogy-entries {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  flex-direction: row-reverse;
  justify-content: flex-start;
  align-items: stretch;
  min-width: 0;
  overflow: hidden;
}

/* One person is one vertical text block; long lines wrap into further columns to
   the left exactly as the printed page does. Batang is only a fallback here: at
   the sheet's small sizes it draws from pixel bitmaps whose vertical placement is
   off, so in a column 二 rides up against 九 and 二二 runs together, while an
   outline Myeongjo keeps every character in step. */
.genealogy-person {
  writing-mode: vertical-rl;
  flex: 0 0 auto;
  height: 100%;
  padding: 8px 4px 8px 7px;
  font: 11px/1.28 "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
}

.genealogy-person strong {
  font-family: "Noto Serif KR", "HCR Batang", "KoPubWorld바탕체", "KoPub바탕체", "Nanum Myeongjo", "Batang", serif;
  font-size: 18px;
  font-weight: 700;
  font-synthesis: none;
  letter-spacing: 0;
}

/* The book sets the 子/女 mark smaller than the name and leaves a small gap after
   it; margin-inline-end is the gap below the mark in vertical text. A Myeongjo
   bold is too light at this size to tell the mark from the text around it, so it
   takes Malgun Gothic's bold, which every Windows machine carries. */
.genealogy-person strong i {
  margin-inline-end: 4px;
  font-family: "Malgun Gothic", "Apple SD Gothic Neo", sans-serif;
  font-size: 12px;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0;
}

.genealogy-person strong em {
  color: #39443d;
  font-size: 9.5px;
  font-weight: 400;
  font-style: normal;
  letter-spacing: 0;
}

.genealogy-person span {
  display: block;
}

/* A column set in its place under its parent: the row is the ground it stands
   on, measured from the right, as the page is read. */
.genealogy-entries {
  position: relative;
}

.genealogy-person.placed {
  position: absolute;
  top: 0;
}

/* Trim the empty space around 一 (top, then bottom in vertical text) to about
   the gap between other characters; trimmed any further, 一 would touch them. */
.genealogy-person b.thin-one {
  margin-inline: -0.3em -0.37em;
  font-weight: inherit;
}

.genealogy-person .genealogy-note {
  color: #47504a;
  font-size: 10px;
  line-height: 1.35;
}

.genealogy-empty {
  margin: auto;
  color: var(--ink-faint);
}

@media print {
  /* The screen sheet is already one A4 page; print only restates it in mm so the
     browser fits it to the paper, and keeps the grid from being split up. */
  .traditional-book {
    width: 180mm;
    height: 250mm;
    margin: 0;
    break-inside: avoid;
  }

  /* A sheet is a page of paper with no margin of the browser's, which is what
     keeps the browser from printing its own head and foot (the date, the app's
     title, its address) around it; the sheet sets its own margins and lines. */
  .book-sheet {
    page: book-sheet;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
    width: 210mm;
    height: 297mm;
    padding: 10mm 15mm 8mm;
    break-after: page;
  }

  .book-sheet:last-child {
    break-after: auto;
  }

  .book-sheet + .book-sheet {
    margin-top: 0;
  }

  .sheet-head,
  .sheet-foot {
    display: flex;
    justify-content: space-between;
    width: 180mm;
    color: #333;
    font: 9pt/1 var(--sans);
  }

  .sheet-head {
    margin-bottom: 5mm;
  }

  .sheet-head .sheet-page {
    font: 11pt/1 var(--serif);
    letter-spacing: 1px;
  }

  .sheet-foot {
    justify-content: center;
    margin-top: auto;
  }

  .genealogy-body,
  .genealogy-generation,
  .genealogy-entries,
  .genealogy-person {
    break-inside: avoid;
  }

  .tree-options {
    display: none;
  }
}

/* ── 가족 추가 ──────────────────────────────────────── */
/* Both ways in stay on screen: register someone new, or pick someone already
   recorded. The old single toggle hid whichever one it was not showing. */
.relative-modes {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.relative-modes button {
  flex: 1;
  padding: 9px 12px;
  font-size: 13px;
}

.relative-modes button[aria-pressed="true"] {
  border-color: var(--green-deep);
  background: var(--green-deep);
  color: #fff;
}

#relativeKindDialog {
  width: min(420px, 94vw);
}

#relativeKindText {
  margin: 0 0 14px;
  font-size: 13px;
}

.relative-kinds {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 14px;
}

.relative-kinds button {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper-raised);
  color: var(--ink);
  text-align: left;
}

.relative-kinds button strong {
  font-size: 15px;
}

.relative-kinds button small {
  color: var(--ink-soft);
  font-size: 11.5px;
}

.relative-kinds button:hover {
  border-color: var(--green);
}

/* A sibling needs a parent to share, so that choice says so before it is taken. */
.relative-kinds button.off {
  border-style: dashed;
}

.relative-kinds button.off strong,
.relative-kinds button.off small {
  color: var(--ink-faint);
}

#relativeKindNote {
  margin: 0 0 12px;
}

/* 가족 추가 opens a whole flow of its own, so it is filled like + 인물 등록
   rather than outlined. An outline among outlines was not seen. It takes 단청
   blue, the one hue the page does not otherwise use, so it never reads as a
   second 저장, and it stands off at the far right where the row ends. */
#addFamily {
  margin-left: auto;
  border-color: #1d3a5f;
  background: #24507f;
  color: #fff;
  box-shadow: 0 1px 2px #1d3a5f33, 0 6px 16px #1d3a5f2e;
}

#addFamily:hover {
  border-color: #16304f;
  background: #16304f;
  color: #fff;
}

/* A window taller than the screen scrolls inside itself, and 저장 went under the
   fold with everything else — you had to scroll to find out the window even had
   buttons. The row now rides the bottom of the window and is always in reach. */
#personDialog .actions {
  position: sticky;
  bottom: 0;
  z-index: 2;
  margin: 10px -28px 0;
  padding: 14px 28px;
  border-top: 1px solid var(--line-soft);
  background: var(--paper-raised);
}

#confirmDialog {
  width: min(420px, 94vw);
}

#confirmText {
  margin: 0 0 20px;
  font-size: 14px;
  line-height: 1.7;
  /* The dates are read back on their own line. */
  white-space: pre-wrap;
}

/* 확인 last, so the eye passes 취소 on the way to it. */
.confirm-actions {
  justify-content: flex-end;
}

/* ── 스캔 보고 옮겨 적기 ─────────────────────────────── */
#scanDialog {
  width: min(1240px, 97vw);
}

.scan-layout {
  display: grid;
  grid-template-columns: minmax(300px, 44fr) minmax(360px, 56fr);
  gap: 18px;
  align-items: start;
}

.scan-pane {
  position: sticky;
  /* Just under the window's fixed head, and short enough to stand whole
     between it and the buttons at the foot: the scan, its source and its
     zoom never move while the lines beside them scroll. */
  top: 63px;
}

#scanDialog .scan-frame {
  height: max(240px, calc(90vh - 368px));
}

.scan-source {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  margin-bottom: 10px;
}

.scan-source label {
  flex: 1;
  min-width: 0;
  margin: 0;
}

.scan-source button {
  flex: none;
  padding: 9px 12px;
  font-size: 13px;
}

.scan-zoom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.scan-zoom button {
  padding: 5px 10px;
  font-size: 12px;
}

.scan-zoom small {
  color: var(--ink-faint);
  font-size: 11.5px;
}

/* The page is read at whatever size the eye needs, so the frame scrolls under it. */
.scan-frame {
  overflow: auto;
  height: min(62vh, 620px);
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper-sunk);
  cursor: grab;
}

.scan-frame.dragging {
  cursor: grabbing;
}

.scan-frame img {
  display: block;
  width: 100%;
  max-width: none;
  /* A dragged picture must move the frame, not fly off on its own. */
  user-select: none;
  -webkit-user-drag: none;
}

#scanEmpty {
  margin: 0;
  padding: 24px;
  text-align: center;
}

.scan-rows > p {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.7;
}

/* One person to a line, in two ranks: the name above, the rest below. */
.scan-row {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) minmax(0, 1fr) auto 78px 28px;
  gap: 6px 8px;
  margin-bottom: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line-soft);
  border-radius: 8px;
  background: var(--paper);
}

.scan-row label {
  min-width: 0;
  margin: 0;
  font-size: 11px;
}

.scan-row input,
.scan-row select,
.scan-row textarea {
  margin-top: 3px;
  padding: 6px 8px;
  font-size: 13px;
}

/* A note on record and what a reading adds to it stand on lines of their own. */
.scan-row textarea {
  min-height: 34px;
  line-height: 1.45;
  resize: vertical;
}

.scan-row .scan-hanja {
  align-self: end;
  padding: 7px 9px;
  font-size: 12px;
}

.scan-row .scan-drop {
  align-self: end;
  width: 28px;
  padding: 0;
  height: 32px;
  border-color: var(--line);
  background: #fff;
  color: var(--ink-faint);
  font-size: 15px;
  line-height: 1;
}

.scan-row .scan-drop:hover {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--accent);
}

.scan-row label:nth-of-type(5) { grid-column: 1 / 3; }
.scan-row label:nth-of-type(6) { grid-column: 3 / 4; }
.scan-row label:nth-of-type(7) { grid-column: 4 / 7; }
/* 字·墓·기일 run long, so the record takes a rank of its own. */
.scan-row label:nth-of-type(8) { grid-column: 1 / -1; }

.scan-actions {
  position: sticky;
  bottom: 0;
  z-index: 2;
  align-items: center;
  margin: 12px -28px 0;
  padding: 14px 28px;
  border-top: 1px solid var(--line-soft);
  background: var(--paper-raised);
}

#scanCount {
  margin-right: auto;
  font-size: 12.5px;
}

@media (max-width: 900px) {
  .scan-layout {
    grid-template-columns: 1fr;
  }

  .scan-pane {
    position: static;
  }
}

/* A line that stands for someone already in the book is marked, so a page of
   corrections cannot be mistaken for a page of new people. */
.scan-row.filling {
  border-color: #a9bcd4;
  background: #f2f6fb;
}

.scan-match {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  grid-column: 1 / -1;
  margin: 2px 0 0;
  font-size: 11.5px;
  color: var(--ink-soft);
}

.scan-match span {
  margin-right: auto;
}

.scan-match button {
  padding: 4px 9px;
  font-size: 11.5px;
}

.scan-match button[aria-pressed="true"] {
  border-color: #23456f;
  background: #23456f;
  color: #fff;
}

/* A generation's lines in a reading are headed with it. */
.scan-generation {
  margin: 14px 0 6px;
  padding-bottom: 3px;
  border-bottom: 1px solid var(--line);
  color: var(--green);
  font: 700 13px/1.4 var(--sans);
}

/* The rule a new family starts under, as the book draws between two lines. */
.scan-family {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  margin: 18px 0 10px;
  padding: 10px 14px;
  border-top: 3px solid #b3322b;
  border-radius: 0 0 var(--radius) var(--radius);
  background: #fbf0ee;
  font-size: 13px;
}

.scan-family strong {
  color: #b3322b;
}

.scan-family span {
  flex: 1 1 260px;
  color: var(--ink-soft);
}

/* 신규 등록 and 업데이트 file their own line; a line filed so is marked. */
.scan-match button.scan-new {
  cursor: pointer;
}

.scan-match button.scan-new:hover {
  filter: brightness(.95);
}

/* 신규 등록 adds someone the book does not have, so it stands out from 업데이트:
   solid green against the pale blue of a line that only fills blanks. */
.scan-match button.scan-new:not(.scan-update) {
  border-color: var(--green);
  background: var(--green);
  color: #fff;
}

.scan-row.saved {
  box-shadow: inset 4px 0 0 var(--green);
}

.scan-match .scan-done {
  color: var(--green);
}

/* 업데이트 reads as a mark like 신규 등록, in the blue of a matched line. */
.scan-match .scan-update {
  border-color: #a9bcd4;
  background: #e8eff8;
  color: #23456f;
}

/* Lines that will not be filed are dimmed, not removed. */
.scan-family.skipped ~ .scan-row {
  opacity: .45;
}

/* Not a choice, only what saving this line will do. */
.scan-match .scan-new {
  padding: 3px 9px;
  border: 1px solid #b9cbbf;
  border-radius: 999px;
  background: #eef5f0;
  color: var(--green);
  font-weight: 700;
}

/* The key is asked for once, beside the buttons that need it. */
.claude-key {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px 12px;
  margin: 0 0 12px;
  padding: 10px 12px;
  border: 1px solid #a9bcd4;
  border-radius: var(--radius);
  background: #f2f6fb;
}

/* Shown only once 'Claude로 판독' finds no key; display:flex above would
   otherwise override the hidden attribute. */
.claude-key[hidden] {
  display: none;
}

.claude-key label {
  flex: 1 1 260px;
}

.claude-key small {
  flex-basis: 100%;
}

.scan-start {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.scan-start label {
  flex: none;
  width: 150px;
  margin: 0;
}

#scanReadNote {
  margin: 0;
  font-size: 12px;
  line-height: 1.6;
}

/* A year that does not match its 간지 means one of the two was misread. */
.scan-row.doubted {
  border-color: #dfaaa4;
  background: #fff5f3;
}

/* The person a search found, ringed where they stand in the whole drawing. */
.tree-card.found,
.genealogy-person.found {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
}

#relationHint {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 1.7;
}

#relationScope {
  margin: 14px 0 4px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 12px;
}

/* The descent to someone who married in, drawn dashed so it is not mistaken for
   the line of the family the tree is about. */
.parent-line.married-in {
  stroke-dasharray: 5 4;
  opacity: 0.75;
}

/* Which line means what, said where the lines are. */
.tree-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  /* Pushed to the far end of the zoom row, into the space it was leaving. */
  margin: 0 0 0 auto;
  font-size: 12px;
  color: var(--ink-soft);
}

.tree-legend span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.tree-legend i {
  width: 26px;
  height: 0;
  border-top: 2px solid var(--green);
}

.tree-legend .line-dashed {
  border-top-style: dashed;
  opacity: 0.75;
}

/* Outside this book's line: dashed, like the line that reaches it. */
.tree-card.outside {
  border-style: dashed;
  background: var(--paper);
}

#marriageDialog {
  width: min(480px, 94vw);
}

#marriageText {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.7;
}

.marriage-children {
  max-height: 46vh;
  overflow: auto;
  margin-bottom: 12px;
  border: 1px solid var(--line-soft);
  border-radius: 8px;
}

.marriage-child {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 9px 12px;
  border-bottom: 1px solid var(--line-soft);
  font-size: 13px;
  font-weight: 400;
}

.marriage-child:last-child {
  border-bottom: 0;
}

.marriage-child input {
  flex: none;
  margin: 0;
}

.marriage-child span {
  flex: 1;
  min-width: 0;
}

/* Which marriage it is under now, so a move is a known change. */
.marriage-child em {
  flex: none;
  color: var(--ink-faint);
  font-size: 11.5px;
  font-style: normal;
}

.marriage-child input:disabled + span {
  color: var(--ink-faint);
}

.marriage-actions {
  justify-content: flex-end;
}

/* A syllable the dictionary does not hold: said, not skipped past. */
.hanja-none {
  margin: 0 0 10px;
  color: var(--ink-soft);
  font-size: 13px;
}

/* The date box keeps the look of the browser's own: 연도-월-일 in one field with
   the calendar at its end. Only now a part may be left empty. */
.date-box {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  min-width: 0;
  margin-top: 6px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #fff;
  color: var(--ink);
  font: 15px/1.5 var(--sans);
  cursor: text;
}

.date-control .date-box { margin: 0; }

.date-box:focus-within {
  border-color: var(--green);
  box-shadow: 0 0 0 3px #2f5d4a22;
}

.date-box:has([aria-invalid="true"]) {
  border-color: #b83b31;
  box-shadow: 0 0 0 2px #f8d9d5;
}

.date-box input[data-seg],
.date-control .date-box input[data-seg],
.scan-row .date-box input[data-seg] {
  flex: none;
  width: 2.2ch;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: transparent;
  box-shadow: none;
  color: inherit;
  font: inherit;
  text-align: center;
}

.date-box input[data-seg="y"],
.date-control .date-box input[data-seg="y"],
.scan-row .date-box input[data-seg="y"] { width: 4.4ch; }

.date-box input[data-seg]:focus { background: #cfe3d8; }
.date-box input[data-seg]::placeholder { color: var(--ink); }
.date-box span { padding: 0; }

.date-box .date-calendar {
  display: grid;
  place-items: center;
  margin: 0 0 0 auto;
  padding: 2px;
  border: 0;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}

/* The browser's calendar, opened from the icon and never shown as a box. */
.date-box .date-native {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.scan-row .date-box {
  margin-top: 3px;
  padding: 6px 8px;
  font-size: 13px;
}

/* The page number read off the photo, beside the count and open to correction. */
.scan-start .scan-page {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  margin: 0;
  font-size: 13px;
}

.scan-start .scan-page input {
  width: 5.5em;
  padding: 4px 8px;
}

/* Reading a page off a photo is what the app is for, so its button stands
   apart from the green ones beside it: the seal red, a little raised. */
#openScan {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 2px 8px #9c3b2e40;
}

#openScan:hover {
  border-color: #7f2f24;
  background: #7f2f24;
  box-shadow: 0 4px 14px #9c3b2e59;
}

#openScan span {
  margin-right: 2px;
}

/* An attachment and the button that takes it off, on one line. */
#fileList .file-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

#fileList .file-row a {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

#fileList .file-row button {
  flex: none;
  padding: 4px 10px;
  font-size: 12px;
}

/* ── 가계도 인쇄 ─────────────────────────────────── */
/* Made only for the paper, and taken away again once it is printed. */
.tree-print-pages {
  display: none;
}

@media print {
  body.print-tree #view > :not(.tree-print-pages),
  body.print-tree .view-bar {
    display: none !important;
  }

  body.print-tree .tree-print-pages {
    display: block;
  }

  /* A sheet sets its own margin, as the book's do, which leaves the browser
     no room to print its own head and foot (the date, the app's title). */
  .tree-page {
    page: tree-sheet;
    box-sizing: border-box;
    width: 297mm;
    height: 210mm;
    padding: 10mm;
    overflow: hidden;
    break-after: page;
  }

  /* The whole tree turned a quarter clockwise to fill the sheet. */
  .tree-turned {
    position: relative;
  }

  .tree-turned-inner {
    position: absolute;
    top: 0;
    left: 0;
    transform-origin: top left;
  }

  .tree-page:last-child {
    break-after: auto;
  }

  .tree-page.tall {
    page: tree-sheet-tall;
    width: 210mm;
    height: 297mm;
  }

  .tree-print-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin: 0 0 3mm;
    color: #222;
    font: 10pt/1.2 var(--sans);
  }

  .tree-print-head strong {
    font: 700 13pt/1.2 var(--serif);
  }

  /* One sheet's share of the tree, drawn at the sheet's scale. */
  .tree-tile {
    position: relative;
    overflow: hidden;
  }

  .tree-tile-shift {
    position: absolute;
  }

  .tree-tile .tree-add {
    display: none !important;
  }

  .tree-tile .tree-card,
  .tree-tile .family-tree,
  .tree-tile-level {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* A sheet of the tree says its rows' 世 in its own strip at the left. */
  .tree-tile-level {
    position: absolute;
    left: 0;
    width: 60px;
    padding: 1px 0;
    background: #fffdf4;
    color: #555;
    font: 700 13px/1.2 var(--sans);
    text-align: center;
  }

  .tree-tile-part .level-label {
    display: none;
  }

  .tree-tile-part {
    background: #fffdf4;
  }
}

/* The view's controls in the row of its tabs: flat, on one line, the hint
   about dragging and Ctrl+wheel short and small at its end. */
.view-tools {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
}

.view-tools .zoom-bar {
  position: static;
  margin: 0;
  padding: 4px 8px;
  box-shadow: none;
}

.view-tools .zoom-bar {
  gap: 6px;
}

.view-tools .zoom-bar button {
  padding: 4px 8px;
}

.view-tools .zoom-level {
  min-width: 40px;
}

/* Two short lines: 끌어서 이동 / Ctrl+휠 확대·축소. */
.view-tools .zoom-bar small {
  max-width: 96px;
  font-size: 11px;
  line-height: 1.25;
}

.view-tools .zoom-bar small .long {
  display: none;
}

.zoom-bar small .short {
  display: none;
}

.view-tools .zoom-bar small .short {
  display: inline;
}

/* In the book a drag moves the sheets; the text is selected with Shift held. */
.zoom-scroll .traditional-book .genealogy-person,
.zoom-scroll .traditional-book .genealogy-side,
.zoom-scroll .traditional-book .genealogy-branch,
.zoom-scroll .traditional-book .genealogy-margin,
.zoom-scroll .traditional-book .genealogy-generation h3 {
  cursor: grab;
}

.zoom-scroll.panning .traditional-book * {
  cursor: grabbing;
}

/* A window's title, with its 한글/한자 switch just after it, stays in view
   while the window scrolls, and so does the close button. */
dialog .dialog-head {
  position: sticky;
  /* The window's own 28px padding is above the head; it sticks at the edge. */
  top: -28px;
  z-index: 20;
  justify-content: flex-start;
  align-items: center;
  gap: 14px;
  margin: -28px -28px 18px !important;
  padding: 24px 68px 14px 28px !important;
  /* Its paper reaches out to the window's sides and top whatever the
     window's padding, so nothing scrolls past beside it; the foot is
     left clear with a hairline. */
  box-shadow: 0 0 0 80px var(--paper-raised), 0 1px 0 var(--line-soft);
  clip-path: inset(-80px -80px -1px -80px);
  background: var(--paper-raised);
}

dialog .dialog-head [data-script-toggle] {
  margin-top: 6px;
}

dialog .dialog-close {
  position: sticky;
  top: -18px;
  float: right;
  z-index: 21;
  margin: -18px -18px 0 0;
}

/* The row of tabs, controls and 한글/한자 never breaks onto a second line: as
   the room narrows (a 14-inch screen, a wide sidebar) the hint goes first,
   then the buttons tighten and their type gets smaller. */
.view-bar {
  flex-wrap: nowrap;
  container-type: inline-size;
}

.view-bar nav {
  flex: none;
}

@container (max-width: 1060px) {
  .view-tools .zoom-bar small {
    max-width: 78px;
    font-size: 10px;
  }
}

@container (max-width: 940px) {
  .view-bar nav button {
    padding: 7px 12px;
    font-size: 13px;
  }

  .view-tools .zoom-bar {
    gap: 4px;
    padding: 3px 6px;
  }

  .view-tools .zoom-bar button {
    min-width: 28px;
    padding: 3px 7px;
    font-size: 12px;
  }

  .view-tools .zoom-level {
    min-width: 34px;
    font-size: 12px;
  }
}

@container (max-width: 800px) {
  .view-bar nav button {
    padding: 6px 9px;
    font-size: 12px;
  }

  .view-bar > button {
    padding: 5px 8px;
    font-size: 11px;
  }
}

/* ── 좁은 화면: 줄바꿈 없이 줄어들기 ───────────────── */
/* A button's words never break inside it. */
button {
  white-space: nowrap;
}

/* The page's width is what is left beside the sidebar, which the reader can
   widen, so the title row and the tab row answer to that width. */
.content {
  container-type: inline-size;
  container-name: content;
}

.page-title h1 {
  white-space: nowrap;
}

.page-actions {
  flex-wrap: nowrap;
}

@container content (max-width: 1060px) {
  .page-title h1 {
    font-size: 28px;
  }

  .page-actions {
    gap: 6px;
  }

  .page-actions button {
    padding: 8px 11px;
    font-size: 13px;
  }
}

@container content (max-width: 900px) {
  .page-title h1 {
    font-size: 24px;
  }

  .page-actions button {
    padding: 6px 9px;
    font-size: 12px;
  }
}

@container content (max-width: 760px) {
  .page-title {
    flex-wrap: wrap;
  }
}

/* The tab row, at its narrowest: smaller still, the level shown only while
   there is room for it. */
@container (max-width: 700px) {
  .view-bar nav button {
    padding: 5px 7px;
    font-size: 11.5px;
  }

  .view-tools .zoom-bar {
    gap: 3px;
    padding: 2px 4px;
  }

  .view-tools .zoom-bar button {
    min-width: 24px;
    padding: 3px 5px;
    font-size: 11px;
  }

  .view-tools .zoom-level {
    min-width: 30px;
    font-size: 11px;
  }

  .view-tools .zoom-bar small {
    max-width: 64px;
    font-size: 9.5px;
  }
}

/* The first screen's sign-in card: its title and buttons stay on one line. */
.intro-side .panel h2 {
  white-space: nowrap;
  font-size: clamp(17px, 1.6vw, 20px);
}

.intro-side .panel .actions {
  flex-wrap: nowrap;
}

@media (max-width: 1180px) {
  .welcome.intro {
    grid-template-columns: minmax(0, 1fr) minmax(300px, .9fr);
    gap: 28px 32px;
  }

  .intro-scroll {
    font-size: 24px;
    letter-spacing: 4px;
    padding: 18px 10px;
  }
}

/* The tree's 표시 항목 row tightens before it wraps. */
@container content (max-width: 960px) {
  .tree-options {
    gap: 4px 10px;
    font-size: 12px;
  }

  .tree-options label {
    gap: 4px;
  }
}

@container content (max-width: 760px) {
  .tree-options {
    gap: 4px 8px;
    font-size: 11px;
  }
}

/* The page's 한글/한자 switch leads the title row's buttons, set apart and
   unlike them: a two-part switch, 한글 | 漢字, the side in view filled in
   red, so which is showing reads at a glance. */
.page-actions .title-script {
  display: inline-flex;
  align-items: stretch;
  margin-right: 20px;
  padding: 3px;
  border: 2px solid var(--accent);
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 2px 8px #b3372a33;
}

.page-actions .title-script span {
  padding: 6px 14px;
  border-radius: 999px;
  color: var(--accent);
  font: 800 14px/1.2 var(--sans);
  letter-spacing: .5px;
  transition: background .15s, color .15s;
}

.page-actions .title-script span:last-child {
  font-family: var(--serif);
}

.page-actions .title-script span.on {
  background: var(--accent);
  color: #fff;
}

.page-actions .title-script:hover {
  border-color: #8f2a1f;
  background: #fff5f2;
}

.page-actions .title-script:hover span.on {
  background: #8f2a1f;
}

@container content (max-width: 1060px) {
  .page-actions .title-script {
    margin-right: 12px;
  }

  .page-actions .title-script span {
    padding: 5px 10px;
    font-size: 13px;
  }
}

/* The bar itself never wraps; its hint keeps two short lines, the second
   shortened where room is least. */
.view-tools .zoom-bar {
  flex-wrap: nowrap;
}

.view-tools .zoom-bar small {
  white-space: nowrap;
  max-width: none;
}

@container (max-width: 780px) {
  .view-tools .zoom-bar small {
    font-size: 9px;
    letter-spacing: -0.3px;
  }

  .view-tools .zoom-bar button {
    padding: 3px 4px;
  }
}

/* At its narrowest the whole row takes the smallest type, so nothing is
   hidden and nothing overlaps. */
@container (max-width: 780px) {
  .view-bar {
    gap: 6px;
  }

  .view-bar nav button {
    padding: 4px 6px;
    font-size: 11px;
  }

  .view-tools .zoom-bar {
    gap: 2px;
    padding: 2px 4px;
  }

  .view-tools .zoom-bar button {
    min-width: 20px;
    padding: 2px 4px;
    font-size: 10.5px;
  }

  .view-tools .zoom-level {
    min-width: 28px;
    font-size: 10.5px;
  }

  .view-bar > button {
    padding: 4px 6px;
    font-size: 10.5px;
  }
}

/* Buttons never squeeze into one another: the bar takes the room its
   controls need, and the type above shrinks to make that room. */
.view-tools {
  flex: 0 1 auto;
}

.view-tools .zoom-bar > * {
  flex: none;
}

/* 웹 공유 칸 (왼쪽, 족보 선택 바로 아래). 족보 정보처럼 남색 서가 안의 종이 카드입니다. */
#workspace > aside .share-panel {
  margin: 16px 0;
  padding: 14px 14px;
  font-size: 13px;
  border: 1px solid #ffffff22;
  border-radius: var(--radius);
  background: var(--paper-raised);
  color: var(--ink);
  box-shadow: 0 6px 20px #0000003a;
}

.share-panel h3 {
  margin: 0 0 8px;
  padding-bottom: 8px;
  font-size: 15px;
  border-bottom: 1px solid var(--line-soft);
  color: var(--green-deep);
}

/* 안의 입력 칸은 카드 속 카드가 되지 않게 둡니다. */
#workspace > aside .share-panel form {
  margin: 8px 0 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}

.share-panel > div > button,
.share-actions button {
  width: 100%;
}

.share-panel .share-stop {
  margin-top: 10px;
}

/* 작은 칸이라 글자와 단추를 한 단계 줄입니다. */
.share-panel .muted,
.share-panel label {
  margin: 0;
  font-size: 12px;
}

.share-panel input {
  padding: 7px 10px;
  font-size: 13px;
}

.share-panel button {
  padding: 7px 10px;
  font-size: 13px;
}

.share-status {
  font-size: 12px;
}

.share-actions {
  display: flex;
  gap: 7px;
  margin-top: 8px;
}

.share-status {
  margin: 8px 0 0;
  font-size: 13px;
  color: #3f6b4a;
}

.share-status.error {
  color: #b42318;
}

/* 무료 인원 안내 (왼쪽, 족보 선택 아래) */
#workspace > aside .plan-note {
  margin: 10px 0 0;
  padding: 9px 12px;
  border: 1px solid #ffffff22;
  border-radius: var(--radius);
  background: var(--paper-raised);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  box-shadow: 0 6px 20px #0000003a;
}

/* 다 쓰면 읽히도록 밝은 붉은 바탕에 진한 붉은 글씨로 둡니다. */
#workspace > aside .plan-note.full {
  border-color: #e7b3ab;
  background: #fff1ee;
  color: #a1281d;
}

/* 가려진 칸의 눈 단추 */
.reveal {
  position: relative;
  display: block;
}

.reveal input {
  width: 100%;
  padding-right: 42px;
}

/* 엣지가 따로 그리는 눈은 겹치지 않게 감춥니다. */
.reveal input::-ms-reveal {
  display: none;
}

.reveal-eye {
  position: absolute;
  top: 50%;
  right: 6px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #6b7280;
  transform: translateY(-50%);
  cursor: pointer;
}

.reveal-eye:hover {
  color: var(--ink);
  background: transparent;
}

/* 웹 공유 제목 옆의 족보 이름 */
.share-panel h3 small {
  margin-left: 6px;
  color: var(--ink-faint);
  font-size: 12px;
  font-weight: 400;
}

/* 선택한 족보 정보: 제목 옆에 한글/한자 전환 */
#workspace > aside form .form-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line-soft);
}

#workspace > aside form .form-head h3 {
  margin: 0;
  padding: 0;
  border: 0;
}

#workspace > aside form .form-head button {
  flex: none;
  width: auto;
  padding: 5px 10px;
  font-size: 12px;
}

/* 무료 인원 안내가 웹 공유 아래로 오면서 족보 선택과 띄웁니다. */
#workspace > aside .plan-note {
  margin-bottom: 14px;
}

/* 정식판 창 */
#licenseDialog {
  width: min(480px, calc(100vw - 32px));
}

#licenseDialog p {
  margin: 0 0 10px;
}

.license-steps {
  margin: 4px 0 16px;
  padding-left: 20px;
  color: var(--ink-faint);
  font-size: 14px;
}

#licenseForm {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--line-soft);
}

#workspace > aside .plan-note {
  cursor: pointer;
}

#workspace > aside .plan-note:hover {
  filter: brightness(.97);
}

/* ── 휴대폰: 한 줄로 두면 오른쪽으로 넘치는 줄들을 폭에 맞춰 쌓습니다 ───── */
/* 넓은 화면에서는 위의 규칙대로 한 줄을 지키고, 본문 폭이 휴대폰만큼 좁을 때만
   제목 옆 단추, 보기 탭, 확대·축소 막대를 여러 줄로 내려 화면 안에 둡니다. */
@container content (max-width: 640px) {
  .page-title {
    flex-wrap: wrap;
    gap: 12px;
  }

  .page-title h1 {
    font-size: 22px;
    white-space: normal;
  }

  .page-actions {
    flex-wrap: wrap;
    width: 100%;
  }

  .view-bar {
    flex-wrap: wrap;
  }

  .view-bar nav {
    display: flex;
    flex: 1 1 100%;
  }

  .view-bar nav button {
    flex: 1;
  }

  .view-tools {
    flex: 1 1 100%;
    order: 3;
  }

  /* 검색 칸은 한 줄을 다 쓰고, 등록·이미지 단추는 그 아래에 나란히 둡니다. */
  .toolbar {
    flex-wrap: wrap;
    gap: 10px;
  }

  .toolbar label {
    flex: 1 1 100%;
  }

  .toolbar button {
    flex: 1 1 0;
    padding: 10px 12px;
  }
}

/* 보기 막대 안: 확대·축소 단추는 폭에 맞춰 줄을 바꾸고, 손가락으로 쓰는 화면이라
   "끌어서 이동 · Ctrl+휠" 안내는 뺍니다. */
@container (max-width: 640px) {
  .view-tools .zoom-bar {
    flex-wrap: wrap;
    width: 100%;
    border-radius: 14px;
  }

  .view-tools .zoom-bar small {
    display: none;
  }
}

/* ── 어느 폭에서든 넘치지 않게 ─────────────────────────────── */
/* 보기 막대는 넓은 화면에서 한 줄을 지키되, 확대·축소 막대가 들어갈 자리
   (440px)가 모자라면 그 막대가 다음 줄로 내려갑니다. 막대 안의 단추도 자리가
   모자라면 줄을 바꿉니다. 정해 둔 폭이 아니라 남은 자리로 정하므로 휴대폰,
   펼친 접는 폰, 태블릿, 좁힌 PC 창 어디서나 오른쪽으로 삐져나가지 않습니다. */
.view-bar {
  flex-wrap: wrap;
}

.view-tools {
  min-width: min(100%, 440px);
}

.view-tools .zoom-bar {
  min-width: 0;
  flex-wrap: wrap;
}
