/* components.css — 버튼·입력·모달·태그·아바타·배지·배너·진행률
   출처: design/mockups (19화면). 괄호 안 숫자 = 그 규칙을 쓰는 화면 수.
   계열 스코프(.app/.admin/.auth)와 변형 클래스로 이름 충돌을 이미 해소했습니다.
*/

*{box-sizing:border-box} /* 19 */
html,body{height:100%} /* 19 */
body{margin:0;background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Apple SD Gothic Neo","Pretendard","Malgun Gothic",sans-serif;font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased} /* 19 */
a{color:var(--accent);text-decoration:none} /* 19 */
a:hover{text-decoration:underline} /* 19 */
button{font:inherit;color:inherit;background:none;border:none;padding:0;cursor:pointer} /* 19 */
[hidden]{display:none !important} /* 19 */
.field{display:flex;flex-direction:column;gap:6px;margin-bottom:14px} /* 19 */
.field-label{font-size:12px;font-weight:600;color:var(--ink-muted)}
.input{height:40px;border:none;border-radius:var(--radius);background:var(--bg-input);padding:0 12px;font:inherit;font-size:14px;color:var(--ink);width:100%}
.input::placeholder{color:var(--ink-faint)}
.input:focus{outline:none;box-shadow:0 0 0 2px var(--accent-bg) inset}
.input:read-only{color:var(--ink-faint);cursor:default}
.input.is-error{box-shadow:0 0 0 1px var(--danger) inset}
.field-error{font-size:12px;color:var(--danger)}
.field-hint{font-size:12px;color:var(--ink-faint)} /* 19 */
.btn-primary{height:32px;padding:0 12px;border-radius:var(--radius);flex:none;background:var(--accent);color:#fff;font-size:13px;font-weight:500;display:flex;align-items:center;gap:6px;white-space:nowrap} /* 19 */
.btn-primary:hover{filter:brightness(.95)} /* 8 */
.btn-primary:disabled{background:var(--bg-input);color:var(--ink-faint);cursor:default;filter:none} /* 7 */
.btn-secondary{height:32px;padding:0 12px;border-radius:var(--radius);flex:none;background:var(--bg);color:var(--ink);font-size:13px;box-shadow:var(--shadow-card);display:flex;align-items:center;gap:6px;white-space:nowrap;cursor:pointer} /* 19 */
.btn-secondary:hover{background:var(--bg-hover)} /* 9 */
.avatar{width:24px;height:24px;border-radius:50%;flex:none;background:var(--tag-blue);color:var(--ink);font-size:11px;display:flex;align-items:center;justify-content:center} /* 19 */
.chip{display:inline-flex;align-items:center;gap:4px;height:20px;padding:0 8px;border-radius:10px;font-size:12px;color:var(--ink);background:var(--tag-gray)} /* 19 */
.chip.blue{background:var(--tag-blue)} /* 7 */
.strength{display:flex;align-items:center;gap:8px;margin-top:2px} /* 19 */
.auth .avatar{width:36px;height:36px;background:var(--tag-green);font-size:12px} /* 19 */
.btn-danger{height:32px;padding:0 12px;border-radius:var(--radius);background:var(--danger);color:#fff;font-size:13px;font-weight:500;white-space:nowrap} /* 19 */
.btn-danger-text{height:32px;padding:0 10px;border-radius:var(--radius);color:var(--danger);font-size:13px;white-space:nowrap} /* 19 */
.auth .btn-primary{padding:0;flex:0 1 auto;white-space:normal;height:40px;width:100%;font-size:14px;justify-content:center;margin-top:6px} /* 19 */
/* .auth .btn-secondary — SC-01 로그인 화면의 "재시도" 링크 등 세로로 쌓이는 전체폭 보조
   버튼 전용 변형. part001에서 .btn-secondary 기본 규칙에 이 값(width:100%·margin-top:6px·
   justify-content:center)이 스코프 없이 얹혀 있었다 — .btn-primary는 .auth로 스코프를
   나눴는데 .btn-secondary만 놓친 것으로 보인다. 그 버그가 admin-head의 [복구 →] 같은
   보조 버튼을 100% 폭으로 늘려 옆 flex:1 형제(.head-text)를 0폭으로 밀어내
   "워크스페이스" 제목이 한 글자씩 세로로 쪼개지던 원인이었다(devplan003 CONTRACT 서문의
   그 증상). SC-18:86-92의 스코프 없는 원래 값으로 되돌리고, SC-18의 "정규화 블록"이
   합쳐 버린 auth 전용 값은 .btn-primary와 똑같이 .auth로만 옮겼다. */
.auth .btn-secondary{width:100%;justify-content:center;margin-top:6px}
.auth .chip{background:transparent;gap:6px;height:24px;padding:0 10px;border-radius:12px} /* 19 */
.comment .avatar{width:22px;height:22px;font-size:10px} /* 19 */
.comment .text{font-size:13px;line-height:1.5;margin-top:2px} /* 19 */
.comment-input{width:100%;min-height:56px;resize:vertical;border:none;border-radius:var(--radius);background:var(--bg-input);padding:8px 10px;font:inherit;font-size:13px;color:var(--ink);margin-top:12px} /* 19 */
.modal{width:440px;max-width:100%;background:var(--bg);border-radius:var(--radius-lg);box-shadow:var(--shadow-pop);padding:22px} /* 19 */
.modal.modal-search{padding:0;width:620px;max-width:calc(100vw - 32px);margin-top:20vh;display:flex;flex-direction:column;max-height:60vh;overflow:hidden} /* 19 */
.modal-impact{background:var(--bg-input);border-radius:var(--radius);padding:10px 12px;font-size:13px;line-height:1.7;margin-bottom:16px} /* 19 */
.modal-input{width:100%;height:36px;border:none;border-radius:var(--radius);background:var(--bg-input);padding:0 10px;font:inherit;font-size:14px;color:var(--ink)} /* 19 */
.modal-search .modal-input{width:auto;height:auto;border-radius:0;padding:0;flex:1;min-width:0;background:transparent;font-size:18px} /* 19 */
.modal-input:focus{outline:none;box-shadow:0 0 0 2px var(--accent-bg) inset} /* 19 */
.modal-search .modal-input:focus{box-shadow:none} /* 19 */
.modal-overlay{position:fixed;inset:0;z-index:80;background:rgba(15,15,15,.6);display:flex;align-items:center;justify-content:center;padding:24px} /* 19 */
.more-btn{align-self:flex-start;margin-top:12px;height:32px;padding:0 14px;border-radius:var(--radius);background:var(--bg-input);font-size:13px;color:var(--ink-muted);cursor:pointer} /* 19 */
.prop-add{display:flex;align-items:center;gap:6px;margin-top:6px;padding:5px 6px;border-radius:var(--radius);font-size:13px;color:var(--ink-faint);cursor:pointer} /* 19 */
.prop-label{display:flex;align-items:center;gap:6px;min-width:0;padding:4px 6px;border-radius:var(--radius);font-size:14px;color:var(--ink-muted);cursor:pointer;text-align:left} /* 19 */
.prop-list{display:flex;flex-direction:column;gap:2px} /* 19 */
.prop-row{display:grid;grid-template-columns:minmax(120px,150px) minmax(160px,1fr);align-items:center;gap:8px;border-radius:var(--radius);padding:2px;position:relative} /* 19 */
.prop-value{display:flex;align-items:center;gap:6px;min-height:30px;padding:0 8px;border-radius:var(--radius);font-size:14px;cursor:pointer;text-align:left;width:100%} /* 19 */
.prop-value.is-static{cursor:default;color:var(--ink-muted);font-size:13px} /* 19 */
.prop-value:hover{background:var(--bg-active)} /* 19 */
.row-actions{display:flex;align-items:center;gap:4px;justify-content:flex-end} /* 19 */
.section-title{font-size:15px;font-weight:600;margin:0 0 10px} /* 19 */
.tag{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:3px;font-size:12px;color:var(--ink);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;background:var(--tag-gray)} /* 19 */
.text-btn{height:26px;padding:0 8px;border-radius:var(--radius);font-size:13px;color:var(--ink-muted)} /* 19 */
.text-btn:hover{background:var(--bg-hover);color:var(--ink)} /* 19 */
.text-btn.danger{color:var(--danger)} /* 19 — SC-12_trash.html:691. 휴지통 "영구 삭제" 글자 버튼의 빨간색이 빠져 있었다 */
.text-btn.danger:hover{background:rgba(235,87,87,.1)} /* 19 — SC-12_trash.html:692 */
.thread{border:1px solid var(--line);border-radius:var(--radius-lg);padding:10px;margin-bottom:10px} /* 19 */
.thread-foot{display:flex;gap:8px;margin-top:8px} /* 19 */
.toast{position:fixed;bottom:70px;left:50%;transform:translateX(-50%);z-index:85;background:#2f2f2c;color:#e9e9e6;border-radius:var(--radius);padding:10px 14px;font-size:13px;box-shadow:var(--shadow-pop);max-width:520px} /* 19 */
.tool-btn{height:28px;padding:0 8px;border-radius:var(--radius);display:flex;align-items:center;gap:5px;font-size:13px;color:var(--ink-muted);cursor:pointer;flex:none;white-space:nowrap} /* 19 */
.tooltip{position:absolute;bottom:calc(100% + 6px);right:0;z-index:70;background:#2f2f2c;color:#e9e9e6;border-radius:var(--radius);padding:6px 8px;font-size:12px;white-space:nowrap;box-shadow:var(--shadow-pop)} /* 19 */
.tooltip-below{bottom:auto;top:calc(100% + 6px)} /* 19 */
.view-tabs{display:flex;align-items:center;gap:2px;flex:none} /* 19 */
::-webkit-scrollbar{width:10px;height:10px} /* 17 */
::-webkit-scrollbar-thumb{background:rgba(55,53,47,.18);border-radius:5px;border:3px solid transparent;background-clip:content-box} /* 17 */
.badge{min-width:16px;height:16px;padding:0 4px;border-radius:8px;background:var(--danger);color:#fff;font-size:11px;display:flex;align-items:center;justify-content:center} /* 12 */
.menu-divider{height:1px;background:var(--line);margin:6px 0} /* 17 */
.menu-user{display:flex;align-items:center;gap:8px;padding:6px 14px} /* 12 */
.menu-action{display:block;width:100%;padding:6px 14px;font-size:14px;color:var(--ink-muted);text-align:left;cursor:pointer} /* 12 */
.menu-action:hover{background:var(--bg-hover)} /* 12 */
.section-header{display:flex;align-items:center;gap:4px;width:calc(100% - 12px);margin:0 6px;padding:4px 8px;border-radius:var(--radius);font-size:12px;font-weight:600;color:var(--ink-faint);text-align:left;cursor:pointer} /* 12 */
.section-header:hover{background:var(--bg-hover)} /* 12 */
.section-header.static{cursor:default} /* 12 */
.section-header.static:hover{background:none} /* 12 */
.section-gap{height:14px} /* 12 */
.page-menu{position:absolute;top:34px;right:0;width:230px;z-index:40;background:var(--bg);border-radius:var(--radius-lg);box-shadow:var(--shadow-pop);padding:6px 0} /* 10 */
.page-menu button{display:flex;align-items:center;gap:8px;width:100%;padding:6px 14px;font-size:14px;text-align:left;cursor:pointer} /* 10 */
.page-menu button:hover{background:var(--bg-hover)} /* 10 */
.page-menu button.danger{color:var(--danger)} /* 10 */
.doc-scroll{flex:1;overflow-y:auto} /* 10 */
.cover{position:relative;height:220px;background:linear-gradient(120deg,#d8e6ef 0%,#e8dfef 45%,#fbf0d9 100%)} /* 10 */
.cover-actions{position:absolute;right:96px;bottom:12px;opacity:0;transition:opacity 20ms ease-in} /* 10 */
.cover:hover .cover-actions{opacity:1} /* 10 */
.cover-btn{height:26px;padding:0 8px;border-radius:var(--radius);background:var(--bg);color:var(--ink-muted);font-size:12px;box-shadow:var(--shadow-card);cursor:pointer} /* 10 */
.cover-btn:hover{color:var(--ink)} /* 10 */
.doc{max-width:708px;margin:0 auto;padding:0 0 30vh} /* 10 */
.doc-inner{padding:0 2px} /* 10 */
.page-icon{font-size:78px;line-height:1;margin-top:-40px;display:inline-block;cursor:pointer;border-radius:var(--radius)} /* 10 */
.page-icon:hover{background:var(--bg-hover)} /* 10 */
.doc-title{font-size:40px;font-weight:700;letter-spacing:-0.02em;line-height:1.2;margin:6px 0 8px;padding:3px 2px;outline:none} /* 10 */
.doc-title:empty:before{content:"제목 없음";color:var(--ink-faint)} /* 10 */
.doc-title:focus{box-shadow:0 0 0 2px var(--accent-bg) inset;border-radius:var(--radius)} /* 10 */
.block{position:relative;margin:1px 0} /* 10 */
.block > .block-content{padding:3px 2px;outline:none} /* 10 */
.block > .block-content:focus{box-shadow:0 0 0 2px var(--accent-bg) inset;border-radius:var(--radius)} /* 10 */
.block-handles{position:absolute;left:-44px;top:2px;display:flex;gap:1px;opacity:0;transition:opacity 20ms ease-in} /* 10 */
.block:hover .block-handles{opacity:1} /* 10 */
.block.is-dragging{opacity:.4} /* 10 */
.block.drop-target{box-shadow:0 -2px 0 var(--accent)} /* 10 */
.handle{width:20px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius);color:var(--ink-faint);cursor:grab} /* 10 */
.handle:hover{background:var(--bg-hover);color:var(--ink-muted)} /* 10 */
.handle.add{cursor:pointer} /* 10 */
.is-readonly .block-handles{display:none} /* 10 */
h1.block-content{font-size:30px;font-weight:600;letter-spacing:-0.01em;margin:1.4em 0 .25em} /* 10 */
h2.block-content{font-size:24px;font-weight:600;margin:1.4em 0 .25em} /* 10 */
h3.block-content{font-size:20px;font-weight:600;margin:1.4em 0 .25em} /* 10 */
.doc code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.85em;background:rgba(135,131,120,.15);color:var(--danger);padding:.15em .35em;border-radius:var(--radius)} /* 10 */
.doc s{color:var(--ink-muted)} /* 10 */
.list{padding-left:26px;margin:0} /* 10 */
.list li{padding:3px 2px} /* 10 */
.list .list{padding-left:24px;margin:1px 0} /* 10 */
.todo{display:flex;align-items:flex-start;gap:8px;padding:3px 2px} /* 10 */
.todo input[type=checkbox]{appearance:none;width:16px;height:16px;margin-top:4px;flex:none;border:1.5px solid var(--ink-faint);border-radius:2px;cursor:pointer;position:relative} /* 10 */
.todo input[type=checkbox]:checked{background:var(--accent);border-color:var(--accent)} /* 10 */
.todo input[type=checkbox]:checked:after{content:"";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid #fff;border-width:0 1.8px 1.8px 0;transform:rotate(42deg)} /* 10 */
.todo .todo-text{flex:1;outline:none} /* 10 */
.todo.is-done .todo-text{text-decoration:line-through;color:var(--ink-faint)} /* 10 */
.toggle-head{display:flex;align-items:flex-start;gap:6px;cursor:pointer} /* 10 */
.toggle-caret{width:18px;height:24px;flex:none;display:flex;align-items:center;justify-content:center;color:var(--ink-muted);border-radius:var(--radius);transition:transform 100ms ease-in} /* 10 */
.toggle-caret:hover{background:var(--bg-hover)} /* 10 */
.toggle-body{padding:2px 0 2px 24px} /* 10 */
blockquote.block-content{margin:6px 0;padding:2px 0 2px 14px;border-left:3px solid var(--ink)} /* 10 */
.callout{display:flex;gap:10px;padding:14px 16px;border-radius:var(--radius);background:var(--warn-bg)} /* 10 */
.callout .callout-emoji{font-size:18px;line-height:1.4;flex:none} /* 10 */
.divider{height:1px;background:var(--line);margin:14px 0} /* 10 */
.code-block{position:relative;background:var(--bg-input);border-radius:var(--radius);padding:28px 16px 16px} /* 10 */
.code-block .lang{position:absolute;top:6px;left:14px;font-size:12px;color:var(--ink-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace} /* 10 */
.code-block pre{margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:14px;line-height:1.6;color:var(--ink);white-space:pre;overflow-x:auto} /* 10 */
table.doc-table{border-collapse:collapse;width:100%;font-size:14px;table-layout:fixed} /* 10 */
table.doc-table th,table.doc-table td{border:1px solid var(--line);padding:7px 9px;text-align:left;vertical-align:top;overflow:hidden;text-overflow:ellipsis} /* 10 */
table.doc-table th{background:var(--bg-input);font-weight:600;font-size:13px} /* 10 */
table.doc-table tr:hover td{background:var(--bg-hover)} /* 10 */
figure.doc-image{margin:6px 0} /* 10 */
.image-placeholder{height:220px;border-radius:var(--radius);background:repeating-linear-gradient(135deg,#f1f1ef 0 10px,#e9e9e6 10px 20px);display:flex;align-items:center;justify-content:center} /* 10 */
.image-placeholder span{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-muted)} /* 10 */
figure.doc-image figcaption{font-size:12px;color:var(--ink-muted);padding:6px 2px} /* 10 */
.page-link{display:inline-flex;align-items:center;gap:6px;color:var(--ink);text-decoration:underline;text-decoration-color:var(--line);cursor:pointer} /* 10 */
.page-link:hover{background:var(--bg-hover)} /* 10 */
.format-toolbar{position:absolute;z-index:50;display:flex;align-items:center;gap:1px;background:#2f2f2c;border-radius:var(--radius);padding:3px;box-shadow:var(--shadow-pop)} /* 10 */
.format-toolbar button{min-width:28px;height:26px;padding:0 7px;border-radius:2px;color:#e9e9e6;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center} /* 10 */
.format-toolbar button:hover{background:rgba(255,255,255,.12)} /* 10 */
.comments{width:300px;min-width:300px;height:100vh;border-left:1px solid var(--line);display:flex;flex-direction:column;background:var(--bg)} /* 10 */
.comments-head{height:45px;min-height:45px;display:flex;align-items:center;justify-content:space-between;padding:0 14px;font-size:14px;font-weight:600;border-bottom:1px solid var(--line)} /* 10 */
.comments-body{flex:1;overflow-y:auto;padding:12px} /* 10 */
.thread.is-resolved{opacity:.5} /* 10 */
.thread .quoted{font-size:12px;color:var(--ink-muted);background:var(--warn-bg);padding:2px 4px;border-radius:2px;display:inline-block;margin-bottom:8px} /* 10 */
.comment{display:flex;gap:8px;margin-bottom:10px} /* 10 */
.comment:last-child{margin-bottom:0} /* 10 */
.comment .who{font-size:13px;font-weight:600} /* 10 */
.comment .when{font-size:11px;color:var(--ink-faint);margin-left:6px} /* 10 */
.thread-foot button{font-size:12px;color:var(--ink-muted)} /* 10 */
.thread-foot button:hover{color:var(--ink);text-decoration:underline} /* 10 */
.comments-foot{border-top:1px solid var(--line);padding:10px 12px} /* 10 */
.comment-input:focus{outline:none;box-shadow:0 0 0 2px var(--accent-bg) inset} /* 10 */
.comment-hint{font-size:11px;color:var(--ink-faint);margin-top:6px} /* 10 */
.view-tab{height:32px;padding:0 8px;border-radius:var(--radius) var(--radius) 0 0;font-size:14px;color:var(--ink-muted);cursor:pointer;display:flex;align-items:center;gap:6px;border-bottom:2px solid transparent}
.view-tab:hover{background:var(--bg-hover)}
.view-tab.is-active{color:var(--ink);font-weight:600;border-bottom-color:var(--ink)}
.tool-btn:hover{background:var(--bg-hover)}
.tool-btn.is-active{background:var(--bg-active);color:var(--ink)}
.select-bar{display:flex;align-items:center;gap:10px;margin:10px var(--page-pad) 0;padding:6px 10px;background:var(--accent-bg);border-radius:var(--radius);font-size:13px}
.select-bar .count{font-weight:600}
.select-bar .danger-btn{height:26px;padding:0 10px;border-radius:var(--radius);color:var(--danger);font-size:13px;cursor:pointer;margin-left:auto}
.select-bar .danger-btn:hover{background:rgba(235,87,87,.1)}
.tag.gray{background:var(--tag-gray)} /* 9 */
.tag.brown{background:var(--tag-brown)}
.tag.orange{background:var(--tag-orange)} /* 5 */
.tag.yellow{background:var(--tag-yellow)} /* 9 */
.tag.green{background:var(--tag-green)} /* 9 */
.tag.blue{background:var(--tag-blue)} /* 5 */
.tag.purple{background:var(--tag-purple)} /* 5 */
.tag.pink{background:var(--tag-pink)}
.tag.red{background:var(--tag-red)} /* 9 */
.tag-list{display:flex;align-items:center;gap:4px;overflow:hidden}
.avatar.blue{background:var(--tag-blue)} /* 9 */
.avatar.green{background:var(--tag-green)} /* 9 */
.avatar.orange{background:var(--tag-orange)} /* 9 */
.avatar.purple{background:var(--tag-purple)} /* 9 */
.avatar.pink{background:var(--tag-pink)} /* 9 */
.more-btn:hover{background:var(--bg-active);color:var(--ink)}
.btn-danger-text:hover{background:rgba(235,87,87,.1)} /* 6 */
.modal-title{font-size:16px;font-weight:600;margin:0 0 10px} /* 7 */
.modal-impact strong{font-weight:600} /* 6 */
.modal-label{display:block;font-size:12px;color:var(--ink-muted);margin-bottom:6px} /* 6 */
.modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:18px} /* 7 */
.btn-danger:hover{filter:brightness(.95)} /* 6 */
.btn-danger:disabled{background:var(--bg-input);color:var(--ink-faint);cursor:default;filter:none} /* 6 */
.tooltip-host{position:relative;display:inline-flex} /* 6 */
.btn-secondary:disabled{color:var(--ink-faint);cursor:default} /* 5 */
.chip.green{background:var(--tag-green)} /* 5 */
.chip-list{display:flex;flex-wrap:wrap;gap:4px} /* 5 */
.select{height:28px;border:none;border-radius:var(--radius);background:var(--bg-input);padding:0 6px;font:inherit;font-size:13px;color:var(--ink)} /* 5 */
.select:focus{outline:none;box-shadow:0 0 0 2px var(--accent-bg) inset} /* 5 */
.icon-btn{width:26px;height:26px;border-radius:var(--radius);color:var(--ink-muted);display:flex;align-items:center;justify-content:center} /* 5 */
.icon-btn:hover{background:var(--bg-hover)} /* 5 */
.modal-text{font-size:13px;color:var(--ink-muted);line-height:1.7;margin:0 0 16px} /* 5 */
/* 모달 안의 입력 한 칸 묶음 — SC-18_workspaces.html에서 그대로 가져왔다(devplan003 part001).
   목업에는 있었는데 개발로 안 옮겨져서, 워크스페이스 만들기 모달의 칸 사이 간격이
   통째로 빠져 있었다. */
.modal-field{margin-bottom:16px}
.modal-field .modal-label{margin-bottom:6px}
.modal-error{font-size:12px;color:var(--danger);margin-top:6px}
.modal-help{font-size:12px;color:var(--ink-faint);margin-top:6px;line-height:1.5}
.role-radios{display:flex;gap:16px;margin-top:2px}
.chip-input{min-height:40px;display:flex;flex-wrap:wrap;align-items:center;gap:6px;background:var(--bg-input);border-radius:var(--radius);padding:6px 8px} /* 5 */
.chip-input:focus-within{box-shadow:0 0 0 2px var(--accent-bg) inset} /* 5 */
.chip-input input{flex:1;min-width:120px;height:26px;border:none;background:transparent;font:inherit;font-size:14px;color:var(--ink)} /* 5 */
.chip-input input:focus{outline:none} /* 5 */
.radio-row{display:flex;gap:16px} /* 5 */
.radio-opt,.check-opt{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer} /* 5 */
.radio-opt input,.check-opt input{appearance:none;width:16px;height:16px;flex:none;position:relative;border:1.5px solid var(--ink-faint);border-radius:50%;cursor:pointer} /* 5 */
.check-opt input{border-radius:2px} /* 5 */
.radio-opt input:checked,.check-opt input:checked{background:var(--accent);border-color:var(--accent)} /* 5 */
.radio-opt input:checked:after{content:"";position:absolute;left:4px;top:4px;width:5px;height:5px;border-radius:50%;background:#fff} /* 5 */
.check-opt input:checked:after{content:"";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid #fff;border-width:0 1.7px 1.7px 0;transform:rotate(42deg)} /* 5 */
.stepper{display:flex;align-items:center;gap:8px;margin-bottom:28px;flex-wrap:wrap} /* 5 */
.step{display:flex;align-items:center;gap:8px} /* 5 */
.step .dot{width:24px;height:24px;border-radius:50%;flex:none;background:var(--bg-input);color:var(--ink-faint);font-size:12px;display:flex;align-items:center;justify-content:center} /* 5 */
.step .step-label{font-size:13px;color:var(--ink-faint);white-space:nowrap} /* 5 */
.step.is-current .dot{background:var(--accent);color:#fff} /* 5 */
.step.is-current .step-label{color:var(--ink);font-weight:600} /* 5 */
.step.is-done .dot{background:var(--ok-bg);color:#3f9142} /* 5 */
.step.is-done .step-label{color:var(--ink-muted)} /* 5 */
.step-line{width:26px;height:1px;background:var(--line);flex:none} /* 5 */
.callout-warn{background:var(--warn-bg);border-radius:var(--radius);padding:14px 16px;margin-bottom:22px} /* 5 */
.callout-warn .callout-title{font-size:13px;font-weight:600;margin-bottom:8px} /* 5 */
.callout-warn ol{margin:0;padding-left:18px;font-size:13px;line-height:1.9;color:var(--ink)} /* 5 */
.callout-gray{background:var(--bg-input);border-radius:var(--radius);padding:14px 16px;margin-bottom:22px} /* 5 */
.callout-gray .callout-title{font-size:13px;font-weight:600;margin-bottom:8px} /* 5 */
.callout-gray ul{margin:0;padding-left:18px;font-size:13px;line-height:1.9;color:var(--ink-muted)} /* 5 */
.progress-track{height:4px;border-radius:2px;background:var(--bg-input);overflow:hidden} /* 5 */
.progress-fill{height:100%;background:var(--accent);border-radius:2px} /* 5 */
.progress-big{height:8px;border-radius:4px;background:var(--bg-input);overflow:hidden;margin-bottom:10px} /* 5 */
.progress-big .progress-fill{height:100%} /* 5 */
.progress-caption{display:flex;align-items:center;justify-content:space-between;font-size:13px;margin-bottom:22px} /* 5 */
.progress-caption .pct{font-weight:600} /* 5 */
.tooltip-host.block{display:block} /* 5 */

/* ===== part014 — 가져오기 STEP3(진행률)·STEP4(결과·되돌리기) =====
   design/mockups/SC-19_admin_import.html의 같은 이름 규칙을 따르되, 이 파일에
   정의된 변수만 쓴다(#3f9142/#c1893a 같은 하드코딩 색은 --ok-bg/--accent/--danger로 치환). */
.muted{color:var(--ink-muted);font-size:13px}
.callout-text{margin:0;font-size:13px;color:var(--ink-muted);line-height:1.6}
.form-block{margin-bottom:26px}
.run-row{display:flex;align-items:center;gap:12px;border-top:1px solid var(--line);padding-top:16px}
.current-file{
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-muted);
  background:var(--bg-input);border-radius:var(--radius);padding:8px 10px;margin-top:10px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
/* 서버 실행 명령 등 줄바꿈 없이 잘리면 안 되는 텍스트(관리자가 통째로 복사해야 한다) */
.current-file.is-command{white-space:pre-wrap;overflow:visible;text-overflow:clip;word-break:break-all}
.import-summary{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;font-size:14px}
.import-summary > li{padding-bottom:10px;border-bottom:1px solid var(--line)}
.import-summary > li:last-child{border-bottom:none;padding-bottom:0}
.import-summary ul{list-style:none;margin:8px 0 0;padding:0;display:flex;flex-direction:column;gap:6px}
.import-cannot{list-style:none;margin:0;padding:0}
.import-cannot li{position:relative;padding-left:14px;font-size:13px;color:var(--ink)}
.import-cannot li::before{content:"·";position:absolute;left:0;color:var(--ink-faint)}
.done-head{display:flex;align-items:center;gap:10px;margin-bottom:20px}
.done-head .done-icon{
  width:36px;height:36px;border-radius:50%;background:var(--ok-bg);color:var(--accent);
  display:flex;align-items:center;justify-content:center;flex:none;font-size:16px;font-weight:700;
}
.done-head .done-title{font-size:20px;font-weight:700;margin:0}
.fail-row{display:flex;flex-direction:column;gap:2px;padding:6px 0;border-bottom:1px solid var(--line);font-size:13px}
.fail-row:last-child{border-bottom:none}
.fail-row .fpath{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fail-row .freason{font-size:12px;color:var(--danger)}
.link-row-item{display:block;padding:4px 0;font-size:13px;color:var(--ink-muted)}
.final-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;border-top:1px solid var(--line);padding-top:18px;margin-top:22px}

/* ===== part015 — 감사 로그(SC-23) · 파일 사용량(SC-25) =====
   design/mockups/SC-23_audit.html · SC-25_storage.html은 화면 구조만 참고했다.
   토큰 변수(tokens.css)만 쓰고 색은 하드코딩하지 않는다. */

/* 여러 관리자 화면이 이미 class="faint"를 쓰고 있었는데 정의가 빠져 있었다
   (예: workspaces.php, members.php). 감사 로그 화면에서도 그대로 필요해 함께 채운다. */
.faint{color:var(--ink-faint);font-size:12px}

/* 표의 숫자 칸(오른쪽 정렬 + 줄바꿈 방지). 파일 사용량 화면의 파일 수·용량 칸에 쓴다. */
.admin-table .num{text-align:right;white-space:nowrap}

/* ---------- 감사 로그 필터 바 ---------- */
.filter-bar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:16px}
.filter-bar .filter-item{display:flex;align-items:center;gap:6px}
.filter-bar .filter-item .f-label{font-size:12px;color:var(--ink-faint);white-space:nowrap}
.filter-bar .spacer{flex:1}

/* ---------- 감사 로그 표 ---------- */
.audit-table .col-time{width:150px;white-space:nowrap}
.audit-table .col-actor{width:160px}
.audit-table .col-ip{width:130px;white-space:nowrap}
.audit-table .ip-cell{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-faint)}
.audit-table .meta-pre{
  margin:6px 0 0;max-width:420px;max-height:220px;overflow:auto;
  background:var(--bg-input);border-radius:var(--radius);padding:8px 10px;
  font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink);
  white-space:pre-wrap;word-break:break-all;
}
.audit-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;padding:48px 0;color:var(--ink-faint)}
.audit-empty .empty-text{font-size:14px}
.audit-empty .empty-sub{font-size:12px}
.more-row{display:flex;align-items:center;gap:10px;margin-top:16px}

/* ---------- 파일 사용량 ---------- */
.storage-total{margin-bottom:22px}
.storage-total .total-value{font-size:28px;font-weight:700;letter-spacing:-0.01em}
.dedup-box{
  display:flex;align-items:flex-start;gap:10px;max-width:900px;
  background:var(--ok-bg);border-radius:var(--radius);padding:12px 14px;
  font-size:13px;line-height:1.6;margin-bottom:24px;
}
.dedup-box .d-icon{flex:none;margin-top:1px}
.section-block{margin-bottom:28px}
.storage-bar{width:100%;height:6px;border-radius:3px;background:var(--bg-input);overflow:hidden;display:flex}
.storage-bar .storage-bar-fill{display:block;height:100%;background:var(--accent);border-radius:3px}
.ratio-cell{display:flex;align-items:center;gap:8px;min-width:140px}
.ratio-cell .storage-bar{flex:1;min-width:60px}

/* ---------- 편집 잠금 강제 해제(part015 · modules/admin/CONTRACT.md §6) ----------
   .lock-btn 자체(크기·배경)는 editor.css의 잠금 배너 스타일을 그대로 물려받는다.
   여기서는 "되돌릴 수 없는 관리자 행위"임을 색으로만 구분한다.
   주의: editor.css가 layouts/app.php에서 components.css보다 나중에 로드되므로,
   같은 특정성(.lock-banner .lock-btn)의 색 규칙을 여기서 얹으면 뒤에 오는 editor.css가
   이긴다. #forceReleaseBtn(id)로 특정성을 높여 로드 순서와 무관하게 적용되게 한다. */
#forceReleaseBtn.lock-btn-danger{color:var(--danger)}

/* ---------- 휴지통 선택 삭제(part015 · modules/admin/CONTRACT.md §5) ----------
   행 체크박스. .todo 체크박스(에디터 안 할 일 목록)와 같은 모양으로 통일감을 준다. */
.trash-check{appearance:none;width:16px;height:16px;flex:none;border:1.5px solid var(--ink-faint);border-radius:2px;cursor:pointer;position:relative;vertical-align:middle}
.trash-check:checked{background:var(--accent);border-color:var(--accent)}
.trash-check:checked:after{content:"";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid #fff;border-width:0 1.8px 1.8px 0;transform:rotate(42deg)}
.trash-bulk-bar{display:flex;align-items:center;gap:10px;margin-bottom:10px}
.trash-bulk-bar .select-count{font-size:13px;color:var(--ink-muted)}
.ratio-cell .ratio-pct{font-size:12px;color:var(--ink-faint);width:36px;text-align:right;flex:none}
.file-name{display:flex;align-items:center;gap:8px;min-width:0}
.file-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.imported-badge{
  flex:none;font-size:10px;color:var(--ink-muted);background:var(--bg-input);
  border-radius:2px;padding:1px 5px;white-space:nowrap;
}
.workspace-select-form{display:flex;align-items:center;gap:8px;margin-bottom:14px}

/* ===== part002 — 인증·오류 화면(SC-01/SC-24) =====
   design/mockups/SC-01_auth.html, SC-24_errors.html에서 값 그대로 가져왔다. */
.card{width:400px;max-width:100%;display:flex;flex-direction:column}
.card-title{font-size:22px;font-weight:700;letter-spacing:-0.01em;margin:0 0 6px}
.card-sub{font-size:13px;color:var(--ink-muted);margin:0 0 22px}
.card-foot{font-size:12px;color:var(--ink-faint);text-align:center;margin-top:10px}
.link-row{display:flex;justify-content:center;margin-top:16px}
.link-row button{font-size:13px;color:var(--accent)}
.link-row button:hover{text-decoration:underline}
.notice{display:flex;align-items:flex-start;gap:8px;background:var(--warn-bg);border-radius:var(--radius);padding:10px 12px;font-size:13px;line-height:1.5;margin-bottom:18px}
.notice .notice-icon{flex:none;color:var(--ink-muted);margin-top:1px}
/* SC-01 초대 수락 카드 상단의 "○○님이 회원님을 ○○ 팀에 초대했습니다" 줄.
   목업의 invite-head/invite-msg는 이 화면에만 있는 이름이라 같은 계열인
   .inviter/.inviter-text로 대체했다(devplan003 part002, CONTRACT §3). */
.inviter{display:flex;align-items:center;gap:10px;background:var(--bg);border-radius:var(--radius-lg);box-shadow:var(--shadow-card);padding:12px;margin-bottom:18px}
.inviter .inviter-text{font-size:13px;line-height:1.45}
.inviter .inviter-text strong{font-weight:600}
.error-card{width:400px;max-width:100%;display:flex;flex-direction:column;align-items:center;text-align:center}
.error-icon{width:56px;height:56px;border-radius:50%;background:var(--bg-input);display:flex;align-items:center;justify-content:center;color:var(--ink-faint);margin-bottom:20px}
.error-title{font-size:20px;font-weight:700;letter-spacing:-0.01em;margin:0 0 10px}
.error-desc{font-size:14px;color:var(--ink-muted);line-height:1.65;margin:0 0 24px}
.error-actions{display:flex;flex-direction:column;gap:8px;width:100%}
.error-code{display:flex;align-items:center;gap:8px;margin-top:22px;font-size:12px;color:var(--ink-faint)}
.error-code .code-value{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}

/* ===== part003 — 홈·워크스페이스(SC-03) =====
   design/mockups/SC-03_app_shell.html:174-215에서 값 그대로 가져왔다.
   (반응형 분기는 같은 목업 218-231 → public/assets/css/responsive.css로 옮겼다.) */
.home{padding:0 var(--page-pad) 96px;max-width:1180px}
.greeting{font-size:32px;font-weight:700;letter-spacing:-0.02em;margin:24px 0 40px}
.home-section{margin-bottom:40px}

/* 최근 방문 */
.recent-strip{display:flex;gap:12px;overflow-x:auto;padding-bottom:8px}
.recent-card{
  flex:none;width:184px;height:120px;
  border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:12px;display:flex;flex-direction:column;justify-content:space-between;
  cursor:pointer;text-align:left;transition:background 20ms ease-in;
}
.recent-card:hover{background:var(--bg-hover)}
.recent-card .emoji{font-size:20px;line-height:1}
.recent-card .name{font-size:14px;font-weight:500;line-height:1.35}
/* 목업은 .when에 style="display:block"을 직접 박아 뒀다(검수용 장치). 뷰에는 인라인
   스타일을 남기지 않는다는 규칙(CONTRACT §3)에 따라 그 선언을 여기로 옮긴다 — 보이는
   결과는 목업과 같다. */
.recent-card .when{font-size:12px;color:var(--ink-faint);margin-top:4px;display:block}

/* 내가 만든 페이지 */
.page-row{
  display:grid;grid-template-columns:22px minmax(160px,1fr) 120px 110px;
  align-items:center;gap:10px;
  width:100%;padding:7px 8px;border-radius:var(--radius);
  font-size:14px;text-align:left;cursor:pointer;transition:background 20ms ease-in;
}
.page-row:hover{background:var(--bg-hover)}
.page-row .title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.page-row .ws{font-size:12px;color:var(--ink-muted)}
.page-row .edited{font-size:12px;color:var(--ink-faint)}

/* 워크스페이스 카드 */
.ws-grid{display:grid;grid-template-columns:repeat(2,minmax(220px,320px));gap:12px}
.ws-card{
  border:1px solid var(--line);border-radius:var(--radius-lg);
  padding:16px;text-align:left;cursor:pointer;transition:background 20ms ease-in;
}
.ws-card:hover{background:var(--bg-hover)}
.ws-card .head{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.ws-card .emoji{font-size:18px;line-height:1}
.ws-card .name{font-size:16px;font-weight:600}
.ws-card .meta{font-size:12px;color:var(--ink-muted)}

/* workspace/show.php — SC-03에 별도 목업이 없는 "워크스페이스 진입" 화면. 홈과 같은
   .home/.home-section/.greeting 계열을 그대로 쓰되(CONTRACT §3 "목업에 없는 화면"),
   기존 뷰에 남아 있던 인라인 style="..."을 부모 스코프 클래스로 옮긴 것뿐이다.
   새 시각 규칙을 만들지 않았다 — 원래 인라인에 있던 값 그대로다. */
.home-section.ws-intro{margin-bottom:8px}
.ws-intro .emoji{font-size:40px;line-height:1;display:inline-block}
.ws-intro .greeting{margin:8px 0 4px}
.ws-toolbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.ws-toolbar .section-title{margin:0}
.error-foot{font-size:12px;color:var(--ink-faint);margin-top:18px;line-height:1.6}

/* ===== part006 — 휴지통(SC-12) =====
   design/mockups/SC-12_trash.html:636-699에서 값 그대로 가져왔다. .state-bar·상태 전환
   스크립트·ITEMS 더미 데이터는 검수용이라 옮기지 않았다(CONTRACT §4). */
.trash-head{padding:24px var(--page-pad) 0}
.trash-title-row{display:flex;align-items:center;gap:10px;margin-bottom:6px}
.trash-page-icon{color:var(--ink-muted);display:flex}
.trash-title{font-size:32px;font-weight:700;letter-spacing:-0.02em;margin:0}
.trash-note{font-size:13px;color:var(--ink-muted);margin:0 0 16px}
.trash-bar{display:flex;align-items:center;gap:10px;justify-content:space-between;border-bottom:1px solid var(--line);flex-wrap:wrap}
.ws-tabs{display:flex;gap:2px;flex:none}
.ws-tab{height:32px;padding:0 10px;border-radius:var(--radius) var(--radius) 0 0;font-size:14px;color:var(--ink-muted);border-bottom:2px solid transparent;white-space:nowrap}
.ws-tab:hover{background:var(--bg-hover)}
.ws-tab.is-active{color:var(--ink);font-weight:600;border-bottom-color:var(--ink)}
.trash-tools{display:flex;align-items:center;gap:8px;padding-bottom:4px;flex:none}
.trash-search{height:28px;width:220px;display:flex;align-items:center;gap:6px;background:var(--bg-input);border-radius:var(--radius);padding:0 8px}
.trash-search input{flex:1;min-width:0;border:none;background:transparent;font:inherit;font-size:13px;color:var(--ink)}
.trash-search input:focus{outline:none}
.trash-search:focus-within{box-shadow:0 0 0 2px var(--accent-bg) inset}
.trash-search .s-icon{color:var(--ink-faint);display:flex;flex:none}
.trash-wrap{padding:0 var(--page-pad) 80px;overflow-x:auto}
.trash-table{width:100%;border-collapse:collapse;font-size:14px;min-width:720px}
.trash-table th{text-align:left;font-size:12px;font-weight:600;color:var(--ink-faint);padding:8px;border-bottom:1px solid var(--line);white-space:nowrap}
.trash-table td{padding:8px;border-bottom:1px solid var(--line);vertical-align:middle}
.trash-table tbody tr:hover{background:var(--bg-hover)}
.trash-table tbody tr:hover .row-actions{opacity:1} /* SC-12:687-688을 .trash-table로 스코프 — 목업은 무스코프 tbody라 다른 표(.admin-table 등)까지 새지 않게 했다 */
.trash-table .col-name{min-width:220px}
.trash-table .col-actions{width:170px}
.t-name{display:flex;align-items:center;gap:8px;min-width:0}
.t-name .t-emoji{font-size:15px;line-height:1;flex:none}
.t-name .t-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.child-badge{flex:none;font-size:11px;color:var(--ink-muted);background:var(--bg-input);border-radius:2px;padding:1px 6px;white-space:nowrap}
.t-path{font-size:13px;color:var(--ink-muted);display:flex;align-items:center;gap:5px;min-width:0}
.t-path span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-path.is-gone{color:var(--ink-faint)}
.t-left{font-size:13px;white-space:nowrap}
.t-left.is-soon{color:var(--danger)}
.trash-summary{padding:10px 8px 0;font-size:12px;color:var(--ink-faint)}
.trash-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:80px 0;color:var(--ink-faint)}
.trash-empty .empty-text{font-size:14px}

/* 선택 삭제용 체크박스 열(modules/admin/CONTRACT.md §5) — 목업(SC-12)에는 일괄 선택 기능이
   없어 .col-select 자체가 없다. 새 색은 쓰지 않고, 이미 있는 체크박스(16px, .trash-check)가
   칸 여백(8px×2)과 함께 들어갈 만큼만 폭을 정했다(devplan003 part006, CONTRACT §3 옵션3). */
.trash-table .col-select{width:36px}

/* ===== part007 — 관리자 설정 공통 탭·폼(SC-15) =====
   design/mockups/SC-15_settings.html:106-244에서 값 그대로 가져왔다. 이 규칙들은 SC-15
   자체에 목업 화면(개인 설정)이 없는 team.php·mail_settings.php·member_invite.php·
   members.php에서도 함께 쓴다 — 이 다섯 화면이 이미 공유해 온 관리자 폼 관례이고,
   SC-15의 공용 스타일 블록(개인 설정 화면들과 같은 <style>)에 값 그대로 있다. */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:14px}
.tab{height:32px;padding:0 10px;font-size:14px;color:var(--ink-muted);border-bottom:2px solid transparent;white-space:nowrap}
.tab:hover{background:var(--bg-hover)}
.tab.is-active{color:var(--ink);font-weight:600;border-bottom-color:var(--ink)}
.member{display:flex;align-items:center;gap:8px;min-width:0}
.member .mname{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.member .me{font-size:11px;color:var(--ink-faint)}
.form-label{font-size:13px;font-weight:600;margin-bottom:6px}
.form-help{font-size:12px;color:var(--ink-faint);margin-bottom:8px}
.ws-assign{display:flex;flex-direction:column;gap:8px}
.ws-assign-row{display:grid;grid-template-columns:minmax(140px,1fr) 200px;align-items:center;gap:12px;border:1px solid var(--line);border-radius:var(--radius);padding:10px 12px}
.ws-assign-row .ws-name{display:flex;align-items:center;gap:8px;font-size:14px;min-width:0}
.ws-assign-row .ws-name span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.form-foot{display:flex;align-items:center;gap:12px;border-top:1px solid var(--line);padding-top:16px}
.form-foot .foot-hint{font-size:12px;color:var(--ink-faint)}

/* admin/members.php의 역할 변경 <select>는 change 시 즉시 자기 <form>을 제출한다(F-A-08).
   목업(SC-15/SC-19)은 이 즉시제출 폼이 없어 대응 클래스가 없다 — .row-actions 안에서
   옆 text-btn과 높이가 맞도록 정렬만 새로 정했다(devplan003 part007, CONTRACT §3 옵션3). */
.role-form{display:inline-flex;align-items:center}

/* admin/member_invite.php: 메일 미설정 시 초대 링크를 보여주는 복사 줄. 목업(SC-19)의
   .chip-input을 그대로 쓰되, 안에 인라인 style="margin-top:8px"/"flex:1;background:transparent"가
   남아 있었다(CONTRACT §3 "인라인 스타일 걷어내기"). 값은 그대로, 선언만 클래스로 옮겼다. */
.invite-link-row{margin-top:8px}
.invite-link-row .input{flex:1;background:transparent}

/* admin/member_invite.php의 이메일 여러 줄 입력은 목업(SC-19)의 JS 칩 입력과 달리 원문
   그대로 서버로 보내는 <textarea class="input">라 대응 목업이 없다. .input의 고정
   height:40px가 rows="4" textarea를 짓누르던 것도 함께 풀었다(기존 인라인 style 그대로 이관). */
textarea.input{width:100%;height:auto;resize:vertical}

/* ===== part008 — 워크스페이스 관리·슈퍼관리자·가져오기(SC-18·SC-19) =====
   design/mockups/SC-18_workspaces.html:404-484에서 값 그대로 가져왔다(워크스페이스 표 행·
   멤버 배정/인수인계 모달). admin/workspaces.php · workspace/settings/members.php ·
   admin/workspaces_trash.php가 함께 쓴다. */
.ws-row-name{display:flex;align-items:center;gap:8px;min-width:0}
.ws-row-name .ws-emoji{font-size:16px;line-height:1;flex:none}
.ws-row-name .ws-title{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.admin-table tr.is-archived td{opacity:.55}
.archived-badge{
  flex:none;font-size:11px;color:var(--ink-muted);background:var(--bg-input);
  border-radius:2px;padding:1px 6px;white-space:nowrap;
}
.usage-cell{display:flex;align-items:center;gap:8px;min-width:90px}
.usage-bar{width:56px;height:4px;border-radius:2px;background:var(--bg-input);overflow:hidden;flex:none;display:flex}
.usage-fill{display:block;height:4px;background:var(--accent);border-radius:2px}

/* 멤버 배정/인수인계 모달 — admin/workspaces.php(인수인계)·workspace/settings/members.php
   (멤버 추가·주인 넘기기)가 같은 이름으로 쓴다. 두 화면 다 SC-18의 두 칸(assign-grid) 대신
   한 칸짜리 목록(assign-list 하나)만 쓰지만, 항목 하나(.assign-item과 그 안 .a-name/
   .a-mail/.a-plus)의 구조와 클래스는 그대로다(CONTRACT §3 — 같은 계열 목업 패턴을 따른다).
   .assign-col·.assign-grid·.assigned-row 등 두 칸 변형에서만 쓰는 규칙도 목업과 값을
   맞추려고 함께 옮겨 둔다. */
.modal.wide{width:720px}
.modal-overlay.overlay-top{align-items:flex-start;overflow-y:auto;padding:24px}
.modal.wide{max-height:calc(100vh - 48px);overflow-y:auto;margin:auto 0}
.assign-grid{display:grid;grid-template-columns:minmax(220px,1fr) minmax(240px,1.1fr);gap:16px}
.assign-col{border:1px solid var(--line);border-radius:var(--radius);display:flex;flex-direction:column;min-height:180px;max-height:40vh}
.assign-col-head{
  padding:8px 10px;border-bottom:1px solid var(--line);
  font-size:11px;font-weight:600;color:var(--ink-faint);
}
.assign-search{padding:8px 10px}
.assign-search input{
  width:100%;height:30px;border:none;border-radius:var(--radius);background:var(--bg-input);
  padding:0 8px;font:inherit;font-size:13px;color:var(--ink);
}
.assign-search input:focus{outline:none;box-shadow:0 0 0 2px var(--accent-bg) inset}
.assign-list{flex:1;overflow-y:auto;padding:0 6px 8px;min-height:0}
.assign-item{
  display:flex;align-items:center;gap:8px;width:100%;
  padding:6px 8px;border-radius:var(--radius);text-align:left;cursor:pointer;
}
.assign-item:hover{background:var(--bg-hover)}
.assign-item.is-taken{opacity:.45;cursor:default}
.assign-item.is-taken:hover{background:transparent}
.assign-item .a-meta{min-width:0;flex:1}
.assign-item .a-name{display:block;font-size:13px}
.assign-item .a-mail{display:block;font-size:11px;color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.assign-item .a-plus{color:var(--ink-faint);display:flex;flex:none}
.assigned-row{
  display:grid;grid-template-columns:1fr 120px 44px;align-items:center;gap:8px;
  padding:6px 8px;border-radius:var(--radius);
}
.assigned-row:hover{background:var(--bg-hover)}
.assigned-row .a-who{display:flex;align-items:center;gap:8px;min-width:0}
.assigned-row .a-who span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}
.assign-note{font-size:12px;color:var(--ink-faint);margin-top:14px;line-height:1.6}
.assign-empty{padding:16px 10px;font-size:12px;color:var(--ink-faint)}

@media (max-width:1024px){
  .modal.wide{width:100%}
  .assign-grid{grid-template-columns:1fr}
  .assign-col{min-height:220px}
}

/* 슈퍼관리자 회사 목록(platform/companies.php)의 [⋯] 팝업 메뉴(.menu-pop, SC-18과 값 동일).
   목업은 검수용이라 메뉴를 JS로 document.body에 붙이고 클릭한 버튼의 getBoundingClientRect()
   좌표를 계산해 배치한다 — 그 계산 자체가 목업 전용 장치라 그대로 옮기지 않는다(CONTRACT §4).
   이 화면은 정적으로 .row-actions 바로 안에 넣고 hidden을 토글하므로, .menu-pop이 기준으로
   삼을 position:relative를 .row-actions에 추가하고 top/right로 버튼 아래 오른쪽 정렬만
   새로 정했다(CONTRACT §3 옵션3 — 색·폭·그림자는 전부 목업 값 그대로, 배치 기준점만 새로 씀). */
.row-actions{position:relative}
.menu-pop{
  position:absolute;top:calc(100% + 4px);right:0;z-index:60;width:210px;
  background:var(--bg);border-radius:var(--radius-lg);box-shadow:var(--shadow-pop);padding:6px 0;
}
.menu-pop button{
  display:flex;align-items:center;gap:8px;width:100%;padding:6px 14px;
  font-size:14px;text-align:left;
}
.menu-pop button:hover{background:var(--bg-hover)}
.menu-pop button.danger{color:var(--danger)}

/* 가져오기 1단계 안내 목록(admin/import/index.php) — SC-19 STEP1은 이 안내를 .callout-warn
   안 <ol>(스타일 없는 맨 태그, .callout-warn ol이 값을 준다)로 넣지만, 이 화면은 "복원 불가"
   고지를 별도 callout-warn으로 아래에 한 번 더 둬야 해서(파일을 고르기 전에도, 실행 직전에도
   보여준다 — part008_노션마이그레이션설계.md §11) 안내 목록만 먼저 뺐다. 목업에 이 안내
   전용 클래스는 없어 .callout-warn ol과 같은 값으로 새로 썼다(CONTRACT §3 옵션3, 토큰·
   타이포는 목업 그대로 — components.css:232 .callout-warn ol 참고). */
.import-guide{margin:0;padding-left:18px;font-size:13px;line-height:1.9;color:var(--ink)}

/* 가져오기 1단계 업로드 진행 문구 — SC-19의 .run-row .eta(분석 시작 버튼 옆 안내)와 같은
   자리, 같은 값. */
.run-row .eta{font-size:13px;color:var(--ink-muted)}
