/* MOCA Web Studio(웹 툴) — VS Code 다크 테마 느낌. 확장 웹뷰들은 --vscode-* 변수를 쓰므로 여기서 같은 이름을 정해 준다. */
:root {
	--vscode-font-family: "Pretendard Variable", Pretendard, "Segoe UI", "Malgun Gothic", system-ui, sans-serif;
	--vscode-editor-font-family: Consolas, "D2Coding", "Courier New", monospace;
	--vscode-foreground: #cccccc;
	--vscode-editor-background: #1e1e1e;
	--vscode-sideBar-background: #252526;
	--vscode-activityBar-background: #333333;
	--vscode-titleBar-background: #3c3c3c;
	--vscode-statusBar-background: #007acc;
	--vscode-widget-border: #3c3c3c;
	--vscode-input-background: #3c3c3c;
	--vscode-input-foreground: #cccccc;
	--vscode-input-border: #3c3c3c;
	--vscode-focusBorder: #007fd4;
	--vscode-button-background: #0e639c;
	--vscode-button-foreground: #ffffff;
	--vscode-button-hoverBackground: #1177bb;
	--vscode-button-secondaryBackground: #3a3d41;
	--vscode-button-secondaryForeground: #cccccc;
	--vscode-button-secondaryHoverBackground: #45494e;
	--vscode-list-hoverBackground: #2a2d2e;
	--vscode-list-activeSelectionBackground: #094771;
	--vscode-list-activeSelectionForeground: #ffffff;
	--vscode-dropdown-background: #3c3c3c;
	--vscode-dropdown-foreground: #f0f0f0;
	--vscode-errorForeground: #f48771;
	--vscode-charts-blue: #4a8fd6;
	--vscode-charts-orange: #d19a66;
	--vscode-editorWidget-background: #252526;
	--vscode-panel-border: #3c3c3c;
	--vscode-descriptionForeground: #9d9d9d;
	--vscode-textLink-foreground: #3794ff;
	--vscode-badge-background: #4d4d4d;
	--vscode-badge-foreground: #ffffff;
	/* ── 팝업 표준색 — 떠 있는 것은 **밝게**, 뒤는 **확실히 어둡게**. 팝업마다 색을 따로 정하지 않는다(2026-09-17 표준) ── */
	--m-pop-bg: #34373d;                          /* 본문(#1e1e1e)·패널(#252526)보다 한 단 밝다 — 떠 있음이 색으로 보인다 */
	--m-pop-bd: #6a707b;                          /* 테두리도 또렷하게 */
	--m-pop-sd: 0 18px 50px rgba(0,0,0,.75);      /* 그림자로 높이를 준다 */
	--m-pop-in: #212327;                          /* 팝업 안 입력칸 — 팝업보다 어두워야 칸으로 보인다 */
	--m-scrim: rgba(0,0,0,.74);                   /* 딤은 팝업과 헷갈리지 않을 만큼 어둡게 */
}
html, body { height: 100%; margin: 0; }
body { font-family: var(--vscode-font-family); font-size: 13px; color: var(--vscode-foreground); background: var(--vscode-editor-background); overflow: hidden; }
.studio { display: flex; flex-direction: column; height: 100vh; }
.grow { flex: 1; }
.dim { opacity: .6; }
button.tb { font: inherit; font-size: 12px; background: transparent; color: var(--vscode-foreground); border: 1px solid transparent; border-radius: 3px; padding: 3px 9px; cursor: pointer; }
button.tb:hover { background: rgba(255,255,255,.08); }
button.tb.pri { background: var(--vscode-button-background); color: var(--vscode-button-foreground); }
button.tb.pri:hover { background: var(--vscode-button-hoverBackground); }
button.ic { font: inherit; background: transparent; color: var(--vscode-foreground); border: none; cursor: pointer; opacity: .7; padding: 0 5px; }
button.ic:hover { opacity: 1; background: rgba(255,255,255,.1); border-radius: 3px; }
.sep { width: 1px; height: 16px; background: rgba(255,255,255,.2); margin: 0 6px; }
/* GitHub 로그인 버튼 — 아바타 + 로그인명 + 상태 알약(승인 대기·차단) */
button.tb.user { display: inline-flex; align-items: center; gap: 6px; }
button.tb.user.on { border-color: rgba(255,255,255,.15); }
button.tb.user img { width: 16px; height: 16px; border-radius: 50%; }
.pill { font-size: 10px; line-height: 14px; padding: 0 6px; border-radius: 8px; color: #fff; }
.pill.wait { background: #9a6700; }
.pill.bad { background: #a1260d; }
.dlg input.filter { margin-bottom: 6px; }
/* 시작 화면(게이트) — 로그인·승인 안내를 전면에. 뒤의 IDE 는 흐리게 비친다 */
.gate { position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; background: rgba(20,20,22,.94); backdrop-filter: blur(3px); }
.gate[hidden] { display: none; }
.gate-card { width: 460px; max-width: 92vw; background: var(--m-pop-bg); border: 1px solid var(--m-pop-bd); border-radius: 8px; padding: 28px 30px 24px; box-shadow: var(--m-pop-sd); }
.gate-card .brand-big { text-align: left; margin-bottom: 4px; color: rgba(255,255,255,.7); font-size: 22px; }
.gate-card h2 { margin: 6px 0 10px; font-size: 18px; font-weight: 600; color: #fff; }
.gate-card p { margin: 0 0 10px; line-height: 1.65; color: rgba(255,255,255,.78); font-size: 13px; }
.gate-card .who { display: flex; align-items: center; gap: 10px; margin: 10px 0 14px; padding: 10px 12px; background: rgba(255,255,255,.05); border-radius: 6px; }
.gate-card .who img { width: 36px; height: 36px; border-radius: 50%; }
.gate-card .who .nm { font-weight: 600; color: #fff; }
.gate-card .who .st { font-size: 12px; opacity: .75; }
.gate-card .actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.gate-card .actions button.tb { padding: 9px 14px; font-size: 13.5px; border: 1px solid rgba(255,255,255,.14); text-align: left; }
.gate-card .actions button.tb.pri { border-color: transparent; }
.gate-card .actions button.tb small { display: block; font-size: 11.5px; opacity: .7; font-weight: 400; margin-top: 2px; }
.gate-card .foot { display: flex; gap: 12px; justify-content: space-between; align-items: center; margin-top: 16px; font-size: 12px; }
.gate-card .foot a, .gate-card .foot button.lnk { background: none; border: none; padding: 0; color: var(--vscode-textLink-foreground); cursor: pointer; font: inherit; font-size: 12px; text-decoration: none; }
.gate-card .foot a:hover, .gate-card .foot button.lnk:hover { text-decoration: underline; }
.gate-card .steps { display: flex; gap: 6px; margin: 4px 0 8px; font-size: 11.5px; }
.gate-card .steps span { flex: 1; padding: 6px 8px; border-radius: 4px; background: rgba(255,255,255,.05); color: rgba(255,255,255,.6); text-align: center; }
.gate-card .steps span.on { background: var(--vscode-button-background); color: #fff; }
.gate-card .steps span.done { color: #8fd18f; }

/* 여러 칸 입력(프로필) */
.dlg .frow { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
/* 줄 숨김 — display:flex 가 브라우저 기본 [hidden]{display:none} 을 이겨서, hidden 을 줘도 줄이 그대로 보였다
   (모델을 Sonnet 으로 골라도 Ollama 줄이 남던 증상 · 2026-09-19). 숨길 수 있는 줄에는 규칙을 따로 준다. */
.dlg .frow[hidden] { display: none; }
.dlg .frow .fl { flex: 0 0 64px; font-size: 12px; opacity: .8; }
.dlg .frow input[type=text] { flex: 1; width: auto; }

/* 제목줄 */
.titlebar { display: flex; align-items: center; gap: 4px; height: 34px; padding: 0 8px 0 10px; background: var(--vscode-titleBar-background); font-size: 12.5px; }
.titlebar .brand { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; margin-right: 10px; }
.titlebar .brand img { width: 22px; height: 22px; border-radius: 5px; }   /* 배지(흰 바탕 + 검정 블링이) — 투명 실루엣은 작은 크기에서 묻혔다(2026-09-17 지시) */
.titlebar .ws { opacity: .8; max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 본문 */
.main { display: flex; flex: 1; min-height: 0; }
.activity { width: 44px; background: var(--vscode-activityBar-background); display: flex; flex-direction: column; align-items: center; padding-top: 4px; gap: 2px; }
.activity .act { width: 40px; height: 40px; border: none; background: transparent; color: rgba(255,255,255,.5); font-size: 18px; cursor: pointer; border-left: 2px solid transparent; text-decoration: none; display: flex; align-items: center; justify-content: center; }
.activity .act.on { color: #fff; border-left-color: #fff; }
/* 아이콘 크기는 여기서 준다 — <svg> 에 width/height 속성이 없으면 브라우저 기본(300x150)으로 커진다 */
.activity .act > svg { width: 20px; height: 20px; flex: 0 0 auto; }
/* 접기/펴기(위)와 작업 버튼(새 화면·AI 화면·실행)을 가르는 줄 — 하는 일이 달라 붙여 두면 같은 무리로 보인다 */
.activity .act-sep { width: 22px; height: 0; margin: 5px 0; border-top: 1px solid rgba(255,255,255,.18); flex: 0 0 auto; }
.activity .act:hover { color: #fff; }
/* 화살표 아이콘 — 한 모양(‹)을 돌려서 세 자리에 쓴다(2026-09-18 지시).
   펴져 있으면 「이쪽으로 접힌다」, 접혀 있으면 「이쪽으로 펴진다」를 가리킨다 — .on 은 relayout 이 붙인다. */
.activity .act .chev { width: 20px; height: 20px; transition: transform .16s ease; }
.activity .act[data-side="left"] .chev { transform: rotate(0deg); }        /* 펴짐: ‹ 눌러 왼쪽으로 접는다 */
.activity .act[data-side="left"]:not(.on) .chev { transform: rotate(180deg); }   /* 접힘: › */
.activity .act[data-side="right"] .chev { transform: rotate(180deg); }     /* 펴짐: › */
.activity .act[data-side="right"]:not(.on) .chev { transform: rotate(0deg); }    /* 접힘: ‹ */
.activity .act[data-bottom] .chev { transform: rotate(-90deg); }           /* 펴짐: ⌄ */
.activity .act[data-bottom]:not(.on) .chev { transform: rotate(90deg); }   /* 접힘: ⌃ */
.side { width: 280px; min-width: 160px; max-width: 50vw; flex: 0 0 auto; background: var(--vscode-sideBar-background); display: flex; flex-direction: column; overflow: hidden; border-right: 1px solid var(--vscode-widget-border); }
.side.right { border-right: none; border-left: 1px solid var(--vscode-widget-border); width: 330px; }
.side[hidden] { display: none; }
/* 섹션 — 제목줄은 진한 띠(위 경계선 + 살짝 밝은 배경 + 아래 그림자)로 뷰 사이 경계를 분명히 한다(뷰들이 한 덩어리로 섞여 보이던 문제). */
.sec { display: flex; flex-direction: column; min-height: 30px; }
.sec.open { flex: 1; min-height: 120px; }
.sec-h { margin: 0; height: 30px; box-sizing: border-box; font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: #e6e6e6;
	padding: 0 8px; cursor: pointer; user-select: none; display: flex; align-items: center; gap: 5px; flex: 0 0 30px;
	background: #303031; border-top: 1px solid rgba(255,255,255,.14); border-bottom: 1px solid rgba(0,0,0,.45); box-shadow: 0 2px 4px rgba(0,0,0,.28); position: relative; z-index: 1; }
.sec-h:hover { background: #38383a; }
.sec-h .tw { display: inline-block; width: 12px; font-size: 10px; transition: transform .12s; opacity: .85; }
.sec:not(.open) .sec-h .tw { transform: rotate(-90deg); }
.sec-sub { font-weight: 400; text-transform: none; opacity: .6; margin-left: 4px; }
/* 제목줄 오른쪽 단추(모두 접기·펼치기) — 제목줄을 누르면 섹션이 접히므로 클릭은 단추가 가로챈다 */
.sec-acts { margin-left: auto; display: flex; gap: 2px; }
.sec-act { width: 22px; height: 22px; padding: 0; line-height: 1; font: inherit; font-size: 12px; cursor: pointer;
	background: transparent; color: #e6e6e6; border: 1px solid transparent; border-radius: 4px; opacity: .75; }
.sec-act:hover { background: rgba(255,255,255,.12); border-color: var(--m-pop-bd); opacity: 1; }
.sec-b { flex: 1; min-height: 0; overflow: auto; background: var(--vscode-sideBar-background); }
.sec:not(.open) .sec-b { display: none; }
.view-host { display: flex; padding-top: 2px; }
.view-host iframe { flex: 1; border: none; width: 100%; height: 100%; min-height: 120px; background: transparent; }

/* 탐색기 */
/* 도구 줄(검색 / 모두 커밋·목록 비우기)은 **스크롤에 묻히면 안 된다** —
   파일이 많아 목록을 내리면 버튼이 위로 사라져 "기능이 없는 줄 알았다" 가 된다(2026-09-20 지적).
   sticky 로는 모자랐다: 트리는 긴 경로 때문에 가로로도 넓은데(.ftree min-width:max-content)
   스크롤 컨테이너가 몸통(.sec-b)이면 **가로로 밀 때 도구줄이 같이 밀려** 검색칸이 잘린다
   (sticky top 은 세로만 잡는다 — 2026-09-20 지적). 그래서 스크롤을 안쪽 목록으로 내리고
   몸통은 세로로 쌓기만 한다. 도구줄은 스크롤 밖이라 언제나 제자리다. */
#explorer, #changed { display: flex; flex-direction: column; overflow: hidden; }
#explorer > .ex-tree, #changed > .chg-list { flex: 1 1 auto; min-height: 0; overflow: auto; }
.ex-tools { display: flex; flex-wrap: wrap; gap: 4px; padding: 4px 6px; align-items: center;
	flex: 0 0 auto; background: var(--vscode-sideBar-background);
	border-bottom: 1px solid var(--vscode-widget-border, rgba(255,255,255,.08)); }
.ex-tools input { flex: 1 1 8em; min-width: 7em; font: inherit; font-size: 12px; padding: 2px 6px; background: var(--vscode-input-background); color: var(--vscode-input-foreground); border: 1px solid var(--vscode-input-border); border-radius: 2px; outline: none; }
.ex-tools input:focus { border-color: var(--vscode-focusBorder); }
.ftree { list-style: none; margin: 0; padding: 0 0 8px; font-size: 12.5px; }
.ftree li { white-space: nowrap; }
/* 폭이 좁아도 이름을 자르지 않는다 — 줄을 내용만큼 늘여 두고(min-width:100% 로 선택 바탕은 끝까지) 넘치는 만큼 가로로 굴린다(2026-09-18 지시) */
.ftree .row { display: flex; align-items: center; gap: 4px; padding: 2px 6px; cursor: pointer; width: max-content; min-width: 100%; box-sizing: border-box; }
.ftree .row:hover { background: var(--vscode-list-hoverBackground); }
.ftree .row.on { background: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); }
.ftree .row .ic { width: 14px; text-align: center; opacity: .8; font-size: 11px; }
/* 폴더의 펼침표(▸·▾)는 11px 로는 안 보였다(2026-09-17 지시) — 글자 크기를 따라 크게 키우고 또렷하게 */
.ftree .row.dir .ic { width: auto; min-width: 0; font-size: calc(var(--m-view-font) + 6px); line-height: 1; opacity: 1; }
.ftree .row.dir { gap: 1px; }   /* 펼침표는 이름 바로 앞에 붙인다 — 떨어져 있으면 어느 줄 것인지 애매하다 */
.ftree .row .nm { flex: 0 0 auto; }
.ftree .row .nm.moca { color: #c5e1a5; }
.ftree ul { list-style: none; margin: 0; padding-left: 12px; }
.ftree, .ftree ul, .ftree li { min-width: max-content; }   /* 들여쓴 하위 줄까지 스크롤 폭에 잡히게 */
.ftree li.closed > ul { display: none; }
.ftree .dirty::after { content: ' ●'; color: #e2c08d; font-size: 9px; }

/* Outline 트리뷰(호스트가 그린다) */
.vtree { list-style: none; margin: 0; padding: 2px 0 8px; font-size: 12.5px; }
.vtree ul { list-style: none; margin: 0; padding-left: 14px; }
.vtree .row { display: flex; align-items: center; gap: 5px; padding: 2px 6px; cursor: pointer; white-space: nowrap; }
.vtree .row:hover { background: var(--vscode-list-hoverBackground); }
.vtree .row.sel { background: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); }
.vtree .row.drop { outline: 1px dashed var(--vscode-focusBorder); outline-offset: -1px; }
/* 바탕색은 **선택**만 쓴다 — 골격은 글자색으로만 구분한다(2026-09-17 지시). 바탕이 여럿이면 무엇을 짚었는지가 묻힌다 */
.vtree .row[data-ico="symbol-namespace"] { color: #6fc0ff; font-weight: 700; }
.vtree .row[data-ico="symbol-namespace"] > .icon { color: #6fc0ff; }
.vtree .row[data-ico="symbol-key"] { color: #9ab0c6; }
.vtree .row[data-ico="symbol-key"] > .icon { color: #9ab0c6; }
/* 선택·마우스오버는 위 색을 덮는다 — 지금 무엇을 짚었는지가 먼저다 */
.vtree .row[data-ico]:hover { background: var(--vscode-list-hoverBackground); }
.vtree .row[data-ico].sel { background: var(--vscode-list-activeSelectionBackground); color: var(--vscode-list-activeSelectionForeground); }
.vtree .row[data-ico].sel > .icon { color: inherit; }   /* 선택한 행에서는 아이콘도 글자색을 따른다 */
.vtree .tw { width: 12px; font-size: 10px; opacity: .7; }
.vtree .icon { width: 14px; text-align: center; font-size: 11px; opacity: .8; }
.vtree .desc { opacity: .55; font-size: 11px; margin-left: 4px; }
.vtree li.closed > ul { display: none; }
.vtree-drop { min-height: 24px; }

/* 드래그 손잡이(sash) — 사이드바·디자인뷰·출력 패널·섹션 사이. 폭은 4px 이고 hover/드래그 중에만 색이 난다(VS Code 식) */
.sash { flex: 0 0 4px; background: transparent; position: relative; z-index: 3; transition: background .12s; }
.sash.v { cursor: col-resize; }
.sash.h { cursor: row-resize; height: 4px; flex-basis: 4px; width: 100%; }
.sash:hover, .sash.on { background: var(--vscode-focusBorder); }
.sash[hidden] { display: none; }
.side[hidden] + .sash, .sash:has(+ .design-pane[hidden]) { display: none; }
/* 드래그 중에는 iframe(Monaco·웹뷰)이 포인터를 삼키지 않게 */
body.sashing, body.sashing * { user-select: none !important; }
body.sashing iframe { pointer-events: none !important; }
body.sashing.v { cursor: col-resize; }
body.sashing.h { cursor: row-resize; }
/* 사이드바 안 섹션 사이 손잡이 — 평소엔 다음 섹션 제목줄의 경계선과 겹치는 1px 선, 잡으면 4px 강조 */
.side .sash.h { margin: 0; flex-basis: 3px; height: 3px; background: #1f1f1f; }
.side .sash.h:hover, .side .sash.h.on { background: var(--vscode-focusBorder); }

/* 편집기 — 현재 커서가 든 MOCA 컴포넌트의 여는 태그만 강조(구조별 색은 스튜디오에서 끔) */
.moca-cur { background: #264f78; border-radius: 2px; }   /* 체험 페이지의 선택 강조와 같은 파란 띠(2026-09-11 "이정도 컬러 좋음") */

/* 편집기 */
.editor-area { flex: 1; min-width: 200px; display: flex; flex-direction: column; min-height: 0; }
.tabs { display: flex; height: 35px; background: #252526; overflow-x: auto; overflow-y: hidden; }
.tabs .tab { display: inline-flex; align-items: center; gap: 6px; padding: 0 10px; font-size: 12.5px; color: rgba(255,255,255,.6); background: #2d2d2d; border-right: 1px solid #252526; cursor: pointer; white-space: nowrap; }
.tabs .tab.on { background: var(--vscode-editor-background); color: #fff; }
.tabs .tab .x { opacity: .5; font-size: 12px; padding: 0 2px; border-radius: 3px; }
.tabs .tab .x:hover { opacity: 1; background: rgba(255,255,255,.15); }
.tabs .tab.dirty .x::before { content: '●'; font-size: 9px; color: #e2c08d; }
.tabs .tab:not(.dirty) .x::before { content: '✕'; }
.crumb { height: 22px; line-height: 22px; padding: 0 12px; font-size: 11.5px; opacity: .7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.editor-wrap { flex: 1; position: relative; min-height: 0; }
#monaco { position: absolute; inset: 0; }
.editor-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; color: rgba(255,255,255,.55); line-height: 1.7; }
.editor-empty[hidden] { display: none; }
.brand-big { font-size: 28px; font-weight: 700; letter-spacing: .04em; color: rgba(255,255,255,.35); margin-bottom: 8px; }

/* 디자인뷰 분할창 */
.design-pane { width: 40%; min-width: 240px; flex: 0 0 auto; display: flex; flex-direction: column; border-left: 1px solid var(--vscode-widget-border); background: var(--vscode-editor-background); }
.design-pane[hidden] { display: none; }
/* 디자인뷰 제목줄은 쓰지 않는다 — 웹뷰 자체 도구줄(골격·디자인·렌더링·선택·뷰포트)이 편집기 탭 줄과 같은 높이에 바로 온다(2026-09-11 지시: 우측 상단 빈 줄과 합침). 닫기는 제목줄 「디자인뷰」 버튼 토글 */
.pane-h { display: none; }
button.tb.on { background: rgba(255,255,255,.12); }
.design-pane iframe { flex: 1; border: none; width: 100%; background: #1e1e1e; }

/* 뷰 배치 — 제목줄을 끌어 사이드바·아래 패널로. 끌기 중엔 iframe 이 포인터를 삼키지 않게, 놓을 자리는 파란 선/점선으로 */
.sec-h[draggable=true] { cursor: pointer; }
.sec-h[draggable=true]:active { cursor: grabbing; }
body.secdrag iframe { pointer-events: none !important; }
body.secdrag .side, body.secdrag .bottom-body { outline: 1px dashed rgba(255,255,255,.12); outline-offset: -1px; }
.side.drop-into, .bottom-body.drop-into { outline: 2px dashed var(--vscode-focusBorder) !important; outline-offset: -2px; }
.side > .sec.drop-before { box-shadow: inset 0 3px 0 var(--vscode-focusBorder); }
.side > .sec.drop-after { box-shadow: inset 0 -3px 0 var(--vscode-focusBorder); }
.bottom-body > .sec.drop-before { box-shadow: inset 3px 0 0 var(--vscode-focusBorder); }
.bottom-body > .sec.drop-after { box-shadow: inset -3px 0 0 var(--vscode-focusBorder); }
.side.none::before { content: '뷰를 여기에 끌어다 놓으세요'; display: block; padding: 24px 10px; text-align: center; font-size: 12px; opacity: .45; }
.bottom { height: 260px; display: flex; flex-direction: column; border-top: 1px solid var(--vscode-widget-border); background: var(--vscode-sideBar-background); }
.bottom[hidden] { display: none; }
.bottom-body { flex: 1; display: flex; min-height: 0; }
.bottom-body > .sec { flex: 1 1 0; min-width: 160px; min-height: 0; border-right: 1px solid rgba(255,255,255,.06); }
.bottom-body > .sec.open { min-height: 0; }
.bottom-body > .sec:last-of-type { border-right: none; }
.bottom-body > .sash.v { flex: 0 0 3px; background: #1f1f1f; }
.bottom-body > .sash.v:hover, .bottom-body > .sash.v.on { background: var(--vscode-focusBorder); }
.bottom-body:empty::before { content: '뷰 제목줄을 여기에 놓으면 아래 패널에 나란히 배치됩니다'; display: flex; align-items: center; justify-content: center; flex: 1; font-size: 12px; opacity: .5; }

/* 출력 패널 */
.panel { height: 180px; display: flex; flex-direction: column; border-top: 1px solid var(--vscode-panel-border); background: var(--vscode-editor-background); }
.panel[hidden] { display: none; }
.panel-h { display: flex; align-items: center; gap: 8px; height: 30px; padding: 0 10px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.panel-h select { font: inherit; font-size: 11px; background: var(--vscode-dropdown-background); color: var(--vscode-dropdown-foreground); border: 1px solid var(--vscode-widget-border); }
.panel-b { flex: 1; margin: 0; padding: 4px 10px; overflow: auto; font-family: var(--vscode-editor-font-family); font-size: 12px; white-space: pre-wrap; }

/* 상태줄 */
.status { display: flex; align-items: center; gap: 14px; height: 22px; padding: 0 10px; background: var(--vscode-statusBar-background); color: #fff; font-size: 12px; }
.status .dim { opacity: .85; }

/* 대화상자·토스트 */
.modal { position: fixed; inset: 0; background: var(--m-scrim); display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; z-index: 50; }
.modal[hidden] { display: none; }
.dlg { width: min(560px, 92vw); background: var(--m-pop-bg); border: 1px solid var(--m-pop-bd); border-radius: 6px; box-shadow: var(--m-pop-sd); padding: 12px 14px; }
.dlg h4 { margin: 0 0 8px; font-size: 13px; font-weight: 600; }
.dlg p { margin: 0 0 8px; font-size: 12.5px; line-height: 1.5; opacity: .9; }
.dlg input[type=text], .dlg input[type=password] { box-sizing: border-box; width: 100%; font: inherit; font-size: 13px; padding: 5px 8px; background: var(--m-pop-in); color: var(--vscode-input-foreground); border: 1px solid var(--vscode-input-border); border-radius: 2px; outline: none; margin-bottom: 6px; }
.dlg input:focus { border-color: var(--vscode-focusBorder); }
.dlg .err { color: var(--vscode-errorForeground); font-size: 12px; min-height: 16px; }
.dlg .btns { display: flex; gap: 6px; justify-content: flex-end; margin-top: 8px; }
.dlg .list { max-height: 50vh; overflow: auto; border: 1px solid var(--vscode-widget-border); border-radius: 3px; }
.dlg .item { padding: 6px 10px; cursor: pointer; display: flex; gap: 10px; align-items: baseline; }
.dlg .item:hover, .dlg .item.on { background: var(--vscode-list-activeSelectionBackground); color: #fff; }
.dlg .item .d { opacity: .6; font-size: 12px; }
.dlg label { display: block; font-size: 12px; opacity: .8; margin: 6px 0 3px; }
.dlg .hint { font-size: 11.5px; opacity: .6; line-height: 1.5; }
.toasts { position: fixed; right: 14px; bottom: 34px; display: flex; flex-direction: column; gap: 6px; z-index: 60; }
.toast { background: var(--m-pop-bg); border: 1px solid var(--m-pop-bd); border-left: 3px solid var(--vscode-charts-blue); padding: 8px 12px; border-radius: 4px; font-size: 12.5px; max-width: 420px; box-shadow: 0 4px 16px rgba(0,0,0,.4); }
.toast.warn { border-left-color: var(--vscode-charts-orange); }
.toast.error { border-left-color: var(--vscode-errorForeground); }

/* 구조 색 표시(decorations.js) — 타입별 클래스는 스크립트가 만든다 */
.moca-deco { border-left: 3px solid transparent; }

/* ── 모바일(폰 폭 900px 미만) — 하단 탭 바로 한 번에 한 화면(A안, 2026-09-17 지시) ──
   body.mobile + body[data-mtab] 는 studio.js applyMobile/setMTab 이 붙인다. 탐색기·Outline·소스·디자인·속성·데이터셋·트랜잭션·팔레트 중 하나만 보이고
   활동바·손잡이·제목줄 버튼은 숨긴다(제목줄 버튼은 「더보기」 시트가 대신 누른다). 데스크톱 배치는 손대지 않는다. */
.mtabs, #btnMore { display: none; }
.sheet { position: fixed; inset: 0; z-index: 55; }
.sheet[hidden] { display: none; }
.sheet-scrim { position: absolute; inset: 0; background: var(--m-scrim); }
.sheet-card { position: absolute; left: 0; right: 0; bottom: 0; background: var(--m-pop-bg); border-top: 1px solid var(--m-pop-bd); border-radius: 12px 12px 0 0; padding: 4px 10px calc(12px + env(safe-area-inset-bottom)); box-shadow: var(--m-pop-sd); display: flex; flex-direction: column; gap: 2px; }
/* 시트가 화면보다 길어지면(글자 크기를 키운 폰) 그리기도 바깥도 손이 닿지 않았다 — 높이를 묶고
   넘치는 항목은 시트 안에서 굴린다. 폰 폭에서는 아래 media 가 화면 전체로 키운다(2026-09-18 지시) */
.sheet-card { max-height: 86vh; max-height: 86dvh; overflow-y: auto; overscroll-behavior: contain; }
.sheet-grip { width: 44px; height: 5px; border-radius: 3px; background: rgba(255,255,255,.28); margin: 6px auto 10px; cursor: pointer; flex: 0 0 auto; }
.sheet .sh { display: block; flex: 0 0 auto; min-height: 48px; box-sizing: border-box; padding: 8px 12px; font: inherit; font-size: 14px; line-height: 1.35; color: var(--vscode-foreground); background: transparent; border: none; border-radius: 6px; text-align: left; text-decoration: none; cursor: pointer; }
.sheet .sh:hover, .sheet .sh:active { background: rgba(255,255,255,.08); }
.sheet .sh small { display: block; font-size: .72em; line-height: 1.3; margin-top: 2px; opacity: .55; }
/* 맨 아래 [닫기] — 굴러도 늘 보이게 시트 바닥에 붙여 둔다 */
.sheet .sh.close { position: sticky; bottom: -4px; margin-top: 4px; text-align: center; font-weight: 600;
	background: var(--vscode-editorWidget-background, #252526); border-top: 1px solid var(--vscode-widget-border, #3c3c3c); border-radius: 0 0 6px 6px; }
.sheet .sh[hidden] { display: none; }
@media (max-width: 899px) {
	.studio { height: 100vh; height: 100dvh; }
	.titlebar { height: 48px; padding: 0 4px 0 12px; }
	.titlebar .brand { font-size: 14px; }
	.titlebar .ws, .titlebar .sep, #btnGithub, #btnLocal, #btnSample, #btnDesign, #btnSave, #btnPanel, #btnReset { display: none !important; }
	#btnMore { display: flex; width: 44px; height: 44px; padding: 0; align-items: center; justify-content: center; }
	button.tb.user { height: 36px; border-radius: 18px; }
	button.tb.user span:not(.pill) { display: none; }   /* 아바타만 — 이름은 시트에 */
	.activity, .sash { display: none !important; }
	.main > .side, .main > .editor-area, .main > .design-pane { display: none !important; }
	/* 뷰 탭(탐색기·Outline·속성·데이터셋·트랜잭션·팔레트 — 뷰마다 독립 탭, 2026-09-17 지시): 탭 id = 섹션 data-sec.
	   그 섹션이 든 컨테이너(왼쪽·오른쪽 사이드바 또는 아래 패널)만 보이고 그 안의 다른 섹션은 숨긴다 — 데스크톱에서 뷰를 어디로 옮겨 놨든 따라간다 */
	body[data-mtab="explorer"] .side:has(> .sec[data-sec="explorer"]),
	body[data-mtab="outline"] .side:has(> .sec[data-sec="outline"]),
	body[data-mtab="mocaProps"] .side:has(> .sec[data-sec="mocaProps"]),
	body[data-mtab="mocaDataset"] .side:has(> .sec[data-sec="mocaDataset"]),
	body[data-mtab="mocaTransaction"] .side:has(> .sec[data-sec="mocaTransaction"]),
	body[data-mtab="mocaPalette"] .side:has(> .sec[data-sec="mocaPalette"]) { display: flex !important; width: auto !important; max-width: none; min-width: 0; flex: 1 1 auto; border: none; }
	body[data-mtab="explorer"] .bottom:has(.sec[data-sec="explorer"]),
	body[data-mtab="outline"] .bottom:has(.sec[data-sec="outline"]),
	body[data-mtab="mocaProps"] .bottom:has(.sec[data-sec="mocaProps"]),
	body[data-mtab="mocaDataset"] .bottom:has(.sec[data-sec="mocaDataset"]),
	body[data-mtab="mocaTransaction"] .bottom:has(.sec[data-sec="mocaTransaction"]),
	body[data-mtab="mocaPalette"] .bottom:has(.sec[data-sec="mocaPalette"]) { display: flex !important; height: auto !important; flex: 1 1 auto; border-top: none; }
	body[data-mtab="explorer"] .main:not(:has(.sec[data-sec="explorer"])),
	body[data-mtab="outline"] .main:not(:has(.sec[data-sec="outline"])),
	body[data-mtab="mocaProps"] .main:not(:has(.sec[data-sec="mocaProps"])),
	body[data-mtab="mocaDataset"] .main:not(:has(.sec[data-sec="mocaDataset"])),
	body[data-mtab="mocaTransaction"] .main:not(:has(.sec[data-sec="mocaTransaction"])),
	body[data-mtab="mocaPalette"] .main:not(:has(.sec[data-sec="mocaPalette"])) { display: none; }   /* 뷰가 아래 패널에 있으면 .main 은 비워 아래 패널이 전부 차지한다 */
	body[data-mtab="explorer"] .sec:not([data-sec="explorer"]) { display: none !important; }
	body[data-mtab="outline"] .sec:not([data-sec="outline"]) { display: none !important; }
	body[data-mtab="mocaProps"] .sec:not([data-sec="mocaProps"]) { display: none !important; }
	body[data-mtab="mocaDataset"] .sec:not([data-sec="mocaDataset"]) { display: none !important; }
	body[data-mtab="mocaTransaction"] .sec:not([data-sec="mocaTransaction"]) { display: none !important; }
	body[data-mtab="mocaPalette"] .sec:not([data-sec="mocaPalette"]) { display: none !important; }
	body.mobile .sec.open { flex: 1 1 auto !important; }   /* 데스크톱에서 끌어 둔 px 높이는 폰에서 무시 */
	body[data-mtab="source"] .editor-area { display: flex !important; }
	body[data-mtab="design"] .design-pane:not([hidden]) { display: flex !important; width: auto !important; min-width: 0; flex: 1 1 auto; border: none; }
	.bottom { display: none !important; }
	.panel { height: 40vh !important; }
	.sec-h { height: 36px; flex-basis: 36px; padding: 0 12px; }
	.ftree .row, .vtree .row { min-height: 32px; box-sizing: border-box; font-size: var(--m-view-font); }   /* 글자 크기 슬라이더를 따라간다 — 고정값을 두면 폰에서만 안 커진다(실사고) */
	.ex-tools input { height: 34px; font-size: 14px; }
	.tabs { height: 40px; }
	.tabs .tab { padding: 0 14px; font-size: 13px; }
	.status { gap: 10px; }
	.status span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
	#stWs, #stCatalog { display: none; }
	.mtabs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); grid-auto-rows: 50px; padding-bottom: env(safe-area-inset-bottom); background: var(--vscode-activityBar-background); border-top: 1px solid var(--vscode-widget-border); flex: 0 0 auto; }
	.mtabs .mt { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; font: inherit; font-size: 10.5px; color: rgba(255,255,255,.55); background: transparent; border: none; border-top: 2px solid transparent; margin-top: -1px; padding: 0; cursor: pointer; }
	.mtabs .mt.on { color: #fff; border-top-color: #fff; background: rgba(255,255,255,.06); }
	.mtabs .mt svg { width: 22px; height: 22px; }
	.mtabs .mt.mt-act { color: rgba(140,205,255,.9); }   /* 작업 탭은 뷰 탭과 구별되게 — 누르면 뷰가 바뀌는 게 아니라 일이 시작된다 */
	.toasts { left: 10px; right: 10px; bottom: 90px; }
	.toast { max-width: none; }
	.modal { padding-top: 6vh; }
	/* 아래 패널은 폰에서 세로 방향 — 탭이 고른 섹션 하나만 보이므로 나란히 놓일 일이 없다 */
	.bottom-body { flex-direction: column; }
	.bottom-body > .sec { border-right: none; min-width: 0; }
	.bottom-body > .sec:not(.open) { flex: 0 0 36px !important; }   /* 접힌 뷰는 제목줄만 */
	#stFile { direction: rtl; text-align: left; }   /* 긴 경로는 앞을 자르고 파일명이 보이게 */
	.gate-card { padding: 22px 18px 18px; }
}

/* 폰용 가벼운 편집기(textarea) — 일부 모바일 자판에서 Monaco 가 입력을 못 받아 둔 대체 편집기(studio.js plain).
   편집기 자리를 그대로 덮는다. 자동 대문자·맞춤법은 끄고(코드다), 글꼴은 편집기와 같은 고정폭. */
.plain-editor { position: absolute; inset: 0; z-index: 2; box-sizing: border-box; width: 100%; height: 100%;
	margin: 0; padding: 8px 10px; border: none; outline: none; resize: none; white-space: pre; overflow: auto;
	background: var(--vscode-editor-background); color: var(--vscode-foreground);
	font-family: var(--vscode-editor-font-family); font-size: 13px; line-height: 1.5; tab-size: 4; }
.plain-editor[hidden] { display: none; }
/* 폰 편집기를 쓸 때는 Monaco 를 아예 감춘다 — 줄 표시 띠를 편집기 뒤에 깔려면 textarea 가 투명해야 하고,
   그러면 뒤의 Monaco 글자가 비쳐 두 겹으로 보인다. 배경은 편집기 칸이 맡는다. */
.studio.plain .editor-wrap { background: var(--vscode-editor-background); }
.studio.plain #monaco { display: none; }
.studio.plain .plain-editor { background: transparent; }

/* 폰 편집기의 현재 줄 표시 — textarea 는 장식을 못 달고 포커스가 없으면 선택도 안 보여서, 줄 띠로 알려 준다.
   글자를 가리지 않게 편집기 **뒤**에 깔고(z-index), 포인터는 통과시킨다. */
.plain-mark { position: absolute; left: 0; right: 0; z-index: 1; pointer-events: none; background: #264f78; opacity: .55; }
.plain-mark[hidden] { display: none; }
/* 폰 편집기의 자동완성 — 목록 대신 **한 줄 칩**을 편집기 바닥에 둔다(자판의 추천 줄과 같은 자리라 손가락이 닿기 쉽다).
   자판에 가리지 않는 것은 viewport 의 interactive-widget=resizes-content 덕이고, 그 값을 모르는 브라우저는
   studio.js 가 가린 높이만큼 **transform 으로** 올린다 — bottom 을 건드리면 top 과 겹쳐 칩 줄이 세로로 늘어난다(실사고). */
.plain-suggest { position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; display: flex; gap: 6px; align-items: center;
	padding: 5px 8px; overflow-x: auto; overflow-y: hidden; white-space: nowrap; scrollbar-width: none;
	background: #2a2d2e; border-top: 1px solid rgba(255,255,255,.14); box-shadow: 0 -4px 12px rgba(0,0,0,.45); }
.plain-suggest[hidden] { display: none; }
/* 대비 — 어두운 알약에 흐린 글씨는 폰 밝기에서 안 읽힌다(2026-09-17 지시). 흰 글씨 + 밝은 회색 알약(대비 7:1 이상) */
.plain-suggest .sug { flex: 0 0 auto; font: inherit; font-family: var(--vscode-editor-font-family); font-size: calc(var(--m-view-font) + 0.5px); font-weight: 500;
	min-height: 36px; padding: 6px 14px; border-radius: 18px; cursor: pointer;
	background: #4c5361; color: #ffffff; border: 1px solid #5d6673; }
.plain-suggest .sug:active { background: #0e639c; border-color: #1177bb; color: #ffffff; }
.plain-suggest .sug.close { background: transparent; border-color: rgba(255,255,255,.22); color: rgba(255,255,255,.75); }

/* ── 뷰 안쪽 글자 크기(상단 헤더 슬라이더) ──────────────────────────────────────────
   도구 자체(제목줄·탭·상태줄·하단 탭 바)는 그대로 두고 **뷰 안쪽만** 키운다 — 브라우저 확대는
   도구까지 같이 커져 화면이 좁아지고, 폰에서는 그만큼 덜 보인다(2026-09-17 지시).
   웹뷰(속성·데이터셋 등)는 다른 문서라 이 변수가 안 넘어가므로 studio.js 가 iframe zoom 으로 키운다. */
:root { --m-view-font: 13px; }
.fontsize { display: inline-flex; align-items: center; gap: 4px; margin: 0 4px; }
.fontsize .a1 { font-size: 10px; opacity: .7; }
.fontsize .a2 { font-size: 15px; opacity: .85; }
.fontsize input[type=range] { width: 88px; height: 28px; accent-color: var(--vscode-button-background); background: transparent; cursor: pointer; }
.plain-editor { font-size: var(--m-view-font); }
.plain-suggest .sug { font-size: calc(var(--m-view-font) + 0.5px); }
/* 뷰 안쪽은 섹션 본문 전체가 따라온다 — 트리뿐 아니라 탐색기 검색칸·안내문까지(제목줄 .sec-h 는 도구라 그대로) */
.sec-b { font-size: var(--m-view-font); }
.ftree, .vtree { font-size: var(--m-view-font); }
.ex-tools input { font-size: calc(var(--m-view-font) - 0.5px); height: calc(var(--m-view-font) + 20px); }
.ftree .row, .vtree .row { box-sizing: border-box; min-height: calc(var(--m-view-font) + 9px); padding-top: 0; padding-bottom: 0; line-height: 1.25; }   /* PC 는 VS Code 탐색기와 같은 줄높이(글자 13px → 22px). 폰은 아래 media 에서 손가락 목표로 키운다 */
.crumb { font-size: calc(var(--m-view-font) - 1.5px); }
@media (max-width: 899px) {
	.titlebar .brand span, .titlebar .brand { font-size: 13px; }
	.fontsize input[type=range] { width: 76px; }
	.ftree .row, .vtree .row { min-height: calc(var(--m-view-font) + 23px); }   /* 폰은 손가락 목표를 더 크게 */
}

/* ── 탐색기 — 폰에서 쓸 수 있게(2026-09-17 지시) ─────────────────────────────
   글자를 키우면 검색칸과 「＋ 새 화면」이 한 줄에 눌려 둘 다 못 쓰게 됐다(실사고). 줄을 나눈다.
   고른 폴더·연 파일은 왼쪽 색 띠로 분명히 표시한다 — 폰에서는 배경색만으로는 잘 안 보인다. */
.ex-tools { flex-wrap: wrap; }
.ex-tools input { flex: 1 1 100%; min-width: 0; }
.ex-tools button.tb { flex: 1 1 100%; white-space: nowrap; min-height: 36px; border-color: var(--vscode-widget-border); }
.ftree .row.dir.pick { background: rgba(255,255,255,.07); box-shadow: inset 3px 0 0 #5fd3c4; }
.ftree .row.dir.pick .nm { color: #ffffff; font-weight: 600; }
.ftree .row.on { box-shadow: inset 3px 0 0 #ffffff; }
.ftree .row.on .nm { font-weight: 600; }
@media (max-width: 899px) {
	.ex-tools { gap: 6px; padding: 6px; }
	.ex-tools button.tb { min-height: calc(var(--m-view-font) + 20px); font-size: calc(var(--m-view-font) - 1px); }
	.ftree .row .ic { flex: 0 0 auto; }

}

/* ── 값 입력 중(zen) — 제목줄·상태줄·하단 탭 바·섹션 제목줄을 감춘다(2026-09-17 지시) ──────────
   폰은 자판이 화면의 절반을 먹는다. 남은 절반을 입력 시트가 다 쓰지 않으면 입력칸과 단추가 안 보인다.
   뷰(속성 등)가 「편집 시작」을 알리면 셸이 이 클래스를 켠다(studio.js). 끝나면 되돌린다.
   ★ 폰 폭에서만이다 — PC 는 자판이 화면을 안 먹는데 편집기를 누를 때마다 제목줄이 사라졌다(2026-09-17 지시). */
@media (max-width: 899px) {
	.studio.zen .titlebar,
	.studio.zen .status,
	.studio.zen .mtabs,
	.studio.zen .sec-h { display: none !important; }
	.studio.zen .sec { min-height: 0; }
}

/* ── 대화상자 — 글자 크기 슬라이더를 따라가고, 설명은 제목 옆 ? 로 접는다(2026-09-17 지시) ──────
   폰에서는 설명 문단이 입력칸과 단추를 화면 밖으로 밀어냈다. 또 경로 input 과 템플릿 select 의
   폭이 달라 줄이 어긋나 보였다 — 같은 규칙으로 묶는다. */
.dlg { font-size: var(--m-view-font); }
.dlg h4 { display: flex; align-items: center; gap: 8px; font-size: calc(var(--m-view-font) + 1px); }
.dlg h4 .help { margin-left: auto; width: 26px; height: 26px; flex: 0 0 26px; border-radius: 13px; cursor: pointer;
	font: inherit; font-size: calc(var(--m-view-font) - 1px); line-height: 1; background: transparent;
	color: var(--vscode-foreground); border: 1px solid var(--vscode-widget-border); }
.dlg h4 .help.on { background: var(--vscode-button-background); color: var(--vscode-button-foreground); border-color: transparent; }
.dlg p, .dlg p.detail { font-size: calc(var(--m-view-font) - 1.5px); line-height: 1.55; }
.dlg p.detail[hidden] { display: none; }
/* 라벨 폭을 고정해야 세 줄의 입력칸 폭이 같아진다 — 글자대로 두면 「파일명 *」 줄만 좁아진다(실측 6px) */
/* 라벨은 **자르지 않는다** — 「추가 지…」처럼 말이 끊기면 무슨 칸인지 알 수가 없다(2026-09-20 지적).
   폭이 좁으면 두 줄로 흐르게 두고, 라벨 자체는 끝까지 보여 준다. */
.dlg .frow .fl { flex: 0 0 auto; min-width: 5em; max-width: 12em; white-space: normal; word-break: keep-all;
	font-size: calc(var(--m-view-font) - 1px); line-height: 1.35; }
/* 입력칸과 고르는 칸을 같은 폭·같은 높이로 */
/* 자유 서술(추가 지시)은 프롬프트에 그대로 실리는 글이라 한 줄 칸으로는 좁다 — 여러 줄로 받는다 */
.dlg .frow textarea { flex: 1 1 auto; min-width: 0; min-height: 4.5em; resize: vertical; font: inherit;
	padding: 4px 6px; border-radius: 4px; background: var(--m-pop-in); border: 1px solid var(--m-pop-bd);
	color: inherit; outline: none; line-height: 1.45; }
.dlg .frow textarea:focus { border-color: var(--vscode-focusBorder, #3794ff); }
.dlg .frow.top { align-items: flex-start; }

.dlg .frow input[type=text], .dlg .frow select {
	flex: 1 1 auto; width: auto; min-width: 0; box-sizing: border-box;
	height: calc(var(--m-view-font) + 22px); padding: 0 10px; font: inherit; font-size: calc(var(--m-view-font) - 1px);
	background: var(--vscode-input-background); color: var(--vscode-input-foreground);
	border: 1px solid var(--vscode-input-border, var(--vscode-widget-border)); border-radius: 3px; outline: none; }
.dlg .frow select { appearance: auto; }
.dlg .frow input[type=text], .dlg .frow select, .dlg .fparts input, .dlg .fparts select { background: var(--m-pop-in); color: var(--vscode-input-foreground); border: 1px solid var(--m-pop-bd); }
.dlg .btns button.tb { min-height: calc(var(--m-view-font) + 18px); font-size: calc(var(--m-view-font) - 1px); padding: 0 16px; }

/* 대화상자 설명 — 제목 옆 ? 를 누르면 **떠 있는 팝업**으로 뜬다. 대화상자 안에 펼치면 입력칸과 단추가
   아래로 밀려 자판 뒤로 들어간다(2026-09-17 실측). 팝업이라 아래 내용이 움직이지 않는다. */
.dlg { position: relative; }
.dlg .detail { position: absolute; left: 10px; right: 10px; top: 42px; z-index: 5; box-sizing: border-box;
	padding: 12px 14px; border-radius: 8px; background: var(--m-pop-bg); border: 1px solid var(--m-pop-bd);
	box-shadow: var(--m-pop-sd); }
.dlg .detail[hidden] { display: none; }
.dlg .detail .tx { font-size: calc(var(--m-view-font) - 1.5px); line-height: 1.6; color: var(--vscode-foreground); }
.dlg .detail button.tb { display: block; margin: 10px 0 0 auto; min-height: calc(var(--m-view-font) + 14px);
	padding: 0 14px; border: 1px solid var(--vscode-widget-border); }
@media (max-width: 899px) {
	/* 대화상자는 **맨 위에 딱 붙인다** — 위에 빈칸을 두면 자판이 뜬 화면에서 그만큼 손해다(2026-09-17 지시) */
	.modal { padding: 0; align-items: flex-start; }
	.dlg { width: 100%; max-width: none; max-height: 100%; overflow: auto; border-radius: 0 0 10px 10px; border-top: none; }
}
@media (max-width: 899px) {
	/* 라벨은 숨긴다 — 폰에서는 왼쪽 라벨이 폭을 반쯤 먹는다. 대신 자리안내 글씨가 라벨 노릇을 한다(2026-09-17 지시) */
	.dlg .frow .fl { display: none; }
	.dlg .frow { gap: 0; }
	/* 자유 서술(추가 지시)은 프롬프트에 그대로 실리는 글이라 한 줄 칸으로는 좁다 — 여러 줄로 받는다 */
.dlg .frow textarea { flex: 1 1 auto; min-width: 0; min-height: 4.5em; resize: vertical; font: inherit;
	padding: 4px 6px; border-radius: 4px; background: var(--m-pop-in); border: 1px solid var(--m-pop-bd);
	color: inherit; outline: none; line-height: 1.45; }
.dlg .frow textarea:focus { border-color: var(--vscode-focusBorder, #3794ff); }
.dlg .frow.top { align-items: flex-start; }

.dlg .frow input[type=text], .dlg .frow select { flex: 1 1 100%; }
}
@media (max-width: 899px) {
	/* 대화상자 단추는 반반으로 꽉 채운다 — 오른쪽에 몰아 두면 왼쪽이 통째로 빈다(2026-09-17 지시) */
	.dlg .btns { gap: 8px; }
	.dlg .btns button.tb { flex: 1 1 0; min-width: 0; }
	.dlg .detail button.tb { flex: 0 0 auto; }   /* 도움말 팝업의 닫기는 그대로 */
}

/* ── 트리 깊이를 눈에 보이게(2026-09-17 지시) ─────────────────────────────────────
   들여쓰기가 고정 px 이라 글자를 키우면 단계가 애매해졌다. 들여쓰기를 글자에 비례(em)시키고(한 단계 .7em — 2026-09-17 지시로 절반으로 줄였다),
   단계마다 **세로 안내선**을 그어 어디에 속한 줄인지 바로 보이게 한다. 선은 한 단계에 하나씩 쌓인다. */
.ftree ul, .vtree ul { padding-left: .42em; margin-left: .28em; border-left: 1px solid rgba(255,255,255,.16); }
/* 깊이마다 **색**을 준다(2026-09-17 지시) — 선만으로는 몇 단계인지 세어야 한다. 색이 다르면 한눈에 안다.
   여섯 색이 돌아가며 쓰이고, 줄 앞의 아이콘도 같은 색이라 줄 자체가 깊이를 말해 준다. */
.ftree > li > ul, .vtree > li > ul { border-left-color: #5fd3c466; }
.ftree > li > ul > li > .row > .ic, .vtree > li > ul > li > .row > .icon { color: #5fd3c4; opacity: .95; }
.ftree ul > li > ul, .vtree ul > li > ul { border-left-color: #4a8fd666; }
.ftree ul > li > ul > li > .row > .ic, .vtree ul > li > ul > li > .row > .icon { color: #4a8fd6; opacity: .95; }
.ftree ul ul > li > ul, .vtree ul ul > li > ul { border-left-color: #d19a6666; }
.ftree ul ul > li > ul > li > .row > .ic, .vtree ul ul > li > ul > li > .row > .icon { color: #d19a66; opacity: .95; }
.ftree ul ul ul > li > ul, .vtree ul ul ul > li > ul { border-left-color: #b58cf066; }
.ftree ul ul ul > li > ul > li > .row > .ic, .vtree ul ul ul > li > ul > li > .row > .icon { color: #b58cf0; opacity: .95; }
.ftree ul ul ul ul > li > ul, .vtree ul ul ul ul > li > ul { border-left-color: #89d18566; }
.ftree ul ul ul ul > li > ul > li > .row > .ic, .vtree ul ul ul ul > li > ul > li > .row > .icon { color: #89d185; opacity: .95; }
.ftree ul ul ul ul ul > li > ul, .vtree ul ul ul ul ul > li > ul { border-left-color: #e5c07b66; }
.ftree ul ul ul ul ul > li > ul > li > .row > .ic, .vtree ul ul ul ul ul > li > ul > li > .row > .icon { color: #e5c07b; opacity: .95; }
.ftree > li > ul, .vtree > li > ul { margin-left: .22em; }
.ftree .row, .vtree .row { position: relative; }
/* 고른 줄·연 파일은 그 줄이 속한 안내선까지 밝게 — 어느 가지인지 따라가기 쉽게 */
.ftree li:has(> .row.on) > ul, .ftree li:has(> .row.dir.pick) > ul,
.vtree li:has(> .row.sel) > ul { border-left-color: rgba(255,255,255,.34); }
.vtree .row.sel, .ftree .row.on { border-radius: 2px; }
@media (max-width: 899px) {
	/* 폰에서는 한 단계를 조금 더 좁게 — 깊은 트리가 화면 밖으로 밀리지 않게(선이 있어 좁아도 구분된다) */
	.ftree ul, .vtree ul { padding-left: .3em; margin-left: .2em; }
}

/* ── 팝업 한 벌(2026-09-17 지시 "팝업들 디자인 통일") ───────────────────────────────
   대화상자(.dlg) · 더보기 시트(.sheet-card) · 도움말(.dlg .detail) · 속성 편집 시트(뷰 안의 .psheet)가
   같은 규격을 쓴다: 같은 바탕·테두리·모서리 12 · 그림자 · 여백 12/14 · 제목 굵게 · 단추 높이 글자+20 · 반반.
   속성 시트는 다른 문서(iframe)라 propertyView.js 가 같은 값을 들고 있다 — 둘을 함께 고친다. */
.dlg, .sheet-card, .dlg .detail {
	background: var(--vscode-editorWidget-background, #252526);
	border: 1px solid var(--vscode-widget-border, #3c3c3c);
	box-shadow: 0 10px 30px rgba(0,0,0,.55);
}
.dlg { border-radius: 12px; padding: 12px 14px 14px; }
.dlg .detail { border-radius: 12px; padding: 12px 14px; }
.sheet-card { border-radius: 12px 12px 0 0; }
.dlg h4 { margin: 0 0 10px; font-weight: 600; }
.dlg .btns { margin-top: 12px; }
.dlg .btns button.tb, .dlg .detail button.tb {
	min-height: calc(var(--m-view-font) + 20px); border-radius: 6px;
	border: 1px solid var(--vscode-widget-border); font-size: calc(var(--m-view-font) - 1px); }
.dlg .btns button.tb.pri { border-color: transparent; }
@media (max-width: 899px) {
	.dlg { border-radius: 0 0 12px 12px; border-top: none; }
	/* 폰에서는 시트가 화면 전체 — 위쪽에 남기던 「바깥」 띠를 없애고 그만큼 항목에 준다(2026-09-18 지시). 닫기는 아래 [닫기]·Esc */
	.sheet-card { top: 0; max-height: none; height: 100dvh; border-radius: 0; padding-top: 0; }
	.sheet .sh, .sheet-card .sh { min-height: calc(var(--m-view-font) + 24px); font-size: var(--m-view-font); }
}
/* 파일명 한 줄에 세 칸 — 접두어(고르기) · 번호(입력) · 확장자(고르기) */
.dlg .fparts { display: flex; gap: 6px; flex: 1 1 100%; min-width: 0; }
/* 준비 화면(dialogAgentPrep)의 상태 줄 — 버튼 아래 한 줄로 결과를 말한다(✔ 연결됨 / ✖ 까닭) */
.dlg .prep-st { font-size: 12px; line-height: 1.45; margin: 4px 0 10px; opacity: .9; white-space: normal; word-break: keep-all; }
/* 잠긴 버튼은 잠겨 보여야 한다 — 준비가 안 됐는데 [다음]이 파랗게 멀쩡해 보여 「눌러도 안 된다」가 됐다(2026-09-23 실측) */
.dlg button.tb:disabled { opacity: .4; cursor: not-allowed; filter: grayscale(.6); }
.dlg .fparts > * { box-sizing: border-box; height: calc(var(--m-view-font) + 22px); padding: 0 8px; min-width: 0;
	font: inherit; font-size: calc(var(--m-view-font) - 1px);
	background: var(--vscode-input-background); color: var(--vscode-input-foreground);
	border: 1px solid var(--vscode-input-border, var(--vscode-widget-border)); border-radius: 3px; outline: none; }
.dlg .fparts input { flex: 1 1 auto; }

/* ── 트리 들여쓰기 어긋남(2026-09-17 세 번째 지적) ────────────────────────────────
   행은 flex 인데 앞의 펼침 표시(.tw)·아이콘(.ic/.icon)에 width 만 주고 flex 를 안 줬다.
   이름이 길어 행이 넘치면 flex 가 그것들을 **줄여 버려서**, 펼침 표시가 없는 줄(빈 칸)은 0 이 되고
   있는 줄은 글자 폭만큼 남아 같은 깊이인데도 시작점이 달라졌다.
   → 줄어들지 않는 고정 자리(flex: 0 0 …)로 못박는다. 크기는 em 이라 글자 크기를 따라간다. */
.vtree .row > .tw, .vtree .row > .icon,
.ftree .row > .ic { flex: 0 0 auto; }
.vtree .row > .tw { width: 1em; min-width: 1em; text-align: center; position: relative; }
.vtree .row > .icon { width: 1.15em; min-width: 1.15em; text-align: center; }
.ftree .row > .ic { width: 1.25em; min-width: 1.25em; text-align: center; }
.vtree .row > .label, .ftree .row > .nm { flex: 0 1 auto; min-width: 0; }
.vtree .row > .desc { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* 폰: 펼침표(▾)의 **손가락 목표만** 넓힌다 — 보이는 폭은 들여쓰기를 맞추려 1em 으로 못 박아 둔 칸이라 그대로 둔다 */
@media (max-width: 899px) {
	.vtree .row > .tw::after { content: ''; position: absolute; left: -12px; right: -12px; top: -10px; bottom: -10px; }
	.sec-act { width: 32px; height: 32px; font-size: 16px; border-color: var(--m-pop-bd); opacity: .9; }
}

/* ── MOCA Web Studio: full-viewport particle startup ── */
.boot { --boot-accent: #7df5e2; --boot-word-size: min(22.5vw, 210px, 27vh); position: fixed; inset: 0; z-index: 10000; overflow: hidden; isolation: isolate; background: #030810; color: #e9fffc; font-family: "Segoe UI", "Malgun Gothic", sans-serif; transition: opacity .45s ease; }
.boot.done { opacity: 0; pointer-events: none; }
.boot[hidden], .boot [hidden] { display: none !important; }
.boot-aurora { position: absolute; inset: -35%; opacity: .85; background: conic-gradient(from 50deg at 50% 44%, transparent 0deg, rgba(20,95,125,.07) 40deg, rgba(125,245,226,.23) 65deg, transparent 90deg, rgba(88,59,198,.17) 160deg, transparent 200deg, rgba(125,245,226,.15) 245deg, transparent 280deg); filter: blur(32px); animation: studio-boot-nebula 18s linear infinite; }
.boot-floor { position: absolute; left: -50%; right: -50%; height: 65%; bottom: -36%; background-image: linear-gradient(rgba(125,245,226,.12) 1px, transparent 1px), linear-gradient(90deg,rgba(125,245,226,.12) 1px,transparent 1px); background-size: 70px 70px; transform: perspective(360px) rotateX(58deg); mask-image: linear-gradient(transparent,#000 65%); animation: studio-boot-grid 3s linear infinite; }
.boot-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.boot-top { position: absolute; left: 32px; right: 32px; top: 24px; display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.boot-brand { display: flex; align-items: center; gap: 5px; font-size: 24px; font-weight: 650; letter-spacing: -1px; }
.boot-brand > span { width: 5px; height: 5px; border-radius: 50%; background: var(--boot-accent); box-shadow: 0 0 15px var(--boot-accent); }
.boot button { min-height: 36px; padding: 8px 14px; border: 1px solid #355362; border-radius: 6px; background: #0c1e2a; color: #c4e1e5; font: 400 12px/1.5 "Segoe UI", "Malgun Gothic", sans-serif; cursor: pointer; }
.boot button:hover { border-color: var(--boot-accent); color: #fff; }
.boot button:focus-visible { outline: 2px solid var(--boot-accent); outline-offset: 3px; }
.boot-title { position: absolute; left: 0; right: 0; top: 43%; transform: translateY(-50%); margin: 0; text-align: center; font: 800 var(--boot-word-size)/1 "Segoe UI", sans-serif; color: var(--boot-accent); text-shadow: 0 0 35px rgba(125,245,226,.4); }
.boot.has-canvas .boot-title { opacity: 0; }
.boot-copy { position: absolute; left: 16px; right: 16px; top: calc(43% + var(--boot-word-size) * .65); text-align: center; opacity: 0; transform: translateY(16px); transition: opacity .8s, transform .8s; }
.boot.formed .boot-copy, .boot:not(.has-canvas) .boot-copy { opacity: 1; transform: translateY(0); }
.boot-subtitle { color: var(--boot-accent); font-size: 22px; font-weight: 400; line-height: 1.4; letter-spacing: .5em; padding-left: .5em; text-shadow: 0 0 28px rgba(125,245,226,.5); }
.boot-subtitle > span { color: #ecfaff; }
.boot-copy p { margin: 18px 0 0; color: #96b0c0; font-size: 13px; letter-spacing: .15em; }
.boot.launch .boot-copy, .boot.launch .boot-title { opacity: 0; transition: opacity .45s; }
.boot-flare { position: absolute; left: 0; right: 0; top: 43%; height: 2px; background: linear-gradient(90deg, transparent, rgba(125,245,226,.5), #f5ffff, rgba(125,245,226,.5), transparent); box-shadow: 0 0 30px 6px rgba(125,245,226,.45); opacity: 0; transform: scaleX(.1); pointer-events: none; }
.boot.impact .boot-flare { animation: studio-boot-flare 1.6s ease-out both; }
.boot-bottom { position: absolute; left: 40px; right: 40px; bottom: max(28px, env(safe-area-inset-bottom)); }
.boot-status { display: flex; justify-content: space-between; align-items: end; gap: 18px; margin-bottom: 16px; }
.boot-msg { max-width: 75%; color: #afc5d2; font-size: 13px; line-height: 1.6; word-break: keep-all; overflow-wrap: anywhere; }
.boot-number { flex-shrink: 0; color: #dcfff8; font: 300 42px/1 Consolas, monospace; font-variant-numeric: tabular-nums; letter-spacing: -.06em; }
.boot-number small { margin-left: 6px; color: #94b6bf; font-size: 14px; }
.boot-progress { height: 2px; background: #1d3440; }
.boot-progress > div { width: 100%; height: 100%; transform: scaleX(0); transform-origin: left; background: linear-gradient(90deg, #277dc9, var(--boot-accent), #e9fff7); box-shadow: 0 0 14px rgba(125,245,226,.6); }
.boot-footer { margin-top: 16px; display: flex; justify-content: space-between; gap: 16px; color: #718f9f; font: 400 12px/1.5 Consolas, monospace; letter-spacing: .08em; }
#bootPhase { color: var(--boot-accent); }
.boot-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.boot.boot-error .boot-number { visibility: hidden; }
.boot.boot-error *, .boot.done * { animation-play-state: paused !important; }
.boot.boot-error .boot-flare { display: none; }
@keyframes studio-boot-nebula { to { transform: rotate(360deg); } }
@keyframes studio-boot-grid { to { background-position: 0 70px; } }
@keyframes studio-boot-flare { 0% { opacity: 0; transform: scaleX(.1); } 18% { opacity: .9; transform: scaleX(1); } 100% { opacity: 0; transform: scaleX(1.5); } }
@media (max-width: 600px) {
	.boot-top { left: 20px; right: 20px; top: 18px; }
	.boot-subtitle { font-size: 17px; letter-spacing: .3em; }
	.boot-bottom { left: 22px; right: 22px; bottom: max(22px, env(safe-area-inset-bottom)); }
	.boot-footer { letter-spacing: 0; }
	.boot-number { font-size: 34px; }
	.boot button { min-height: 44px; }
}
@media (max-height: 480px) {
	.boot-copy p { display: none; }
	.boot-top { top: 12px; }
	.boot-copy { top: calc(43% + var(--boot-word-size) * .5); }
	.boot-subtitle { font-size: 15px; }
	.boot-bottom { bottom: 14px; }
	.boot-footer { margin-top: 8px; }
	.boot-status { margin-bottom: 10px; }
	.boot-number { font-size: 28px; }
	.boot.boot-error .boot-copy { opacity: 0; }
}

/* ── 진행 상황 덮개(새 화면(AI)) ───────────────────────────────────────────
   기동 덮개(.boot)와 같은 자리·같은 무게로 화면을 덮는다. 오래 걸리는 일에 「아무 일도 안 일어난다」는
   느낌을 없애는 것이 목적이라, 지금 하는 단계는 굵게·색으로 두드러지게 하고 경과(초)를 계속 갱신한다. */
/* z-index 는 대화상자(.modal 50)·시트(55)·토스트(60)보다 **아래**다 — 덮개가 떠 있는 동안에도
   「덮어쓸까요?」 같은 물음창이 위로 떠야 한다(2026-09-20 실측: 60 이면 물음창이 가려진다). */
.prog { position: fixed; inset: 0; z-index: 45; display: flex; align-items: center; justify-content: center;
	background: rgba(0,0,0,.55); backdrop-filter: blur(2px); padding: 16px; box-sizing: border-box; }
.prog[hidden] { display: none; }
.prog-card { width: min(560px, 100%); max-height: 100%; overflow: auto; box-sizing: border-box;
	display: flex; flex-direction: column; gap: 10px; padding: 18px 20px; border-radius: 10px;
	background: var(--m-pop-bg); border: 1px solid var(--m-pop-bd); box-shadow: var(--m-pop-sd);
	color: var(--vscode-foreground); font-size: var(--m-view-font); }
.prog-card.bad { border-color: var(--vscode-inputValidation-errorBorder, #be1100); }
.prog-card h4 { margin: 0; font-size: calc(var(--m-view-font) + 1px); }
.prog-steps { display: flex; flex-direction: column; gap: 2px; }
.prog-step { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: 4px; opacity: .55; }
.prog-step .ic { flex: 0 0 16px; text-align: center; }
.prog-step .tx { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prog-step .note { flex: 0 1 auto; max-width: 55%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	font-size: calc(var(--m-view-font) - 1px); opacity: .8; }
.prog-step.on { opacity: 1; font-weight: 600; background: var(--vscode-list-hoverBackground, rgba(255,255,255,.06)); }
.prog-step.on .ic { color: var(--vscode-button-background, #3794ff); }
.prog-step.ok { opacity: 1; }
.prog-step.ok .ic { color: #3fb950; }
.prog-step.bad { opacity: 1; }
.prog-step.bad .ic, .prog-step.bad .note { color: var(--vscode-errorForeground, #f14c4c); }
.prog-step.skip .note { font-style: italic; }
/* ── 단계 모니터(큰 화면, 2026-09-20 지시) ──────────────────────────────
   만드는 동안 어디까지 왔는지 한눈에 보이게 한다 — 전체 퍼센트 막대, 단계별 상태(예정·진행중·완료·생략),
   생략한 까닭, 단계마다 [상세] 팝업. 좁은 화면에서는 한 줄이 접히지 않게 상태·비고를 줄인다. */
/* 화면에 맞춰 크게(2026-09-21 지시) — 860px 고정이라 큰 모니터에서 남는 자리를 전혀 안 썼다.
   height 를 줘야 안쪽 .prog-log 의 flex:1 이 실제로 늘어난다(높이가 없으면 내용 높이에 머문다). */
.prog-card.big { width: min(1400px, 96vw); height: 90vh; }
.prog-head { display: flex; align-items: center; gap: 10px; }
.prog-pct { flex: 0 0 auto; font-weight: 700; font-size: calc(var(--m-view-font) + 2px); min-width: 3.2em; }
.prog-bar { flex: 1 1 auto; height: 8px; border-radius: 99px; overflow: hidden;
	background: var(--m-pop-in); border: 1px solid var(--m-pop-bd); }
.prog-bar > i { display: block; height: 100%; width: 0; border-radius: 99px;
	background: var(--vscode-button-background, #3794ff); transition: width .3s ease; }
.prog-sum { flex: 0 1 auto; opacity: .75; font-size: calc(var(--m-view-font) - 1px); white-space: nowrap; }
.prog-step .st { flex: 0 0 3.6em; text-align: center; border-radius: 99px; padding: 1px 0;
	font-size: calc(var(--m-view-font) - 1px); background: var(--m-pop-in); border: 1px solid var(--m-pop-bd); }
.prog-step.on .st { background: var(--vscode-button-background, #3794ff); border-color: transparent; color: #fff; }
.prog-step.ok .st { color: #3fb950; }
.prog-step.bad .st { color: var(--vscode-errorForeground, #f14c4c); }
.prog-step .tb.sm { flex: 0 0 auto; padding: 1px 7px; font-size: calc(var(--m-view-font) - 1px); opacity: .8; }
.prog-step:hover .tb.sm { opacity: 1; }
@media (max-width: 640px) {
	.prog-sum { display: none; }
	.prog-step .note { max-width: 35%; }
}

/* ── 만들 단계 고르기 — 전부 켜진 것이 풀스택 ─────────────────────────── */
.stepsel { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 14px; max-height: 210px; overflow: auto;
	padding: 6px 8px; border-radius: 6px; background: var(--m-pop-in); border: 1px solid var(--m-pop-bd); }
.stepsel-it { display: flex; align-items: center; gap: 6px; min-width: 0; cursor: pointer; }
.stepsel-it .nm { flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stepsel-it .why { flex: 1 1 auto; min-width: 0; opacity: .6; font-size: calc(var(--m-view-font) - 1px);
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stepsel-it.off { opacity: .55; cursor: default; }
@media (max-width: 640px) { .stepsel { grid-template-columns: 1fr; } }

/* 기록 — 출력 패널과 같은 줄들이 실시간으로 쌓인다(무엇을 하고 있는지의 근거)
   ★ 높이를 px 로 박지 않는다(2026-09-21 지시). 고정이면 카드가 커져도 로그는 140px 에 머물고,
     글자 크기 슬라이더를 올리면 글자만 커져 **보이는 줄 수가 오히려 줄었다**(13px 8.3줄 → 18px 5.4줄).
     flex 로 두면 남는 세로를 전부 차지한다.
   ★ 글자는 10.5px 였다 — 이 저장소가 스스로 금지한 크기다(SKILL: 10·11px 금지). 본문과 같게 둔다. */
.prog-log { flex: 1 1 auto; min-height: 160px; overflow: auto; padding: 8px 10px; border-radius: 6px;
	background: var(--m-pop-in); border: 1px solid var(--m-pop-bd);
	font-family: var(--vscode-editor-font-family, monospace); font-size: var(--m-view-font); line-height: 1.5; white-space: pre-wrap; }
.prog-foot { display: flex; align-items: center; gap: 8px; }
.prog-time { flex: 1 1 auto; opacity: .7; font-size: calc(var(--m-view-font) - 1px); }
.prog-foot button.tb { min-height: calc(var(--m-view-font) + 18px); padding: 0 16px; font-size: calc(var(--m-view-font) - 1px); }
@media (max-width: 560px) {
	.prog { padding: 8px; }
	.prog-log { min-height: 110px; }
}
/* 끝난 뒤 「이제 할 일」 — 저장만으로는 메뉴에 안 뜬다(메뉴 SQL 은 서버가 기동할 때 반영된다) */
.prog-next { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border-radius: 6px;
	background: var(--vscode-textBlockQuote-background, rgba(255,255,255,.05));
	border-left: 3px solid var(--vscode-button-background, #3794ff); font-size: calc(var(--m-view-font) - 1px); line-height: 1.6; }
.prog-next[hidden] { display: none; }
.prog-next b { font-size: calc(var(--m-view-font) - 0.5px); }
/* 실패한 단계의 사유는 한 줄로 자르지 않는다 — 원인이 거기 적혀 있다(2026-09-20) */
.prog-step.bad { align-items: flex-start; }
.prog-step.bad .note { white-space: normal; max-width: 70%; text-align: right; }

/* 「변경 파일」 칸 — 저장 전(●)·저장됨(✓)을 한눈에 */
.chg-list { display: flex; flex-direction: column; gap: 1px; }
.chg { display: flex; align-items: center; gap: 6px; padding: 4px 6px; border-radius: 4px; cursor: pointer;
	font-size: calc(var(--m-view-font) - 1px); }
.chg:hover { background: var(--vscode-list-hoverBackground, rgba(255,255,255,.06)); }
.chg .ic { flex: 0 0 12px; text-align: center; }
.chg .nm { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chg .tag { flex: 0 0 auto; font-size: calc(var(--m-view-font) - 3px); opacity: .65; }
.chg.dirty .ic { color: var(--vscode-editorWarning-foreground, #cca700); }
.chg.dirty .nm { font-weight: 600; }
.chg.ok .ic { color: #3fb950; }
.chg.ok .nm { opacity: .75; }

/* 변경 파일 칸은 낮게 — 파일 몇 개뿐인데 사이드바를 다 먹었다(2026-09-20 지시).
   내용만큼만 차지하고, 많아지면 이 칸 안에서 스크롤한다. */
.sec[data-sec="changed"] { flex: 0 0 auto; }
.sec[data-sec="changed"] > .sec-b { max-height: 22vh; overflow: auto; }
#changed .ex-tools { margin-bottom: 4px; }
#changed .chg { padding: 3px 6px; }

/* ── AI 사양 확인 대화상자(dialogReviewSpec) ───────────────────────────────
   줄글 한 덩이는 사람이 못 읽는다 — 시연 화면에서 글이 통째로 쏟아졌다(2026-09-20 지적).
   내용은 그대로 두고 배치만 준다: 사실은 배지, 조건·컬럼은 칸, 설계서 원문은 접힌 목록. */
.dlg.wide { width: min(780px, 94vw); }
.spec { max-height: 56vh; overflow: auto; margin: 0 -2px; padding: 2px; }
.spec-title { font-size: calc(var(--m-view-font) + 4px); font-weight: 700; line-height: 1.3; margin-bottom: 10px; }

.spec-facts { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.spec-fact { display: flex; align-items: center; gap: 7px; padding: 5px 11px; border-radius: 999px;
	background: var(--vscode-input-background); border: 1px solid var(--vscode-widget-border);
	font-size: calc(var(--m-view-font) - 1px); }
.spec-fact .k { opacity: .55; font-size: calc(var(--m-view-font) - 2px); }
.spec-fact .v { font-weight: 600; }
.spec-fact .v.mono { font-family: var(--vscode-editor-font-family); letter-spacing: .01em; }
.spec-fact.on { border-color: var(--vscode-charts-blue); background: color-mix(in srgb, var(--vscode-charts-blue) 12%, transparent); }
.spec-fact.dim .v { font-weight: 400; opacity: .6; }
.spec-fact .tg { font-size: calc(var(--m-view-font) - 4px); padding: 1px 7px; border-radius: 999px;
	background: var(--vscode-charts-blue); color: #fff; }

.spec-sec { margin-bottom: 14px; }
.spec h5 { display: flex; align-items: baseline; gap: 6px; margin: 0 0 7px;
	font-size: calc(var(--m-view-font) - 1px); font-weight: 700; opacity: .8; }
.spec h5 .n, .spec-read summary .n { font-weight: 400; opacity: .55; font-size: calc(var(--m-view-font) - 2px); }
.spec-chips { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 6px; }
.spec-chip { min-width: 0; padding: 6px 9px; border-radius: 7px;
	background: var(--vscode-editor-background); border: 1px solid var(--vscode-widget-border); }
.spec-chip .nm { display: block; font-size: var(--m-view-font); font-weight: 600;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spec-chip .cd { display: block; margin-top: 1px; font-family: var(--vscode-editor-font-family);
	font-size: calc(var(--m-view-font) - 3px); opacity: .55;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.spec-chip .tg { float: right; margin-left: 6px; font-size: calc(var(--m-view-font) - 4px);
	padding: 1px 7px; border-radius: 999px; background: var(--vscode-charts-blue); color: #fff; }
.spec-chip .tg.alt { background: transparent; color: inherit; opacity: .5;
	border: 1px solid var(--vscode-widget-border); }
.spec-none { opacity: .5; font-size: calc(var(--m-view-font) - 1px); }

.spec-read { margin-bottom: 8px; border: 1px solid var(--vscode-widget-border); border-radius: 7px; }
.spec-read > summary { cursor: pointer; padding: 7px 10px; list-style: none;
	display: flex; align-items: baseline; gap: 6px; font-size: calc(var(--m-view-font) - 1px); opacity: .8; }
.spec-read > summary::-webkit-details-marker { display: none; }
.spec-read > summary::before { content: '▸'; opacity: .6; }
.spec-read[open] > summary::before { content: '▾'; }
.spec-read ul { margin: 0; padding: 0 12px 9px 30px; font-size: calc(var(--m-view-font) - 1px); line-height: 1.6; opacity: .8; }
.spec-read li { margin: 2px 0; }
@media (max-width: 640px) { .spec-chips { grid-template-columns: 1fr 1fr; } .spec { max-height: 50vh; } }

/* ── 대화상자 덮개(busy) — 설계서 업로드처럼 몇 초 걸리는 동안 (2026-09-21) ──────────────
   덮개가 없으면 사람은 눌렸는지 모르고 버튼을 다시 누르거나 [취소]로 올라가던 파일을 끊는다.
   .dlg 에 position 을 주는 이유: 덮개를 대화상자 안쪽에만 씌우기 위해서다(화면 전체를 덮으면
   진행 중에 다른 일까지 막힌 것처럼 보인다). */
.dlg { position: relative; }
.dlg-busy { position: absolute; inset: 0; z-index: 5; display: flex; align-items: center; justify-content: center;
            background: rgba(20,20,22,.72); backdrop-filter: blur(2px); border-radius: 6px; }
.dlg-busy-box { width: min(320px, 80%); text-align: center; }
.dlg-busy-msg { font-size: 13px; color: rgba(255,255,255,.88); margin-bottom: 10px; }
/* 막대는 총 크기를 알 때만 보인다 — 가짜로 움직이는 막대는 남은 시간을 아는 것처럼 보여 더 답답하다 */
.dlg-busy-bar { height: 4px; border-radius: 3px; background: rgba(255,255,255,.14); overflow: hidden; }
.dlg-busy-bar[hidden] { display: none; }
.dlg-busy-bar i { display: block; height: 100%; width: 0; background: var(--m-accent, #4da3ff); transition: width .15s linear; }

/* 지시문 칸 — 라벨 없이 대화상자 폭을 다 쓴다 (2026-09-21 지시).
   테이블·템플릿 칸을 없앤 만큼 필요한 것을 전부 여기 적으므로, 좁으면 쓰다 만다. */
/* ★ 테마 색은 .dlg .frow textarea 에만 걸려 있었다 — 라벨을 없애며 .frow 밖으로 빼자
   브라우저 기본(흰 배경)으로 떨어졌다(2026-09-21). 그래서 색·테두리를 여기서 다시 준다. */
.dlg textarea.note-wide { display: block; width: 100%; box-sizing: border-box; margin: 10px 0 2px;
	min-height: 86px; resize: vertical; font: inherit; line-height: 1.45;
	padding: 6px 8px; border-radius: 4px; outline: none;
	background: var(--m-pop-in); border: 1px solid var(--m-pop-bd); color: inherit; }
.dlg textarea.note-wide:focus { border-color: var(--vscode-focusBorder, #3794ff); }
.dlg textarea.note-wide::placeholder { color: inherit; opacity: .45; }
