@font-face {
  font-family: "GuideFont";
  src: url("/fonts/nanumgothic.ttf") format("truetype");
}

@font-face {
  font-family: "GuideFontBold";
  src: url("/fonts/nanumgothic-bold.ttf") format("truetype");
  font-weight: bold;
}

/* 밝은 테마(기본값)와 어두운 테마 - html[data-theme]로 전환한다(app.js, localStorage에 저장).
   상단 내비게이션 바는 두 테마 모두에서 짙은 남색/검정 계열을 유지해서 브랜드 바 느낌을 준다. */
:root {
  --ink: #23262b;
  --ink-soft: #767c8a;
  --rule: #e3e6ec;
  --accent: #dd5049;
  --accent-light: #f0a29b;
  --cream: #f2f4f7;
  --card: #ffffff;
  --badge-red: #e0524a;
  --badge-green: #22b573;
  --navbar-bg: #2b2c30;
  --navbar-ink: #ffffff;
  --navbar-ink-soft: #aab2c8;
  --shadow-color: rgba(23, 32, 56, 0.1);
  --accent-tint: #fbebea;
  --tile-bg: #ffffff;
  --role-cho: #3f6fd1;
  --role-jung: #c9820f;
  --role-jong: #8452c9;
}

html[data-theme="dark"] {
  --ink: #e8e7e9;
  --ink-soft: #99969f;
  --rule: #3a3a40;
  --accent: #d9615c;
  --accent-light: #e69490;
  --cream: #1b1b1e;
  --card: #262629;
  --badge-red: #ff6b5b;
  --badge-green: #4cbf82;
  --navbar-bg: #1c1c1e;
  --navbar-ink: #ffffff;
  --navbar-ink-soft: #8f8f9a;
  --shadow-color: rgba(0, 0, 0, 0.4);
  --accent-tint: #3a2624;
  --tile-bg: #313136;
  --role-cho: #7ea3f0;
  --role-jung: #e3ab52;
  --role-jong: #b498ea;
}

* { box-sizing: border-box; }

input[type="range"] { accent-color: var(--accent); }

html {
  height: 100%;
  background: var(--cream);
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  font-family: "GuideFont", "Segoe UI", -apple-system, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  background: var(--cream);
  color: var(--ink);
  margin: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  transition: background-color 0.15s ease, color 0.15s ease;
}

/* ---------- 프로젝트 이름 입력 (첫 화면) ---------- */

#projectGate {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--cream);
  z-index: 1000;
  padding: 20px;
}

#projectGateCard {
  width: min(440px, 100%);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 16px;
  box-shadow: 0 8px 30px rgba(180, 68, 66, 0.12);
  overflow: hidden;
}

#gateSteps {
  display: flex;
  width: 200%;
  transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 유형 선택(step1) -> 이름 입력(step2) 2단계 슬라이드 */
#gateSteps.step2 { transform: translateX(-50%); }
#gateSteps.step3 { transform: translateX(-50%); }

.gate-step {
  flex: 0 0 50%;
  width: 50%;
  padding: 32px 28px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
}

#projectGateCard h1 {
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: "GuideFontBold", sans-serif;
  font-size: 22px;
  color: var(--accent);
}

#projectGateCard h1 .mascot-icon { width: 34px; height: 34px; }

#projectGateCard p {
  margin: 0 0 6px;
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.5;
}

#projectNameInput {
  padding: 10px 16px;
  border: 1.4px solid var(--rule);
  border-radius: 999px;
  font-size: 14px;
  color: var(--ink);
  text-align: center;
}

#projectNameInput:focus { border-color: var(--accent); outline: none; }

#charsetSizeChoice {
  display: flex;
  gap: 10px;
  margin-top: 6px;
}

/* 유형(오리지널/베이직/플러스) 선택 - 설명이 있어 세로로 쌓아 보여준다. */
#projectTypeChoice {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 6px;
}
#projectTypeChoice .charset-choice-btn {
  padding: 18px 20px;
  gap: 6px;
}
#projectTypeChoice .charset-choice-btn .hint {
  line-height: 1.5;
}
#projectTypeChoice .charset-choice-btn .plan-price {
  margin-top: 2px;
  font-family: "GuideFontBold", sans-serif;
  font-size: 17px;
  color: var(--ink);
}

.charset-choice-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 36px 16px;
  border: 2px solid var(--rule);
  border-radius: 18px;
  background: var(--cream);
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}

.charset-choice-btn:hover {
  border-color: var(--accent);
  background: var(--card);
  transform: translateY(-1px);
}

.charset-choice-btn .charset-num {
  font-family: "GuideFontBold", sans-serif;
  font-size: 24px;
  color: var(--accent);
}

.charset-choice-btn .hint {
  color: var(--ink-soft);
  font-size: 13px;
}

#gateBackBtn {
  align-self: flex-start;
  background: none;
  border: none;
  padding: 0;
  margin-bottom: -6px;
  color: var(--ink-soft);
  font-size: 12px;
  cursor: pointer;
}

#gateBackBtn:hover { color: var(--accent); }

#gateSelectedCharset {
  align-self: center;
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--cream);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 4px 12px;
}

#projectGateStatus {
  color: var(--badge-red);
  font-size: 12px;
  min-height: 14px;
}

#projectStartBtn {
  padding: 12px 20px;
  border: none;
  background: var(--accent);
  color: white;
  border-radius: 999px;
  cursor: pointer;
  font-size: 15px;
  font-family: "GuideFontBold", sans-serif;
  transition: background 0.15s, transform 0.1s;
}

#projectStartBtn:hover { background: #c0433f; transform: translateY(-1px); }
#projectStartBtn:disabled { opacity: 0.5; cursor: default; transform: none; }

/* ---------- 상단 내비게이션 바 ---------- */

#mainApp {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

#topNavbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 24px;
  background: var(--navbar-bg);
  flex-shrink: 0;
  gap: 16px;
  flex-wrap: wrap;
}

#navbarLeft {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.mascot-icon {
  width: 28px;
  height: 28px;
  object-fit: contain;
  flex-shrink: 0;
  vertical-align: middle;
}

#navbarLeft .mascot-icon { width: 30px; height: 30px; }

#navBrand {
  font-family: "GuideFontBold", sans-serif;
  font-size: 16px;
  color: var(--navbar-ink);
  letter-spacing: 0.2px;
}

#navProjectName {
  font-family: "GuideFontBold", sans-serif;
  font-size: 15px;
  color: var(--navbar-ink);
  padding-left: 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.22);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
  cursor: pointer;
  border-radius: 6px;
  padding-right: 6px;
  transition: background 0.15s;
}

#navProjectName:hover {
  background: rgba(255, 255, 255, 0.12);
}

#navProjectNameInput {
  font-family: "GuideFontBold", sans-serif;
  font-size: 15px;
  color: var(--navbar-ink);
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 6px;
  margin-left: 12px;
  padding: 2px 8px;
  width: 160px;
  outline: none;
}

#navProjectNameInput[hidden] {
  display: none;
}

#navCharsetBadge {
  font-size: 11px;
  color: var(--navbar-ink-soft);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}

#navSaveStatus {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--badge-green);
  white-space: nowrap;
  opacity: 0.9;
  transition: opacity 0.2s, transform 0.2s;
}

#navSaveStatus svg { width: 13px; height: 13px; }
#navSaveStatus.saving { opacity: 0.4; }
#navSaveStatus.flash { animation: save-flash 0.6s ease; }

@keyframes save-flash {
  0% { transform: scale(1); }
  35% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

#navbarRight {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

.nav-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: var(--navbar-ink-soft);
  border-radius: 999px;
  padding: 6px 11px;
  font-size: 12px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s, color 0.15s;
}

.nav-btn svg { width: 15px; height: 15px; flex-shrink: 0; }
.nav-btn:hover { background: rgba(255, 255, 255, 0.12); color: var(--navbar-ink); }
#themeToggleBtn, #profileBtn, .nav-icon-only { padding: 7px; }
/* 아이콘 전용 버튼은 텍스트 여백(gap)이 필요 없다. */
.nav-icon-only { gap: 0; }
#profileBtn svg { width: 17px; height: 17px; }

#navUserName {
  font-size: 13px;
  color: var(--navbar-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

#buildBtn {
  padding: 10px 20px;
  border: none;
  background: var(--accent);
  color: white;
  border-radius: 14px;
  cursor: pointer;
  font-size: 14px;
  font-family: "GuideFontBold", sans-serif;
  transition: background 0.15s, transform 0.1s;
  white-space: nowrap;
}

#buildBtn:hover { background: #c0433f; transform: translateY(-1px); }
#buildBtn:disabled { opacity: 0.5; cursor: default; transform: none; }

/* ---------- 퀘스트 진행률 헤더 ---------- */

#questHeader {
  background: var(--card);
  border-bottom: 1px solid var(--rule);
  padding-bottom: 10px;
  flex-shrink: 0;
}

.gauge.overall {
  position: relative;
  height: 4px;
  width: 100%;
  background: var(--rule);
  overflow: hidden;
}

.gauge.overall .gauge-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent-light), var(--accent));
  transition: width 0.3s ease;
}

.gauge.overall.complete .gauge-fill {
  background: linear-gradient(90deg, #6fd19b, var(--badge-green));
}

#questHeaderRow {
  max-width: 1400px;
  width: 100%;
  margin: 0 auto;
  padding: 10px 24px 0;
  display: grid;
  grid-template-columns: minmax(140px, auto) 1fr minmax(140px, auto);
  align-items: center;
  gap: 24px;
}

#questHeaderLeft { min-width: 140px; grid-column: 1; }

#milestoneRow { grid-column: 2; justify-content: center; }

#questHeaderSpacer {
  grid-column: 3;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
}

#previewJumpBtn, #viewAllHangulBtn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 20px;
  border: 1.4px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-family: "GuideFontBold", sans-serif;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s, background 0.15s;
}

#previewJumpBtn svg, #viewAllHangulBtn svg { width: 16px; height: 16px; flex-shrink: 0; }
#previewJumpBtn:hover, #viewAllHangulBtn:hover { border-color: var(--accent); }

#previewSection.jump-highlight {
  animation: preview-jump-flash 1s ease;
}

@keyframes preview-jump-flash {
  0%, 100% { box-shadow: none; }
  30% { box-shadow: 0 0 0 3px var(--accent-light); }
}

#questLabel {
  font-size: 15px;
  color: var(--ink-soft);
  font-family: "GuideFontBold", sans-serif;
  letter-spacing: 0.3px;
}

#questStatsRow {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

#overallGaugeText {
  font-size: 26px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  line-height: 1.3;
}

#questCountText {
  font-size: 15px;
  color: var(--ink-soft);
}

#questCountText::before {
  content: "· ";
  color: var(--ink-soft);
}

/* 태블릿(가로)처럼 화면이 좁아지면 5개 그룹(한글/자모/영문/숫자/특수문자)이
   한 줄에 안 들어가고 둘째 줄로 넘어가던 문제 - 간격/폭을 고정값 대신
   clamp()로 화면 폭에 비례하게 줄여서 항상 한 줄을 유지한다(넓은 PC
   화면에서는 clamp()가 최대값에 걸려 기존과 동일하게 보인다). 연결선
   위치/길이 계산도 같은 변수를 참조해서 같이 줄어들게 한다. */
#milestoneRow {
  --milestone-gap: clamp(16px, 3vw, 40px);
  --milestone-width: clamp(44px, 6vw, 52px);
  display: flex;
  align-items: flex-start;
  gap: var(--milestone-gap);
  flex-wrap: nowrap;
}

.milestone {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  width: var(--milestone-width);
}

/* 원형 버튼 사이를 선으로 이어서 하나로 쭉 이어지는 느낌만 준다 - 그룹 완료
   여부는 원 색과 아래 게이지바로 이미 보여주므로, 이 연결선 자체는 완료해도
   항상 회색으로 유지한다. 기본값(간격 40px, 폭 52px)일 때 left:-63px;
   width:86px가 나오도록 역산한 식이라, 위 변수가 줄어들면 이 값도 같이
   줄어든다. */
.milestone:not(:first-child)::before {
  content: "";
  position: absolute;
  top: 14.5px;
  left: calc(-1 * (var(--milestone-gap) + var(--milestone-width)) + 29px);
  width: calc(var(--milestone-gap) + var(--milestone-width) - 6px);
  height: 3px;
  background: var(--rule);
  z-index: 0;
}

.milestone-circle {
  position: relative;
  z-index: 1;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--cream);
  border: 2px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: "GuideFontBold", sans-serif;
  font-size: 13px;
  color: var(--ink-soft);
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.milestone-num {
  position: absolute;
  top: -2px;
  right: -2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--ink-soft);
  color: white;
  font-size: 8px;
  font-family: "GuideFont", sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
}

.milestone.active .milestone-circle {
  border-color: var(--accent);
  background: var(--card);
  color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-light);
}

.milestone.active .milestone-num { background: var(--accent); }

.milestone.complete .milestone-circle {
  border-color: var(--badge-green);
  background: var(--badge-green);
  color: white;
}

.milestone.complete .milestone-num {
  background: var(--card);
  color: var(--badge-green);
  box-shadow: 0 0 0 1.5px var(--badge-green);
}

.milestone-label {
  font-size: 11px;
  color: var(--ink);
  font-family: "GuideFontBold", sans-serif;
}

.milestone-frac {
  font-size: 10px;
  color: var(--ink-soft);
}

/* 마일스톤 사이 연결선과는 별개로, 각 그룹 자체의 완료율을 바로 확인할 수 있는
   작은 게이지바 - 원형 버튼 아래 글자 수 표시 밑에 놓는다. */
.milestone-gauge {
  width: 100%;
  height: 4px;
  border-radius: 999px;
  background: var(--rule);
  overflow: hidden;
}

.milestone-gauge-fill {
  height: 100%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 0.3s ease;
}

.milestone.complete .milestone-gauge-fill { background: var(--badge-green); }

/* ---------- 전체 레이아웃 (좌: 목록/검색, 중앙: 캔버스/도구, 우: 빌드/미리보기) ---------- */

#appBody {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 270px minmax(0, 1fr) 320px;
  gap: 16px;
  max-width: 1400px;
  width: 100%;
  margin: 0 auto;
  padding: 14px 24px;
  overflow: auto;
  align-items: stretch;
}

.side-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 14px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.side-card h2 {
  margin: 0;
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--ink-soft);
  letter-spacing: 0.3px;
}

#sidebarLeft, #sidebarRight {
  display: flex;
  flex-direction: column;
  gap: 18px;
  position: sticky;
  top: 0;
  min-height: 0;
}

/* appBody의 align-items:stretch로 사이드바 높이가 가운데 캔버스 카드와 맞춰지면,
   오른쪽 속성 패널 카드도 그 높이만큼 배경이 꽉 차게 늘어나야 아래쪽에 빈 여백이
   생기지 않는다 - 왼쪽은 #charGridCard가 이미 flex:1을 갖고 있다. */
/* 오른쪽 속성 패널도 왼쪽 글자 목록(#charGrid)과 같은 이유로 내용이 늘어나면
   페이지 전체를 밀어내지 않고 카드 안에서만 스크롤되게 한다. */
#sidebarRight > .side-card {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
}

/* ---------- 글자 목록 (세로 리스트) ---------- */

#tabs {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.tab {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  cursor: pointer;
  padding: 8px 10px;
  border-radius: 10px;
  border: 1.4px solid transparent;
  transition: background 0.15s, border-color 0.15s;
}

.tab:hover { background: var(--cream); }

.tab.active {
  border-color: var(--accent);
  background: var(--cream);
}

.tab-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.tab-pill {
  font-family: "GuideFontBold", sans-serif;
  font-size: 14px;
  color: var(--ink);
}

.tab.active .tab-pill { color: var(--accent); }

.tab-badge {
  font-size: 11px;
  color: var(--ink-soft);
  white-space: nowrap;
}

.tab.complete .tab-badge {
  color: var(--badge-green);
  font-weight: bold;
}

.tab-mini-gauge {
  width: 100%;
  height: 5px;
  border-radius: 999px;
  background: var(--rule);
  overflow: hidden;
}

.tab-mini-gauge .gauge-fill {
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent-light), var(--accent));
  transition: width 0.3s ease;
}

.tab.complete .tab-mini-gauge .gauge-fill {
  background: linear-gradient(90deg, #6fd19b, var(--badge-green));
  box-shadow: 0 0 6px rgba(63, 166, 107, 0.6);
}

.level-up {
  font-size: 11px;
  white-space: nowrap;
}

/* ---------- 글자 검색 ---------- */

#searchBox {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
}

#searchInputWrap {
  position: relative;
  display: flex;
  align-items: center;
}

#searchIcon {
  position: absolute;
  left: 12px;
  width: 15px;
  height: 15px;
  color: var(--ink-soft);
  pointer-events: none;
}

#searchInput {
  width: 100%;
  padding: 8px 14px 8px 34px;
  border: 1.4px solid var(--rule);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink);
  text-align: left;
}

#searchInput:focus { border-color: var(--accent); outline: none; }

#searchStatus {
  color: var(--ink-soft);
  font-size: 12px;
  text-align: center;
  min-height: 14px;
}

/* ---------- 전체/미완성/완료 필터 ---------- */

#charFilterGroup {
  display: flex;
  gap: 6px;
}

.char-filter-btn, .prop-tab-btn {
  flex: 1;
  padding: 7px 0;
  border: 1.4px solid var(--rule);
  border-radius: 8px;
  background: var(--card);
  color: var(--ink-soft);
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.char-filter-btn:hover, .prop-tab-btn:hover { border-color: var(--accent); color: var(--ink); }

.char-filter-btn.active, .prop-tab-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* ---------- 목록 다중 선택 표시 ---------- */

#listSelectionInfo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--accent-soft, rgba(255, 90, 90, 0.12));
  color: var(--accent);
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
}

#listSelectionClearBtn {
  border: none;
  background: none;
  color: var(--accent);
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}

/* ---------- 왼쪽 하단: 현재 그룹 전체 글자 목록 ---------- */

#charGridCard { gap: 10px; flex: 1; min-height: 0; }

#charGridDivider {
  height: 1px;
  background: var(--rule);
  margin: -6px 0;
  flex-shrink: 0;
}

#charGridToggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  font-family: "GuideFontBold", sans-serif;
  font-size: 12px;
  color: var(--ink-soft);
  letter-spacing: 0.3px;
}

#charGridToggle .chevron-icon {
  width: 16px;
  height: 16px;
  transition: transform 0.15s;
}

#charGridCard.collapsed #charGridToggle .chevron-icon { transform: rotate(-90deg); }
#charGridCard.collapsed #charGrid { display: none; }

#charGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(34px, 1fr));
  align-content: start;
  gap: 6px;
  flex: 1;
  min-height: 0;
  /* 상한을 안 주면 2,780자 전체 타일의 실제 콘텐츠 높이가 그리드 행(auto) 크기
     계산에 그대로 들어가서 appBody 전체가 그 크기로 늘어나 버린다(align-items:stretch
     때문에 다른 칸까지 전부 영향받음) - 가운데 캔버스 카드보다는 낮은 상한을 줘서
     가운데 카드 높이가 기준이 되게 하고, 왼쪽 카드 전체(#charGridCard)는 flex:1로
     그 기준 높이까지 늘어난다. */
  max-height: 480px;
  overflow-y: auto;
  scrollbar-color: var(--ink-soft) transparent;
}

#charGrid::-webkit-scrollbar { width: 8px; }
#charGrid::-webkit-scrollbar-track { background: transparent; }
#charGrid::-webkit-scrollbar-thumb {
  background-color: var(--ink-soft);
  border-radius: 4px;
}

.char-tile {
  position: relative;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.4px solid var(--rule);
  border-radius: 8px;
  background: var(--tile-bg);
  color: var(--ink);
  font-size: 14px;
  cursor: pointer;
  padding: 0;
  transition: border-color 0.15s, background 0.15s;
}

.char-tile:hover { border-color: var(--accent); }

.char-tile-canvas {
  width: 78%;
  height: 78%;
  object-fit: contain;
}

/* 실제로 그린 글자는 목록에서도 진짜 손글씨(커스텀 폰트)로 보여준다 - 아직 안
   그린 글자는 기본 폰트(상속받은 GuideFont)로 그대로 둔다. MoglediPreview가
   아직 로드 전이거나 그 글자의 글리프가 아직 최신 빌드에 없으면 자동으로
   기본 폰트로 자연스럽게 대체된다. */
.char-tile.done {
  color: var(--badge-green);
  font-family: "MoglediPreview", "GuideFont", "Segoe UI", -apple-system, sans-serif;
}

.char-tile.current {
  border-color: var(--accent);
  border-width: 2px;
  color: var(--accent);
  background: var(--accent-tint);
}

.char-tile.current:not(.done) { font-family: "GuideFontBold", sans-serif; }

/* '기타' 탭의 원하는 문자 추가(+) 타일 - 회색 테두리 + 회색 + */
.char-tile-add {
  color: var(--ink-soft);
  border-color: var(--rule);
  font-size: 26px;
  font-weight: 300;
  line-height: 1;
}
.char-tile-add:hover { background: var(--cream); border-color: var(--ink-soft); }

/* '기타' 탭 커스텀 문자 입력 바(+ 클릭 시 아래에 표시) */
#customCharAddBar { display: flex; gap: 6px; margin-top: 8px; }
#customCharAddBar[hidden] { display: none; }
#customCharAddBar input {
  flex: 1; min-width: 0; padding: 7px 9px;
  border: 1.4px solid var(--rule); border-radius: 8px;
  background: var(--tile-bg); color: var(--ink); font-size: 14px;
}
#customCharAddBar button {
  padding: 7px 12px; border-radius: 8px; border: 1.4px solid var(--accent);
  background: var(--accent); color: #fff; font-weight: 700; cursor: pointer; font-size: 13px;
}

/* Shift+클릭으로 범위 선택한 글자 칸 - 지금 편집 중인 칸(.current, 빨간 테두리)과
   동시에 켜질 수 있어서 border 대신 겹쳐도 안 부딪히는 파란 안쪽 그림자로 표시한다. */
.char-tile.list-selected {
  background: rgba(66, 133, 244, 0.16);
  box-shadow: inset 0 0 0 2px rgba(66, 133, 244, 0.65);
}

/* 자모 조합형 전용 - 지금 이 칸이 초성/중성/종성 중 어디에 쓰이는지 좌상단 점
   색깔로 보여준다. .current(테두리)/.list-selected(안쪽 그림자)와 겹쳐도 서로
   다른 자리(점)라 부딪히지 않는다. */
.char-tile.role-cho::before,
.char-tile.role-jung::before,
.char-tile.role-jong::before {
  content: "";
  position: absolute;
  top: 4px;
  left: 4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
}
.char-tile.role-cho::before { background: var(--role-cho); }
.char-tile.role-jung::before { background: var(--role-jung); }
.char-tile.role-jong::before { background: var(--role-jong); }

/* ---------- 맨 아래: 오늘 완성한 글자 수 ---------- */

/* fixed 대신 sticky를 쓴다 - fixed는 body 문서 흐름에서 완전히 빠져버려서, body의
   padding-bottom을 이 바 높이만큼 수동으로 맞춰줘야 했다(그 값이 실제 높이와
   어긋나면 여백이 벌어지거나 좁아지는 문제가 계속 생겼다). sticky는 원래 자리(문서
   맨 끝)에 실제 공간을 차지한 채로 있다가 화면 하단에 닿으면 붙어서, 여백 계산이
   항상 저절로 맞다 - 별도로 맞춰줄 값 자체가 없다. */
#dailyProgressBar {
  position: sticky;
  bottom: 0;
  z-index: 60;
  flex-shrink: 0;
  min-height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 6px 24px;
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--card);
  border-top: 1px solid var(--rule);
  box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.06);
}

#dailyProgressNote {
  text-align: left;
}

#dailyProgressCountRow {
  font-size: 13px;
  white-space: nowrap;
}

#dailyProgressCount {
  color: var(--accent);
  font-family: "GuideFontBold", sans-serif;
}

/* ---------- 중앙: 이동 / 캔버스 / 도구 ---------- */

#workArea {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  min-width: 0;
  min-height: 0;
  width: 100%;
}

#workCard {
  width: 100%;
  max-width: 760px;
  align-items: center;
  gap: 12px;
  min-height: 0;
  /* 왼쪽/오른쪽 카드가 이미 flex:1로 행 높이만큼 늘어나 있으므로, 가운데 카드도
     같이 늘어나야 셋의 아래쪽 테두리가 맞는다(늘어난 만큼 남는 공간은 카드 맨
     아래에 여백으로 남는다). */
  flex: 1;
}

#canvasTopBar {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
}

/* 현재글자/다음글자가 #canvasCenterRow(캔버스 옆)로 옮겨가면서 canvasTopBar에는
   이제 이 가운데 그룹 하나만 남는다 - grid-column을 명시하지 않으면
   auto-placement가 1번 칸(맨 왼쪽)으로 당겨버려 가운데 정렬이 깨지므로
   2번 칸에 명시적으로 고정한다(양옆 1fr 칸은 비워둔 채로 폭만 차지해서
   가운데 정렬 균형을 잡아준다). */
#canvasTopBarCenter { justify-self: center; grid-column: 2; }

.canvasTopBarGroup {
  display: flex;
  align-items: center;
  gap: 10px;
}

.pill-nav-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  font-family: "GuideFont", sans-serif;
  cursor: pointer;
  box-shadow: 0 1px 2px var(--shadow-color);
  transition: border-color 0.15s, color 0.15s;
}

.pill-nav-btn svg { width: 15px; height: 15px; }
.pill-nav-btn:hover { border-color: var(--accent); color: var(--accent); }

#posInfo { display: flex; align-items: center; gap: 7px; }
#jumpInputWrap {
  position: relative;
  display: inline-flex;
  align-items: stretch;
}

#jumpInput {
  width: 62px;
  text-align: right;
  padding: 3px 18px 3px 6px;
  border: none;
  border-radius: 7px;
  background: var(--cream);
  color: var(--ink);
  font-size: 16px;
  font-family: "GuideFontBold", sans-serif;
  transition: background 0.15s;
  -moz-appearance: textfield;
}
/* 자체 위아래 버튼을 두므로 브라우저 기본 스피너는 감춘다(마우스를 올려야만 보이는
   것과 달리, 우리가 만든 버튼은 항상 보인다). */
#jumpInput::-webkit-inner-spin-button, #jumpInput::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
#jumpInput:hover, #jumpInputWrap:hover #jumpInput { background: var(--rule); }
#jumpInput:focus { outline: 1.5px solid var(--accent); background: var(--card); }

#jumpInputSteppers {
  position: absolute;
  right: 2px;
  top: 2px;
  bottom: 2px;
  display: flex;
  flex-direction: column;
  width: 14px;
}

#jumpInputSteppers button {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 0;
}

#jumpInputSteppers button svg { width: 10px; height: 10px; }
#jumpInputSteppers button:hover { color: var(--accent); }
#totalLabel { font-size: 16px; font-family: "GuideFontBold", sans-serif; color: var(--ink); }
#totalLabel { font-size: 16px; font-family: "GuideFontBold", sans-serif; color: var(--ink); }

#workCardDivider {
  width: 100%;
  height: 1px;
  background: var(--rule);
  margin: 4px 0;
}

#canvasArea {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  justify-content: center;
}

/* #canvasToolRow는 모바일에서만 의미 있는 래퍼(글자목록/속성 서랍 버튼이
   drawToolDock 좌우에 오도록) - PC/태블릿에서는 display:contents로 투명하게
   만들어서 canvasArea의 flex row에 drawToolDock가 예전처럼 직접 참여한다
   (글자목록/속성 버튼은 .drawer-trigger-btn 기본값이 display:none이라 어차피
   안 보인다). */
#canvasToolRow { display: contents; }

/* #canvasCenterRow도 같은 방식의 투명 래퍼 - PC는 현재글자/다음글자가
   position:absolute라 실제 자리를 차지하지 않으므로 이 래퍼가 투명해도
   canvasArea의 flex row(도구독|캔버스|그리드독)는 그대로 유지된다. 태블릿
   가로 전용 블록에서만 진짜 가로줄로 바꿔서 캔버스 양옆에 현재글자/다음글자를
   나란히 둔다. */
#canvasCenterRow { display: contents; }

#drawToolDock {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
  padding: 6px;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
}

/* PC/태블릿: 10개 도구를 세로 한 줄로 쌓으면 캔버스보다 훨씬 길어져서 캔버스
   카드 전체 높이를 그만큼 밀어 올린다 - 2열로 접어서 실제로 필요한 높이를
   거의 절반으로 줄인다(아이콘 크기는 그대로 유지해 가독성은 그대로 둔다). */
#drawToolDockTools {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 4px;
}

.dock-tool-btn {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.dock-tool-btn svg { width: 17px; height: 17px; }

.dock-tool-btn:hover { background: var(--cream); color: var(--ink); }

.dock-tool-btn.active {
  background: var(--accent);
  color: #fff;
}

#canvasWrap {
  position: relative;
  width: min(420px, 31vh, 100%);
  height: min(420px, 31vh, 100%);
  aspect-ratio: 1 / 1;
}

/* 매끄럽게 도구 강도 - 도구 선택 시 캔버스 안쪽 아래에 알약 모양으로 떠오른다. */
#smoothStrengthFloat {
  position: absolute;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100% - 24px);
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--card);
  border: 1px solid var(--rule);
  box-shadow: 0 3px 12px var(--shadow-color);
  font-size: 12px;
  color: var(--ink-soft);
  z-index: 6;
}
#smoothStrengthFloat[hidden] { display: none; }
#smoothStrengthFloat .smooth-float-label { flex-shrink: 0; white-space: nowrap; }
#smoothStrengthFloat input[type="range"] { flex: 1; min-width: 120px; }
#smoothApplyBtn {
  flex-shrink: 0;
  border: none;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  padding: 5px 13px;
  cursor: pointer;
}
#smoothApplyBtn[hidden] { display: none; }

#canvas {
  width: 100%;
  height: 100%;
  display: block;
  border: 2px solid var(--accent-light);
  border-radius: 20px;
  background: white;
  box-shadow: 0 4px 16px rgba(180, 68, 66, 0.1);
  touch-action: none;
  cursor: crosshair;
}

#currentCharGroup, #nextCharGroup {
  padding: 4px 14px;
  border: 1.4px solid var(--rule);
  border-radius: 999px;
  background: var(--cream);
}

#currentCharLabel, #nextCharLabel {
  font-family: "GuideFontBold", sans-serif;
  font-size: 20px;
  color: var(--ink);
}

/* 모바일 현재글자/다음글자 박스와 동일하게 완료/미완성 대신 고정 캡션을 쓴다 */
.pc-char-caption {
  font-size: 11px;
  color: var(--ink-soft);
  margin-left: 8px;
}

/* 자모 조합형 전용 - 지금 그리는 자모가 실제로 어떤 한글에서 어떤 역할(초성/중성/
   종성)로 쓰이는지 색상으로 보여준다. 캔버스(<canvas>)는 DOM이 아니라 안에 못
   넣으므로 canvasArea 바로 아래 독립된 일반 흐름 블록으로 둔다. */
#composeHintRow {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  width: 100%;
  padding: 8px 16px 0;
  margin: 0 auto;
  max-width: 480px;
}
#composeHintRow[hidden] { display: none; }

.compose-hint-jamo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 34px;
  padding: 0 8px;
  border-radius: 8px;
  font-family: "GuideFontBold", sans-serif;
  font-size: 18px;
  color: var(--ink);
  background: var(--cream);
  border: 1.4px dashed var(--rule);
  transition: opacity 0.15s, border-color 0.15s, color 0.15s;
}
.compose-hint-jamo.role-cho { color: var(--role-cho); border-color: var(--role-cho); }
.compose-hint-jamo.role-jung { color: var(--role-jung); border-color: var(--role-jung); }
.compose-hint-jamo.role-jong { color: var(--role-jong); border-color: var(--role-jong); }
.compose-hint-jamo.current { border-style: solid; box-shadow: 0 1px 4px var(--shadow-color); }
.compose-hint-jamo:not(.current) { opacity: 0.7; }

.compose-hint-plus, .compose-hint-arrow {
  font-size: 15px;
  color: var(--ink-soft);
}
.compose-hint-result {
  font-family: "GuideFontBold", sans-serif;
  font-size: 22px;
  min-width: 34px;
  text-align: center;
  color: var(--ink);
}

/* 왼쪽 글자 목록 카드 맨 아래에 고정되는 안내 섹션 - #charGrid 다음 형제로 둬서
   (flex-direction:column인 #charGridCard 안) 목록 스크롤과 무관하게 항상 카드
   하단에 붙어있고, 캔버스 쪽 레이아웃에는 전혀 영향을 주지 않는다. */
#mixedGroupNotice, #otherGroupNotice {
  flex-shrink: 0;
  text-align: center;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ink-soft);
  background: var(--cream);
  border: 1px dashed var(--rule);
  border-radius: 8px;
  padding: 8px 10px;
}
#mixedGroupNotice[hidden], #otherGroupNotice[hidden] { display: none; }

.canvas-toggle-btn {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1.4px solid var(--rule);
  border-radius: 50%;
  background: var(--card);
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.canvas-toggle-btn svg {
  width: 15px;
  height: 15px;
}

.canvas-toggle-btn:hover {
  background: var(--cream);
  color: var(--ink);
}

.canvas-toggle-btn.active {
  background: var(--accent-tint);
  border-color: var(--accent-light);
  color: var(--accent);
}

#canvasRightDock {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 8px;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
}

#canvasRightDockDivider {
  width: 24px;
  height: 1px;
  background: var(--rule);
  margin: 2px 0;
}

#zoomControls {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

#zoomControls .icon-btn .circle {
  width: 26px;
  height: 26px;
  background: var(--card);
  border: 1.4px solid var(--rule);
}

#zoomControls .icon-btn .circle .icon {
  width: 13px;
  height: 13px;
}

#zoomControls .icon-btn:hover .circle { transform: none; border-color: var(--accent); }

#zoomLevel {
  font-size: 10px;
  color: var(--ink-soft);
  text-align: center;
  cursor: pointer;
  white-space: nowrap;
}

#toolCard {
  width: 100%;
  align-items: center;
}

/* #toolCard의 align-items:center가 h2도 블록째로 가운데 정렬시켜서 글자가
   가운데로 보였다 - 제목만 왼쪽으로 고정한다. */
#toolCard h2 { align-self: flex-start; }

.context-menu {
  position: fixed;
  display: none;
  flex-direction: column;
  min-width: 190px;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 12px;
  box-shadow: 0 8px 24px var(--shadow-color);
  padding: 6px;
  z-index: 1000;
}

.context-menu.open {
  display: flex;
}

.context-menu-label {
  font-size: 11px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--ink-soft);
  padding: 6px 10px 4px;
}

.context-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  background: none;
  color: var(--ink);
  font-size: 13px;
  padding: 7px 10px;
  border-radius: 7px;
  cursor: pointer;
}

.context-menu-item:hover {
  background: var(--cream);
  color: var(--accent);
}

.context-menu-divider {
  height: 1px;
  background: var(--rule);
  margin: 5px 4px;
}

#toolSelectGroup {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  justify-items: center;
  gap: 12px 6px;
  font-size: 11px;
  color: var(--ink-soft);
}

#tools, #tools2, #quickToolsGrid, .align-grid {
  display: grid;
  justify-items: center;
  gap: 12px 6px;
  font-size: 11px;
  color: var(--ink-soft);
}

#quickToolsGrid { grid-template-columns: repeat(4, 1fr); }
.align-grid { grid-template-columns: repeat(3, 1fr); }

/* ---------- 속성 패널: 도구/정렬/변형 탭 ---------- */

#propTabs {
  width: 100%;
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}

.prop-panel {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.prop-panel[hidden] { display: none; }

/* ---------- 필압 감지 토글 ---------- */

#pressureToggleRow {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--ink-soft);
  margin-top: 4px;
}

#pressureToggleRow span:first-child { flex-shrink: 0; }

#pressureToggleBtn {
  position: relative;
  width: 34px;
  height: 19px;
  border: none;
  border-radius: 999px;
  background: var(--rule);
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: background 0.15s;
}

#pressureToggleBtn .switch-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 2px var(--shadow-color);
  transition: transform 0.15s;
}

#pressureToggleBtn.on { background: var(--accent); }
#pressureToggleBtn.on .switch-knob { transform: translateX(15px); }

#pressureToggleLabel {
  flex: 1;
  text-align: right;
  white-space: nowrap;
}

/* ---------- 정렬 탭 ---------- */

/* "선택 도구로 획을 2개 이상 고르면 정렬할 수 있습니다" 안내창을 화면에서 뺀다 -
   DOM/JS(app.js의 alignStatusEl.innerHTML 갱신)는 그대로 둬서 다른 로직이
   깨지지 않게 하고, 시각적으로만 숨긴다. */
#alignStatus {
  display: none;
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink-soft);
  text-align: center;
  padding: 10px 8px;
  background: var(--cream);
  border-radius: 10px;
}

.align-btn:disabled { opacity: 0.4; cursor: default; }
.align-btn:disabled:hover .circle { border-color: var(--rule); transform: none; }
.align-btn:disabled:hover .circle .icon { color: var(--ink-soft); }

.tool-group {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
}

.tool-divider {
  width: 100%;
  height: 1px;
  margin: 6px 0;
  background: var(--rule);
}

.tool-box {
  width: 100%;
  border-radius: 14px;
  padding: 10px 10px 10px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 7px;
}

.tool-box-pink, .tool-box-gray { background: var(--cream); }

.tool-group-label {
  font-size: 11px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--ink-soft);
  letter-spacing: 0.3px;
}

/* ---------- 선택한 글자 크기조정 ---------- */
/* 버튼을 그냥 왼쪽 정렬(align-self:flex-start)만 하면, 버튼 자기 폭이 라벨
   글자 폭("크기조정")에 맞춰지고 그 안에서 원이 다시 가운데 정렬돼 위 "도구
   목록" 그리드의 첫 칸 원(실행취소)과 몇 픽셀 어긋난다 - 그리드 첫 칸의 폭은
   버튼 폭이 아니라 그리드 전체를 4등분한 값이기 때문. #quickToolsGrid와
   똑같은 4열 그리드(같은 gap)를 여기도 써서, 두 원이 "같은 폭의 첫 칸 안에서
   가운데 정렬"이라는 같은 계산을 거치게 만들어 픽셀 단위로 맞춘다.
   실제로 4칸을 다 채우진 않고 버튼 하나만 첫 칸에 들어간다. */
#bulkScaleBtnGrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px 6px;
  justify-items: center;
}

dialog#bulkScaleModal {
  border: none;
  border-radius: 20px;
  padding: 32px 34px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(360px, 90vw);
  background: var(--card);
  color: var(--ink);
}

dialog#bulkScaleModal::backdrop { background: rgba(0, 0, 0, 0.55); }

dialog#bulkScaleModal h3 {
  margin: 0 0 14px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}

#bulkScaleModalHint {
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 16px;
}

dialog#bulkScaleModal label {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 13px;
  color: var(--ink-soft);
}

#bulkScaleModalRow {
  display: flex;
  align-items: center;
  gap: 8px;
}

#bulkScaleInput {
  width: 100px;
  text-align: right;
  padding: 11px 14px;
  border: 1.4px solid var(--rule);
  border-radius: 10px;
  background: var(--cream);
  color: var(--ink);
  font-size: 15px;
  font-family: "GuideFontBold", sans-serif;
  -moz-appearance: textfield;
}
#bulkScaleInput::-webkit-inner-spin-button, #bulkScaleInput::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
#bulkScaleInput:focus { border-color: var(--accent); outline: none; }
#bulkScalePercentSign { font-size: 14px; color: var(--ink-soft); }

#bulkScaleModalActions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}
#bulkScaleModalActions button {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}
#bulkScaleApplyBtn { background: var(--accent); color: #fff; }
#bulkScaleApplyBtn:disabled { opacity: 0.5; cursor: default; }

/* ---------- 간격조정 모달(조합형) ---------- */
dialog#spacingModal {
  border: none;
  border-radius: 20px;
  padding: 26px 26px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(600px, 96vw);
  background: var(--card);
  color: var(--ink);
}
dialog#spacingModal::backdrop { background: rgba(0, 0, 0, 0.55); }
dialog#spacingModal h3 {
  margin: 0 0 12px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}
#spacingModalHint {
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 16px;
}
#spacingTable {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
#spacingTable th {
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 11px;
  text-align: center;
  padding: 3px 3px;
  line-height: 1.2;
  border-bottom: 1px solid var(--rule);
}
#spacingTable thead tr:first-child th { border-bottom: none; }
#spacingTable thead tr:first-child th[colspan] { border-left: 1px solid var(--rule); }
#spacingTable td {
  padding: 5px 3px;
  border-top: 1px solid var(--rule);
  text-align: center;
  vertical-align: middle;
}
#spacingTable td.spacing-label { text-align: left; color: var(--ink); white-space: nowrap; padding-right: 6px; }
#spacingRulesWrap { margin-top: 16px; }
/* 적용 중인 조정 - 펼침(details)으로 접었다 폈다. 기본은 접혀 있어 세로 스크롤바를 막는다. */
.spacing-rules-summary { cursor: pointer; font-size: 12.5px; font-weight: 700; color: var(--ink); list-style: none; padding: 4px 2px; user-select: none; }
.spacing-rules-summary::-webkit-details-marker { display: none; }
.spacing-rules-summary::before { content: "▸ "; color: var(--ink-soft); }
details[open] > .spacing-rules-summary::before { content: "▾ "; }
#spacingRulesList { display: flex; flex-direction: column; gap: 5px; max-height: 130px; overflow-y: auto; margin-top: 6px; }
.spacing-rules-empty { font-size: 12px; color: var(--ink-soft); padding: 4px 2px; }
.spacing-rule {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 12px;
  color: var(--ink);
  background: var(--cream);
  border-radius: 8px;
  padding: 6px 10px;
}
.spacing-rule button {
  border: none;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  flex-shrink: 0;
}
.spacing-rule button:hover { color: var(--badge-red, #e0524a); }
#spacingTable input[type="number"] {
  width: 46px;
  text-align: right;
  padding: 5px 5px;
  border: 1.4px solid var(--rule);
  border-radius: 7px;
  background: var(--cream);
  color: var(--ink);
  font-size: 12px;
}
/* 자모 그룹 경계(자음|모음|받침) 세로선 - 짝수번째 입력 셀 오른쪽 구분 */
#spacingTable td:nth-child(3), #spacingTable td:nth-child(5) { border-right: 1px solid var(--rule); }
#spacingTable input[type="number"]:focus { border-color: var(--accent); outline: none; }
#spacingTable .spacing-na { color: var(--ink-soft); }
#spacingFilter { margin-top: 16px; }
.spacing-filter-title { font-size: 12px; color: var(--ink-soft); margin-bottom: 8px; }
.spacing-filter-row { display: flex; gap: 10px; }
.spacing-filter-row label {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-soft);
  flex: 1;
}
.spacing-filter-row input {
  width: 100%;
  min-width: 0;
  padding: 7px 9px;
  border: 1.4px solid var(--rule);
  border-radius: 8px;
  background: var(--cream);
  color: var(--ink);
  font-size: 13px;
}
.spacing-filter-row input:focus { border-color: var(--accent); outline: none; }
#spacingModalActions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}
#spacingModalActions button {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}
#spacingResetBtn { border-color: var(--rule); color: var(--ink-soft); margin-right: auto; }
#spacingApplyBtn { background: var(--accent); color: #fff; }
#spacingApplyBtn:disabled { opacity: 0.5; cursor: default; }

/* ===== 균형조정 모달 - 위치/간격조정 모달과 같은 스타일 공유 ===== */
dialog#balanceModal {
  border: none; border-radius: 20px; padding: 26px 26px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(720px, 96vw); background: var(--card); color: var(--ink);
}
dialog#balanceModal::backdrop { background: rgba(0, 0, 0, 0.55); }
dialog#balanceModal h3 { margin: 0 0 12px; font-family: "GuideFontBold", sans-serif; color: var(--accent); font-size: 19px; }
.spacing-modal-hint { font-size: 12px; line-height: 1.5; color: var(--ink-soft); margin-bottom: 16px; }
#balanceControls { display: flex; flex-direction: column; gap: 6px; margin: 14px 0; }
#balanceControls .balance-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 10px; border: 1.2px solid var(--rule); border-radius: 10px; background: var(--cream); }
#balanceControls .balance-row-all { border-color: var(--accent); border-width: 1.6px; }
#balanceControls label { font-size: 14px; font-weight: 700; display: flex; flex-direction: column; gap: 1px; }
#balanceControls .balance-sub { font-size: 11px; font-weight: 400; color: var(--ink-soft); }
#balanceControls .balance-input-wrap { display: flex; align-items: center; gap: 5px; font-size: 14px; white-space: nowrap; }
#balanceControls .balance-cur { font-size: 11px; color: var(--accent); font-weight: 600; }
#balanceControls .balance-cur:empty { display: none; }
#balanceControls input { width: 60px; text-align: right; padding: 7px 9px; border: 1.4px solid var(--rule); border-radius: 9px; background: var(--card); color: var(--ink); font-size: 15px; }
#balanceControls input:focus { border-color: var(--accent); outline: none; }
/* 모음종류 한 줄: [세로/가로/혼합모음형][자음][모음][받침] - 4칸을 균일한 그리드로. */
#balanceControls .balance-class-row {
  display: grid; grid-template-columns: minmax(130px, 1.4fr) 1fr 1fr 1fr;
  gap: 6px; align-items: stretch;
}
#balanceControls .balance-cell {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 9px 11px; border: 1.2px solid var(--rule); border-radius: 10px; background: var(--cream);
}
/* 유형 이름(세로모음형 등)이 한 글자씩 세로로 쪼개지지 않게 한 줄 유지. */
#balanceControls .balance-class-row label { white-space: nowrap; }
#balanceControls .balance-class-row .balance-cell:not(.balance-cell-main) label { font-size: 12.5px; font-weight: 600; color: var(--ink-soft); }
/* 입력 영역은 셀 폭을 꽉 채워 모든 칸의 크기를 통일. '현재 N%'는 자리가 없으면 아랫줄로. */
#balanceControls .balance-class-row .balance-cell .balance-input-wrap { align-self: stretch; flex-wrap: wrap; white-space: normal; }
#balanceControls .balance-class-row .balance-cell input { flex: 1 1 auto; width: auto; min-width: 44px; }
#balanceFilter { margin-top: 4px; }
.spacing-preview-bar { display: flex; gap: 8px; margin-bottom: 10px; }
.spacing-preview-bar input { flex: 1; min-width: 0; padding: 8px 11px; border: 1.4px solid var(--rule); border-radius: 9px; background: var(--cream); color: var(--ink); font-size: 14px; }
.spacing-preview-bar input:focus { border-color: var(--accent); outline: none; }
.spacing-preview-bar button { padding: 8px 14px; border-radius: 999px; border: 1.4px solid var(--accent); background: var(--card); color: var(--accent); cursor: pointer; font-size: 13px; white-space: nowrap; }
.spacing-preview-strip { min-height: 92px; display: flex; align-items: center; justify-content: safe center; padding: 10px 16px; border: 1.4px solid var(--rule); border-radius: 12px; background: var(--cream); overflow-x: auto; white-space: nowrap; }
#balancePreviewText { font-family: "MoglediPreview", "GuideFont", sans-serif; font-size: 58px; line-height: 1.1; color: var(--ink); }
#balancePreviewText.pos-preview-placeholder { font-family: inherit; font-size: 14px; color: var(--ink-soft); }
#balancePreviewStatus { font-size: 12px; color: var(--ink-soft); min-height: 16px; margin: 4px 2px 0; text-align: center; }
.spacing-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }
.spacing-modal-actions button { padding: 8px 18px; border-radius: 999px; border: 1.4px solid var(--accent); background: var(--card); color: var(--accent); cursor: pointer; font-size: 13px; }
#balanceResetBtn { border-color: var(--rule); color: var(--ink-soft); margin-right: auto; }
#balanceApplyBtn { background: var(--accent); color: #fff; }
#balanceApplyBtn:disabled { opacity: 0.5; cursor: default; }

/* ===== 간격조정 모달(자간) ===== */
dialog#posModal {
  border: none;
  border-radius: 20px;
  padding: 26px 28px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(460px, 94vw);
  background: var(--card);
  color: var(--ink);
}
dialog#posModal::backdrop { background: rgba(0, 0, 0, 0.55); }
dialog#posModal h3 {
  margin: 0 0 12px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}
#posModalHint {
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
  margin-bottom: 14px;
}
#posPreviewBar, #spacingPreviewBar { display: flex; gap: 8px; margin-bottom: 10px; }
#spacingPreviewBar { margin-top: 12px; }
#posPreviewBar input, #spacingPreviewBar input {
  flex: 1; min-width: 0;
  padding: 8px 11px;
  border: 1.4px solid var(--rule);
  border-radius: 9px;
  background: var(--cream);
  color: var(--ink);
  font-size: 14px;
}
#posPreviewBar input:focus, #spacingPreviewBar input:focus { border-color: var(--accent); outline: none; }
#posPreviewBar button, #spacingPreviewBar button {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
  white-space: nowrap;
}
#posPreviewStrip, #spacingPreviewStrip {
  min-height: 92px;
  display: flex;
  align-items: center;
  /* safe center: 내용이 넘칠 땐 가운데정렬 대신 왼쪽(start)부터 놓아, 넘친 왼쪽 글자가
     스크롤로도 안 보이던 문제를 막는다(justify-content:center는 양쪽으로 넘쳐 왼쪽이 잘림). */
  justify-content: safe center;
  padding: 10px 16px;
  border: 1.4px solid var(--rule);
  border-radius: 12px;
  background: var(--cream);
  overflow-x: auto;
  white-space: nowrap;
}
#posPreviewText, #spacingPreviewText {
  font-family: "MoglediPreview", "GuideFont", sans-serif;
  font-size: 58px;
  line-height: 1.1;
  color: var(--ink);
}
#posPreviewText.pos-preview-placeholder, #spacingPreviewText.pos-preview-placeholder {
  font-family: inherit;
  font-size: 14px;
  color: var(--ink-soft);
}
#posPreviewStatus, #spacingPreviewStatus { font-size: 12px; color: var(--ink-soft); min-height: 16px; margin: 4px 2px 0; text-align: center; }
/* 띄어쓰기(스페이스 폭) 조정 - 간격조정 모달 상단의 독립 컨트롤 */
#posSpaceWrap { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--rule); border-radius: 10px; background: var(--cream); }
#posSpaceRow { display: flex; align-items: center; gap: 10px; margin: 8px 0 6px; }
#posSpaceRow input[type="number"] { width: 90px; padding: 7px 9px; border: 1.4px solid var(--rule); border-radius: 8px; font-size: 14px; font-variant-numeric: tabular-nums; }
#posSpaceUnit { color: var(--ink-soft); font-size: 13px; }
#posSpaceResetBtn, #posSpaceApplyBtn { padding: 6px 12px; border-radius: 8px; border: 1.4px solid var(--rule); background: #fff; cursor: pointer; font-size: 13px; }
#posSpaceApplyBtn { border-color: var(--accent); background: var(--accent); color: #fff; font-weight: 700; }

#posScopeWrap { margin-top: 14px; }
.pos-scope-opt {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  color: var(--ink);
  padding: 4px 0;
  cursor: pointer;
}
.pos-scope-opt input { accent-color: var(--accent); }
.pos-scope-note { color: var(--ink-soft); font-size: 12px; }
#posJamoFilter { margin: 8px 0 2px; padding-left: 24px; }
#posJamoFilter[hidden] { display: none; }
#posGapWrap { display: flex; gap: 12px; align-items: flex-end; margin: 8px 0 6px; padding-left: 24px; }
#posGapWrap[hidden] { display: none; }
.pos-gap { max-width: 190px; }
#posDeltaRow { display: flex; gap: 14px; margin-top: 14px; }
.pos-delta {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  color: var(--ink-soft);
}
.pos-delta input {
  width: 100%;
  text-align: right;
  padding: 8px 10px;
  border: 1.4px solid var(--rule);
  border-radius: 9px;
  background: var(--cream);
  color: var(--ink);
  font-size: 14px;
}
.pos-delta input:focus { border-color: var(--accent); outline: none; }
#posRulesWrap { margin-top: 18px; }
#posRulesList { display: flex; flex-direction: column; gap: 5px; max-height: 120px; overflow-y: auto; }
#posModalActions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}
#posModalActions button {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}
#posResetBtn { border-color: var(--rule); color: var(--ink-soft); margin-right: auto; }
#posApplyBtn { background: var(--accent); color: #fff; }
#posApplyBtn:disabled { opacity: 0.5; cursor: default; }

#brushSettings {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 2px 4px 0;
}

#widthLabel, #brushTypeLabel, #smoothingLabel, #pencilSizeLabel {
  display: flex;
  /* #widthLabel은 가로 방향 flex 컨테이너(#brushSettingsMain)의 자식이라
     기본값으로는 내용물 크기만큼만 차지해서(가로 stretch 없음) 매끄러움/
     연필 크기 라벨(세로 flex 컨테이너의 자식이라 기본으로 꽉 채워짐)보다
     몇 px 좁게 렌더링됐다 - 슬라이더 길이가 서로 달라 보이던 원인이라
     명시적으로 폭을 꽉 채운다. */
  width: 100%;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  color: var(--ink-soft);
}

#brushTypeLabel { justify-content: space-between; flex-wrap: nowrap; }
#brushTypeLabel > span:first-child { white-space: nowrap; flex-shrink: 0; }
/* 브러시 타입 펼침 목록도 접었을 때 버튼과 같은 폭으로(기본 min-width:178px 무시). */
#brushTypeDropdownMenu { left: 0; right: auto; width: 100%; min-width: 0; }
/* 브러시 타입 드롭다운 폭을 굵기 슬라이더와 같은 길이로 - 고정 폭 대신 남는 공간을
   꽉 채워(flex) 슬라이더 바처럼 늘어나게 하고, 오른쪽은 굵기 슬라이더 값("18pt")
   자리(약 42px)만큼 비워 드롭다운 오른쪽 끝을 슬라이더 끝과 맞춘다. */
#brushTypeLabel { padding-right: 42px; }
#brushTypeDropdown { flex: 1; min-width: 0; }
#brushTypeDropdownBtn { width: 100%; }

/* 굵기/매끄러움/연필 크기 라벨 글자 수가 서로 달라 슬라이더 시작 위치가
   제각각이었다 - 라벨을 고정 폭으로 두고 그 안에서 가운데 정렬해서 세
   슬라이더가 항상 같은 위치에서 시작하게 맞춘다. */
.brush-label-text {
  display: inline-block;
  width: 52px;
  flex-shrink: 0;
  text-align: center;
}

#widthLabel input[type="range"], #smoothingLabel input[type="range"], #previewSizeLabel input[type="range"], #pencilSizeLabel input[type="range"], #smoothStrengthFloat input[type="range"] {
  flex: 1;
  -webkit-appearance: none;
  appearance: none;
  height: 4px;
  border: none;
  outline: none;
  border-radius: 999px;
  background: var(--rule);
}

#widthLabel input[type="range"]::-webkit-slider-thumb,
#smoothingLabel input[type="range"]::-webkit-slider-thumb,
#previewSizeLabel input[type="range"]::-webkit-slider-thumb,
#pencilSizeLabel input[type="range"]::-webkit-slider-thumb,
#smoothStrengthFloat input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
  cursor: pointer;
}

#widthLabel input[type="range"]::-moz-range-thumb,
#smoothingLabel input[type="range"]::-moz-range-thumb,
#previewSizeLabel input[type="range"]::-moz-range-thumb,
#pencilSizeLabel input[type="range"]::-moz-range-thumb,
#smoothStrengthFloat input[type="range"]::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
  border: none;
  cursor: pointer;
}

#widthLabel input[type="range"]::-moz-range-track,
#smoothingLabel input[type="range"]::-moz-range-track,
#previewSizeLabel input[type="range"]::-moz-range-track,
#pencilSizeLabel input[type="range"]::-moz-range-track,
#smoothStrengthFloat input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: var(--rule);
  border: none;
}

#widthValue, #smoothingValue, #pencilSizeValue, #smoothStrengthValue {
  min-width: 32px;
  text-align: right;
  color: var(--ink);
}

.custom-select {
  position: relative;
}

.custom-select-btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 178px;
  padding: 5px 8px;
  border: 1.2px solid var(--rule);
  border-radius: 8px;
  font-size: 12px;
  color: var(--ink);
  background: var(--card);
  cursor: pointer;
  white-space: nowrap;
}

.custom-select-btn:focus, .custom-select-btn:hover { outline: none; border-color: var(--accent); }

#brushTypeDropdownLabel {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1;
}

.brush-preview-icon {
  width: 26px;
  height: 11px;
  color: var(--ink-soft);
  flex-shrink: 0;
}

.chevron-icon {
  width: 12px;
  height: 12px;
  color: var(--ink-soft);
  flex-shrink: 0;
  transition: transform 0.15s;
}

.custom-select.open .chevron-icon { transform: rotate(180deg); }

.custom-select-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 178px;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  box-shadow: 0 8px 24px var(--shadow-color);
  padding: 6px;
  z-index: 20;
  display: none;
  flex-direction: column;
  gap: 2px;
}

.custom-select.open .custom-select-menu { display: flex; }

.custom-select-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 10px;
  border: none;
  background: none;
  border-radius: 7px;
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  text-align: left;
}

.custom-select-option:hover { background: var(--cream); }

.custom-select-option.active {
  background: var(--accent-tint);
  color: var(--accent);
}

.custom-select-option .brush-preview-icon { color: inherit; }

.icon-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  border: none;
  background: none;
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 11px;
}

.icon-btn .circle {
  width: 36px;
  height: 36px;
  border-radius: 11px;
  background: var(--tile-bg);
  border: 1.4px solid var(--rule);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
  box-shadow: 0 1px 2px var(--shadow-color);
}

/* 도구 가방 안의 타일은 한 줄에 다 들어가야 하므로(그리기 5개/편집 5개/변형 4개) */
#toolSelectGroup .icon-btn, #tools .icon-btn, #tools2 .icon-btn {
  width: auto;
  min-width: 42px;
  font-size: 10.5px;
  white-space: nowrap;
  line-height: 1.15;
  flex-shrink: 0;
  gap: 4px;
}

#toolSelectGroup .icon-btn .circle, #tools .icon-btn .circle, #tools2 .icon-btn .circle {
  width: 36px;
  height: 36px;
  border-radius: 10px;
}

#toolSelectGroup .icon-btn .circle .icon, #tools .icon-btn .circle .icon, #tools2 .icon-btn .circle .icon {
  width: 17px;
  height: 17px;
}

.icon-btn .circle .icon {
  width: 17px;
  height: 17px;
  color: var(--ink-soft);
  transition: color 0.15s;
}

.icon-btn:hover .circle { border-color: var(--accent); transform: translateY(-2px); }
.icon-btn:hover .circle .icon { color: var(--accent); }

.icon-btn.active .circle {
  background: var(--accent);
  border-color: var(--accent);
}
.icon-btn.active .circle .icon { color: white; }
.icon-btn.active { color: var(--accent); }

#shortcutList {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

#shortcutList li {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 10px;
}

#shortcutList .key {
  justify-self: start;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--cream);
  border: 1px solid var(--rule);
  font-family: monospace;
  font-size: 11px;
  color: var(--accent);
  white-space: nowrap;
}

#shortcutList .desc {
  font-size: 11px;
  color: var(--ink-soft);
}

#previewSection {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

#previewInputGroup {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

#previewToolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 6px;
}

#previewToolbarRight {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

#previewToolbar h2 {
  margin: 0;
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--ink-soft);
  letter-spacing: 0.3px;
  flex-shrink: 0;
}

/* 실시간 미리보기 접기/펼치기 - 화면 크기와 무관하게 언제든 숨겼다 다시 꺼낼 수
   있게 한다(글자가 커질수록 미리보기 박스가 늘어날 수 있게 되면서, 필요 없을 때
   치워둘 방법이 있어야 한다). */
#previewToggleBtn {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
}

#previewToggleBtn:hover { color: var(--accent); }

#previewToggleBtn .chevron-icon {
  width: 16px;
  height: 16px;
  transition: transform 0.15s ease;
}

/* 펼쳐진 상태(기본값)에서는 위를 가리켜 "접을 수 있음"을 알려준다 */
#previewSection:not(.preview-collapsed) #previewToggleBtn .chevron-icon {
  transform: rotate(180deg);
}

#previewSection.preview-collapsed #previewSizeLabel,
#previewSection.preview-collapsed #previewStatus,
#previewSection.preview-collapsed #previewInputGroup,
#previewSection.preview-collapsed #previewBottomRow {
  display: none;
}

#previewBottomRow {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.text-icon-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: none;
  color: var(--ink-soft);
  font-size: 12px;
  font-family: "GuideFont", sans-serif;
  cursor: pointer;
  padding: 4px 0;
}

.text-icon-btn svg { width: 15px; height: 15px; }
.text-icon-btn:hover { color: var(--accent); }

#previewSizeLabel {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-soft);
  white-space: nowrap;
  min-width: 0;
}

#previewStatus {
  display: block;
  color: var(--ink-soft);
  font-size: 12px;
  line-height: 14px;
  min-height: 14px; /* 항상 한 줄 높이를 확보한다 - 예전엔 비어있을 때 display:none으로
                        접었는데, 그러면 자모를 그릴 때마다(획 저장 -> 자동 미리보기
                        새로고침) 이 문구가 나타났다 사라지며 #previewSection 전체
                        높이가 바뀌고, flex 컬럼을 같이 쓰는 캔버스(#canvasWrap, min()에
                        100%가 들어있음)가 그만큼 커졌다 작아졌다 했다 - 그리는 도중
                        캔버스 크기가 흔들려 브러시 획이 삐뚤어지는 원인이었다(사용자
                        보고). 항상 자리를 고정해두면 문구 유무와 무관하게 높이가 절대
                        안 바뀐다. */
}

#previewInputRow {
  display: flex;
  align-items: center;
  gap: 6px;
  position: relative;
}

#previewInput {
  width: 100%;
  flex: 1;
  min-width: 0;
  padding: 7px 14px;
  border: 1.4px solid var(--rule);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink);
  text-align: center;
}

#previewInput:focus { border-color: var(--accent); outline: none; }

#previewSentenceMenuBtn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 3px;
  border: 1.4px solid var(--rule);
  border-radius: 999px;
  padding: 0 12px;
  height: 32px;
  background: var(--cream);
  color: var(--ink);
  font-size: 12px;
  font-family: "GuideFontBold", sans-serif;
  cursor: pointer;
  white-space: nowrap;
}

#previewSentenceMenuBtn:hover { border-color: var(--accent); color: var(--accent); }
#previewSentenceMenuBtn .chevron-icon { width: 12px; height: 12px; }

/* 캔버스 우클릭 메뉴(.context-menu)와 같은 룩앤필을 쓰되, 여기선 fixed 좌표를
   JS로 계산할 필요 없이 버튼 바로 아래에 CSS만으로 고정한다. */
#previewSentenceMenu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  left: auto;
  min-width: 180px;
  max-height: 260px;
  overflow-y: auto;
}

/* 글자 크기를 키우면 줄바꿈되면서 세로로 길어져 flex:1인 캔버스가 그만큼
   줄어들던 문제 - 줄바꿈 대신(white-space:nowrap) 가로로 넘치게 하고,
   넘친 부분은 가로 스크롤로 보게 한다(모바일은 아래에서 overflow-x:hidden으로
   덮어써서 스크롤 없이 그냥 잘리게 한다). 최대 크기(72pt)로도 위아래가
   잘리지 않도록 min-height를 넉넉히 잡는다. */
#previewText {
  width: 100%;
  min-height: 108px;
  /* 세로 가운데 정렬: 한 줄짜리 내용의 줄 높이를 박스 높이와 같게 잡는
     방식(line-height 트릭)이라 .preview-char 클릭 영역 레이아웃에 영향을
     주지 않는다. */
  line-height: 108px;
  padding: 0 18px;
  border: none;
  border-radius: 12px;
  background: var(--cream);
  font-family: "MoglediPreview", sans-serif;
  font-size: 20px;
  color: var(--ink);
  text-align: center;
  white-space: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
}

/* "영문 전체"처럼 \n이 든 여러 줄 예문 - 단일행 nowrap/line-height 트릭을 끄고
   pre-wrap으로 줄바꿈을 살린다. display는 그대로 두어(flex 부모 안에서 grid로 바꾸면
   높이가 늘어나 버림) 블록 흐름으로 두 줄이 자연 높이로만 쌓이게 한다. */
#previewText.multiline {
  white-space: pre-wrap;
  line-height: 1.5;
  overflow-x: hidden;
  padding-top: 14px;
  padding-bottom: 14px;
}

#previewText .preview-char {
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 0.12s ease;
}

#previewText .preview-char:hover {
  background-color: var(--rule);
}

/* ---------- 도움말(단축키) 모달 ---------- */

dialog#helpModal {
  border: none;
  border-radius: 16px;
  padding: 24px 28px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.2);
  width: min(420px, 90vw);
  max-height: 80vh;
  overflow-y: auto;
  background: var(--card);
  color: var(--ink);
}

dialog#helpModal::backdrop { background: rgba(0, 0, 0, 0.55); }

dialog#helpModal h3 {
  margin: 0 0 16px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
}

#helpModalActions {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

#helpCloseBtn {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

/* ---------- 이름 입력 모달 ---------- */

dialog#nameModal {
  border: none;
  border-radius: 20px;
  padding: 32px 34px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(440px, 90vw);
  background: var(--card);
  color: var(--ink);
}

dialog#nameModal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

dialog#nameModal h3 {
  margin: 0 0 20px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}

dialog#nameModal label {
  display: flex;
  flex-direction: column;
  gap: 7px;
  font-size: 13px;
  color: var(--ink);
  font-weight: 700;
  margin-bottom: 18px;
}
/* '폰트 스토어 등록 신청' 라벨도 검정·굵게(안내문 .modal-field-desc는 그대로 흐리게). */
dialog#nameModal .modal-field-label { color: var(--ink); font-weight: 700; }

dialog#nameModal input {
  padding: 11px 14px;
  border: 1.4px solid var(--rule);
  border-radius: 10px;
  font-size: 15px;
  color: var(--ink);
  background: var(--cream);
}

dialog#nameModal input:focus { border-color: var(--accent); outline: none; }

.modal-field {
  display: flex;
  flex-direction: column;
  gap: 9px;
  margin-bottom: 20px;
}

.modal-field-label {
  font-size: 13px;
  color: var(--ink-soft);
}

.modal-field-desc {
  margin: -3px 0 2px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.weight-segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  background: var(--cream);
  padding: 6px;
  border-radius: 12px;
}

.weight-option {
  padding: 14px 8px;
  border: none;
  border-radius: 9px;
  background: transparent;
  color: var(--ink-soft);
  font-family: "GuideFontBold", sans-serif;
  font-size: 15px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}

.weight-option:hover { color: var(--ink); }

.weight-option.active {
  background: var(--card);
  color: var(--accent);
  box-shadow: 0 2px 8px var(--shadow-color);
}

#modalActions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
}

#modalActions button {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

#nameConfirmBtn {
  background: var(--accent);
  color: white;
}

/* ---------- 폰트 제작 중 / 다운로드 모달 ---------- */

dialog#buildingModal, dialog#downloadReadyModal {
  border: none;
  border-radius: 16px;
  padding: 28px 32px;
  box-shadow: 0 8px 30px rgba(0,0,0,0.2);
  width: min(320px, 90vw);
  text-align: center;
  background: var(--card);
  color: var(--ink);
}

dialog#buildingModal::backdrop, dialog#downloadReadyModal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

dialog#buildingModal h3, dialog#downloadReadyModal h3 {
  margin: 0 0 14px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 17px;
}

#buildingSpinner {
  width: 34px;
  height: 34px;
  margin: 0 auto 16px;
  border: 3.5px solid var(--rule);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: buildingSpin 0.8s linear infinite;
}

@keyframes buildingSpin {
  to { transform: rotate(360deg); }
}

#buildingStatusText {
  margin: 0;
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.5;
  word-break: break-all;
}

#buildingModalCloseBtn, #downloadModalCloseBtn {
  margin-top: 18px;
  padding: 8px 20px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

#downloadModalActions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.download-format-link {
  display: block;
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--accent);
  color: white;
  text-decoration: none;
  font-family: "GuideFontBold", sans-serif;
  font-size: 14px;
  transition: background 0.15s, transform 0.1s;
}

.download-format-link:hover { background: #c0433f; transform: translateY(-1px); }

dialog#previewModal {
  border: none;
  border-radius: 20px;
  padding: 32px 34px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(560px, 90vw);
  background: var(--card);
  color: var(--ink);
}

dialog#previewModal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

dialog#previewModal h3 {
  margin: 0 0 16px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}

#previewModalCategoryGroup {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

#previewModalStatus {
  display: block;
  text-align: center;
  color: var(--ink-soft);
  font-size: 12px;
  min-height: 14px;
  margin-bottom: 4px;
}

.preview-category-btn {
  flex: 1;
  padding: 9px 0;
  border: 1.4px solid var(--rule);
  border-radius: 10px;
  background: var(--card);
  color: var(--ink-soft);
  font-size: 13px;
  font-family: "GuideFontBold", sans-serif;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
}

.preview-category-btn:hover { border-color: var(--accent); }

.preview-category-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

#previewModalText {
  width: 100%;
  min-height: 100px;
  padding: 16px;
  border-radius: 12px;
  background: var(--cream);
  font-family: "MoglediPreview", sans-serif;
  /* "미리보기 버튼 눌렀을 때 한글/영어/특수문자 크기를 더 키워달라"는 요청 -
     세 카테고리 모두 이 같은 요소(#previewModalText)를 공유해서 렌더링하므로
     하나만 키우면 셋 다 같이 커진다. */
  font-size: 32px;
  color: var(--ink);
  text-align: center;
  word-break: break-word;
  line-height: 1.5;
}

/* 특수문자는 띄어쓰기가 전혀 없는 기호 나열이다 - word-break:break-word는
   유니코드 줄바꿈 규칙을 따르는데, 음표/화살표 같은 일부 기호는 그 규칙상
   "여기서만 끊어라"는 지점이 정해져 있어 몇 글자만 다음 줄로 밀리면서 직전
   줄이 몇 글자 남고 뚝 끊긴 것처럼 보였다. break-all로 그 규칙과 무관하게
   아무 글자 사이에서나 끊게 해서 항상 줄이 꽉 채워지게 한다 - 이렇게 하면
   가운데 정렬이어도 마지막 줄만 짧아질 뿐(한글/영문 문장과 같은 자연스러운
   모습) 중간에 끊긴 것처럼 보이지 않는다. */
#previewModalText.symbol-mode {
  word-break: break-all;
}

#previewModalText .preview-char {
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 0.12s ease;
}

#previewModalText .preview-char:hover {
  background-color: var(--rule);
}

#previewModalText.empty {
  font-family: "GuideFont", sans-serif;
  font-size: 13px;
  color: var(--ink-soft);
}

/* 아직 안 그린 글자만 기본 폰트로 - 나머지 그려진 글자와 섞여있을 때 어떤 글자가
   아직 안 됐는지도 자연스럽게 눈에 들어온다. */
#previewModalText .preview-char-fallback {
  font-family: "GuideFont", sans-serif;
}

#previewModalActions {
  display: flex;
  justify-content: flex-end;
  margin-top: 18px;
}

#previewModalCloseBtn {
  padding: 8px 20px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

/* 전체 한글 보기 모달 - 예문 미리보기(#previewModal)와 같은 카드 스타일이지만,
   2,780~11,172자를 한 화면에 다 보여줘야 해서 훨씬 크고 세로 스크롤이 생긴다. */
dialog#allHangulModal {
  border: none;
  border-radius: 20px;
  padding: 28px 30px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(900px, 92vw);
  height: min(720px, 86vh);
  background: var(--card);
  color: var(--ink);
}

dialog#allHangulModal[open] {
  display: flex;
  flex-direction: column;
}

dialog#allHangulModal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

dialog#allHangulModal h3 {
  margin: 0 0 12px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
  flex-shrink: 0;
}

#allHangulModalStatus {
  display: block;
  text-align: center;
  color: var(--ink-soft);
  font-size: 12px;
  min-height: 16px;
  margin-bottom: 8px;
  flex-shrink: 0;
}

#allHangulModalText {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px;
  border-radius: 12px;
  background: var(--cream);
  font-family: "MoglediAllHangul", sans-serif;
  font-size: 30px;
  color: var(--ink);
  line-height: 1.5;
  word-break: break-all;
}

#allHangulModalActions {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
  flex-shrink: 0;
}

#allHangulModalCloseBtn {
  padding: 8px 20px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

@media (max-width: 767px) {
  dialog#allHangulModal {
    width: 94vw;
    height: 88vh;
    padding: 20px 18px;
  }
  #allHangulModalText { font-size: 24px; }
}

/* ---------- 반응형 (좁은 화면: 한 열로 쌓기) ----------
   태블릿 세로(768px~1024px, portrait)도 여기 같이 포함시킨다 - 화면 폭이
   좁아 그리기 도구를 캔버스 위/아래로 쌓아야 하는 사정은 휴대폰과 같고,
   가로(landscape)만 별도의 태블릿 전용 블록(위)에서 처리한다. */
@media (max-width: 767px), (min-width: 768px) and (max-width: 1100px) and (orientation: portrait) {
  /* 페이지 자체는 스크롤되지 않고(body 높이를 뷰포트에 고정), 캔버스가 남는
     세로 공간에 맞춰 자동으로 커지고 줄어든다 - PC 무스크롤과 같은 원리를
     모바일에도 적용한다(아래 body/#appBody/#canvasArea/#canvasWrap 규칙 참고).
     에디터 페이지(body.editor-page)에만 적용한다 - 관리자/마이페이지 등 다른
     모든 페이지도 이 style.css를 같이 쓰므로, 범위를 안 좁히면 그 페이지들까지
     스크롤이 통째로 막혀버린다. */
  body.editor-page {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }

  #appBody {
    grid-template-columns: 1fr;
    /* PC와 같은 이유(암시적 auto 행이 내부 flex 자손의 콘텐츠 크기를 그대로
       반영해버리는 그리드+플렉스 중첩 문제)로 행 크기를 appBody 자신의 남는
       공간(1fr)으로 못박는다. */
    grid-template-rows: minmax(0, 1fr);
    /* 아래 flex:1;min-height:0 체인이 정상적으로 다 줄어들면 스크롤이 생기지
       않는다 - 아주 낮은 화면 등 그래도 다 못 줄어드는 극단적인 경우에만
       최후 수단으로 이 안에서만 스크롤되게 한다(페이지 전체 스크롤은 막힌
       채로). */
    overflow-y: auto;
    overflow-x: hidden;
    /* 화면 하단 고정 바(#questHeaderSpacer)가 appBody 박스 아래쪽 20px만 덮으므로,
       그만큼만 여백을 남겨 캔버스 카드가 바 바로 위까지 꽉 차게 한다(하단 빈 여백 제거). */
    padding-bottom: 20px;
    /* 세로 스크롤바는 숨긴다(스크롤 자체는 유지) - 아래 내부 스크롤 컨테이너도 함께. */
    scrollbar-width: none;
  }
  #appBody::-webkit-scrollbar { display: none; }

  /* 모바일: 캔버스 카드/글자 목록/속성 서랍의 세로 스크롤바 숨김(스크롤은 그대로). */
  #workCard, #sidebarLeft, #sidebarRight, #charGrid { scrollbar-width: none; }
  #workCard::-webkit-scrollbar, #sidebarLeft::-webkit-scrollbar,
  #sidebarRight::-webkit-scrollbar, #charGrid::-webkit-scrollbar { display: none; }

  #sidebarLeft, #sidebarRight {
    position: static;
  }

  #charGridCard, #charGrid {
    flex: none;
    max-height: none;
  }
}

/* ---------- 태블릿 가로 전용 (768px~1024px, landscape): 서랍이 아니라 좁아진
   고정 사이드바 ----------
   PC와 같은 3열 그리드/캔버스 상단바/속성 패널 구조를 그대로 쓰되, 사이드바 폭만
   좁힌다. 태블릿 세로(portrait)는 아래 모바일 블록의 미디어 쿼리에 같이
   포함시켜서(오리엔테이션만 다를 뿐 화면 폭이 좁은 건 같으므로) 모바일과
   완전히 동일한 서랍/엣지탭/캔버스 레이아웃을 그대로 쓴다. */
@media (min-width: 768px) and (max-width: 1100px) and (orientation: landscape) {
  #appBody {
    grid-template-columns: 210px minmax(0, 1fr) 235px;
    gap: 14px;
    padding: 14px 16px;
  }

  /* 현재글자/다음글자를 position:absolute로 두려면 그 기준이 되는 카드 자체가
     position:relative여야 한다(PC와 같은 이유). */
  #workCard { position: relative; }

  /* 도구독/그리드독/현재-다음글자를 PC와 똑같이 캔버스 좌우에 세로로 세워둔다
     (#canvasArea/#drawToolDock/#canvasRightDock/#zoomControls 모두 별도
     오버라이드 없이 기본 규칙 그대로 써서 PC와 동일한 가로 한 줄:
     도구독 | 캔버스 | 그리드독 구조가 된다). 현재글자/다음글자도 PC처럼
     카드 기준 position:absolute로 도구독/그리드독 바로 위에 둔다 -
     JS(syncCurrentCharGroupPosition)가 PC와 같은 로직으로 위치를 잡아준다. */
  #currentCharGroup, #nextCharGroup {
    position: absolute;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 70px;
    padding: 6px 4px;
    border-radius: 14px;
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .pc-char-caption { margin-left: 0; }
}

/* ---------- PC 전용 (1025px 이상): 페이지 자체는 스크롤되지 않고, 내용이 많은
   패널(글자 목록/속성 패널)만 그 안에서 스크롤된다 ----------
   body/appBody 높이를 뷰포트에 딱 맞게 고정해야만(overflow:hidden) #appBody의
   3개 열(align-items:stretch)과 그 안의 flex:1;min-height:0 체인들이 "진짜
   정해진 높이"를 기준으로 계산된다 - 그래야 #charGrid/오른쪽 속성 패널이 JS
   측정 없이도 순수 CSS로 남는 공간에 딱 맞게 줄어들고, 넘치는 내용은 그
   패널 안에서만 스크롤된다(태블릿/모바일은 이 고정을 하지 않으므로 이 계산이
   그대로 통하지 않아 자바스크립트 측정(syncCharGridHeight)에 계속 의존한다). */
@media (min-width: 1101px) {
  /* body.editor-page로 범위를 좁힌 이유는 위 모바일/태블릿 블록의 주석 참고. */
  body.editor-page {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }

  /* grid-template-rows를 명시하지 않으면 암시적 "auto" 트랙이 내부 flex/overflow
     자손들의 콘텐츠 크기를 그대로 반영해버려서(그리드+플렉스 중첩 시 브라우저의
     "max-content contribution" 계산 특성), align-items:stretch로 늘어난 각 열이
     appBody 자신의 실제 높이보다 더 커지는 현상이 생긴다 - 행 크기를 appBody의
     남는 공간(1fr)으로 못박아 이 문제를 원천 차단한다. */
  #appBody {
    overflow: hidden;
    grid-template-rows: minmax(0, 1fr);
    /* 왼쪽 글자 검색/목록 카드도 오른쪽 속성 패널과 같은 폭으로.
       고정폭(320px) 대신 clamp()로 모니터 가로길이에 비례해서 커지고
       줄어들게 한다 - 노트북처럼 좁은 화면에서는 최소 280px, 아주 넓은
       모니터에서는 최대 420px까지. 1400px로 못박혀 있던 전체 폭 제한도
       풀어서(아래 max-width:none) 가운데 칸(1fr, 캔버스)이 화면이 넓어지는
       만큼 계속 커질 수 있게 한다. */
    grid-template-columns: clamp(280px, 20vw, 420px) minmax(0, 1fr) clamp(280px, 20vw, 420px);
    max-width: none;
  }

  /* 위 진행률 바도 아래 3열 폭 제한 해제와 맞춰서 같이 넓어지게 한다 -
     안 그러면 아래는 넓어지는데 위 바만 1400px에 묶여 있어 어긋나 보인다. */
  #questHeaderRow { max-width: none; }

  #charGrid, #sidebarRight > .side-card {
    max-height: none;
  }

  /* 안내글자(현재글자 라벨)를 캔버스 바로 왼쪽, 그리기 도구독 바로 위에 오게
     한다. 도구독/격자독은 원래대로 캔버스와 함께 가운데 정렬된 한 줄이라
     (justify-content:center, flex 그대로) 도구독의 실제 좌표가 캔버스 크기에
     따라 매번 달라진다 - canvasTopBar 안에 두고 CSS로 맞추는 대신, 카드 기준
     position:absolute로 빼서 JS(syncCurrentCharGroupPosition)가 도구독의
     실제 위치를 실측해 top/left를 그때그때 맞춰준다. 다음글자(#nextCharGroup)도
     같은 방식으로 그리드/줌 독(#canvasRightDock) 바로 위, 캔버스 바로
     오른쪽에 오게 맞춘다(모바일의 현재글자-도구독-다음글자 배치와 같은 발상). */
  #workCard {
    position: relative;
    /* 가운데 칸이 넓어져도 캔버스 카드가 계속 760px에 묶여 있으면 늘어난
       공간이 다 빈 여백으로 낭비된다 - 실시간 미리보기(72pt까지) 등이
       넓어진 폭을 실제로 쓸 수 있게 최대 폭을 늘린다. */
    max-width: 1100px;
  }

  #currentCharGroup, #nextCharGroup {
    position: absolute;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 78px;
    padding: 6px 4px;
    /* 아래 그리기 도구독(#drawToolDock)과 모서리 라운드를 통일 */
    border-radius: 14px;
    /* 새로고침 직후 위치가 자리잡기 전(글자 목록이 비동기로 채워지며 도구독
       위치가 계속 바뀌는 동안) 그리기 도구독과 겹쳐 보이던 문제 - 자바스크립트
       (revealCharGroups)가 최종 위치를 확정한 뒤에야 보이게 한다. */
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .pc-char-caption { margin-left: 0; }

  #canvasArea {
    flex: 1;
    min-height: 0;
    /* 캔버스와 양옆 도구독 사이 간격을 기본값(10px)보다 조금 더 넉넉하게. */
    gap: 22px;
  }

  #canvasWrap {
    width: auto;
    height: 100%;
    max-width: 100%;
  }
}

/* ---------- PC 초와이드 (1920px 이상): 사이드바는 고정, 가운데 캔버스만 확장 ----------
   위 clamp(280px,20vw,420px)는 2100px(20vw=420px)에서야 상한에 닿으므로, 그
   사이(1920~2100px)에서는 사이드바가 계속 커지면서 정작 가운데 칸은 #workCard의
   max-width:1100px에 막혀 안 커지고 그만큼 빈 여백만 늘어난다 - 1920px 지점의
   실제 값(20vw = 384px)으로 사이드바 폭을 그대로 고정해 그 지점에서 폭이 툭
   끊기지 않게 하고, workCard의 상한을 풀어서 남는 폭을 가운데 칸(글자검색창/
   속성창 폭은 그대로 두고 캔버스 카드만)이 그대로 넓게 쓰게 한다. */
@media (min-width: 1920px) {
  #appBody {
    grid-template-columns: 384px minmax(0, 1fr) 384px;
  }

  #workCard {
    max-width: none;
  }
}

@media (max-width: 640px) {
  #headerTop {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }

  header h1 { font-size: 18px; }

  /* padding-bottom은 손대지 않는다 - 위쪽 767px 블록에서 하단 고정바 자리를
     비워두려고 잡아둔 값(74px)이 있어서, 여기서 단축 속성으로 덮어쓰면 안 된다. */
  #appBody { padding-top: 12px; padding-left: 14px; padding-right: 14px; gap: 12px; }

  #nav { flex-wrap: wrap; gap: 10px; }

  #tools { gap: 10px; }

  #tools2 { gap: 8px; }

  #buildBtn, #previewJumpBtn { font-size: 15px; padding: 13px 22px; }
}

/* ---------- 결제 유도 모달 (무료 체험 한도 도달 / 다운로드 결제 필요) ---------- */

dialog#paywallModal {
  border: none;
  border-radius: 20px;
  padding: 32px 34px;
  box-shadow: 0 12px 40px rgba(0,0,0,0.22);
  width: min(460px, 90vw);
  background: var(--card);
  color: var(--ink);
}

dialog#paywallModal::backdrop {
  background: rgba(0, 0, 0, 0.55);
}

dialog#paywallModal h3 {
  margin: 0 0 10px;
  font-family: "GuideFontBold", sans-serif;
  color: var(--accent);
  font-size: 19px;
}

#paywallStatusText {
  margin: 0 0 18px;
  color: var(--ink-soft);
  font-size: 13.5px;
  line-height: 1.5;
}

#paywallProductGroup {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}

#paywallProductGroup .charset-choice-btn { padding: 24px 14px; }
#paywallProductGroup .charset-choice-btn:disabled {
  opacity: 0.6;
  cursor: default;
  pointer-events: none;
}

#paywallDevPayBtn {
  display: block;
  margin: 0 0 8px;
  padding: 0;
  border: none;
  background: none;
  color: var(--ink-soft);
  font-size: 11.5px;
  line-height: 1.5;
  text-decoration: underline;
  cursor: pointer;
}
#paywallDevPayBtn:hover { color: var(--accent); }

#paywallModalActions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 8px;
}

#paywallModalActions button {
  padding: 8px 18px;
  border-radius: 999px;
  border: 1.4px solid var(--accent);
  background: var(--card);
  color: var(--accent);
  cursor: pointer;
  font-size: 13px;
}

/* ==================================================================
   모바일 전용 UI (서랍/펼침/하단 고정바) - 데스크톱에서는 기본적으로
   전부 숨겨두고, 아래 @media (max-width: 1000px) 블록에서만 켠다.
   ================================================================== */

.drawer-trigger-btn { display: none; }

#mobileProgressSummary, #mobileProgressDetail { display: none; }

#brushSettingsMain {
  display: flex;
  align-items: center;
  gap: 8px;
}

#brushSettingsExtra {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* '브러시 설정' 제목 줄 오른쪽에 압력 감지 토글을 둔다(제목은 왼쪽, 토글은 오른쪽 끝). */
#brushSettingsHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
#brushSettingsHead #pressureToggleRow { margin-top: 0; }

#drawerBackdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 190;
}

#drawerBackdrop.visible { display: block; }

/* 상단 내비바 "더보기(⋮)" 메뉴 - 데스크톱에서는 안 쓴다 */
#navMoreBtn { display: none; }
#navMoreMenu { display: none; }

/* 캔버스 아래 "속성 도구" 바(실행취소~교차, 정렬 펼침) - 데스크톱에서는 이미
   오른쪽 속성 패널에 같은 기능이 있으므로 안 쓴다. */
#mobileQuickToolsBar { display: none; }

/* 즐겨찾기 도구창(태블릿 세로 전용) - 기본은 숨겨두고 태블릿 세로 미디어
   쿼리에서만 켠다. */
#favoritesBar { display: none; }

/* 모바일 전용 "지금/다음 쓸 글자" - .canvasTopBarGroup 클래스 기본값이
   display:flex라 이걸로 덮어써야 PC/태블릿에서 canvasToolRow(=display:contents
   라 canvasArea의 flex row에 직접 참여)에 빈 박스로 끼어드는 걸 막는다. */
#mobileCurrentCharGroup, #mobileNextCharGroup { display: none; }

@media (max-width: 767px), (min-width: 768px) and (max-width: 1100px) and (orientation: portrait) {
  /* ---- 상단 내비바: 로고/프로젝트명/자동저장됨만 남기고 나머지는 ⋮ 메뉴로 ---- */
  #navbarRight > *:not(#navMoreBtn):not(#navMoreMenu) { display: none; }

  #navbarRight { position: relative; }

  #navMoreBtn {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 8px;
  }

  #navMoreMenu {
    display: none;
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    flex-direction: column;
    min-width: 180px;
    padding: 6px;
    border-radius: 12px;
    background: var(--card);
    border: 1px solid var(--rule);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
    z-index: 210;
  }

  #navMoreMenu.open { display: flex; }

  .nav-menu-item {
    display: block;
    width: 100%;
    padding: 10px 12px;
    border: none;
    background: none;
    color: var(--ink);
    font-size: 13px;
    text-align: left;
    text-decoration: none;
    border-radius: 8px;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  .nav-menu-item:hover { background: var(--cream); }

  /* ---- 상단 진행률: 한 줄 요약 + 펼침 상세 ---- */
  /* #questHeaderRow 자체를 통째로 숨기면 그 자식인 #questHeaderSpacer(미리보기/폰트
     만들기 버튼)까지 같이 사라진다 - position:fixed를 줘도 조상이 display:none이면
     화면에 안 그려지므로, 감춰야 할 두 부분(진행률 통계/마일스톤)만 따로 숨긴다. */
  /* 모바일도 데스크톱처럼 스텝 트래커(마일스톤)를 그대로 보여준다 - 펼침 요약 없이,
     7개 단계가 화면보다 넓으면 가로로 스와이프해서 볼 수 있게 한다. */
  #questHeaderLeft { display: none; }
  #questHeaderRow { padding: 0; gap: 0; }
  #milestoneRow {
    display: flex;
    /* 화면에 다 들어오면 가운데, 넘치면 왼쪽부터(safe) 보여줘서 스크롤로 나머지 확인. */
    justify-content: safe center;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    padding: 10px 14px 6px;
    scrollbar-width: none;
    /* 진행률 헤더 안에서 전체 폭을 쓰게 한다(플렉스 형제에 눌려 좁아지지 않게). */
    width: 100%;
    box-sizing: border-box;
    order: 2;
  }
  /* 진행률 헤더를 세로로 쌓아 마일스톤 줄이 한 줄을 통째로 쓰게 한다. */
  #questHeaderRow { display: flex; flex-direction: column; }
  #milestoneRow::-webkit-scrollbar { display: none; }
  #milestoneRow .milestone { flex-shrink: 0; }
  /* 단계 이름(세로모음용 등 5글자)이 좁은 칸에서 두 줄로 접히지 않게 - 폰트를 줄이고
     한 줄로 고정한다(칸 폭도 살짝 넓혀 5글자가 한 줄에 들어오게). */
  #milestoneRow { --milestone-width: 50px; }
  #milestoneRow .milestone-label { font-size: 9px; white-space: nowrap; }

  /* 요약 줄은 "제작 진행률"이라는 고정 라벨 + 지금 선택된 그룹의 N/전체 · N%를
     가운데 정렬로 한 줄에 보여준다 - 탭하면 그룹을 고를 수 있는 목록(상세)이
     펼쳐지고, 그룹을 하나 고르면 그 그룹 하나의 게이지바만 요약에 반영된 채
     목록은 다시 접힌다. */
  /* 펼침 요약 방식은 스텝 트래커로 대체 - 요약 버튼/상세 목록 모두 숨긴다. */
  #mobileProgressSummary, #mobileProgressDetail { display: none; }

  #mobileProgressGroupText { font-size: 15px; color: var(--ink-soft); }

  #mobileProgressRight {
    display: flex;
    align-items: center;
    gap: 4px;
    color: var(--ink);
    font-size: 14px;
  }

  /* N% 는 빨간색 + 더 큰 글자로 강조, N/전체자는 검정으로 뒤에 붙인다 */
  #mobileProgressPct {
    color: var(--accent);
    font-size: 21px;
  }

  #mobileProgressSep { color: var(--ink-soft); }
  #mobileProgressCount { color: var(--ink); }

  #mobileProgressRight .chevron-icon {
    width: 16px;
    height: 16px;
    transition: transform 0.15s ease;
  }

  #mobileProgressSummary.expanded #mobileProgressRight .chevron-icon { transform: rotate(180deg); }

  #mobileProgressDetail {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 4px 4px 10px;
  }

  #mobileProgressDetail[hidden] { display: none; }

  /* ---- 글자 목록 / 속성 서랍 트리거: 화면 좌우 가장자리에 고정된 세로 탭 ----
     canvasToolRow 안에 있던 자리에서 빼서 화면 왼쪽/오른쪽 끝에 붙이고,
     텍스트를 세로쓰기(writing-mode)로, 화살표 아이콘으로 당기는 방향을
     알려준다. */
  .drawer-trigger-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 150;
    width: auto;
    padding: 14px 6px;
    border: 1.4px solid var(--rule);
    background: var(--card);
    color: var(--ink-soft);
    font-size: 12px;
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  }

  .drawer-trigger-btn span {
    writing-mode: vertical-rl;
    text-orientation: upright;
    letter-spacing: 1px;
  }

  .drawer-trigger-btn .drawer-arrow-icon { width: 16px; height: 16px; flex-shrink: 0; }

  #charListDrawerBtn { left: 0; border-radius: 0 14px 14px 0; border-left: none; }
  #propsDrawerBtn { right: 0; border-radius: 14px 0 0 14px; border-right: none; }

  /* ---- 캔버스 상단바: 이전 - 순서 - 다음 (지금 쓰고 있는 글자 표시는 모바일에서
     뺐다 - 캔버스 위에 안내 글자로 이미 크게 보이므로 중복) ----
     canvasTopBarCenter는 원래 prevBtn/posInfo/nextBtn를 담는 별도 래퍼인데,
     display:contents로 그 박스 자체를 없애서 안의 요소들을 canvasTopBar의
     grid에 직접 참여시킨다(DOM은 안 건드리고 시각적 배치만 바꾼다). */
  #canvasTopBar {
    display: grid;
    grid-template-columns: auto 1fr auto;
    grid-template-areas: "prev posinfo next";
    align-items: center;
    justify-items: center;
    gap: 6px;
    padding: 10px 4px;
  }

  #canvasTopBarCenter { display: contents; }
  #nextCharGroup { display: none; }
  #currentCharGroup { display: none; }

  #prevBtn { grid-area: prev; }
  #posInfo { grid-area: posinfo; }
  #nextBtn { grid-area: next; }

  /* ---- 상단 내비바: "자동 저장됨" 문구는 좁은 화면에서 생략 ---- */
  #navSaveStatus { display: none; }

  /* ---- 글자 목록 / 속성 서랍(드로어) ---- */
  #sidebarLeft, #sidebarRight {
    position: fixed;
    top: 0;
    bottom: 0;
    width: min(320px, 85vw);
    z-index: 200;
    margin: 0;
    padding: 16px;
    overflow-y: auto;
    background: var(--cream);
    box-shadow: 0 0 24px rgba(0, 0, 0, 0.25);
    transition: transform 0.25s ease;
  }

  #sidebarLeft { left: 0; transform: translateX(-105%); }
  #sidebarRight { right: 0; transform: translateX(105%); }
  #sidebarLeft.drawer-open, #sidebarRight.drawer-open { transform: translateX(0); }

  /* ---- 캔버스 위: 글자목록-그리기도구(2줄)-속성 가로줄 / 캔버스 아래: 그리드·안내글자·줌 가로줄 ---- */
  /* 예전에는 canvasArea/canvasWrap이 flex:1로 "남는 세로 공간"을 차지해서
     페이지 스크롤을 완전히 없앴었다 - 하지만 실시간 미리보기가 이제 글자
     크기에 따라 여러 줄로 줄바꿈되며 세로로 늘어날 수 있게 되면서(아래
     #previewText), 캔버스가 그 늘어난 만큼 계속 작아지는 문제가 생긴다.
     그래서 캔버스는 화면 크기 기준의 고정 공식(vw/vh)으로 크기를 못박고,
     미리보기가 늘어나면 그만큼은 페이지 스크롤(body의 기본 overflow-y:auto)로
     받는다. */
  #canvasArea {
    flex-direction: column;
    gap: 10px;
  }

  /* 세로 폭이 좁은 화면(휴대폰)에서는 가로폭이, 태블릿 세로처럼 폭이 넉넉한
     화면에서는 420px 상한이 실제 기준이 된다 - 미리보기 섹션 높이와 무관하게
     항상 같은 크기로 고정된다. */
  #canvasWrap {
    width: min(70vw, 50vh, 420px);
    height: min(70vw, 50vh, 420px);
    aspect-ratio: 1 / 1;
    flex-shrink: 0;
  }

  /* 데스크톱에서는 display:contents(투명)였던 래퍼를 모바일에서는 진짜 가로줄로
     만들어서, 글자목록/속성 드로어 버튼이 그리기 도구 좌우에 오게 한다. */
  /* 글자목록/속성 버튼이 화면 가장자리 고정 탭으로 빠지면서 이 줄에는 이제
     현재글자·도구독·다음글자만 남는다 - 폭은 JS(syncMobileCanvasRowWidths)가
     캔버스(#canvasWrap)의 실제 렌더 폭을 실측해서 맞춰준다. */
  #canvasToolRow {
    display: flex;
    align-items: stretch;
    gap: 6px;
    width: 92vw;
    /* 캔버스가 아주 작게 계산되는 극단적인 경우에도 도구 아이콘이 겹치거나
       잘리지 않도록, 이 줄 전체의 최소 폭을 보장한다(캔버스보다 넓어지는
       건 감수한다 - 아이콘이 깨지는 것보다 낫다). */
    min-width: 304px;
  }

  #canvasToolRow #drawToolDock { flex: 1; width: auto; min-width: 180px; }

  /* 지금/다음 쓸 글자를 그리기 도구독 좌우에 고정폭으로 두고, 도구독은 남은
     공간을 전부 차지한다(flex:1) - 셋을 합친 폭이 항상 canvasToolRow의 폭
     (= 캔버스 폭)과 같아진다. align-items:stretch라 세로 크기도 도구독과
     자동으로 같아진다. */
  /* 기본값(display:none)이 ID 선택자라 우선순위가 더 높은 클래스 선택자로는
     못 덮어쓴다 - display만 ID로 다시 켜고, 나머지 레이아웃은 공용 클래스로. */
  #mobileCurrentCharGroup, #mobileNextCharGroup { display: flex; }
  .mobile-edge-char-group {
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    width: 56px;
    flex-shrink: 0;
    padding: 4px;
    border: 1px solid var(--rule);
    border-radius: 14px;
    background: var(--card);
  }

  #mobileCurrentCharLabel, #mobileNextCharLabel {
    font-family: "GuideFontBold", sans-serif;
    font-size: 23px;
    color: var(--ink);
  }

  .mobile-char-caption {
    font-size: 10px;
    color: var(--ink-soft);
  }

  #canvasRightDock {
    flex-direction: row;
    width: 92vw;
    /* 그리드/안내글자 버튼 + 구분선 + 확대/축소가 한 줄에 다 들어가는 실제
       최소 폭(약 210px) - 이보다 좁아지면 2줄로 접히면서 오히려 세로 공간을
       더 잡아먹어(캔버스가 더 줄어드는 악순환) 최소 폭으로 막아둔다. */
    min-width: 220px;
    justify-content: center;
    flex-wrap: wrap;
  }

  /* 도구 10개를 2줄(5칸x2행)로 고정 배치 - flex-wrap은 폭에 따라 줄 수가
     들쭉날쭉해질 수 있어서 grid로 정확히 2줄을 보장한다. 컬럼을 아이콘
     실제 크기(30px)로 고정하고 justify-content:center로 도구독 안에서
     그룹 전체를 가운데 정렬한다(전에는 1fr 컬럼이라 왼쪽으로 쏠려 보였다). */
  #drawToolDockTools {
    display: grid;
    grid-template-columns: repeat(5, 30px);
    justify-content: center;
    gap: 4px;
  }

  #canvasRightDockDivider { width: 1px; height: 24px; margin: 0 2px; }
  #zoomControls { flex-direction: row; }

  /* ---- 미리보기 / 폰트 만들기: 화면 하단 고정 ---- */
  #questHeaderSpacer {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 150;
    display: flex;
    gap: 10px;
    padding: 10px 14px;
    background: var(--card);
    border-top: 1px solid var(--rule);
  }

  #questHeaderSpacer #previewJumpBtn { flex: 1; justify-content: center; }
  #questHeaderSpacer #buildBtn { flex: 1; }

  /* ---- 캔버스 아래: 도구 모음 바(#mobileQuickToolsBar, 실행취소~정렬)는 이미
     오른쪽 속성 패널에 같은 기능이 있어 중복이라 계속 숨겨두고(기본값
     display:none, 위쪽 데스크톱 전용 규칙 그대로 적용됨), 그 자리에는
     실시간 미리보기를 토글 없이 항상 띄운다. 세로 여백/글자 크기를 조금
     압축해서 캔버스가 남는 공간을 더 확보하게 한다.
     캔버스/도구 영역과 이어진 하나의 덩어리로 안 보이도록, #favoritesBar와
     같은 방식(테두리+둥근 모서리+카드 배경)으로 독립된 박스처럼 분리한다 -
     그 사이의 얇은 구분선(#workCardDivider)은 이제 필요 없어 숨긴다. */
  #workCardDivider { display: none; }

  #previewSection {
    display: flex;
    gap: 4px;
    margin-top: 6px;
    padding: 10px 12px;
    border: 1px solid var(--rule);
    border-radius: 14px;
    background: var(--card);
  }
  #previewInputGroup { gap: 3px; }
  #previewToolbar { margin-top: 2px; }
  /* 모바일은 화면이 좁아 PC처럼 72pt를 한 줄에 다 담을 여유가 없다 - 가로
     스크롤/클리핑 대신 글자가 커지면 자연스럽게 아랫줄로 줄바꿈되게 한다
     (박스는 min-height만 바닥값으로 두고 줄 수만큼 자동으로 늘어난다 -
     캔버스는 더 이상 이 박스 높이에 영향받지 않는다, 위 #canvasWrap 참고). */
  #previewText {
    min-height: 44px;
    line-height: 1.35;
    padding: 10px 12px;
    font-size: 17px;
    white-space: normal;
    overflow: visible;
  }
  #previewInput { padding: 6px 12px; }
}

/* ---------- 태블릿 세로 전용: 캔버스 아래 즐겨찾기 도구창 ----------
   휴대폰은 화면이 좁아 이 칸까지 넣을 자리가 없어서 태블릿 세로에서만 켠다.
   속성 패널의 "도구 목록"과 같은 quick-tool-btn/data-quick 방식을 그대로 써서
   (편집 버튼을 눌러 고른 항목을 클릭하면 실제 버튼으로 클릭이 전달된다)
   실행취소~교차 12개 중 사용자가 원하는 것만 골라 담을 수 있게 한다. */
@media (min-width: 768px) and (max-width: 1100px) and (orientation: portrait) {
  #favoritesBar {
    display: flex;
    align-items: center;
    gap: 10px;
    width: min(560px, 40vh, 92vw);
    padding: 8px 12px;
    border: 1px solid var(--rule);
    border-radius: 14px;
    background: var(--card);
  }

  #favoritesBar .tool-group-label { flex-shrink: 0; }

  #favoritesGrid {
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: 28px;
  }

  #favoritesGrid:empty::before {
    content: "편집을 눌러 즐겨찾기를 추가해보세요";
    font-size: 12px;
    color: var(--ink-soft);
  }

  #favoritesGrid .quick-tool-btn {
    flex-direction: row;
    gap: 0;
    font-size: 0;
  }

  #favoritesGrid .quick-tool-btn .circle {
    width: 30px;
    height: 30px;
    border-radius: 9px;
  }

  #favoritesPickerWrap { flex-shrink: 0; }
  #favoritesPickerWrap .custom-select-menu { right: 0; left: auto; width: 220px; }

  .favorites-picker-option {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 7px 10px;
    border: none;
    background: none;
    border-radius: 7px;
    font-size: 12px;
    color: var(--ink);
    cursor: pointer;
    text-align: left;
  }

  .favorites-picker-option:hover { background: var(--cream); }

  .favorites-picker-option .circle {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    background: var(--cream);
    color: var(--ink-soft);
  }

  .favorites-picker-option .icon { width: 14px; height: 14px; }

  /* 이미 즐겨찾기에 담긴 항목은 눈에 띄게 표시한다 */
  .favorites-picker-option.selected { color: var(--accent); }
  .favorites-picker-option.selected .circle { background: var(--accent-tint); color: var(--accent); }
}

/* ==================================================================
   태블릿 공통(768px~1024px, 세로+가로 모두): 글자 목록/속성 패널만 서랍(드로어)
   으로 유지하고, 그 외 모든 배치·크기·동작은 PC 버전과 완전히 동일하게 맞춘다.
   태블릿 세로는 위쪽 블록들에서 모바일과 똑같은 레이아웃(상단 요약, 캔버스
   위/아래로 쌓기, 하단 고정 버튼, 실시간 미리보기 줄바꿈 등)을 썼었는데,
   이 블록이 파일 맨 뒤에 있어 그 규칙들을 여기서 전부 되돌리고 PC 값을
   다시 선언한다. 태블릿 가로는 지금까지 사이드바가 항상 보이는 좁은 고정
   패널이었는데, 여기서 서랍(오버레이)으로 바꾼다. 사이드바 서랍 자체의
   CSS(위치/슬라이드 애니메이션)는 모바일 것과 완전히 동일해서 그대로
   재사용한다. ================================================================== */
@media (min-width: 768px) and (max-width: 1100px) {
  /* ---- PC와 같은 무스크롤 구조: 캔버스가 남는 공간에 맞춰 커지고 줄어든다 ----
     (body.editor-page로 범위를 좁힌 이유는 위쪽 모바일 블록의 주석 참고) */
  body.editor-page {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }

  /* 사이드바 두 개가 서랍(고정 오버레이)이 되므로 그 자리를 위한 열이 더
     이상 필요 없다 - 가운데 캔버스 카드 하나가 전체 폭을 그대로 쓴다. */
  #appBody {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1fr);
    overflow: hidden;
    max-width: none;
    padding: 14px 24px;
  }

  #charGrid, #sidebarRight > .side-card { max-height: none; }

  /* ---- 상단 내비바: PC처럼 전체 메뉴를 그대로 보여준다(⋮ 축소 안 함) ---- */
  #navbarRight > *:not(#navMoreBtn):not(#navMoreMenu) { display: flex; }
  #navMoreBtn, #navMoreMenu { display: none; }
  #navSaveStatus { display: flex; }

  /* ---- 진행률 헤더: 상단 2단(진행률 왼쪽 | 미리보기·폰트만들기 버튼 오른쪽)과
     3단(마일스톤, 항상 펼쳐짐)을 분리된 두 줄로 나눈다. PC는 이 셋을 한 줄
     그리드로 욱여넣지만, 태블릿은 폭이 좁아 두 줄로 나누는 게 덜 빡빡하다. */
  #questHeaderRow {
    max-width: none;
    padding: 10px 24px 0;
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas: "left spacer" "milestone milestone";
    row-gap: 10px;
    column-gap: 24px;
  }
  #questHeaderLeft { display: flex; grid-area: left; min-width: 0; }
  /* 2단(진행률·버튼)과 3단(마일스톤) 사이를 가로선으로 구분한다 - 위쪽 여백은
     row-gap이 이미 주고 있으니, 마일스톤 줄 위에 테두리+자체 padding만 더한다. */
  #milestoneRow {
    display: flex;
    grid-area: milestone;
    justify-content: center;
    padding-top: 10px;
    border-top: 1px solid var(--rule);
  }
  #mobileProgressSummary, #mobileProgressDetail { display: none; }
  #questHeaderSpacer {
    grid-area: spacer;
    position: static;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 10px;
    padding: 0;
    background: none;
    border: none;
  }

  /* ---- 캔버스 상단바: PC처럼 이전-순번-다음만 가운데(현재/다음글자는 캔버스
     옆 절대위치 박스로 대신 보여준다, 아래 참고). canvasTopBarCenter를
     display:contents(모바일 방식)에서 실제 박스로 되돌리고, prevBtn/posInfo/
     nextBtn에 남아있던 grid-area 지정도 지워서(안 그러면 셋이 한 칸에
     겹친다) 그 안에서 flex row로 정상 배치되게 한다. */
  #canvasTopBar {
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: none;
    justify-items: stretch;
    padding: 0;
  }
  #canvasTopBarCenter { display: flex; justify-self: center; grid-column: 2; }
  #prevBtn, #posInfo, #nextBtn { grid-area: auto; }

  /* ---- 글자 목록/속성 패널: 서랍(드로어)으로 유지 - 모바일과 동일한 CSS ---- */
  .drawer-trigger-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 150;
    width: auto;
    padding: 14px 6px;
    border: 1.4px solid var(--rule);
    background: var(--card);
    color: var(--ink-soft);
    font-size: 12px;
    cursor: pointer;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  }

  .drawer-trigger-btn span {
    writing-mode: vertical-rl;
    text-orientation: upright;
    letter-spacing: 1px;
  }

  .drawer-trigger-btn .drawer-arrow-icon { width: 16px; height: 16px; flex-shrink: 0; }

  #charListDrawerBtn { left: 0; border-radius: 0 14px 14px 0; border-left: none; }
  #propsDrawerBtn { right: 0; border-radius: 14px 0 0 14px; border-right: none; }

  #sidebarLeft, #sidebarRight {
    position: fixed;
    top: 0;
    bottom: 0;
    width: min(320px, 85vw);
    z-index: 200;
    margin: 0;
    padding: 16px;
    overflow-y: auto;
    background: var(--cream);
    box-shadow: 0 0 24px rgba(0, 0, 0, 0.25);
    transition: transform 0.25s ease;
  }

  #sidebarLeft { left: 0; transform: translateX(-105%); }
  #sidebarRight { right: 0; transform: translateX(105%); }
  #sidebarLeft.drawer-open, #sidebarRight.drawer-open { transform: translateX(0); }

  /* ---- 캔버스: PC와 동일하게 도구독 | 캔버스 | 그리드독 한 줄 ---- */
  #canvasToolRow { display: contents; }
  #canvasCenterRow { display: contents; }
  #mobileCurrentCharGroup, #mobileNextCharGroup { display: none; }

  #workCard { position: relative; max-width: 1100px; }

  #currentCharGroup, #nextCharGroup {
    display: flex;
    position: absolute;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    width: 78px;
    padding: 6px 4px;
    border-radius: 14px;
    opacity: 0;
    transition: opacity 0.15s ease;
  }

  .pc-char-caption { margin-left: 0; }

  /* 캔버스-도구독 간격도 PC와 동일하게(22px). */
  #canvasArea { flex-direction: row; flex: 1; min-height: 0; gap: 22px; }

  #canvasWrap {
    width: auto;
    height: 100%;
    max-width: 100%;
    aspect-ratio: 1 / 1;
    flex-shrink: 0;
  }

  #drawToolDock, #canvasRightDock {
    flex-direction: column;
    width: auto;
    min-width: 0;
    justify-content: flex-start;
    flex-wrap: nowrap;
  }

  /* 모바일 전용 규칙(#canvasToolRow #drawToolDock { flex:1; ... })이 DOM상
     여전히 drawToolDock의 조상인 canvasToolRow를 거쳐 매칭되어(canvasToolRow
     자체가 display:contents로 화면에서 사라진 것과 무관하게 CSS 선택자는
     DOM 구조만 본다) 도구독이 flex:1로 남는 캔버스 옆 공간을 계속 차지해
     화면이 넓어질수록 도구독 가로 폭도 같이 늘어나 보였다 - 같은 특이도로
     다시 눌러서 아이콘 크기만큼의 고정 폭으로 되돌린다. */
  #canvasToolRow #drawToolDock { flex: none; width: auto; min-width: 0; }

  #drawToolDockTools {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 4px;
    justify-content: normal;
  }

  #canvasRightDockDivider { width: 24px; height: 1px; margin: 4px 0; }
  #zoomControls { flex-direction: column; }

  /* ---- 즐겨찾기 도구: 태블릿 세로 전용 기능이었다 - PC와 동일하게 맞추므로
     다시 숨긴다. ---- */
  #favoritesBar { display: none; }

  /* ---- 실시간 미리보기: PC와 동일(가로 스크롤, 캔버스와 구분선으로만 구분) ---- */
  #workCardDivider { display: block; }

  #previewSection {
    display: flex;
    gap: 6px;
    margin-top: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
  }

  #previewInputGroup { gap: 5px; }
  #previewToolbar { margin-top: 6px; }

  #previewText {
    min-height: 108px;
    line-height: 108px;
    padding: 0 18px;
    font-size: 20px;
    white-space: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
  }

  #previewInput { padding: 7px 14px; }
}

/* ---------- 모바일 전용: 실시간 미리보기를 다시 캔버스 카드 안으로 ----------
   태블릿/PC와 달리 모바일은 계속 독립된 카드(테두리+배경)로 분리해뒀었는데,
   이제 태블릿과 같은 방식 - 캔버스 영역과 같은 카드 안에 있되 가로선
   (#workCardDivider)으로만 구분하는 것으로 되돌린다. 위 공용 블록(max-width:767px,
   min-width:768px~1024px and orientation:portrait 공통)에서 준 테두리/배경/
   패딩만 지우고, 줄바꿈 등 나머지 모바일 전용 동작은 그대로 둔다. */
@media (max-width: 767px) {
  /* workCard는 appBody 그리드 행 높이에 stretch로 맞춰진 고정 높이인데,
     캔버스는 vw/vh 공식으로 크기가 고정돼 있어 줄어들지 않고, 실시간
     미리보기는 글자가 커지면 여러 줄로 늘어날 수 있다 - 내용 합이 workCard
     높이를 넘으면(overflow 기본값 visible이라) 넘친 부분이 카드 경계를 넘어
     화면 하단 고정바 밑으로 깔려버렸다(구분선도 flex-shrink로 찌그러져
     0px가 됨). workCard 자체를 세로로 스크롤 가능하게 만들어 넘친 내용은
     카드 안에서 스크롤해서 보게 하고, 구분선은 flex-shrink:0으로 못박아
     찌그러지지 않게 한다. */
  #workCard {
    overflow-y: auto;
  }

  #workCardDivider {
    display: block;
    flex-shrink: 0;
  }

  #previewSection {
    margin-top: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
  }
}
