/* Metalogy Spatial Editor — 공통 색상·글꼴·버튼·입력·대화상자 (metalogy.co.kr 디자인 기준) */

/* Noto Sans KR 가변 글꼴(원본 3.9MB)을 tools/build_fonts.py 로 둘로 나눴다.
   - ext: KS X 1001 밖의 한글 음절 · 옛 자모 (928KB) — 장면 제목 등에 드문 글자가 나올 때만 받는다
   - core: 라틴 · 문장부호 · 기호 · 호환 자모 · KS X 1001 한글 2,350자 (356KB, 페이지가 미리 불러옴)
   같은 글꼴 이름이 겹치면 브라우저는 뒤에 선언한 것부터 찾으므로 core 를 뒤에 둔다
   (core 에 있는 음절은 ext 를 받지 않는다). 한자는 시스템 글꼴로 보인다. */
@font-face {
  font-family: "Noto Sans KR";
  src: url("fonts/NotoSansKR-ext-1.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+1100-11FF, U+A960-A97F, U+AC00-D7A3, U+D7B0-D7FF;
}
@font-face {
  font-family: "Noto Sans KR";
  src: url("fonts/NotoSansKR-core-1.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0020-007E, U+00A0-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20A9-20AC, U+2100-214F,
    U+2190-21FF, U+2212, U+2460-24FF, U+25A0-27BF, U+3000-303F, U+3131-318E, U+AC00-D7A3, U+FF01-FF5E, U+FFE0-FFE6;
}
@font-face {
  font-family: "Jaapokkisubtract";
  src: url("fonts/Jaapokkisubtract-Regular.otf") format("opentype");
  /* 로고 글자(51KB)는 대체 글꼴로 먼저 그리지 않는다 — 메뉴 전환 때 로고가 바뀌어 보이는 깜빡임 방지 */
  font-display: block;
}

:root {
  color-scheme: dark;
  --brand-blue: #1b60e1;
  --brand-green: #00b050;
  --teal: #20c489;
  --accent: #2fd3a8;
  --accent-soft: #2fd3a826;
  --bg: #050607;
  --bg-2: #0a0e12;
  --panel: #0f1419;
  --panel-2: #141b22;
  --field: #071019;
  --line: #ffffff1a;
  --line-2: #ffffff2e;
  --text: #f2f6fb;
  --muted: #a1abb8;
  --dim: #6f7a88;
  --danger: #ff6b81;
  --gradient: linear-gradient(105deg, var(--brand-green), #07999e 48%, var(--brand-blue));
  --glow: 0 0 24px #00b88c55, 0 12px 40px #008fa666;
  --radius: 10px;
  --font: "Noto Sans KR", "Malgun Gothic", system-ui, sans-serif;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { margin: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  word-break: keep-all;
}
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
::selection { color: #fff; background: var(--brand-blue); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.brand-wordmark {
  font-family: "Jaapokkisubtract", var(--font);
  letter-spacing: .015em;
  background: var(--gradient);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  white-space: nowrap;
}
.gradient-text {
  background: linear-gradient(105deg, #00c574, #2782ed);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
.eyebrow { font: 600 12px/1.4 var(--font); letter-spacing: .12em; color: var(--teal); text-transform: uppercase; }
.muted { color: var(--muted); }
.dim { color: var(--dim); }

/* buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  height: 34px; padding: 0 14px;
  border: 1px solid var(--line-2); border-radius: 8px;
  background: #ffffff0a; color: var(--text);
  font-size: 13px; font-weight: 500; white-space: nowrap; cursor: pointer;
  transition: background-color .2s, border-color .2s, box-shadow .3s, color .2s, opacity .35s, filter .35s;
}
.btn:hover { background: #ffffff17; border-color: #ffffff45; }
/* v2.2.11 (사용자 요청) 비활성 단추는 금지 커서 — 예전엔 일부가 '기다림'(돌아가는) 커서라 처리 중인 것처럼 보였다. 켜고 꺼질 때는
   투명도 · 채도가 0.35초 동안 이어진다 (위 transition). 비활성 단추에 마우스를 올려도 밝아지지 않게 */
.btn:disabled { opacity: .45; cursor: not-allowed; filter: saturate(.4); }
.btn:disabled:hover { background: #ffffff0a; border-color: var(--line-2); box-shadow: none; }
.btn.primary:disabled:hover { background: var(--gradient); }
button:disabled, select:disabled, input:disabled, textarea:disabled, [aria-disabled="true"] { cursor: not-allowed; }
.btn svg { width: 16px; height: 16px; flex: none; }
.btn.primary { border: 0; background: var(--gradient); color: #fff; font-weight: 600; }
.btn.primary:hover { box-shadow: var(--glow); }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: #ffffff12; }
.btn.danger:hover { color: var(--danger); border-color: #ff6b8160; }
.btn.small { height: 28px; padding: 0 10px; font-size: 12px; }
.btn.icon { width: 32px; padding: 0; }
.btn.icon.small { width: 28px; }
.btn.is-active { background: var(--accent-soft); border-color: #2fd3a880; color: #bff5e6; }

/* fields */
.field {
  width: 100%; min-width: 0; height: 32px; padding: 0 10px;
  background: var(--field); border: 1px solid #2b3a48; border-radius: 7px;
  transition: border-color .3s, outline-color .3s;
  outline: 2px solid transparent; outline-offset: 1px;
}
textarea.field { height: auto; min-height: 64px; padding: 8px 10px; resize: vertical; line-height: 1.6; }
select.field { padding-right: 26px; }
.field:focus { border-color: var(--accent); outline-color: #2fd3a833; }
.field::placeholder { color: #5f6f80; }
.field[aria-invalid="true"] { border-color: var(--danger); }

/* toggle switch */
.switch { position: relative; display: inline-block; width: 32px; height: 18px; flex: none; }
.switch input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.switch span { position: absolute; inset: 0; border-radius: 99px; background: #2a333d; transition: background .25s; pointer-events: none; }
.switch span::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%; background: #c9d1da; transition: transform .25s, background .25s; }
.switch input:checked + span { background: var(--gradient); }
.switch input:checked + span::after { transform: translateX(14px); background: #fff; }
.switch input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.switch input:disabled + span { opacity: .4; }

/* range */
input[type=range] { width: 100%; accent-color: var(--accent); height: 18px; margin: 0; }

/* dialog */
dialog.modal {
  width: min(620px, calc(100vw - 32px)); max-height: calc(100vh - 48px);
  /* 게시 화면 '설정' 창과 같은 표면 (viewer index.scss mse-popup-surface) */
  padding: 0; border: 1px solid rgb(255 255 255 / 12%); border-radius: 16px;
  background: color-mix(in srgb, #0b1116 88%, transparent); color: var(--text);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  box-shadow: 0 24px 80px rgb(0 0 0 / 60%);
}
dialog.modal::backdrop { background: rgb(0 0 0 / 72%); backdrop-filter: blur(7px); }
/* 홈페이지(www.metalogy.co.kr css/dialog-motion.css)와 같은 팝업 움직임 — 닫기는 assets/motion.js 가 is-closing 을 붙인다 */
dialog.modal[open] { animation: mse-dialog-enter .35s ease both; }
dialog.modal[open]::backdrop { animation: mse-backdrop-enter .35s ease both; }
dialog.modal.is-closing { animation: mse-dialog-exit .35s ease both; }
dialog.modal.is-closing::backdrop { animation: mse-backdrop-exit .35s ease both; }
@keyframes mse-dialog-enter { from { opacity: 0; transform: translateY(18px) scale(.99); } to { opacity: 1; transform: none; } }
@keyframes mse-backdrop-enter { from { opacity: 0; } to { opacity: 1; } }
@keyframes mse-dialog-exit { from { opacity: var(--dialog-close-opacity, 1); transform: var(--dialog-close-transform, none); } to { opacity: 0; transform: translateY(18px) scale(.99); } }
@keyframes mse-backdrop-exit { from { opacity: var(--dialog-close-backdrop-opacity, 1); } to { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { dialog.modal[open], dialog.modal[open]::backdrop { animation: none; } }
.modal-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 22px 0; }
.modal-head h2 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.02em; }
.modal-head .btn.icon[data-close] { width: 32px; height: 32px; border: 0; border-radius: 8px; color: #aaa; background: transparent; transition: color .15s, background-color .15s; }
.modal-head .btn.icon[data-close]:hover { color: #fff; background: #ffffff1a; }
.modal-head .btn.icon[data-close] svg { width: 22px; height: 22px; stroke-width: 2; }
.modal-body { padding: 16px 22px 22px; overflow: auto; }
.modal-body h3 { margin: 18px 0 8px; font-size: 14px; }
.modal-body p { margin: 0 0 10px; color: var(--muted); font-size: 13px; }
.modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 0 22px 20px; }
.copy-row { display: flex; gap: 6px; }
.copy-row .field { font-family: ui-monospace, Consolas, monospace; font-size: 12px; }
.step { border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; margin-top: 12px; background: #ffffff05; }
.step-title { display: flex; align-items: center; gap: 8px; font-weight: 600; margin-bottom: 6px; }
.step-num { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--gradient); font-size: 12px; font-weight: 700; color: #fff; }
code, .mono { font-family: ui-monospace, Consolas, monospace; font-size: 12px; }
code { padding: 1px 6px; border-radius: 5px; background: #ffffff12; color: #cfe9ff; }

/* toast */
.toast-host { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); z-index: 1000; display: grid; gap: 8px; pointer-events: none; }
/* v2.3.39 알림 칸은 popover(맨 위 층 — 열린 창 위) — 브라우저 기본 popover 꾸밈(가운데 · 테두리 · 바탕)을 지우고 위 자리 그대로 */
.toast-host[popover] { inset: auto; left: 50%; bottom: 28px; margin: 0; padding: 0; border: 0; background: transparent; color: inherit; overflow: visible; width: max-content; max-width: calc(100vw - 32px); }
.toast-host[popover]:not(:popover-open) { display: none; }
.toast-host[popover]:popover-open { display: grid; }
.toast {
  padding: 10px 18px; border-radius: 9px; background: #121a21f2; border: 1px solid #2fd3a855;
  color: #dff9f1; font-size: 13px; box-shadow: 0 10px 40px #0009;
  animation: toast-in .25s ease-out;
}
.toast.error { border-color: #ff6b8188; color: #ffd5dc; }
/* 단추가 있는 알림(예: 초기화 → 되돌리기) — 알림 칸은 누르기를 통과시키므로 이 알림만 받는다 */
.toast.has-action { display: flex; align-items: center; gap: 14px; padding-right: 8px; pointer-events: auto; }
.toast-action {
  flex: none; padding: 5px 12px; border: 1px solid #2fd3a866; border-radius: 7px; background: #2fd3a81a;
  color: #bff5e6; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; transition: background-color .15s, color .15s;
}
.toast-action:hover { background: #2fd3a833; color: #fff; }
.toast-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* site header (list page) — www.metalogy.co.kr 헤더와 같은 크기 · 배치:
   높이 92px, 안쪽 폭 = 화면 폭 - 112px(최대 1248px, 900px 이하 - 40px), METALOGY 는 Jaapokkisubtract 30px 글자 로고 */
.site-head {
  position: sticky; top: 0; z-index: 10; height: 92px;
  background: rgb(0 0 0 / 64%); -webkit-backdrop-filter: blur(7px); backdrop-filter: blur(7px); border-bottom: 1px solid #ffffff12;
}
.site-head-inner {
  width: calc(100% - 112px); max-width: 1248px; height: 100%; margin-inline: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.logo-group { display: inline-flex; align-items: center; gap: 14px; min-width: 0; }
.logo-link { display: inline-block; flex-shrink: 0; }
.logo-link:hover { text-decoration: none; }
/* 홈페이지 css/brand.css .brand-wordmark 와 같은 값 */
.site-wordmark { display: inline-block; font-size: 30px; line-height: 1.15; background: linear-gradient(105deg, #00b050, #07999e 48%, #1b60e1); -webkit-background-clip: text; background-clip: text; }
.logo-group .product { white-space: nowrap; padding-left: 14px; border-left: 1px solid var(--line-2); color: var(--muted); font-size: 13px; font-weight: 500; letter-spacing: .02em; line-height: 22px; }
.logo-group .product:hover { color: var(--text); text-decoration: none; }
@media (forced-colors: active) { .site-wordmark { background: none; color: LinkText; } }
/* 상단 메뉴 — 홈페이지 css/site.css .main-nav 와 같은 값 (현재 메뉴는 #00c9ac) */
.main-nav { display: flex; align-items: center; gap: 42px; font: 500 14px/1.5 var(--font); letter-spacing: .035em; }
.main-nav a { padding-block: 10px; color: #bdc5d1; transition: color .5s ease; }
.main-nav a:hover { color: #fff; text-decoration: none; }
.main-nav a[aria-current] { color: #00c9ac; }
/* 메뉴 전환 (PROJECT · PLY TOOLS · SKP TOOLS) — 머리(로고 · 메뉴)는 모든 페이지가 같아 그대로 두고 본문 · 하단만 페이드.
   나타나기는 여기 CSS 가, 사라지기는 assets/motion.js 가 html.is-leaving 을 붙여서 한다. */
.site-head ~ main, .site-head ~ footer { animation: mse-page-in .4s ease both; }
html.is-leaving .site-head ~ main, html.is-leaving .site-head ~ footer { animation: mse-page-out .25s ease both; }
@keyframes mse-page-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes mse-page-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { .site-head ~ main, .site-head ~ footer, html.is-leaving .site-head ~ main, html.is-leaving .site-head ~ footer { animation: none; } }
/* v1.8.1 페이지 전환 효과(View Transition) — 아는 브라우저(Chrome · Edge 126+, Safari 18.2+)는 다음 페이지가 준비될 때까지 지금 화면을
   그대로 두었다가 바꾼다 (사이에 빈 화면이 끼지 않음): 앞 화면의 사진을 새 화면 위에 두고 0.2초에 걷어 내며, 새 화면은 그대로 —
   머리줄은 두 페이지가 같아 그대로 보이고 새 본문은 위 mse-page-in 으로 나타난다. 두 화면을 같이 흐리게 겹치면(기본) 글자가 겹쳐 보여서
   앞 화면만 사라지게 했다(섞기 normal). 모르는 브라우저는 motion.js 가 본문을 먼저 사라지게 한 뒤 옮긴다 (is-leaving). */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
}
::view-transition-old(root) { z-index: 1; mix-blend-mode: normal; animation: mse-vt-out .16s ease-in both; }
::view-transition-new(root) { mix-blend-mode: normal; animation: none; }
@keyframes mse-vt-out { from { opacity: 1; } to { opacity: 0; } }
/* 전환 효과로 열린 페이지(머리 스크립트의 pagereveal → mse-vt-in)는 앞 화면이 걷힌 뒤 새 본문이 나타난다 */
html.mse-vt-in .site-head ~ main, html.mse-vt-in .site-head ~ footer { animation-delay: .12s; }

@media (max-width: 900px) {
  .site-head-inner { width: calc(100% - 40px); }
  .main-nav { gap: 28px; }
}
/* v2.3.35 TOOLS 드롭 메뉴 (nav.html .nav-tools — PROJECT 옆 'TOOLS ▾' 하나, PC · 휴대폰 같게): 누르면(마우스는 올리기만 해도) 아래로 부드럽게
   펼침, 바깥 · Esc · 링크를 누르면 접힘 (assets/motion.js). 도구 화면이면 TOOLS 가 지금 메뉴 색. 관리자만 TOOLS 를 보임 (아래 :not(.mse-role-admin), v2.3.39 부터 손님도 숨김) */
.nav-tools { position: relative; display: inline-flex; align-items: center; }
.nav-tools-toggle {
  display: inline-flex; align-items: center; gap: 5px; margin: 0; padding: 10px 0; border: 0; background: none; color: #bdc5d1;
  font: inherit; letter-spacing: inherit; cursor: pointer; transition: color .5s ease;
}
.nav-tools-toggle:hover, .nav-tools.is-menu-open .nav-tools-toggle { color: #fff; }
.nav-tools:has(a[aria-current]) .nav-tools-toggle { color: #00c9ac; }
.nav-tools-toggle:focus-visible { outline: 2px solid #55e6c6; outline-offset: 3px; border-radius: 4px; }
.nav-menu-chev { width: 12px; height: 12px; transition: transform .25s ease; }
.nav-tools.is-menu-open .nav-menu-chev { transform: rotate(180deg); }
.nav-links {
  position: absolute; left: -14px; top: 100%; z-index: 30; display: grid; min-width: 180px; margin-top: 6px; padding: 6px; border: 1px solid #ffffff1f;
  border-radius: 10px; background: rgb(10 14 20); box-shadow: 0 14px 40px #0009; opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity .22s ease, transform .22s ease, visibility 0s linear .22s; /* v2.3.39 배경 불투명 — 96% 일 때 뒤 '계정 설정' 단추 글이 비쳤다 */
}
/* 단추와 펼친 칸 사이 6 px 를 지나는 동안에도 마우스 올림이 이어지게 */
.nav-links::before { content: ''; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }
.nav-tools.is-menu-open .nav-links { opacity: 1; visibility: visible; transform: none; transition: opacity .22s ease, transform .22s ease, visibility 0s; }
@media (hover: hover) and (pointer: fine) {
  .nav-tools:hover .nav-links { opacity: 1; visibility: visible; transform: none; transition: opacity .22s ease, transform .22s ease, visibility 0s; }
  .nav-tools:hover .nav-menu-chev { transform: rotate(180deg); }
}
.main-nav .nav-links a { padding: 10px 12px; border-radius: 7px; white-space: nowrap; }
.main-nav .nav-links a:hover { background: #ffffff0f; }
html:not(.mse-role-admin) .nav-tools { display: none; } /* v2.3.39 손님(로그인 전 mse-auth-pending)도 — 숨은 펼친 칸이 폭을 차지해 390 px 로그인 화면이 398 로 넘쳤다 (manual.css 와 같게) */
/* v2.3.38 'ADMIN ▾' (nav.html — TOOLS 옆): 관리자 계정이면 어디서나, 서버 컴퓨터 전용 항목은 주소가 localhost 일 때만 (nav.html 의 한 줄이 <html> 에 mse-local).
   펼친 칸에는 링크와 창 여는 단추(data-admin-open)가 섞여 같은 모양, 묶음 이름은 작게 */
.main-nav .nav-admin { display: none; }
html.mse-role-admin .main-nav .nav-admin { display: inline-flex; }
html:not(.mse-local) .main-nav .nav-admin-local { display: none; } /* 아래 단추 모양 규칙(.main-nav .nav-links button)보다 강하게 */
.main-nav .nav-links button {
  display: block; width: 100%; margin: 0; padding: 10px 12px; border: 0; border-radius: 7px; background: none; color: #bdc5d1;
  font: inherit; letter-spacing: inherit; text-align: left; white-space: nowrap; cursor: pointer; transition: color .5s ease;
}
.main-nav .nav-links button:hover { color: #fff; background: #ffffff0f; }
.main-nav .nav-links button:focus-visible { outline: 2px solid #55e6c6; outline-offset: -2px; }
.nav-links-label { padding: 8px 12px 4px; color: #7d92a6; font-size: 11px; font-weight: 600; letter-spacing: .06em; white-space: nowrap; }
.nav-links-label ~ .nav-links-label { margin-top: 4px; padding-top: 10px; border-top: 1px solid #ffffff14; }
.nav-admin-links { min-width: 200px; }
/* ADMIN 은 머리줄 오른쪽 가까이라 펼친 칸을 단추 오른쪽 끝에 맞춘다 (좁은 화면에서 칸이 화면 밖으로 나가지 않게 — 390 px 에서 33 px 나갔었음) */
.nav-tools.nav-admin .nav-links { left: auto; right: -14px; }
/* v2.4.0-beta14 머리줄 'AI Agent' (nav.html — PROJECT 오른쪽): 회원(사용자 계정)만 — 관리자는 ADMIN ▾ 'AI 에이전트 연결', 손님은 숨김.
   메뉴 글자와 같은 모양에 제미나이식 그라데이션 별 (편집기 AI 단추 효과와 같은 색 — assets/ai/ai.css). 누르면 AI 에이전트 연결 창 (auth.js) */
.main-nav .nav-ai {
  display: none; align-items: center; gap: 6px; margin: 0; padding: 10px 0; border: 0; background: none; color: #bdc5d1;
  font: inherit; letter-spacing: inherit; white-space: nowrap; cursor: pointer; transition: color .5s ease;
}
html.mse-role-user .main-nav .nav-ai { display: inline-flex; }
.main-nav .nav-ai:hover { color: #fff; }
.main-nav .nav-ai:focus-visible { outline: 2px solid #55e6c6; outline-offset: 3px; border-radius: 4px; }
.main-nav .nav-ai svg { flex: none; width: 15px; height: 15px; fill: url(#mse-nav-ai-grad); }
.main-nav .nav-ai svg path:first-child { transform-box: fill-box; transform-origin: center; transition: transform .6s cubic-bezier(.34, 1.56, .64, 1); }
.main-nav .nav-ai:hover svg path:first-child { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .main-nav .nav-ai svg path:first-child { transition: none; } .main-nav .nav-ai:hover svg path:first-child { transform: none; } }
@media (forced-colors: active) { .main-nav .nav-ai svg { fill: currentColor; } }
/* 좁은 화면의 회원 머리줄 — 'AI Agent' 가 더해져 390 px 에서 로그아웃이 둘째 줄로 내려갔다 (재어 고침, 관리자 v2.3.37 과 같은 방법):
   480 px 아래는 사이를 줄이고 메뉴얼은 책 아이콘만 (이름은 읽기 도구에 그대로 — 430 px 큰 휴대폰은 '사용자 메뉴얼' 이 길어 넘쳤다) */
@media (max-width: 480px) {
  html.mse-role-user .main-nav { gap: 12px; }
  html.mse-role-user .nav-manual span { font-size: 0; }
  html.mse-role-user .avatar-action { margin-right: -4px; }
  html.mse-role-user .nav-manual span::after { content: none; }
}
/* 360 px 휴대폰(데스크톱 좁은 창은 스크롤 막대 15 px 까지 — 칸 305 px)에서 5 px 모자라 로그아웃이 내려갔다 → 380 px 아래는 사이 10 px */
@media (max-width: 380px) { html.mse-role-user .main-nav { gap: 10px; } }
@media (prefers-reduced-motion: reduce) { .nav-links, .nav-menu-chev { transition: none !important; } }
/* 휴대폰: 홈페이지처럼 두 줄 — 로고(30px 그대로) 한 줄, 버튼 한 줄 */
@media (max-width: 640px) {
  .site-head { height: auto; }
  .site-head-inner { flex-wrap: wrap; gap: 10px; padding-block: 14px 12px; }
  .site-head-inner > :last-child { width: 100%; justify-content: flex-end; }
  .main-nav { gap: 22px; font-size: 12px; }
  .logo-group .product { font-size: 12px; }
}

/* drop zone (열기·업로드 공용) */
.drop-zone { position: relative; display: grid; place-items: center; gap: 6px; padding: 22px; border: 1px dashed #ffffff40; border-radius: 10px; text-align: center; color: var(--muted); cursor: pointer; transition: border-color .3s, background .3s; }
.drop-zone svg { width: 28px; height: 28px; }
.drop-zone.is-over, .drop-zone:hover { border-color: var(--accent); background: #2fd3a80d; }

/* 장면 업로드 */
dialog.upload-modal { width: min(680px, calc(100vw - 32px)); }
.up-guide { display: grid; gap: 4px; margin-bottom: 12px; padding: 12px 14px; border-radius: 10px; background: #1b60e114; border: 1px solid #1b60e144; font-size: 12.5px; color: #c8d6ee; }
.up-guide strong { color: #e6eefc; font-size: 13px; }
.up-summary { display: grid; gap: 3px; margin-top: 10px; padding: 10px 14px; border-radius: 9px; border: 1px solid var(--line); background: #ffffff06; font-size: 12.5px; color: var(--muted); }
.up-summary strong { color: var(--text); font-size: 13px; }
.up-summary.ok { border-color: #2fd3a855; background: #2fd3a80d; }
.up-summary.ok strong { color: #9ff0d8; }
.up-summary.bad { border-color: #ff6b8166; background: #ff6b810d; }
.up-summary.bad strong { color: #ffc2cd; }
.up-grid { display: grid; grid-template-columns: 120px 1fr; gap: 8px 12px; align-items: center; margin-top: 14px; }
.up-grid .sub { margin: 0; }
.up-check { display: flex; gap: 8px; align-items: flex-start; font-size: 12.5px; color: #ffd479; margin-top: 6px; cursor: pointer; }
.up-check input { margin-top: 3px; accent-color: var(--accent); }
.up-server { margin: 12px 0 0 !important; font-size: 12.5px !important; }
.up-server.ok { color: #7fe3c2 !important; }
.up-server.bad { color: #ffb4c1 !important; }
.bar { height: 3px; border-radius: 3px; background: #ffffff18; overflow: hidden; }
.bar span { display: block; height: 100%; width: 0; background: var(--gradient); transition: width .3s; }
.bar.big { height: 8px; border-radius: 6px; }
.up-total { display: grid; gap: 8px; margin-bottom: 14px; }
.up-total-line { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.up-total-line strong { font-size: 18px; letter-spacing: -.02em; }
.up-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.up-step { display: grid; grid-template-columns: 26px 1fr; gap: 10px; align-items: start; padding: 8px 10px; border-radius: 9px; transition: background .3s; }
.up-step strong { display: block; font-size: 13.5px; }
.up-detail { display: block; font-size: 12px; color: var(--dim); word-break: break-all; }
.up-dot { position: relative; width: 20px; height: 20px; margin-top: 1px; border-radius: 50%; border: 2px solid #ffffff30; }
.up-step[data-state="run"] { background: #ffffff08; }
.up-step[data-state="run"] .up-dot { border-color: #ffffff20; border-top-color: var(--accent); animation: up-spin .8s linear infinite; }
.up-step[data-state="run"] .up-detail { color: #cfe9ff; }
.up-step[data-state="done"] .up-dot, .up-step[data-state="skip"] .up-dot { border: 0; background: var(--gradient); }
.up-step[data-state="done"] .up-dot::after, .up-step[data-state="skip"] .up-dot::after { content: ""; position: absolute; left: 7px; top: 3px; width: 5px; height: 10px; border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg); }
.up-step[data-state="skip"] .up-dot { opacity: .45; }
.up-step[data-state="error"] .up-dot { border-color: var(--danger); background: #ff6b8133; }
.up-step[data-state="error"] .up-detail { color: #ffb4c1; }
.up-message { margin-top: 12px !important; padding: 10px 14px; border-radius: 9px; font-size: 13px !important; }
.up-message.ok { background: #2fd3a814; color: #9ff0d8 !important; border: 1px solid #2fd3a844; }
.up-message.bad { background: #ff6b8114; color: #ffc2cd !important; border: 1px solid #ff6b8144; }
@keyframes up-spin { to { transform: rotate(360deg); } }
@media (max-width: 560px) { .up-grid { grid-template-columns: 1fr; } }
.up-password h3 { margin-top: 0; }
.up-cmd { display: grid; gap: 8px; }
.up-cmd pre { margin: 0; padding: 10px 12px; border-radius: 8px; background: #000a; border: 1px solid var(--line); color: #d7e6f5; white-space: pre-wrap; word-break: break-all; font-size: 11.5px; }
.up-cmd .btn { justify-self: start; }
.up-server .btn { margin-left: 6px; vertical-align: middle; }
/* v1.17.1 맵 올리기: 이 프로젝트에 있는 맵 이름이면 덮어쓰지 않고 '파일 교체로 열기' */
.up-exists { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; margin-top: 8px; padding: 10px 14px; border-radius: 9px; border: 1px solid #ffc85a55; background: #ffc85a10; color: #ffe2a8; font-size: 12.5px; line-height: 1.6; }
.up-exists span { flex: 1 1 260px; }
.up-message-main, .up-message-sub { display: block; }
.up-message-sub { margin-top: 4px; font-size: 12px; opacity: .85; }
/* v1.17.1 맵 파일 교체 창 (assets/upload.js openReplaceDialog) — 맵 올리기 창과 같은 틀 + 바꿀 맵 · 분석(진행 줄 → 평면도 · 표 · 판정) */
dialog.upload-modal.replace-modal { width: min(720px, calc(100vw - 32px)); }
.rp-map { display: grid; gap: 4px; margin-bottom: 12px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; }
.rp-map-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; min-width: 0; }
.rp-map-name strong { font-size: 15px; color: var(--text); overflow-wrap: anywhere; }
.rp-map-name .mono { color: var(--muted); }
.rp-map-file { font-size: 12.5px; color: var(--dim); overflow-wrap: anywhere; }
.rp-map-file .mono { color: var(--muted); }
.rp-notes { display: grid; gap: 4px; margin: 0 0 12px; padding: 10px 14px 10px 30px; border-radius: 10px; border: 1px solid #ffc85a55; background: #ffc85a12; color: #ffe9bf; font-size: 12.5px; line-height: 1.6; }
.rp-check { margin-top: 12px; }
.rp-busy { display: grid; gap: 10px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; }
.rp-row { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 4px 12px; align-items: center; font-size: 12.5px; }
.rp-row strong { font-size: 13px; }
.rp-row .bar { height: 6px; }
.rp-row-text { grid-column: 2; color: var(--muted); overflow-wrap: anywhere; }
.rp-row[data-state="done"] .rp-row-text { color: #9ff0d8; }
.rp-row[data-state="error"] .rp-row-text { color: #ffc2cd; }
.rp-row[data-state="error"] .bar span { background: #ff6b8166; }
.rp-busy-foot { display: flex; justify-content: flex-end; }
.rp-result { display: grid; gap: 10px; }
.rp-figure { display: grid; gap: 10px; min-width: 0; }
.rp-plan { display: block; width: 100%; aspect-ratio: 2 / 1; border-radius: 10px; border: 1px solid var(--line); background: #071019; }
.rp-table { width: 100%; border-collapse: collapse; font-size: 12.5px; font-variant-numeric: tabular-nums; }
.rp-table caption { caption-side: top; padding: 0 0 6px; text-align: left; font-size: 12px; color: var(--dim); }
.rp-table th, .rp-table td { padding: 6px 10px; border-bottom: 1px solid #ffffff0d; text-align: right; white-space: nowrap; }
.rp-table thead th { font-weight: 600; color: var(--muted); background: #121a21; }
.rp-table th[scope="row"], .rp-table thead th:first-child { text-align: left; }
.rp-table td { font-family: ui-monospace, Consolas, monospace; color: var(--text); }
.rp-table td.is-over { color: #ffd479; font-weight: 600; }
.rp-info { margin: 0 !important; font-size: 12px !important; color: var(--dim) !important; overflow-wrap: anywhere; }
.rp-verdict span { display: block; }
.rp-verdict ul { margin: 4px 0 0; }
.rp-verdict .rp-ask { margin: 8px 0 0 !important; font-size: 13px !important; color: #fff !important; }
.rp-verdict .btn { margin-top: 8px; }
/* 범위 · 분포만 다를 때(한쪽을 잘라 내거나 덧붙임) — 막지 않는 노란 안내, 초록 판정 칸 안에도 (upload.js showVerdict) */
.rp-verdict .rp-range { margin-top: 10px; padding: 8px 12px; border-radius: 8px; border: 1px solid #ffc85a55; background: #ffc85a12; color: #ffe9bf; font-size: 12.5px; }
.rp-verdict .rp-range strong { font-size: 13px; color: #ffe2a8; }
@media (max-width: 560px) {
  .rp-plan { aspect-ratio: 4 / 3; }
  .rp-table th, .rp-table td { padding: 6px; }
  .rp-row { grid-template-columns: 1fr; }
  .rp-row-text { grid-column: auto; }
}

/* 장면 삭제 · 휴지통 (assets/trash.js) */
.btn.danger-solid { border: 0; background: #d8445c; color: #fff; font-weight: 600; }
.btn.danger-solid:hover { background: #e85a71; box-shadow: 0 0 0 3px #ff6b8133; }
.btn.danger-solid:disabled { opacity: .55; }
.btn.warn-solid { border: 0; background: #d99a22; color: #1a1205; font-weight: 700; }
.btn.warn-solid:hover { background: #e8ad3a; box-shadow: 0 0 0 3px #ffc85a33; }
.btn.warn-solid:disabled { opacity: .55; }
.trash-modal { width: min(560px, calc(100vw - 32px)); }
.trash-modal.trash-wide { width: min(820px, calc(100vw - 32px)); }
.trash-warning { padding: 12px 14px; border-radius: 10px; border: 1px solid #ff6b8155; background: #ff6b8112; color: #ffd3da; font-size: 13px; line-height: 1.6; }
.trash-warning strong { display: block; color: #fff; font-size: 14px; margin-bottom: 4px; }
.trash-warning ul { margin: 0; padding-left: 18px; }
.trash-warning.warn { border-color: #ffc85a55; background: #ffc85a12; color: #ffe9bf; }
.trash-warning.ok { border-color: #2fd3a855; background: #2fd3a810; color: #c8f5e8; }
.trash-pass { display: grid; gap: 6px; margin-top: 16px; font-size: 13px; color: var(--muted); }
/* v1.10.2: 삭제 창의 '장면 이름을 똑같이 입력' — 입력할 이름 */
.trash-pass code { font-family: ui-monospace, Consolas, monospace; font-size: 12.5px; color: #fff; background: #ffffff14; border: 1px solid #ffffff26; border-radius: 5px; padding: 1px 6px; }
.trash-open .trash-open-row { display: flex; gap: 8px; }
.trash-open .trash-open-row .field { flex: 1; }
.trash-list { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 8px; }
.trash-item { display: flex; align-items: center; gap: 14px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; }
/* 썸네일 (16:9) — 대표 이미지가 없으면 METALOGY 글자 */
.trash-thumb { flex: none; width: 128px; aspect-ratio: 16 / 9; border-radius: 8px; overflow: hidden; display: grid; place-items: center; background: linear-gradient(135deg, #0f1a24, #0a1f2e); border: 1px solid var(--line); }
.trash-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.trash-thumb span { font-size: 11px; font-weight: 700; letter-spacing: .12em; color: #ffffff40; }
.trash-info { flex: 1; display: grid; gap: 2px; min-width: 0; font-size: 12px; color: var(--muted); }
.trash-info strong { color: var(--text); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* v1.16.0 프로젝트째 지운 항목 표시 */
.trash-kind { display: inline-block; margin-right: 8px; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; vertical-align: 2px; color: #c6fbe9; background: #0c2a24; border: 1px solid #2fd3a866; }
.trash-conflict { color: #ffd479; }
.trash-actions { display: flex; gap: 6px; flex: none; }
.trash-empty, .trash-note { color: var(--muted); font-size: 13px; }
/* 보안 설정 창 (v1.12.0, assets/security.js) — 홈페이지 관리자 보안 설정과 같은 짜임: 설정 · 차단 IP · 로그인 기록 */
.trash-modal.sec-modal { width: min(980px, calc(100vw - 32px)); }
.sec-section { padding: 16px 0 18px; border-top: 1px solid var(--line); }
.sec-section:first-child { border-top: 0; padding-top: 4px; }
.sec-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.sec-head h3 { margin: 0; font-size: 15px; }
.sec-head-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.sec-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px 16px; margin-top: 12px; }
/* v2.2.8 보안 설정 — 콘텐츠 보호 스위치 */
.sec-protect { display: grid; gap: 12px; margin: 12px 0 4px; }
.sec-switch-row { display: flex; align-items: center; gap: 10px; font-weight: 600; cursor: pointer; }
.sec-switch .sec-help { margin: 4px 0 0 42px; }
@media (max-width: 760px) { .sec-grid { grid-template-columns: 1fr; } }
.sec-field { display: grid; gap: 6px; align-content: start; font-size: 13px; color: var(--muted); }
.sec-field .field { width: 100%; }
.sec-help { margin: 6px 0 0; font-size: 12px; line-height: 1.6; color: var(--dim); }
.sec-actions { display: flex; justify-content: flex-end; margin-top: 12px; }
.sec-block-form { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto; gap: 10px; align-items: end; margin-top: 12px; padding: 12px; border: 1px solid #ff6b8155; border-radius: 10px; background: #ff6b810a; }
.sec-block-form[hidden] { display: none; }
@media (max-width: 760px) { .sec-block-form { grid-template-columns: 1fr; } }
.sec-filter { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 110px auto; gap: 10px; align-items: end; margin-top: 12px; }
@media (max-width: 760px) { .sec-filter { grid-template-columns: 1fr 1fr; } }
.sec-table-wrap { margin-top: 12px; overflow-x: auto; border: 1px solid var(--line); border-radius: 10px; }
.sec-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.sec-table th { position: sticky; top: 0; padding: 9px 10px; text-align: left; font-weight: 600; color: var(--muted); background: #121a21; border-bottom: 1px solid var(--line); white-space: nowrap; }
.sec-table td { padding: 8px 10px; border-bottom: 1px solid #ffffff0d; color: var(--text); vertical-align: middle; }
.sec-table tr:last-child td { border-bottom: 0; }
.sec-table td.mono { font-family: ui-monospace, Consolas, monospace; white-space: nowrap; }
.sec-empty { text-align: center; color: var(--dim) !important; padding: 18px 10px !important; }
.sec-badge { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; white-space: nowrap; background: #ffffff10; border: 1px solid #ffffff1f; color: #dfe6ee; }
.sec-badge.is-manual, .sec-ev-manual_block { background: #ff6b8114; border-color: #ff6b8155; color: #ffc2cd; }
.sec-ev-login_success, .sec-ev-unblock, .sec-ev-block_expired { background: #2fd3a814; border-color: #2fd3a855; color: #9ff0d8; }
.sec-ev-login_failed, .sec-ev-blocked { background: #ffc85a12; border-color: #ffc85a55; color: #ffe2a8; }
.sec-ev-auto_block { background: #ff6b8114; border-color: #ff6b8155; color: #ffc2cd; }
.sec-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.sec-count { margin: 0; font-size: 12px; color: var(--muted); }
.sec-pager { display: flex; gap: 6px; }
.sec-limit-label { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); }
.sec-limit { width: auto; min-width: 84px; }
.sec-failures { color: #ffd479; }
/* 장면 패키징 창 (v1.11.0, assets/scenepack.js) — 범위 고르기 · 진행은 복제 창(.dup-*)과 같은 모양 */
.pack-checks { display: grid; gap: 8px; margin-top: 14px; }
.pack-checks label { display: flex; gap: 10px; align-items: flex-start; font-size: 13px; color: var(--text); cursor: pointer; }
.pack-checks input { margin: 3px 0 0; accent-color: var(--accent); }
/* v1.13.0: 1인칭만 — 충돌 상자가 없으면 흐리게 (고를 수 없음) */
.pack-checks label.is-off { opacity: .55; cursor: not-allowed; }
/* 장면 복제 창 (v1.10.0, assets/trash.js openDuplicateDialog) */
.dup-title { display: grid; gap: 6px; margin-top: 14px; font-size: 13px; color: var(--muted); }
.dup-modes { display: grid; gap: 8px; min-width: 0; margin: 14px 0 0; padding: 0; border: 0; }
.dup-modes legend { padding: 0; margin-bottom: 6px; font-size: 13px; color: var(--muted); }
.dup-mode { display: grid; grid-template-columns: 18px 1fr; gap: 3px 10px; padding: 11px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; cursor: pointer; transition: border-color .3s, background .3s; }
.dup-mode input { grid-row: span 2; margin: 3px 0 0; accent-color: var(--accent); }
.dup-mode strong { font-size: 14px; color: var(--text); }
.dup-mode span { font-size: 12.5px; line-height: 1.6; color: var(--muted); }
.dup-mode:has(input:checked) { border-color: #2fd3a877; background: #2fd3a80d; }
.dup-mode:has(input:disabled) { cursor: not-allowed; opacity: .7; }
.dup-progress { display: grid; gap: 8px; margin-top: 16px; }
.dup-progress-line { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; color: var(--muted); }
.dup-progress-line strong { flex: none; color: var(--text); }
.trash-note { margin-top: 12px !important; }
@media (max-width: 560px) { .trash-item { flex-wrap: wrap; } .trash-thumb { width: 96px; } .trash-actions { width: 100%; justify-content: flex-end; } }

/* v1.19.0 맵 'LOD 설정' 창 (lodsettings.js — 프로젝트 화면 맵 카드): PLY Tools 의 단계 체크처럼, 단계마다 개수 · 막대 · 뷰어에서 쓰일 번호 */
.lod-modal { width: min(640px, calc(100vw - 32px)); }
.lod-modal .modal-head h2 { display: inline-flex; align-items: center; gap: 8px; }
.lod-title-icon svg { width: 20px; height: 20px; color: var(--accent); }
.lod-modal .list-spin { width: 16px; height: 16px; box-sizing: border-box; border-radius: 50%; border: 2px solid #ffffff25; border-top-color: var(--accent); animation: up-spin .8s linear infinite; flex: none; }
.lod-sub { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0 0 10px !important; }
.lod-sub strong { color: var(--text); font-size: 14px; }
.lod-sub .mono { color: var(--dim); font-size: 12px; }
.lod-summary { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; padding: 10px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; color: var(--muted); font-size: 13px; }
.lod-summary.is-error { color: #ffc9c9; background: #3a1a1a; border-color: #7a3434; }
.lod-source { padding: 1px 8px; border-radius: 999px; color: #ffe2a8; background: #3a2c0f; border: 1px solid #ffc85a55; font-size: 12px; }
.fmt-badge { display: inline-flex; align-items: center; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; color: #cfe4ff; background: #0f223a; border: 1px solid #5b8cff55; white-space: nowrap; }
.fmt-badge.is-lod { color: #9ff0d8; background: #0c2a24; border-color: #2fd3a855; }
.lod-levels { display: grid; gap: 6px; min-width: 0; margin: 14px 0 0; padding: 0; border: 0; }
.lod-levels[hidden] { display: none; }
.lod-levels legend { padding: 0; margin-bottom: 8px; font-size: 13px; color: var(--muted); }
.lod-level { display: grid; grid-template-columns: 18px 52px minmax(60px, 1fr) auto; grid-template-areas: "box name bar count" ". hint hint to"; align-items: center; gap: 2px 10px; padding: 9px 12px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; cursor: pointer; transition: border-color .3s, background .3s, opacity .3s; }
.lod-level input { grid-area: box; margin: 0; accent-color: var(--accent); }
.lod-level-name { grid-area: name; font-weight: 600; color: var(--text); font-size: 13.5px; }
.lod-level-bar { grid-area: bar; height: 6px; border-radius: 999px; background: #ffffff10; overflow: hidden; }
.lod-level-bar i { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #2fd3a8, #5b8cff); transition: opacity .3s; }
.lod-level-count { grid-area: count; color: var(--muted); font-size: 12.5px; font-variant-numeric: tabular-nums; text-align: right; }
.lod-level-hint { grid-area: hint; color: var(--dim); font-size: 12px; }
.lod-level-to { grid-area: to; color: #9ff0d8; font-size: 12px; text-align: right; white-space: nowrap; }
.lod-level:has(input:checked) { border-color: #2fd3a855; background: #2fd3a80b; }
.lod-level.is-off { opacity: .62; }
.lod-level.is-off .lod-level-bar i { opacity: .35; }
.lod-level.is-off .lod-level-to { color: #ffb4c0; }
.lod-level:has(input:disabled) { cursor: not-allowed; }
.lod-result { margin: 12px 0 0 !important; color: var(--muted) !important; font-size: 13px; line-height: 1.6; }
.lod-result strong { color: var(--text); }
.lod-warn { margin-top: 10px; }
.lod-env { display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap; margin-top: 12px; padding: 10px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff04; color: var(--muted); font-size: 12.5px; line-height: 1.6; }
.lod-env[hidden] { display: none; }
.lod-env > span:nth-child(2) { flex: 1 1 260px; }
.lod-env-state { padding: 1px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; color: #9ff0d8; background: #0c2a24; border: 1px solid #2fd3a855; white-space: nowrap; }
.lod-env-state.is-off { color: #ffd0d8; background: #3a1a22; border-color: #ff6b8155; }
.lod-notes { margin: 12px 0 0; padding-left: 18px; color: var(--dim); font-size: 12px; line-height: 1.7; }
.lod-foot { padding: 16px 0 0; align-items: center; }
/* v2.0.19 맵 '영문 이름(링크)' 창 (maplink.js — 프로젝트 화면 맵 목록) */
.maplink-field { display: flex; align-items: center; gap: 8px; }
.maplink-field > span { flex: none; color: var(--muted); font-size: 12.5px; }
.maplink-field .maplink-input { flex: 1; min-width: 0; }
.maplink-input[aria-invalid="true"] { border-color: #ff7a93aa; }
.maplink-state { margin: 6px 0 0 !important; color: var(--dim); font-size: 12px; }
.maplink-state.is-bad { color: #ffb4c0; }
.maplink-preview { display: grid; gap: 4px; margin-top: 10px; padding: 9px 11px; border: 1px solid #ffffff14; border-radius: 9px; background: #ffffff06; font-size: 12px; }
.maplink-preview code { color: #9ff0d3; word-break: break-all; }
/* 맵 카드의 영문 이름 줄 (project.js) */
.meta .map-link-row { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; min-width: 0; margin-top: 6px; color: var(--muted); font-size: 12px; }
.meta .map-link-label { display: inline-flex; flex: none; align-items: center; gap: 4px; }
.meta .map-link-label svg { width: 13px; height: 13px; }
.meta .map-link-value { min-width: 0; max-width: 100%; overflow: hidden; padding: 1px 6px; border-radius: 6px; background: #ffffff0d; color: #dfe6ee; text-overflow: ellipsis; white-space: nowrap; }
.meta .map-link-row.is-set .map-link-value { background: #2fd3a81a; color: #9ff0d3; }
.meta .map-link-edit { flex: none; height: 24px; padding: 0 8px; font-size: 11.5px; }
/* v2.0.20 프로젝트 영문 이름 창 (projectlink.js — 목록 화면) · 목록 카드 줄의 표시 */
.plink-legacy { display: block; margin-bottom: 10px; font-size: 12.5px; line-height: 1.6; }
.plink-map { display: flex; align-items: flex-start; gap: 8px; margin-top: 10px; font-size: 12.5px; cursor: pointer; }
.plink-map input { flex: none; margin: 3px 0 0; accent-color: var(--accent); }
.plink-map small { display: block; margin-top: 2px; }
.meta .plink-tag { flex: none; padding: 0 6px; border: 1px solid #ffffff22; border-radius: 8px; color: var(--muted); font-size: 10.5px; line-height: 17px; white-space: nowrap; }
.meta .plink-tag.is-map { border-color: #2fd3a866; color: #9ff0d3; }
.meta .plink-tag.is-legacy { border-color: #ffd47966; color: #ffd479; }
.lod-foot-gap { flex: 1; }
@media (max-width: 560px) { .lod-level { grid-template-columns: 18px 48px minmax(40px, 1fr) auto; } }
@media (prefers-reduced-motion: reduce) { .lod-modal .list-spin { animation: none; } }


/* 확인 창 · 업로드 암호 창 (장면 목록 · 편집기 공통, v1.5.0-alpha4) */
dialog.modal.confirm-modal { width: min(440px, calc(100vw - 32px)); }
.confirm-message { color: var(--text) !important; font-size: 14.5px !important; }
.confirm-detail { font-size: 12.5px !important; }
/* v2.1.17 편집본 버리기 경고 창 (common.js confirmDraftDiscard — 편집기 띠 · 프로젝트 화면 맵 카드) */
.draft-discard { display: grid; gap: 10px; margin-bottom: 12px; }
.draft-discard-warn { display: flex; align-items: center; gap: 8px; margin: 0 !important; padding: 9px 11px; border: 1px solid #ff6b8155; border-radius: 9px; background: #ff6b8114; color: #ffc9d1 !important; font-size: 13px !important; font-weight: 600; line-height: 1.45; }
.draft-discard-warn svg { flex: none; width: 18px; height: 18px; color: #ff8a9a; }
.draft-discard-info { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 5px 12px; margin: 0; padding: 10px 12px; border: 1px solid #ffffff14; border-radius: 9px; background: #ffffff06; font-size: 12.5px; line-height: 1.45; }
.draft-discard-info dt { color: var(--muted); white-space: nowrap; }
.draft-discard-info dd { margin: 0; min-width: 0; color: var(--text); overflow-wrap: anywhere; }
.pass-modal .trash-pass { margin-top: 12px; }
.pass-modal .pass-keep { margin: 10px 0 0; }

/* ---- v1.8.0 관리자 로그인 (assets/auth.js) — 메타로지 홈페이지 관리자(/edit/) 로그인과 같은 모양 · 값 (cafe24 css/editor.css
   .editor-header · .access-panel · .eyebrow · .primary · .site-view · .message.error). 로그인 전에는 관리 화면 내용을 숨긴다 */
/* v2.3.27 로그인 화면 위에 띄우는 창(자동 로그인 경고 · confirmBox)은 가리지 않는다 — 가리면 보이지 않는 창이 화면을 막았다 */
html.mse-auth-pending body > :not(.mse-login):not(dialog) { visibility: hidden; }
/* v2.0.21 로그인 전에는 숨긴 관리 화면이 스크롤되지 않게 — 오른쪽 세로 스크롤바를 감추고 휠로 내려가지 않는다 (로그인하면 다시, auth.js 가 맨 위로) */
html.mse-auth-pending { overflow: hidden; }
.mse-login {
  position: fixed; inset: 0; z-index: 10000; overflow: auto; display: flex; flex-direction: column;
  background: radial-gradient(ellipse at 30% 0, #06322c55, transparent 42%), #060a0e; color: #f2f6fb; font-size: 15px; line-height: 1.7;
}
.mse-login-head {
  width: 100%; max-width: 1280px; margin: 0 auto; padding: 26px 36px; flex: none;
  display: flex; justify-content: space-between; align-items: center; gap: 20px; border-bottom: 1px solid #293744;
}
.mse-login-head > a { display: flex; align-items: center; justify-content: center; min-height: 48px; line-height: 1; }
.mse-login-head > a:hover { text-decoration: none; }
.mse-login-head .brand-wordmark { display: block; font-size: 30px; line-height: 1; padding-top: 10px; }
.mse-login-actions { display: flex; align-items: center; gap: 24px; font-size: 13px; }
.mse-site-view {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; border-radius: 7px; padding: 12px 20px; white-space: nowrap;
  font-weight: 600; font-size: 13px; line-height: 1.7; color: #fff; background: linear-gradient(110deg, #008f66, #195bd4); box-shadow: 0 5px 16px #006b8b18;
  transition: box-shadow .2s;
}
.mse-site-view:hover { box-shadow: 0 5px 25px #1682b448; text-decoration: none; }
/* v2.2.11 …/edit/ 관리자 로그인의 '일반 계정 로그인' (사이트 보기 왼쪽) */
.mse-member-login {
  display: inline-flex; align-items: center; justify-content: center; border-radius: 7px; padding: 11px 18px; white-space: nowrap;
  font-weight: 600; font-size: 13px; line-height: 1.7; color: #e9f2fb; border: 1px solid #40576c; background: #1b2b3a99;
  transition: background-color .3s, border-color .3s, color .3s;
}
.mse-member-login:hover { background: #263d50; border-color: #55e6c6aa; color: #fff; text-decoration: none; }
/* v2.3.36 로그인 화면 머리의 '사용자 메뉴얼' ('사이트 보기' 왼쪽 — 가입 전에도 설명서를 읽게) */
.mse-manual-link { display: inline-flex; align-items: center; gap: 7px; color: #c9d6e3; font-weight: 600; font-size: 13px; white-space: nowrap; transition: color .2s; }
.mse-manual-link:hover { color: #fff; text-decoration: none; }
.mse-manual-link svg { width: 16px; height: 16px; flex: none; color: #55e6c6; }
.mse-login-main { flex: 1 0 auto; width: 100%; }
.mse-login-message { max-width: 900px; margin: 24px auto 0; padding: 15px 20px; border-radius: 8px; background: #351b24; border: 1px solid #884455; color: #ffc5d0; }
.mse-access-panel {
  width: min(440px, calc(100% - 40px)); margin: 10vh auto 60px; padding: 34px;
  border: 1px solid #293744; background: #0f1922dd; border-radius: 18px; box-shadow: 0 20px 90px #0005;
}
/* v2.2.11 처리 중 표시는 단추 · 글로 — 칸 전체를 '기다림' 커서로 바꾸지 않는다 */
.mse-eyebrow { color: #51e4c4; font-size: 11px; font-weight: 700; letter-spacing: .14em; margin: 0 0 18px; }
.mse-access-panel h1 { font-size: 28px; line-height: 1.4; margin: 0 0 12px; letter-spacing: -.04em; }
.mse-muted { color: #a1b3c6; margin: 0; }
.mse-login-form { margin-top: 28px; }
.mse-login-form label { display: block; font-weight: 500; font-size: 13px; margin: 18px 0 9px; }
.mse-login-form input {
  width: 100%; min-width: 0; background: #071019; border: 1px solid #354959; color: #fff; border-radius: 7px; padding: 12px 14px;
  font-size: 15px; transition: border-color .3s, outline-color .3s; outline: 2px solid transparent; outline-offset: 1px;
}
.mse-login-form input::placeholder { color: #70869a; }
.mse-login-form input:focus { border-color: #54d9bb; outline-color: #54d9bb33; }
.mse-help { font-size: 12px; line-height: 1.7; margin: 10px 0 0; color: #a1b3c6; }
.mse-help.is-bad { color: #ffb8c6; } /* v2.2.4 가입 닉네임 — 규칙에 안 맞는 까닭 (가입 단추가 꺼진 이유) */
.mse-primary, .mse-secondary {
  border: 0; border-radius: 7px; padding: 12px 20px; white-space: nowrap; font-weight: 600; font-size: 13px; cursor: pointer;
  transition: background-color .3s, color .3s, box-shadow .3s, opacity .35s, filter .35s;
}
.mse-primary { background: linear-gradient(110deg, #008f66, #195bd4); color: #fff; box-shadow: 0 5px 16px #006b8b18; }
.mse-primary:hover { box-shadow: 0 5px 25px #1682b448; }
.mse-secondary { background: #1b2b3a; border: 1px solid #40576c; color: #e9f2fb; }
.mse-secondary:hover { background: #263d50; }
.mse-primary:disabled, .mse-secondary:disabled { cursor: not-allowed; opacity: .45; filter: saturate(.35); box-shadow: none; }
.mse-full { display: block; width: 100%; margin-top: 26px; }
.mse-login :focus-visible { outline: 2px solid #55e6c6; outline-offset: 4px; }
@media (max-width: 800px) { .mse-login-head { padding: 22px; } .mse-login-message { margin: 20px; } }
@media (max-width: 480px) {
  .mse-access-panel { margin-top: 8vh; padding: 25px; }
  .mse-login-head { gap: 18px; }
  .mse-login-actions { gap: 10px; font-size: 11px; }
  .mse-site-view, .mse-member-login { padding: 7px 10px; font-size: 11px; }
}
@media (forced-colors: active) { .mse-login-head .brand-wordmark { background: none; color: LinkText; } }
/* 머리줄 로그아웃 단추 (nav.html) — 홈페이지 관리자 .logout-action 과 같은 색 */
[data-logout] { display: none; }
html.mse-logged-in [data-logout] { display: inline-block; }
.logout-action {
  border: 1px solid #b65769; border-radius: 7px; background: #321a22; color: #ffd5dc; padding: 6px 14px; font-size: 13px; font-weight: 600;
  white-space: nowrap; cursor: pointer; flex-shrink: 0; transition: background-color .2s, border-color .2s, color .2s;
}
.logout-action:hover { background: #48222e; border-color: #df8193; color: #fff; }
.logout-action:focus-visible { outline-color: #ffc0cb; }
/* v2.2.21 머리줄 프로필 사진 (nav.html — 로그아웃 옆, 누르면 계정 설정). 사진은 <html> 의 CSS 변수(auth.js), 없으면 닉네임 첫 글자 */
[data-account-avatar] { display: none; }
html.mse-logged-in [data-account-avatar] { display: inline-grid; }
/* 로그아웃 바로 옆 (메뉴 간격 42 px 중 10 px 만 — 좁은 화면의 28 · 22 px 도 아래에서) */
.avatar-action {
  position: relative; width: 32px; height: 32px; margin: 0 -32px 0 0; padding: 0; border: 1px solid #2f7f6c; border-radius: 50%; background: #0f2a26; color: #c9f5e9;
  flex-shrink: 0; overflow: hidden; cursor: pointer; transition: border-color .2s, box-shadow .2s;
}
@media (max-width: 900px) { .avatar-action { margin-right: -18px; } }
@media (max-width: 640px) { .avatar-action { margin-right: -12px; } }
.avatar-action:hover { border-color: #55e6c6; box-shadow: 0 0 0 3px #55e6c62e; }
.avatar-action:focus-visible { outline: 2px solid #55e6c6; outline-offset: 2px; }
/* 사진 칸은 단추를 채운다 (절대 위치 — 그리드 칸이면 글자가 없을 때 크기 0 으로 줄어 사진이 안 보였다) */
.avatar-face {
  position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%;
  background: var(--mse-avatar-img, none) center / cover no-repeat; font-size: 14px; font-weight: 700; line-height: 1;
}
.avatar-face::after { content: var(--mse-avatar-initial, ''); }
html.mse-has-avatar .avatar-face::after { content: none; }

/* ---- v2.2.0 계정 (assets/auth.js) — 회원가입 · 보안 연결 안내 · 탈퇴 대기. 사용자 계정은 위 메뉴가 PROJECT · 로그아웃만(TOOLS 는 숨김 —
   주소로 열어도 목록으로 보내고 서버도 막는다), 관리자 전용 단추([data-admin-only])도 숨김 — 화면 표시는 편의, 권한은 서버가 */
html.mse-role-user .main-nav a[data-nav-key]:not([data-nav-key="editor"]):not([data-nav-key="manual"]) { display: none; }
/* v2.3.36 사용자 메뉴얼 (nav.html — 프로필 사진 왼쪽). 좁은 화면은 책 아이콘 + '메뉴얼' */
.main-nav .nav-manual { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.nav-manual svg { flex: none; width: 15px; height: 15px; }
@media (max-width: 420px) { .nav-manual span { font-size: 0; } .nav-manual span::after { content: '메뉴얼'; font-size: 12px; } }
/* v2.3.37 좁은 화면의 관리자 머리줄 (재어 고침 — ADMIN 이 더해져 390 px 에서 PROJECT 가 화면 밖 -50 px, 360 px 아래는 예전에도 넘침, v2.3.38 ADMIN ▾ 도):
   420 px 아래는 사이를 줄이고 메뉴얼은 책 아이콘만 (이름은 읽기 도구에 그대로), 그래도 넘치면 왼쪽으로 잘리지 않고 두 줄로 */
@media (max-width: 640px) { .main-nav { flex-wrap: wrap; row-gap: 4px; } }
@media (max-width: 420px) {
  html.mse-role-admin .main-nav { gap: 12px; }
  html.mse-role-admin .avatar-action { margin-right: -4px; } /* 사진과 로그아웃 사이 8 px (위 -12px 은 사이 22 px 기준) */
  html.mse-role-admin .nav-manual span::after { content: none; }
}
/* v2.3.38 400 px 아래 관리자: TOOLS · ADMIN 의 ▾ 를 빼 한 줄에 (누르면 펼치기는 그대로 — 390 px 에서 로그아웃이 둘째 줄로 내려갔었음) */
@media (max-width: 400px) {
  html.mse-role-admin .main-nav .nav-menu-chev { display: none; }
  html.mse-role-admin .main-nav .nav-tools-toggle { gap: 0; }
}
/* 메인 회원 로그인 — 바깥은 편집기로 만든 3DGS 맵 그림(1920px — assets/login-bg.jpg)을 아주 연하게, 가운데로 갈수록 바탕색에 묻히게.
   관리자 로그인(…/edit/ — .is-admin)은 홈페이지 관리자 /edit/ 처럼 바탕만 */
.mse-login.has-backdrop::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: var(--mse-login-bg, url(login-bg.jpg)) center / cover no-repeat; opacity: var(--mse-login-bg-opacity, .16); filter: saturate(.85);
}
.mse-login.has-backdrop::after { content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none; background: radial-gradient(ellipse at 50% 45%, #060a0e00 25%, #060a0ee6 100%); }
.mse-login.has-backdrop .mse-access-panel { background: #0f1922ee; }
.mse-or { display: flex; align-items: center; gap: 12px; margin: 26px 0 0; color: #70869a; font-size: 12px; }
.mse-or::before, .mse-or::after { content: ''; flex: 1; height: 1px; background: #293744; }
.mse-full.mse-signup-btn { margin-top: 12px; }
.mse-hidden-user { position: absolute !important; left: -10000px; width: 1px !important; height: 1px; opacity: 0; }
/* ---- v2.2.0 계정 창 (assets/accounts.js) — 내 계정 · 공유 · 계정 관리(서버 컴퓨터) · 로그인 화면 배경. 상태 표시(새 가입 · 탈퇴 대기 · 사용 중지) */
.acct-badge { display: inline-flex; align-items: center; margin-left: 6px; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; line-height: 18px; vertical-align: middle; white-space: nowrap; border: 1px solid transparent; }
.acct-badges .acct-badge { margin-left: 0; }
.acct-badge.is-admin { color: #f3dca0; background: #3a2f12; border-color: #d6b25e55; }
.acct-badge.is-new { color: #c9f7e8; background: #0f3a30; border-color: #2fd3a866; }
.acct-badge.is-withdrawn { color: #ffd0d8; background: #3a1820; border-color: #df819366; }
.acct-badge.is-disabled { color: #d6dde5; background: #2a3138; border-color: #6c7a8766; }
dialog.modal.acct-modal { width: min(560px, calc(100vw - 32px)); }
.acct-modal .modal-body { max-height: min(78vh, 760px); overflow: auto; }
.acct-summary { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 14px; margin: 0; padding: 12px 14px; border: 1px solid #ffffff14; border-radius: 10px; background: #ffffff06; font-size: 13px; }
.acct-summary dt { color: var(--muted); white-space: nowrap; }
.acct-summary dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
/* v2.2.4 내 계정 요약: 닉네임을 크게 (없는 예전 계정은 정해 달라는 안내) */
.acct-summary dd.acct-nick { font-size: 15px; font-weight: 700; line-height: 1.35; }
.acct-summary dd.acct-nick.is-missing { color: #ffd479; font-size: 13px; font-weight: 500; }
.acct-section { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.acct-section h3 { margin: 0 0 10px; font-size: 14.5px; }
.acct-row { display: grid; grid-template-columns: 110px minmax(0, 1fr); align-items: center; gap: 6px 12px; margin-top: 8px; font-size: 13px; color: var(--muted); }
.acct-row small { grid-column: 2; color: var(--dim); font-size: 11.5px; }
.acct-check { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-size: 13px; cursor: pointer; }
.acct-check input { width: 16px; height: 16px; accent-color: var(--accent); }
.acct-company { margin: 2px 0 0 4px; padding-left: 12px; border-left: 2px solid #2fd3a840; }
.acct-company[hidden] { display: none; }
.acct-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
/* v2.2.21 계정 설정: 프로필 사진 (동그라미를 누르거나 끌어 놓기 — 창 어디에 놓아도 받음) */
.acct-avatar-row { display: flex; align-items: center; gap: 18px; }
.acct-avatar-drop {
  position: relative; flex: none; width: 96px; height: 96px; margin: 0 0 8px; padding: 0; border-radius: 50%; border: 2px dashed #2f7f6c; background: #0f2a26;
  display: grid; place-items: center; place-content: center; cursor: pointer; color: #c9f5e9; transition: border-color .2s, box-shadow .2s, background-color .2s;
}
.acct-avatar-drop:hover, .acct-avatar-drop:focus-visible, .acct-avatar-drop.is-over { border-color: #55e6c6; box-shadow: 0 0 0 4px #55e6c62e; outline: none; }
.acct-avatar-drop.is-over { background: #164038; border-style: solid; }
.acct-avatar-drop.is-busy { opacity: .6; cursor: default; }
.acct-avatar-face {
  position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%; overflow: hidden;
  background: center / cover no-repeat; font-size: 36px; font-weight: 700; line-height: 1;
}
.acct-avatar-hint {
  position: absolute; left: 50%; bottom: -9px; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px;
  border-radius: 999px; border: 1px solid #2f7f6c; background: #15302b; color: #c9f5e9; font-size: 11px; font-weight: 600; white-space: nowrap; pointer-events: none;
}
.acct-avatar-hint svg { width: 12px; height: 12px; }
.acct-avatar-side { flex: 1; min-width: 0; }
.acct-avatar-side .hint { margin: 0; font-size: 12.5px; line-height: 1.55; }
.acct-avatar-side .acct-actions { justify-content: flex-start; flex-wrap: wrap; margin-top: 10px; }
.acct-avatar-side .up-message { margin: 10px 0 0; }
@media (max-width: 520px) {
  .acct-avatar-row { flex-direction: column; text-align: center; }
  .acct-avatar-side .acct-actions { justify-content: center; }
}
.acct-leave .hint { margin: 0; }
.acct-warn-list { margin: 10px 0 0; padding-left: 18px; display: grid; gap: 6px; color: var(--muted); font-size: 13px; }
@media (max-width: 520px) { .acct-row { grid-template-columns: 1fr; } .acct-row small { grid-column: 1; } }
/* v2.2.3 공유 창 · 공유 받음 표시는 grant 이름 — 'share' 가 든 클래스(.share-list · .share-row · .card-share)는 광고 · SNS 차단 목록이 숨긴다 */
.grant-modal .field[type=search] { width: 100%; margin-top: 12px; }
.grant-list { list-style: none; margin: 10px 0 0; padding: 0; max-height: 46vh; overflow: auto; border: 1px solid var(--line); border-radius: 10px; }
.grant-row label { display: flex; align-items: center; gap: 10px; padding: 9px 12px; cursor: pointer; font-size: 13.5px; }
.grant-row + .grant-row { border-top: 1px solid #ffffff0d; }
.grant-row.is-on { background: #2fd3a80d; }
.grant-row input { width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
.grant-row small { color: var(--dim); }
/* v2.2.4 공유 창 줄: 닉네임(굵게) + 아이디(작게 · 고정폭) — 닉네임이 없는 예전 계정은 아이디를 굵게 */
.grant-name { display: inline-flex; align-items: baseline; flex-wrap: wrap; gap: 2px 7px; min-width: 0; }
.grant-name b { font-weight: 600; overflow-wrap: anywhere; }
.grant-name small { font-size: 11.5px; }
.grant-empty { padding: 16px; color: var(--dim); font-size: 13px; text-align: center; }
/* v2.2.3 공유 창: 아이디 목록 대신 검색 결과만 · 체크를 모아 '확인' 으로 (추가 · 해제 표시 · 지금 공유 수) */
.grant-count { margin: 12px 0 0 !important; color: var(--muted); font-size: 12.5px !important; }
.grant-more { padding: 10px 12px; border-top: 1px solid #ffffff0d; color: var(--dim); font-size: 12px; text-align: center; }
.grant-tag { margin-left: auto; padding: 1px 8px; border-radius: 999px; border: 1px solid #5b8cff44; background: #10263a; color: #9fd8ff; font-size: 11px; font-weight: 600; line-height: 18px; white-space: nowrap; }
.grant-tag.is-add { border-color: #2fd3a866; background: #0f3a30; color: #c9f7e8; }
.grant-tag.is-remove { border-color: #df819366; background: #3a1820; color: #ffd0d8; }
.grant-pending { display: grid; gap: 4px; margin: 10px 0 0 !important; padding: 9px 12px; border-radius: 9px; border: 1px solid #2fd3a833; background: #2fd3a80a; color: var(--muted); font-size: 12.5px !important; }
.grant-pending b { color: var(--text); font-weight: 600; overflow-wrap: anywhere; }
.grant-tag[hidden], .grant-pending[hidden] { display: none; }
/* v2.4.12 공유 창: 공유 중인 계정 칸(늘 보임 · 이름 차례 · 칸 안 스크롤 · 6명부터 거르기 칸) + 공유할 계정 찾기 칸 — 작은 제목으로 나눔 */
.grant-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 30px; margin-top: 14px; }
.grant-modal .grant-sec-title { margin: 0; font-size: 13px; font-weight: 600; line-height: 1.4; color: var(--text); } /* .modal-body h3 여백 · 크기를 덮음 */
.grant-sec-title small { margin-left: 8px; color: var(--dim); font-size: 12px; font-weight: 500; }
.grant-modal .grant-sec-head .field.grant-filter { width: min(220px, 50%); margin: 0; min-height: 0; padding-top: 5px; padding-bottom: 5px; font-size: 12.5px; }
.grant-modal .grant-sec-find .field[type=search] { margin-top: 8px; }
.grant-sec .grant-list { margin-top: 8px; max-height: min(30vh, 250px); }
.grant-note { margin: 6px 0 0 !important; color: var(--dim); font-size: 12px !important; }
.grant-filter[hidden], .grant-count[hidden], .grant-sec[hidden] { display: none; }
/* 창 높이가 모자라면 창 전체가 스크롤되지 않고(확인 단추가 가려짐) 두 목록 칸이 먼저 줄어든다 — 그래도 모자라면 예전처럼 창 안 스크롤.
   두 칸(section)은 상자 없이(contents) 제목 · 목록 · 안내가 창 본문의 줄로 바로 놓인다 — 칸이 줄면서 안의 목록이 아래 칸과 겹치지 않게 */
.grant-modal .modal-body { display: flex; flex-direction: column; }
.grant-modal .modal-body > * { flex: none; }
.grant-modal .modal-body > .grant-sec { display: contents; }
.grant-modal .modal-body > .grant-sec[hidden] { display: none; }
.grant-sec > * { flex: none; }
.grant-sec > .grant-list { flex: 0 1 auto; min-height: 0; }
.grant-sec > .grant-list.is-short { flex: none; } /* 두 줄까지(안내 · 결과 없음 포함)는 줄이지 않음 */
.grant-sec > .grant-list.is-tall { min-height: 84px; } /* 세 줄 넘는 목록은 두 줄 넘게 남김 */
.grant-modal .modal-body > .hint { margin-bottom: 0; } /* 다음 줄(제목) 위 여백 14 px 와 겹쳐 24 px 가 되지 않게 */
/* 낮은 화면(1366×640 등) · 휴대폰 폭: 목록 칸 · 안내 글을 줄이고 본문을 창 높이까지 (창 자체 max-height 100vh − 48 안) — 확인 단추가 스크롤 밖으로 밀리지 않게 */
@media (max-height: 720px) { .grant-sec .grant-list { max-height: 24vh; } }
@media (max-height: 720px), (max-width: 520px) { .grant-modal .modal-body { max-height: calc(100vh - 104px); } .grant-modal .modal-body > .hint { font-size: 12px; line-height: 1.5; } }
@media (max-width: 520px) { .grant-sec-head { flex-wrap: wrap; } .grant-modal .grant-sec-head .field.grant-filter { width: 100%; } }
dialog.modal.acct-manager { width: min(1200px, calc(100vw - 32px)); } /* v2.3.44 1080 → 1200 — 표 칸이 늘어 14 px 넘쳤다 (가입 알림 칸 '관리자가 만듦' 등) */
/* v2.3.44 계정 관리 위 줄: 안내 + 계정 만들기 · 계정 만들기 창 (아이디 + 중복 확인 한 줄, 안내 글 색) */
.acct-manager-top { display: flex; align-items: flex-start; gap: 16px; }
.acct-manager-top .hint { flex: 1; min-width: 0; margin: 0; }
.acct-manager-top .acct-create-btn { flex: none; }
@media (max-width: 640px) { .acct-manager-top { flex-direction: column; gap: 10px; } }
dialog.modal.acct-create { width: min(600px, calc(100vw - 32px)); }
.acct-create .acct-row > label { color: var(--muted); }
.acct-idrow { display: flex; gap: 8px; min-width: 0; }
.acct-idrow .field { flex: 1; min-width: 0; }
.acct-idrow .btn { flex: none; }
.acct-idrow .btn.is-done { color: #c9f7e8; border-color: #2fd3a866; }
.acct-create .acct-row small.is-bad { color: #ffb3c0; }
.acct-create .acct-row small.is-good { color: #8ff0cf; }
.acct-create-note { margin: 14px 0 0; padding: 10px 12px; border-radius: 9px; border: 1px solid #5b8cff44; background: #10263a; color: #cfe3ff; font-size: 12.5px; line-height: 1.6; }
.acct-table-wrap { margin-top: 12px; overflow: auto; max-height: 60vh; border: 1px solid var(--line); border-radius: 10px; }
.acct-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.acct-table th, .acct-table td { padding: 8px 10px; text-align: left; vertical-align: middle; border-bottom: 1px solid #ffffff0d; white-space: nowrap; }
.acct-table thead th { position: sticky; top: 0; z-index: 1; background: #101a22; color: var(--muted); font-weight: 600; }
.acct-table tbody th { font-weight: 600; }
/* v2.2.4 계정 관리 첫 칸: 닉네임(굵게) 아래 아이디(작게) · 옆에 표시 */
.acct-table .acct-who { display: inline-flex; flex-direction: column; vertical-align: middle; line-height: 1.35; }
.acct-table .acct-who small { color: var(--dim); font-size: 11px; font-weight: 400; }
.acct-table select.field { width: auto; min-width: 150px; padding: 4px 8px; } /* v2.3.39 width auto — .field 의 100% 로 칸을 다 차지해 옆 '변경' 단추가 다음 칸 날짜를 덮었다 */
.acct-table td small { display: block; color: #ffc9d2; font-size: 11px; }
.acct-table tr.is-withdrawn, .acct-table tr.is-disabled { color: var(--muted); }
dialog.modal.loginbg-modal { width: min(640px, calc(100vw - 32px)); }
.loginbg-preview { position: relative; aspect-ratio: 16 / 9; margin: 12px 0 0; border-radius: 10px; overflow: hidden; background: #060a0e; border: 1px solid var(--line); }
.loginbg-shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: saturate(.85); }
.loginbg-vignette { position: absolute; inset: 0; background: radial-gradient(ellipse at 50% 45%, #060a0e00 25%, #060a0ee6 100%); }
.loginbg-card { position: absolute; left: 50%; top: 50%; width: 23%; aspect-ratio: 440 / 620; transform: translate(-50%, -48%); box-sizing: border-box; border: 1px solid #293744; border-radius: 6px; background: #0f1922ee; display: grid; align-content: center; gap: 9%; padding: 0 9%; }
.loginbg-card i { display: block; height: 8px; border-radius: 2px; background: #071019; border: 1px solid #354959; }
.loginbg-card b { display: block; height: 9px; border-radius: 2px; background: linear-gradient(110deg, #008f66, #195bd4); }
.loginbg-row { display: flex; align-items: center; gap: 10px; margin-top: 12px; flex-wrap: wrap; font-size: 13px; color: var(--muted); }
.loginbg-row input[type=range] { flex: 1; min-width: 160px; accent-color: var(--accent); }
.loginbg-value { min-width: 3.5em; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.loginbg-file { min-width: 0; overflow-wrap: anywhere; color: var(--dim); font-size: 12.5px; }
html.mse-role-user [data-admin-only] { display: none !important; }
html.pj-granted [data-owner-only] { display: none !important; }
.pj-granted-note { margin: 8px 0 0; padding: 8px 12px; border-radius: 9px; border: 1px solid #5b8cff55; background: #0f223a99; color: #cfe4ff; font-size: 12.5px; line-height: 1.6; }
.pj-granted-note[hidden] { display: none; }
.mse-warn { margin: 18px 0 0; padding: 10px 14px; border-radius: 8px; background: #3a2c0f; border: 1px solid #8a6a22; color: #ffe2a8; font-size: 12.5px; line-height: 1.6; }
.mse-switch { margin: 20px 0 0; text-align: center; font-size: 13px; color: #a1b3c6; }
/* v2.2.12 비밀번호 찾기 · 바꾼 뒤 안내(초록) · 계정 관리 '변경' */
.mse-forgot { margin: 12px 0 0; text-align: right; font-size: 12.5px; }
.mse-forgot-note { margin-top: 14px; }
.mse-login-message.is-ok { background: #0f2f27; border-color: #2f7f6c; color: #c9f5e9; }
.acct-status-cell { white-space: nowrap; }
.acct-status-cell .acct-pw-btn { margin-left: 6px; vertical-align: middle; }
.mse-link { border: 0; background: none; padding: 0; color: #55e6c6; font: inherit; font-weight: 600; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
.mse-link:hover { color: #8ff3dc; }
.mse-login-form label.mse-check { display: flex; align-items: flex-start; gap: 10px; margin: 18px 0 0; font-weight: 500; cursor: pointer; }
.mse-login-form .mse-check input { width: 18px; height: 18px; flex: none; margin: 3px 0 0; padding: 0; accent-color: #2fd3a8; }
/* v2.3.27 회원 로그인 아래 옵션 — 아이디 기억하기 · 자동 로그인 (한 줄 · 좁으면 두 줄) */
.mse-login-opts { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 18px; margin-top: 16px; }
.mse-login-opts label.mse-check { margin: 0; align-items: center; font-size: 13px; color: #c9d6e2; }
.mse-login-opts .mse-check input { margin: 0; }
.mse-login-opts + .mse-full { margin-top: 20px; }
/* v2.2.11 회원가입 — 세로를 줄인 배치(두 칸 줄 · 짧은 칸 사이) · 아이디 중복 확인 · 접고 펴는 칸(auth.js reveal — 홈페이지 문의 화면처럼
   0.5초 높이 · 투명도) · 안내 글 색(맞음 · 틀림) */
/* 가입 칸은 조금 넓게(안내 글이 한 줄에) · 위 여백 · 제목을 줄여 세로를 줄인다 */
.mse-access-panel:has(.mse-signup-form) { width: min(520px, calc(100% - 40px)); margin-top: 5vh; padding-top: 28px; padding-bottom: 28px; }
.mse-access-panel:has(.mse-signup-form) .mse-eyebrow { margin-bottom: 10px; }
.mse-access-panel:has(.mse-signup-form) h1 { font-size: 25px; margin-bottom: 4px; }
.mse-signup-form { margin-top: 16px; }
.mse-signup-form label { margin: 13px 0 7px; }
.mse-signup-form input { padding: 10px 13px; }
.mse-signup-form .mse-help { margin-top: 6px; line-height: 1.6; }
.mse-su-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
.mse-su-cell { min-width: 0; }
.mse-su-idrow { display: flex; gap: 8px; }
.mse-su-idrow input { flex: 1 1 auto; }
.mse-su-idcheck { flex: none; padding: 0 14px; }
.mse-su-idcheck.is-done, .mse-su-idcheck.is-done:disabled { border-color: #2fd3a888; color: #8ef0d2; opacity: 1; filter: none; cursor: default; }
.mse-help.is-good { color: #8ef0d2; }
.mse-su-company { margin-top: 6px; }
.mse-su-company-in { padding: 0 0 4px 14px; border-left: 2px solid #2fd3a855; }
.mse-su-company[hidden], .mse-su-privacy[hidden] { display: none; }
.mse-su-consent-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.mse-su-consent-row label.mse-check { margin-top: 14px; }
.mse-su-more {
  flex: none; display: inline-flex; align-items: center; gap: 8px; margin-top: 14px; padding: 2px 4px; border: 0; background: none;
  color: #93b2c8; font: inherit; font-size: 12px; cursor: pointer; transition: color .3s;
}
.mse-su-more:hover { color: #d7e5ef; }
.mse-su-more::after {
  content: ''; width: 6px; height: 6px; margin-top: -3px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg); transition: transform .5s cubic-bezier(.22,.68,.2,1), margin .5s;
}
.mse-su-more[aria-expanded="true"]::after { transform: rotate(225deg); margin-top: 3px; }
.mse-su-privacy dl { display: grid; grid-template-columns: 64px 1fr; gap: 6px 14px; margin: 10px 0 0 28px; padding: 12px 14px; border: 1px solid #243c4d;
  border-radius: 9px; background: #0a1825; font-size: 12px; line-height: 1.6; }
.mse-su-privacy dt { color: #d9e6ef; font-weight: 600; }
.mse-su-privacy dd { margin: 0; color: #a8c0d1; }
.mse-signup-form .mse-full { margin-top: 20px; }
.mse-su-why { min-height: 1.6em; text-align: center; }
@media (max-width: 420px) { .mse-su-row { grid-template-columns: 1fr; } .mse-su-privacy dl { margin-left: 0; } }
@media (prefers-reduced-motion: reduce) { .mse-su-more::after, .btn, .mse-primary, .mse-secondary { transition: none; } }
.mse-trap { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* ---- v2.0.0 맵 올리기 — 유형 선택(일반 맵 · Cesium 지리정보 맵) · 지도 · 주소 패널 (assets/upload.js openUploadDialog) ----
   카드(.up-type)는 복제 창의 .dup-mode 와 같은 값 · 2열, 540px 아래 1열 */
.up-types { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; min-width: 0; margin: 14px 0 0; padding: 0; border: 0; }
.up-types legend { padding: 0; margin-bottom: 6px; font-size: 13px; color: var(--muted); }
.up-type { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 10px; align-items: start; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; background: #ffffff05; cursor: pointer; transition: border-color .3s, background .3s, box-shadow .3s; }
.up-type input { margin: 3px 0 0; accent-color: var(--accent); }
.up-type-body { display: grid; gap: 4px; min-width: 0; }
.up-type-body > svg { width: 26px; height: 26px; margin-bottom: 2px; color: var(--teal); }
.up-type strong { font-size: 14px; color: var(--text); }
.up-type span { font-size: 12.5px; line-height: 1.6; color: var(--muted); }
.up-type:hover { border-color: #ffffff45; background: #ffffff0a; }
.up-type:has(input:checked) { border-color: #2fd3a877; background: #2fd3a80d; box-shadow: 0 0 0 1px #2fd3a833 inset; }
.up-type:has(input:checked) .up-type-body > svg { color: var(--accent); }
.up-type:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.up-type.is-off, .up-type:has(input:disabled) { cursor: not-allowed; opacity: .65; }
.up-type.is-off:hover { border-color: var(--line); background: #ffffff05; }
.up-type-note { display: block; margin-top: 2px; font-size: 12px; font-style: normal; line-height: 1.5; color: #ffd479; }
/* 폼 위 한 줄 — Cesium 맵이면 위치 요약 · 위치 바꾸기 · 유형 바꾸기 */
.up-typeline { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; margin-top: 10px; padding: 9px 14px; border-radius: 9px; border: 1px solid #1b60e144; background: #1b60e114; font-size: 12.5px; color: #c8d6ee; }
.up-typeline > svg { width: 16px; height: 16px; flex: none; color: var(--teal); }
.up-typeline strong { color: #e6eefc; }
.up-typeline > span { flex: 1 1 200px; color: var(--muted); overflow-wrap: anywhere; }
/* 지도 (Leaflet, assets/geomap.js createGeoPicker) — 높이 260px 틀. 지도 전이나 모듈이 없을 때는 안내 글만 */
:is(.upload-modal, .mt-geo-modal) .geo-map { position: relative; width: 100%; height: 260px; margin-top: 12px; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: #071019; isolation: isolate; }
:is(.upload-modal, .mt-geo-modal) .geo-map.leaflet-container { background: #0a1016; font: inherit; }
/* v2.0.3 맵 올리기 창은 지도를 시도마다 안쪽 칸(.geo-map-host)에 만든다 (upload.js ensurePicker) — 틀을 꽉 채움 */
:is(.upload-modal, .mt-geo-modal) .geo-map-host { position: absolute; inset: 0; }
:is(.upload-modal, .mt-geo-modal) .geo-map-host.leaflet-container { background: #0a1016; font: inherit; }
:is(.upload-modal, .mt-geo-modal) .geo-map-note { position: absolute; inset: 0; z-index: 1; display: grid; place-items: center; padding: 16px; text-align: center; color: var(--dim); font-size: 12.5px; }
:is(.upload-modal, .mt-geo-modal) .geo-map-note.bad { color: #ffb4c1; }
/* 주소 검색 (Enter · 단추) → 결과 최대 5개 */
:is(.upload-modal, .mt-geo-modal) .geo-search { display: flex; gap: 8px; margin-top: 10px; }
:is(.upload-modal, .mt-geo-modal) .geo-search .field { flex: 1; }
:is(.upload-modal, .mt-geo-modal) .geo-results { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 4px; }
:is(.upload-modal, .mt-geo-modal) .geo-result { display: flex; align-items: baseline; gap: 10px; width: 100%; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; background: #ffffff05; color: var(--text); font: inherit; font-size: 12.5px; line-height: 1.5; text-align: left; cursor: pointer; transition: border-color .2s, background .2s; }
:is(.upload-modal, .mt-geo-modal) .geo-result:hover { border-color: #2fd3a877; background: #2fd3a80d; }
:is(.upload-modal, .mt-geo-modal) .geo-result > span:first-child { flex: 1; min-width: 0; overflow-wrap: anywhere; }
:is(.upload-modal, .mt-geo-modal) .geo-result .geo-src { flex: none; font-size: 11px; color: var(--dim); }
:is(.upload-modal, .mt-geo-modal) .geo-results .geo-empty { padding: 6px 12px; font-size: 12.5px; color: var(--dim); }
/* 좌표 칸 — 경도 · 위도 · 높이 · 방향 (4열, 540px 아래 2열). 위치를 정하기 전에는 비활성 */
:is(.upload-modal, .mt-geo-modal) .geo-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px 12px; margin-top: 12px; }
:is(.upload-modal, .mt-geo-modal) .geo-field { display: grid; gap: 4px; font-size: 12px; color: var(--muted); }
:is(.upload-modal, .mt-geo-modal) .geo-field .field { font-variant-numeric: tabular-nums; }
:is(.upload-modal, .mt-geo-modal) .geo-field .field:disabled { opacity: .5; cursor: not-allowed; }
:is(.upload-modal, .mt-geo-modal) .geo-keys { margin: 10px 0 0; font-size: 12px; color: var(--dim); }
/* v2.0.1 'Cesium 맵으로' 위치 정하기 창 (assets/maptype.js) — 맵 올리기 창의 지도 · 주소 칸과 같은 모양, 지도는 조금 크게 */
dialog.mt-geo-modal { width: min(720px, calc(100vw - 32px)); }
.mt-geo-modal .geo-map { height: 300px; }
.mt-geo-modal .geo-readout { margin: 10px 0 0; font-size: 12.5px; line-height: 1.6; color: var(--muted); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.mt-geo-modal .geo-readout strong { color: var(--text); font-weight: 600; }
.mt-geo-modal .modal-foot { flex-wrap: wrap; }
@media (max-width: 540px) {
  .up-types { grid-template-columns: 1fr; }
  :is(.upload-modal, .mt-geo-modal) .geo-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  :is(.upload-modal, .mt-geo-modal) .geo-map { height: 220px; }
}
/* 'API 설정' 창 (assets/apisettings.js) — 보안 설정 창의 틀(.trash-modal .trash-wide) 에 폭만 */
.trash-modal.api-modal { width: min(760px, calc(100vw - 32px)); }
/* v2.0.2 '연결 확인' 결과 줄 (assets/apisettings.js) — 연결됨(초록) · 일부만 연결됨(노랑) · 연결 안 됨(빨강) · 확인 중 · 다시 확인(점선) */
.api-status { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; margin: 8px 0 0; padding: 7px 11px; border: 1px solid var(--line); border-radius: 8px; background: #ffffff06; font-size: 12.5px; line-height: 1.55; color: var(--muted); }
.api-status strong { font-weight: 700; color: var(--text); }
.api-status-mark { flex: none; font-size: 11px; }
.api-status-text { flex: 1 1 260px; min-width: 0; overflow-wrap: anywhere; }
.api-status.is-ok { border-color: #2fd3a866; background: #2fd3a812; }
.api-status.is-ok strong, .api-status.is-ok .api-status-mark { color: #2fd3a8; }
.api-status.is-warn { border-color: #ffd47966; background: #ffd47912; }
.api-status.is-warn strong, .api-status.is-warn .api-status-mark { color: #ffd479; }
.api-status.is-bad { border-color: #ff6b8166; background: #ff6b8112; }
.api-status.is-bad strong, .api-status.is-bad .api-status-mark { color: #ff8a9a; }
.api-status.is-busy, .api-status.is-stale { border-style: dashed; }
.api-key-field[data-check="ok"] .field { border-color: #2fd3a877; }
.api-key-field[data-check="bad"] .field { border-color: #ff6b8177; }
/* v2.3.4 API 설정 창 — 온라인 모드 중계 서버(TURN)의 최근 연결 (플레이어 화면이 보낸 진단) */
.rtc-recent { margin-top: 14px; }
.rtc-recent h4 { margin: 0 0 6px; font-size: 13px; font-weight: 700; color: var(--muted); }
.rtc-recent ol { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; max-height: 240px; overflow: auto; }
.rtc-recent li { padding: 6px 10px; border: 1px solid var(--line); border-radius: 8px; font-size: 12.5px; line-height: 1.5; color: var(--muted); overflow-wrap: anywhere; }
.rtc-recent li.is-ok { border-color: #2fd3a844; }
.rtc-recent li.is-bad { border-color: #ff6b8144; }
.rtc-recent li b { color: var(--text); font-weight: 700; }
.rtc-recent li.is-bad b { color: #ff8a9a; }
.rtc-recent small { display: block; color: var(--dim); font-size: 11.5px; }
/* 카드 배지 — Cesium · 지리정보 맵 (목록 · 프로젝트 카드). 썸네일 안에 두면 오른쪽 아래, 글줄 안이면 작은 알약 */
.badge-cesium { display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 700; letter-spacing: .04em; line-height: 1.5; white-space: nowrap; vertical-align: middle; color: #cfe4ff; background: #0f223ad9; border: 1px solid #5b8cff80; }
.thumb .badge-cesium { position: absolute; right: 10px; bottom: 10px; z-index: 1; pointer-events: none; }

/* v2.1.12 프로젝트 게시 설정 창 (assets/publishset.js — 프로젝트 화면 '게시 · 변경 사항 게시') · 퍼가기 코드 창.
   게시 유형 카드는 맵 올리기 .up-type 결, 세그먼트 · 스위치는 편집기와 같은 모양 (프로젝트 화면은 editor.css 를 읽지 않음) */
dialog.modal.pubset-modal { width: min(700px, calc(100vw - 32px)); }
.pubset { display: grid; gap: 12px; }
.pubset-types { grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 0; }
.pubset-type { padding: 12px 14px; }
.pubset-type .up-type-body > svg { width: 22px; height: 22px; }
.pubset-note { margin: 0 !important; padding: 9px 12px; border-radius: 9px; border: 1px solid #1b60e144; background: #1b60e114; font-size: 12.5px; line-height: 1.6; color: #c8d6ee !important; overflow-wrap: anywhere; }
.pubset-note.is-warn { border-color: #ffd47955; background: #ffd47912; color: #ffe2a3 !important; }
.pubset-sec { display: grid; padding: 10px 14px 6px; border: 1px solid var(--line); border-radius: 12px; background: #ffffff05; }
.pubset-sec[hidden] { display: none; }
.pubset-h { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin: 0 0 4px !important; font-size: 13.5px; }
.pubset-h small { font-weight: 400; color: var(--muted); font-size: 12px; }
.pubset-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 6px 14px; padding: 8px 0; border-top: 1px solid #ffffff0d; }
.pubset-h + .pubset-row { border-top: 0; }
.pubset-label { display: grid; gap: 2px; min-width: 0; }
.pubset-label strong { font-size: 13px; font-weight: 600; }
.pubset-label small { font-size: 11.5px; line-height: 1.5; color: var(--muted); }
.pubset-col { display: grid; justify-items: end; gap: 4px; }
.pubset-warn { font-size: 11.5px; color: #ffd479; }
.pubset-warn[hidden] { display: none; }
/* v2.3.0 게시 설정 '온라인 모드' — 거리 줄은 켰을 때만 */
.pubset-row[hidden] { display: none; }
.pubset-online .pubset-warn { margin: 0 0 8px; }
/* v2.3.34 하단 바 단추 하나씩 (하단 바 줄 아래 — 이름 · 단축키 칸 격자) */
.pubset-barrow { grid-template-columns: 1fr; border-top: 0; padding-top: 0; }
.pubset-baritems { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 6px; }
.pubset-baritem { display: flex; align-items: center; gap: 8px; min-width: 0; padding: 6px 10px; border: 1px solid var(--line); border-radius: 9px; background: #ffffff05; font-size: 12.5px; cursor: pointer; transition: border-color .25s, background .25s, color .25s; }
.pubset-baritem:hover { border-color: var(--line-2); }
.pubset-baritem input { width: 15px; height: 15px; margin: 0; flex-shrink: 0; accent-color: #2fd3a8; cursor: pointer; }
.pubset-baritem-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pubset-baritem:has(input:not(:checked)) { color: var(--muted); background: transparent; }
.pubset-baritem:has(input:not(:checked)) .pubset-baritem-name { text-decoration: line-through; text-decoration-color: #ffffff40; }
.pubset-key { margin-left: auto; padding: 1px 6px; border: 1px solid var(--line); border-radius: 5px; background: #ffffff0a; color: var(--muted); font: 600 10.5px/1.5 ui-monospace, Consolas, monospace; white-space: nowrap; }
.pubset .seg { display: flex; gap: 2px; padding: 2px; border-radius: 9px; background: #ffffff0d; }
.pubset .seg-btn { display: inline-flex; align-items: center; height: 26px; padding: 0 10px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); font: inherit; font-size: 12px; font-weight: 600; white-space: nowrap; cursor: pointer; transition: background .25s, color .25s; }
.pubset .seg-btn:hover { color: var(--text); }
.pubset .seg-btn[aria-checked="true"] { background: var(--gradient); color: #fff; }
.pubset .seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pubset-inline { display: flex; align-items: center; gap: 6px; }
.pubset-num { width: 84px; text-align: right; }
.pubset-map { width: auto; min-width: 180px; max-width: 260px; }
.pubset-code { width: 100%; min-height: 64px; resize: vertical; font-family: ui-monospace, Consolas, monospace; font-size: 11.5px; line-height: 1.5; margin: 4px 0 8px; box-sizing: border-box; }
.pubset-copy { align-items: stretch; }
.pubset-copy .pubset-code { margin: 0; }
.pubset-linkline { margin: 10px 0 0 !important; font-size: 12px; overflow-wrap: anywhere; }
.pubset-foot { padding: 2px 0 0 !important; }
.pubset-goicon { display: contents; }
@media (max-width: 620px) {
  .pubset-types { grid-template-columns: 1fr; }
  .pubset-row { grid-template-columns: 1fr; }
  .pubset-col { justify-items: start; }
}

/* v2.3.62 새 판 알림 띠 (updatecheck.js) — 화면 위 가운데. 나타남은 popShow(translate) 라 가운데 맞춤은 margin auto */
.mse-upd { position: fixed; top: 64px; left: 0; right: 0; z-index: 3000; display: flex; align-items: center; gap: 10px; width: max-content; max-width: min(720px, calc(100vw - 24px)); box-sizing: border-box; margin: 0 auto; padding: 9px 10px 9px 14px; border: 1px solid #2fd3a85c; border-radius: 12px; background: #0d1419f0; box-shadow: 0 14px 40px #00000080; color: var(--text); font-size: 13px; line-height: 1.45; backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
.mse-upd[hidden] { display: none; }
.mse-upd-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 4px #2fd3a833; }
.mse-upd-text { flex: 1 1 auto; min-width: 0; }
.mse-upd-acts { display: inline-flex; flex: none; gap: 6px; }
@media (max-width: 600px) { .mse-upd { top: 8px; flex-wrap: wrap; } }

/* v2.5.0 방문 상세 · 업데이트 기록 창 (assets/mapreport.js — 프로젝트 화면 맵 카드). 막대 그래프: 막대 24 px 이하 · 위 끝 4 px 둥글게 ·
   가는 눈금 · 글자는 글자 색(막대 색 아님) · 막대 색 #22a884 = 이 바탕(#0b1218)에서 대비 3:1 넘고 밝기 범위 안 (dataviz 검사) */
dialog.modal.mr-modal { width: min(860px, calc(100vw - 32px)); }
.mr-modal .modal-head h2 { display: inline-flex; align-items: center; gap: 8px; }
.mr-modal .mr-body { max-height: calc(100vh - 170px); }
.mr-sub { margin-bottom: 12px !important; }
.mr-sub-project { color: var(--muted); font-size: 12px; }
.mr-loading, .mr-empty { color: var(--muted); font-size: 13px; }
.mr-rule { display: grid; gap: 6px; margin-bottom: 14px; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; }
.mr-rule-row { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.mr-rule-label { font-size: 13px; font-weight: 600; color: var(--text); }
.mr-rule-select.field { width: auto; min-width: 168px; height: 30px; }
.mr-rule-name { font-size: 13px; color: var(--text); }
.mr-rule-since, .mr-rule-ro { font-size: 12px; color: var(--dim); }
.mr-rule-help { font-size: 12px; line-height: 1.6; color: var(--muted); }
.mr-rule-confirm { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 10px; border: 1px solid #ffc85a55; border-radius: 8px; background: #ffc85a12; color: #ffe9bf; font-size: 12.5px; }
.mr-rule-confirm[hidden] { display: none; }
.mr-rule-confirm > span { flex: 1 1 260px; min-width: 0; }
.mr-tabs { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff06; }
.mr-tab { height: 30px; padding: 0 14px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; cursor: pointer; transition: background-color .2s, color .2s, box-shadow .2s; }
.mr-tab:hover { color: var(--text); background: #ffffff0d; }
.mr-tab.is-on { background: var(--accent-soft); color: #c6fbe9; font-weight: 600; box-shadow: inset 0 0 0 1px #2fd3a866; }
.mr-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.mr-filters { display: flex; align-items: center; gap: 10px 16px; flex-wrap: wrap; }
.mr-who { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); }
.mr-who .field { width: auto; min-width: 180px; }
.mr-panel { margin-top: 14px; }
.mr-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.mr-tile { display: grid; align-content: start; gap: 4px; min-width: 0; padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: #ffffff05; }
.mr-tile.is-main { border-color: #2fd3a84d; background: #2fd3a80d; }
.mr-tile-label { font-size: 12px; color: var(--muted); }
.mr-tile-value { font-size: 22px; font-weight: 600; line-height: 1.25; letter-spacing: -.02em; color: var(--text); overflow-wrap: anywhere; }
.mr-tile-note { font-size: 11.5px; line-height: 1.5; color: var(--dim); overflow-wrap: anywhere; }
.mr-tile.is-text .mr-tile-value { font-size: 15px; line-height: 1.45; letter-spacing: 0; }
.mr-when { white-space: nowrap; font-variant-numeric: tabular-nums; }
.mr-chart { position: relative; height: 236px; margin-top: 14px; border: 1px solid var(--line); border-radius: 10px; background: #0b1218; outline: 2px solid transparent; outline-offset: 1px; transition: outline-color .2s; }
.mr-chart:focus-visible { outline-color: #2fd3a8aa; }
.mr-svg { display: block; overflow: visible; }
.mr-grid { stroke: #ffffff12; stroke-width: 1; shape-rendering: crispEdges; }
.mr-base { stroke: #ffffff2e; stroke-width: 1; shape-rendering: crispEdges; }
.mr-ytick, .mr-xtick { fill: var(--dim); font-size: 11px; font-variant-numeric: tabular-nums; }
.mr-xtick.is-before { fill: #4c5866; }
.mr-before { fill: #ffffff05; }
.mr-before-text { fill: #56626f; font-size: 11px; }
.mr-bar { fill: #22a884; transition: fill .15s; transform-box: fill-box; transform-origin: 50% 100%; }
.mr-bar.is-on { fill: #2fd3a8; }
.mr-bar.is-grow { animation: mr-grow .5s cubic-bezier(.22, .68, .2, 1) var(--mr-delay, 0ms) both; }
@keyframes mr-grow { from { transform: scaleY(0); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .mr-bar.is-grow { animation: none; } }
.mr-maxlabel { fill: var(--text); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.mr-hit { fill: transparent; pointer-events: all; }
.mr-tip { position: absolute; z-index: 2; display: grid; gap: 2px; padding: 7px 10px; border: 1px solid #ffffff24; border-radius: 8px; background: #121b22f2; box-shadow: 0 8px 24px #0008; white-space: nowrap; pointer-events: none; }
.mr-tip[hidden] { display: none; }
.mr-tip strong { font-size: 14px; color: var(--text); font-variant-numeric: tabular-nums; }
.mr-tip span { font-size: 11.5px; color: var(--muted); }
.mr-details { margin-top: 10px; }
.mr-details > summary { width: max-content; font-size: 12.5px; color: var(--muted); cursor: pointer; }
.mr-details > summary:hover { color: var(--text); }
.mr-table-wrap { max-height: 320px; margin-top: 8px; overflow: auto; }
.mr-log-wrap { max-height: 420px; }
.mr-table th.num, .mr-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.mr-table tr.is-before td { color: var(--dim); }
.mr-sec { margin-top: 18px; }
.mr-modal .mr-sec h3 { margin: 0 0 8px; font-size: 14px; }
.mr-log td { vertical-align: top; }
.mr-log td strong { display: block; font-size: 12.5px; font-weight: 600; }
.mr-log-note, .mr-log-dev { display: block; margin-top: 3px; font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.mr-log-dev { color: var(--dim); }
.mr-role { display: block; margin-top: 3px; font-size: 11.5px; color: var(--dim); }
.mr-scope { display: inline-block; padding: 1px 8px; border: 1px solid var(--line); border-radius: 999px; font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.mr-scope.is-project { border-color: #6aa8ff55; background: #6aa8ff12; color: #bcd8ff; }
.mr-more { margin-top: 8px; }
.mr-more[hidden] { display: none; }
.mr-notes { margin-top: 16px; }
.mr-foot { align-items: center; }
/* v2.7.0 업데이트 기록 복구: 줄마다 '복구' 단추 · '지금 판' 표시 · 복구한 맵 띠(최신본으로 되돌리기) · 경고 창 목록 */
.mr-restore-col { width: 1%; white-space: nowrap; }
.mr-restore-cell { white-space: nowrap; text-align: right; }
.mr-restore-btn.btn.small { height: 26px; padding: 0 9px; font-size: 12px; }
.mr-restore-btn.is-disabled, .mr-revert-btn.is-disabled { opacity: .45; cursor: not-allowed; }
.mr-rev.is-current { display: inline-block; padding: 1px 8px; border: 1px solid #2fd3a855; border-radius: 999px; background: #2fd3a812; color: #c6fbe9; font-size: 11.5px; white-space: nowrap; }
.mr-restored { display: grid; gap: 8px; margin-bottom: 14px; }
.mr-restored-row { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; padding: 10px 12px; border: 1px solid #ffc85a55; border-radius: 10px; background: #ffc85a12; }
.mr-restored-text { display: grid; gap: 3px; flex: 1 1 260px; min-width: 0; }
.mr-restored-text strong { font-size: 13px; color: #ffe9bf; overflow-wrap: anywhere; }
.mr-restored-sub { font-size: 12px; line-height: 1.5; color: var(--muted); overflow-wrap: anywhere; }
.mr-revert-btn { flex: 0 0 auto; }
.mr-restore-ask { display: grid; gap: 10px; margin-bottom: 12px; }
.mr-restore-what { margin: 0; font-size: 13.5px; line-height: 1.6; color: var(--text); overflow-wrap: anywhere; }
.mr-warn-list { display: grid; gap: 6px; margin: 0; padding: 10px 12px 10px 28px; border: 1px solid #ffc85a40; border-radius: 10px; background: #ffc85a0d; font-size: 12.5px; line-height: 1.6; color: #f3e3c4; }
.mr-warn-list li::marker { color: #ffc85a; }
@media (max-width: 520px) { .mr-revert-btn { width: 100%; justify-content: center; } }
/* v2.5.1 통합 창: 볼 맵(프로젝트) 고르기 · 맵별(프로젝트별) 표의 몫 막대 */
.mr-pick.field { width: auto; min-width: 200px; max-width: min(360px, 100%); }
.mr-split td { vertical-align: middle; }
.mr-split-note { display: block; margin-top: 2px; font-size: 11.5px; color: var(--dim); }
.mr-share-col { width: 34%; }
.mr-share { display: block; height: 8px; overflow: hidden; border-radius: 4px; background: #ffffff0d; }
.mr-share-bar { display: block; height: 100%; border-radius: 4px; background: #22a884; }
@media (max-width: 760px) { .mr-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); } .mr-tile-value { font-size: 19px; } }
@media (max-width: 420px) { .mr-tab { padding: 0 10px; } }
/* v2.5.1 좁은 화면: 고르기 칸(맵, 프로젝트, 계정)은 줄 폭에 맞춰 줄어듦 — 휴대폰에서 '프로젝트, 맵' 칸이 11 px 넘쳤다 */
@media (max-width: 520px) { .mr-who { display: flex; width: 100%; min-width: 0; } .mr-who .field, .mr-pick.field { flex: 1 1 auto; min-width: 0; max-width: none; } }
