/* ==========================================================================
   Cosmotif 브랜드 토큰 (관리 세션 메일 2026-08-21 — 지시서 v1.30 §24 예정)
   ==========================================================================

   **다크가 기본이다.** 라이트는 아래 @media 로 남겨 둔다.

   ⚠ 색을 세 층으로 나눠 뒀다. **섞으면 기능이 죽는다** — 이게 그 메일의 핵심이었다.

   1) 브랜드 5색 (`--brand-*`) — 값의 정본. 화면 코드에서 직접 쓰지 말고 아래 2)를 쓴다.
   2) 자리 토큰 (`--bg`·`--fg`·`--accent` …) — 화면 코드가 쓰는 것.
   3) **상태 색은 여기 없다. 데이터다** (M3.6, `statuses` 표). 사용자가 설정에서 바꾼다.
      아래 `--st-*` 는 **DB 가 아직 안 읽힌 순간의 대비책**일 뿐이고, 상태 칩의 진짜 색은
      `statusColor()` 가 DB 에서 가져온다. 여기 값을 브랜드 색으로 바꾸면 사용자가 고른
      색을 덮어쓰는 게 아니라, **덮어쓰는 것처럼 보이는 순간이 생긴다.** 건드리지 말 것.

   ⚠ **스텝 6색(§20)도 여기 없다** — `app.js` 의 `STEP_COLORS` 다. 그 여섯은 서로 구별되는
   것이 목적인 범주형 색이라 브랜드 5색으로 대체할 수 없다.
   실측 2026-08-21: 바탕이 `#16161a` → `#0B0B0F` 로 어두워져 여섯 다 대비가 **올랐다**
   (3.97 ~ 6.40, 전부 3.0 이상). **밝기를 올릴 슬롯이 없다.**
*/
:root {
  color-scheme: dark light;

  /* 1) 브랜드 5색 — 링고 확정 */
  --brand-carbon:     #0B0B0F;   /* Carbon Black — 바탕 */
  --brand-warm-white: #F5F2EB;   /* Warm White — 본문 글자 */
  --brand-plum:       #4B2E83;   /* Deep Plum — 깊은 면 · 강조 서페이스 */
  --brand-periwinkle: #6366F1;   /* Electric Periwinkle — 주 동작색 */
  --brand-mint:       #3FE0B8;   /* Aurora Mint — 준비됨 · 완료 · 성공 */

  /* 2) 자리 토큰 — 화면 코드는 이것만 쓴다 */
  --bg: var(--brand-carbon);
  --fg: var(--brand-warm-white);
  --muted: #98958d;              /* Warm White 를 낮춘 것 — 바탕 대비 5.3 */
  --line: #24242e;
  --panel: #131319;
  --accent: var(--brand-periwinkle);
  --surface-deep: var(--brand-plum);
  --ok: var(--brand-mint);
  --on-accent: #ffffff;          /* Periwinkle·Plum 위에 얹는 글자 */

  /* 3) 상태 대비책 — 진짜 색은 DB 다 (위 설명 참고) */
  /* ⭐ 상태 아이콘 뒤 바탕 (발주 §3). 어두운 판은 흰 안개로 띄운다 —
     발주가 준 #EEF0F2 는 흰 바탕 값이라 그대로 두면 어두운 판에서 눈을 챌러다. */
  --sicon-bg: rgba(255,255,255,.07);
  --st-fix: #D93025;             /* 수정 — 발주 §4 의 그 붉은색 */
  --danger: #D93025;             /* 10-10 · 지우기·삭제·휴지통으로 단추·메뉴 한 색(링고 「모든 지우기 단추는 빨간색」) — 여태 주황(--st-retake)·빨강이 섞였다 */
  --st-todo: #8a8a95;
  --st-wip: #1c7ed6;
  --st-retake: #f08c00;
  --st-done: #2f9e44;
  --st-hold: #7048e8;
  --st-review: #c98500;      /* 리뷰 요청 — 띠의 "노란 링" (§20-1) */
  --st-review-fg: #d6336c;   /* 글자용 — 띠의 링과 값이 다르다 (원래 그랬다) */

  /* ⭐⭐ **누를 수 있는 글자** (HQ [덧] 09-16 덧1 ② · 링고: *"90년대 하이퍼링크 느낌의 밑줄
     있는 파란 글씨는 여전히 싼맛이 난다"*).
     ⚠ 여태 `button.link` 는 `--accent`(파랑) + 밑줄이었다 — 「누를 수 있다」를 밑줄로만 말했다.
     ⭐ 이제 **본문보다 한 단 도드라진 글자색** + 손 모양 커서가 그 말을 하고, 밑줄은 **마우스를
       올렸을 때**만 선다. 눌린 자리는 테두리(포커스)다.
     ⚠ `--accent` 를 그대로 쓰지 않는다(발주 못박음) — 링크 전용 칸 하나를 둔다. 다음에 색을
       바꾸면 **여기 두 줄**이다. `--lift` 는 「한 단 도드라지게」의 방향이다(다크는 밝게, 라이트는 진하게). */
  --lift: #ffffff;
  --link: color-mix(in srgb, var(--fg) 82%, var(--lift));
  --link-hover: var(--lift);
}
/* 라이트를 고른 사람에게는 예전 밝은 화면을 준다. 브랜드 강조색은 라이트에서도 같다.
   ⚠ 세 가지가 있다: ① 아무것도 안 고르면 **기기 설정**을 따른다 ② 사람이 고르면
   그것이 이긴다(`data-theme`) — 링고 2026-08-22 ④ 로 탭 줄에 스위치가 생겼다.
   그래서 기기 설정 규칙에는 `:root:not([data-theme])` 를 씌운다 — 안 씌우면
   "라이트로 골랐는데 밤이 되면 다크로 돌아간다" 가 된다. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) {
    --bg: #ffffff; --fg: #1b1b1f; --muted: #6b6b76;
    --line: #e2e2e8; --panel: #fafafc;
    --on-accent: #ffffff;
    --sicon-bg: #e6e9ed;         /* 발주 §3 은 #EEF0F2 「정도」였다 — 흰 표 위에서 그 값은 눈에 안 보여 한 단 진하게 */
    /* 밝은 화면에서 「한 단 도드라지게」는 **진하게**다 — 흰 바탕 위에서 더 밝은 글자는 안 보인다 */
    --lift: #000000;
  }
}
:root[data-theme="light"] {
  --bg: #ffffff; --fg: #1b1b1f; --muted: #6b6b76;
  --line: #e2e2e8; --panel: #fafafc;
  --on-accent: #ffffff;
  --sicon-bg: #e6e9ed;
  --lift: #000000;
}

* { box-sizing: border-box; }
/* ── 서체 — Pretendard 하나로 덮는다 (관리 세션 판정 2026-08-21) ──────────────
   General Sans 는 안 쓴다. 워드마크를 SVG 로 박았으니 로고용 웹폰트가 필요 없어졌고,
   남는 용도인 영문 UI 라벨은 Pretendard 가 라틴까지 갖고 있어 한 벌로 덮인다.

   자체 호스팅이다 — 외부 CDN 을 안 쓴다 (§21-5 외부 서비스 최소주의 · §3 의존 최소).
   라이선스는 **SIL Open Font License 1.1** (Pretendard v1.3.9, 예약 이름 'Pretendard').
   원문은 이 폴더의 `fonts/OFL.txt` — OFL 이 폰트와 함께 배포할 것을 요구한다.

   웨이트는 셋뿐이다 (400·600·700). 늘리기 전에 무게를 재라 — 한글 웹폰트는 무겁다
   (여기 셋이 합쳐 약 2.2MB). 첫 로딩이 아프면 그때 동적 서브셋으로 간다
   (CSS + 쪼갠 woff2 — 빌드 체인은 안 생긴다). **재기 전에 서브셋부터 넣지 마라.**

   `font-display: swap` — 폰트가 오는 동안 글자가 사라지지 않게. 잠깐 시스템 서체로
   보였다가 바뀐다. 안 그러면 느린 회선에서 화면이 빈 채로 멈춘 것처럼 보인다. */
@font-face {
  font-family: "Pretendard";
  src: url("/static/fonts/Pretendard-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("/static/fonts/Pretendard-SemiBold.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Pretendard";
  src: url("/static/fonts/Pretendard-Bold.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

body {
  margin: 0; background: var(--bg); color: var(--fg);
  /* 한 벌이라 순서를 다툴 것이 없다. 뒤는 폰트를 못 받았을 때의 대비다. */
  font-family: "Pretendard", "Malgun Gothic", system-ui, sans-serif;
  font-size: 15px; line-height: 1.6;
}
h1 { font-size: 1.6rem; margin: 0 0 .25rem; }
h2 { font-size: 1.15rem; margin: 0; }
.sub { color: var(--muted); margin: .2rem 0 1.2rem; }
.hidden { display: none !important; }

button { font: inherit; cursor: pointer; }
/* ⭐⭐ 2.117.0 · **밑줄 파란 링크를 걷었다** (HQ [덧] 09-16 덧1 ② · 링고 사진 보고).
   ⛔ 여기에 `text-decoration: underline` 을 되돌리지 마라 — 「누를 수 있다」는 **손 모양 커서**와
     본문보다 한 단 도드라진 색이 말한다. 밑줄은 **마우스를 올렸을 때**의 확인이다.
   ⚠ 색을 덮어쓰는 자리들(`.ep-en.need-fill` · `button.link.danger` · `.tab-tools .link`)은 그대로다 —
     저기는 「이 링크는 다른 뜻」을 말하는 자리라 여기 규칙이 이겨서는 안 된다. */
button.link {
  background: none; border: 0; color: var(--link); padding: 0;
  text-decoration: none; cursor: pointer;
}
button.link:hover { color: var(--link-hover); text-decoration: underline; }
/* 눌린 자리(키보드 포커스)는 **테두리**다 — 색만으로는 «지금 여기» 가 안 보인다 */
button.link:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
  text-decoration: none;
}
button.link:disabled { color: var(--muted); cursor: default; text-decoration: none; }
button.ghost, .inline-form button {
  background: var(--panel); color: var(--fg); border: 1px solid var(--line);
  border-radius: 7px; padding: .35rem .7rem;
}
button.ghost:hover, .inline-form button:hover { border-color: var(--accent); }
/* ⭐⭐ 이 판에서 제일 자주 누르는 단추 (링고 2026-08-25: *"올리기 버튼 … 다 크고 가장 잘
   보여야 함"*). ⚠ 이 무게를 아무 데나 쓰지 마라 — **제일 진한 단추가 여럿이면 아무것도
   제일 진하지 않다.** 지금 이 옷을 입는 것은 「올리기」 하나다. */
button.primary {
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  border-radius: 8px; padding: .4rem .9rem; font-weight: 700;
}
button.primary:hover { filter: brightness(1.08); }
button.primary.big { padding: .55rem 1.15rem; font-size: 1.05rem; border-radius: 10px; }
button.primary:disabled { opacity: .45; }
/* ⭐⭐ **넣는 줄의 「추가」는 진한 단추다** (링고 2026-09-06: *"신규 추가시 추가 버튼 잘 안
   보임. 눈에 띄게 할 것."*). 여태 이 단추는 `.inline-form button` 규칙에 걸려 **「그만두기」와
   똑같은 옷**을 입고 있었다 — 한 줄에 칸이 일곱인데 정작 누를 것이 제일 흐렸다.
   ⚠ 위의 「제일 진한 단추는 하나」 규칙과 부딪히지 않는다: 넣는 줄은 **열려 있는 동안만**
     서고, 그때 그 줄에서 누를 것은 이것 하나다(옆의 「그만두기」는 되돌리는 길이라 흐린 채로).
   되돌리는 법: 이 덩어리를 지우면 옛 옷으로 돌아간다. */
.inline-form button[type="submit"] {
  background: var(--accent); color: #fff; border: 1px solid var(--accent);
  font-weight: 700; padding: .4rem 1.15rem; border-radius: 8px;
}
.inline-form button[type="submit"]:hover { filter: brightness(1.08); border-color: var(--accent); }
.inline-form button[type="submit"]:disabled { opacity: .45; }
input, select {
  font: inherit; color: var(--fg); background: var(--bg);
  border: 1px solid var(--line); border-radius: 7px; padding: .32rem .5rem;
}

/* 로그인 · 프로젝트 선택 */
.screen.center { max-width: 720px; margin: 4rem auto; padding: 0 1.5rem; }
.cards { display: flex; flex-wrap: wrap; gap: .8rem; margin-bottom: 1.2rem; }
.card {
  border: 1px solid var(--line); border-radius: 12px; padding: 1rem 1.2rem;
  background: var(--panel); cursor: pointer; min-width: 190px; text-align: left;
}
.card:hover { border-color: var(--accent); }
.card .name { font-weight: 600; font-size: 1.05rem; }
.card .meta { color: var(--muted); font-size: .88rem; }
.inline { display: inline-flex; align-items: center; gap: .4rem; color: var(--muted); }
/* ⭐⭐ 2.137.0 · **체크박스 + 글 한 줄 부품** (HQ [발주] 09-18 ⑦ · 링고 09-18 아침 캡처 — 2단계 인증 화면에서
   「이 기기 30일 기억」 글이 두 줄로 밀리고 체크박스와 세로 가운데가 안 맞았다).
   뿌리: `.login-panel input { width: 100% }` 가 **체크박스까지** 늘려 글을 옆으로 밀어냈다.
   ⛔ 체크박스는 절대 늘어나지 않는다(`flex: 0 0 auto`) · 글은 한 덩어리로 흐른다(좁으면 글자만 줄바꿈) ·
     세로는 가운데 맞춤 · 누르는 자리는 글까지(label 이라서). 같은 꼴이 서는 자리(`.inline`)도 같이 지킨다. */
.check-line { display: flex; align-items: center; gap: .45rem; line-height: 1.4; cursor: pointer; }
.check-line > span { min-width: 0; }
.check-line > input[type="checkbox"], .check-line > input[type="radio"],
.inline > input[type="checkbox"], .inline > input[type="radio"] { flex: 0 0 auto; width: auto; margin: 0; }
.login-panel input[type="checkbox"], .login-panel input[type="radio"] { width: auto; }
.inline-form { display: flex; flex-wrap: wrap; gap: .5rem; margin: 1rem 0; align-items: center; }

/* 상단바 */
/* 상단바 — **왼쪽 정렬** (지시서 §20-6, 2026-08-23)
   ⚠ 예전 `justify-content: space-between` 은 결정이 아니라 **부산물**이었다: 세 덩어리를
     양끝으로 밀다 보니 가운데가 남았을 뿐이라, **프로젝트 이름이나 사람 이름 길이가 바뀌면
     탭 줄이 통째로 좌우로 밀렸다.** 링고가 그것을 "중앙 정렬" 로 읽은 것이 증상이었다.
   ⚠ 탭은 앞으로 늘고 준다(§16-11 표시/숨김 · 스케줄·회차 탭 예정). 가운데에 두면
     **탭이 하나 늘 때마다 나머지 전부가 미끄러진다** — 근육 기억이 붙는 조건은 왼쪽 고정이다.
   ⚠ `flex-wrap: wrap` 을 걷었다. 줄바꿈은 **어디서 끊길지 모른다** — 좁아지면 탭 줄이
     가로로 스크롤된다(아래). 예측 가능한 쪽을 고른다. */
.topbar {
  display: flex; align-items: center; gap: 1rem;
  padding: .6rem 1.2rem; border-bottom: 1px solid var(--line); background: var(--panel);
  position: sticky; top: 0; z-index: 5;
}
.topbar .right { margin-left: auto; }

/* ⚠ **프로젝트 이름이 상단바 폭을 정하게 두지 않는다** (실측 2026-08-23).
   `CONS · 컨센서스(Consensus)` 같은 긴 이름이 오면 왼쪽 덩어리가 그만큼 커지고,
   그 폭을 탭 줄이 물어 준다 — 1280 에서 **탭이 37px 넘쳤다.** 잘린 이름은 목록을 열면
   그대로 보이고 `title` 에도 있다. **이름 길이가 화면 구조를 흔드는 자리를 끊는다.** */
#project-switch { max-width: 11rem; }

/* ⚠ 탭 열 개가 1280 에서 37px 넘쳤다 (실측). **탭을 접거나 묶기 전에 값싼 것부터** —
   좌우 여백을 .8 → .6rem 으로 줄이면 열 개에서 40px 이 나온다. 글자는 그대로 남는다.
   ⚠ 그래도 모자라는 날이 오면 그건 여백 문제가 아니라 **「탭이 열 개」 문제**다 —
   그때 볼 것은 묶기(그룹핑)이고, 미리 짓지 않는다 (§26-3). */
.topbar .left, .topbar .right { display: flex; align-items: center; gap: .6rem; }
.brand { letter-spacing: .02em; }
.tabs {
  display: flex; gap: .25rem;
  /* 좁으면 **가로로 스크롤**한다 (§20-6). `min-width: 0` 이 없으면 flex 자식이 안 줄어서
     상단바가 통째로 넘친다. 스크롤바는 감춘다 — 손가락·트랙패드로는 그냥 밀린다. */
  flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs > * { flex: none; }
.tab {
  background: none; border: 0; border-bottom: 2px solid transparent;
  /* ⚠ 좌우 여백이 `.8rem` 일 때 탭 열 개가 1280 에서 **37px 넘쳤다**(실측 2026-08-23).
     `.6rem` 으로 줄이면 열 개에서 40px 이 나오고 **글자는 그대로 남는다.**
     ⚠ 그래도 모자라는 날은 여백 문제가 아니라 **「탭이 열 개」 문제**다 — 그때 볼 것은
     묶기(그룹핑)이고 미리 짓지 않는다 (§26-3). */
  padding: .4rem .6rem; color: var(--muted);
}
.tab.active { color: var(--fg); border-bottom-color: var(--accent); font-weight: 600; }
.badge {
  background: var(--st-hold); color: #fff; border-radius: 999px;
  padding: .1rem .6rem; font-size: .8rem;
}

/* ⭐ **창을 넓히면 그만큼 다 쓴다** (링고 2026-08-24: *"창 확장시 전체를 쓰면 좋다.
   현재 프레임 안에 갇혀 안 보인다. 넓게 보는 상황은 많다."*).
   1400px 상한은 글을 읽는 화면에는 맞지만 **표를 보는 화면에는 감옥**이다 —
   단계가 여섯이면 그 안에서 칸이 서로를 밀어낸다. */
main { padding: .8rem 1rem; max-width: none; margin: 0; }
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: .8rem; flex-wrap: wrap;
}
.panel-actions { display: flex; gap: .4rem; }
.notice {
  border: 1px solid var(--st-retake); background: color-mix(in srgb, var(--st-retake) 12%, transparent);
  border-radius: 8px; padding: .6rem .9rem; margin-bottom: 1rem;
}
.empty { color: var(--muted); border: 1px dashed var(--line); border-radius: 10px; padding: 2rem; text-align: center; }
/* ⭐ **접은 빈 자리** (발주 v2 §② 「빈 상자는 있을 때만 편다」) — 상자가 아니라 한 줄이다.
   말은 그대로 두고 **자리만 줄인다**: 다음 손짓이 사라지면 사람이 거기서 멈춘다. */
.empty.thin { padding: .45rem .6rem; border-style: dashed; text-align: left; }
.empty.thin p { margin: 0; }
/* 자료가 하나도 없는 타이틀의 머리줄 — 단추 하나만 남는다 */
.pipeline-bar.thin {
  border: 0; background: none; padding: 0; margin: .2rem 0 .4rem;
  min-height: 0; justify-content: flex-start;
}

/* 표 */
table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: .45rem .6rem; border-bottom: 1px solid var(--line); vertical-align: middle; }
th { color: var(--muted); font-weight: 500; font-size: .85rem; }
tbody tr:hover { background: var(--panel); }
td.code { font-family: ui-monospace, Consolas, monospace; white-space: nowrap; }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
.seq-row td { background: var(--panel); font-weight: 600; }
/* 썸네일 크기는 **사람이 고른다** (링고 2026-08-21). `--thumb-w/h` 는 app.js 가 넣는다.
   ⚠ 행 높이를 따로 박지 않는다 — 제목·내용을 따로 열로 가른 뒤로는 **썸네일이 행에서
   가장 큰 것**이라, 이것만 줄이면 행이 따라 줄어든다. 둘을 따로 정하면 어긋난다. */
.thumb {
  width: var(--thumb-w, 44px); height: var(--thumb-h, 30px);
  border-radius: 4px; background: var(--line);
  display: inline-block; vertical-align: middle;
}

/* 에셋 그리드 */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: .9rem; }
.asset-card { border: 1px solid var(--line); border-radius: 10px; overflow: hidden; background: var(--panel); }
.asset-card .thumb-big { height: 120px; background: var(--line); }
.asset-card .body { padding: .6rem .8rem; }
.asset-card .code { font-family: ui-monospace, Consolas, monospace; color: var(--muted); font-size: .85rem; }
.asset-card .name { font-weight: 600; }
.asset-card .desc { color: var(--muted); font-size: .88rem; min-height: 1.5em; }

/* 상태 칩 = select */
select.status {
  border-radius: 999px; padding: .12rem 1.4rem .12rem .6rem; font-size: .85rem;
  border: 1px solid currentColor; background: transparent; font-weight: 600;
  appearance: none; background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right .6rem center, right .42rem center;
  background-size: 4px 4px, 4px 4px; background-repeat: no-repeat;
}
select.status option { color: var(--fg); background: var(--bg); font-weight: 400; }
select.status:disabled { opacity: .75; cursor: default; }
/* 상태 색은 M3.6 부터 데이터에서 온다 — 칩·드롭다운은 style.color 를 받아 쓰고,
   테두리·화살표는 currentColor 라 따라온다. 아래 .st-* 는 상태 전용이 아니라
   화면 여기저기서 쓰는 강조색으로 남는다 (리뷰 판정·인코딩 오류 등). */
.stdot { display: inline-block; width: 11px; height: 11px; border-radius: 3px; }
.addrow { margin-top: .7rem; align-items: center; }
.addrow input[type="color"] { width: 2.2rem; height: 1.8rem; padding: 0; border: 1px solid var(--line); }
.st-todo { color: var(--st-todo); }
.st-wip { color: var(--st-wip); }
.st-retake { color: var(--st-retake); }
.st-done { color: var(--st-done); }
.st-hold { color: var(--st-hold); }

select.assignee { font-size: .85rem; max-width: 8.5rem; }

.toast {
  position: fixed; bottom: 1.2rem; left: 50%; transform: translateX(-50%);
  background: var(--fg); color: var(--bg); padding: .55rem 1.1rem;
  border-radius: 999px; box-shadow: 0 4px 16px rgba(0,0,0,.2); z-index: 20;
}

/* --- M1.5: 필터 바 · 그룹 접기 · 태스크 칸 --- */
.filterbar {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  padding: .6rem .8rem; margin-bottom: .8rem;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel);
}
.filterbar label { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); font-size: .88rem; }
.filterbar .spacer { flex: 1; }
.muted { color: var(--muted); font-size: .88rem; }

.group-row td { background: var(--panel); }
.group-row.level-1 td { font-weight: 700; border-top: 2px solid var(--line); }
.group-row.level-2 td { font-weight: 600; padding-left: 1.4rem; }
.grouptoggle {
  background: none; border: 0; color: inherit; font: inherit; padding: 0;
}
.grouptoggle:hover { color: var(--accent); }
/* ⭐ 2.139.0 · 컷이 0 인 타이틀 묶음 (HQ [덧] 09-18 링고 실측 셋 ③) — 있는 줄이지 빈 줄이 아니다.
   ⚠ 숨기지 않는다 · 색으로만 한 걸음 물러선다(글자 굵기는 다른 묶음 줄과 같다 — 차례가 섞이면 못 읽는다). */
.group-row.group-empty td { color: var(--muted); }
/* ⚠ 2.139.1 · 이 줄도 단계 열 칸을 **다 든다**(선이 안 끊기게) — 들여쓰기는 **앞 칸 하나**에만 준다
   (칸마다 주면 단계 칸의 값이 오른쪽으로 밀린다). */
.group-empty-row td { background: var(--panel); }
.group-empty-row td:first-child { padding-left: 1.6rem; }
/* 10-10 · 필터 때문에 숨긴 타이틀을 편 줄(흐리게) · 맨 아래 한 줄 — title_hidden.js */
.group-row.th-dim td { opacity: .55; }
.th-foot td { padding: .45rem .8rem; background: var(--panel); }
/* 2.182.0 · 목록 「더 보기」 줄(list_window.js) — 처음 100줄 뒤에 서는 한 줄 · 컷·에셋 표 공용 */
.shot-table tr.list-more td { background: var(--panel); text-align: center; padding: .4rem .6rem; }
.shot-table tr.list-more .list-more-info { margin-left: .5rem; }

td.taskcell { white-space: nowrap; }
td.taskcell select + select { margin-left: .35rem; }
.taskcell { display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; }
td.taskcell { display: table-cell; }

.rowsub { color: var(--muted); font-size: .87rem; }
tr.highlight { animation: flash 2s ease-out; }
@keyframes flash {
  from { background: color-mix(in srgb, var(--accent) 30%, transparent); }
  to { background: transparent; }
}

.groupheading { margin: 1.2rem 0 .4rem; font-size: 1rem; }
.chip {
  border: 1px solid currentColor; border-radius: 999px;
  padding: .1rem .6rem; font-size: .85rem; font-weight: 600;
}
.st-review { color: var(--st-review-fg); }
button:disabled { opacity: .4; cursor: default; }

/* --- M1.6: 표 안에서 바로 고치기 --- */
input.cell {
  border: 1px solid transparent; background: transparent; border-radius: 6px;
  padding: .18rem .35rem; width: 100%; min-width: 3rem;
}
input.cell:hover:not(:read-only) { border-color: var(--line); }
input.cell:focus { border-color: var(--accent); outline: none; background: var(--bg); }
input.cell:read-only { cursor: default; }
input.cell.code-input { font-family: ui-monospace, Consolas, monospace; min-width: 5rem; }
input.cell.num-input { text-align: right; font-variant-numeric: tabular-nums; }
input.cell.rowsub { color: var(--muted); font-size: .87rem; }
input.cell.saved { border-color: var(--st-done); background: color-mix(in srgb, var(--st-done) 12%, transparent); }
td.num { width: 6rem; }
.build { color: var(--muted); font-size: .78rem; font-family: ui-monospace, Consolas, monospace; }

/* --- M2: 상세 화면 · 버전 스택 · 플레이어 --- */
.detail-head { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.viewer { margin-bottom: 1.2rem; }
.viewer .player {
  max-width: 100%; max-height: 60vh; border-radius: 10px; background: #000;
  display: block; margin-bottom: .4rem;
}
.task-block { border: 1px solid var(--line); border-radius: 10px; padding: .8rem 1rem; margin-bottom: 1rem; }
.task-head { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .6rem; }
.version-list { display: flex; flex-direction: column; gap: .3rem; }
.version-row {
  display: flex; gap: .7rem; align-items: center; padding: .4rem .5rem;
  border: 1px solid transparent; border-radius: 8px; cursor: pointer;
}
.version-row:hover { background: var(--panel); }
.version-row.current { border-color: var(--accent); background: var(--panel); }
.version-row .vmeta { flex: 1; min-width: 0; }
.version-row .vactions { display: flex; gap: .6rem; white-space: nowrap; }
.vthumb { width: 72px; height: 46px; object-fit: cover; border-radius: 5px; background: var(--line); }
.empty-thumb { display: inline-block; }
.encode {
  margin-left: .5rem; font-size: .78rem; border-radius: 999px;
  padding: .05rem .5rem; border: 1px solid currentColor;
}
.encode.queued, .encode.processing { color: var(--st-wip); }
.encode.failed { color: var(--st-retake); }
.encode-log { color: var(--st-retake); font-size: .82rem; }
.upload-form { display: flex; gap: .5rem; align-items: center; margin-top: .7rem; flex-wrap: wrap; }
.upload-form input[type=text] { flex: 1; min-width: 12rem; }
/* 목록 썸네일도 같은 자 — 세로 그림이 잘리지 않는다 (손맛 다섯 ②) */
img.thumb { object-fit: contain; cursor: pointer; background: var(--line); }
span.thumb { cursor: pointer; }
img.thumb-big, div.thumb-big { width: 100%; object-fit: contain; cursor: pointer;
  background: var(--line); }
button.linkish {
  background: none; border: 0; padding: 0; font: inherit; font-weight: 600;
  color: inherit; text-align: left; cursor: pointer;
}
button.linkish:hover { color: var(--accent); }
/* ⭐⭐ 2.124.0 · **밑줄 링크 = 다른 화면으로 가기만** (HQ [발주] 09-15 ⑤ 「링크 꼴 통일」 · 링고: *"90년대 하이퍼링크 같은 것이 가득"*).
   자 하나: 이동(타이틀 열기 · 태스크로 이동 · 보러 가기 · → 설정) = `link goto` · 동작 = `ghost small` · 위험 동작 = `ghost small danger`
   · 창의 「취소」「닫기」 = `ask-cancel`(옅은 글자 단추 — 창 바닥 줄에서 쓰던 꼴을 어디서나) · 글자·기호 그 자체를 누르는 자리(접기 ▸ · ↑↓ · ✕ · 값 알약) = `linkish`.
   ⛔ 새 동작 단추에 `link` 를 달지 마라 — 관문 [B78] 이 `.link` 가 `goto` 아닌 자리를 센다. */
button.ask-cancel {
  background: none; border: 0; padding: 0 .2rem; font: inherit; color: var(--muted); cursor: pointer;
}
button.ask-cancel:hover { color: var(--fg); }
a.goto { color: var(--link); text-decoration: none; cursor: pointer; }
a.goto:hover { color: var(--link-hover); text-decoration: underline; }

/* --- M2.5: 에셋 오버뷰 · 갤러리 · 드롭존 · 열 고르기 --- */
.detail-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 40%); gap: 1.2rem; align-items: start; }
/* ⚠ **기준점은 셋뿐이다** (§20-6, 2026-08-23). 예전에는 1200·960·900·820 이 근거 없이
   흩어져 있었고, 새 화면을 지을 때마다 **넷 중 무엇을 고를지가 매번 새 판단**이었다.
     1200px — 아주 넓은 화면에서만 3단 (리뷰 화면 하나)
      900px — **2단 → 1단** (거의 전부 여기다)
      560px — 폰. 탭 줄을 햄버거로 접는다
   ⚠ CSS 변수는 미디어 쿼리 안에서 못 쓴다 — 그래서 **토큰이 아니라 이 목록이 정본**이다.
     새 기준점을 더하려면 여기에 이유를 적고 더해라. */
@media (max-width: 900px) { .detail-body { grid-template-columns: 1fr; } }
.detail-side { position: sticky; top: 4.2rem; }
/* ⭐ 2.117.0 · 파일 없는 타이틀 — 오른쪽 기둥을 접는다 (HQ [발주] 09-15 ③③ · `renderDetail` 이 딱지를 붙인다).
   ⚠ 극장 판(t1·t2)보다 무겁게 적는다 — 볼 것이 없는 판을 크게 펼 일은 없다. */
.detail-body.ep-nofile, .detail-body.ep-nofile.t1, .detail-body.ep-nofile.t2 { grid-template-columns: minmax(0, 1fr); }
.detail-body.ep-nofile > .detail-side { display: none; }
.detail-side .player { max-height: 46vh; width: 100%; object-fit: contain; }
.hint { color: var(--muted); font-size: .8rem; margin-top: .2rem; }

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: .5rem; margin-bottom: .8rem; }
.gcell { margin: 0; border: 2px solid transparent; border-radius: 8px; overflow: hidden; cursor: pointer; background: var(--panel); }
/* ⚠ 2.92.0 · 높이 92px 고정 + 폭 100% 가 뿌리였다(칸이 넓어지면 상자만 납작해졌다) — 상자는 16:9 한 비율 */
.gcell img { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
.gcell figcaption { display: flex; justify-content: space-between; padding: .15rem .4rem; font-size: .76rem; color: var(--muted); }
.gcell:hover { border-color: var(--line); }
.gcell.current { border-color: var(--accent); }
.gplay { color: var(--accent); }

table.history { margin-top: .2rem; }
table.history td, table.history th { padding: .3rem .5rem; font-size: .88rem; }
table.history tbody tr { cursor: pointer; }
table.history tbody tr.current { background: var(--panel); box-shadow: inset 2px 0 0 var(--accent); }

.dropzone { flex-direction: column; align-items: stretch; gap: .5rem; border: 1px dashed var(--line); border-radius: 10px; padding: .7rem; }
.dropzone.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.dz-hint { color: var(--muted); font-size: .85rem; }
.dz-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.dz-row input[type=text] { flex: 1; min-width: 10rem; }
.hidden-file { display: none; }
.upload-progress:not(:empty) { padding-top: .3rem; }

video.scrubbing { cursor: ew-resize; }

.col-menu {
  position: absolute; z-index: 10; background: var(--bg); border: 1px solid var(--line);
  border-radius: 8px; padding: .5rem .7rem; display: flex; flex-direction: column; gap: .25rem;
  box-shadow: 0 6px 20px rgba(0,0,0,.18);   /* 자리는 js 가 단추에 맞춰 잡는다 */
}
.col-menu label { color: var(--fg); font-size: .88rem; }

/* --- M2.1: 필름스트립 · Omit · 보기 옵션 --- */
.strip { background-repeat: no-repeat; cursor: pointer; }
/* 필름스트립 썸네일도 같은 변수를 쓴다 — 안 그러면 여기서 고정값이 덮어써서
   "크기를 골랐는데 안 바뀐다" 가 된다 (2026-08-21 실측으로 잡았다). */
.thumb.strip { width: var(--thumb-w, 44px); height: var(--thumb-h, 30px);
  border-radius: 4px; display: inline-block; vertical-align: middle; }
.gcell .gimg { width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover; display: block; }
.gcell .gimg.strip { background-color: #0d0f12; }
/* 세로 그림은 줄여 넣는다 — 좌우 어두운 여백 (늘리지도 위아래를 자르지도 않는다) */
.gcell img.gimg.tall { object-fit: contain; background: #0d0f12; }

/* ⭐ 2.92.0 · 필름스트립 = 틀 + **한 칸 비율 그대로인 판** (HQ [발주] 09-14 18시 「상세 둘」 ①)
   ⚠ 여태 틀 자체에 `background-size: N×100% 100%` 를 깔아 한 칸이 틀 모양으로 늘었다(갤러리·목록·머리 셋 다).
   판 크기는 틀의 컨테이너 단위로 정한다 — 가로 영상은 max(틀 폭, 틀 높이×비율) = 채워 자르기,
   세로 영상(`tall`)은 min(…) = 줄여 넣기 + 어두운 여백. `--ar` 은 js 가 띠 그림을 한 번 읽어 잰다(모르면 16:9). */
.strip { position: relative; overflow: hidden; container-type: size; background-color: #0d0f12; }
.strip > .strip-frame {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  background-repeat: no-repeat; pointer-events: none; display: block;
  aspect-ratio: var(--ar, 1.7778);
  width: max(100cqw, calc(100cqh * var(--ar, 1.7778)));
}
.strip.tall > .strip-frame { width: min(100cqw, calc(100cqh * var(--ar, 1.7778))); }
/* ⚠ `.hero-img` 가 뒤에서 `background:` 한 벌로 바탕을 덮는다 — 머리 그림 세로 영상 여백이 밝게 떴다(B49 실측). 둘을 붙여 이긴다. */
.hero-img.strip, .thumb.strip { background-color: #0d0f12; }
.gcell.omitted { opacity: .45; }
.gcell.omitted .gimg { filter: grayscale(1); }
.gomit { color: var(--st-retake); font-weight: 600; }
.view-opts { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin-bottom: .8rem; }
.view-opts label { font-size: .88rem; }

/* --- 열 폭 조절 --- */
table.shot-table { table-layout: fixed; }
table.shot-table th { position: relative; }
table.shot-table th > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
table.shot-table td { overflow: hidden; }
.col-resize {
  position: absolute; top: 0; right: -4px; width: 9px; height: 100%;
  cursor: col-resize; z-index: 3; touch-action: none;
  /* 2.111.0 · 3 — 진행 요약을 숨긴 꼴(`sum-hide`)에서 고르기 칸 머리의 알약(z 2 · DOM 뒤)이 손잡이를 덮어 끌기가 안 먹었다([B66] 플랫폼 탭 실측) */
}
.col-resize:hover::after, .col-resize.dragging::after {
  content: ""; position: absolute; top: 15%; right: 4px; width: 2px; height: 70%;
  background: var(--accent); border-radius: 2px;
}
.col-menu button.ghost.small { margin-top: .3rem; text-align: left; }

/* --- 파이프라인 상태 줄 (상세 화면 맨 위) --- */
.pipeline-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; padding: .6rem .8rem; margin-bottom: .8rem;
  border: 1px solid var(--line); border-radius: 10px; background: var(--panel);
}
.pipeline-bar .steps { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.pipeline-bar .pipe-right { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.pipeline-bar .step {
  border: 1px solid currentColor; border-radius: 999px; background: transparent;
  padding: .15rem .7rem; font-size: .85rem; font-weight: 600;
}
.pipeline-bar .step:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.pipeline-bar .arrow { color: var(--muted); }

/* --- M2.5: 파이프라인 --- */
.ministeps { display: flex; gap: .25rem; flex-wrap: wrap; margin-top: .35rem; }
.ministep {
  border: 1px solid currentColor; border-radius: 999px;
  padding: 0 .45rem; font-size: .74rem; font-weight: 600;
}
.doc-note { padding: 1rem; }
.pipe-manage { display: flex; flex-direction: column; gap: 1rem; }
.pipe-card { border: 1px solid var(--line); border-radius: 10px; padding: .8rem 1rem; background: var(--panel); }
.pipe-card h3 { margin: 0 0 .4rem; font-size: 1rem; }
/* ⭐⭐ 09-21 [발주] 설정 > 라이브러리 관리(항목3 — 배지·바꾸기 단추를 한 칸으로 모은 자리) */
.lib-manage-card select.cell { margin: .3rem 0 .6rem; }
.lib-manage-body { display: flex; flex-direction: column; gap: .5rem; }
.lib-manage-badges { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.step-row { display: flex; align-items: center; gap: .5rem; padding: .25rem 0; flex-wrap: wrap; }
.step-row .code { font-family: ui-monospace, Consolas, monospace; color: var(--muted); font-size: .85rem; }
.final-badge { color: var(--st-done); font-size: .78rem; font-weight: 600; }

/* --- M3: 리뷰 · 인박스 · 코멘트 · 리플 --- */
.badge-count {
  background: var(--st-retake); color: #fff; border-radius: 999px;
  padding: 0 .4rem; font-size: .72rem; margin-left: .2rem;
}
.review-body { display: grid; grid-template-columns: minmax(260px, 32%) minmax(0, 1fr); gap: 1.2rem; align-items: start; }
@media (max-width: 900px) { .review-body { grid-template-columns: 1fr; } }
.review-list { display: flex; flex-direction: column; gap: .4rem; }
.review-item {
  display: flex; gap: .6rem; align-items: center; text-align: left;
  border: 1px solid var(--line); border-radius: 9px; padding: .5rem;
  background: var(--panel); color: inherit; font: inherit; cursor: pointer;
}
.review-item:hover { border-color: var(--accent); }
.review-item.current { border-color: var(--accent); box-shadow: inset 3px 0 0 var(--accent); }
.review-detail .viewer .player { max-height: 52vh; }
.vote-row { padding: .25rem 0; border-bottom: 1px dashed var(--line); }
.verdict-row { display: flex; gap: .5rem; align-items: center; margin-top: .8rem; flex-wrap: wrap; }
.verdict-row input[type=text] { flex: 1; min-width: 12rem; }
.ghost.ok { border-color: var(--st-done); color: var(--st-done); }
.ghost.no { border-color: var(--st-retake); color: var(--st-retake); }

.notes-panel { margin-top: .8rem; }
.note-list { display: flex; flex-direction: column; gap: .3rem; max-height: 30vh; overflow-y: auto; }
.note-row { display: flex; gap: .5rem; align-items: flex-start; padding: .3rem; border-radius: 7px; cursor: pointer; }
.note-row:hover { background: var(--panel); }
.frame-chip {
  font-family: ui-monospace, Consolas, monospace; font-size: .76rem;
  border: 1px solid var(--accent); color: var(--accent); border-radius: 999px;
  padding: 0 .45rem; white-space: nowrap;
}
.frame-chip.none { border-color: var(--line); color: var(--muted); }
.note-form { display: flex; gap: .4rem; align-items: center; margin-top: .5rem; flex-wrap: wrap; }
.note-form input[type=text] { flex: 1; min-width: 9rem; }

/* --- 대화 한 줄 (130 · HQ [발주] 09-20) — 태스크 하나 = 줄 하나 · 버전은 꼬리표 --- */
.talk { margin-top: .7rem; border-top: 1px dashed var(--line); padding-top: .5rem; }
.talk.talk-one { margin-top: .5rem; border-top: 0; padding-top: 0; }
.talk.drop-on { outline: 2px dashed var(--accent); outline-offset: 3px; border-radius: 9px; }
.talk-h { color: var(--muted); font-size: .88rem; margin-bottom: .35rem; }
.talk-list { display: flex; flex-direction: column; gap: .35rem; max-height: 32vh; overflow-y: auto; }
.talk-row { padding: .3rem .5rem; background: var(--panel); border-radius: 7px; }
.talk-row.talk-ver { display: flex; gap: .6rem; align-items: center; cursor: pointer; }
.talk-row.talk-ver:hover { background: color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.talk-head { display: flex; gap: .35rem; align-items: center; flex-wrap: wrap; }
.talk-head .frame-chip { cursor: pointer; }
.talk-body { white-space: pre-wrap; word-break: break-word; }
.talk-shots, .talk-pending { display: flex; gap: .35rem; flex-wrap: wrap; margin-top: .3rem; }
.talk-shot { max-height: 120px; max-width: 200px; border-radius: 6px; cursor: zoom-in; background: var(--line); }
.talk-chip { position: relative; display: inline-flex; }
.talk-chip img { height: 56px; border-radius: 6px; background: var(--line); }
.talk-chip .chip-x {
  position: absolute; top: -.35rem; right: -.35rem; line-height: 1;
  background: var(--bg); border: 1px solid var(--line); border-radius: 999px; padding: 0 .25rem;
}
.talk-big {
  position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.72); cursor: zoom-out; padding: 2rem;
}
.talk-big img { max-width: 100%; max-height: 100%; border-radius: 8px; }

.replies { margin-top: .7rem; border-top: 1px dashed var(--line); padding-top: .5rem; }
.replies summary { cursor: pointer; color: var(--muted); font-size: .88rem; }
.reply-list { display: flex; flex-direction: column; gap: .35rem; margin: .5rem 0; }
.reply-row { padding: .3rem .5rem; background: var(--panel); border-radius: 7px; }

.inbox-row {
  display: flex; gap: .7rem; align-items: flex-start; padding: .55rem .7rem;
  border-bottom: 1px solid var(--line); cursor: pointer;
}
.inbox-row:hover { background: var(--panel); }
.inbox-row.unread { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.inbox-type {
  font-size: .76rem; border: 1px solid currentColor; border-radius: 999px;
  padding: 0 .5rem; white-space: nowrap; color: var(--muted);
}
.inbox-type.t-review_requested { color: var(--st-wip); }
.inbox-type.t-review_resolved { color: var(--st-done); }
.inbox-type.t-reply, .inbox-type.t-comment { color: var(--st-hold); }
/* CC 는 사람이 콕 집어 건 것이라 지켜보기(리플)보다 눈에 띄어야 한다 (052) */
.inbox-type.t-comment_cc { color: var(--accent); }
.pipe-name { font-size: 1rem; font-weight: 700; min-width: 14rem; }
.pipe-note { flex: 1; min-width: 16rem; color: var(--muted); }
.pipe-types { flex: 1; min-width: 12rem; max-width: 24rem; }

/* --- 리뷰 타임라인 · 프레임 이동 --- */
.timeline {
  position: relative; height: 22px; margin-top: .3rem; cursor: ew-resize;
  touch-action: none; user-select: none;
}
.tl-bar {
  position: absolute; top: 9px; left: 0; right: 0; height: 4px;
  background: var(--line); border-radius: 2px;
}
.tl-marks { position: absolute; inset: 0; }
.tl-mark {
  position: absolute; top: 2px; width: 3px; height: 18px; padding: 0;
  transform: translateX(-1px); border: 0; border-radius: 2px;
  background: var(--st-retake); cursor: pointer;
}
.tl-mark:hover { background: var(--accent); width: 5px; }
/* 그림 자국 마크 — 글 코멘트(긴 빨강)와 한 줄에, 짧은 파랑으로 가른다 (2.32.0) */
.tl-mark.anno { top: 11px; height: 9px; background: #4cc9f0; }
.tl-mark.anno:hover { background: var(--accent); }
.tl-head {
  position: absolute; top: 0; width: 2px; height: 22px; background: var(--accent);
  pointer-events: none;
}
.framebar { display: flex; align-items: center; gap: .4rem; margin-top: .2rem; flex-wrap: wrap; }
.framebar .step { padding: .1rem .5rem; line-height: 1.2; }
.frame-now {
  font-family: ui-monospace, Consolas, monospace; font-size: .82rem;
  min-width: 3.5rem; text-align: center; color: var(--accent);
}
.note-row.highlight { background: color-mix(in srgb, var(--accent) 20%, transparent); }

/* --- 목록 우클릭 메뉴 --- */
.ctx-menu {
  position: fixed; z-index: 50; min-width: 12rem;
  background: var(--bg); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 8px 24px rgba(0,0,0,.22); padding: .3rem; display: flex; flex-direction: column;
}
.ctx-item {
  background: none; border: 0; text-align: left; padding: .4rem .6rem;
  border-radius: 6px; color: var(--fg); font: inherit; cursor: pointer;
}
.ctx-item:hover { background: var(--panel); color: var(--accent); }

/* --- 리뷰 3단: 왼쪽 히스토리 · 가운데 영상(크게) · 오른쪽 코멘트 --- */
.review-body3 {
  display: grid; grid-template-columns: 260px minmax(0, 1fr) 320px;
  gap: 1rem; align-items: start;
}
@media (max-width: 1200px) { .review-body3 { grid-template-columns: 220px minmax(0,1fr); } .rv-right { grid-column: 1 / -1; } }
@media (max-width: 900px) { .review-body3 { grid-template-columns: 1fr; } }
.rv-left, .rv-right { position: sticky; top: 4.2rem; max-height: calc(100vh - 5rem); overflow-y: auto; }
.rv-h { font-size: .92rem; margin: 0 0 .4rem; color: var(--muted); }
.rv-center .player { width: 100%; max-height: 72vh; }
.rv-center .viewer { margin-bottom: .6rem; }
#review-history { margin-top: 1rem; }

/* --- 표 격자 (링고: 컷 구분이 안 된다) --- */
table.shot-table th, table.shot-table td { border-right: 1px solid var(--line); }
table.shot-table th:last-child, table.shot-table td:last-child { border-right: 0; }
table.shot-table tbody tr:nth-child(even of :not(.group-row)) {
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
table.shot-table td { border-bottom: 1px solid var(--line); }
table.shot-table .group-row td { border-right: 0; }
img.thumb, span.thumb, .thumb.strip { transition: width .1s, height .1s; }

/* ==========================================================================
   §20 파이프라인 띠 — 스텝 = 색, 상태 = 채움 (한 칸에 색 두 개를 섞지 않는다)
   시각 정본: docs/cutboard_layout_mockup_v1.html
   ========================================================================== */
.pbar-cell { padding-top: .35rem; padding-bottom: .35rem; }
.pbar { display: flex; gap: 3px; align-items: stretch; }
.segp { --h: #6f6e68; flex: 1; min-width: 40px; position: relative; cursor: pointer; }
.segp.none { cursor: default; opacity: .35; }
/* 채움 상자 — 컷리스트 띠와 상세 레일이 같은 어휘를 쓴다 */
.fillbox {
  height: 15px; border: 1.5px solid var(--h); border-radius: 4px;
  position: relative; overflow: hidden;
  background: color-mix(in srgb, var(--h) 8%, transparent);
}
/* ⭐ [덧]1 (2.90.0 · 링고 09-14: *"태스크가 없는 것은 아예 — 표시도 없는 게 좋겠다"*) — 빈 조각은 **아무것도 안 그린다**.
   ⚠ 자리는 남긴다(줄마다 조각이 같은 자리에 서야 띠를 세로로 읽는다) · 올리면 옅게 「+」 · 누르면 그 단계 태스크. */
.segp.none { opacity: 1; }
.segp.none .fillbox { border-color: transparent; background: none; }
.segp.none .lab { visibility: hidden; }
.segp.none.can-add { cursor: pointer; }
.segp.none.can-add:hover > .fillbox { border: 1.5px dashed color-mix(in srgb, var(--fg) 30%, transparent); }
.segp.none.can-add:hover > .fillbox::before {
  content: "+"; position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: .72rem; line-height: 1; color: var(--muted); opacity: .8;
}
.fillbox > .fill { position: absolute; inset: 0; background: var(--h); opacity: 0; }
/* 채움 키는 상태 code 가 아니라 **meaning** 이다 (M3.6 — 지시서 v1.26 §4).
   사용자가 '1차 컨펌' 같은 상태를 새로 만들어도 뜻만 붙어 있으면 같은 모양으로 칠해진다.
   (예전엔 code 를 그대로 썼고, 그래서 'retake' 가 아래 'fix' 규칙과 안 맞아
    줄무늬가 아예 안 칠해지고 있었다 — 실측 2026-08-20.)

   하는 중·판정 대기 = 절반쯤 채움 / 끝남 = 꽉 / 다시 하는 중 = 줄무늬 / 세지 않음 = 점선 */
[data-st="active"] > .fillbox > .fill,
[data-st="review"] > .fillbox > .fill { opacity: .34; right: 45%; }
[data-st="review"] > .fillbox { box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--st-review) 85%, transparent); }
[data-st="done"] > .fillbox > .fill { opacity: .95; }
[data-st="rework"] > .fillbox > .fill {
  opacity: .85;
  background: repeating-linear-gradient(45deg, var(--h) 0 3px, transparent 3px 6px);
}
[data-st="hold"] > .fillbox { border-style: dashed; border-color: var(--st-todo); background: none; }
.segp .lab {
  font-size: .68rem; line-height: 1.35; color: var(--muted); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.segp .lab b { color: var(--fg); font-weight: 600; }
body:not(.showTask) .segp .lab .tk { display: none; }
body:not(.showArtist) .segp .lab .art { display: none; }
body:not(.showTask):not(.showArtist) .segp .lab { display: none; }
.segp:not(.none):hover > .fillbox { box-shadow: 0 0 0 2px color-mix(in srgb, var(--h) 45%, transparent); }
.segp.open > .fillbox { box-shadow: 0 0 0 2px var(--accent); }

/* 세그먼트 팝오버 — 표를 떠나지 않고 상태·담당을 고친다 */
/* ⚠ 뜬 판은 **바탕과 다른 색이어야 한다** (링고 2026-08-24: *"바탕 화면과 색이
   똑같아서 글씨가 잘 안 보인다"*). 예전엔 `--bg` 라 페이지 바탕과 똑같았고,
   테두리 한 줄로만 갈렸다 — 어두운 화면에서는 그 한 줄이 안 보인다.
   ⭐ 판은 `--panel`(바탕보다 한 단 밝다) + 또렷한 테두리 + 깊은 그림자로 띄운다. */
.seg-pop {
  position: fixed; z-index: 60; min-width: 15rem;
  background: var(--panel); border-radius: 10px; padding: .6rem .75rem;
  border: 1px solid color-mix(in srgb, var(--fg) 22%, var(--line));
  box-shadow: 0 18px 48px rgba(0,0,0,.55);
  display: flex; flex-direction: column; gap: .35rem;
}
.seg-pop h4 { margin: 0 0 .2rem; font-size: .9rem; display: flex; align-items: center; gap: .4rem; }
.seg-pop h4 i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.seg-pop .row { display: flex; align-items: center; justify-content: space-between; gap: .5rem; font-size: .88rem; color: var(--muted); }
.seg-pop .row select { max-width: 9.5rem; }
.seg-pop .row.links { justify-content: flex-start; gap: .9rem; padding-top: .2rem; }
.seg-pop button.ghost.danger { color: var(--danger); }

/* 열 방식 머리줄 — SG 처럼 열 전체를 형광으로 칠하지 않고 밑줄 악센트만 */
table.shot-table th.stepH { border-bottom: 2px solid var(--sc); }
/* ⛔ 2.68.0 의 6% 단계 색 띠(`col.step-tint`)는 2.70.0 에서 걷었다 — 아래 「단계 열 테두리」가 대신한다. */

/* ⭐⭐⭐ **단계 열 테두리 · 머리 칸 바탕** (HQ [발주] 09-13 · 링고 세 번째 말 · 플로우 캡처 그대로).
   *"파이프라인 태스크의 색은 각 파이프라인의 바깥선을 감싸고 있어 중요하게 티가 나고 인지돼야 한다."*
   ① 열 **양옆 4px 선**이 단계 색 — 머리 칸부터 마지막 줄까지 그 열의 **모든 칸**이 딱지(`.stepE`)를
     들고 안쪽 그림자로 긋는다(자리를 안 먹는다 · 줄 바탕 위에 선다 · 가운데는 비어 줄무늬를 안 덮는다).
     ⚠ `<col>` 테두리는 sticky 머리칸 밑으로 깔리고, `border` 는 칸 폭을 조용히 줄인다(09-13 함정).
     ⚠ 옆 칸끼리 사이 세로선은 여전히 없다(B22) — 선은 `border` 가 아니라 그림자다.
   ② 머리 칸 바탕 = 단계 색, 글자는 `--sc-ink`(흰색이 4.5:1 을 못 넘으면 검정 · `stepInk`).
   ⚠ 스위치 「단계 색 테두리」가 끄는 것은 ① 뿐이다(표의 `.step-edge`). ② 는 늘 선다. */
table.shot-table.step-edge th.stepE,
table.shot-table.step-edge td.stepE {
  box-shadow: inset 4px 0 0 var(--sc), inset -4px 0 0 var(--sc);
}
#shot-body table.shot-table thead th.stepH,
#asset-body table.shot-table thead th.stepH {
  background: var(--sc); color: var(--sc-ink, #fff);
}
table.shot-table th.stepH .col-head > .col-name,
table.shot-table th.stepH button.col-chev,
table.shot-table th.stepH .col-head > .col-sort,
table.shot-table th.stepH.sorted .col-head > .col-name,
table.shot-table th.stepH.sorted .col-head > .col-sort { color: var(--sc-ink, #fff); font-weight: 700; }

/* ⭐⭐ **단계별 진행률 줄** — 요약 줄(머리줄 아래) · 묶음 줄 (발주 09-13 §3).
   `86% ●` — 점 색은 **장부 상태 색**(`rollupStatus` → `statusColor`)이지 % 구간 색표가 아니다. */
/* ⚠ 머리줄 칸의 바탕은 `#shot-body … thead th` 가 쥐고 있다(sticky) — 같은 무게로 적어야 이긴다 */
#shot-body table.shot-table thead tr.sum-head th,
#asset-body table.shot-table thead tr.sum-head th {
  background: var(--panel); font-weight: 500; font-size: .8rem;
  padding-top: .15rem; padding-bottom: .15rem; border-bottom: 1px solid var(--line);
  white-space: nowrap; text-align: left;
}
table.shot-table tr.sum-head th.plead b { font-weight: 700; }
table.shot-table td.plead, table.shot-table th.plead {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* ⚠ 요약 줄 앞 칸 「11컷 · 전체 13%」가 두 줄로 접혔다 (2.70.1 캡처 · HQ 09-13) — 머리 칸 글
   (`th > span` = 블록 · 452줄)이 이 칸의 「· 전체 %」 span 까지 블록으로 세웠다. 이 칸만 줄 안에 둔다. */
table.shot-table th.plead > span { display: inline; }
table.shot-table .group-row td.pcell,
table.shot-table .group-row td.prest { padding-left: .6rem; font-weight: 500; }
.ppct {
  display: inline-flex; align-items: center; gap: .3rem; font-size: .8rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.ppct b { font-weight: 700; color: var(--fg); }
.ppct .pdot { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
.group-row .grp-pct { font-weight: 500; }
/* ⭐⭐ **컷 상태 한 덩이** (HQ [발주] 09-14 22시) — 요약 줄 「· 컷 상태: ●완료 12 · ◐진행 중 5 → 60%」 · 묶음 줄 「· 완료 4/7 · 57%」.
   ⚠ 앞 칸(`plead`) 안 **한 줄** — 두 줄로 접히면 고정 머리(2.78.0)가 밀린다. 좁으면 js 가 `cst-short`(짧은 꼴)를 붙인다.
   ⚠ 점은 상태 강조의 큰 점(`i.sdot` 12px)을 그대로 쓴다 — 여기서 크기·색을 새로 정하지 않는다. */
.cst { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--fg); font-weight: 500; }
.cst::before { content: " · "; color: var(--muted); white-space: pre; }
.cst .cst-long { display: inline; }
.cst .cst-brief { display: none; }
.cst.cst-short .cst-long { display: none; }
.cst.cst-short .cst-brief { display: inline; }
.cst .cst-word { color: var(--muted); margin-right: .3rem; }
.cst .cst-item { display: inline-flex; align-items: center; gap: .2rem; vertical-align: -.1em; }
.cst .cst-sep { color: var(--muted); margin: 0 .3rem; }
.cst .cst-pct { margin-left: .35rem; font-weight: 700; }
.cst.full .cst-pct, .cst.full .cst-brief { color: var(--ok, var(--fg)); }

/* ⭐⭐ **진행 요약 자리** (HQ [발주] 09-15 13시 · app.js `listHeadRows`) — 한 줄: 머리줄 위 얇은 띠 · 숨김: 머리줄 왼쪽 알약.
   ⚠ 띠 칸도 `thead th` 라 고정 머리(2.78.0 · `--pin-top`)가 그대로 붙인다 — 여기서 `top` 을 안 적는다.
   ⚠ 바탕은 옅게: 머리 칸(`--bg`)과 몸통 사이에 끼지 않고 도구 줄 밑에 서니 머리줄과 갈려 보여야 한다. */
#shot-body table.shot-table thead tr.sum-line th,
#asset-body table.shot-table thead tr.sum-line th {
  background: var(--panel); font-size: .74rem; line-height: 1.2;
  padding-top: .05rem; padding-bottom: .05rem; border-bottom: 1px solid var(--line);
}
table.shot-table tr.sum-line .ppct { font-size: .74rem; }
.sum-pill {
  display: inline-block; white-space: nowrap; font-variant-numeric: tabular-nums;
  font-size: .74rem; font-weight: 700; line-height: 1.25; color: var(--fg);
  padding: 0 .5rem; border: 1px solid var(--line); border-radius: 999px; background: var(--bg);
  cursor: default;
}
.sum-pill.full { color: var(--ok, var(--fg)); }
table.shot-table th.plead > span.sum-pill { display: inline-block; }
/* 숨김 — 체크박스 칸 옆에 뜬다(칸 폭 46px 을 안 늘린다 · 옆 칸 머리 위에 겹쳐 선다) */
table.shot-table thead th .sum-pill.head-pill {
  position: absolute; left: 26px; top: 50%; transform: translateY(-50%); z-index: 2;
  font-size: .68rem; padding: 0 .4rem; pointer-events: auto;
}
table.shot-table thead th .col-head > .sum-pill.head-pill { position: static; transform: none; margin-right: .3rem; }
#shot-body table.shot-table.sum-hide thead th[data-col-key="pick"],
#asset-body table.shot-table.sum-hide thead th[data-col-key$=":pick"] { z-index: 8; overflow: visible; }
/* 알약이 덮는 썸네일 머리 글자 — 겹쳐 읽히지 않게 비운다(칸 폭 손잡이·끌기는 그대로) */
table.shot-table.sum-hide thead th[data-col-key="thumb"] .col-name,
table.shot-table.sum-hide thead th[data-col-key$=":thumb"] .col-name { visibility: hidden; }

/* ⭐⭐ **탭 줄 상태 알약** (HQ [발주] 09-15 13시 ② · app.js `paintStatusBar`) — 점은 2.89.0 큰 점 · 누르면 그 상태로 거른다
   ⭐ 2.105.0 (HQ [덧] 09-15 13시 40분 · 링고: *"붙어 있으면 같은 정보처럼 보이겠다"*) — 탭 묶음과 떼어 **줄 오른쪽 끝**(`margin-left: auto`)
   · 탭과 사이는 적어도 3rem(`.pill-tabs` 오른쪽 여백) · 창이 좁으면 줄이 접혀 **탭 줄 아래** 오른쪽으로 · 작고 옅게(12px · 옅은 바탕·테두리). */
.list-tabs > .pill-tabs { margin-right: 3rem; }
.list-tabs > .list-status {
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0 .1rem; margin-left: auto;
  font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--muted);
  padding: .05rem .55rem; border: 1px solid color-mix(in srgb, var(--line) 70%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--panel) 55%, transparent);
}
.list-tabs > .list-status.hidden { display: none; }
.list-tabs > .list-status.on { border-color: var(--accent); }
.list-status .cst-word { color: var(--muted); margin-right: .35rem; }
.list-status .cst-sep { color: var(--muted); margin: 0 .2rem; }
.list-status .cst-item {
  appearance: none; background: none; border: 0; color: var(--muted); font: inherit; cursor: pointer;
  display: inline-flex; align-items: center; gap: .2rem; padding: 0 .15rem; border-radius: 4px;
}
.list-status .cst-item:hover { color: var(--accent); }
.list-status .cst-item.on { color: var(--accent); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }
.list-status .cst-pct { margin-left: .35rem; font-weight: 700; }
.list-status .cst-clear { appearance: none; background: none; border: 0; color: var(--muted); cursor: pointer; font: inherit; margin-left: .3rem; padding: 0 .2rem; }
.list-status .cst-clear:hover { color: var(--fg); }
/* ⭐⭐ **「완료 빼고 보기」 스위치** (HQ [발주] 웹 09-28) — 상태 알약 바로 옆 · 같은 자리에 태스크 탭(`#tasks-filters`)도 같은 옷을 입는다.
   ⚠ 켜져 있을 때(`on`)만 강조색 — 숨긴 수가 늘 보인다(「완료 6 숨김」) · 꺼진 것처럼 보일 때(검색·상태 알약 중)는 옅은 기본 글자. */
.hide-done-toggle {
  appearance: none; cursor: pointer; font: inherit; font-size: 12px; font-variant-numeric: tabular-nums;
  border: 1px solid color-mix(in srgb, var(--line) 70%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--panel) 55%, transparent); color: var(--muted);
  padding: .05rem .5rem; margin-left: .45rem; white-space: nowrap;
}
.hide-done-toggle.on { color: var(--accent); border-color: var(--accent); font-weight: 700; }
.hide-done-toggle:hover { color: var(--fg); }
.hide-done-toggle.on:hover { color: var(--accent); }
.hide-done-note { margin-left: .35rem; font-size: 12px; }
#tasks-filters { display: flex; align-items: center; flex-wrap: wrap; }
#tasks-filters .hide-done-toggle { margin-left: .6rem; }
/* ⭐⭐ **묶음 줄(▼ EP021 Soccer 13컷 · 전체 45% · 로그라인) = 요약 줄과 같은 높이 규칙 · 한 줄** (HQ [발주] 09-14 4시 반 ③).
   여백·글자는 요약 줄(`tr.sum-head th` · 위) 값 그대로 · 긴 로그라인은 접히지 않고 끝이 「…」.
   ⚠ 회차 줄 윗선(2px)이 줄 키를 2px 올리므로 선은 자리를 안 먹는 그림자로 긋는다(단계 칸은 제 양옆 선을 그대로 든다). */
#shot-body table.shot-table tr.group-row td {
  padding-top: .15rem; padding-bottom: .15rem; font-size: .8rem; white-space: nowrap;
}
#shot-body table.shot-table tr.group-row td.plead { overflow: hidden; text-overflow: ellipsis; }
#shot-body table.shot-table tr.group-row.level-1 td { border-top: 0; }
#shot-body table.shot-table tr.group-row.level-1 td:not(.stepE) { box-shadow: inset 0 2px 0 var(--line); }
#shot-body table.shot-table tr.group-row .grouptoggle { line-height: inherit; }
/* ⭐ 「내용」 글자 = 에셋 「설명」 글자 — 옅게 쓰던 것(`.rowsub`)을 표 안에서는 같은 색으로 (09-14 4시 반 ①) · 빈 칸의 옅은 「내용」은 자리표 글자다 */
table.shot-table input.cell.rowsub { color: inherit; }

/* ⭐⭐⭐ **가운데 정렬** (HQ [발주] 09-13 17시 ③ · 링고: *"이 아이콘들도 중앙 정렬돼야 한다 …
   각 필드의 제목은 중앙 정렬로 하자. 현재 앞 정렬이다."*).
   ① 모든 열 머리 글자 — 겉옷(`.col-head`)이 flex 라 `text-align` 이 아니라 **`justify-content`** 가 정한다.
     ⚠ 정렬 화살표는 여태 `margin-left:auto` 로 칸 오른쪽 끝에 붙었다 — 그러면 이름이 도로 왼쪽으로 밀린다.
       이름 **바로 옆**에 붙인다(켜진 칸에서만 보이는 것은 그대로).
   ② 단계 칸(접힌 칸) 아이콘 · 상태 열 아이콘 — 칸 가운데.
     ⚠ 펼친 칸은 격자(상태 · 태스크 이름 · 담당) 안이라 그대로다 — 작은 머리줄 글자와 줄이 맞아야 한다.
   ③ 요약 줄 · 묶음 줄의 % — 그 칸 가운데. 앞 칸(「11컷 · 전체 13%」)은 이름 칸이라 왼쪽 그대로. */
table.shot-table th .col-head { justify-content: center; }
table.shot-table th .col-head > .col-sort { margin-left: .2rem; }
table.shot-table td.taskcell.shut,
table.shot-table td.st-icon-cell { text-align: center; }
table.shot-table tr.sub-head th.shut { text-align: center; }
#shot-body table.shot-table thead tr.sum-head th.pcell,
#asset-body table.shot-table thead tr.sum-head th.pcell,
table.shot-table .group-row td.pcell { text-align: center; }
table.shot-table .group-row td.pcell { padding-left: .6rem; padding-right: .6rem; }
/* ⚠ 요약 줄 % 는 `th` 안의 `span` 이라 머리 칸 규칙(`th > span` = 블록 · 452줄)에 먹혀 **% 와 점 사이가 붙었다**
   (묶음 줄 `td` 는 멀쩡 · 09-13 캡처). 「11컷」 칸과 같은 병이다 — 이 칸도 줄 안 꼴로 돌려놓는다. */
table.shot-table th.pcell > span.ppct { display: inline-flex; }

/* ⭐ 우클릭 「파이프라인 태스크 보이기 ▸」 체크 줄 (HQ [덧] 09-13 덧1) — 체크 · 단계 색 점 · 이름.
   ⚠ 체크칸은 누름을 안 받는다 — 줄이 받는다(두 번 뒤집혀 제자리가 되는 것을 막는다 · app.js `drawSubItem`). */
.ctx-sub .ctx-check { display: flex; align-items: center; gap: .4rem; }
.ctx-sub .ctx-check input { pointer-events: none; margin: 0; }
.ctx-sub .ctx-check .stepdot { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
/* ⭐ 남는 폭을 먹는 **빈 칸** — 아무 옷도 안 입는다 (링고 2026-08-29 ①).
   ⚠ 여기에 테두리·바탕을 주면 그것이 곧 «터진 것» 으로 보인다. */
/* ⭐ 큰 그림 옆의 상태 — **1.5배** (링고 2026-08-29 ②). 이 화면에서 제일 먼저 읽는 값이다. */
.hero-status { display: flex; align-items: center; gap: .45rem; margin: .5rem 0 .2rem; }
.hero-status > .muted { font-size: 1rem; }
.hero-status select.status { font-size: 1.05rem; padding: .45rem 1.8rem .45rem .7rem; }
.hero-status .sicon { transform: scale(1.5); transform-origin: left center; margin-right: .4rem; }
.hero-status .chip { font-size: 1.05rem; padding: .3rem .7rem; }

table.shot-table th.spacer-cell,
table.shot-table td.spacer-cell {
  border-right: 0; border-bottom: 0; background: transparent; padding: 0;
}
th.stepH i.stepdot {
  display: inline-block; width: 7px; height: 7px; border-radius: 2px;
  margin-right: 5px; vertical-align: 1px;
}
th.stepH > span { display: inline-block; max-width: calc(100% - 14px); vertical-align: bottom; }

/* "필드 보기" 안의 보기 전환 */
.seg-switch { display: flex; background: var(--panel); border-radius: 8px; padding: 2px; gap: 2px; }
.seg-switch button {
  flex: 1; border: 0; background: none; color: var(--muted);
  padding: .3rem .6rem; border-radius: 6px; font-size: .88rem;
}
.seg-switch button.on { background: var(--bg); color: var(--fg); font-weight: 600; box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.col-menu hr { border: 0; border-top: 1px solid var(--line); width: 100%; margin: .35rem 0 .1rem; }

/* 칸 고르개의 한 줄 — 체크로 켜고 끄고, 끌어서 차례를 바꾼다
   (발주 SPEC_web_공통보기엔진_v1 §2 「칸 고르개」).
   ⚠ 손잡이(⠿)를 둔다: 끌 수 있다는 것이 안 보이면 없는 기능이다. */
.col-menu .col-pick { display: flex; align-items: center; gap: .35rem; cursor: grab; }
.col-menu .col-pick .grip { color: var(--muted); font-size: .8rem; cursor: grab; }
.col-menu .col-pick.dragging { opacity: .45; }
.col-menu .col-pick.drop-top { box-shadow: inset 0 3px 0 var(--accent); }
.col-menu .col-pick.drop-bot { box-shadow: inset 0 -3px 0 var(--accent); }
/* 2.110.0 · 「파이프라인 보기」 묶음 줄 (HQ [발주] 09-15 열 셋 ③) — 한 줄 · ▸ 펼치면 단계 줄이 들여 선다 */
.col-menu .col-pick-list, .col-menu .col-pick-kids { display: flex; flex-direction: column; gap: .25rem; }
.col-menu .col-pick-kids { padding-left: 1.1rem; border-left: 2px solid var(--line); margin-left: .3rem; }
.col-menu .col-pick-kids.hidden { display: none; }
.col-menu .col-pick-group .pipe-group-name { font-weight: 600; }
.col-menu .col-pick-group .pipe-group-chev { margin-left: auto; padding: 0 .3rem; font-size: .9rem; text-decoration: none; }
.col-menu .col-pick-step .stepdot { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; box-shadow: 0 0 0 1px var(--line); }  /* 계약 색이 흰색인 단계(원고)도 보이게 */

/* ==========================================================================
   §20-4 컷 상세 = 스텝 탭 + "전체" 통합 표
   ========================================================================== */
.rail-strip { display: flex; gap: 3px; flex: 1; min-width: 240px; }
.rtab {
  --h: var(--muted);
  display: block; flex: 1; min-width: 76px; text-align: left;
  padding: .2rem .3rem .25rem; border-radius: 7px;
  border: 1px solid transparent; background: none; color: var(--muted);
  font: inherit; font-size: .88rem;
}
.rtab.all {
  flex: none; min-width: 0; align-self: flex-start;
  border-color: var(--line); background: var(--panel); padding: .35rem .7rem;
}
.rtab .lab {
  font-size: .68rem; line-height: 1.35; margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.rtab .lab .tk { color: var(--fg); font-weight: 600; }
.rtab .lab .st, .rtab .lab .art { color: var(--muted); font-weight: 400; }
body:not(.showArtist) .rtab .lab .art { display: none; }
.rtab:hover > .fillbox { box-shadow: 0 0 0 2px color-mix(in srgb, var(--h) 45%, transparent); }
.rtab.on { background: color-mix(in srgb, var(--h) 10%, transparent); border-color: color-mix(in srgb, var(--h) 45%, transparent); }
.rtab.all.on { background: color-mix(in srgb, var(--accent) 14%, var(--panel)); border-color: var(--accent); color: var(--fg); font-weight: 600; }
table.all-hist td:first-child { white-space: nowrap; }
.stepname { display: inline-flex; align-items: center; gap: .35rem; }
.stepname i { width: 7px; height: 7px; border-radius: 2px; flex: none; }

/* --- §20-5 모니터 늘어나기 (팝업 없음) --- */
/* 폭은 애니메이션 없이 바로 바꾼다. grid-template-columns 트랜지션은 트랙 목록 모양이
   다르면 값이 아예 안 먹는 자리가 있었다 (크롬 실측 2026-08-19) — 접히는 것이 먼저다.
   0fr 만 쓰면 min-content 만큼 남으므로 minmax(0,0fr) 이라야 실제로 접힌다. */
.detail-body.t1 { grid-template-columns: minmax(0px, 0fr) minmax(300px, 100%); }
.detail-body.t1 .detail-main { overflow: hidden; }
/* 1단은 "보면서 적는" 단계다 — 코멘트가 화면 밖으로 밀리지 않을 만큼만 키운다 (§20-5) */
.detail-body.t1 .detail-side .player { max-height: 60vh; }
/* ⭐⭐ **큰 화면에서는 코멘트가 오른쪽으로 빠진다** (링고 2026-08-24).
   큰 화면은 TV 다 — 그림이 가운데를 다 쓰고, **코멘트는 옆에서 같이 보인다.**
   ⚠ 예전에는 2단에서 코멘트를 아예 감췄다. 그런데 큰 화면을 켜는 이유가 «보면서 말하려고»
     라서, 감추면 **켜는 순간 하려던 일을 못 하게 된다.** 감추는 것은 왼쪽 표뿐이다. */
.detail-body.t1 .detail-side, .detail-body.t2 .detail-side {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(300px, 26%);
  grid-template-areas: "viewer notes" "strip notes" "line notes";
  gap: .8rem 1.1rem; align-items: start;
}
.detail-body.t1 .detail-side > #detail-viewer,
.detail-body.t2 .detail-side > #detail-viewer { grid-area: viewer; }
.detail-body.t1 .detail-side > .theater-strip,
.detail-body.t2 .detail-side > .theater-strip { grid-area: strip; }
.detail-body.t1 .detail-side > .theater-line,
.detail-body.t2 .detail-side > .theater-line { grid-area: line; }
.detail-body.t1 .detail-side > #detail-notes,
.detail-body.t2 .detail-side > #detail-notes {
  grid-area: notes; max-height: 78vh; overflow: auto;
}
.detail-body.t2 .detail-side .player { max-height: 74vh; }
@media (max-width: 900px) {
  .detail-body.t1 .detail-side, .detail-body.t2 .detail-side {
    grid-template-columns: 1fr;
    grid-template-areas: "viewer" "strip" "line" "notes";
  }
}

/* 아래에 깔리는 다른 판 — 누르면 그 판이 위에 걸린다 */
.theater-strip { display: none; }
.detail-body.t1 .theater-strip:not(:empty),
.detail-body.t2 .theater-strip:not(:empty) {
  display: flex; gap: .4rem; overflow-x: auto; padding: .2rem 0 .3rem;
}
.theater-strip figure {
  margin: 0; flex: none; width: 108px; cursor: pointer;
  border: 2px solid transparent; border-radius: 8px; overflow: hidden; background: var(--panel);
}
.theater-strip figure.current { border-color: var(--accent); }
.theater-strip img { width: 100%; height: 62px; object-fit: cover; display: block; }
.theater-strip figcaption {
  display: flex; justify-content: space-between; gap: .3rem;
  padding: .1rem .3rem; font-size: .72rem; color: var(--muted);
}
.theater-line { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.theater-line .mode:not(:empty) { color: var(--st-retake); font-weight: 600; }
kbd {
  background: var(--panel); border: 1px solid var(--line); border-bottom-width: 2px;
  border-radius: 5px; padding: 0 .3rem; font-size: .78rem; font-family: inherit;
}
#shot-body { overflow-x: auto; }

/* 레일이 띠가 되면서 가로를 넉넉히 가져가야 한다 (한눈에 보이는 것이 목적) */
.pipeline-bar { align-items: flex-start; }
.pipeline-bar .steps { flex: 1 1 420px; min-width: 0; }
.pipeline-bar .pipe-right { flex: 0 0 auto; padding-top: .1rem; }
.seg-pop.wide { min-width: 22rem; }
.seg-pop.wide .row input, .seg-pop.wide .row select { flex: 1; min-width: 0; max-width: none; }
.seg-pop.wide .row { gap: .8rem; }
.seg-pop .hint { margin: .1rem 0 .2rem; }

/* --- 인박스는 하나의 프레임 (링고 2026-08-20) --- */
.inbox-frame {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 40%);
  gap: 1rem; align-items: start;
}
@media (max-width: 900px) { .inbox-frame { grid-template-columns: 1fr; } }
.inbox-list { min-width: 0; }
.inbox-detail {
  position: sticky; top: 4.2rem; min-width: 0;
  border: 1px solid var(--line); border-radius: 10px; padding: .8rem 1rem; background: var(--panel);
}
.inbox-detail h3 { margin-top: 0; }
.inbox-detail .viewer { margin-top: .6rem; }
.inbox-detail .player, .inbox-detail img { max-width: 100%; }
.inbox-row.current { box-shadow: inset 3px 0 0 var(--accent); background: var(--panel); }
/* ⭐ 2.106.0 · 인박스에서 바로 처리 — 처리된 줄은 옅게 · 오른쪽 판 = 태스크 줄 · 처리 단추 · 내용(버전 · md 문서) */
.inbox-row.handled { opacity: .55; }
.inbox-row .inbox-done-chip { align-self: center; font-size: .72rem; margin-left: auto; white-space: nowrap; }
.inbox-handled-toggle { display: inline-flex; align-items: center; gap: .3rem; font-size: .85rem; color: var(--muted); }
.inbox-handled-line { color: var(--st-done); font-size: .85rem; margin: .2rem 0; }
.inbox-task-line { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin: .4rem 0; }
.inbox-handle { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .7rem 0 .35rem; }
.inbox-handle .spacer { flex: 1; }
.inbox-handle .primary { min-width: 7rem; }
.inbox-why { width: 100%; box-sizing: border-box; }
.inbox-keys { margin: .25rem 0 0; }
.inbox-doc { margin-top: .7rem; border: 1px solid var(--line); border-radius: 10px; background: var(--panel); }
.inbox-doc-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; padding: .45rem .7rem; border-bottom: 1px solid var(--line); }
.inbox-doc-head .spacer { flex: 1; }
.inbox-doc-body { max-height: none; }

/* ==========================================================================
   M3.5 문서(텍스트) 태스크 — 쓰기 · 미리보기 · 판 · 비교
   ========================================================================== */
.doc-box { margin-top: .4rem; }
.doc-bar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.doc-bar .spacer { flex: 1; }
.doc-note-in { min-width: 12rem; flex: 0 1 16rem; }
.doc-panes { display: grid; gap: .8rem; align-items: stretch; }
.doc-box.show-edit:not(.show-preview) .doc-panes { grid-template-columns: 1fr; }
.doc-box.show-preview:not(.show-edit) .doc-panes { grid-template-columns: 1fr; }
.doc-box.show-edit.show-preview .doc-panes { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .doc-box.show-edit.show-preview .doc-panes { grid-template-columns: 1fr; } }
.doc-box:not(.show-edit) .doc-area { display: none; }
.doc-box:not(.show-preview) .doc-preview { display: none; }
.doc-area {
  width: 100%; min-height: 16rem; resize: vertical;
  font-family: ui-monospace, Consolas, monospace; font-size: .92rem; line-height: 1.65;
  padding: .7rem .8rem; border: 1px solid var(--line); border-radius: 9px;
  background: var(--bg); color: var(--fg);
}
.doc-preview {
  min-height: 16rem; padding: .7rem 1rem; overflow-wrap: anywhere;
  border: 1px solid var(--line); border-radius: 9px; background: var(--panel);
}
.doc-preview > :first-child { margin-top: 0; }
.doc-preview h1.md-h { font-size: 1.35rem; }
.doc-preview h2.md-h { font-size: 1.15rem; }
.doc-preview h3.md-h, .doc-preview h4.md-h { font-size: 1rem; }
.doc-preview blockquote {
  margin: .5rem 0; padding: .1rem .8rem; border-left: 3px solid var(--line); color: var(--muted);
}
.doc-preview pre {
  background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
  padding: .6rem .8rem; overflow-x: auto;
}
.doc-preview code { font-family: ui-monospace, Consolas, monospace; font-size: .9em; }
.doc-preview img.md-img { max-width: 100%; border-radius: 8px; }
.doc-h { margin: 1rem 0 .3rem; font-size: .95rem; color: var(--muted); }
.doc-revs table { width: 100%; }

/* 판 비교 */
.doc-diff:not(:empty) {
  margin-top: .8rem; border: 1px solid var(--line); border-radius: 9px; overflow: hidden;
}
.doc-diff-head {
  display: flex; align-items: center; gap: .7rem;
  padding: .4rem .7rem; background: var(--panel); border-bottom: 1px solid var(--line);
}
.doc-diff-head .ask-cancel { margin-left: auto; }
.doc-diff-body { max-height: 24rem; overflow: auto; padding: .3rem 0; }
.dl {
  font-family: ui-monospace, Consolas, monospace; font-size: .85rem;
  padding: 0 .7rem; white-space: pre-wrap; overflow-wrap: anywhere;
}
.dl-add { background: color-mix(in srgb, var(--st-done) 16%, transparent); }
.dl-del { background: color-mix(in srgb, var(--st-retake) 16%, transparent); }
.dl-same { color: var(--muted); }
.boot-error {
  margin: 1.5rem auto; max-width: 40rem; padding: 1rem 1.2rem;
  border: 1px solid var(--st-retake); border-radius: 10px;
  background: color-mix(in srgb, var(--st-retake) 8%, transparent);
}
.boot-error h3 { margin: 0 0 .4rem; }

/* 휴지통·아티스트 카드 (M3.5) */
.pipe-card table.history th { font-size: .78rem; }
.pipe-card table.history td.num { text-align: right; font-variant-numeric: tabular-nums; }
tr.unassigned td { color: var(--muted); }
#asset-body { overflow-x: auto; }

/* + 단추 · 대분류 조망 (M3.5, 링고 2026-08-20) */
button.ghost.plus { font-size: 1.15rem; line-height: 1; padding: .2rem .6rem; font-weight: 700; }
.struct-pop { max-width: 46rem; max-height: 70vh; overflow: auto; }
.struct-pop table { width: 100%; }
.struct-pop td.num { text-align: right; color: var(--muted); white-space: nowrap; }
.ctx-menu hr { border: 0; border-top: 1px solid var(--line); margin: .25rem .3rem; }
/* ⚠ 예전엔 `width:100%` 라 여섯 칸이 화면 끝까지 늘어났다 — 숫자 한 자리를 보려고
   눈이 화면을 가로지른다 (링고 2026-08-24: *"필드 폭이 와이드하니 반 정도씩 줄여도"*).
   ⭐ 내용만큼만 넓힌다. 좁은 화면에서는 그때 100% 가 된다. */
.artist-table { width: auto; min-width: min(100%, 34rem); max-width: 100%; table-layout: auto; }
.artist-table th, .artist-table td { padding-right: 1.1rem; }
.artist-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
#artist-filters { gap: .6rem; }
#artist-filters .seg-switch { flex-wrap: wrap; }
.offscreen { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* 태그 (§16-11) */
.taglist { display: flex; gap: .3rem; flex-wrap: wrap; align-items: center; }
.tags { display: flex; gap: .3rem; flex-wrap: wrap; margin-top: .35rem; }
.tagchip {
  display: inline-flex; align-items: center; gap: .25rem;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .05rem .5rem; font-size: .76rem; color: var(--muted);
  background: var(--panel); font-family: inherit;
}
button.tagchip { cursor: pointer; }
button.tagchip:hover, .tagchip.on { border-color: var(--accent); color: var(--accent); }
.tagchip .x { border: 0; background: none; color: var(--muted); padding: 0 0 0 .1rem; font-size: .8rem; cursor: pointer; }
.tagchip .x:hover { color: var(--st-retake); }
.tagchip.add { border-style: dashed; }
/* ⭐ 목록의 태그는 **한 단 작게 · 한 줄** (발주 2026-09-02 · 링고: *"태그는 더 작게"*).
   ⚠ 칸이 넘치면 줄 높이가 늘어 표가 들쭉날쭉해진다 — 넘치는 것은 `+N` 이 대신 말한다. */
.tagchip.mini { font-size: .68rem; padding: 0 .35rem; gap: .15rem; }
.tagchip.mini.more { border-style: dashed; color: var(--fg); }
td.tagcell {
  white-space: nowrap; overflow: hidden; text-overflow: clip;
  display: flex; gap: .25rem; align-items: center; height: 100%;
}
td.tagcell.clickable { cursor: pointer; }
td.tagcell.clickable:hover .tagchip { border-color: var(--accent); }
/* 태그 팝업 — 스케줄 줄 팝업과 같은 옷을 입되 좁다 */
.seg-pop.tagpop { min-width: 17rem; max-width: 24rem; }
.seg-pop.tagpop .tags { margin-top: 0; max-height: 9rem; overflow: auto; }
.seg-pop.tagpop .tagchip .tname {
  border: 0; background: none; color: inherit; font: inherit; padding: 0; cursor: pointer;
}
.seg-pop.tagpop .row { display: flex; gap: .35rem; align-items: center; margin-top: .4rem; }
.seg-pop.tagpop .row .cell { flex: 1; }
#asset-search { min-width: 14rem; }
/* ① 설정 탭 줄 — 링고 2026-08-22: *"잘 안 보인다"*.
   ⚠ 진짜 원인은 폭이 아니라 **줄바꿈 규칙**이었다. `.seg-switch button` 이 `flex: 1` 이라
     모든 탭이 같은 폭으로 눌렸고, 기본 `word-break` 가 한글을 **낱말 한가운데서** 끊어
     "파이프 라인 템 플릿" 으로 보였다. 글자 크기 문제가 아니다.
   → ① 폭은 글자만큼만(`flex: 0 0 auto`) ② 한글은 낱말 단위로만 끊는다(`keep-all`)
     ③ 그래도 좁으면 **탭 줄 자체가 다음 줄로 넘어간다**(`flex-wrap`) — 글자를 쪼개지 않는다.
   → 안 고른 탭의 대비도 올렸다. 고른 것만 읽히고 나머지는 배경에 묻혀 있었다. */
.settings-nav { margin-bottom: 1rem; width: fit-content; max-width: 100%; flex-wrap: wrap; }
.settings-nav button {
  flex: 0 0 auto;                 /* 긴 이름이 짧은 이름에 맞춰 눌리지 않게 */
  padding: .4rem 1rem;
  word-break: keep-all;           /* 한글을 낱말 한가운데서 끊지 않는다 */
  white-space: nowrap;
  color: color-mix(in srgb, var(--fg) 62%, transparent);
}
.settings-nav button:hover { color: var(--fg); }
.kindtag { margin-left: .4rem; font-size: .7rem; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 .4rem; }
.doc-area.dropping { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--bg)); }

/* ==========================================================================
   바이블 — 프로젝트 문서 선반 (지시서 v1.28 §16-13, M3.7)
   왼쪽이 선반, 오른쪽이 글. 글 판(.doc-box)은 §16-8 것을 그대로 쓴다.
   ========================================================================== */
.bible-frame {
  display: grid; grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
  gap: 1rem; align-items: start;
}
@media (max-width: 900px) { .bible-frame { grid-template-columns: 1fr; } }
.bible-shelf {
  position: sticky; top: 4.2rem; min-width: 0;
  border: 1px solid var(--line); border-radius: 10px; padding: .5rem; background: var(--panel);
  display: flex; flex-direction: column; gap: .15rem;
}
.bible-row { display: flex; align-items: center; gap: .1rem; }
.bible-row .bible-item { flex: 1; min-width: 0; }
.bible-tools { display: flex; flex-direction: column; line-height: 1; }
.bible-tools .linkish { padding: 0 .2rem; font-size: .75rem; }
.bible-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
  width: 100%; text-align: left; padding: .4rem .55rem; border-radius: 8px;
  border: 1px solid transparent; background: none; cursor: pointer; color: var(--fg);
}
.bible-item:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); }
.bible-item.on { border-color: var(--line); background: var(--bg); font-weight: 600; }
.bible-item .t { font-size: .92rem; }
.bible-item .sub { font-size: .74rem; color: var(--muted); font-weight: 400; }
/* 클라이언트 노출 표시는 항목 안에 붙인다 — 관리 권한이 없으면 .bible-row 로
   감싸지 않으므로, 기준을 항목 자신으로 둬야 자리가 안 튄다. */
.bible-item { position: relative; padding-right: 1.4rem; }
.bible-item .cvis { position: absolute; right: .45rem; top: .4rem; font-size: .7rem; color: var(--st-wip); }
.bible-body { min-width: 0; }
.bible-head {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin-bottom: .6rem;
}
.bible-head .bible-title { font-size: 1.05rem; font-weight: 600; min-width: 14rem; }
.bible-add { margin-top: .5rem; }
.bible-add .cell { min-width: 0; }
.empty-note { padding: 1.2rem .2rem; }
.empty-note p { margin: .2rem 0; }

/* ==========================================================================
   빽빽하게 보기 (링고 2026-08-21 — "컷이 100개 넘어가면 정신 사납다")
   행 높이의 주범은 제목 칸이 입력칸 둘(제목·내용)을 위아래로 쌓는 것이다.
   지우지 않고 **접는다** — 내용은 제목 오른쪽으로 가고, 여백과 띠가 낮아진다.
   끄면 그대로 돌아온다 (개인 설정, localStorage).
   ========================================================================== */
body.dense table.shot-table th,
body.dense table.shot-table td { padding: .12rem .4rem; }

/* 제목 칸: 위아래 → 좌우. 내용은 남는 폭만 차지하고 넘치면 말줄임 */
body.dense table.shot-table td:has(> input.cell.rowsub) { white-space: nowrap; }
body.dense input.cell.rowsub {
  display: inline-block; width: 45%; margin-left: .3rem;
  text-overflow: ellipsis;
}
body.dense td > input.cell:not(.rowsub):not(.num-input):not(.code-input) {
  display: inline-block; width: 52%;
}

/* 썸네일·띠도 같이 낮춘다 — 행 높이는 가장 큰 칸이 정한다 */
/* 빽빽하게 보기는 이제 썸네일 크기를 건드리지 않는다 — 그건 사람이 따로 고른다.
   여기서는 여백만 줄인다 (둘이 각자 한 가지씩만 맡아야 서로 안 싸운다). */
body.dense .fillbox { height: 10px; }
body.dense .pbar-cell { padding-top: .1rem; padding-bottom: .1rem; }
body.dense .segp .lab { display: none; }   /* 띠 밑 글자는 빽빽할 땐 접는다 */
body.dense select.status { padding: .02rem 1.3rem .02rem .5rem; font-size: .8rem; }
body.dense input.cell { padding: .1rem .35rem; }

/* 설정 > 상태 표 — 칸이 화면 폭만큼 벌어져서 이름과 색이 멀리 떨어져 있었다
   (링고 2026-08-21: "가시성을 위해 더 가깝게"). 칸 폭을 내용에 맞춘다. */
.status-table { width: auto; min-width: 0; }
.status-table th, .status-table td { padding: .3rem .5rem; white-space: nowrap; }
.status-table td input.cell { width: 9rem; }
.status-table td input[type="color"] { width: 2.2rem; height: 1.7rem; padding: 0; }
.status-table .step-row { gap: .25rem; }

/* 로그인 (Phase B — 비밀번호가 붙었다) */
.login-panel {
  margin-top: 1rem; padding: 1rem 1.2rem; max-width: 26rem;
  border: 1px solid var(--line); border-radius: 12px; background: var(--panel);
  display: flex; flex-direction: column; gap: .5rem;
}
.login-panel h3 { margin: 0; font-size: 1rem; }
.login-panel .sub { margin: 0 0 .3rem; }
.login-panel input { width: 100%; }
.login-foot { margin-top: 1rem; color: var(--muted); font-size: .88rem; }
.card.nopw { border-style: dashed; }
.card .meta.warn { color: var(--st-retake); font-size: .8rem; }

/* 표에서 가져오기 (§6-1 · §22-3) — 붙여넣기 → 열 맞추기 → 미리보기 → 적용 */
.import-pop { max-width: 54rem; }
.import-drop {
  width: 100%; box-sizing: border-box; font-family: ui-monospace, monospace;
  font-size: .82rem; border: 1px dashed var(--line); border-radius: 8px; padding: .5rem;
}
.import-drop.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.import-map td { padding: .25rem .5rem; }
.import-map select { max-width: 14rem; }
.import-sum { margin: .3rem 0 .6rem; padding-left: 1.1rem; }
.import-sum li { line-height: 1.5; }
/* 200줄까지 보여 주므로 스스로 스크롤한다 — 창이 화면 밖으로 자라지 않게 */
.import-list { max-height: 40vh; overflow: auto; }
.import-list tr.bad td { color: var(--st-retake); }
.import-pop .warn { color: var(--st-retake); }

/* 브랜드 마크·워드마크 (관리 세션 메일 §3·§4)
   ⚠ 마크는 index.html 의 <symbol> 하나뿐이다. 여기서는 크기만 정한다 —
      벡터 원본이 오면 그 symbol 만 갈면 끝나야 한다. */
.mark { width: 1.5em; height: 1.5em; vertical-align: -.35em; }
/* 워드마크는 **글자색을 따라간다** (`fill="currentColor"`). 비율은 원본 그대로 두고
   높이만 정한다 — 폭을 정하면 글자가 눌린다. */
/* ⚠ 인라인 SVG 는 `width:auto` 가 **300px(브라우저 기본)** 로 떨어진다 — viewBox 가
   있어도 그렇다. 그래서 비율을 명시해 **높이에서 폭이 나오게** 한다 (원본 978:152). */
.word { height: 1em; width: auto; aspect-ratio: 978 / 152; color: inherit; }
.brand { display: inline-flex; align-items: center; gap: .5rem; }
/* ⚠ 워드마크는 가로로 길다(978:152 ≈ 6.4:1). 높이만 정하면 폭이 6배로 따라온다 —
   상단바에서 300px 를 먹어 프로젝트 고르는 칸을 밀어냈다. 높이를 낮춰 폭을 잡는다. */
.brand .word { height: .72rem; }
/* 로고가 단추가 됐다 (링고 2026-08-26 — 홈으로 가는 길).
   ⚠ 모양은 **그대로**다: 단추 기본 옷을 벗기고, 누를 수 있다는 것만 손짓으로 알린다. */
button.brand {
  border: 0; background: none; padding: 0; margin: 0; font: inherit; color: inherit;
  cursor: pointer; border-radius: 6px;
}
button.brand:hover { opacity: .8; }
button.brand:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.wordmark { display: flex; align-items: center; gap: .7rem; }
.wordmark .mark { width: 2.4rem; height: 2.4rem; vertical-align: 0; }
.wordmark .word { height: 1.5rem; }
.about-card .wordmark .mark { width: 1.8rem; height: 1.8rem; }
.about-card .wordmark .word { height: 1.1rem; }

/* 제작사 푸터 — 작게, 가운데 (링고 2026-08-21). 표기 정본은 10_Business/COMPANY.md */
.site-foot {
  margin-top: 2.5rem; text-align: center;
  color: var(--muted); font-size: .78rem; letter-spacing: .02em;
}
.site-foot a { color: inherit; }

/* 제작사 크레딧 — 제품 이름이 크고 제작사는 작다 (메일 §4의 위계) */
.made-by {
  margin-top: 2.5rem; color: var(--muted);
  font-size: .78rem; letter-spacing: .14em; text-transform: uppercase;
}
.about-card .made-by { margin-top: .6rem; }

/* 비밀번호 바꾸기 (설정 > 정보) — 칸이 화면 폭만큼 벌어지지 않게 */
.pw-change { margin-top: 1.2rem; max-width: 24rem; }
.pw-change input { width: 100%; margin-bottom: .4rem; }

/* 로그인 — 아이디 폼이 기본, 카드는 아래 (링고 2026-08-21) */
#screen-login .login-panel { margin: 0 0 1.4rem; }
.cards-lead { width: 100%; margin: 0 0 .5rem; font-size: .88rem; }

/* '필드 보기' 메뉴 안의 작은 제목 (썸네일 크기 등) */
.col-menu .menu-lead { color: var(--muted); font-size: .82rem; margin: .4rem 0 .2rem; }

/* 행 촘촘함 — '썸네일 크기' 가 같이 정한다 (링고 2026-08-21).
   ⚠ 썸네일만 줄이면 **글자 칸 여백이 바닥을 만들어** 행이 안 줄어든다 (실측 29px).
      사람이 고르는 것은 사실 "행을 얼마나 촘촘히 볼까" 라, 둘을 같이 움직인다. */
table.shot-table td, table.shot-table th { padding: var(--row-pad, .45rem) .6rem; }
table.shot-table td > input.cell { padding-top: var(--row-pad, .32rem); padding-bottom: var(--row-pad, .32rem); }


/* SVG 스프라이트(마크·로고) 보관함. 화면에 자리를 차지하지 않는다.
   ⚠ 예전에는 index.html 에 style="position:absolute" 로 적혀 있었다 — CSP 가
   인라인 style 을 막으므로 여기로 옮겼다 (2026-08-21). 인라인으로 되돌리지 마라. */
.svg-sprite { position: absolute; }

/* 여러 줄 고르기 — 컷·에셋 같은 모양 (링고 2026-08-21).
   ⚠ 색은 브랜드 강조색을 **연하게** 깐다. 상태 색과 겹치면 "무슨 상태지?" 로 읽힌다. */
.shot-table tbody tr.picked > td,
.asset-table tbody tr.picked > td {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
}
.shot-table tbody tr.picked > td:first-child,
.asset-table tbody tr.picked > td:first-child {
  box-shadow: inset 3px 0 0 var(--accent);
}


/* ==========================================================================
   행 높이 — **바닥을 만드는 것은 썸네일이 아니라 글자 칸이다** (실측 2026-08-22)
   '작게' 에서 행이 36px 인데 썸네일은 18px 이었다. 진짜 바닥은 입력칸 29px
   (줄높이 24px + 여백 + 테두리) 와 상태 드롭다운 28px 이었다.
   그래서 크기 단계가 글자 크기·줄높이까지 같이 정한다 (`--row-fs`·`--row-lh`).
   ⚠ 여기 값을 px 로 못박지 마라 — 사람이 고른 단계가 못 이기게 된다.
   ========================================================================== */
table.shot-table td,
table.asset-table td { padding: var(--row-pad, .2rem) .5rem; }

table.shot-table input.cell,
table.asset-table input.cell {
  font-size: var(--row-fs, .95rem);
  line-height: var(--row-lh, 1.35);
  padding: 0 .35rem;
}
table.shot-table select.status,
table.asset-table select.status {
  font-size: var(--row-fs, .95rem);
  line-height: var(--row-lh, 1.35);
  padding: 0 1.15rem 0 .4rem;
  background-position: right .3rem center;
}
/* 코드·숫자 칸도 같은 크기로 — 하나만 크면 그것이 다시 바닥이 된다 */
table.shot-table td.code, table.asset-table td.code,
table.shot-table td.num, table.asset-table td.num { font-size: var(--row-fs, .95rem); }

/* 파이프라인 띠도 행 높이를 따라간다 (실측 2026-08-22).
   ⚠ 글자 칸을 낮췄더니 이번엔 **띠(31.7px)가 바닥이 됐다.** 한 놈을 낮추면 다음 놈이
   바닥이 된다 — 그래서 행 높이를 정하는 것들은 **다 같은 변수를 봐야 한다.**
   `--bar-h` 는 크기 단계가 준다. 밑에 붙는 글자(스텝 이름·담당)는 자리를 많이 먹으므로
   작은 단계에서는 접는다 — 색과 채움만으로도 진행은 읽힌다. */
.pbar-cell { padding-top: var(--row-pad, .35rem); padding-bottom: var(--row-pad, .35rem); }
.fillbox { height: var(--bar-h, 15px); }
body.tiny-rows .segp .lab { display: none; }

/* 잠긴 칸 / 열린 칸 (링고 2026-08-22 — "그냥 수정은 안 되고 더블클릭으로")
   잠겨 있을 때는 입력칸처럼 안 보이는 편이 낫다. 테두리가 보이면 눌러서 고치는 줄 안다. */
input.cell.lockable[readonly] {
  background: transparent; border-color: transparent; cursor: default;
}
.shot-table tbody tr:hover input.cell.lockable[readonly],
.asset-table tbody tr:hover input.cell.lockable[readonly] {
  border-color: color-mix(in srgb, var(--line) 70%, transparent);
}
input.cell.editing {
  background: var(--panel); border-color: var(--accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}

/* 열을 끌어 옮길 때 (링고 2026-08-22 ⑧) — 어디에 놓이는지 선으로 보여 준다 */
.shot-table thead th.dragging { opacity: .45; }
.shot-table thead th.drop-left { box-shadow: inset 3px 0 0 var(--accent); }
.shot-table thead th.drop-right { box-shadow: inset -3px 0 0 var(--accent); }
/* 탭 차례 바꾸기 칩 */
.tab-order .chip { display: inline-flex; align-items: center; gap: .15rem;
  border: 1px solid var(--line); border-radius: 999px; padding: .1rem .3rem; }
.tab-order .chip b { font-weight: 600; font-size: .85rem; padding: 0 .15rem; }
.tab-order .chip button.linkish { padding: 0 .2rem; }

/* 가져오기 열 맞추기 — **붙여넣은 표와 같은 모양** (링고 2026-08-22 ⑥) */
.import-map.wide th { white-space: nowrap; }
.import-map.wide .map-row th { padding-top: .2rem; }
.import-map.wide .map-row select { width: 100%; min-width: 7rem; }
.import-map.wide .map-row select.mapped {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.import-map.wide tbody td { max-width: 14rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.import-pipe { align-items: center; gap: .5rem; margin: .4rem 0; }

/* 드롭다운 목록이 안 보이던 것 (링고 2026-08-22 ②).
   ⚠ 창을 그리는 것은 브라우저이고, 다크 테마에서 <option> 은 **우리 색을 안 물려받는다** —
   그래서 검정 위 검정 글씨가 됐다. option 에 색을 직접 박고, 바탕이 밝은 쪽으로 맞춘다.
   (color-scheme 을 주면 브라우저가 다크용 창을 그려 준다 — 그것이 진짜 고치는 자리다.) */
select, input, textarea { color-scheme: dark light; }
select option {
  background: var(--panel);
  color: var(--fg);
}
select option:checked { background: var(--accent); color: var(--on-accent); }
/* 가져오기 열 맞추기 드롭다운은 좁아서 더 잘 안 보인다 — 글자를 키운다 */
.import-map.wide .map-row select { font-size: .9rem; padding: .15rem .3rem; }

/* 휴지통에 걸린 줄을 되살릴지 묻는 자리 */
.warn-box { align-items: center; gap: .6rem; padding: .4rem .6rem;
  border: 1px solid color-mix(in srgb, var(--st-retake) 50%, transparent);
  border-radius: 6px; margin: .4rem 0; }

/* 탭 줄의 ☰ (링고 2026-08-22) — 탭 살림을 탭 옆에 둔다 */
.tabs-more {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 6px; padding: .1rem .45rem; margin-left: .3rem; cursor: pointer;
  font-size: .95rem; line-height: 1.4;
}
.tabs-more:hover { color: var(--fg); border-color: var(--accent); }
.tab-menu { min-width: 15rem; padding: .3rem; }
.tab-menu .menu-lead { padding: .25rem .5rem; }
.tab-menu-row { display: flex; align-items: center; gap: .35rem; padding: .12rem .5rem; }
.tab-menu-row b { flex: 1; font-weight: 500; }
.tab-menu-row .box-pad { width: 13px; display: inline-block; }
.tab-menu-row button.linkish { padding: 0 .25rem; }

/* 되돌릴 수 없는 단추는 다르게 보여야 한다 (휴지통 비우기) */
button.danger {
  background: color-mix(in srgb, var(--danger) 22%, transparent);
  border-color: var(--danger); color: var(--fg);
}
button.danger:hover { background: color-mix(in srgb, var(--danger) 35%, transparent); }

/* 파이프라인 조립 (링고 2026-08-22) — 끌어서 차례를 바꾼다.
   ⚠ 놓을 자리는 **선**으로 보여 준다. 줄 자체를 밀거나 키우면 레이아웃이 흔들려서
   "지금 어디에 놓이는지" 보다 "화면이 왜 움직이지" 가 먼저 보인다. */
.assemble .drag-row { cursor: grab; }
.assemble .drag-row.dragging { opacity: .45; }
.assemble .drag-row.drop-above { box-shadow: inset 0 3px 0 var(--accent); }
.assemble .drag-row.drop-below { box-shadow: inset 0 -3px 0 var(--accent); }
.assemble .grip { color: var(--muted); cursor: grab; user-select: none; padding: 0 .1rem; }
.assemble input[type="color"] { width: 1.9rem; height: 1.5rem; padding: 0; border-radius: 4px; }

/* 가져오기 판 — 넣기 단추는 **바닥에 붙어 늘 보인다** (링고 2026-08-22 ⑦).
   목록이 41줄이면 단추가 스크롤 끝에 묻히고, 사람은 그 전에 "안 되는구나" 로 읽는다. */
.import-pop { display: flex; flex-direction: column; max-height: 82vh; }
/* ⚠⚠ **목록만 자란다** (링고 2026-08-24: *"표로 컷 부를 시 창이 깨짐"* — 못 넣는 줄이
   60개면 표가 판 밖으로 흘러나와 테두리 밖에 글자가 찍혔다).
   원인은 flex 아이의 기본 `min-height:auto` 다 — 줄어들 수가 없으니 `overflow:auto` 가
   영영 안 걸리고 판이 통째로 늘어난다. ⭐ 목록에 `min-height:0` 을 주고, **나머지는
   flex:none** 으로 못 박는다. 폴더째 올리기에서 고친 것과 같은 자리다. */
.import-pop > * { flex: none; }
.import-pop .import-list {
  flex: 1 1 auto; min-height: 0; max-height: 46vh; overflow: auto;
  border: 1px solid var(--line); border-radius: 9px;
}
.import-pop .import-list table { margin: 0; }
.import-pop .import-list thead th { position: sticky; top: 0; z-index: 1; background: var(--panel); }
.import-foot {
  position: sticky; bottom: 0; z-index: 2;
  margin-top: auto; padding: .6rem .2rem .2rem;
  background: linear-gradient(to top, var(--panel) 72%, transparent);
  border-top: 1px solid var(--line);
}


/* 컷용·에셋용 파이프라인을 바탕색으로 가른다 (링고 2026-08-22 ③).
   ⚠ 색이 아니라 **왼쪽 띠**가 주로 말한다 — 카드 전체를 물들이면 그 위의 스텝 색
   (파랑·주황…)과 싸운다. 바탕은 아주 옅게만 깐다. */
.pipe-card.for-shot { border-left: 3px solid var(--brand-periwinkle, #6366F1);
  background: color-mix(in srgb, var(--brand-periwinkle, #6366F1) 5%, transparent); }
.pipe-card.for-asset { border-left: 3px solid var(--brand-mint, #3FE0BB);
  background: color-mix(in srgb, var(--brand-mint, #3FE0BB) 5%, transparent); }
.pipe-card .for-badge {
  font-size: .75rem; padding: .05rem .4rem; border-radius: 999px;
  border: 1px solid var(--line); color: var(--muted);
}

/* 테마 스위치 — 탭 줄의 ☰ 옆 */
.theme-toggle {
  background: none; border: 1px solid var(--line); color: var(--muted);
  border-radius: 6px; padding: .1rem .45rem; margin-left: .25rem; cursor: pointer;
  font-size: .95rem; line-height: 1.4;
}
.theme-toggle:hover { color: var(--fg); border-color: var(--accent); }

/* 단계 사이의 연결 (링고 2026-08-22 ① · 마이그레이션 025)
   직선 = 앞이 끝나야 시작 · 점선 = 앞이 시작하면 같이 · 없음 = 상관없음.
   ⚠ 이 선은 장식이 아니다 — 나중에 간트에서 **하나가 밀리면 뒤가 밀리는 계산**이
   이 값을 읽는다. 그래서 눌러서 바꿀 수 있게 해 뒀다. */
.step-link {
  display: flex; align-items: center; gap: .4rem;
  background: none; border: 0; cursor: pointer; padding: 0 0 0 1.15rem;
  color: var(--muted); font-size: .74rem; height: 1.1rem;
}
.step-link .line { display: block; width: 2px; height: 100%; border-radius: 2px; }
.step-link.link-after .line { background: var(--muted); }
.step-link.link-with .line {
  background: repeating-linear-gradient(to bottom,
    var(--muted) 0 3px, transparent 3px 6px);
}
.step-link.link-free .line { background: none; }
/* ⑥ 링고 2026-08-22: *"줄 라인이 에러같다"*.
   ⚠ 라벨이 hover 에서만 보여서, 평소에는 **뜻 없는 세로 막대 하나**로 보였다.
     무엇인지 안 적힌 선은 고장으로 읽힌다. 늘 적어 둔다 — 흐리게, 가까이 가면 진하게. */
.step-link .lab { opacity: .55; transition: opacity .12s, color .12s; }
.step-link:hover .lab { opacity: 1; color: var(--fg); }
.step-link:hover .line { background: var(--accent); }
/* '상관없음' 은 선이 없다 — 그 자리가 빈 줄로만 남으면 무엇이 없어진 건지 모른다.
   점 하나로 "여기에 관계가 있고, 지금은 없음이다" 를 남긴다. */
.step-link.link-free .line {
  background: none; border-left: 2px dotted color-mix(in srgb, var(--muted) 45%, transparent);
}

/* 오래 걸리는 일을 화면 가운데서 잡아 준다 (링고 2026-08-22).
   ⚠ 단추만 잠그면 사람 눈에는 아무 일도 안 일어난 것처럼 보이고, 그래서 또 누른다.
   덮는 동안 다른 것이 안 눌리는 것도 이 판의 일이다. */
.busy-hold {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(2px);
}
.busy-card {
  display: flex; align-items: center; gap: .7rem;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 1rem 1.4rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  font-size: 1rem;
}
.busy-spin {
  width: 1.1rem; height: 1.1rem; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-top-color: var(--accent);
  animation: busy-turn .7s linear infinite;
}
@keyframes busy-turn { to { transform: rotate(360deg); } }
/* 움직임을 싫어하는 사람에게는 돌리지 않는다 — 글자만으로도 뜻은 전해진다 */
@media (prefers-reduced-motion: reduce) { .busy-spin { animation: none; } }


/* ==========================================================================
   ④ 저장 바 — 저장 안 한 이름·설명을 따라다니며 알려 준다 (링고 2026-08-22)
   ⚠ 토스트가 아니라 바인 이유는 app.js `drawSaveBar` 머리말에 적었다:
     "저장해야 들어간다" 는 **안 저장한 동안 계속 참인 사실**이라 사라지면 안 된다.
   ========================================================================== */
.savebar {
  position: fixed; right: 1.2rem; bottom: 1.2rem; z-index: 90;
  display: flex; align-items: center; gap: .8rem;
  max-width: min(30rem, calc(100vw - 2.4rem));
  padding: .7rem 1rem;
  background: var(--panel); color: var(--fg);
  border: 1px solid var(--accent); border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  font-size: .9rem;
}
.savebar .spacer { flex: 1; }

/* 안 저장한 칸은 **그 칸에서** 티가 나야 한다 — 바만 보고는 어느 카드인지 모른다. */
.pipe-name.dirty, .pipe-note.dirty {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}

/* ⑤ '+ 단계 추가' 를 눌러 열린 줄 — 열려 있다는 것이 보여야 한다 */
.step-row.add-open {
  border: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  border-radius: 8px; padding: .45rem .5rem;
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}
.ghost.add-step { border-style: dashed; }


/* ==========================================================================
   ⑨ 셋 이상을 묻는 창 + 단계 쓰임새 (링고 2026-08-22)
   ⚠ `confirm` 은 예/아니오뿐이다. 고르는 것이 셋인데 예/아니오로 물으면
     사람이 나머지 하나를 영영 못 만난다. 덮개는 `.busy-hold` 를 그대로 쓴다.
   ========================================================================== */
.ask-card {
  width: min(30rem, calc(100vw - 2.4rem));
  background: var(--panel); color: var(--fg);
  border: 1px solid var(--line); border-radius: 12px;
  padding: 1.2rem 1.3rem 1rem;
  box-shadow: 0 14px 40px rgba(0, 0, 0, .4);
}
.ask-card h3 { margin: 0 0 .35rem; }
.ask-card .sub { margin: .15rem 0; }
/* ⭐ 2.106.0 · 창 아래 단추 줄 — 여태 CSS 가 없어 글자 단추 둘이 **맞붙었다**(링고 09-15 14시 15분 「행사 추가」 캡처).
   만들기 창 한 꼴: 취소 = 왼쪽 옅은 글자 · 실행 = 오른쪽 채운 단추 · 사이는 spacer 가 민다. */
.ask-card > .row.links { display: flex; align-items: center; gap: .9rem; flex-wrap: wrap; margin-top: 1rem; }
.ask-card > .row.links > .spacer { flex: 1; }
.ask-card > .row.links.ask-foot { padding-top: .7rem; border-top: 1px solid var(--line); }
.ask-card .ask-foot .ask-cancel { color: var(--muted); padding-inline: .2rem; }
.ask-card .ask-foot .ask-cancel:hover { color: var(--fg); }
.ask-card .ask-foot .primary { min-width: 5.5rem; }
.ask-choices { display: flex; flex-direction: column; gap: .5rem; margin: 1rem 0 .6rem; }

/* 고르는 줄 — 이름과 **무슨 일이 일어나는지**를 한 덩어리로 둔다.
   이름만 있는 단추는 누르기 전에 결과를 알 수 없다. */
.ask-pick {
  display: flex; flex-direction: column; align-items: flex-start; gap: .2rem;
  width: 100%; text-align: left;
  padding: .6rem .8rem; border-radius: 9px;
  border: 1px solid var(--line); background: var(--bg); color: var(--fg);
  font: inherit; cursor: pointer;
}
.ask-pick:hover:not(:disabled) { border-color: var(--accent); }
.ask-pick:disabled { opacity: .45; cursor: not-allowed; }
.ask-pick b { font-weight: 600; }
.ask-pick .muted { font-size: .82rem; }
.ask-pick.danger { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); }
.ask-pick.danger:hover:not(:disabled) { border-color: var(--danger); }
.ask-pick select { margin-top: .35rem; }

/* 이 단계로 실제 만들어진 것이 몇 개인가 — 지우기 전에 보여야 하는 수 */
.usecount {
  font-size: .74rem; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 0 .45rem;
  white-space: nowrap;
}
.usecount.on {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
}

/* 공유 스텝 코드 — 잠겨 있다는 것이 보여야 한다 (판정 2026-08-22).
   ⚠ 화면 잠금은 안내이고 강제는 서버가 한다 (§21). */
.code-input.locked {
  opacity: .7; cursor: not-allowed;
  border-style: dashed;
  background: color-mix(in srgb, var(--muted) 8%, transparent);
}

/* ④ 여러 장 올린 결과 — 토스트가 아니라 **남는 자리** (링고 2026-08-22).
   토스트는 다음 것이 덮어써서, 무엇이 왜 안 들어갔는지가 아무 데도 안 남았다. */
.up-report:empty { display: none; }
.up-report {
  margin-top: .6rem; padding: .6rem .7rem;
  border: 1px solid var(--st-retake); border-radius: 8px;
  background: color-mix(in srgb, var(--st-retake) 8%, transparent);
  font-size: .86rem;
}
.up-report .up-head { margin-bottom: .35rem; font-weight: 600; }
.up-report .up-bad { display: flex; gap: .5rem; flex-wrap: wrap; padding: .1rem 0; }
.up-report .up-bad b { word-break: break-all; }

/* ① 단계 줄의 ⋯ — 드물게 하는 일은 여기 안에 있다 */
.rowmenu { font-size: 1.05rem; line-height: 1; padding: 0 .35rem; }

/* ==========================================================================
   한글은 낱말 한가운데서 끊지 않는다 (링고 2026-08-22 — "글자가 짜쳐 보이게 깨진다")
   ⚠ 설정 탭 줄에서 한 번 고쳤는데 **표에는 그대로 남아 있었다.** 좁은 칸에서
     "원본 받기" 가 "원본 받 / 기" 로, "올린 사람" 이 세로 한 글자씩으로 쪼개졌다.
     브라우저 기본 줄바꿈이 한글을 글자 단위로 끊기 때문이다 — 폭 문제가 아니다.
   → 앱 전체에 `keep-all` 을 깐다. 영어 긴 낱말은 `break-word` 로 따로 풀어 준다.
   ========================================================================== */
body { word-break: keep-all; }

/* 파일 이름·코드처럼 **띄어쓰기가 없는 긴 것**은 끊어야 칸을 넘지 않는다 */
.history td, .up-report .up-bad b { overflow-wrap: anywhere; }

/* 줄 끝 단추는 쪼개지면 안 된다 — 여기가 링고를 속인 자리다
   ("원본 받 / 기" 와 "목록에 / 서 감추 / 기" 가 한 덩어리처럼 보였다) */
.vactions { white-space: nowrap; }
.vactions a, .vactions button { white-space: nowrap; }

/* 표 머리도 한 줄로 — 세로로 쪼개진 "올 린 사 람" 을 없앤다 */
table.history th { white-space: nowrap; }

/* 버전 줄에서 고른 것 — 컷·에셋 고르기와 같은 결로 보이게 (링고 2026-08-22) */
table.history tr.picked {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

/* ③ 상태를 펼쳐 둔다 — 드롭다운의 "열기" 한 번을 없앤다 (링고 2026-08-22).
   ⚠ 상태는 하루에 수십 번 누르는 것이라 한 번이 통째로 비용이다. */
.seg-pop .row.statuses { display: flex; flex-wrap: wrap; gap: .3rem; }
.st-chip {
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--bg); font: inherit; font-size: .85rem;
  padding: .2rem .6rem; cursor: pointer; white-space: nowrap;
}
.st-chip:hover:not(:disabled) { border-color: currentColor; }
.st-chip.on { border-color: currentColor; font-weight: 600;
              background: color-mix(in srgb, currentColor 12%, transparent); }
.st-chip:disabled { opacity: .45; cursor: not-allowed; }

/* ⭐ 기본 단계 서랍 — 조립 칸 옆에 늘 열려 있다 (링고 2026-08-23)
   *"기본 템플릿 만들어진 것을 보여주고 드래그드롭으로 연결할 수 있게 하자.
     그게 구현되야 쓸데없는 태스크를 안 만든다."*
   ⚠ 좁아지면 **아래로 내려간다.** 서랍이 표를 눌러 조립이 안 보이면 서랍이 방해가 된다. */
.pipe-lane { display: grid; grid-template-columns: minmax(0, 1fr) 15rem; gap: .8rem; align-items: start; }
@media (max-width: 900px) { .pipe-lane { grid-template-columns: minmax(0, 1fr); } }

.palette {
  border: 1px dashed var(--line); border-radius: 10px;
  padding: .5rem .6rem; background: var(--bg);
  display: flex; flex-direction: column; gap: .3rem;
}
.palette-head { font-size: .85rem; font-weight: 600; color: var(--muted); }
.palette .hint { margin: 0 0 .2rem; font-size: .78rem; }

.palette .chip {
  display: flex; align-items: center; gap: .4rem; width: 100%;
  border: 1px solid var(--line); border-radius: 8px; background: var(--panel);
  font: inherit; font-size: .85rem; padding: .25rem .45rem; cursor: grab; text-align: left;
}
.palette .chip:hover:not(.in) { border-color: var(--accent); }
.palette .chip.dragging { opacity: .45; }
.palette .chip.in { opacity: .4; cursor: default; }
.palette .chip .dot { width: .6rem; height: .6rem; border-radius: 3px; flex: none; }
.palette .chip .nm { flex: 1; word-break: keep-all; }
.palette .chip .cd { font-family: ui-monospace, Consolas, monospace; color: var(--muted); font-size: .78rem; }

/* 끌어온 것을 받는 동안 — 어디에 놓이는지 칸 전체가 말해 준다 */
.assemble { min-height: 2.2rem; border-radius: 8px; }
.assemble.drop-here { box-shadow: inset 0 0 0 2px var(--accent); }

/* 조립 줄의 칸 폭 — **코드는 좁게, 이름은 넓게** (링고 2026-08-23)
   *"태스크 코드 폭은 좀 좁게 가져가서 여유좀 확보하고 우측 이름이 더 붙어서 가시성을 높인다."*
   ⚠ 코드는 `Matte` 다섯 글자가 가장 길다 — 그보다 넓을 이유가 없다.
   이름은 한글이라 같은 글자 수라도 자리를 더 먹는다. 남는 폭을 이름이 가져간다. */
.assemble .drag-row .code-input,
.add-open .code-input {
  flex: 0 0 7rem; width: 7rem;
  font-family: ui-monospace, Consolas, monospace;
}
.assemble .drag-row .name-input,
.add-open .name-input { flex: 1 1 14rem; min-width: 8rem; }
.add-open input[type="color"] { width: 1.9rem; height: 1.5rem; padding: 0; border-radius: 4px; }

/* 추가 폼 안의 칩 목록 — 서랍과 같은 모양이되 옆으로 흐른다 */
.palette.inline {
  flex-direction: row; flex-wrap: wrap; gap: .3rem;
  border: 0; padding: .1rem 0 .35rem;
}
.palette.inline .chip { width: auto; cursor: pointer; }
.add-open { padding: .3rem 0 .2rem; }
.add-open .palette-head { font-size: .85rem; font-weight: 600; color: var(--muted); margin-bottom: .2rem; }
.add-open .hint { margin: .2rem 0 0; }

/* ⚠ 조립 카드가 너무 넓었다 (링고 2026-08-23: *"가운데 빈공간 너무 많다.
   많이 옆으로 줄어들어도 되겠는데"*). 넓은 화면에서 이름 칸만 늘어나 **글자는 짧은데
   칸만 긴** 꼴이 됐다. 칸이 아니라 **카드**를 잡는다 — 안쪽만 줄이면 빈자리가 옆으로
   밀릴 뿐이다. */
.pipe-card.for-shot, .pipe-card.for-asset { max-width: 62rem; }
.assemble .drag-row .name-input,
.add-open .name-input { flex: 1 1 12rem; max-width: 24rem; }

/* 사람 사진 동그라미 (링고 2026-08-23)
   ⚠ 사진이 없는 사람이 더 많다 — 빈 동그라미 대신 **이름 첫 글자**를 그린다.
   빈 자리는 "덜 그려진 화면" 으로 읽힌다. */
/* ⭐ 1.5배로 키웠다 (링고 2026-08-24: *"아티스트 썸네일은 좀 더 크게 · 1.5배"*).
   1.6rem 은 «있는지 없는지» 만 보이고 «누구인지» 는 안 보이는 크기였다. */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.4rem; height: 2.4rem; border-radius: 999px; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line);
  color: var(--muted); font-size: 1.05rem; font-weight: 600; flex: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar.big { width: 4rem; height: 4rem; font-size: 1.4rem; }
.avatar.none { background: transparent; border-style: dashed; }
.who { display: inline-flex; align-items: center; gap: .45rem; }

/* 내 사진 넣는 자리 — 누르기·끌어 놓기·붙여넣기 셋 다 받는다 (링고 2026-08-23) */
.avatar-drop {
  display: inline-flex; align-items: center; gap: .6rem;
  padding: .4rem .6rem; border: 1px dashed var(--line); border-radius: 10px;
  cursor: pointer; background: var(--bg);
}
.avatar-drop:hover, .avatar-drop:focus-visible { border-color: var(--accent); outline: none; }
.avatar-drop.dropping { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.avatar-drop .sub { margin: 0; font-size: .8rem; }

/* 사람마다 참여 프로젝트를 칩으로 (링고 2026-08-23) */
.proj-chips { display: inline-flex; flex-wrap: wrap; gap: .25rem; }

/* 남의 눈으로 보는 중 — **늘 보이는 띠** (링고 2026-08-23)
   ⚠ 잊으면 안 보이는 것을 두고 "고장났다" 고 읽는다. 그래서 화면 아래에 붙박이로 둔다. */
.viewas-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  display: flex; align-items: center; justify-content: center; gap: .8rem;
  padding: .5rem .8rem; font-size: .9rem;
  background: color-mix(in srgb, var(--accent) 22%, var(--panel));
  border-top: 2px solid var(--accent); color: var(--fg);
}
body.viewing { padding-bottom: 2.6rem; }

/* 사람 표가 화면 끝까지 늘어나 읽기 어려웠다 (링고 2026-08-23:
   *"각 사용자의 리스트는 지금 너무 와이드하게 표시되어 가시성이 떨어짐"*).
   ⚠ 칸 하나만 줄이면 빈자리가 옆으로 밀린다 — **표 자체를 잡는다.**
   ⚠ 이름·아이디는 짧다. 남는 폭은 참여 프로젝트 칩이 가져간다. */
.people-table { max-width: 58rem; }
.people-table th, .people-table td { padding-left: .4rem; padding-right: .4rem; }
.people-table td input.cell { width: 9rem; }
.people-table td select { max-width: 8rem; }
.people-table .proj-chips { max-width: 22rem; }
.invite-block table { max-width: 58rem; }
.people-table td input.mail-cell { width: 12rem; }

/* 리소스 표를 더 좁힌다 (링고 2026-08-23: *"폭이 너무 넓어 가독성 떨어짐. 반 정도 좁혀도 된다"*) */
.people-table { max-width: 46rem; }
.people-table td input.cell { width: 6.5rem; }
.people-table td input.mail-cell { width: 10rem; }
.people-table td select { max-width: 6.5rem; }
.people-table .proj-chips { max-width: 14rem; }
.people-table .proj-chips input.proj-add { width: 6.5rem; }
.st-chip .x { margin-left: .25rem; opacity: .6; }
/* ⚠⚠ 참여 프로젝트 칩은 **몸통이 아니라 × 만** 빼기 단추다 (실사고 2026-08-26 —
   몸통을 스쳐 눌러 사람이 프로젝트에서 빠졌고 담당 60건이 비워졌다).
   그래서 몸통은 `<span>`(안 눌림), × 만 `<button>` 이다. 손짓도 그 자리에만 준다. */
.people-table .st-chip { cursor: default; }
.people-table .st-chip button.x {
  border: 0; background: none; padding: 0 .15rem; font: inherit; line-height: 1;
  color: inherit; cursor: pointer; opacity: .55; border-radius: 4px;
}
.people-table .st-chip button.x:hover { opacity: 1; color: var(--st-retake); }
.people-table .st-chip button.x:disabled { opacity: .3; cursor: default; }

/* ⭐ **참여 프로젝트는 2열 격자** (링고 2026-08-26).
   ⚠ 처음엔 «옆으로 길게» 로 지었는데, 링고가 바로 다음 자를 댔다:
     *"프로젝트가 많아질 수 있으니 2열로 여러개 들어갈 수 있게 한다."*
   ⭐ 한 줄로 흐르면 열 개가 되는 날 **가로로 끝없이 밀린다.** 2열은 열 개여도 다섯 줄이라
     자라는 방향이 예측된다 — 표는 아래로 자라는 것이 자연스럽다.
   ⚠ 한 칸에 하나씩 쌓이는 것(1열)과 다르다: 폭을 두 배로 쓰니 줄 수가 반이다. */
/* ⚠ **`min-width` 만으로는 안 잡혔다** (실측 2026-08-26: 칸이 123px 로 눌렸다).
   표가 `max-width: 46rem` 안에서 칸을 나눠 쓰는데, auto 배치에서 `min-width` 는 부탁일
   뿐이라 다른 칸이 먼저 가져간다. **폭을 못박고 표에 그만큼 자리를 준다.**
   ⚠ 표 전체를 46rem 로 좁힌 것은 08-23 판정이라 크게 안 건드린다 — 프로젝트 칸이
     늘어난 만큼만 늘린다(46 → 54rem). */
.people-table { max-width: 62rem; }
.people-table td.projcell, .people-table th.projcol { width: 13rem; }
/* 올린 버전 자동 승인 칸 (104) — 네모 + 켬/끔 + (기본) 한 줄 */
.people-table label.auto-approve { display: inline-flex; gap: .3rem; align-items: center; white-space: nowrap; }
.people-table .auto-default { font-size: .72rem; }
.people-table .proj-chips {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .25rem; max-width: 13rem; align-items: start;
}
/* 더하는 칸은 **두 칸을 다 쓴다** — 반 칸에 넣으면 프로젝트 이름을 칠 자리가 없다 */
.people-table .proj-chips input.proj-add { grid-column: 1 / -1; width: 100%; }
.people-table .proj-chips .st-chip { min-width: 0; }
.people-table .proj-chips .st-chip span:first-child {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 900px) {
  /* 폰에서는 한 줄에 하나 — 두 칸으로 쪼개면 코드가 잘린다 */
  .people-table .proj-chips { grid-template-columns: 1fr; max-width: 10rem; }
  .people-table td.projcell { min-width: 0; }
}

/* 초대 코드가 여는 곳 — 여러 곳을 체크로 고른다 (056) */
.invite-projs { display: inline-flex; flex-wrap: wrap; gap: .1rem .55rem; max-width: 24rem; }
.invite-projs label { font-size: .85rem; }
.invite-projs.off { opacity: .45; }


/* 폰 폭 — 탭 줄을 **햄버거로 접는다** (§20-6, 2026-08-23)
   ⚠ **활성 탭은 접혀도 보인다.** 지금 어느 화면인지가 사라지면 그건 메뉴가 아니라 미아다.
   ⚠ 햄버거(`#tab-menu`)와 테마 스위치는 남긴다 — 접는 손잡이 자체가 사라지면 못 편다. */
@media (max-width: 560px) {
  .topbar { gap: .5rem; padding: .5rem .7rem; }
  .tabs .tab:not(.active) { display: none; }
  .topbar .build { display: none; }      /* 판 도장은 폰에서 자리를 살 값이 없다 */
  #project-switch { max-width: 9rem; }
}

/* 상세 머리 — 큰 그림 + 지금 어디까지 왔나 (링고 2026-08-23 ⑤)
   ⚠ 그림이 화면을 다 먹으면 아래 표가 안 보인다. **그림은 고정 높이, 옆이 설명**이다. */
.hero { display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: 1rem;
        align-items: start; margin: .2rem 0 .8rem; }
/* ⭐ **타이틀은 글이 왼쪽, 그림이 오른쪽** — 허브 「콘텐츠 상세」 꼴 그대로 (발주 v2 §②).
   ⛔ 컷·에셋(`.hero` 그대로)은 뒤집지 않는다: 링고가 2026-08-29 에 정한 자리다.
   ⭐ 2.117.0 · 그림 칸을 **컷 상세와 같은 22rem** 으로 맞췄다 (HQ [발주] 09-15 ③① 「같은 자리·같은 크기」). */
.hero.hero-ep { grid-template-columns: minmax(0, 1fr) minmax(0, 22rem); }
.hero-media { display: flex; flex-direction: column; gap: .3rem; }
.hero-nofile { margin: 0; font-size: .8rem; }
/* 제목 옆 작은 「제목 복사」 (발주 ③④) — 제목 줄의 한 칸이지 화면 폭 단추가 아니다 */
.hero-copy-title { display: inline-flex; align-items: center; gap: .25rem; }
/* 그림이 없으면 **빈 상자를 그리지 않는다** — 칸도 같이 접는다(발주 「빈 상자는 있을 때만 편다」) */
.hero.hero-solo { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) {
  .hero, .hero.hero-ep { grid-template-columns: minmax(0, 1fr); }
}

.hero-img {
  width: 100%; height: 12rem; border-radius: 10px; border: 1px solid var(--line);
  background: var(--panel) center/cover no-repeat; display: block; cursor: pointer;
}
.hero-img.none { display: flex; align-items: center; justify-content: center; cursor: default; }
.hero-side { display: flex; flex-direction: column; gap: .5rem; }
.hero-line { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.hero-line b { font-size: 1.1rem; }
.hero .hint { margin: 0; }

/* 태스크 필드 표 — 나중에 간트가 읽을 것과 같은 줄이다 */
.task-fields { max-width: 62rem; }
.task-fields .task-row { cursor: pointer; }
.task-fields .task-row:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.task-fields .dot { width: .6rem; height: .6rem; border-radius: 3px; display: inline-block; flex: none; }
.task-fields-wrap { margin-bottom: 1rem; }
/* ⭐ 2.95.0 · 표 아래 옅은 「+ 태스크」 — 올리면 진해진다 · 편집 못 하는 사람은 회색(누르면 아무것도 안 함 · 까닭은 풍선) */
.task-add-line {
  display: block; width: 100%; margin-top: 2px; padding: .3rem .6rem;
  background: none; border: 1px dashed transparent; border-radius: 6px;
  color: var(--muted); font: inherit; font-size: .84rem; text-align: left; cursor: pointer; opacity: .55;
}
.task-add-line:hover:not(.off), .task-add-line:focus-visible:not(.off) {
  opacity: 1; color: var(--fg); border-color: var(--line);
  background: color-mix(in srgb, currentColor 6%, transparent);
}
.task-add-line.off { opacity: .35; cursor: not-allowed; }

/* 보기 방식 스위치 — **메뉴 밖에** 둔다 (링고 2026-08-23: 못 찾아서 이미 있는 기능을 다시 청했다) */
.view-switch { flex: none; }
.asset-view-row { display: flex; align-items: center; gap: .5rem; margin: 0 0 .5rem; }

/* ==========================================================================
   단계 열 접기·펼치기 (링고 2026-08-23 · 샷그리드 레퍼런스)

   접힘 → 상태 한 칸 · 펼침 → 상태 · 태스크 이름 · 담당.
   ⚠ 머리줄의 작은 칸과 내용 칸이 **같은 격자**를 쓴다 — 두 벌로 두면 어긋난다.
   ⚠ 열 전체를 형광으로 칠하지 않는다(§20-1). 레퍼런스(SG)는 칠하지만 우리 화면은
     단계가 열둘까지 가고, 그러면 표가 아니라 색표가 된다. **머리줄만 칠한다.**
   ========================================================================== */

/* 머리줄 겉옷 — 꺾쇠 · 점 · 이름 · 진행률이 한 줄에 선다.
   ⭐ **이 겉옷이 스스로 폭을 잰다**(`container-type`). 좁아지면 아래 규칙이 진행률을 감춘다 —
   ⚠ `th` 에 직접 주지 않는다. 칸의 성질을 바꾸면 나란한 칸들이 뭉친다(§9-34). */
th .col-head {
  container-type: inline-size;
  display: flex; align-items: baseline; gap: .1rem; min-width: 0;
}
th .col-head > .col-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
th .col-head > .col-pct { margin-left: auto; }

/* ⭐ **좁으면 진행률이 먼저 사라진다** (링고 2026-08-25). 이름은 끝까지 산다 —
   *"글자가 숨겨지는데 퍼센티지가 숨겨지도록 한다."*
   ⚠ 숫자(112px)는 «꺾쇠+세 글자+진행률» 이 겨우 들어가는 폭이다. 이보다 좁아지면
     둘 중 하나는 잘리는데, **잘려서 못 읽는 것은 이름 쪽이 더 아깝다.** */
@container (max-width: 112px) {
  th .col-head > .col-pct { display: none; }
}

/* ⚠⚠ **화살표는 진행률과 같은 자에 서면 안 된다** (실측 2026-09-01).
   위 112px 규칙에 화살표를 같이 넣었더니 **「코드」 칸(110px)에서 표식이 통째로 사라졌다** —
   정렬은 걸려 있는데 화면은 아무 말도 안 한다(제일 자주 누를 칸에서 그랬다).
   ⭐ 진행률은 «세 글자 + 숫자» 라 112px 이 맞고, 화살표는 10px 이다 — **재는 자가 다르다.** */
@container (max-width: 64px) {
  th .col-head > .col-sort { display: none; }
}

/* ⭐ 버전 갈래 딱지 (069 · FBX). ⚠ **노트보다 세면 안 된다** — 노트가 사람이 쓴 말이다.
   딱지는 «무엇인가» 를 한눈에 알려 주는 자리지 읽을 것이 아니다. */
.vkind {
  display: inline-block; font-size: .62rem; font-weight: 700; letter-spacing: .02em;
  padding: .05rem .3rem; margin-right: .3rem; border-radius: 4px; vertical-align: 1px;
  background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--fg);
}
.vframes { font-size: .72rem; margin-right: .3rem; }
/* ⭐ 천체 만들기가 내는 둘 (09-12) — 무늬는 그림, 형태는 메시라 색으로 가른다.
   ⚠ 「FBX」 처럼 대문자 딱지가 아니라 **사람 말**이 들어온다(`VKIND_WORD`). */
.vkind.texture { background: color-mix(in srgb, #d9a63c 30%, transparent); }
.vkind.body { background: color-mix(in srgb, #4a7bd9 28%, transparent); }
/* 파일이 실제로 있는 자리 — 읽는 글자다(링크가 아니다 · 050). 좁으면 뒤가 잘린다. */
.vpath {
  display: inline-block; font-size: .68rem; margin-left: .35rem;
  max-width: 26rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
}

/* 099 · 「도구」 에셋 (HQ [발주] 09-14 4시) — 판 딱지 · 첨부 칩 · 진행 · 의견 · 문서 */
.vkind.tool { background: color-mix(in srgb, #495057 30%, transparent); font-size: .68rem; }
.tool-block {
  border: 1px solid var(--line); border-radius: 10px; padding: .6rem .8rem; margin: .6rem 0;
  display: grid; gap: .5rem; background: var(--panel);
}
.tool-head { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.tool-head .spacer { flex: 1; }
.tool-next { margin: 0; font-size: .9rem; }
.tool-block h4 { margin: .2rem 0; font-size: .85rem; color: var(--muted); font-weight: 600; }
.tool-pans td { vertical-align: top; }
.tool-atts { display: flex; flex-wrap: wrap; gap: .25rem; }
.tool-att {
  font-size: .72rem; line-height: 1.3; padding: .08rem .45rem; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg); color: var(--muted);
}
.tool-att.readable { color: var(--fg); border-color: color-mix(in srgb, var(--accent) 55%, var(--line)); }
.tool-att:hover { border-color: var(--accent); }
.tool-opinions .reply-row { margin: .2rem 0; }
.tool-opinions .note-form { display: flex; gap: .4rem; }
.tool-opinion-in { flex: 1; min-width: 0; }
.tool-docs ul { margin: 0; padding-left: 1.1rem; }
.tag-chip.opinion {
  display: inline-block; font-size: .66rem; font-weight: 700; padding: .02rem .35rem; margin-right: .3rem;
  border-radius: 4px; background: color-mix(in srgb, #f08c00 28%, transparent); color: var(--fg);
}
.tool-read-head { display: flex; align-items: center; gap: .3rem; margin-bottom: .3rem; }
.tool-read-head + .tool-atts { margin-bottom: .4rem; }

/* 줄 정렬 표식 (링고 2026-09-01) — ⚠ **켜지지 않은 칸에서는 안 보인다.**
   머리줄 열둘에 화살표가 늘 떠 있으면 그것이 곧 소음이다. 손을 얹으면 «누를 수 있다» 가
   흐리게 뜨고, 걸린 칸만 또렷하게 남는다. ⚠ 좁아지면 진행률과 같이 먼저 사라진다. */
th.sortable { cursor: pointer; }
th .col-head > .col-sort {
  margin-left: auto; font-size: .6rem; line-height: 1; flex: none;
  color: var(--muted); opacity: 0; transition: opacity .12s;
}
th.sortable:hover .col-head > .col-sort { opacity: .7; }
th.sorted .col-head > .col-sort { opacity: 1; color: var(--accent); }
th.sorted .col-head > .col-name { color: var(--fg); }

/* 접기·펼치기 꺾쇠 — 머리줄 왼쪽 */
button.col-chev {
  border: 0; background: none; color: var(--muted); cursor: pointer;
  font-size: .95rem; line-height: 1; padding: 0 .25rem 0 0; margin-right: .1rem;
}
button.col-chev:hover { color: var(--fg); }

/* 단계 진행률 — 머리줄 오른쪽 끝 */
th.stepH .col-pct {
  float: right; font-size: .78rem; font-weight: 700; color: var(--muted);
  font-variant-numeric: tabular-nums; padding-left: .3rem;
}
th.stepH .col-pct.full { color: var(--st-done, var(--fg)); }




/* 작은 머리줄 (상태 · 태스크 이름 · 담당) */
table.shot-table thead tr.sub-head th {
  padding-top: 0; padding-bottom: .2rem; border-bottom: 1px solid var(--line);
  font-weight: 500; background: var(--panel);
}
tr.sub-head th small { color: var(--muted); font-size: .74rem; letter-spacing: .02em; }
/* ⚠ 여기에 `display: grid` 를 주면 **th 가 표의 칸이 아니게 되어** 옆 칸들과 한 덩어리로
   뭉친다 (2026-08-24). 격자는 안쪽 겉옷(`.tc-grid`)이 쓴다. */
tr.sub-head th.open { vertical-align: middle; }
tr.sub-head th.shut small { display: block; }

/* 내용 칸 — 작은 머리줄과 같은 격자 */
:root { --tc-grid: minmax(0, 1fr) minmax(0, 1.15fr) minmax(0, 1.15fr); }
/* ⚠⚠ **칸의 display 를 바꾸지 않는다.** 바꾸면 그 칸은 표의 칸이 아니게 되고,
   나란히 있는 그런 칸들이 **익명 칸 하나에 몰려 세로로 쌓인다** — 펼친 단계가 둘 이상일 때
   «두 번째 이후가 안 보인다» 가 그것이었다 (링고 2026-08-24). */
td.taskcell.open { display: table-cell; white-space: nowrap; vertical-align: middle; }
.tc-grid {
  display: grid; grid-template-columns: var(--tc-grid); gap: .3rem; align-items: center;
  min-width: 0;
}
.tc-grid > * { min-width: 0; }
td.taskcell.open > div { min-width: 0; }
td.taskcell.open select { max-width: 100%; }
td.taskcell .tc-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--muted); font-size: .86rem;
}
/* 접힌 칸은 상태 하나. 좁으므로 글자를 줄인다 */
td.taskcell.shut { white-space: nowrap; }
td.taskcell.shut select { max-width: 100%; font-size: .84rem; padding-left: .2rem; padding-right: .2rem; }

/* 파이프라인 한 번에 접기 */
button.pipe-toggle { flex: none; white-space: nowrap; font-size: .86rem; }

/* 접힌 단계 머리줄 — **이름이 먼저 산다** (링고 화면 실측 2026-08-23: `» 디…` 로 잘렸다).
   진행률은 줄바꿈 없이 오른쪽에 붙고, 모자라면 이름이 줄임표로 줄어든다. */
th.stepH.shut { white-space: nowrap; }
/* ⚠ 예전에는 여기서 이름에 `max-width: calc(100% - 52px)` 를 걸어 **진행률 자리를 미리
   비워 뒀다** — 그래서 좁히면 이름이 `» 디…` 로 먼저 잘렸다(링고가 두 번 짚었다).
   ⭐ 이제 겉옷이 폭을 재서 **진행률을 통째로 감춘다.** 이름은 자리를 안 내준다. */
th.stepH.shut .col-pct { float: none; }

/* ==========================================================================
   상태 아이콘 · 리뷰 대기 · 상세 화면 정리 (링고 2026-08-23)
   ========================================================================== */

/* ⭐⭐ **상태는 아이콘이다** (HQ [발주] 09-06 밤 · 옛 도구의 그 줄).
   ⚠ 여태는 **채워지는 동그라미**였다 — 채움 정도로 일곱을 갈랐더니 12px 에서 「반쯤」과
     「4분의 1」이 같아 보였다. 이제 **모양이 다르다**(그림은 app.js 의 `GLYPH_PATH`).
   ⚠ 색은 한 자리(`--sc`)에서 오고, 그림은 `currentColor` 로 그것을 따라간다. */
i.sicon {
  display: inline-flex; align-items: center; justify-content: center;
  /* ⭐⭐ 아이콘 뒤에 **옷은 둥근 바탕** (발주 컷리스트 일곱 §3 · 링고:
     「흰 바탕 위에 아이콘만 떠 있어서 잘 안 보인다」). 바탕 22 · 그림 14 · 모두 같은 크기.
     ⚠ 바탕은 뜻을 안 나른다 — 뜻은 그림이 나른다(그래서 색은 한 가지만 다르다: 수정). */
  width: 22px; height: 22px; border-radius: 6px;
  vertical-align: -6px; color: var(--sc);
  background: var(--sicon-bg); border: 0;
}
i.sicon svg { width: 14px; height: 14px; display: block; }
/* ⛔ 2.68.0 의 상태 색 링(안쪽 그림자 · 굵게 · 점선)과 「수정」의 붉은 바탕은 2.73.0 에서 걷었다
   (HQ [발주] 09-13 17시 ② · 링고 「격자 스트로크는 없어도 된다 · 시작 전 꼴이 눈이 편하다」).
   ⭐ 모든 상태가 위의 조용한 바탕 한 벌이고, 그림 색(`--sc`)만 상태를 말한다(app.js `statusIconInk`).
   ⚠ 되돌리는 법: `git show 8052670:app/static/style.css` 의 이 자리 열여덟 줄. */
/* ⚠ 상세 머리의 큰 아이콘은 **이미 있던 규칙**이 키운다( · scale 1.5) —
   여기서 또 키우면 두 번 커진다(한 번 밟을 뻔했다). */

/* 아이콘 위에 진짜 select 를 투명하게 덮는다 — 누르면 그대로 바뀐다 */
.sicon-wrap { position: relative; display: inline-block; line-height: 1; }
.sicon-wrap select.overlay {
  position: absolute; inset: -4px -6px; opacity: 0; width: calc(100% + 12px);
  height: calc(100% + 8px); cursor: pointer;
}
.sicon-wrap select.overlay:disabled { cursor: default; }
.sicon-wrap:focus-within i.sicon { outline: 2px solid var(--accent, var(--sc)); outline-offset: 2px; }
td.st-icon-cell { text-align: center; }

/* ==========================================================================
   ⭐⭐⭐ 상태 강조 — 멀리서도 보이게 (HQ [발주] 09-14 17시 · 2.89.0 · app.js `statusCell` 주석)
   칸 채움 = 상태 색 40% 바탕(`--st-bg`) + 왼쪽 굵은 띠 100%(`--st-c`) + 큰 점 12px + 이름.
   ⚠ 색은 칸이 든다(JS 가 상태 사전 값을 적는다) — 여기서 색을 짓지 않는다.
   ⚠ 고른 줄의 옅은 파랑(`tr.picked > td`)보다 **상태 칸 바탕이 이긴다** — 골라도 상태는 보여야 한다.
   ========================================================================== */
table.shot-table tbody tr > td.st-icon-cell.st-fill {
  background: var(--st-bg);
  box-shadow: inset 4px 0 0 var(--st-c);
}
/* ⚠ 가운데 정렬은 그대로 — 단계 칸·상태 칸 아이콘이 칸 가운데라는 자([B30])를 칸 채움도 지킨다 */
td.st-icon-cell .st-box {
  container-type: inline-size;
  display: flex; align-items: center; justify-content: center; gap: .35rem; min-width: 0; width: 100%;
}
.col-menu .st-emph-switch button,
.col-menu .sum-mode-switch button { white-space: nowrap; padding: .3rem .45rem; }
/* ⚙ 판 한 줄 묶음 — 이름 옆에 고르개 · 켬끔 여럿 (2.89.0 · 판 키를 줄인다) */
.col-menu .menu-row { display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .7rem; }
.col-menu .menu-row > .menu-lead { margin: 0; }
.sicon-wrap.st-big {
  display: inline-flex; align-items: center; gap: .4rem; min-width: 0; line-height: 1.2;
}
i.sdot {
  display: inline-block; flex: none; width: 12px; height: 12px; color: var(--sc);
}
i.sdot svg { width: 12px; height: 12px; display: block; }
.sicon-wrap.st-big .st-name {
  font-size: .86rem; font-weight: 600; color: var(--fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.sicon-wrap.st-big:focus-within i.sdot { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 50%; }
/* 칸 폭이 좁으면 점만 (발주 ①) */
@container (max-width: 64px) {
  .sicon-wrap.st-big .st-name { display: none; }
}
/* 칸+띠 — 줄 맨 왼쪽 3px 세로 띠 = 그 줄 상태 색. ⚠ 고른 줄은 파란 띠가 위(발주 ②) */
table.st-band tbody tr[data-st]:not([data-st=""]) > td:first-child { box-shadow: inset 3px 0 0 var(--row-st); }
table.st-band tbody tr[data-st] > td:first-child.st-fill { box-shadow: inset 3px 0 0 var(--row-st), inset 7px 0 0 var(--st-c); }
table.st-band tbody tr.picked[data-st] > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }
table.st-band.task-fields tbody tr.on[data-st] > td:first-child { box-shadow: none; }

/* 10-11 · 리뷰 대기 딱지가 선 상태 칸 — 칸 전체가 고르개(status_parts.js `statusCell` · 딱지를 눌러도 상태를 고른다)
   좁으면 상태 이름 밑으로 딱지가 내려간다(이름이 안 잘린다) */
td.st-icon-cell.st-wide { position: relative; }
td.st-icon-cell.st-wide .sicon-wrap { position: static; }
td.st-icon-cell.st-wide .sicon-wrap select.overlay { inset: 0; width: 100%; height: 100%; z-index: 1; border-radius: 0; margin: 0; }
td.st-icon-cell.st-wide .st-box { flex-wrap: wrap; row-gap: 2px; container-type: normal; }   /* 칸 담기(container)는 고르개를 상자 안에 가둔다 — 칸 전체를 덮게 푼다 */
td.st-icon-cell.st-wide .review-wait { margin-left: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
td.st-icon-cell.st-wide:focus-within { outline: 2px solid var(--accent); outline-offset: -2px; }

/* 리뷰 대기 — 상태가 아니라 상태 위에 얹힌 것. 인코딩 딱지를 빌려 쓰지 않는다 */
.review-wait {
  display: inline-block; margin-left: .35rem; padding: .05rem .4rem;
  border: 1px dashed var(--st-review, var(--muted)); border-radius: 999px;
  color: var(--st-review, var(--muted)); font-size: .78rem; white-space: nowrap;
}

/* 상세 — 지금 보고 있는 것과 돌아가는 길 */
.pipeline-bar .back-all {
  border: 1px solid var(--line); background: var(--panel); color: var(--fg);
  border-radius: 8px; padding: .25rem .6rem; margin-right: .5rem; font-size: .88rem;
}
.pipeline-bar .back-all:hover { border-color: var(--fg); }
.pipeline-bar .now-seeing { font-size: .9rem; }
#detail-title.clickable { cursor: pointer; }
#detail-title.clickable:hover { text-decoration: underline; }

/* 표에서 지금 보고 있는 줄 */
table.task-fields tbody tr.task-row { cursor: pointer; }
/* ⭐ **고른 단계는 한눈에 띄어야 한다** (링고 2026-08-24: *"선택된 태스크의 글자 박스에
   하이라이트를 넣어 주자"*). 예전엔 왼쪽 3px 선 하나뿐이라, 줄이 여럿이면 어느 것을
   보고 있는지 눈이 다시 찾아야 했다. ⭐ 바탕을 강조색으로 옅게 깔고 **이름 칸에
   알약**을 씌운다 — 글자가 스스로 «나는 골라진 것» 이라고 말한다. */
/* ⭐ **한 번 더 세게** (링고 2026-08-25: *"지금보다 50% 더 선택된 티가 나도록. 현재도
   선택된 티가 덜 난다"*). 바탕 14%→22% · 왼쪽 선 3px→6px · 위아래로 강조색 테두리를
   둘러 **줄 전체가 한 덩어리로** 보이게 한다. ⚠ 열을 형광으로 칠하지는 않는다(§20-1) —
   칠하는 것은 «고른 줄» 하나뿐이다. */
table.task-fields tbody tr.task-row.on {
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  box-shadow: inset 6px 0 0 var(--accent),
              inset 0 1px 0 color-mix(in srgb, var(--accent) 55%, transparent),
              inset 0 -1px 0 color-mix(in srgb, var(--accent) 55%, transparent);
}
table.task-fields tbody tr.task-row.on td:first-child,
table.task-fields tbody tr.task-row.on td:nth-child(2) { font-weight: 700; color: var(--fg); }
table.task-fields tbody tr.task-row.on td:nth-child(2) > * {
  display: inline-block; padding: .1rem .5rem; border-radius: 999px;
  background: color-mix(in srgb, var(--accent) 42%, transparent);
}
/* 고른 줄의 첫 칸에 ▸ 를 세운다 — 색을 못 가리는 눈에도 «여기» 가 보인다 */
table.task-fields tbody tr.task-row.on td:first-child::before {
  content: "▸"; color: var(--accent); margin-right: .35rem; font-weight: 700;
}

/* ⚠ 비율이 다른 그림은 **누르지 말고 자른다** (링고 2026-08-23).
   `.hero-img` 가 <div> 일 때는 background 의 `cover` 가 이미 그렇게 하고 있었는데,
   <img> 로 그릴 때는 그 규칙이 안 먹어서 **세로로 눌린 얼굴**이 됐다.
   ⭐ 같은 클래스가 두 종류의 태그로 그려지면, 한쪽에만 듣는 규칙이 생긴다. */
/* ⚠⚠ **세로 그림이 잘렸다** (링고 09-03 화면 · 손맛 다섯 ②). `cover` 는 칸을 채우려고
   넘치는 쪽을 자른다 — 도서 컷은 세로가 길어서 **그림의 위아래가 사라졌다.**
   ⭐ `contain` 은 줄여서 넣는다: 좌우에 여백이 생기고 **온전히 보인다.**
   ⚠ 칸 비율은 그대로 둔다(발주) — 표 줄 높이가 그림마다 달라지면 목록이 출렁인다. */
img.hero-img { object-fit: contain; object-position: center; background: var(--line); }

/* 가져오기 뒤 따라다니는 띠 — 판을 닫고 이것만 남는다 (링고 2026-08-23).
   ⚠ 화면을 덮지 않는다. 넣은 뒤 제일 먼저 하고 싶은 일이 «들어간 것 보기» 라서다. */
.import-undo-bar {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 1.2rem; z-index: 60;
  display: flex; align-items: center; gap: .75rem; max-width: min(92vw, 46rem);
  padding: .55rem .9rem; border-radius: 10px;
  background: var(--panel); border: 1px solid var(--line);
  box-shadow: 0 6px 24px rgba(0,0,0,.35);
}
.import-undo-bar b { white-space: nowrap; }
.import-undo-bar .muted { font-size: .86rem; }

/* 표에서 고른 단계 — 한 번은 거르기(on), 두 번은 열기(deep) */
/* ⚠ `.on` 과 같이 붙는 줄에서는 **이 규칙이 나중이라 위의 강조를 덮었다**(실측 2026-08-25:
   6px 로 올려 놨는데 화면에는 3px 이 그려졌다). 그래서 `.on` 이 아닌 때만 그린다 —
   ⭐ 같은 것을 두 규칙이 그리면 **나중에 적은 쪽이 이긴다**. 세기를 올릴 때는 형제를 세어라. */
table.task-fields tbody tr.task-row.deep:not(.on) { box-shadow: inset 3px 0 0 var(--accent); }

button.ghost.small { padding: .15rem .5rem; font-size: .82rem; }

/* 버전 줄의 단추 — **모양을 갈라 둔다** (링고 2026-08-23: "원본 받기목록에서 감추기" 로
   두 낱말이 한 말처럼 읽혔다). 받기는 아이콘, 나머지는 테두리 있는 단추. */
td.vactions { display: flex; align-items: center; gap: .4rem; white-space: nowrap; }
.vbtn {
  border: 1px solid var(--line); background: var(--panel); color: var(--fg);
  border-radius: 6px; padding: .12rem .45rem; font-size: .8rem; line-height: 1.5;
  text-decoration: none; cursor: pointer;
}
.vbtn:hover { border-color: var(--fg); }
.vbtn.dl { font-size: 1rem; padding: .02rem .4rem; }
.vbtn.danger { color: var(--danger); border-color: transparent; }
.vbtn.danger:hover { border-color: var(--danger); }

/* 버전 상태 — 승인 · 리뷰대기 · 미승인 (링고 2026-08-24).
   ⚠ 글자를 안 지운다. 셋이 서로 반대말이라 색만으로는 안 갈린다. */
.vchip {
  display: inline-block; padding: .05rem .45rem; border-radius: 999px;
  font-size: .78rem; white-space: nowrap; border: 1px solid currentColor;
}
.vchip.ok { color: var(--st-done, #4caf50); }
.vchip.wait { color: var(--muted); }
.vchip.no { color: var(--st-retake, #e5533d); }
.vbtn.ok:hover { border-color: var(--st-done, #4caf50); color: var(--st-done, #4caf50); }
.vbtn.no:hover { border-color: var(--st-retake, #e5533d); color: var(--st-retake, #e5533d); }

/* 리뷰대기·미승인은 **그림에서 바로 보인다** (링고 2026-08-24).
   ⚠ 승인은 표시하지 않는다 — 기본이 승인이라, 적으면 전부 적히고 전부 적히면 안 읽힌다. */
.gcell.v-wait .gimg { outline: 2px dashed var(--muted); outline-offset: -2px; }
.gcell.v-no .gimg { outline: 2px solid var(--st-retake, #e5533d); outline-offset: -2px; opacity: .55; }
.gstate {
  margin-left: .3rem; padding: 0 .3rem; border-radius: 999px;
  font-size: .72rem; border: 1px solid currentColor; white-space: nowrap;
}
.gstate.wait { color: var(--muted); }
.gstate.no { color: var(--st-retake, #e5533d); }
/* 「자동 승인」 작은 글자 (104 · 2.93.0) — 테두리 없이 흐리게. 승인 알약보다 앞에 서지 않는다 */
.vauto {
  margin-left: .3rem; font-size: .68rem; color: var(--muted); white-space: nowrap; cursor: help;
}

/* 거푸집의 기본 담당 (037) — 줄이 길어지므로 좁게 */
select.step-assignee { max-width: 8rem; font-size: .84rem; }
/* 아티스트 탭에서 사진 바꾸기 — 누를 수 있다는 것이 보여야 한다 */
.avatar-pick { position: relative; cursor: pointer; display: inline-block; }
.avatar-pick:hover .avatar { outline: 2px solid var(--fg); outline-offset: 1px; }
.avatar-pick .hidden-file { display: none; }

/* 한꺼번에 고치기 판 (링고 2026-08-24) */
.ask-card.wide { max-width: 34rem; }
.bulk-line { display: flex; align-items: center; gap: .6rem; margin: .35rem 0; }
.bulk-line > label { min-width: 9rem; color: var(--muted); font-size: .9rem; }
.bulk-line select { min-width: 10rem; }
.ask-card hr { border: 0; border-top: 1px solid var(--line); margin: .6rem 0; }

/* ── 글 여러 장 (039 · 링고 2026-08-24) ─────────────────────────────────────
   왼쪽에 목록(박스·리스트), 고르면 **오른쪽 뷰어**에 걸린다.
   ⚠ 상태 색은 버전이 쓰는 것을 그대로 쓴다 (vchip·v-wait·v-no) — 두 벌로 두지 않는다. */
.docs-box { margin-top: .4rem; }
.docs-bar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.docs-bar .spacer { flex: 1; }
.docs-box.dropping { outline: 2px dashed var(--accent); outline-offset: 5px; border-radius: 10px; }

.docs-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: .6rem; }
.dcard {
  margin: 0; display: flex; flex-direction: column; cursor: pointer; overflow: hidden;
  background: var(--panel); border: 2px solid var(--line); border-radius: 10px;
}
.dcard:hover { border-color: var(--muted); }
.dcard.current { border-color: var(--accent); }
.dcard-head { display: flex; align-items: center; gap: .4rem; padding: .45rem .55rem .15rem; }
.dcard-title { flex: 1; font-size: .9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 썸네일 자리가 글의 앞머리다 — 그림 없는 물건이라 **글이 곧 그림**이다 */
.dcard-body {
  height: 5.6rem; padding: 0 .55rem; overflow: hidden;
  font-family: ui-monospace, Consolas, monospace; font-size: .74rem; line-height: 1.5;
  color: var(--muted); white-space: pre-wrap; overflow-wrap: anywhere;
}
.dcard-foot {
  display: flex; align-items: center; gap: .4rem;
  padding: .3rem .55rem .45rem; font-size: .76rem;
}
.dcard-foot .muted { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dcard.v-wait { border-style: dashed; }
.dcard.v-no { border-color: var(--st-retake, #e5533d); opacity: .7; }

/* 오른쪽 뷰어에 걸린 글 */
.doc-viewer { display: flex; flex-direction: column; gap: .5rem; }
.doc-viewer-head { display: flex; align-items: center; gap: .5rem; }
.doc-title { flex: 1; font-weight: 600; }
.doc-viewer:not(.show-edit) .doc-area { display: none; }
.doc-viewer:not(.show-preview) .doc-preview { display: none; }
.doc-viewer .doc-area, .doc-viewer .doc-preview { min-height: 20rem; }
.doc-save { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.doc-save .hint { margin: 0; }

/* 폴더째 올리기 — 진행 줄 */
.folder-log:not(:empty) {
  margin-top: .6rem; max-height: 14rem; overflow: auto;
  border: 1px solid var(--line); border-radius: 9px; padding: .4rem .6rem; background: var(--bg);
}
.folder-line { font-family: ui-monospace, Consolas, monospace; font-size: .8rem; line-height: 1.6; }
.row-warn td { color: var(--muted); }
/* 올리기 창 컷 지킴이(09-21 급 항목3) — **막지 않는 주황**(--st-retake) 한 줄. `.row-warn`(빨강 · 못 올림)과 다르다. */
.row-caution-text { color: var(--st-retake); }

/* 폴더를 끌어다 놓는 자리 */
.folder-drop {
  margin: .5rem 0; padding: .7rem .8rem;
  border: 2px dashed var(--line); border-radius: 10px; background: var(--bg);
}
.folder-drop.over { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
.folder-drop .dz-hint { margin-bottom: .5rem; color: var(--muted); font-size: .85rem; }

/* 폴더째 올리기 — **자라는 것은 표 하나뿐이다.** 단추는 늘 바닥에 남는다 */
.import-pop > * { flex: none; }
.import-pop .folder-list {
  flex: 1 1 auto; min-height: 5rem; overflow: auto;
  border: 1px solid var(--line); border-radius: 9px;
}
.import-pop .folder-list table { margin: 0; }
.import-pop .folder-list thead th {
  position: sticky; top: 0; z-index: 1; background: var(--panel);
}
.folder-actions {
  position: sticky; bottom: 0; padding-top: .5rem; margin-top: .1rem;
  background: var(--panel); border-top: 1px solid var(--line);
}
.import-pop .folder-log { max-height: 9rem; }
/* 2.111.0 · 영상 올리기 — 머리 「↘ 숨기기」(올리는 중만) · 알약 「↖ 자세히」 · 같은 모양 같은 강조색 (HQ [발주] 09-15 급 6) */
/* 2.111.0 · 창이 낮아도(끌어 내렸거나 화면이 작다) 안이 잘리지 않는다 — 표는 제 안에서, 나머지는 창 안에서 구른다 (급 7) */
.movie-pop { overflow-y: auto; }
.movie-pop .folder-list { min-height: 8rem; }
.movie-head { display: flex; align-items: center; gap: .6rem; }
.movie-head h4 { flex: 1; margin: 0; }
button.movie-fold {
  display: inline-flex; align-items: center; gap: .35rem; flex: none;
  padding: .32rem .75rem; border-radius: 8px; font-size: .92rem; font-weight: 600;
  background: var(--accent); color: var(--on-accent); border: 1px solid var(--accent);
}
button.movie-fold:hover { filter: brightness(1.08); }
.movie-fold-arrow { font-size: 1.15rem; line-height: 1; }
.upbar-head button.movie-fold { padding: .18rem .55rem; font-size: .85rem; }
.movie-step-src { white-space: nowrap; }
/* 2.118.0 · 머리(숨기기·제목)는 한 번 짓고 몸통만 다시 그린다 — 몸통 상자는 없는 셈(자식이 창의 줄로 선다) (HQ [발주] 09-16 ③) */
.movie-body { display: contents; }
.movie-body > * { flex: none; }
button.movie-fold[hidden], .upbar [hidden] { display: none !important; }
/* 2.118.0 · 올리기를 누른 뒤·태스크 창의 단계 칸은 글자만 (②⑨) */
.movie-step-text { white-space: nowrap; }

/* 걸러 보기 줄 (내 작업 · 아티스트) */
.filters { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .2rem 0 .6rem; }
.filters .seg-switch { flex-wrap: wrap; }

/* 뜬 판의 머리 = 끄는 손잡이 */
.seg-pop h4.drag-handle { cursor: move; user-select: none; }
.seg-pop h4.drag-handle::before {
  content: "⠿"; color: var(--muted); margin-right: .35rem; font-size: .9em;
}

/* 태스크 일정 칸 (041) — 좁게 두어 표가 안 늘어나게 */
.sched-num { width: 4.6rem; }
.sched-day { width: 8.6rem; }
.task-fields .sched-num, .task-fields .sched-day { font-size: .85rem; padding: .15rem .3rem; }
.task-fields { max-width: none; }

/* ⭐ 날짜 칸 (링고 2026-09-06 「숫자로 친다」) — `type="date"` 를 걷고 글자 칸으로 받는다.
   ⚠ 브라우저가 주던 칸은 제 너비를 스스로 정했다. 글자 칸은 안 그러므로 **여기서 정한다** —
     안 정하면 표 안에서 칸이 제각각 넓어진다.
   ⭐ `tabular-nums` — 숫자 폭이 같아야 `2026-12-13` 이 세로로 줄이 맞는다(표에서 이게 크다). */
.day-cell { font-variant-numeric: tabular-nums; letter-spacing: .01em; }
input.day-cell:not(.sched-day) { width: 8.6rem; }

/* ⭐ 달력 단추 (HQ [발주] 09-14 2시 ③) — 글자 칸 + 오른쪽 단추 + 숨은 브라우저 달력 칸.
   ⚠ 숨은 칸은 `display:none` 이면 크롬이 달력을 안 연다 — 투명 1px 로 단추 곁에 둔다.
   ⚠ 표 칸 안에서는 칸 폭을 넘지 않게 글자 칸이 줄어든다(`min-width:0`). */
.day-pick { display: inline-flex; align-items: center; gap: .15rem; position: relative;
  max-width: 100%; vertical-align: middle; }
.day-pick > input.day-cell { flex: 1 1 auto; min-width: 0; }
td > .day-pick { display: flex; width: 100%; }
td > .day-pick > input.sched-day { width: auto; }
.day-pick > .day-cal { flex: none; padding: .1rem .25rem; line-height: 1; }
.day-pick > .day-cal .ic { width: 15px; height: 15px; }
.day-pick > .day-picker { position: absolute; right: 0; bottom: 0; width: 1px; height: 1px;
  opacity: 0; border: 0; padding: 0; pointer-events: none; }
/* ⚠ 날짜 둘 + 달력 단추 둘이 한 줄이라 30rem 창에서는 끝 단추가 창 밖으로 잘렸다(캡처로 잡음) — 창을 넓힌다 */
.ask-card.title-add { width: min(37rem, calc(100vw - 2.4rem)); }
.title-add .day-pick > input.day-cell { width: 8.2rem; }
.title-add .bulk-line { flex-wrap: wrap; }

/* ⭐ 행사 영어 이름 (HQ [발주] 09-14 2시 ②) — 코드 옆 작은 글씨 · 비면 노란 표시 */
.ep-en { display: block; font-size: .75rem; color: var(--muted);
  font-family: ui-monospace, Consolas, monospace; line-height: 1.2; }
.ep-en.need-fill, button.link.ep-en.need-fill { color: var(--st-review); font-family: inherit; padding: 0; }
input.ep-en-input.need-fill { box-shadow: inset 0 0 0 2px var(--st-review); }
.ep-en-line { display: inline-flex; align-items: center; gap: .5rem; white-space: nowrap; }
.ep-en-line > input.ep-en-input { width: 17rem; }

/* 여럿 고르기 (리뷰어) */
.bulk-multi { min-width: 12rem; }

/* ── 목록 화면은 **한 줄이라도 더 보여 주는 것이 일이다** (링고 2026-08-24) ────────
   *"컷리스트, 에셋 리스트는 최대한 많이 보여주는 것이 중요하다. 불필요한 공간·메뉴는
   최소화하여 에셋이나 컷을 1개라도 더 많이 보여줘야 한다."*
   ⚠ 줄이는 것은 **여백과 자리**지 기능이 아니다 — 못 찾는 기능은 없는 기능이다(08-23). */
#tab-shots .panel-head, #tab-assets .panel-head { margin-bottom: .25rem; padding-bottom: .25rem; }
#tab-shots .filterbar, #tab-assets .filterbar {
  margin: .1rem 0 .35rem; padding: .3rem .45rem; row-gap: .3rem;
}
#tab-shots .filterbar label, #tab-assets .filterbar label { font-size: .82rem; }
#tab-shots .filterbar select, #tab-assets .filterbar select { padding: .12rem .3rem; }
.ghost.small { padding: .12rem .5rem; font-size: .82rem; }

/* 표 아래 오른쪽 — 페이지 이동 */
.listfoot {
  display: flex; align-items: center; gap: .45rem;
  padding: .35rem .2rem .1rem; font-size: .85rem;
}
.listfoot .spacer { flex: 1; }

/* ⭐⭐ **머리줄은 스크롤해도 고정이다** (링고 2026-08-24: *"필드 정보가 있는 열은 하단으로
   스크롤되어도 늘 고정인 정보여야 한다"*). 어느 열을 보고 있는지 모르면 표가 숫자 벽이 된다.
   ⚠ 두 줄짜리 머리(단계를 펼치면 작은 머리줄이 하나 더 붙는다)도 같이 붙어야 한다 —
     위 줄만 고정하면 아래 줄이 그 밑으로 파고들어 글자가 겹친다. */
/* ⭐⭐⭐ **머리 줄 + 요약 줄이 같이 붙는다** (HQ [발주] 09-14 0시 · 링고: *"퍼센티지가 있는 열까지는 고정"*).
   ⚠⚠ 여태 요약 줄(`tr.sum-head`)은 `top` 이 없어(auto) **붙지 않고 흘러 올라가** 머리 줄 밑으로 반쯤 파고들었고,
     작은 머리줄은 `2.05rem` 을 박아 머리 줄 키가 달라지면 겹쳤다. 줄마다의 `top` 은 이제 **그려진 키를 재서**
     `pinHeadRows`(app.js)가 줄에 `--pin-top` 으로 넣는다 — 줄 수·키가 바뀌어도 틈·겹침 0.
   ⚠ 머리 칸 층은 **6** — 몸통의 왼쪽 고정 칸(`td[data-col-key]` · 3)이 DOM 뒤라 같은 층이면 머리 위에 그려진다.
   ⚠ 표가 `border-collapse` 라 칸의 밑줄은 **붙지 않고 흘러간다** — 붙은 줄의 밑선은 아래 `::after` 가 긋는다. */
#shot-body table.shot-table thead th,
#asset-body table.shot-table thead th {
  position: sticky; z-index: 6; background: var(--bg); top: var(--pin-top, 0px);
}
/* ⚠⚠ **`border-collapse: collapse` 인 표에서는 붙은 머리 칸 아래 몇 px 에 몸통 글자가 비친다** (09-14 실측 · 3배 캡처).
   스크롤 800 에서 머리 줄 밑 160~165px 띠에 「CH713」 글자 아래쪽이 보였다 — 3px 더 내리면 사라지고(몸통 글자다),
   `separate` 로 바꾸면 그 자리에서 없어졌다. 칸 선은 오른쪽·아래 1px 뿐이라 `separate` + 간격 0 이면 모양이 같다. */
#shot-body table.shot-table,
#asset-body table.shot-table { border-collapse: separate; border-spacing: 0; }
#shot-body table.shot-table thead tr:last-child th::after,
#asset-body table.shot-table thead tr:last-child th::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--line); pointer-events: none;
}
/* ⛔ **묶음 줄은 안 붙인다** (되돌림 2026-08-24 — 링고: *"태스크 모두 확장시 2번째 이후
   태스크 정보는 아예 안 보임"*).
   ⚠⚠ 붙이면 **모든 묶음 줄이 같은 자리에 겹쳐 쌓인다** — 회차 열넷·시퀀스 스물넷이면
   그 띠들이 표 위쪽을 덮어 아래 줄이 통째로 안 보인다. «지금 어느 묶음인가» 를 보여
   주려던 것이 **데이터를 가리는 것**으로 돌아왔다.
   ⭐ 붙일 것은 **하나뿐**이어야 한다 — 머리줄. 그건 그대로 붙어 있다. */

/* ==========================================================================
   ⭐⭐⭐ 2.117.0 · **표 머리 고정 — 한 부품** (HQ [덧] 09-16 덧1 ⑤ · 링고 11시 20분:
   *"타이틀도 스크롤될 때 상단 필터와 필드까지는 락 걸려야 한다 · 에셋·컷리스트 외에도
   공통으로 · 불편하다."*)

   딱지 하나(`pinhead`)가 모든 표를 붙인다 — 타이틀 · 태스크 · 전체 일정 · 내 작업 · 인박스 ·
   리뷰 · 설정 안 표 · 상세 창 안 표. 부르는 손도 하나다(`app.js` 의 `pinHead`).

   ⚠ 붙는 자리 `top` 은 두 값의 합이다:
     `--pin-base`  이 표를 감싼 구르는 칸 안이면 0 · 창이 구르면 위 띠(+붙은 알약 줄) 키 (JS 가 잰다)
     `--pin-top`   머리 줄 차례대로 쌓인 키 (`pinHeadRows` 가 **그려진 키**로 잰다)
   ⚠ `border-collapse: collapse` 인 표는 붙은 칸 밑에 몸통 글자가 비친다(09-14 실측) —
     그래서 `separate` + 간격 0 이고, 칸 밑선은 `::after` 가 긋는다(컷리스트가 이미 그 꼴).
   ⛔ 여기 층(z-index)을 6 보다 올리지 마라 — 위 띠(`.topbar` 5)와 우클릭 메뉴(60) 사이 자리다.
   ========================================================================== */
table.pinhead { border-collapse: separate; border-spacing: 0; }
/* ⚠⚠ 이 줄보다 **무거운** `th { position: relative }` 가 있으면 `top` 이 「붙는 자리」가 아니라 **민 거리**가 된다 —
   머리 칸이 제 자리에서 그만큼 아래로 떠서 몸통 줄을 가린다(결과물 표에서 실측). 무게를 올려 이긴다. */
table.pinhead > thead > tr > th {
  position: sticky; z-index: 6; background: var(--bg);
  top: calc(var(--pin-base, 0px) + var(--pin-top, 0px));
}
table.pinhead thead tr:last-child th::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--line); pointer-events: none;
}
/* 판이 `--panel` 바탕 위에 앉은 표(설정 카드·상세 창)는 그 바탕으로 붙는다 — 비쳐 보이면 안 된다 */
.pipe-card table.pinhead thead th,
.deliv-card table.pinhead thead th,
.ask-card table.pinhead thead th { background: var(--panel); }

/* ⭐ 위 거름 알약 줄도 같이 붙는다 (덧1 ⑤ 「위 거름 알약 줄과 칸 머리 줄」).
   ⚠ 창이 통째로 구르는 판에서만 딱지가 붙는다(`pinBar`) — 구르는 칸이 있는 컷리스트·에셋은
     이 줄이 애초에 그 칸 밖이라 안 흘러간다. */
.pinbar {
  position: sticky; top: var(--topbar-h, 3.2rem); z-index: 7;
  background: var(--bg);
}

/* ⭐ 목록 화면의 **머리 두 줄을 한 줄 반으로** 줄인다 (링고 2026-08-24:
   *"불필요한 공간, 메뉴는 최소화하여 1개라도 더 많이 보여줘야 한다"*).
   ⚠ 기능은 그대로 둔다 — 08-23 에 «못 찾는 기능은 없는 기능이다» 로 밖에 꺼낸 것들이라
   다시 메뉴 안으로 밀어 넣지 않는다. 줄이는 것은 **여백과 글자 크기**다. */
.panel-head.tight { margin: 0 0 .2rem; padding: 0 0 .2rem; align-items: center; }
.panel-head.tight h2 { font-size: 1rem; margin: 0; }
.panel-head.tight .panel-actions button { padding: .12rem .5rem; font-size: .82rem; }

/* ==========================================================================
   ⭐⭐ 2.117.0 · **머리글은 표보다 안쪽으로 들어간다** (HQ [덧] 09-16 덧1 ① · 링고 사진:
   *"「타이틀」 글자를 좀 더 옆으로(안쪽으로) 들여서 사이드 섹션 느낌을 살려라."*)

   한 자로 셋을 다 잡는다 — 머리글 줄 · 유형 탭 줄 · 알약 줄. **컷리스트·에셋도 같은 자**다
   (발주 ① 「다른 페이지 머리글도 같은 자로」). 바뀌는 것은 **여백·글자 한 단 · 가르는 선 하나**이고,
   표는 그대로 왼쪽 끝에서 시작한다 — 그래서 머리글이 표 위에 얹힌 「사이드 섹션」처럼 읽힌다.
   ⚠ 값을 늘리려면 `--head-indent` 한 칸이다(줄마다 padding 을 적지 마라 — 셋이 갈린다).
   ========================================================================== */
.panel { --head-indent: 1.15rem; }
.panel > .panel-head,
.panel > .list-tabs,
.panel > .kindbar { padding-left: var(--head-indent); }
.panel > .panel-head.tight h2 {
  font-size: .92rem; letter-spacing: .04em; color: var(--muted); font-weight: 600;
}
/* 표와 **선 하나로** 가른다 — 머리 덩이가 어디서 끝나는지 눈이 한 번에 잡는다 */
.panel > .list-tabs, .panel > .kindbar { padding-bottom: .25rem; border-bottom: 1px solid var(--line); }
#tab-shots .filterbar, #tab-assets .filterbar {
  column-gap: .5rem; row-gap: .2rem; align-items: center;
}
#tab-shots .filterbar > label, #tab-assets .filterbar > label {
  display: inline-flex; align-items: center; gap: .25rem; margin: 0;
}
#tab-shots .filterbar button, #tab-assets .filterbar button {
  padding: .12rem .5rem; font-size: .82rem;
}
#tab-shots .filterbar .seg-switch button, #tab-assets .filterbar .seg-switch button {
  padding: .1rem .45rem; font-size: .8rem;
}

/* 머리줄로 올라온 찾기 칸 */
.head-search { width: 15rem; max-width: 34vw; padding: .12rem .45rem; font-size: .82rem; }

/* 줄 고르기 칸 — 표가 창 끝에 바짝 붙지 않게 하는 여백이기도 하다 */
/* ⚠ 표가 창 끝에 바짝 붙으면 «갇혀 보인다» (링고 2026-08-24, 두 번 말했다).
   고르기 칸이 그 숨통을 겸한다 — 왼쪽을 넉넉히 준다. */
td.pickcell { text-align: center; padding-left: .75rem; padding-right: .3rem; }
#shot-body table.shot-table th:first-child,
#asset-body table.shot-table th:first-child { padding-left: .75rem; }
#shot-body, #asset-body { padding-left: .15rem; }
.pickbox { cursor: pointer; }

/* 문서 버전 — PDF 는 그 자리에서 펼치고, 글은 우리 마크다운으로 그린다 */
.player.pdf { width: 100%; height: min(70vh, 900px); border: 1px solid var(--line); border-radius: 10px; background: #fff; }
.player-doc { max-height: min(70vh, 900px); overflow: auto; }
.bible-files { margin-top: 1rem; }
.bible-files .viewer:empty { display: none; }

/* ⚠ 「내 작업」 표도 화면 끝까지 늘어났다 (링고 2026-08-24: *"내 작업도 필드가 너무
   와이드함"*). 아티스트 표에 쓴 것과 **같은 자**를 쓴다 — 내용만큼만 넓힌다.
   ⭐ 코드 한 자리를 보려고 눈이 화면을 가로지르지 않게. */
#mytasks-body table { width: auto; min-width: min(100%, 46rem); max-width: 100%; }
#mytasks-body table th, #mytasks-body table td { padding-right: 1.1rem; }
#mytasks-body table td:last-child, #mytasks-body table th:last-child { padding-right: .4rem; }

/* 여러 조건으로 거르기 + 저장한 것 (044) */
.conds { display: inline-flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.cond-row { display: inline-flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.cond-row select { padding: .12rem .3rem; font-size: .82rem; }
.cond-row .sub { font-size: .76rem; }

/* 거르개 바의 칩 — [라벨][값 고르개](×)
   (발주 SPEC_web_공통보기엔진_v1 §2 「거르개 바」 · 컷·에셋·간트가 같은 것을 쓴다)
   ⚠ 값 고르개를 칩 **안**에 둔다 — 눌러서 판을 여는 방식이면 한 손짓이 둘이 된다.
   ⚠ 값이 걸린 칩만 진하다: 걸린 조건이 몇인지 **한눈에** 세어져야 «왜 안 나오지» 가 준다. */
.cond-row .cond-chip {
  display: inline-flex; align-items: center; gap: .25rem;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .05rem .2rem .05rem .55rem; font-weight: 500; color: var(--muted);
  background: var(--panel);
}
.cond-row .cond-chip.on { color: var(--fg); border-color: var(--accent); }
.cond-row .cond-chip .chip-key { font-size: .78rem; white-space: nowrap; }
.cond-row .cond-chip .chip-val {
  border: 0; background: transparent; color: inherit; font-size: .82rem; max-width: 12rem;
}
.cond-row .cond-chip input.chip-val { width: 7.5rem; }
.cond-row .cond-chip .x {
  border: 0; background: transparent; color: var(--muted); cursor: pointer;
  font-size: .9rem; line-height: 1; padding: 0 .2rem;
}
.cond-row .cond-chip .x:hover { color: var(--st-retake, var(--fg)); }
.cond-row .add-cond { font-size: .8rem; padding: .1rem .5rem; }

/* 방금 바꾼 것 — 되돌리기 띠 (링고 2026-08-24) */
.undo-bar {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 1rem; z-index: 80;
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  max-width: min(92vw, 60rem);
  padding: .5rem .8rem; border-radius: 10px;
  background: var(--panel); border: 1px solid color-mix(in srgb, var(--fg) 22%, var(--line));
  box-shadow: 0 14px 40px rgba(0,0,0,.5); font-size: .85rem;
}
.undo-bar .undo-item { display: inline-flex; align-items: center; gap: .35rem; color: var(--muted); }
.undo-bar .undo-item span { max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ⭐ 거르개 아이콘 (링고 2026-08-26). ⚠ 색을 박지 않는다 — `currentColor` 라
   라이트/다크를 갈 때 글자와 함께 저절로 반전한다. 여기서 색을 주면 그 자동이 죽는다. */
.ico-filter { width: 1.05rem; height: 1.05rem; flex: none; vertical-align: -.18em; }
button.icon-only {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .18rem .4rem; line-height: 1;
}
.cond-row .saved-pick { max-width: 9rem; }

/* 머리줄로 올라온 거르개 */
.head-filters { display: inline-flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.head-filters label { display: inline-flex; align-items: center; gap: .2rem; font-size: .8rem; margin: 0; }
.head-filters select { padding: .1rem .3rem; font-size: .8rem; max-width: 8.5rem; }
.head-filters button { padding: .1rem .45rem; font-size: .8rem; }

/* ==========================================================================
   등장연결 (045) — 컷 상세의 «등장», 에셋 상세의 «나오는 컷»
   ⚠ 상세 화면 안에만 산다. 목록 표의 칸에는 아무것도 안 건다 (§9-34·35).
   ========================================================================== */
.appears { margin: .6rem 0 .2rem; }
.appears-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .35rem; }
.appears-body { display: flex; gap: .35rem; flex-wrap: wrap; align-items: center; }
.appears-chip { padding-left: .3rem; }
.appears-chip .name {
  border: 0; background: none; padding: 0; font: inherit; color: var(--fg);
  cursor: pointer; text-align: left;
}
.appears-chip .name:hover { color: var(--accent); text-decoration: underline; }
.appears-chip .kindtag { margin-left: .15rem; }
.appears-thumb {
  width: 1.5rem; height: 1.5rem; object-fit: cover; border-radius: 50%;
  border: 1px solid var(--line);
}
.appears-add-box { margin-top: .4rem; }
input.appears-add { width: 12rem; border-color: var(--line); border-style: dashed; }

/* --- 리플 CC (052) — 남기는 칸 바로 아래 한 줄 --- */
.cc-row { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; margin-top: .35rem; }
.cc-chips { display: inline-flex; gap: .3rem; flex-wrap: wrap; }
.cc-chip {
  display: inline-flex; align-items: center; gap: .1rem;
  border: 1px solid var(--line); border-radius: 999px;
  padding: .05rem .2rem .05rem .5rem; font-size: .8rem;
}
.cc-chip .chip-x {
  border: 0; background: none; padding: 0 .25rem; font: inherit;
  color: var(--muted); cursor: pointer; line-height: 1;
}
.cc-chip .chip-x:hover { color: var(--fg); }
input.cc-add { width: 8rem; border-color: var(--line); border-style: dashed; font-size: .85rem; }
/* 남은 리플에 붙는 «CC 아무개» — 읽는 줄이라 조용하게 */
.cc-on { font-size: .78rem; color: var(--accent); margin-left: .35rem; }

/* 펼친 단계 칸에서 태스크 이름을 누르면 그 태스크가 열린다 (링고 2026-08-25 ③④) */
td.taskcell.open .tc-name.clickable { cursor: pointer; }
td.taskcell.open .tc-name.clickable:hover { color: var(--fg); text-decoration: underline; }
/* 2.106.0 · md 문서가 있는 태스크 이름 — 점선 밑줄 한 줄로 «얹으면 뭔가 있다» 를 말한다 */
td.taskcell.open .tc-name.has-doc { text-decoration: underline dotted; text-underline-offset: 3px; }
.syn-float.doc-float .doc-meta { font-size: .76rem; }
td.taskcell.open { cursor: pointer; }

/* 갤러리에서 고른 카드 (링고 2026-08-25 ① — 여러 장 고르기).
   ⚠ 「지금 보는 것」(.current)과 「고른 것」(.picked)은 다른 말이다 —
     보는 것은 하나, 고른 것은 여럿이다. 그래서 표시도 다르게 한다. */
.gcell.picked { outline: 3px solid var(--accent); outline-offset: -3px; }
.gcell.picked figcaption { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.gcell { cursor: pointer; user-select: none; }
/* 썸네일 표시 — 단추가 아니라 **표시**다 (누르는 자리는 우클릭 메뉴) */
.gcell .gpin { font-size: .72rem; color: var(--muted); margin-left: .3rem; }

/* 처음 온 사람에게만 뜨는 손짓 안내 (링고 2026-08-25 ⑦).
   ⚠ 화면을 덮지 않는다. 목록 위에 한 줄로 눕고, «안 볼래요» 로 스스로 사라진다. */
.tipbar {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  margin: 0 0 .5rem; padding: .4rem .7rem; border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
  font-size: .86rem;
}
.tipbar .tipmark { font-weight: 700; color: var(--accent); white-space: nowrap; }
.tipbar .tiptext { color: var(--fg); min-width: 0; }
.tipbar button { margin-left: auto; }

/* ==========================================================================
   내용 = 시나리오 (링고 2026-08-25 ⑨)
   얹으면 미리보기 하나 · 누르면 뜬 창 여럿 · Shift+닫기로 전부 닫기
   ========================================================================== */
.syn-peek, .syn-float {
  position: fixed; background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,.4);
}
/* ⭐ 폭을 반으로 (링고 2026-08-26: *"내용의 글이 너무 와이드하게 보인다. 반정도 폭을
   줄이고 밑으로 정사각형처럼 보이면 훨씬 가독성이 좋아보이겠다"*).
   46rem → 23rem. **줄 수를 줄이는 것이 아니라 줄을 짧게 하는 것**이라, 같은 글이
   아래로 길어지면서 저절로 네모에 가까워진다. 눈이 줄 끝에서 다음 줄 머리를 찾는
   거리가 짧아지는 것이 가독성의 실제 이유다. */
.syn-peek { z-index: 70; max-width: min(23rem, 70vw); pointer-events: none; padding: .6rem .8rem; }
.syn-peek-head { display: flex; gap: .5rem; align-items: baseline; margin-bottom: .3rem; }
.syn-peek-head .muted { font-size: .76rem; }
/* ⭐ 크기를 손으로 조절한다 (링고 2026-08-26: *"우측 하단에 집기 표시의 포인트가 있어서
   늘렸다 줄였다 크기 조절도 가능하게 하자"*).
   ⚠ 끌기 코드를 새로 안 짓는다 — `resize: both` 가 **브라우저가 그려 주는 집기**를 우측
   하단에 낸다. 머리줄 끌기(`dragFloat`)와 안 싸운다: 그쪽은 머리에만 걸려 있다.
   ⚠ `resize` 는 `overflow: visible` 이면 안 먹는다 — 그래서 겉옷은 `hidden`,
      글 칸(`.syn-body`)이 넘치는 것을 맡는다.
   ⚠ 키우는 것을 `max-height` 가 막지 않게 70vh -> 92vh. **처음 높이는 그대로**다 —
      여는 자리(`openScenarioFloat`)에서 70vh 로 재서 앉힌다. */
.syn-float {
  width: min(34rem, 84vw); max-height: 92vh;
  min-width: 15rem; min-height: 7rem; max-width: 96vw;
  display: flex; flex-direction: column;
  resize: both; overflow: hidden;
}
/* 집기가 어두운 바탕에서 잘 안 보인다 — 자리를 눈에 보이게 짚어 준다.
   ⚠ `pointer-events: none` — 진짜 집기는 브라우저 것이라 이것이 가리면 안 된다. */
.syn-float::after {
  content: ""; position: absolute; right: 2px; bottom: 2px;
  width: .8rem; height: .8rem; pointer-events: none; opacity: .55;
  background:
    linear-gradient(135deg, transparent 46%, var(--muted) 46%, var(--muted) 56%, transparent 56%),
    linear-gradient(135deg, transparent 72%, var(--muted) 72%, var(--muted) 82%, transparent 82%);
}
.syn-float-head {
  display: flex; align-items: center; gap: .4rem; padding: .45rem .6rem;
  border-bottom: 1px solid var(--line); cursor: move; user-select: none;
}
.syn-float-head .spacer { flex: 1; }
.syn-float .syn-body { overflow: auto; }
.syn-body { padding: .5rem .7rem; font-size: .9rem; line-height: 1.55; max-height: 60vh; overflow: auto; }
.syn-body h4, .syn-body h5, .syn-body h6 { margin: .5rem 0 .3rem; }
.syn-body p { margin: .35rem 0; }
.syn-body ul { margin: .3rem 0 .3rem 1.1rem; }
.syn-body blockquote {
  margin: .35rem 0; padding-left: .6rem; color: var(--muted);
  border-left: 3px solid var(--line);
}
.syn-body pre {
  background: color-mix(in srgb, var(--fg) 8%, transparent); padding: .5rem;
  border-radius: 6px; overflow: auto; font-size: .84rem;
}
.syn-body code { font-family: ui-monospace, Consolas, monospace; font-size: .86rem; }
.syn-edit { width: 100%; min-height: 12rem; font: inherit; }
.syn-foot { display: flex; gap: .4rem; justify-content: flex-end; padding: .5rem .7rem; border-top: 1px solid var(--line); }
/* 카드에서는 석 줄까지만 — 카드는 훑는 자리다 */
.syn-peek-src.card {
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden; cursor: zoom-in;
}
td.syn-cell { cursor: zoom-in; }

/* ⭐ 「줄바꿈해서 보기」 (링고 2026-08-26) — 표 안에서 글을 다 읽는 길.
   ⚠ 뜬 창을 대신하는 것이 아니라 **길을 하나 더 여는 것**이다: 훑을 때는 한 줄이 낫고
     읽을 때는 줄바꿈이 낫다. 머리줄 우클릭에서 고른다. */
td.syn-cell.wrapped { vertical-align: top; cursor: auto; }
td.syn-cell.wrapped .desc {
  white-space: pre-wrap; word-break: break-word; line-height: 1.45;
}
textarea.cell.wraptext {
  width: 100%; resize: none; overflow: hidden; min-height: 1.6em;
  white-space: pre-wrap; word-break: break-word; line-height: 1.45;
  font: inherit;
}

/* 커스텀 필드 (046) — 목록의 칸과 설정의 표 */
td.cf-cell input.cell, td.cf-cell select.cell { width: 100%; }
table.cf-table td { vertical-align: middle; }
table.cf-table tr.cf-new td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
table.cf-table input.cell, table.cf-table select.cell { width: 100%; min-width: 6rem; }

/* 상세 화면의 배치 저장 줄 (047 · 링고 2026-08-25 ⑥) */
.viewbar {
  display: flex; align-items: center; gap: .4rem; margin: .2rem 0 .35rem;
  font-size: .82rem;
}
.viewbar .spacer { flex: 1; }
.viewbar .muted { font-size: .8rem; }
/* 상세 표도 목록과 같은 방식으로 폭을 잡는다 */
table.task-fields { table-layout: fixed; }
table.task-fields th { position: relative; }

/* 조건 줄이 머리줄로 올라왔다 (링고 2026-08-25 ①) — 좁아지면 줄을 바꾼다.
   ⚠ 머리줄은 이제 필터·조건·찾기·단추가 다 모이는 자리다. 안 접히게 두면
     좁은 화면에서 단추가 화면 밖으로 나간다(§9-32 가 적어 둔 그 병). */
.panel-actions { flex-wrap: wrap; align-items: center; row-gap: .25rem; }
.panel-actions .conds .cond-row select { max-width: 8.5rem; }
.panel-actions .conds { font-size: .82rem; }
button.layout-btn { font-size: .95rem; line-height: 1; }

/* ==========================================================================
   내 작업 (링고 2026-08-25) — 칩의 글자·숫자 줄 맞추기 · 썸네일 · 표
   ========================================================================== */
/* ⚠ 이름과 숫자를 한 글자 뭉치로 두면 길이가 제각각이라 눈이 기준선을 못 잡는다.
   ⭐ 이름은 왼쪽, 숫자는 오른쪽에 자릿수 고정 글꼴로 — 숫자가 세로로 줄을 선다. */
.seg-switch.count-seg button {
  display: inline-flex; align-items: baseline; gap: .45rem;
  justify-content: space-between; white-space: nowrap;
  min-width: 5.6rem; padding: .3rem .7rem;
}
.seg-switch.count-seg .lab { color: inherit; }
.seg-switch.count-seg .num {
  font-variant-numeric: tabular-nums; font-weight: 700;
  min-width: 2.2ch; text-align: right;
}
.seg-switch.count-seg button:not(.on) .num { color: var(--muted); }

img.mythumb, span.mythumb {
  display: block; width: 48px; height: 27px; object-fit: cover;
  border-radius: 4px; border: 1px solid var(--line); cursor: pointer;
}
span.mythumb.none { background: color-mix(in srgb, var(--fg) 6%, transparent); cursor: default; }
table.mytask-table { table-layout: fixed; }
table.mytask-table th { position: relative; }
/* 「필드 보기」 판이 단추 옆에서 펼쳐지도록 자리를 잡아 준다 */
.colmenu-wrap { position: relative; display: inline-flex; }

/* ==========================================================================
   좁은 화면 — 탭을 ☰ 뒤로 (링고 2026-08-25: *"모바일시에는 일부 메뉴를 햄버거 메뉴에"*)
   ⚠ 기능을 지우는 것이 아니라 **접는다.** ☰ 판에 «여기로 가기» 가 있어서 접힌 탭으로
     갈 길이 남는다 (§20-6 이 세운 자).
   ========================================================================== */
.nav-burger { display: none; }
@media (max-width: 820px) {
  .nav-burger {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .3rem .6rem; font-size: .9rem; white-space: nowrap;
  }
  header.topbar .tabs { display: none; }
  header.topbar { gap: .4rem; padding: .4rem .6rem; flex-wrap: wrap; }
  header.topbar .right .build { display: none; }      /* 판 번호는 설정 > 정보에도 있다 */
  header.topbar #who { max-width: 7rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #project-switch { max-width: 9.5rem; }
  /* 목록 머리줄 — 폰에서는 두세 줄로 접히게 두고 글자를 줄인다 */
  .panel-actions { gap: .3rem; }
  .panel-head.tight .panel-actions button { padding: .1rem .4rem; font-size: .78rem; }
  .panel-actions .conds { font-size: .78rem; }
  .head-filters select, .panel-actions select { max-width: 6.5rem; font-size: .78rem; }
  .head-search { max-width: 9rem; }
  /* 뜬 창·미리보기는 화면을 넘지 않는다 */
  .syn-float { width: min(94vw, 34rem); }
  .syn-peek { max-width: 92vw; }
}

/* 폰에서는 거르는 칸을 「필터 ▾」 뒤로 접는다 (링고 2026-08-25) */
.filter-burger { display: none; }
@media (max-width: 820px) {
  .filter-burger { display: inline-flex; }
  .panel-actions > .head-filters,
  .panel-actions > .conds { display: none; }
  .panel-actions.show-filters > .head-filters,
  .panel-actions.show-filters > .conds { display: inline-flex; }
}

/* 「필드 보기」 판 — 화면 좌표에 띄운다 (링고 2026-08-25: 판이 잘려 안 보였다).
   ⚠ 머리줄이 넘침을 물고 있어서 그 안에 앉히면 잘린다. 그래서 fixed 다. */
.colmenu-wrap > .col-menu {
  position: fixed; z-index: 90; max-height: 70vh; overflow: auto;
  min-width: 12rem;
}
/* 묶음 띠 — 표를 가로지른다 (내 작업의 상태 묶음) */
tr.group-row.statusband td {
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  padding: .3rem .6rem; border-top: 2px solid var(--line);
}
/* ⚠ 크기는 **열 폭이 정한다**(`epThumbSized`) — 여기 값은 폭을 안 정한 판의 기본이다.
   ⚠ `contain` 이라 세로 그림도 안 잘린다(손맛 다섯 ②). */
img.epthumb, span.epthumb {
  display: block; width: var(--thumb-w, 56px); height: var(--thumb-h, 32px); object-fit: contain;
  background: var(--line);
  border-radius: 4px; border: 1px solid var(--line); cursor: pointer;
}
span.epthumb.none { background: color-mix(in srgb, var(--fg) 6%, transparent); cursor: default; }
.epbar { display: inline-block; width: 70px; height: 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 12%, transparent); overflow: hidden; vertical-align: middle; }
.epbar .fill { height: 100%; background: var(--st-done, var(--accent)); }

/* 원본 위치 (050) — 말해 주는 자리. ⚠ 링크처럼 보이면 안 된다 */
.origin-paths { display: flex; flex-direction: column; gap: .25rem; margin: .3rem 0 .5rem; }
.origin-row { display: flex; align-items: center; gap: .5rem; font-size: .84rem; }
code.origin-path {
  font-family: ui-monospace, Consolas, monospace; font-size: .82rem;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  padding: .1rem .4rem; border-radius: 4px; overflow-x: auto; white-space: nowrap;
}

/* ==========================================================================
   간트 (051 · 설계서 §3) — **그리개는 한 벌이다**
   ⚠ 캔버스를 안 쓴다: 테마(밝게·어둡게)와 글자 크기를 그대로 따라야 한다.
   ========================================================================== */
/* ⭐⭐ **스케줄 판은 바탕과 잉크를 한 쌍으로 갖는다** (링고 2026-09-02).
   ⚠⚠ 바탕만 밝히면 **선이 사라진다** — 선·글자가 전부 `--fg`(어둡게에서는 흰색)라
     밝은 바탕 위에서 흰 선이 된다. 그래서 이 판 안에서는 `--g-paper` 위에 `--g-ink`
     로만 그린다. 판을 다시 칠할 일이 생기면 **이 두 줄만** 만지면 된다.
   ⭐ 세 번 만에 자리를 잡았다(링고가 그림으로 보내 준 값이 이것이다):
       ① 거의 흰색(#f4f6fa) → *"눈이 아프다"*
       ② 한 단 낮춘 흰색(#e7ebf2) → 여전히 «어두운 앱 속의 흰 판»
       ③ **어두운 회색 판 + 밝은 잉크** ← 지금. 앱 바탕(#0B0B0F)보다 확실히 밝아서
          날짜 간격은 보이고, 흰 판처럼 눈을 찌르지 않는다.
   ⚠ 밝게 테마에서는 **쌍이 뒤집힌다**(아래 두 규칙) — 흰 화면에 어두운 판을 놓으면
     같은 병이 반대로 난다. */
.gantt {
  --g-paper: #35373b;
  --g-ink: #e6e8ee;
  --g-sat: #8ab4ff;              /* 토 — 어두운 판에서 읽히는 파랑 */
  --g-sun: #ff9a9a;              /* 일 — 같은 자의 빨강 */
  position: relative; margin: .4rem 0 .8rem;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .gantt {
    --g-paper: #e7ebf2; --g-ink: #101828; --g-sat: #1d4ed8; --g-sun: #b91c1c;
  }
}
:root[data-theme="light"] .gantt {
  --g-paper: #e7ebf2; --g-ink: #101828; --g-sat: #1d4ed8; --g-sun: #b91c1c;
}
.gstage, .gantt .gbody { background: var(--g-paper); }
/* 머리줄(달 띠·눈금)은 판보다 **한 겹 짙게** — 링고가 보낸 그림의 그 줄이다.
   ⚠ 여기는 `position: sticky` 라 **불투명해야** 한다(비치면 막대가 글자 뒤로 지나간다). */
.gaxis, .gaxis .gname.gaxis-sp { background: color-mix(in srgb, var(--g-paper) 88%, #000); }
.gantt .gname { color: var(--g-ink); }
.gantt-grid { position: absolute; inset: 0; pointer-events: none; }
/* ⭐⭐ **판이 밝아야 날짜가 보인다** (링고 2026-09-02: *"현재 너무 어두워서 잘 안 보임.
   날짜별 간격이 많이 잘 보일 정도로 밝아야 함"*).
   ⚠ 09-01 에 «눈금은 읽힐 만큼만 진하게» 로 한 단계만 올렸던 자리다 — 그 한 단계로는
     모자랐다. **세 단이 서로 갈리게** 다시 잡는다:
       하루 12% · 주(월요일) 30% · 달 60%   (여태: 없음 · 14% · 30%)
   ⚠ 막대는 **제 색을 가진 통짜**라 이 회색들보다 여전히 세다 — 눈금이 일정을 덮지 않는다. */
.gantt-grid .gline {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: color-mix(in srgb, var(--g-ink) 28%, transparent);
}
/* 하루 선 — 확대했을 때만 선다. 제일 옅다(날짜를 «세는» 데만 쓴다). */
.gantt-grid .gline.day { background: color-mix(in srgb, var(--g-ink) 13%, transparent); }
/* 달이 바뀌는 선은 **한눈에 갈려야** 한다 — 이 선이 판을 읽는 자다. */
.gantt-grid .gline.month { background: color-mix(in srgb, var(--g-ink) 58%, transparent); }
.gantt-grid .gline.today { background: var(--accent); width: 2px; opacity: 1; }
/* ⭐ 2.127.0 · **토·일 바탕 · 주 경계** (HQ [덧] 09-17 ③ · 링고 「주말 표시가 진하게 되야 한 주 느낌」) —
   토·일 이틀 한 덩이(`.gwk`)를 판 잉크 16% 로 · 일요일 뒤(월요일) 선은 주 선 한 단 위(44% · 2px).
   ⚠ 두 간트(전체 일정·타이틀 간트 = `.gwk` · 태스크 간트 = `.g-wk`)가 같은 값 · 인쇄에서도 바탕이 남는다. */
.gantt .gwk, .g-wk {
  position: absolute; top: 0; bottom: 0; pointer-events: none;
  background: color-mix(in srgb, var(--g-ink, var(--fg)) 16%, transparent);
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.gaxis-track .gwk { z-index: 0; }
.gaxis-track .gmonths, .gaxis-track .gticks { position: relative; z-index: 1; }
.gantt-grid .gline.week { width: 2px; background: color-mix(in srgb, var(--g-ink) 44%, transparent);
  -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.gantt-grid .gline.week.month { background: color-mix(in srgb, var(--g-ink) 62%, transparent); }
.gantt-grid .glabel {
  position: absolute; top: -1.1rem; left: .2rem; font-size: .7rem; color: var(--muted);
  white-space: nowrap;
}
/* 줄 사이 실선 — 종이 위에서는 이것이 «칸» 을 만든다 */
.gantt .gbody { position: relative; }
.gantt-row { display: flex; align-items: center; gap: .5rem; height: 26px; }
.gantt-row + .gantt-row { border-top: 1px solid color-mix(in srgb, var(--g-ink) 11%, transparent); }
.gantt-row.clickable { cursor: pointer; }
.gantt-row.clickable:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* ⭐ 글자는 **줄일 때만** 줄어든다 (링고 09-04: *"확대는 안 되며"*).
   `--g-font` 는 1 을 넘지 않는다 — 넓은 두 단에서는 1 이라 지금 크기 그대로다. */
.gantt .gname {
  width: 11rem; flex: none; overflow: hidden;
  font-size: calc(.84rem * var(--g-font, 1));
  text-overflow: ellipsis; white-space: nowrap;
}
.gantt .gtrack { position: relative; flex: 1; height: 100%; min-width: 0; }
/* ⭐ 막대 굵기는 **줄 높이에서 나온다** (링고 09-04) — 예전엔 12px 로 박혀 있어서
   줄만 커지고 막대는 그대로였다. `--g-barh` 는 app.js 가 한 자리에서 푼다.
   ⚠ 「보통」(26px)에서 12px 이라 그때 보던 굵기와 같다 — 거기서부터 같이 움직인다. */
.gantt .gbar {
  position: absolute; height: var(--g-barh, 12px); border-radius: 999px;
  top: calc((var(--ov-rowh, 26px) - var(--g-barh, 12px)) / 2);
  background: color-mix(in srgb, var(--accent) 35%, transparent);
}
/* 실제 막대는 계획 막대보다 **얇고 조금 아래** — 둘이 겹쳐도 서로 안 가린다.
   ⚠ 그 «조금 아래» 도 굵기에서 뽑는다. 픽셀로 적으면 줄이 얇아질 때 밖으로 나간다. */
.gantt .gbar.actual {
  height: calc(var(--g-barh, 12px) * .67);
  top: calc((var(--ov-rowh, 26px) - var(--g-barh, 12px)) / 2
            + var(--g-barh, 12px) * .42);
  background: var(--st-done, var(--accent)); opacity: .9;
}
.gantt .gbar.actual.late { background: var(--st-retake); }
.gantt .gpoint {
  position: absolute; top: 2px; transform: translateX(-50%);
  color: var(--accent); font-size: calc(.9rem * var(--g-font, 1)); line-height: 1;
}

/* ⭐ **베이스 스케줄 바탕 띠** (설계서 §2 ① · 2026-08-26)
   ⚠ 아주 옅게. 이건 «어디쯤인가» 를 알려 주는 바탕이지 읽을 것이 아니다 —
     진해지면 일감 막대가 바탕에 묻힌다. */
.gantt .gband {
  position: absolute; top: 0; bottom: 0;
  background: color-mix(in srgb, var(--g-ink) 8%, transparent);
  border-radius: 4px;
}
/* 납품일 따위의 점 — 파선으로 세로로 그어 준다 */
.gantt .gline.mile {
  border-left: 1px dashed color-mix(in srgb, var(--accent) 70%, transparent);
}
.gantt .glabel.mile {
  color: var(--accent); font-size: .68rem; opacity: .85; white-space: nowrap;
}
/* 다음 납품일까지 며칠 — 간트 위 한 줄 */
.gantt-head { display: flex; gap: .5rem; align-items: center; margin-bottom: .3rem; }
.dday {
  font-size: .8rem; font-weight: 600; border: 1px solid currentColor;
  border-radius: 999px; padding: .05rem .5rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.dday.near { color: var(--st-retake); }
/* ⭐ 끌 수 있는 막대 (간트 2차 · 링고 2026-08-26)
   ⚠ **끄는 동안 글자가 잡히면 안 된다** — 끌기가 글자 선택으로 바뀌어 막대가 안 따라온다.
   ⚠ `touch-action: none` — 폰에서 이걸 안 주면 브라우저가 먼저 화면을 스크롤한다. */
.gantt .gbar.draggable, .gantt .gpoint.draggable {
  cursor: grab; user-select: none; touch-action: none;
}
.gantt .gbar.draggable:active, .gantt .gpoint.draggable:active { cursor: grabbing; }
/* 오른쪽 끝 = 길이 손잡이. 손이 닿는 자리를 눈에도 보여 준다 */
.gantt .gbar.draggable::after {
  content: ""; position: absolute; right: 0; top: 0; bottom: 0; width: 10px;
  border-radius: 0 999px 999px 0; cursor: ew-resize;
}
.gantt .gbar.draggable:hover::after { background: color-mix(in srgb, var(--fg) 35%, transparent); }
.gantt .gbar.draggable:hover { outline: 1px solid var(--accent); }
/* 끄는 동안 날짜를 손 위에 띄운다 — 놓고 나서야 알면 늦다 */
.gdrag-tag {
  position: fixed; z-index: 90; pointer-events: none;
  background: var(--panel); border: 1px solid var(--accent); border-radius: 6px;
  padding: .1rem .4rem; font-size: .78rem; white-space: nowrap;
  font-variant-numeric: tabular-nums; box-shadow: 0 4px 14px rgba(0,0,0,.35);
}

/* 「여기 사는 단계」 칸 (057) — 켜진 것만 진하다 */
.schedule-table td.stepcell { min-width: 13rem; }
.sched-steps { display: flex; flex-wrap: wrap; gap: .2rem; }
.sched-steps .st-chip { font-size: .74rem; padding: .02rem .35rem; opacity: .45; }
.sched-steps .st-chip.on { opacity: 1; }
.sched-steps .st-chip:disabled { cursor: default; }
/* 빈 시작일 옆의 제안 — 눈에 띄되 값처럼 보이지 않게 */
button.linkish.sug {
  font-size: .76rem; color: var(--accent); white-space: nowrap; margin-left: .2rem;
  font-variant-numeric: tabular-nums;
}

.schedule-table input.sched-color { width: 3rem; padding: 0; height: 1.5rem; }
.schedule-table td { vertical-align: middle; }

/* 프로젝트 얼굴 (051) — ⭐ 파일 자체가 16:9 로 잘려서 온다(링고 2026-08-25).
   그래서 화면에서도 **16:9 를 그대로 보여 준다** — 여기서 또 자르면 두 번 잘린다. */
img.pthumb { width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
             border-radius: 8px 8px 0 0; display: block; }
img.pthumb.small { width: 56px; aspect-ratio: 16 / 9; border-radius: 4px; border: 1px solid var(--line); }
.pthumb-box { display: inline-flex; align-items: center; gap: .35rem; }
/* 끌어다 놓는 중 — **놓아도 되는 자리라는 것이 보여야 한다.** 안 보이면 사람은 놓기 전에 멈춘다 */
.drop-here { outline: 2px dashed var(--accent); outline-offset: 2px;
             background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* ==========================================================================
   ===== GANTT =====  발주 SPEC_web_간트 v1 · M1
   ⭐ 되돌리기: 이 구획만 지우면 된다. 다른 화면은 여기 기대지 않는다.
   ========================================================================== */
.gantt-sep { margin-top: 1.6rem; border-top: 1px solid var(--line); padding-top: .9rem; }
.gantt-toolbar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.gantt-wrap { display: flex; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }

/* 왼쪽 이름 — 세로 스크롤은 오른쪽과 묶여 있다(app 쪽에서 잇는다)
   ⚠ M2 에서 넓어졌다: 이름 옆에 **시작일·예상일 칸**이 들어온다(발주 §3 «좌측 인라인 편집»). */
.gantt-left { flex: 0 0 342px; overflow: hidden auto; max-height: 60vh;
  border-right: 1px solid var(--line); background: var(--panel); }
.g-left-head { height: 44px; display: flex; align-items: flex-end; padding: 0 .6rem .3rem;
  font-size: .78rem; color: var(--muted); border-bottom: 1px solid var(--line); }
.g-left-row { height: 32px; display: flex; align-items: center; gap: .4rem;
  padding: 0 .6rem; font-size: .84rem; cursor: pointer; white-space: nowrap; overflow: hidden; }
.g-left-row:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }
.g-left-row.entity { font-weight: 600; }
.g-left-row.task { padding-left: 1.5rem; }
/* ⚠ 이름은 **줄어야 한다** — M2 에서 옆에 일정 칸이 들어왔다. `min-width:0` 이 없으면
   flex 가 글자 폭을 최소로 삼아서 칸이 줄 밖으로 밀려난다. */
.g-left-row .g-step { overflow: hidden; text-overflow: ellipsis; flex: 1 1 auto; min-width: 0; }
.g-left-row .dot { width: 7px; height: 7px; border-radius: 2px; flex: 0 0 auto; }
.g-chev { color: var(--muted); font-size: .8rem; }
.g-count { margin-left: auto; font-size: .75rem; }
.g-badge { margin-left: auto; font-size: .7rem; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 0 .35rem; }

/* 오른쪽 — 날짜 머리줄 + 막대 */
.gantt-right { flex: 1 1 auto; overflow: auto; max-height: 60vh; }
.gantt-head { position: sticky; top: 0; z-index: 2; background: var(--panel); }
/* ⚠⚠ **판의 머리줄은 쌓인다 — 나란히 서면 안 된다** (실측 2026-09-01).
   `.gantt-head` 라는 이름을 **둘이 나눠 쓴다**: 스케줄 화면의 D-day 띠(가로로 나열 · 위
   2413 줄의 flex 가 그것을 위한 것)와, 간트 판의 머리줄(달 띠 → 날짜 눈금 → 마일스톤이
   **위아래로** 쌓여야 한다). 같은 이름이라 flex 가 여기까지 와서, **달 띠와 날짜 눈금이
   좌우로 나란히** 섰다 — 그래서 날짜 눈금이 판 오른쪽 끝의 «다음 달들» 처럼 보였고,
   달 이름이 그 아래 칸과 **어긋난 채로** 08-30 부터 서 있었다(링고가 «달과 날짜가 보여야
   의미가 있다» 고 청해서 지은 그 줄이다 — 뜨긴 떴는데 자리가 틀렸다).
   ⭐ 판 안의 것만 되돌린다 — D-day 띠는 그대로 가로다. */
.gantt-right > .gantt-head { display: block; }
.g-months { display: flex; height: 22px; }
/* 달 이름도 같이 올린다 — 날짜만 밝히면 «며칠인지는 보이는데 무슨 달인지» 가 흐려진다 */
.g-month { font-size: .78rem; font-weight: 600; color: var(--fg); padding-left: .3rem;
  border-left: 1px solid var(--line); overflow: hidden; white-space: nowrap; }
.g-days { display: flex; height: 22px; border-bottom: 1px solid var(--line); }
.g-day { font-size: .66rem; color: var(--muted); text-align: center; line-height: 22px;
  box-sizing: border-box; overflow: hidden; }
/* ⭐ 2.127.0 · 토·일 칸 진하게(5% → 16% · 판의 `.g-wk` 와 같은 값) · 월요일 칸 왼쪽 = 주 경계 (HQ [덧] 09-17 ③) */
.g-day.off { background: color-mix(in srgb, var(--fg) 16%, transparent);
  -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.g-day.wk { border-left: 2px solid color-mix(in srgb, var(--fg) 44%, transparent); }
.g-wk-layer { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.g-wkline { position: absolute; top: 0; bottom: 0; width: 2px; pointer-events: none;
  background: color-mix(in srgb, var(--fg) 30%, transparent);
  -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.gantt-right.panning { cursor: grabbing; user-select: none; }
.g-day.today { color: var(--accent); font-weight: 700;
  background: color-mix(in srgb, var(--accent) 14%, transparent); }

.gantt-body { position: relative; }
.gantt-lane { position: relative; height: 32px; border-bottom: 1px solid
  color-mix(in srgb, var(--line) 60%, transparent); }
.gantt-lane.unplaced { background: repeating-linear-gradient(45deg,
  transparent 0 6px, color-mix(in srgb, var(--fg) 4%, transparent) 6px 12px); }

/* 막대 넷 — 계획 · 실적 · 묶음(rollup) · 지연 */
.g-bar { position: absolute; border-radius: 5px; box-sizing: border-box; }
.g-bar.plan { top: 5px; height: 15px; background: var(--sc, var(--accent));
  border: 1px solid color-mix(in srgb, var(--sc, var(--accent)) 70%, #000); }
.g-bar.actual { top: 22px; height: 5px; border-radius: 3px;
  background: color-mix(in srgb, var(--fg) 45%, transparent); }
.g-bar.rollup { top: 9px; height: 10px; border-radius: 3px;
  background: color-mix(in srgb, var(--fg) 22%, transparent);
  border: 1px solid color-mix(in srgb, var(--fg) 35%, transparent); }
.g-late { position: absolute; top: 11px; height: 3px;
  border-top: 2px dotted var(--st-retake, #d9534f); }

/* ---- M2 (편집) — 끌기 손잡이 · 고른 줄 · 왼쪽 칸 -------------------------
   ⚠ `touch-action:none` 이 있어야 손가락으로 끌 때 화면이 같이 밀리지 않는다
     (발주 §2: v1 은 터치 끌기를 안 만들되 이 한 줄은 둔다). */
.g-bar.plan.drag { cursor: grab; touch-action: none; }
.g-bar.plan.drag:hover { outline: 1px solid var(--accent); outline-offset: 1px; }
.g-bar.plan.dragging { cursor: grabbing; opacity: .9;
  outline: 1px solid var(--accent); outline-offset: 1px; }
/* 양 끝 6px — 발주 §3 이 정한 폭. 위아래로 조금 넘겨 잡기 쉽게 한다. */
.g-grip { position: absolute; top: -3px; bottom: -3px; width: 6px;
  cursor: ew-resize; touch-action: none; border-radius: 3px; }
.g-grip.l { left: -1px; }
.g-grip.r { right: -1px; }
.g-bar.plan.drag:hover .g-grip { background: color-mix(in srgb, #000 45%, transparent); }
/* ---- 빈 줄에서 끌어 만들기 (링고 2026-08-30) ----
   ⚠ **빈 줄이 곧 손잡이다.** 잡을 막대가 없으니 «여기를 끌 수 있다» 를 커서가 말해야 한다 —
     안 그러면 빗금 친 빈 칸은 그냥 «없음» 으로 읽힌다. */
.gantt-lane.makeable { cursor: crosshair; touch-action: none; }
.gantt-lane.makeable:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* 끄는 동안만 사는 허깨비 — 놓으면 진짜가 된다 */
.g-bar.making { opacity: .75; border-style: dashed; pointer-events: none; }

/* 끄는 동안의 날짜 쪽지 — **칸을 세어 맞히게 하지 않는다** */
.g-tip { position: absolute; top: 4px; z-index: 6; white-space: nowrap; pointer-events: none;
  font-size: .7rem; line-height: 16px; padding: 0 .35rem; border-radius: 4px;
  background: var(--fg); color: var(--panel); font-variant-numeric: tabular-nums; }
/* 고른 줄 — 자판 ←/→ 가 미는 그 줄이 어느 것인지 보여야 한다 */
.gantt-lane.sel { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.g-left-row.sel { background: color-mix(in srgb, var(--accent) 13%, transparent); }
/* 왼쪽 목록 안의 일정 칸 */
.g-left-row .g-in { height: 21px; font-size: .72rem; padding: 0 .2rem; margin-left: auto;
  border: 1px solid var(--line); border-radius: 4px; flex: 0 0 auto;
  background: var(--bg); color: var(--fg); font-variant-numeric: tabular-nums; }
.g-left-row .g-in + .g-in { margin-left: .2rem; }
.g-left-row .g-in.day { width: 108px; }
.g-left-row .g-in.num { width: 46px; text-align: right; }
.g-left-row .g-in:focus { outline: 1px solid var(--accent); }

/* ---- M3 (프로젝트 프리셋) — 약속한 창 · 실제로 걸린 자리 · 넘친 만큼 --------
   ⭐ 이 프리셋에서만 줄이 **두 층**이다: 위가 창(Target), 아래가 Rollup.
      그래서 lane 에 `.pr` 를 걸어 그 층에서만 자리를 바꾼다 — 「작업」 프리셋의
      막대 자리는 하나도 안 건드린다(한쪽을 고치다 다른 쪽이 어긋나는 것을 막는다).
   ⚠ 왼쪽이 넓어진다: 띠 줄에는 **날짜가 둘**(시작·끝)이라 342px 로는 밀려난다. */
.gantt-wrap.pr .gantt-left { flex: 0 0 420px; }
.g-left-row.band { font-weight: 600; }
.g-left-row.step { padding-left: 1.5rem; }
.g-left-row .g-in.day.sm { width: 100px; }
/* 넘친 줄은 **이름 쪽에서도** 표가 나야 한다 — 오른쪽 빗금은 스크롤 밖일 수 있다 */
.g-badge.over { color: var(--st-retake, #d9534f);
  border-color: color-mix(in srgb, var(--st-retake, #d9534f) 55%, transparent); }

/* 창(Target) — 띠 줄에서는 채워서, 단계 줄에서는 «물려받은 것» 이라 점선으로 */
.gantt-lane.pr .g-bar.target { top: 4px; height: 13px;
  background: color-mix(in srgb, var(--sc, var(--accent)) 80%, transparent);
  border: 1px solid color-mix(in srgb, var(--sc, var(--accent)) 60%, #000); }
.gantt-lane.pr .g-bar.target.ghost { background: transparent;
  border: 1px dashed color-mix(in srgb, var(--sc, var(--accent)) 60%, transparent); }
.g-bar.target.drag { cursor: grab; touch-action: none; }
.g-bar.target.drag:hover { outline: 1px solid var(--accent); outline-offset: 1px; }
.g-bar.target.dragging { cursor: grabbing; opacity: .9;
  outline: 1px solid var(--accent); outline-offset: 1px; }
.g-bar.target.drag:hover .g-grip { background: color-mix(in srgb, #000 45%, transparent); }

/* Rollup 은 창 **아래**에 깔린다 — 두 막대가 겹치면 어느 것이 약속인지 못 읽는다 */
.gantt-lane.pr .g-bar.rollup { top: 20px; height: 8px; }
.gantt-lane.pr .g-bar.rollup.over {
  border-color: color-mix(in srgb, var(--st-retake, #d9534f) 70%, transparent); }
/* ⭐ **넘친 만큼만** 빗금이다 (발주 §3 «초과분만 해칭»). 막대를 통째로 칠하면
     «넘쳤다» 는 알아도 «며칠» 을 못 읽는다 — 이 화면이 말해야 할 것이 그 며칠이다. */
.g-over { position: absolute; top: 20px; height: 8px; border-radius: 3px;
  background: repeating-linear-gradient(45deg,
    transparent 0 3px, color-mix(in srgb, var(--st-retake, #d9534f) 80%, transparent) 3px 6px);
  border: 1px solid color-mix(in srgb, var(--st-retake, #d9534f) 60%, transparent); }

/* ---- 보는 폭(②) · 겹쳐 보기(④) · 거르개 — 링고 2026-08-30 -----------------
   ⭐ 머리줄의 날짜는 **칸 안이 아니라 칸 위에** 앉는다. 칸 안에 넣으면 하루가 3px 인
      「1년」에서 글자가 통째로 잘린다 — 옆칸이 비어 있으니 넘쳐도 읽힌다. */
/* 빈 날짜 칸 — 「연도-월-일」을 안 그린다(발주 09-02). 누를 자리가 있다는 것만 보인다:
   얹으면 옅게 밝아지고, 누르면 그때 입력칸이 선다. ⚠ 높이는 날짜 칸과 같아야 줄이 안 튄다. */
/* 유형 = 메인 탭 (발주 `SPEC_web_필터-패널` §1) — 영상·도서·굿즈·SNS·플랫폼 --------- */
.type-tabs { display: flex; gap: .3rem; padding: .35rem .6rem 0; }
/* ⭐⭐⭐ **유형 탭 = 둥근 알약 한 부품** (HQ [발주] 09-14 4시 50분 · 링고: *"에셋처럼 둥근 박스가 보이게 · 이런 거로 통일"*) —
   모양은 2.80.0 에셋 종류 알약(`.tagchip`) 그대로: 둥근 알약 · 옅은 테두리 · 고른 것 = 파란(accent) 테두리 + 그 색 글자.
   2.81.0 의 밑줄 탭은 접었다(링고가 고른 기준이 2.80.0 알약) · 그 앞의 아치(위만 둥근 테두리)도 없다 — 되돌리기는 커밋.
   ⚠ 숫자는 `::after` 다(`data-n` · 알약 안 작은 글자) — 단추 글자에 넣으면 「행사12」가 되어 글자로 찾는 자리(검사·손)가 어긋난다.
   ⚠ 높이는 `line-height` 를 박아 맞춘다 — 에셋 코드 글자(고정폭)와 한글 글꼴이 달라도 알약 키가 같아야 한 줄로 읽힌다. */
.pill-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem; }
/* ⭐⭐ 2.105.0 · **품목 탭이 통계보다 먼저 눈에** (HQ [덧] 09-15 13시 40분 · 링고: *"통계보다 품목이 한번에 봐도 더 직관적으로"*) —
   시안 B 의 탭 꼴: 한 단 크고(14px) · 글자 진하게 · 켜진 탭은 채운 바탕 + 굵은 글자 · 개수는 작은 글자.
   눈 차례 = 탭 > 요약 띠(머리줄 위) > 탭 줄 오른쪽 상태 알약(12px · 옅게). ⚠ 테두리 1px · 켜진 탭 accent 테두리·글자는 그대로([B45]). */
.pill-tabs .pill-tab { appearance: none; display: inline-flex; align-items: center; gap: .35rem; box-sizing: border-box;
  margin: 0; border: 1px solid var(--line); border-radius: 999px; padding: .2rem .8rem;
  font: inherit; font-size: .875rem; font-weight: 600; line-height: 1.35; color: var(--fg); background: var(--panel);
  cursor: pointer; white-space: nowrap; }
.pill-tabs .pill-tab:hover,
.pill-tabs .pill-tab.on { border-color: var(--accent); color: var(--accent); }
.pill-tabs .pill-tab.on { background: color-mix(in srgb, var(--accent) 16%, var(--panel)); font-weight: 800; }
.pill-tabs .pill-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pill-tabs .pill-tab[data-n]::after { content: attr(data-n); font-size: .7rem; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--muted); opacity: .85; }
.pill-tabs .pill-tab.on[data-n]::after { color: var(--accent); opacity: 1; }
/* ⭐⭐ **목록 머리 밑 탭 줄 = 한 옷** (HQ [발주] 09-14 4시 반 ② · 링고: *"에셋 쪽이 더 예쁘다"*) —
   에셋 종류(CH BG …) · 컷리스트 유형(영상 도서 …) · 타이틀 유형이 **같은 자리(제목 줄 밑) · 같은 클래스**를 쓴다.
   ⚠ 둘을 다시 가르지 마라 — 한쪽만 고치면 또 갈라진다. 다른 것은 에셋 코드 글자(고정폭) 하나뿐이다. */
div.list-tabs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 8px; }   /* div 를 붙인 까닭: 뒤의 `.kindbar` 여백(6px)을 이긴다 */
div.list-tabs.hidden { display: none; }
.list-tabs > .pill-tabs { padding: 0; }
#asset-kinds.pill-tabs .pill-tab { font-family: ui-monospace, Consolas, monospace; letter-spacing: .02em; }

/* 097 · 색 점 · 구분 칸 · 목록 칸 알약 */
.kdot { display: inline-block; width: .6rem; height: .6rem; border-radius: 50%; flex: none;
  background: var(--muted); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg) 18%, transparent); }
td.kind-cell { white-space: nowrap; }
td.kind-cell > * { vertical-align: middle; }
td.kind-cell .kdot { margin-right: .35rem; }
td.kind-cell select.kind-select { width: calc(100% - 1rem); min-width: 0; font-size: .8rem; padding: .1rem .15rem; }
.cf-pill { display: inline-flex; align-items: center; padding: .05rem .5rem; margin: .1rem .25rem .1rem 0;
  border-radius: 999px; font-size: .74rem; line-height: 1.35; color: var(--fg);
  background: color-mix(in srgb, var(--pc, var(--muted)) 22%, transparent);
  border: 1px solid color-mix(in srgb, var(--pc, var(--muted)) 55%, transparent); }
select.cell.cf-pick { border-radius: 999px; padding-left: .55rem; }
select.cell.cf-pick.on { background: color-mix(in srgb, var(--pc, var(--muted)) 22%, var(--bg));
  border-color: color-mix(in srgb, var(--pc, var(--muted)) 60%, transparent); font-weight: 600; }
.col-head .col-filter { appearance: none; border: 0; background: none; color: var(--muted); cursor: pointer;
  padding: 0 .2rem; margin-left: .15rem; font-size: .72rem; max-width: 8rem; overflow: hidden; text-overflow: ellipsis; }
.col-head .col-filter:hover { color: var(--fg); }
.col-head .col-filter.on { color: var(--on-accent); background: var(--accent); border-radius: 999px; padding: 0 .45rem; }
.cf-filter-pop .cf-filter-list { display: flex; flex-wrap: wrap; gap: .15rem; max-width: 22rem; margin: .3rem 0; }
.cf-filter-pop .cf-filter-opt.on .cf-pill { box-shadow: 0 0 0 2px var(--accent); }
td.cf-opt-cell .ghost { margin-left: .25rem; }
.cf-opt-modal .cf-opt-list { display: flex; flex-direction: column; gap: .3rem; margin: .5rem 0; max-height: 50vh; overflow-y: auto; }
.cf-opt-modal .cf-opt-row { display: flex; align-items: center; gap: .35rem; }
.cf-opt-modal .cf-opt-row input.cell { flex: 1; min-width: 0; }
.cf-opt-modal input[type=color], .dict-table input[type=color] { width: 2rem; height: 1.6rem; padding: 0; border: 1px solid var(--line); background: none; }
.dict-table td.dict-sort { white-space: nowrap; }
.dict-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.dict-table tr.muted input.cell { opacity: .6; }
.dict-table input.code-input { width: 3.2rem; text-transform: uppercase; }
.dict-sec + .dict-sec { margin-top: 1rem; }

/* 098 · 행사 상세 폴더 줄 */
/* ⭐ 100 · 폴더 한 벌 — 상세 폴더 줄(머리 밑 · 세 유형 같은 자리) · 만들기 창 미리보기 · 목록 칸 · 설정 표 */
.folder-row { display: flex; align-items: baseline; gap: .6rem; margin: .35rem 0 .6rem; min-width: 0; }
.folder-row-label { flex: none; min-width: 3.2rem; }
.folder-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .35rem; min-width: 0; }
.folder-line code.origin-path, .folder-preview code.origin-path { word-break: break-all; }
.folder-line .folder-open .ic { width: 14px; height: 14px; vertical-align: -2px; }
.folder-preview { display: inline-flex; flex-wrap: wrap; align-items: center; gap: .4rem; min-width: 0; }
.folder-line-slot { flex-basis: 100%; }
.folder-line-slot .folder-preview-label::after { content: ":"; }
.bulk-line .folder-preview-label { display: none; }
td.folder-cell { text-align: center; white-space: nowrap; }
td.folder-cell .folder-cell-open .ic { width: 16px; height: 16px; vertical-align: -3px; }
td.folder-cell .folder-cell-make { font-size: .78rem; }
td.folder-cell .folder-cell-name { font-size: .72rem; }
/* 101 · 만든 손(웹·마야·포토샵·봇) — 작은 글자 · 씬 한 마디 */
.made-by-tag { font-size: .72rem; padding: 0 .35rem; border-radius: .6rem; border: 1px solid var(--line, #ccc); color: var(--muted, #666); white-space: nowrap; }
td.made-by-cell { text-align: center; white-space: nowrap; }
.folder-preview-scene, .folder-scene { font-size: .8rem; white-space: nowrap; }
.folder-scene { margin-left: .5rem; padding-left: .5rem; border-left: 1px solid var(--line, #ccc); }
.folder-roots-wrap { overflow-x: auto; }
table.folder-roots td { padding: .15rem .3rem; vertical-align: middle; }
table.folder-roots tr.folder-roots-group th { text-align: left; padding-top: .6rem; }
table.folder-roots input.folder-root-input { width: min(26rem, 40vw); }
table.folder-roots input.folder-rule-input { width: 10rem; }
table.folder-roots input.folder-tree-input { width: min(22rem, 30vw); }
.folder-roots-name { white-space: nowrap; }
input.origin-path-input { width: min(34rem, 100%); font-family: ui-monospace, Consolas, monospace; }

/* 거르기 서랍 — **오른쪽 끝에서 미끄러져 나온다** (발주 §2).
   ⚠ 표는 그대로 보인다(덮지 않는다) — 사람이 고르는 즉시 결과를 봐야 한다. */
.filter-drawer { position: fixed; top: 3.2rem; right: 0; bottom: 0; width: 320px;
  max-width: 92vw; padding: .7rem; overflow-y: auto; z-index: 30;
  background: var(--panel); border-left: 1px solid var(--line);
  transform: translateX(100%); transition: transform .18s ease; }
body.drawer-on .filter-drawer { transform: translateX(0); }
body.drawer-on #screen-main { padding-right: 320px; }
.drawer-head { display: flex; align-items: center; gap: .4rem; margin-bottom: .5rem; }
.drawer-head b { flex: 1 1 auto; }
.drawer-top { display: flex; gap: .3rem; margin-bottom: .6rem; }
.drawer-sec { border-top: 1px solid var(--line); padding-top: .5rem; margin-top: .5rem; }
.drawer-sec-head { display: flex; justify-content: space-between; font-size: .8rem;
  color: var(--muted); margin-bottom: .3rem; }
/* 한 화면에 열 개쯤 보이고 스크롤한다 (발주 §2 ①) */
.ep-check-list { max-height: 260px; overflow-y: auto; margin-top: .3rem; }
.ep-check { display: flex; gap: .35rem; align-items: center; padding: .12rem 0;
  font-size: .84rem; }
button.funnel { display: inline-flex; align-items: center; justify-content: center;
  padding: .2rem .45rem; }

/* 빈 날짜·빈 수 — **아무것도 안 그린다** (손맛 다섯 ④ · 링고 09-03).
   ⚠ 높이는 입력칸과 같게 둔다 — 안 그러면 값이 있는 줄과 없는 줄의 높이가 달라 표가 출렁인다. */
.quiet-cell { display: inline-block; min-width: 84px; height: 24px; cursor: text;
  border-radius: 4px; }
.quiet-cell:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }

/* 「방금 올라옴」 — 올린 사람이 화면에서 확인하는 자리 (마야 [요청] ② · 09-03) */
.taskcell .fresh { display: inline-block; margin-top: .15rem; padding: 0 .3rem;
  border-radius: 999px; font-size: .62rem; font-weight: 600;
  color: var(--bg); background: var(--accent); }

/* 그림이 없는 칸 — **왜 없는지** 적는다 (HQ [요청] 09-02 · 회색 칸 대신) */
.thumb.none { display: inline-flex; align-items: center; justify-content: center;
  border: 1px dashed var(--line); border-radius: 4px; cursor: pointer; }
.thumb.none .why { font-size: .62rem; color: var(--muted); text-align: center;
  line-height: 1.1; padding: 0 .15rem; }

/* 단계 사전 — 설정에서 「허브가 밀 수 있는 낱말」을 보여 주는 자리 (2026-09-02) */
.step-dict { margin-top: .6rem; padding-top: .5rem; border-top: 1px solid var(--line); }
.step-dict h4 { margin: 0 0 .2rem; font-size: .85rem; }
.dict-row { display: flex; gap: .5rem; align-items: baseline; margin: .2rem 0; }
.dict-code { margin-right: .3rem; padding: 0 .3rem; border: 1px solid var(--line);
  border-radius: 4px; font-size: .8rem; }

/* 회차 상세 — 「정보」·「산출물」 두 탭 (071) --------------------------------- */
.ep-block { margin: .6rem 0 1rem; }
.ep-tabs { display: flex; gap: .3rem; margin-bottom: .5rem; }
.ep-info { display: grid; grid-template-columns: max-content max-content; gap: .3rem .8rem;
  align-items: center; }
.ep-info-row { display: contents; }
/* ⭐ 2.117.0 · 「항목」 칸은 **글자 폭**, 「상태」 칸이 나머지 전부 (HQ [발주] 09-15 ②①).
   ⚠ 표 폭은 늘 100% 다 — 끌기(`resizeHandle` 의 `fluid`)가 표 폭을 안 건드린다. */
.deliv-box .deliv-table { width: 100%; }
/* ⛔ 여기에 `th { position: relative }` 를 적지 마라 — 이 줄의 무게(0,2,1)가 붙는 머리(`table.pinhead thead th` 0,1,3)를
   이겨서 `top` 값만큼 **머리 칸이 아래로 밀렸다**(캡처 실측: 표 위 59px 아래 줄 사이에 머리가 떴다).
   손잡이의 기준점은 붙는 칸(`sticky`)이 이미 된다. */
.deliv-box .deliv-table th .col-head { display: flex; align-items: center; gap: .3rem; }
/* ⭐ v2 — **줄 사이 여백 절반** (발주 §②). 열두 줄이 한 화면에 들어가는 것이 목표다. */
.deliv-box .deliv-table td, .deliv-box .deliv-table th { padding: .1rem .4rem; line-height: 1.35; }
.deliv-box .deliv-table td:first-child { white-space: nowrap; }
/* 있다/없다 — 색이 먼저 읽히고 글이 그것을 확인해 준다 */
.deliv-state { font-weight: 600; }
.deliv-state.on { color: var(--ok, #4ea172); }
.deliv-state.off { color: var(--muted); font-weight: 500; }
.deliv-tagbar { display: flex; gap: .4rem; align-items: center; margin: .5rem 0; }
.deliv-head { margin: .8rem 0 .3rem; font-size: .85rem; color: var(--muted); }

td.date-blank { cursor: text; }
td.date-blank:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }

.g-dayrow { position: relative; }
.g-daylabs { position: absolute; inset: 0; pointer-events: none; }
/* ⚠ 날짜 눈금을 **한 단계 올린다** — 스케줄 판(`.gtick`)이 09-01 에 받은 그 손질을
   Task 간트는 못 받아서, 같은 날짜를 판 둘이 다르게 그리고 있었다(링고: *"날짜 격자는
   더 잘 보이도록"*). ⭐ 한 단계씩만 — 눈금이 막대보다 세면 일정이 안 읽힌다. */
.g-daylab { position: absolute; top: 0; transform: translateX(-50%);
  font-size: .72rem; line-height: 22px; white-space: nowrap;
  color: color-mix(in srgb, var(--fg) 72%, transparent); }
/* 달 첫날 · 오늘 — 달 띠와 같은 자리에서 갈리는 날이라 굵게, 오늘은 강조색으로 적는다
   (굵은 칸 음영만으로는 «무슨 칸인가» 를 모른다 · 스케줄 판의 `.gtick.now` 와 같은 자) */
.g-daylab.m1 { color: var(--fg); font-weight: 700; }
.g-daylab.now { color: var(--accent); font-weight: 700; }
/* 요일 약자 — 날짜 **뒤에 작게**. ⚠ 날짜보다 세면 며칠인지가 안 읽힌다. */
.g-daylab .g-dow { font-size: .62rem; margin-left: .12rem; opacity: .72; font-weight: 500; }
/* ⚠⚠ 요일 색 쌍은 **스케줄 판(`.gantt`) 안에서만** 살고 있었다 — Task 간트는 그 판 밖이라
   그대로 쓰면 «있지도 않은 값» 이 된다(글자가 상속색으로 뜬다). 같은 값을 한 벌 더 둔다.
   ⚠ **두 테마 모두** 적는다: 한쪽만 적으면 밝게 화면에서 파랑·빨강이 안 읽힌다. */
:root { --dow-sat: #8ab4ff; --dow-sun: #ff9a9a; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) { --dow-sat: #1d4ed8; --dow-sun: #b91c1c; }
}
:root[data-theme="light"] { --dow-sat: #1d4ed8; --dow-sun: #b91c1c; }
.g-daylab .g-dow.sat { color: var(--dow-sat); opacity: .95; }
.g-daylab .g-dow.sun { color: var(--dow-sun); opacity: .95; }
/* 달 첫날에 금을 하나 — 달 띠와 눈금이 같은 자리에서 갈려야 눈이 안 흔들린다 */
.g-day.m1 { border-left: 1px solid color-mix(in srgb, var(--fg) 16%, transparent); }
.g-in.num.mon { width: 40px; text-align: right; margin-left: 0; }
/* 켜 둔 단추 — 「겹쳐 보기」가 지금 켜져 있는지 한눈에 */
button.ghost.small.on { background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-color: var(--accent); color: var(--fg); font-weight: 600; }

/* ④ 베이스라인 — 태스크 막대 **뒤에** 깔리는 옅은 띠. 견줄 때만 켠다. */
.g-bar.base { top: 3px; height: 19px; border-radius: 4px;
  background: color-mix(in srgb, var(--sc, var(--accent)) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--sc, var(--accent)) 30%, transparent); }
/* 그 창 밖에 있는 일 — 띠 쪽에 표시한다(막대 색은 **상태**의 몫이라 안 뺏는다) */
.g-bar.base.out { border-style: dashed;
  border-color: color-mix(in srgb, var(--st-retake, #d9534f) 60%, transparent); }

/* ④ 거르개 줄 — 판 **안**, 거른 결과 바로 위 */
.gantt-filters { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  margin: 0 0 .5rem; }
.gantt-filters .g-fil { height: 26px; font-size: .78rem; padding: 0 .3rem;
  border: 1px solid var(--line); border-radius: 6px;
  background: var(--bg); color: var(--fg); max-width: 11rem; }
/* 걸려 있는 거르개는 **표가 나야 한다** — 안 나면 「없다」와 구별이 안 된다 */
.gantt-filters .g-fil.on { border-color: var(--accent); font-weight: 600;
  background: color-mix(in srgb, var(--accent) 10%, transparent); }

/* ---- M4 (선후 FS) — 잇는 손잡이 · 의존선 · 어긴 것 -------------------------
   ⚠ 막대는 div, **선만 SVG** (발주 §2). 선은 판 위에 얹히되 손짓을 안 먹는다 —
     먹으면 그 아래 막대를 못 잡는다. */
svg.gantt-deps { position: absolute; left: 0; top: 0; pointer-events: none; z-index: 3; }

/* M6 — 접힌 사람 줄에 겹쳐 그리는 일감. **막대보다 얇고 옅다** — 이 줄에서 읽는 것은
   «언제 몰려 있나» 이지 «무슨 일인가» 가 아니다(그것은 펼치면 줄마다 있다).
   ⚠ 손짓을 안 받는다: 이 줄을 누르는 것은 «펼치기» 다. */
.g-bar.load { top: 10px; height: 12px; background: var(--accent); opacity: .55;
              border-radius: 3px; pointer-events: none; }
/* M5 — 마일스톤. 머리줄의 다이아몬드와, 판을 가로지르는 세로선.
   ⚠ 선은 **막대보다 옅고 손짓을 안 받는다**(`pointer-events: none`) — 진하면 막대를
     읽는 눈을 뺏고, 손짓을 받으면 그 자리의 막대를 못 집는다.
   ⚠ z-index 는 의존선(3)보다 아래, 막대와 같은 층 아래다 — 「깔린다」가 이 선의 일이다. */
.g-marks { position: relative; height: 18px; }
.g-mark { position: absolute; top: 2px; transform: translateX(-5px);
          display: inline-flex; align-items: center; gap: .25rem; white-space: nowrap; }
.g-mark .d { width: 9px; height: 9px; background: var(--accent);
             transform: rotate(45deg); border-radius: 1px; flex: 0 0 auto; }
.g-mark .t { font-size: .7rem; color: var(--muted); }
/* 안내 중에 **고쳐야 할 것**을 가리키는 줄 (M5 — 날짜 없는 점). 여느 안내와 같은 크기,
   색만 다르다: 커지면 잔소리가 되고, 같은 색이면 안 읽힌다. */
.hint.warn { color: var(--st-retake, #d9534f); }
/* 전체 일정 (간트 v1.2 §2) — 한 줄이 프로젝트 하나 */
.overview-tags { margin: 0 0 .5rem; }
.overview-tags .tagchip.on { border-color: var(--accent); color: var(--fg); font-weight: 600; }
/* 마일스톤 다이아몬드 — 줄 **안**에 (전체 보기에는 세로선을 안 긋는다: 프로젝트마다
   약속한 날이 달라서 선을 다 그으면 판이 선으로 덮인다) */
.g-mdot { position: absolute; top: 12px; width: 8px; height: 8px; margin-left: -4px;
  background: var(--accent); transform: rotate(45deg); border-radius: 1px; }
/* 「일은 있는데 날짜가 없다」 — 빈 줄로 두면 «일이 없다» 와 똑같이 생긴다 */
.g-none { position: absolute; left: 0; top: 8px; font-size: .74rem; color: var(--muted); }

/* ⭐ 큰 그림 — 프로젝트가 약속한 띠를 판 **바닥**에 (발주 간트 v1.2 §3).
   ⚠ 옅어야 한다: 이 위에서 막대를 읽는다. 진하면 큰 그림이 일정을 가린다.
   ⚠ `z-index: 0` — 마일스톤 선(1)보다도 뒤, 막대(2 이상)보다 뒤다. */
.g-overlay { position: absolute; left: 0; top: 0; right: 0;
          pointer-events: none; z-index: 0; }
.g-over-band {
  position: absolute; top: 0; bottom: 0;
  background: color-mix(in srgb, var(--sc, var(--accent)) 7%, transparent);
  border-left: 1px solid color-mix(in srgb, var(--sc, var(--accent)) 26%, transparent);
  border-right: 1px solid color-mix(in srgb, var(--sc, var(--accent)) 26%, transparent);
}
/* 이름은 판 맨 위에 한 번만 — 줄마다 적으면 글자가 판을 덮는다 */
.g-over-band .t {
  position: sticky; top: 0; display: inline-block; padding: 1px .3rem;
  font-size: .7rem; font-weight: 600; white-space: nowrap;
  color: color-mix(in srgb, var(--fg) 55%, transparent);
}

.g-mlines { position: absolute; left: 0; top: 0; right: 0;
            pointer-events: none; z-index: 1; }
.g-mline { position: absolute; top: 0; bottom: 0; width: 0;
           border-left: 1px dashed var(--accent); opacity: .45; }
.g-dep { fill: none; stroke-width: 1.5;
  stroke: color-mix(in srgb, var(--fg) 45%, transparent); }
.g-dep-tip { fill: color-mix(in srgb, var(--fg) 45%, transparent); stroke: none; }
/* 어긴 선 — **막지 않고 말한다**(자동 재배치는 범위 밖) */
.g-dep.bad { stroke: var(--st-retake, #d9534f); stroke-width: 2; }
.g-dep-tip.bad { fill: var(--st-retake, #d9534f); }
/* 긋는 중인 선 — 점선이라 «아직 안 걸렸다» 가 보인다 */
.g-dep.live { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 4 3; }

/* 잇는 손잡이 ○ — 막대 오른쪽 끝 바깥. 평소엔 옅고, 줄에 손이 얹히면 진해진다. */
.g-link { position: absolute; right: -11px; top: 50%; width: 9px; height: 9px;
  margin-top: -4.5px; border-radius: 50%; cursor: crosshair; touch-action: none;
  background: var(--panel); border: 1.5px solid color-mix(in srgb, var(--fg) 40%, transparent);
  opacity: .35; transition: opacity .12s; z-index: 4; }
.gantt-lane:hover .g-link, .g-link:hover { opacity: 1; border-color: var(--accent); }

/* 어긴 후행 막대 — 선 색만으로는 접힌 줄에서 안 보인다. `!` 는 막대에 남는다. */
.g-bar.plan.dep-bad { outline: 1px solid var(--st-retake, #d9534f); outline-offset: 1px; }
.g-bang { position: absolute; right: 2px; top: 50%; margin-top: -7px;
  width: 12px; height: 14px; line-height: 14px; text-align: center;
  font-size: .7rem; font-weight: 800; font-style: normal;
  color: var(--st-retake, #d9534f); }

/* ---- 메인 스케줄표 — 판에서 직접 만들고 우클릭으로 고친다 (링고 2026-08-30) ----
   ⚠ 표를 걷었다. 이름·종류·시작·끝·단계·색·빼기는 전부 줄 우클릭 판으로 갔다. */
/* 날짜가 없는 줄 — **그을 수 있는 자리라고 보여야** 사람이 시도한다 */
.gantt .gtrack.makeable { cursor: crosshair; border-radius: 6px;
  background: repeating-linear-gradient(45deg,
    transparent 0 6px, color-mix(in srgb, var(--fg) 5%, transparent) 6px 12px); }
.gantt .gtrack.makeable:hover {
  background: repeating-linear-gradient(45deg,
    transparent 0 6px, color-mix(in srgb, var(--accent) 12%, transparent) 6px 12px); }
/* 긋는 동안만 사는 허깨비 — 놓아야 진짜가 된다 */
.gantt .gbar.making { background: color-mix(in srgb, var(--accent) 55%, transparent);
  outline: 1px solid var(--accent); pointer-events: none; }
.gantt .gbar.making.point { border-radius: 3px; }

/* 줄 우클릭 판 — 표가 하던 일곱 가지가 여기 다 있다 */
.seg-pop .row.steps { align-items: flex-start; }
.seg-pop .sched-steps { justify-content: flex-end; max-width: 15rem; }
.seg-pop input.sched-color { width: 3rem; padding: 0; height: 1.5rem; }
.seg-pop .row .spacer { flex: 1; }

/* ---- 스케줄 판: 날짜 축 · 가로로 밀기 · Alt 로 확대 (링고 2026-08-30) --------
   ⚠⚠ 여기 규칙이 위쪽 `.gantt` 묶음을 **덮어쓴다**(뒤에 오니까). 위를 고칠 일이 있으면
     여기부터 보라 — 두 자리에 나눠 적힌 것이 이 구획의 값이자 빚이다. */
.gantt { position: relative; margin: .4rem 0 .8rem;
  overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; }
.gantt.panning { cursor: grabbing; }
.gantt.zooming { cursor: ew-resize; user-select: none; }
.gstage { width: max-content; min-width: 100%; position: relative; }
.gbody { position: relative; width: max-content; }
/* 눈금판은 이제 **트랙 자리에만** 깔린다 (이름 칸 오른쪽부터) */
.gantt .gbody > .gantt-grid { inset: 0 auto 0 0; }
/* 이름 칸은 왼쪽에 붙어 있는다 — 가로로 밀어도 «어느 줄인가» 가 남아야 한다 */
/* ⚠ 이 칸은 **제 바탕을 갖고 있다**(가로로 밀 때 밑줄이 비쳐 보이면 안 되니까) — 판을
   종이로 바꾸면서 여기를 안 고쳤더니 **이름이 검정 위 검정**이 됐다(실측 2026-09-02). */
.gantt .gname { width: 176px; flex: none; position: sticky; left: 0; z-index: 2;
  background: var(--g-paper); color: var(--g-ink);
  padding-right: .5rem; box-sizing: border-box;
  border-right: 1px solid color-mix(in srgb, var(--g-ink) 16%, transparent); }
.gantt .gtrack { flex: none; }
.gantt .gantt-row { gap: 0; }

/* 날짜 축 — 달 띠 + 눈금. ⭐ 이것이 없어서 «현재 날짜가 안 보인다» 였다. */
/* ⚠ 날짜 눈금이 **안 읽혔다** (링고 2026-09-01: *"날짜 격자는 더 잘 보이도록, 현재 잘 안
   보인다"*). 글자가 .66rem 에 옅은 회색이라, 판을 볼 때 «며칠짜리인가» 를 세려면 눈을
   가늘게 떠야 했다. ⭐ **한 단계씩만 올린다** — 눈금이 막대보다 세지면 그때는 눈금을
   읽느라 일정이 안 보인다. 달 띠를 먼저 읽고(굵게), 날짜는 그다음(또렷하게). */
.gaxis { display: flex; align-items: stretch; height: 38px; position: sticky; top: 0; z-index: 3; }
.gaxis .gname.gaxis-sp { background: var(--g-paper); }
.gaxis-track { position: relative; }
.gmonths { display: flex; height: 18px; }
.gmonth { font-size: .78rem; font-weight: 600;
  color: var(--g-ink); padding-left: .3rem; overflow: hidden;
  white-space: nowrap; border-left: 1px solid color-mix(in srgb, var(--g-ink) 22%, transparent); }
.gticks { position: relative; height: 20px; }
/* 눈금 글자도 같이 올린다 — 선만 밝히면 «선은 보이는데 며칠인지는 안 보이는» 판이 된다. */
.gtick { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap;
  font-size: .72rem; line-height: 20px;
  color: color-mix(in srgb, var(--g-ink) 78%, transparent); }
.gtick.mon { color: var(--g-ink); font-weight: 600; }
.gtick.m1 { color: var(--g-ink); font-weight: 700; }
/* ⭐ 요일 약자 — 날짜 **뒤에 작게**. ⚠ 날짜보다 세면 며칠인지가 안 읽힌다. */
.gtick .gdow { font-size: .62rem; margin-left: .12rem; opacity: .72; font-weight: 500; }
.gtick .gdow.sat { color: var(--g-sat); opacity: .95; }
.gtick .gdow.sun { color: var(--g-sun); opacity: .95; }
/* 오늘 — 글로도 적는다. 굵은 선만으로는 무슨 선인지 모른다. */
.gtick.now { color: var(--accent); font-weight: 700;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  border-radius: 4px; padding: 0 .25rem; }

/* ---- 확대·축소 단추 (링고 2026-08-30: "확대 축소 구현은 안된 듯") ------------
   ⭐ Alt+끌기로 지어 뒀는데 **보이지 않는 손짓은 없는 기능이다.** 단추를 붙인다.
   ⚠ 판 위에 얹되 **오른쪽 위 구석**에 — 막대가 사는 왼쪽·가운데를 안 가린다. */
.gzoom { position: sticky; float: right; top: 2px; right: 2px; z-index: 5;
  display: flex; gap: 2px; margin-left: auto; }
.gzoom button { padding: 0 .4rem; line-height: 18px; min-width: 22px;
  background: var(--panel); opacity: .55; }
.gantt:hover .gzoom button { opacity: 1; }
/* 색이 없는 띠도 **보이게** — 기본 색은 새로 만들 때 붙지만, 옛 줄은 이 값이 받는다 */
.gantt .gbar.plan { background: color-mix(in srgb, var(--accent) 55%, transparent); }

/* ---- 두 간트가 같은 옷을 입는다 (링고 2026-08-30) --------------------------
   ⭐ 거르개 줄은 에셋·컷리스트의 `.filterbar`·`.cond-row` 를 그대로 쓴다 —
      여기서는 간트 판 안에 놓이는 자리만 잡아 준다. */
.gantt-filters { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin: 0 0 .5rem; }
.gantt-filters .cond-row { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.gantt-filters select { height: 26px; font-size: .78rem; max-width: 11rem; }
/* 「보는 폭」 한 벌 — 스케줄 판과 Task 간트가 같은 모양으로 쓴다 */
.span-ctl { display: inline-flex; align-items: center; gap: .35rem; }
.span-ctl .seg-switch button { padding: 0 .45rem; }
.gzoom .span-ctl { background: var(--panel); border-radius: 8px; padding: 2px 4px;
  box-shadow: 0 1px 6px rgba(0,0,0,.25); }


/* ==========================================================================
   전체 일정 = 스케줄 한 장 (HQ [발주] 09-14 ②⑥)
   ⚠ 왼쪽 칸 폭은 **그리개가 인라인으로 준다**(`nameWidth` · 끌어서 바꾼다) — 여기서 폭을 다시 적지 않는다.
   ⭐ 한 줄 = 이름(굵게 · 한 줄 다 보임) / 밑에 작은 글자 「9-7 → 9-17 · 11일」 · 색 점은 이름 앞 ·
     마일스톤은 ◆ · 묶음(프로젝트) 줄은 접기 화살표. ⛔ 옛 일곱 칸 격자(번호·점·썸네일·이름·일수·시작·끝)는 걷었다.
   ========================================================================== */
#overview-box .gantt-row { height: var(--ov-rowh, 34px); min-height: 0; }
#overview-box .gantt .gname { overflow: visible; white-space: normal; padding: 0 .5rem 0 0; height: 100%; }
.ovl { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: 100%; }
.ovl-arrow {
  flex: none; width: 16px; height: 16px; padding: 0; border: 0; background: none;
  color: var(--g-ink); font-size: .72rem; line-height: 16px; cursor: pointer; border-radius: 4px;
}
.ovl-arrow:hover { background: color-mix(in srgb, var(--g-ink) 12%, transparent); }
.ovl-arrow.none { cursor: default; background: none; }
.ovl-dot { flex: none; width: 9px; height: 9px; border-radius: 999px; background: var(--pc, var(--accent)); }
.ovl-dot.small { width: 7px; height: 7px; }
.ovl-diamond { flex: none; width: 9px; font-style: normal; font-size: .72rem; line-height: 1; color: var(--pc, var(--accent)); text-align: center; }
.ovl-thumb { flex: none; width: 40px; height: 26px; object-fit: cover; border-radius: 4px; }
.ovl-text { display: flex; flex-direction: column; justify-content: center; min-width: 0; line-height: 1.18; }
.ovl-name {
  font-size: calc(.84rem * var(--g-font, 1)); font-weight: 600; color: var(--g-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ovl-name b { font-weight: 700; }
.ovl-title { font-weight: 500; }
.ovl-sub {
  font-size: calc(.7rem * var(--g-font, 1)); color: color-mix(in srgb, var(--g-ink) 62%, transparent);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums;
}
/* 좁은 두 단(촘촘·보통) — 날짜가 이름 **옆**으로 온다(두 줄이 안 들어간다) */
#overview-box.ov-short .ovl-text { flex-direction: row; align-items: baseline; gap: 8px; }
/* 묶음 줄 — 한 단 짙은 바탕 · 이름은 누르면 접고 편다 */
.gantt-row.ov-row.group { background: color-mix(in srgb, var(--g-ink) 6%, transparent); }
.gantt-row.ov-row.group .ovl-name { cursor: pointer; font-size: calc(.9rem * var(--g-font, 1)); }
/* ⚠⚠ 줄 갈래 이름이 `sub` 이던 때 전역 `.sub`(설명 글자 · margin .2rem 0 1.2rem)가 줄에 붙어 **줄마다 19px 씩 벌어졌다** — 왼쪽과 막대가 어긋나 보인 뿌리 하나. `ov-sub` 로 갈랐다. */
.gantt-row.ov-row.ov-sub .gname { padding-left: 14px; }
.gantt-row.ov-row.step .gname { padding-left: 28px; }
.gantt-row.ov-row.step .ovl-name { font-weight: 500; }
/* 새 줄 칸 — 「스케줄 새로 작성」 옅게 · 누르면 이름 칸 */
.ovl-plus { flex: none; width: 9px; font-style: normal; color: color-mix(in srgb, var(--g-ink) 45%, transparent); text-align: center; }
.ovl-new {
  flex: 1; min-width: 0; height: 22px; padding: 0 6px; border-radius: 6px;
  border: 1px solid transparent; background: transparent; color: var(--g-ink);
  font-size: calc(.8rem * var(--g-font, 1));
}
.ovl-new::placeholder { color: color-mix(in srgb, var(--g-ink) 42%, transparent); }
.ovl-new:hover { border-color: color-mix(in srgb, var(--g-ink) 18%, transparent); }
.ovl-new:focus { border-color: var(--accent); background: var(--g-paper); outline: none; }
.ovl-newmile { flex: none; padding: 0 5px; height: 22px; font-size: .7rem; opacity: .55; }
.ovl-newmile:hover { opacity: 1; }
/* ⭐ 마우스를 올리면 **그 줄 막대가 밝아진다** — 왼쪽 이름과 오른쪽 막대를 눈이 잇는다 */
#overview-box .gantt-row:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); }
#overview-box .gantt-row:hover .gbar.plan:not(.ov-step-bar):not(.ov-task) {
  filter: brightness(1.22) saturate(1.15);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 55%, transparent);
}
#overview-box .gantt-row:hover .gpoint { filter: brightness(1.22); text-shadow: 0 0 6px var(--accent); }
/* 이름 칸 폭 손잡이 — 머리 빈칸 오른쪽 끝 */
.gname-grip {
  position: absolute; top: 0; right: -3px; bottom: 0; width: 7px; cursor: col-resize; z-index: 4;
}
.gname-grip:hover, body.col-resizing .gname-grip { background: color-mix(in srgb, var(--accent) 60%, transparent); }
body.col-resizing { cursor: col-resize; user-select: none; }
/* 막대 — 접힌 줄은 여럿이 겹친다 · 하루짜리도 **보인다**(끝날까지 칠하고, 그래도 좁으면 6px) */
.gantt .gbar.plan { min-width: 6px; }
.gantt .gbar.ov-band { height: var(--g-barh, 12px); overflow: hidden; }
.gantt .gbar.ov-band .gbar-lab { max-width: calc(100% - 10px); overflow: hidden; text-overflow: clip; }
.gantt .gbar-lab {
  position: absolute; left: 6px; top: 50%; transform: translateY(-50%);
  font-size: .68rem; color: #fff; white-space: nowrap; pointer-events: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .45);
}
.gantt .gbar.ov-step-bar {
  opacity: .35; height: calc(var(--g-barh, 12px) * .5);
  top: calc((var(--ov-rowh, 26px) - var(--g-barh, 12px) * .5) / 2);
}
.gantt .gbar.ov-sum { opacity: .55; height: calc(var(--g-barh, 12px) * .67);
  top: calc((var(--ov-rowh, 26px) - var(--g-barh, 12px) * .67) / 2); }
/* ▦ 태스크 막대 — 스케줄 막대 **밑에 얇게** · 짙게(스케줄과 같은 색이라도 갈려 읽힌다) */
.gantt .gbar.plan.ov-task {
  height: 4px; min-width: 4px; opacity: .95; border-radius: 2px; z-index: 1;
  top: calc((var(--ov-rowh, 26px) + var(--g-barh, 12px)) / 2 + 1px);
  filter: brightness(.6) saturate(1.2);
}
/* ⭐ 2.127.0 · **프로젝트 뒷판 홀짝** (HQ [덧] 09-17 ④ · 링고 「홀수·짝수 뒷판 색이 바뀌어야 프로젝트 여러 개 비교가 가능」).
   한 프로젝트의 줄 전부(묶음·스케줄·단계·새 줄)가 한 판 — 짝 판이 한 단 짙다 · 이름 칸은 불투명이라 같은 값을 판 색에 섞어 깐다.
   ⚠ 뒷판 색을 사람이 정하는 칸은 아직 없다 — 생기면 줄에 `--ov-plate` 를 적어 이 값을 이긴다. */
.gantt-row.ov-row { --ov-plate-mix: 3%; }
.gantt-row.ov-row.ov-even { --ov-plate-mix: 10%; }
.gantt-row.ov-row.group { --ov-plate-mix: 8%; }
.gantt-row.ov-row.group.ov-even { --ov-plate-mix: 16%; }
.gantt-row.ov-row.ov-odd, .gantt-row.ov-row.ov-even {
  background: var(--ov-plate, color-mix(in srgb, var(--g-ink) var(--ov-plate-mix), transparent));
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.gantt-row.ov-row.ov-odd .gname, .gantt-row.ov-row.ov-even .gname {
  background: var(--ov-plate, color-mix(in srgb, var(--g-ink) var(--ov-plate-mix), var(--g-paper)));
}
/* 그룹 줄 (119) — 스케줄 줄과 같은 들여쓰기 · 안에 든 줄은 한 칸 더 */
.gantt-row.ov-row.ov-grp .gname { padding-left: 14px; }
.gantt-row.ov-row.in-grp .gname { padding-left: 28px; }
.gantt-row.ov-row.in-grp.step .gname { padding-left: 42px; }
.ovl-grp { flex: none; font-style: normal; font-size: .72rem; color: color-mix(in srgb, var(--g-ink) 70%, transparent); }
.gantt .gbar.ov-grp { opacity: .8; height: calc(var(--g-barh, 12px) * .5);
  top: calc((var(--ov-rowh, 26px) - var(--g-barh, 12px) * .5) / 2);
  background-image: linear-gradient(90deg, rgba(0,0,0,.25) 0 3px, transparent 3px calc(100% - 3px), rgba(0,0,0,.25) calc(100% - 3px));
}
/* 고른 막대 (Ctrl·Shift 로 여럿) — 흰 테 + 강조색 그림자 · 인쇄에서도 테는 남는다 */
.gantt .gbar.sel, .gantt .gpoint.sel {
  outline: 2px solid #fff; outline-offset: 1px;
  box-shadow: 0 0 0 4px var(--accent);
  z-index: 2;
}
.gantt .gpoint.sel { outline: none; box-shadow: none; text-shadow: 0 0 0 #fff, 0 0 6px var(--accent), 0 0 2px #fff; }
/* 마일스톤 ◆ — 줄 가운데 */
.gantt .gpoint { top: 50%; margin-top: -.5em; }
.ov-icons { display: inline-flex; gap: 2px; align-items: center; }
.ov-icons .on { color: var(--accent); border-color: var(--accent); }
/* 「마우스: 마야 꼴 · 잠김」 — 단축키 바꾸기 자리(다음 판) */
.ov-mouse {
  display: inline-flex; align-items: center; gap: 5px; font-size: .74rem; color: var(--muted);
  border: 1px dashed var(--line); border-radius: 999px; padding: 1px 8px; cursor: help; white-space: nowrap;
}
.ov-mouse .lock { font-size: .66rem; opacity: .8; }
.ov-hints p { margin: .15rem 0; }
#overview-box.ov-pic .ovl-thumb { width: 56px; height: 36px; }

/* ==========================================================================
   태스크 탭 (HQ [발주] 09-14 ①) — 진행 요약 카드 넷 · 거르개 · 묶은 표
   ========================================================================== */
.tk-cards { display: grid; grid-template-columns: minmax(150px, .7fr) repeat(3, minmax(220px, 1fr));
  gap: 10px; margin: .2rem 0 .8rem; }
@media (max-width: 1100px) { .tk-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.tk-card { background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
  padding: .6rem .75rem; min-width: 0; }
.tk-card h3 { margin: 0 0 .35rem; font-size: .78rem; font-weight: 600; color: var(--muted); }
.tk-big { font-size: 2rem; font-weight: 700; line-height: 1.05; color: var(--fg); font-variant-numeric: tabular-nums; }
.tk-big small { font-size: .9rem; font-weight: 600; margin-left: 2px; color: var(--muted); }
.tk-card.total .tk-big { color: var(--accent); }
.tk-note { margin: .25rem 0 0; font-size: .74rem; color: var(--muted); }
.tk-bar { display: inline-block; flex: none; width: 64px; height: 6px; border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 12%, transparent); overflow: hidden; vertical-align: middle; }
.tk-bar i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.tk-card.total .tk-bar { width: 100%; height: 8px; margin-top: .35rem; }
.tk-list { display: flex; flex-direction: column; gap: 1px; max-height: 164px; overflow-y: auto; }
.tk-line { display: flex; align-items: center; gap: 7px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 6px; padding: 3px 5px; color: var(--fg); cursor: pointer; font-size: .8rem; }
.tk-line:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
.tk-line.on { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.tk-dot { display: inline-block; flex: none; width: 8px; height: 8px; border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 35%, transparent); vertical-align: middle; }
.tk-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-num { flex: none; font-size: .74rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tk-num.day { min-width: 3.6rem; }
.tk-card.week .tk-line .tk-big { font-size: 1.6rem; }
.tk-late { color: var(--st-retake, #d9480f); font-weight: 600; font-size: .78rem; }
.tk-table-wrap { overflow-x: auto; }
.tk-table td.day, .tk-table td.num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.tk-table td.day.late { color: var(--st-retake, #d9480f); font-weight: 600; }
.tk-table tr.tk-row { cursor: pointer; }
.tk-table tr.tk-group td { background: color-mix(in srgb, var(--fg) 6%, transparent); cursor: pointer;
  font-size: .84rem; padding-top: .4rem; padding-bottom: .4rem; }
.tk-table tr.tk-group .tk-arrow { display: inline-block; width: 1.1rem; color: var(--muted); }
.tk-table tr.tk-group .tk-dot { margin-right: 6px; }
#tasks-actions .seg-switch .hint { padding: 0 .35rem; align-self: center; }
/* 태스크 탭 안의 간트 — 머리 이름(「Task 간트」)은 탭 이름과 겹친다 · 도구 줄만 남긴다 */
#tasks-gantt .gantt-sep { margin-top: 0; border-top: 0; padding-top: 0; }
#tasks-gantt .gantt-sep h2 { display: none; }

/* 인박스의 「로컬 손이 한 일」 (085) */
.hand-box { margin: 0 0 10px; display: grid; gap: 3px; }
.hand-head { display: flex; gap: 8px; align-items: center; }
.hand-head .chip.on { color: var(--st-done, #2f9e44); border-color: currentColor; }
.hand-row {
  display: grid; grid-template-columns: 52px 110px 150px 80px 1fr 120px;
  gap: 8px; align-items: center; font-size: .8rem; padding: 2px 4px;
  border-radius: 4px;
}
.hand-row > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hand-row.st-err { background: color-mix(in srgb, var(--st-retake, #d6336c) 12%, transparent); }
.hand-row.st-ip { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.hand-log { color: var(--muted); }

/* 타이틀 화면의 탭 넷 (구성안 09-03 ①) */
.ep-links .ep-link-list { display: grid; gap: 2px; max-height: 420px; overflow: auto; }
/* ⭐⭐ 2.136.0 · **코드 칸은 글자만큼**이다 (HQ [덧] 09-18 ① · 링고 실측 `CS_VC001_IM000` 위에 `Book2025` 가 겹쳐 찍힘).
   ⚠ 여태 코드 칸이 `90px` 로 박혀 있었다 — 격자 칸은 글자보다 좁아도 안 줄고 **넘쳐서 옆 칸 글자 위에 그려진다**
     (칸이 서로 밀지 않는다). 코드가 길어진 VC 에서 두드러졌을 뿐, 자리 자체가 도서·영상·굿즈와 같은 한 줄이다.
   ⭐ 코드는 `max-content` 로 제 글자만큼 갖고(모자라면 `5.5rem`), 이름이 남은 자리를 갖고 길면 **줄임표**로 잘린다.
     `min-width: 0` 이 없으면 격자 칸은 다시 안 줄어든다 — 줄임표가 서려면 둘이 한 벌이다. */
.ep-link-row {
  display: grid; grid-template-columns: 48px minmax(5.5rem, max-content) minmax(0, 1fr);
  gap: 8px; align-items: center;
  background: none; border: 0; text-align: left; cursor: pointer; padding: 2px 4px;
  border-radius: 4px; color: inherit; font: inherit;
}
.ep-link-row > * { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ep-link-row:hover { background: color-mix(in srgb, currentColor 8%, transparent); }
.ep-link-row .thumb { width: 48px; height: 28px; object-fit: cover; border-radius: 3px; }
.ep-link-row .thumb.none { background: color-mix(in srgb, currentColor 12%, transparent); }
.ep-text .doc-h { margin: 10px 0 4px; }

/* 묶음 머리줄의 한글 제목 — 이름을 밀어내지 않고 옆에 흐리게 (링고 09-03) */
.group-row .group-note { margin-left: 10px; color: var(--muted); font-weight: 400; }

/* Alt + 위아래 끌기 = 줄 높이 (링고 09-03) — 축이 잠긴 동안 손짓을 눈에 보인다 */
.gantt.rowsizing { cursor: ns-resize; }
/* 줄 높이는 **모든 판**에 닿는다(스케줄·전체 일정) — 값은 `.gantt-host` 가 든다 */
.gantt-host .gantt-row { min-height: var(--ov-rowh, 26px); }

/* 빈 자리의 단추 둘 — 「필터 지우기」·「조건 보기」 (링고 09-03) */
.empty .empty-acts { display: flex; gap: 6px; justify-content: center; margin-top: 8px; }

/* 깔때기에 걸린 조건 수 (링고 09-03) — 켜져 있으면 색으로도 말한다 */
.ghost.funnel.on { color: var(--accent); border-color: var(--accent); }
.ghost.funnel .chip { margin-left: 4px; padding: 0 5px; font-size: .7rem; }

/* 줄 끝의 「⋯」 (발주 09-03 4번) — 줄에 마우스를 올리면 진해진다 */
.dots-cell { text-align: center; padding: 0; }
.shot-table .ghost.dots {
  padding: 0 4px; line-height: 1; opacity: .35; border: 0; background: none;
  cursor: pointer; color: inherit; font-size: 1rem;
}
tr:hover .ghost.dots, .ghost.dots:focus { opacity: 1; }
.ghost.off { opacity: .5; }

/* 우클릭 메뉴 — 묶음 넷 · 아이콘 · 짧은 말 (HQ [요청] 09-03) */
.ctx-menu .ctx-item { display: flex; gap: 8px; align-items: center; }
.ctx-menu .ctx-item .ic { flex: none; opacity: .8; }
.ctx-menu .ctx-item.off { opacity: .38; cursor: default; }
.ctx-menu .ctx-item.danger { color: var(--danger); }
/* 2.109.0 · 고르는 줄의 동그라미 — 썸네일 세 줄 (칠한 ● = 지금 고른 것 · 색은 「완료」 상태 색을 화면이 칠한다) */
.ctx-menu .ctx-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid var(--muted); box-sizing: border-box; }
.ctx-menu .ctx-dot.on { border-color: transparent; }
.ctx-menu .ctx-head {
  display: flex; gap: 6px; align-items: center; padding: 6px 10px 4px;
  font-size: .82rem; border-bottom: 1px solid color-mix(in srgb, currentColor 14%, transparent);
}
.ctx-menu .ctx-section {
  padding: 6px 10px 2px; font-size: .68rem; letter-spacing: .04em;
  color: var(--muted); text-transform: none;
}
/* 2.87.0 · 뒤따르는 묶음(「파일」) — 판의 줄과 한 줄기로 선다(감싼 상자는 자리를 안 먹는다) */
.ctx-menu .ctx-lazy { display: contents; }
.bolt { display: inline-flex; line-height: 0; }
.bolt.on { color: #2f9e44; }
.bolt.off { color: #e03131; }
#toast.ok { border-color: #2f9e44; }
#toast.bad { border-color: #e03131; }

/* ↻ 다시 받기 (HQ [요청] 09-03) — 도는 동안 한 바퀴 */
.refresh-wrap { display: inline-flex; gap: 6px; align-items: center; }
.refresh-stamp { font-size: .7rem; white-space: nowrap; }
.refresh-btn.spin .ic { animation: spin1 .6s linear; }
/* ⭐⭐ **전 화면 같은 크기** (발주 09-13 19시). ⚠ 머리줄마다 단추 옷이 다르다 — `.panel-head.tight
   .panel-actions button` 이 안쪽 여백·글자 크기를 바꿔서, 같은 단추가 컷리스트와 상세에서 **크기가 갈렸다.**
   그래서 폭·높이를 박고 그 규칙들보다 높은 자리(0,4,1)에 둔다. 천체 만들기(`celestial/screen.css`)도 같은 값이다. */
.panel-head .panel-actions button.refresh-btn.refresh-btn {
  width: 28px; height: 26px; padding: 0; flex: none; font-size: 15px; line-height: 1;
}
@keyframes spin1 { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* ⭐⭐ 태스크 없는 단계 칸 = 빈 칸 ([덧]1 · 2.90.0) — 글자·네모 0 · 올리면 옅게 「+ 태스크」(글자는 여기 `::before` 가 그린다 · 칸 글자는 빈 채) */
/* ⚠ 칸에 `position: relative` 를 주지 마라 — 표 칸이 겉 그림자(단계 색 양옆 선)를 둥글게 깎아 빈 칸마다 괄호 모양이 섰다(09-14 실측) */
td.taskcell.no-task { color: transparent; }
td.taskcell.no-task .step-add-hint {
  visibility: hidden; background: none; border: 0; padding: 0 .35rem; margin: 0; min-height: 0; height: auto;
  font: inherit; font-size: .74rem; color: var(--muted); cursor: pointer; border-radius: 4px; line-height: 1.2;
}
td.taskcell.no-task .step-add-hint::before { content: "+ 태스크"; opacity: .7; white-space: nowrap; }
td.taskcell.no-task:hover .step-add-hint,
td.taskcell.no-task .step-add-hint:focus-visible { visibility: visible; }
td.taskcell.no-task .step-add-hint:hover { background: color-mix(in srgb, currentColor 10%, transparent); color: var(--fg); }
td.taskcell.no-task .step-add-hint:hover::before { opacity: 1; }
/* 같은 단계 태스크 둘 이상 (103) — 칸 안 작은 개수 */
td.taskcell .tc-more { font-size: .68rem; color: var(--muted); margin-left: .15rem; vertical-align: super; }

/* 단계 붙이기 — 누른 줄 · 도는 동안 잠김 · 묻는 창 (HQ [발주] 09-14 17시 반 · 2.90.0) */
.seg-pop.busy { cursor: wait; }
.seg-pop.busy button, .seg-pop.busy input, .seg-pop.busy select { cursor: wait; }
.seg-pop.busy .dict-item:not(.pressing), .seg-pop.busy .row, .seg-pop.busy .make-new, .seg-pop.busy .hint { opacity: .45; }
.seg-pop .dict-item.pressing, .seg-pop button.pressing {
  background: color-mix(in srgb, var(--accent) 22%, transparent); outline: 1.5px solid var(--accent); opacity: 1;
}
.seg-pop.busy h4 { color: var(--accent); }
/* ⭐ 2.92.0 · 태스크 삭제 묻는 창 (HQ [발주] 09-14 18시 「상세 둘」 ②) — 덮개·카드·고르는 줄은 있는 옷을 입는다 */
.task-del-hold { z-index: 120; }
.task-del-card { width: min(34rem, calc(100vw - 2.4rem)); }
.task-del-card .ask-btns { gap: .6rem; align-items: center; margin-top: .6rem; }
.task-del-card .ask-btns .spacer { flex: 1; }
.task-del-card.busy { cursor: progress; }
.task-del-pick-move.on { border-color: var(--accent); }
.task-del-move { display: flex; flex-direction: column; gap: .4rem; padding: .2rem .2rem .4rem .8rem;
  border-left: 3px solid var(--accent); }
.task-del-card [hidden] { display: none !important; }
.task-del-search { width: 100%; }
.task-del-list { display: flex; flex-direction: column; gap: 2px; max-height: 15rem; overflow-y: auto;
  border: 1px solid var(--line); border-radius: 8px; padding: 3px; }
.task-del-row { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left;
  padding: .35rem .5rem; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--fg); }
.task-del-row:hover:not(:disabled) { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.task-del-row.on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
.task-del-row .muted { font-size: .82rem; flex: 1; }
.task-del-msg { margin: .4rem 0 0; font-size: .88rem; }
.task-del-msg.bad { color: var(--st-retake, #e5533d); }
.task-del-msg.wait { color: var(--muted); }
.attach-ask { z-index: 70; max-width: 30rem; }
.attach-ask .ask-btns { gap: .6rem; }
.attach-ask .ask-btns .spacer { flex: 1; }

/* 단계 붙이기 — 사전에서 고르는 자리 (링고 09-03 §2) */
.dict-pick { display: grid; gap: 2px; max-height: 320px; overflow: auto; margin: 6px 0; }
.dict-item {
  display: grid; grid-template-columns: 10px 1fr auto auto; gap: 8px; align-items: center;
  background: none; border: 0; color: inherit; font: inherit; text-align: left;
  padding: 4px 6px; border-radius: 4px; cursor: pointer;
}
.dict-item:hover:not(.off) { background: color-mix(in srgb, currentColor 10%, transparent); }
.dict-item.off { opacity: .4; cursor: default; }
.dict-item.has { opacity: .6; }                    /* 다 가짐 — 누르면 묻는다 (2.90.0) */
.dict-item code { font-size: .72rem; color: var(--muted); }
.make-new { border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
            margin-top: 6px; padding-top: 6px; }

/* 줄 진행률 (링고 09-03 §8) — 상태 점 옆에 작게 */
.prog { font-size: .72rem; color: var(--muted); margin-left: 6px; white-space: nowrap; }
.prog.full { color: var(--st-done, #2f9e44); }

/* 에셋 목록의 종류 단추 줄 (링고 2026-09-04) — 거르개 서랍이 접혀도 안 묻히게 **밖**에 산다 */
.kindbar { display: flex; align-items: center; gap: 6px; margin: 0 0 6px; }
/* 머리줄 안에 서는 알약 줄(타이틀 탭 · 094) — 제목 옆에 붙으므로 아래 여백을 뺀다 */
.panel-head .kindbar { margin: 0; }
.kindbar.hidden { display: none; }
.kindbar .tagchip { font-family: ui-monospace, Consolas, monospace; letter-spacing: .02em; }

/* 큰 「＋ 추가」 (링고 2026-09-04 — 작은 `+` 를 한참 찾았다). 머리줄에서 안 잘리게 flex 고정 */
.addbtn { flex: none; white-space: nowrap; font-weight: 700; }

/* 복사 판 — 겹치는 코드는 **누르기 전에** 빨갛게 (HQ [요청] 09-04 §2) */
input.cell.bad { border-color: var(--st-retake); }
.hint.bad { color: var(--st-retake); }

/* ── 탭 배치 모드 · ≡ 메뉴 · ⊞ 앱 판 (링고 [결정] 2026-09-04) ────────────── */
/* ⚠ 배치 중에는 **꺼 둔 탭도 보인다** — 안 보이면 다시 켤 자리가 없다 */
/* ⭐⭐ 손잡이는 **탭 밑 얇은 줄**(링고 09-14 · 2.84.0) — 탭 이름 옆에는 아무것도 안 붙는다.
   ⚠ 탭이 좁으면(「UI」) ◀◉▶ 셋이 그 폭에 안 들어간다 → 수정 중에만 탭 최소 폭을 준다. */
body.tab-arrange nav .tab { min-width: 3.9rem; }
body.tab-arrange nav .tab.tab-off { opacity: .45; }
/* ⚠ `flex-wrap: wrap` 으로 줄을 내리면 안 된다 — 줄바꿈 판정은 탭 줄의 **안 줄어든 폭**으로 해서
   탭 줄이 통째로 둘째 줄로 떨어졌다(09-14 첫 실측). 머리 아래 여백을 줄 키만큼 늘리고 그 자리에 앉힌다. */
body.tab-arrange header.topbar { padding-bottom: 1.6rem; }
/* ⚠ 탭 최소 폭만큼 탭 줄이 넓어지면 머리 오른쪽(이름·판·로그아웃)이 눌려 두 줄로 접혔다(09-14 실측) —
   수정 중에는 그 덩어리를 안 누르고 탭 줄이 흐른다 */
body.tab-arrange header.topbar .right { flex: none; }
.tab-arrange-row {
  position: absolute; left: 0; right: 0; bottom: 0; height: 1.45rem;
  border-top: 1px dashed color-mix(in srgb, currentColor 14%, transparent);
}
.arrange-lane { position: absolute; top: 0; bottom: 0; overflow: hidden; }
.tab-tools {
  position: absolute; top: 0; bottom: 0; display: flex; gap: 1px;
  align-items: center; justify-content: center;
}
.tab-tools .linkish { padding: 0 3px; font-size: .8rem; line-height: 1; text-decoration: none; }
.tab-tools .linkish:disabled { opacity: .3; }
.tab-tools .linkish.off { color: var(--muted); }
.tab-tools .box-pad { display: inline-block; width: 1rem; }
/* ⚠ 「기본값으로 · 끝」은 줄 **오른쪽 끝** — 탭 줄 스크롤 밖이라 흐르지 않는다(09-04 실측: 탭 줄에
   두면 탭이 많을 때 화면 밖으로 밀려 나갈 길이 사라졌다). 로그아웃 옆에는 안 둔다(09-14). */
.arrange-end {
  position: absolute; right: 1.2rem; top: 0; bottom: 0;
  display: flex; align-items: center; gap: 10px; padding-left: 10px; background: var(--panel);
}
.arrange-end .primary.small { padding: .05rem .8rem; font-size: .82rem; line-height: 1.2; }
.arrange-end .ghost { font-size: .82rem; }

/* ≡ 는 폰의 메인 메뉴다 — 큰 글씨 · 한 열 · 화살표·체크칸 없음 */
.ctx-menu.big-menu { min-width: 220px; }
.big-menu .menu-big {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  width: 100%; padding: .55rem .7rem; font-size: 1rem; text-align: left;
  background: none; border: 0; color: inherit; cursor: pointer; border-radius: 6px;
}
.big-menu .menu-big:hover:not(:disabled) { background: var(--panel); }
.big-menu .menu-big.on { font-weight: 700; cursor: default; }

/* ⊞ 앱 판 — 격자 · 아이콘 + 이름 */
/* 2.108.0 · 에이전트 머리 한 줄 — 누구로 로그인됐나 (「링고로 로그인됨 · 로그아웃」 / 「코즈모티 로그인」) */
.hand-who-mount:not(:empty) { margin: -.2rem 0 .6rem; }
.hand-who-line { display: flex; align-items: center; gap: 2px; font-size: .85rem; }
.hand-who-line .hand-who { font-weight: 600; }
.apps-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
.app-tile {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: .8rem .5rem; border: 1px solid var(--line); border-radius: 10px;
  background: none; color: inherit; cursor: pointer; font-size: .85rem; text-align: center;
}
.app-tile:hover:not(:disabled) { border-color: var(--accent); }
/* ⚠ 아직 안 선 것은 **회색으로 두고 왜 회색인지 적는다** — 「없다」와 「아직」은 다르다 */
.app-tile.off { opacity: .5; cursor: default; }
.app-tile .app-ic { font-size: 1.4rem; line-height: 1; }
/* ⭐ AR 메이커 「켜기」 (09-15) — 꺼져 있으면 타일 안에 작은 단추 꼴 한 조각 · 켜는 중이면 남은 초 */
.app-tile .ar-start {
  font-size: .75rem; padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--accent); color: var(--accent);
}
.app-tile .ar-start:empty { display: none; }
.app-tile.ar-tile:disabled:not(.off) { cursor: progress; }
.apps-card .ar-start-note:empty { display: none; }
.apps-card .ar-start-note { margin: 8px 0 0; }
/* 2.132.0 · 캐러셀 타일 — 살았나 점 · 꺼짐 한 줄 */
.app-tile .carousel-dot { font-size: 11px; opacity: .75; }
.apps-card .carousel-note:empty { display: none; }
.apps-card .carousel-note { margin: 8px 0 0; }

/* ⭐ 앱 아이콘 일곱 ([요청] 09-04) — 모양은 파일에서, **색은 글자색**이 칠한다.
   ⚠ `<img>` 로 걸면 파일 안의 `currentColor` 가 죽어서 어두운 판에서 검게 뭉갠다.
     마스크로 걸면 한 벌로 두 테마를 다 쓴다. */
.ic-app { display: inline-block; background: currentColor; }
.app-tile .ic-app { width: 32px; height: 32px; }   /* 앱 판은 크게 */
.ic-app { width: 20px; height: 20px; }             /* 메뉴 줄은 글자에 맞춰 */
/* ⚠ 판이 화면 밖으로 나가지 않게 — 격자는 좁아지면 줄을 접는다 */
.apps-card { max-width: min(560px, calc(100vw - 32px)); }
/* 제목 옆에 붙는 단추 — `space-between` 이 오른쪽 끝으로 밀지 못하게 */
.mr-auto { margin-right: auto; }

/* ⭐ 어노테이션 — 버전 위에 겹쳐 그리는 자국 (M4.5 · 092).
   ⚠ 그리는 층은 **그림 위에 얹힌 SVG** 하나다 — 원본 `img` 는 그대로 둔다. */
.shot-wrap { position: relative; display: inline-block; max-width: 100%; }
.shot-wrap .anno-layer {
  position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;
}
/* 그리는 동안에는 손이 그림을 끌지 않게 (모바일에서 판이 밀리는 것을 막는다) */
.shot-wrap.drawing { cursor: crosshair; touch-action: none; }
.shot-wrap.drawing img { user-select: none; -webkit-user-drag: none; }
/* ⚠⚠ 영상 위에 그릴 때는 **영상이 손을 안 받게** 한다 — 안 그러면 재생 컨트롤이
   손짓을 먼저 먹어서 «그려지지 않는다»가 된다(그리기를 켜면 재생은 이미 멈춘다). */
.shot-wrap.drawing video { pointer-events: none; }
.anno-bar { align-items: center; gap: 6px; margin: 6px 0; flex-wrap: wrap; }
.anno-tools { display: inline-flex; gap: 4px; }
/* 에이전트 「켜기」 줄 — 까닭 · 단추 · (10초 뒤) 안내. 빈 까닭(에이전트 상자)은 자리를 안 먹는다 */
.hand-start-row { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; margin: 10px 0 0; max-width: 100%; }
.hand-start-row > * { max-width: 100%; margin: 0; white-space: normal; overflow-wrap: anywhere; }
.hand-start-row .hand-start { white-space: nowrap; flex: none; }
.hand-start-row .hand-start-note { line-height: 1.45; }
.hand-start-row .hand-start-note:empty { display: none; }
/* 고른 줄이 있을 때 머리줄에 서는 옮기기·지우기 (09-06) */
.sel-bar { display: inline-flex; align-items: center; gap: 6px; margin-right: 6px; }
/* 연결 칸 (093) */
.links-box { margin: 10px 0; }
.link-list { display: flex; flex-direction: column; gap: 4px; }
.link-row { display: flex; align-items: center; gap: 8px; }
.link-row .chip { font-size: .75rem; }
.link-form { align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.link-form input[type=text]:first-of-type { min-width: 18rem; }
.title-add .bulk-line input[type=date] { width: 10rem; }
.hand-start-row .hint:empty { display: none; }
.anno-tools.hidden { display: none; }
.shot-wrap.erasing { cursor: cell; }
/* 스크러빙하다 건너뛴 프레임의 자국 — 흐리게 잠깐 (paintAnnotations 가 700ms 뒤 지운다) */
.anno-layer .anno-ghost { opacity: .45; }
.anno-dot {
  width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--line);
  padding: 0; cursor: pointer;
}

/* ⭐ 스크리닝룸 (M4.5) — 감독이 줄지어 보고 그 자리에서 판정하는 큰 판.
   ⚠ 나가는 길(닫기·Esc)을 늘 보이게 둔다 — 큰 판은 갇힌 느낌을 주기 쉽다. */
.busy-hold.screening { align-items: stretch; }
/* 2.109.0 · 「적던 내용이 있습니다 — 닫을까요?」 — 어느 창(판·작은 창) 위에도 선다 */
.busy-hold.draft-ask-hold { z-index: 400; }
.ask-card.draft-ask { min-width: 22rem; }
.screening-card {
  display: flex; flex-direction: column; gap: 8px;
  width: min(1400px, 96vw); height: min(92vh, 1000px); margin: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 12px; padding: 12px;
}
.screening-head, .screening-foot { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.screening-stage { flex: 1; overflow: auto; display: flex; }
.screening-stage .viewer { flex: 1; }
.screening-meta { flex: 1; min-width: 200px; }

/* ⭐ 새 판 알림 (2.30.0) — 「Ctrl+F5 하세요」를 사람에게 안 시킨다.
   ⚠ 스스로 새로 고치지 않는다: 사람이 무언가 적는 중일 수 있다. 말하고 단추를 준다. */
.newver-bar {
  position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 10px; z-index: 60;
  background: var(--panel); border: 1px solid var(--accent); border-radius: 10px;
  padding: 8px 12px; box-shadow: 0 6px 20px rgba(0,0,0,.35);
}

/* ==========================================================================
   산출물 판 — 한 페이지 (발주 SPEC_web_산출물-판… + HQ [결정] 09-06 17:05)
   ⭐ 탭이 없다: 구획이 위에서 아래로 선다. 머리줄을 누르면 접힌다(기본 펼침).
   ========================================================================== */
.ep-onepage { display: flex; flex-direction: column; gap: .8rem; }
.ep-sec { border-top: 1px solid var(--line); padding-top: .5rem; }
.ep-sec-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.ep-sec-title { display: inline-flex; align-items: center; gap: .35rem; font-size: .95rem; }
.fold-arrow { color: var(--muted); font-size: .8rem; }

/* 표 두 칸 — 항목 · 상태(점 + 파일 이름 + 첫 줄). ⛔ 「있다/없다」 글자는 안 쓴다.

   ⭐⭐ **v2 — 한 줄 높이** (발주 §② · 허브 참고 그림 05 · 링고: *"적은 공간에 많은 정보"*).
   ⚠⚠ **줄이 두 줄이 된 범인은 `flex-wrap: wrap` 이었다.** 파일 이름과 첫 줄 미리보기가
     한 칸 안에 있는데, 자리가 모자라면 미리보기가 **아랫줄로 내려갔다** — 그래서 열두 줄이
     스물넉 줄이 됐다. 이제 안 내려가고 **말줄임(…)** 으로 끊는다.
     ⛔ `flex-wrap: wrap` 으로 되돌리지 마라. 그 한 줄이 이 판의 밀도를 통째로 정한다. */
.deliv-cell {
  display: flex; align-items: center; gap: .45rem;
  flex-wrap: nowrap; min-width: 0;
}
.deliv-dot {
  width: .6rem; height: .6rem; border-radius: 50%; flex: none;
  display: inline-block; background: var(--muted);
}
.deliv-dot.green { background: var(--ok, #4ea172); }
.deliv-dot.gray { background: color-mix(in srgb, var(--muted) 45%, transparent); }
.deliv-dot.yellow { background: #d8a038; }
/* 이름은 잘 안 줄인다(끝의 `_kr.srt` 가 그 줄의 뜻이다) · 미리보기가 먼저 줄어든다 */
.deliv-name {
  font-family: ui-monospace, Consolas, monospace; font-size: .82rem;
  flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.deliv-preview {
  color: var(--muted); font-size: .82rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; flex: 1 1 0; min-width: 0;
}
/* 경로는 켠 사람에게만 · 제 줄에 선다(한 줄 규칙의 유일한 예외다 — 스스로 켠 것이니까) */
.deliv-cell .origin-path { flex: 1 0 100%; font-size: .76rem; }

/* ⭐ 표 아래 단추 — **격자 큰 단추** (발주 §② · 허브 참고 그림 05).
   ⚠⚠ **허브가 두 칸인 것은 그 판이 좁아서다**(610px). 코즈모티의 산출물 판은 한 단일 때
     1000px 가 넘는데, 거기서 두 칸이면 단추 하나가 470px 가 된다 — 그건 「빽빽」이 아니라
     **가로 낭비**다(발주가 없애라는 바로 그것). 그래서 **칸 수를 판 너비가 정한다**:
     좁으면(두 단 모드·폰) 허브처럼 두 칸, 넓으면 서너 칸으로 줄이 줄어든다.
   ⭐ 최소 너비 **13rem** 은 재서 고른 값이다: 허브 폭(600px)에서 정확히 **두 칸**이 되고,
     한 단 판(1000px 남짓)에서는 네 칸이 되어 열두 단추가 넉 줄에서 두 줄로 준다. */
.deliv-copybar, .deliv-folders {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: .3rem; margin: .35rem 0 0;
}
.deliv-copybar > button, .deliv-folders > button {
  width: 100%; padding: .32rem .6rem; font-size: .88rem;
}
@media (max-width: 420px) {
  .deliv-copybar, .deliv-folders { grid-template-columns: 1fr; }
}
.ep-sec-toggle { margin-left: auto; font-size: .82rem; }
.ep-sec-prefs, .ep-sec-publish { font-size: .82rem; }
/* ⭐ 2.117.0 · 폴더 단추 — **폴더 줄 밑 작은 ghost 한 줄** (HQ [발주] 09-15 ③④).
   ⚠ 격자가 아니다: 다섯이 화면 폭을 나눠 먹던 자리라, 이제 글자 폭만큼만 서고 좁으면 줄이 바뀐다. */
.ep-folderbar { display: flex; flex-wrap: wrap; gap: .25rem; margin: .1rem 0 .2rem; }

/* 112 · 설정 「결과물 품목」·「앱 판」 표 — 폴더 뿌리 표와 **같은 옷**(`folder-roots-wrap` 을 같이 쓴다) */
.deliv-items td, .app-tiles td { vertical-align: middle; }
.deliv-items-on { text-align: center; }
.deliv-items-name code, .app-tiles code { font-size: .72rem; }
.deliv-items th:not(:first-child) { text-align: center; }

/* 편집 창 — 스크리닝룸과 **같은 덮개**(`busy-hold`)를 쓴다. 바깥을 눌러도 안 닫힌다. */
.deliv-edit { padding: 2.5vh 2.5vw; }
.deliv-card {
  display: flex; flex-direction: column; gap: .6rem;
  width: min(1200px, 95vw); height: min(88vh, 900px);
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: .9rem 1rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}
.deliv-head-row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.deliv-head-row b { font-family: ui-monospace, Consolas, monospace; }
.deliv-note { font-size: .82rem; }
/* ⭐⭐ 2.117.0 · **어디가 칸인지 보이게** (HQ [발주] 09-15 ④ · 링고: *"산출물 필드에서 자막 선택 시
   나오는 프레임은 색이 좀 더 달라야 한다. 10% 정도 밝게."*)
   ⚠ 여태 칸 바탕이 `--bg` 였다 — 밝은 화면에서 창 바탕(`--panel` #fafafc)과 거의 같은 흰색이라
     **테두리 한 줄로만** 갈렸다. 둘을 나란히 놓으면 어디가 칸인지 안 보인다.
   ⭐ 이제 창 바탕에서 **한 단씩 띄운다**: 안 고른 칸 +4% · **고른(포커스) 칸 +10%** · 테두리도 한 단.
     `--lift` 가 방향이다(다크는 밝게 · 라이트는 진하게) — 두 화면에서 같은 뜻이 된다. */
.deliv-text {
  flex: 1; width: 100%; min-height: 0; resize: none;
  font-family: ui-monospace, Consolas, monospace; font-size: .86rem; line-height: 1.5;
  background: color-mix(in srgb, var(--lift) 4%, var(--panel));
  color: var(--fg); border: 1px solid var(--line); border-radius: 8px;
  padding: .6rem .7rem;
}
.deliv-text:focus {
  background: color-mix(in srgb, var(--lift) 10%, var(--panel));
  border-color: color-mix(in srgb, var(--lift) 26%, var(--line));
  outline: none;
}
/* 원본 칸은 읽기만 하는 칸이라 한 단 더 가라앉는다(고를 수는 있다 — 복사하려고 끈다) */
.deliv-text.src { background: color-mix(in srgb, var(--lift) 2%, var(--panel)); }
.deliv-two { flex: 1; display: flex; gap: .7rem; min-height: 0; }
.deliv-col { flex: 1; display: flex; flex-direction: column; gap: .3rem; min-width: 0; }
.deliv-col .muted { font-size: .8rem; }
.deliv-foot { display: flex; align-items: center; gap: .5rem; }
.deliv-foot .spacer { flex: 1; }

/* 두 단 — 태스크 표와 산출물을 좌우로 ([결정] 09-06 17:05 · 스위치를 켠 사람에게만).
   ⚠ 좁은 화면에서는 **도로 한 단**이다: 폰에서 두 단은 못 읽는다. */
.ep-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; }
@media (max-width: 1200px) { .ep-cols { grid-template-columns: 1fr; } }

/* ==========================================================================
   우클릭 메뉴 — **한 줄 + 오른쪽 펼침** (HQ [발주] 09-06 저녁 · 「읽을 것 적게」)
   ⚠ 펼친 목록은 메뉴 **안에** 산다 — 몸통에 붙이면 메뉴가 닫힐 때 조각이 남는다.
   ========================================================================== */
.ctx-subwrap { position: relative; }
.ctx-item.has-sub .ctx-arrow { margin-left: auto; color: var(--muted); }
.ctx-sub {
  position: absolute; left: 100%; top: -4px; min-width: 160px; z-index: 1;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 4px; box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
}
.ctx-sub.left { left: auto; right: 100%; }
.ctx-sub.hidden { display: none; }
/* 지금 값에 점 하나 — 자리는 늘 차지한다(줄이 들쭉날쭉하면 눈이 헤맨다) */
.sub-dot {
  width: .45rem; height: .45rem; border-radius: 50%; flex: none; margin-right: .1rem;
  display: inline-block; background: transparent;
}
.sub-dot.on { background: var(--accent); }

/* 우클릭 펼침 — 점 · 아이콘 · 낱말 (발주 09-06 밤: 어디에나 같은 아이콘) */
.ctx-sub .ctx-item i.sicon { margin-right: .1rem; }

/* 영상 올리기 — 줄마다 진행 막대 (발주 SPEC_cutboard_영상-여러-개-올리기 §5).
   ⚠ 막대는 **자리를 늘 차지한다** — 올리는 동안만 생기면 표가 들썩여서 어느 줄을
   보고 있었는지 놓친다. 끝난 줄은 초록 점 하나로 조용해진다. */
.bar {
  display: flex; align-items: center; gap: .3rem;
  min-width: 6rem; height: 1rem;
  background: var(--line); border-radius: .5rem; overflow: hidden;
}
.bar-fill {
  height: 100%; background: var(--accent);
  transition: width .15s linear;
}
.bar .sub { padding-right: .3rem; }
.ok-dot { color: var(--ok, #2e7d32); }
/* ⚠ 「1MB」가 「1M / B」로 갈려 있었다 (캡처를 눈으로 보고 잡았다) — 숫자 칸은 안 접는다 */
.nowrap { white-space: nowrap; }

/* 올리는 중 띠 — 판을 닫고 다른 일을 해도 진행이 보인다
   (링고 2026-09-11: "업로드 할 때 대기열은 플로팅창으로 올려놔야 내가 다른 일을 할 수 있을 듯").
   ⚠ 오른쪽 아래에 **작게** 둔다. 크면 그것 때문에 다른 일을 못 한다 — 띠를 둔 뜻이 없어진다. */
.upbar {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 90;
  min-width: 15rem; max-width: 22rem;
  padding: .5rem .7rem; border-radius: .5rem;
  background: var(--panel); color: var(--fg);
  border: 1px solid var(--line);
  box-shadow: 0 .4rem 1.2rem rgba(0, 0, 0, .18);
  font-size: .85rem;
}
.upbar-head { display: flex; align-items: center; gap: .5rem; }
.upbar-head b { flex: 1; }
.upbar-head .linkish, .upbar-head .goto { padding: 0; }
.upbar-line { display: flex; align-items: center; gap: .4rem; margin-top: .35rem; }
.upbar-line .muted {
  flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.upbar-line .bar { width: 5rem; flex: none; }
.upbar .uprow { margin-top: .35rem; }

/* ⭐⭐ 올리기 진행 한 부품 (HQ [발주] 09-14 17시 40분 · 2.91.0) — app.js `upRowNode`·`upTotalNode`.
   링고: "영상 업로드 시 업데이트 되는 중인 bar 가 보여야겠다. 마냥 기다리기 힘드네."
   막대 색 넷: 보내는 중 = 강조색 · 서버가 %를 주면 민트 · 못 주면 흐르는 줄무늬 · 걸리면 빨강.
   ⚠ 막대는 **굵게**(8px) 둔다 — 창 구석에서도 움직이는 것이 보여야 「되는 건가」가 안 나온다. */
.up-list { display: flex; flex-direction: column; gap: .45rem; margin-top: .4rem; }
.up-list:empty { display: none; }
.uprow { display: flex; flex-direction: column; gap: .2rem; min-width: 0; font-size: .84rem; }
.uprow .up-head { display: flex; align-items: baseline; gap: .5rem; min-width: 0; }
.uprow .up-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.up-track {
  position: relative; height: 8px; border-radius: 4px; overflow: hidden;
  background: color-mix(in srgb, var(--muted) 28%, transparent);
}
.up-fill { height: 100%; width: 0; background: var(--accent); border-radius: 4px; transition: width .2s linear; }
.up-track.enc .up-fill { background: var(--ok); }
.up-track.ok .up-fill { background: var(--ok); }
.up-track.bad .up-fill { background: var(--st-fix); }
.up-track.bad { background: color-mix(in srgb, var(--st-fix) 22%, transparent); }
/* 서버가 %를 못 주는 단계 — %를 지어내지 않고 흐르는 줄무늬로 «돌고 있다» 만 말한다 */
.up-track.indet .up-fill {
  width: 100% !important;
  background: repeating-linear-gradient(-45deg,
    color-mix(in srgb, var(--ok) 75%, transparent) 0 8px,
    color-mix(in srgb, var(--ok) 30%, transparent) 8px 16px);
  background-size: 22.6px 100%;
  animation: up-flow 0.9s linear infinite;
}
@keyframes up-flow { to { background-position: 22.6px 0; } }
@media (prefers-reduced-motion: reduce) { .up-track.indet .up-fill { animation: none; } }
.uprow .up-text { display: flex; align-items: center; flex-wrap: wrap; gap: .35rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.uprow.up-send .up-text, .uprow.up-encode .up-text, .uprow.up-server .up-text { color: var(--fg); }
/* ⚠ 민트 글자는 밝은 판 흰 바탕에서 안 읽힌다(09-14 캡처) — 글자만 본문색 쪽으로 한 단 눌러 둔다(막대는 민트 그대로) */
.uprow.up-done .up-text { color: color-mix(in srgb, var(--ok) 55%, var(--fg)); font-weight: 600; }
.uprow .up-text.row-warn, .uprow.up-fail .up-text, .uprow.up-encfail .up-text { color: var(--st-fix); }
/* ⚠ 걸린 파일 몫이 있는 전체 줄 — 빨강을 다 채우면 「전부 실패」로 읽힌다. 옅게만 */
.uprow.total .up-track.bad .up-fill { background: color-mix(in srgb, var(--ok) 70%, var(--st-fix)); }
.uprow .up-retry { font-weight: 600; }
.uprow.total { padding: .35rem .5rem; border-radius: 6px; background: var(--sicon-bg); }
.uprow.total .up-track { height: 10px; }
.uprow.total .up-text b { font-weight: 600; color: var(--fg); }
.up-spin.busy-spin { width: .8rem; height: .8rem; border-width: 2px; flex: none; }
.up-total:empty { display: none; }
.up-total { margin-top: .4rem; }
/* 올리기 창 안 — 폼이 가로로 흐르는 줄(flex-wrap)이라 막대 자리는 한 줄을 통째로 쓴다 */
.upload-form .up-list, .upload-form .up-total, .upload-form .up-report { flex-basis: 100%; }
.up-pop { width: min(42rem, 94vw); }
.up-pop .up-list { max-height: 46vh; overflow-y: auto; padding-right: .2rem; }
.import-pop .folder-log .uprow { margin: .2rem 0 .3rem; }
/* 영상 올리기 표의 끝 칸 — 판 번호 + 막대 줄. 칸이 좁아 이름 머리는 뺀 줄(`compact`)을 쓴다 */
.up-cell { display: flex; flex-direction: column; gap: .15rem; min-width: 14rem; }
.folder-list td .uprow.compact { min-width: 14rem; }
.encode-live { display: inline-flex; align-items: center; gap: .3rem; }
/* 목록 썸네일 위 「처리 중」 딱지 — 끝나면 저절로 빠진다 */
.up-proc-wrap { position: relative; display: inline-block; line-height: 0; }
.up-proc {
  position: absolute; left: 2px; right: 2px; bottom: 2px;
  padding: 1px 4px; border-radius: 3px; line-height: 1.3;
  font-size: .64rem; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  background: color-mix(in srgb, var(--bg) 78%, transparent); color: var(--ok);
  pointer-events: none;
}
button.ghost.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 55%, transparent); }
button.linkish.danger, button.x.danger { color: var(--danger); }

/* 거르기 서랍의 갈래 알약 줄 — 회차 목록 바로 위 (링고 2026-09-11).
   ⚠ 회차 목록과 **붙여** 둔다. 떨어지면 「이 알약이 무엇을 거르나」가 안 보인다. */
.drawer-kinds { display: flex; flex-wrap: wrap; gap: .25rem; margin: .3rem 0 .35rem; }

/* 몇 줄씩 볼 것인가 — 20·50·100·전체 (발주 컷리스트 일곱 §7). 오른쪽 아래 한 줄.
   ⚠ 지금 값은 **눌린 것처럼** 보여야 한다 — 넷이 똑같이 생기면 어느 것이 지금인지 모른다. */
.pagesizes { display: inline-flex; gap: .15rem; }
.pagesizes button.on {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent);
}

/* 파이프라인 한 띠 (발주 컷리스트 일곱 §2 · 샷그리드 꼴).
   ⚠ 띠 안은 **사이 여백이 없다** — 열 사이 선을 지우고 바깥으로만 선을 세운다.
   ⛔ 「파이프라인」 묶음 머리 줄(`tr.band-head`)은 2.73.0 에서 걷었다 (HQ [발주] 09-13 17시 ① ·
     머리 칸 단계 색이 이미 말한다). */
/* 띠 안쪽 세로선을 지운다 — 나란히 선 단계 칸끼리는 붙어 보여야 한다 */
table.shot-table th.stepH + th.stepH,
table.shot-table td.taskcell + td.taskcell { border-left: 0; }

/* 왼쪽 고정 — 고르기·썸네일·코드 (발주 컷리스트 일곱 §2: *"컷 이름·썸네일 열은 왼쪽에 고정"*).
   띠가 넓어 가로로 밀 때, 지금 보는 줄이 어느 컷인지 늘 보여야 한다.
   ⚠ 폭은 `colgroup` 이 정한다 — 여기서 폭을 적지 않는다(두 자리가 다투면 칸이 튄다).
   ⚠ 고정된 칸은 **제 바탕을 들어야 한다** — 투명하면 밀려 오는 칸이 밑으로 비쳐 보인다. */
table.shot-table th[data-col-key="pick"],
table.shot-table td[data-col-key="pick"] { position: sticky; left: 0; z-index: 3; }
table.shot-table th[data-col-key="thumb"],
table.shot-table td[data-col-key="thumb"] { position: sticky; left: 46px; z-index: 3; }
table.shot-table th[data-col-key="code"],
table.shot-table td[data-col-key="code"] { position: sticky; left: calc(46px + var(--pin-thumb-w, 64px)); z-index: 3; }  /* 썸네일 칸 폭은 app.js 가 표에 넣는다(2.103.0 · 끌면 바뀐다) */
table.shot-table td[data-col-key="pick"],
table.shot-table td[data-col-key="thumb"],
table.shot-table td[data-col-key="code"] { background: var(--bg); }
table.shot-table tr.picked td[data-col-key="pick"],
table.shot-table tr.picked td[data-col-key="thumb"],
table.shot-table tr.picked td[data-col-key="code"] { background: var(--panel); }
table.shot-table thead th[data-col-key="pick"],
table.shot-table thead th[data-col-key="thumb"],
table.shot-table thead th[data-col-key="code"] { background: var(--bg); z-index: 4; }
/* ⚠ 위 층 4 는 `#shot-body … thead th`(아이디 무게 · 층 6)에 진다 — 가로로 밀 때 왼쪽 고정 머리 칸이 밀려오는 머리 칸 위에 서도록 같은 무게로 7 */
#shot-body table.shot-table thead th[data-col-key="pick"],
#shot-body table.shot-table thead th[data-col-key="thumb"],
#shot-body table.shot-table thead th[data-col-key="code"],
#asset-body table.shot-table thead th[data-col-key="pick"],
#asset-body table.shot-table thead th[data-col-key="thumb"],
#asset-body table.shot-table thead th[data-col-key="code"] { z-index: 7; }

/* ==========================================================================
   템플릿 손으로 적용 (SPEC_web 템플릿-손으로-적용 v1 · 2026-09-09)
   ⚠ 칸 안에서 바로 고른다 — 고르개가 아니라 **글자를 치는 칸**이다. 템플릿이
     열 개를 넘으면 고르개는 훑어야 하고, 링고가 적은 것은 *"이름 일부만 쳐도
     목록이 좁혀짐"* 이다.
   ========================================================================== */
.tpl-open {
  border: 1px solid transparent; background: none; color: inherit;
  font: inherit; padding: .1rem .35rem; border-radius: 6px; cursor: pointer;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tpl-open:hover { border-color: var(--line); background: var(--sicon-bg); }
.tpl-open.none { color: var(--muted); }

.tpl-combo { position: relative; display: block; min-width: 11rem; }
.tpl-combo-input {
  width: 100%; padding: .25rem .4rem; font: inherit;
  border: 1px solid var(--accent); border-radius: 6px;
  background: var(--panel); color: var(--fg);
}
/* ⚠ 표 칸 안에서 뜬다 — 칸이 잘리면 목록도 잘리므로 띄워서 그린다. */
.tpl-combo-menu {
  position: absolute; z-index: 60; left: 0; top: calc(100% + 2px);
  min-width: 20rem; max-width: 32rem; max-height: 17rem; overflow-y: auto;
  margin: 0; padding: .25rem; list-style: none;
  background: var(--panel); border: 1px solid var(--line); border-radius: 9px;
  box-shadow: 0 12px 30px rgba(0, 0, 0, .38);
}
/* ⭐ 2.95.0 · 몸통 층 — 표 스크롤 칸에 안 잘린다 · 자리는 app.js `templateCombo` 가 입력 칸에 맞춘다(아래가 모자라면 위로).
   ⚠ z-index 는 템플릿 적용 창 덮개(`.busy-hold` 100) 위 */
.tpl-combo-menu.floating { position: fixed; z-index: 120; top: 0; left: 0; }
.tpl-combo-menu.floating.up { box-shadow: 0 -12px 30px rgba(0, 0, 0, .38); }
.tpl-combo-row {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .32rem .5rem; border-radius: 6px; cursor: pointer;
}
.tpl-combo-row.on { background: var(--sicon-bg); }
.tpl-combo-row.new { border-top: 1px solid var(--line); margin-top: .2rem; padding-top: .42rem; }
/* 2.111.0 · 유형이 안 맞는 템플릿 — 숨기지 않고 흐리게 + 까닭(고를 수 없다) */
.tpl-combo-row.off { opacity: .5; cursor: not-allowed; }
.tpl-combo-row.off .tpl-combo-hint { font-style: italic; }
.tpl-combo-name { font-weight: 600; }
.anno-extras { display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap; }
.anno-extras.hidden { display: none; }
/* 2.201.2 · 다른 유형 템플릿 — 구분선 줄 + 회색 꼬리표(고를 수 있다) */
.tpl-combo-sep { padding: .38rem .5rem .16rem; margin-top: .2rem; border-top: 1px solid var(--line); font-size: .74rem; color: var(--muted); cursor: default; }
.tpl-combo-tag { align-self: flex-start; font-size: .7rem; color: var(--muted); border: 1px solid var(--line); border-radius: 999px; padding: 0 .4rem; }
.tpl-combo-hint { font-size: .78rem; color: var(--muted); }

/* 미리 보여 주는 창 — 줄마다 「이미 있음 / 새로 생김」 */
.ask-card.tpl-card { width: min(38rem, calc(100vw - 2.4rem)); }
.tpl-allbar { margin: .6rem 0 .2rem; gap: .4rem; align-items: center; }
.tpl-list {
  margin: .6rem 0 .2rem; max-height: 19rem; overflow-y: auto;
  border: 1px solid var(--line); border-radius: 9px;
}
.tpl-row {
  display: flex; align-items: center; gap: .55rem;
  padding: .38rem .6rem; border-bottom: 1px solid var(--line); font-size: .88rem;
}
.tpl-row:last-child { border-bottom: 0; }
.tpl-row.off { color: var(--muted); }
.tpl-step { font-weight: 600; min-width: 7rem; }
.tpl-have { color: var(--muted); }
.tpl-new { color: var(--ok); margin-left: auto; }
/* ⚠ 「하나 더 만들기」는 **아직**이다 — 회색으로 세우고 까닭을 곁말로 단다.
     줄을 아예 안 두면 사람은 없는 기능으로 읽는다. */
.tpl-pick { display: inline-flex; align-items: center; gap: .25rem; color: var(--muted); }
.tpl-pick.on { color: var(--fg); }
.tpl-pick.off { opacity: .55; }
.tpl-yet {
  font-size: .72rem; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 0 .4rem;
}

/* ==========================================================================
   설정 > 파이프라인 템플릿 — 두 칸 (SPEC_web 설정-템플릿-두-칸 v1 · 2026-09-10)
   ⚠ 왼쪽 260px 고정 · 오른쪽 나머지 (발주 §4). 좁은 창에서는 위아래로 쌓는다 —
     260px 를 접어 두면 고르는 자리가 사라진다.
   ========================================================================== */
/* ⭐⭐ 2.72.0 — 왼쪽 목록이 **격자 표**가 됐다 (HQ [발주] 09-13 ②). 표는 위 · 자세히 판은 아래로 쌓는다
     (단계 칸이 열 개 넘게 서면 260px 옆자리에 안 들어간다). 넘치면 표만 가로로 민다. */
.tpl-two { display: flex; flex-direction: column; gap: 1rem; align-items: stretch; }
.tpl-pane-grid { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.tpl-pane-grid .tpl-find { max-width: 22rem; }
.tpl-pane-grid .tpl-new-btn { width: auto; align-self: flex-start; }
.tpl-grid-wrap {
  overflow-x: auto; max-height: 60vh; overflow-y: auto;
  border: 1px solid var(--line); border-radius: 9px; background: var(--panel);
}
/* ⭐ 2.124.0 · 칸 폭은 `<colgroup>` 이 쥔다(끌기 · `s:` 열쇠) — 표 폭 = 칸 합(JS) · 넘치면 `.tpl-grid-wrap` 안에서만 가로로 */
.tpl-grid { border-collapse: collapse; table-layout: fixed; font-size: .82rem; }
.tpl-grid th .col-name { overflow: hidden; text-overflow: ellipsis; display: block; }
.tpl-viewbar { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.tpl-viewbar .muted { font-size: .78rem; }
.tpl-grid th, .tpl-grid td { border: 1px solid var(--line); padding: .3rem .45rem; vertical-align: middle; }
.tpl-grid thead th {
  position: sticky; top: 0; z-index: 1; background: var(--panel); color: var(--muted);
  font-weight: 600; font-size: .74rem; text-align: left; white-space: nowrap;
}
.tpl-grid thead th.tpl-step-h { text-align: center; }
.tpl-grid td.tpl-kind {
  font-weight: 700; white-space: nowrap; background: var(--sicon-bg); color: var(--fg);
  cursor: default; overflow: hidden;
}
.tpl-grid td.tpl-kind .tpl-grp-n { margin-left: .4rem; color: var(--muted); font-weight: 400; font-size: .74rem; }
.tpl-grid td.tpl-kind.drop-here { outline: 2px dashed var(--accent); outline-offset: -3px; }
.tpl-grid tr.tpl-item { cursor: pointer; }
.tpl-grid tr.tpl-item:hover td.tpl-name, .tpl-grid tr.tpl-item:hover td.tpl-made { background: var(--sicon-bg); }
/* 고른 줄 — 이름 칸에 강조색 안쪽 선 (칸 폭을 안 먹는다 · 09-13 함정) */
.tpl-grid tr.tpl-item.on td.tpl-name { box-shadow: inset 4px 0 0 var(--accent); background: var(--sicon-bg); }
.tpl-grid tr.tpl-item.dragging { opacity: .45; }
.tpl-grid td.tpl-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tpl-grid td.tpl-name .dot {
  display: inline-block; width: .6rem; height: .6rem; border-radius: 50%; margin-right: .45rem;
  vertical-align: middle;
}
/* ⭐⭐ 2.124.0 · 단계 칸 = **알약 + 사이 화살표** (HQ [발주] 09-15 ③④ · 링고: *"단계 사이에 예쁜 화살표"*)
   · 칸 좌우 3px 씩 = 알약 사이 틈 6px · 화살표는 그 틈에(색 위에 안 얹는다) · 옅기·둥글기는 계약 색 알약(`.cf-pill` 999px · 55%) 그대로
   · 단계 칸끼리는 세로 선이 없다 — 한 줄이 사슬로 읽힌다 · 인쇄·라이트 모드도 같은 칸(`--muted`) */
.tpl-grid td.tpl-step-cell {
  position: relative; text-align: center; line-height: 1.15; padding: .2rem 3px;
  border-left-color: transparent; border-right-color: transparent;
}
.tpl-grid td.tpl-step-cell .tpl-step-pill {
  display: block; border-radius: 999px; padding: .22rem .5rem; overflow: hidden;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.tpl-grid td.tpl-step-cell b { display: block; font-weight: 600; font-size: .8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tpl-grid td.tpl-step-cell small { display: block; font-size: .68rem; opacity: .85; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tpl-grid td.tpl-step-cell.none { background: transparent; }
.tpl-grid td.tpl-step-cell .tpl-arrow {
  position: absolute; top: 50%; right: -3px; width: 6px; height: 9px; margin-top: -4.5px; z-index: 1;
  background: color-mix(in srgb, var(--muted) 55%, transparent);
  clip-path: polygon(0 0, 100% 50%, 0 100%, 0 72%, 55% 50%, 0 28%);
  pointer-events: none;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.tpl-grid td.tpl-step-cell.can-color { cursor: pointer; }
.tpl-grid td.tpl-step-cell.can-color:hover .tpl-step-pill { box-shadow: 0 0 0 2px var(--accent); }
.tpl-color-pop .tpl-swatches { display: grid; grid-template-columns: repeat(6, 1.6rem); gap: .35rem; margin: .4rem 0; }
.tpl-color-pop .tpl-swatch {
  width: 1.6rem; height: 1.6rem; border-radius: 999px; border: 1px solid var(--line); padding: 0; cursor: pointer;
}
.tpl-color-pop .tpl-swatch.on { box-shadow: 0 0 0 2px var(--accent); }
.tpl-color-pop .tpl-swatch-own { width: 2.2rem; height: 1.5rem; padding: 0; vertical-align: middle; }
.tpl-grid td.tpl-made { color: var(--muted); white-space: nowrap; font-size: .76rem; }
.tpl-pane-right { flex: 1 1 auto; min-width: 0; }
.tpl-find {
  width: 100%; padding: .4rem .55rem; font: inherit;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); color: var(--fg);
}
/* ⛔ 2.72.0 — 옛 왼쪽 목록 규칙(`.tpl-pane-list` · `.tpl-grp` · `.tpl-item { display: grid }`)을 걷었다.
     `.tpl-item` 이름을 표 줄이 물려받아서, 남겨 두면 **줄(tr)이 격자 상자가 되어** 칸이 첫 열 안에 쌓였다
     (09-13 캡처로 봤다 · 칸 수를 재는 자는 다 초록이었다). 이름을 물려줄 때는 옛 규칙부터 센다. */
.tpl-item-name { white-space: nowrap; }
.pane-empty { padding: 1.6rem .4rem; text-align: center; }

@media (max-width: 900px) {
  .tpl-grid-wrap { max-height: 22rem; }
}

/* ⭐ 2.113.0 · 컷 「길이」 칸 — 입력칸(프레임)은 그대로, 잠겨 있을 때 그 위에 「3.2초 · 77F」 (HQ [발주] 09-16 0시 · `durationCell`)
   ⚠ 글은 누름을 안 가로챈다(`pointer-events: none`) — 두 번 눌러 고치기·줄 고르기·Tab 은 밑 입력칸이 받는다.
   ⚠ 최신 영상에서 온 길이는 흐리게 — 손으로 적은 길이와 눈으로 갈린다. */
td.len-cell { position: relative; white-space: nowrap; }
td.len-cell input.cell[readonly] { color: transparent; caret-color: transparent; }
td.len-cell input.cell[readonly]::placeholder { color: transparent; }
td.len-cell .len-text {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: flex-end;
  padding: 0 calc(.5rem + .35rem + 1px); pointer-events: none; overflow: hidden;
  font-variant-numeric: tabular-nums;
}
td.len-cell .len-text.from-video { color: var(--muted); }
td.len-cell input.cell:not([readonly]) + .len-text { display: none; }
.len-sum { white-space: nowrap; }
.col-menu .col-pick .len-mode-switch { margin-left: auto; padding: 0 1px; flex: none; }
.col-menu .col-pick .len-mode-switch button { padding: 0 .45rem; font-size: .76rem; line-height: 1.5; white-space: nowrap; flex: none; }

/* ⭐ 2.119.0 · 「필드 수정」 창 (HQ [발주] 09-16 ①) */
.seg-pop.field-edit-pop { min-width: 22rem; max-width: 30rem; }
.field-edit-row { display: flex; align-items: center; gap: .6rem; margin: .25rem 0; font-size: .88rem; }
.field-edit-row > span { flex: none; width: 3rem; color: var(--muted); }
.field-edit-row input, .field-edit-row select { flex: 1; min-width: 0; }
.field-edit-preview.bad { color: var(--st-retake); }
/* ⭐ 2.119.0 · 결과물 품목 ← 컷 연결 (HQ [발주] 09-16 ③) */
.deliv-link { display: inline-flex; align-items: center; gap: .45rem; }
.deliv-link-word { font-weight: 600; font-size: .82rem; color: var(--ok, #4ea172); white-space: nowrap; }
.deliv-cell .deliv-link-btn { margin-left: .6rem; font-size: .8rem; color: var(--muted); }
.deliv-cell .deliv-unlink-btn { margin-left: .4rem; font-size: .8rem; color: var(--muted); }
.deliv-cell .deliv-link-btn:hover, .deliv-cell .deliv-unlink-btn:hover { color: var(--link, var(--text)); }
.deliv-suggest button { white-space: nowrap; flex: none; }
.seg-pop.deliv-link-pop { min-width: 24rem; max-width: 34rem; }
.deliv-suggest { display: flex; align-items: center; gap: .5rem; padding: .4rem .5rem; margin: .2rem 0 .4rem;
  border-radius: 6px; background: color-mix(in srgb, var(--ok, #4ea172) 12%, transparent); font-size: .86rem; }
.deliv-cands { max-height: 16rem; overflow: auto; display: flex; flex-direction: column; gap: 2px; }
.deliv-cand { display: flex; align-items: center; gap: .35rem; padding: .2rem .3rem; font-size: .86rem; border-radius: 4px; }
.deliv-cand.same { background: color-mix(in srgb, var(--ok, #4ea172) 8%, transparent); }
.deliv-cand.now { outline: 1px solid var(--ok, #4ea172); }
.deliv-cand .deliv-cand-ok { color: var(--ok, #4ea172); font-size: .78rem; }
.deliv-cand .deliv-cand-file { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ep-folderbar button .deliv-dot { margin-right: .3rem; }

/* ⭐ 114 · 폴더 약도 — 단추의 「만들까요?」·「어느 폴더인가요?」·「이렇게 이을까요?」 창 · 설정 표 · 초대 코드 기한 */
.seg-pop.folder-place-pop { min-width: 22rem; max-width: 40rem; }
.seg-pop.folder-guess-pop { max-width: 48rem; }
.folder-place-pop h4 { margin: 0 0 .35rem; }
.folder-place-pop .origin-path { display: block; margin: .2rem 0 .4rem; word-break: break-all; }
.folder-ask-group { margin: .35rem 0; }
.folder-ask-names { display: flex; flex-wrap: wrap; gap: .25rem; margin-top: .2rem; max-height: 12rem; overflow: auto; }
.folder-ask-name.likely { border-color: var(--accent); }
.folder-ask-make { gap: .3rem; margin: .4rem 0; }
.folder-ask-new { min-width: 12rem; }
.folder-guess-path { width: 100%; min-width: 16rem; }
table.folder-map th .spacer { display: inline-block; width: .8rem; }
table.folder-map .folder-map-root { width: 22rem; max-width: 100%; margin-right: .3rem; }
.folder-map-path { width: 100%; min-width: 18rem; }
.folder-map-sample .deliv-dot, .folder-cell .deliv-dot { margin-right: .2rem; }
.deliv-folder-btn .deliv-dot { margin-right: .2rem; }
.deliv-cell .deliv-folder-btn { margin-left: .4rem; }
.ep-folder-more { align-self: center; }
.invite-left.bad { color: var(--bad, #c0504d); }
.folder-line .folder-guess { margin-right: .7rem; }
.folder-ask-make button { white-space: nowrap; }

/* ⭐ 2.184.0 · 공통 창 한 벌 — `modal-back`(화면을 덮는 뒤판) + `modal-card`(가운데 · 넘치면 안에서 스크롤)
   (HQ [덧] 09-28 · 링고: 「가져오기 하면 늘 같은 문제다. 목록이 길면 확인 단추가 안 보인다」).
   ⚠ 여태 이 두 이름의 일반 CSS 가 없어 스토리 창(가져오기·새 글·판 표)이 뒤판 없이 **본문 끝에 붙어** 나왔다.
   ⭐ 창 맨 아래 단추 줄(`step-row`·`modal-foot`)은 창 바닥에 붙어 늘 보인다(sticky). 쓰는 창: 스토리 · 계정 지우기 · 2단계 인증 · 설명서. */
.modal-back {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem; box-sizing: border-box;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(2px);
}
.modal-card {
  background: var(--panel); color: var(--fg); border: 1px solid var(--line); border-radius: 10px;
  padding: 1.1rem 1.4rem 0; box-shadow: 0 10px 30px rgba(0, 0, 0, .35); box-sizing: border-box;
  width: min(34rem, 94vw); max-width: 94vw; max-height: calc(100vh - 2rem); overflow: auto;
  display: flex; flex-direction: column; gap: .5rem;
}
.modal-card > * { flex: none; }
.modal-card > h3 { margin: 0 0 .2rem; }
.modal-card > .step-row:last-child, .modal-card > .modal-foot {
  position: sticky; bottom: 0; z-index: 2; margin-top: auto;
  background: var(--panel); border-top: 1px solid var(--line); padding: .6rem 0 .9rem;
}
/* ⭐ 같은 틀 — 묻는 창(`ask-card`)도 화면보다 길면 안에서 스크롤 · 맨 아래 단추 줄은 바닥에 붙는다 */
.ask-card { max-height: calc(100vh - 2rem); overflow-y: auto; box-sizing: border-box; }
.ask-card > .ask-foot:last-child, .ask-card > .row.links:last-child, .ask-card > .ask-btns:last-child,
.ask-card > .step-row:last-child {
  position: sticky; bottom: -1rem; z-index: 2; background: var(--panel); padding-bottom: 1rem; margin-bottom: -1rem;
}

/* 2.122.0 · 2단계 인증 (HQ [발주] 09-17) — 등록 창 · QR · 백업 코드 · 로그인 6자리 */
.twofa-dialog {
  position: fixed; inset: 0; z-index: 120;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(2px);
}
.twofa-dialog .modal-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 1.1rem 1.4rem; box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  width: min(30rem, 92vw); max-height: 90vh; overflow: auto;
  display: flex; flex-direction: column; gap: .5rem;
}
.twofa-qr { width: 13rem; height: 13rem; background: #fff; border-radius: 6px; padding: .3rem; align-self: flex-start; }
.twofa-secret { font-family: ui-monospace, Consolas, monospace; font-size: 1rem; letter-spacing: .06em; user-select: all; word-break: break-all; }
.twofa-code { font-size: 1.15rem; letter-spacing: .12em; }
/* 2.126.0 · 어디를 누르나 한 줄 — 진한 「켜기」 바로 위 */
.twofa-howto { margin: .4rem 0 .2rem; font-weight: 600; line-height: 1.5; }
.twofa-code-list { font-family: ui-monospace, Consolas, monospace; font-size: 1.05rem; line-height: 1.6; column-count: 2;
  background: var(--bg); border: 1px solid var(--line); border-radius: 6px; padding: .6rem .9rem; user-select: all; }
.twofa-remember-row { font-size: .95rem; }      /* 줄 꼴은 `.check-line` 한 부품이 든다 (2.137.0 · 발주 ⑦) */
.twofa-cell { display: flex; align-items: center; gap: .5rem; }
.twofa-cell .warn { color: var(--warn, #d9a441); }

/* ⭐ 117 · 퍼블리시 창 · 기록 표 · 방식 표 (HQ [발주] 09-16 「타이틀 우클릭 퍼블리시 v1」) */
.ask-card.publish-card { width: min(54rem, calc(100vw - 2.4rem)); max-height: calc(100vh - 3rem); overflow-y: auto; }
.publish-target { margin: .5rem 0 .3rem; font-size: .9rem; overflow-wrap: anywhere; }
.publish-target .publish-folder { font-size: .85rem; }
.publish-kinds { flex-wrap: wrap; }
.publish-card .bulk-line > label.publish-kind, .publish-card .bulk-line > label.publish-old { min-width: 0; color: var(--fg); margin-right: .8rem; }
.publish-all { display: inline-flex; gap: .7rem; }
.publish-cuts { max-height: 22rem; overflow: auto; border: 1px solid var(--line); border-radius: 9px; margin: .2rem 0 .5rem; }
.publish-cut-table { width: 100%; }
.publish-cut-table tr.publish-nofile td { opacity: .5; }
.publish-sum { margin: 0; }
.publish-note { flex: 1; min-width: 0; }
.publish-progress { margin: .5rem 0 .2rem; }
.publish-progress .publish-bar { display: inline-block; width: 12rem; vertical-align: middle; }
/* 2.125.0 · 기다리는 막대(끝을 모를 때) — 누르면 바로 창 (덧1 ②) */
.publish-loading .publish-bar { display: block; width: 100%; margin: .6rem 0 .4rem; }
.publish-wait { overflow: hidden; position: relative; }
.publish-wait .fill { width: 35%; animation: publish-wait 1.1s ease-in-out infinite alternate; }
@keyframes publish-wait { from { transform: translateX(-10%); } to { transform: translateX(200%); } }
.publish-slow, .publish-loading-error { margin: .3rem 0 0; }
.publish-recount { margin: 0 0 .3rem; }
.publish-result.err b { color: var(--bad, #d55); }
.publish-result .publish-open { margin-left: .6rem; }
.publish-skipped ul { margin: .3rem 0; padding-left: 1.2rem; max-height: 10rem; overflow: auto; font-size: .85rem; }
.publish-log-note { width: 100%; min-width: 7rem; }
.publish-log-row.running td, .publish-log-row.ip td { font-weight: 600; }
.publish-methods tr.publish-later td { opacity: .65; }
.publish-methods .publish-exclude { width: 8rem; }

/* 2.129.0 · VC 폴더에서 타이틀 가져오기 창 (2.130.0 낱말)
   2026-09-22 · 표만 스크롤 · [가져오기]/[닫기] 줄은 늘 보인다(링고 캡처: 「폴더에서 한꺼번에
   올리기」 98컷 표에 창이 화면 밖으로 밀려 [가져오기] 가 안 보였다) — `.import-pop`/
   `.ask-card.dlib-rule-card` 와 같은 결(카드를 flex-column + overflow:hidden 으로 세우고,
   자식은 기본 flex:none 으로 박고, 표 담는 자리(`.vc-import-body`→`.vc-import-scroll`)만
   flex:1·min-height:0·overflow:auto 로 자란다 · 바닥 줄은 sticky). planImportDialog 도
   같은 카드 클래스를 쓴다(`ask-card vc-import-card plan-import-card`). */
.vc-import-card {
  width: min(1100px, 96vw);
  max-height: min(90vh, calc(100vh - 2rem));
  display: flex; flex-direction: column; overflow: hidden;
}
.vc-import-card > * { flex: none; }
.vc-import-card .vc-import-body {
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: .4rem;
}
.vc-import-card .vc-import-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; }
.vc-import-card .ask-foot { position: sticky; bottom: 0; z-index: 2; background: var(--panel); }
.vc-import-table td { vertical-align: top; }
.vc-import-table .vc-code-name { width: 14rem; max-width: 100%; }
.vc-import-table .vc-cut-count { font-size: 1.15em; font-weight: 700; text-align: right; }
.vc-import-table tr.vc-blocked td { opacity: .75; }
.vc-cuts { display: flex; flex-direction: column; gap: .25rem; padding: .25rem 0 .5rem 2.2rem; }
.vc-cut { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.vc-cut .vc-cut-name { width: 16rem; max-width: 100%; }
.vc-cut-exists { opacity: .6; }
.vc-import-sum { margin: 0 .8rem 0 0; }
.vc-import-table .vc-folder { white-space: nowrap; }

/* 2.160.0 · 폴더에서 한꺼번에 올리기(시퀀스\컷) — vc-import 와 같은 결(같은 표·칸 클래스를 나눠 쓴다) */
.plan-import-pick { align-items: flex-end; gap: .8rem; flex-wrap: wrap; }
.plan-import-field { display: flex; flex-direction: column; gap: .2rem; font-size: .85rem; }
.plan-import-field input { min-width: 18rem; }
.plan-import-root-why { margin: -.2rem 0 .3rem; }
.plan-import-ask { display: flex; align-items: center; gap: .4rem; margin: .3rem 0; }
.plan-import-radio { display: inline-flex; align-items: center; gap: .25rem; margin-right: .6rem; }
.plan-import-files { display: flex; flex-direction: column; gap: .12rem; padding: .2rem 0 .3rem 2.2rem; }
.plan-file { display: flex; gap: .5rem; align-items: center; font-size: .85rem; }
.plan-import-bar.bad b { color: #d93025; }

/* 2.130.0 · 타이틀 상태(단계·컷에서 센다 · 손으로 못 바꾼다) — 색은 계약 상태 색(시작 전·진행 중·완료·보류) */
.episode-table td.title-state { text-align: center; }
.title-state-pill { display: inline-block; padding: .08rem .55rem; border-radius: 999px; font-size: .82rem; line-height: 1.35;
                    border: 1px solid currentColor; white-space: nowrap; }
.ts-todo .title-state-pill { color: #8a8a8a; }
.ts-active .title-state-pill { color: #d9a63c; }
.ts-done .title-state-pill { color: #fff; background: #3ca85a; border-color: #3ca85a; }
.ts-hold .title-state-pill { color: #e06a2c; }
/* 2.130.0 · 설정 > 타이틀 기본 템플릿 */
.title-tpl-card .title-tpl-auto-row { display: inline-flex; gap: .35rem; align-items: center; margin: .2rem 0 .6rem; }
.title-tpl-table select { min-width: 11rem; }
/* 2.130.0 · 올리기 창 — 컷 코드 없는 파일은 타이틀 태스크로 */
.movie-pop .up-title-tag { font-size: .78rem; margin-left: .35rem; padding: 0 .35rem; border-radius: 4px; border: 1px solid var(--line); }
/* 2.133.0 · 타이틀 코드·폴더·코드이름 바꾸기 창 · 컷 있으면 빨간 경고 */
.ask-card.rename-card { width: min(46rem, calc(100vw - 2.4rem)); max-height: calc(100vh - 3rem); overflow-y: auto; }
.rename-fields { display: flex; gap: 1rem; flex-wrap: wrap; margin: .5rem 0; }
.rename-fields label { display: inline-flex; gap: .4rem; align-items: center; }
.rename-fields .rename-code { width: 5.5rem; }
.rename-fields .rename-name { width: 16rem; }
.rename-folder { overflow-wrap: anywhere; margin: .4rem 0; }
.rename-sum { margin: .3rem 0; font-weight: 600; }
/* ⚠ 「빨간 창」(발주 3) — 재작업 색(--st-retake)은 밝은 판에서 주황이라 빨강을 따로 적는다 */
.rename-warn { margin: .6rem 0; padding: .6rem .8rem; border-radius: 9px; border: 2px solid #d93025;
  background: color-mix(in srgb, #d93025 13%, transparent); }
.rename-warn b { color: #d93025; }
.rename-card button.danger.rename-go { background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 600; }
.rename-card button.danger.rename-go:disabled { opacity: .45; }
.rename-code:disabled { opacity: .6; cursor: not-allowed; }
.rename-warn p { margin: 0 0 .5rem; }
.rename-warn .rename-confirm { width: 7rem; margin-left: .3rem; }
.rename-block { margin: .2rem 0; }
.rename-log-row.undone td { opacity: .6; }

/* ── 2.135.0 · VC B꼴 (HQ [발주] 09-18 「VC B꼴 v1」) ─────────────────────────── */
/* ② 가져오기 두 겹 — 게시물 줄 */
.vc-cut { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; padding: .12rem 0; }
.vc-cut .vc-cut-name { width: 12rem; }
.vc-cut .vc-cut-folder { max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vc-cut-exists { opacity: .62; }
.vc-cut-blocked .bad { font-weight: 600; }
.vc-page-count { text-align: right; }
/* ③ 버전 하나에 여러 장 — 좌우로 넘기기 */
.vpage-bar { gap: .4rem; align-items: center; flex-wrap: wrap; margin: .35rem 0; }
.vpage-now { font-variant-numeric: tabular-nums; min-width: 3.4rem; text-align: center; }
.vpage-strip { display: flex; gap: .25rem; overflow-x: auto; max-width: min(42rem, 60vw); }
.vpage-thumb { padding: 0; border: 2px solid transparent; border-radius: 5px; background: none; cursor: pointer; line-height: 0; }
.vpage-thumb img { width: 42px; height: 42px; object-fit: cover; border-radius: 3px; }
.vpage-thumb.current { border-color: var(--accent, #4a7cff); }
/* ⭐ 2.140.0 · 장 손질 — 대표 ★ · 끌어 놓는 자리 (HQ [발주] 09-18 「여러 장 버전 손질」) */
.vpage-thumb { position: relative; }
.vpage-thumb.cover img { outline: 2px solid var(--ok, #2f9e44); outline-offset: -2px; }
.vpage-star { position: absolute; left: 1px; top: -2px; font-size: .8rem; line-height: 1;
              color: #ffd43b; text-shadow: 0 0 2px rgba(0, 0, 0, .7); pointer-events: none; }
.vpage-thumb.drop { border-color: var(--accent, #4a7cff); border-style: dashed; }
.vpage-bar .vpage-cover, .vpage-bar .vpage-left, .vpage-bar .vpage-right,
.vpage-bar .vpage-swap, .vpage-bar .vpage-add, .vpage-bar .vpage-drop,
.vpage-bar .vpage-undo { white-space: nowrap; }
/* ④ 파일 이름 규칙대로 바꾸기 창 */
.ask-card.vcren-card { width: min(56rem, calc(100vw - 2.4rem)); max-height: calc(100vh - 3rem); overflow-y: auto; }
.vcren-cut { margin: .5rem 0; padding: .4rem .5rem; border: 1px solid var(--line); border-radius: 8px; }
/* ⚠ `display: flex` 를 여기서 박는다 — 안 그러면 컷 코드와 컷 이름이 **붙어 찍힌다**(2.136.0 ① 과 같은 병) */
.vcren-cut-head { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; }
.vcren-cut-head .vcren-folder { max-width: 26rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vcren-file { display: flex; gap: .45rem; align-items: center; flex-wrap: wrap; padding: .1rem 0; }
.vcren-file .vcren-old { max-width: 18rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vcren-file .vcren-new { width: 16rem; }
.vcren-same { opacity: .55; }
.vcren-skip { opacity: .5; }
.vcren-log-row.undone td { opacity: .6; }
/* 2.137.0 · 컷마다 묶음 둘 — 컷 폴더 · 씬 폴더 (어느 폴더 것인지 줄에 표시) */
.vcren-group { margin: .3rem 0 .1rem; padding-left: .3rem; border-left: 3px solid var(--line); }
.vcren-group-scene { border-left-color: var(--accent); }
.vcren-group-head { display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline; }
.vcren-group-head .vcren-place { font-weight: 600; font-size: .9rem; }
.vcren-group-head .vcren-folder { max-width: 30rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vcren-scene-warn { margin: .2rem 0 .1rem; font-weight: 600; }
.vcren-csv-where { margin: 0 0 .4rem; word-break: break-all; }
.movie-group { margin-left: .5rem; gap: .3rem; }

/* ==========================================================================
   2.141.0 · 디자인 라이브러리 — 에셋 상세 구획 (HQ [발주] 09-18 「디자인 라이브러리 v1」)
   ⚠ 기본 접힘이다 — 머리 한 줄만 서고, 펴야 끌어놓는 자리와 격자가 선다.
   ========================================================================== */
.dlib { margin: .6rem 0 .2rem; }
.dlib-head { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.dlib-head .dlib-title { cursor: pointer; }
.dlib-head .dlib-toggle { min-width: 1.6rem; }
.dlib-where { max-width: 30rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlib-body { margin-top: .4rem; }
.dlib-body.hidden { display: none; }
.dlib-drop .dz-hint { margin-bottom: .4rem; }
.dlib-empty { margin: .3rem 0; }
.dlib-grid {
  display: grid; gap: .5rem; margin-top: .5rem;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
}
.dlib-cell {
  position: relative; margin: 0; padding: .25rem;
  border: 1px solid var(--line); border-radius: 8px;
}
/* 찾아온 줄을 잠깐 짚어 준다 — 「이미 있는 파일입니다」가 데려가는 자리 */
.dlib-cell.found { outline: 2px solid var(--accent); outline-offset: 1px; }
.dlib-thumb {
  width: 100%; aspect-ratio: 1 / 1; object-fit: cover; border-radius: 5px;
  background: var(--line); cursor: zoom-in; display: block;
}
.dlib-cap { display: flex; flex-direction: column; gap: .1rem; margin-top: .25rem; font-size: .76rem; }
.dlib-cap .dlib-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dlib-cap .dlib-by { font-size: .7rem; }
.dlib-tags { display: flex; gap: .2rem; flex-wrap: wrap; }
.dlib-x {
  position: absolute; right: .3rem; top: .3rem; border: 0; border-radius: 50%;
  width: 1.2rem; height: 1.2rem; line-height: 1; cursor: pointer;
  background: color-mix(in srgb, var(--bg) 70%, transparent); color: var(--muted);
}
.dlib-x:hover { color: var(--st-retake); }

/* 2.150.0 · 디자인 라이브러리 v1.1 — 감정 버튼 일곱 · 거름 · ★ · 고르기 (HQ [발주] 09-20) */
.dlib-toolbar { display: flex; flex-direction: column; gap: .45rem; margin: .5rem 0 .1rem; }
.dlib-emobar { display: flex; gap: .35rem; flex-wrap: wrap; }
.dlib-emo-btn {
  display: flex; flex-direction: column; align-items: center; gap: 0;
  min-width: 3.6rem; padding: .3rem .4rem; border: 1px solid var(--line); border-radius: 8px;
  background: var(--panel); cursor: pointer; line-height: 1.15;
}
.dlib-emo-btn:hover { border-color: var(--accent); }
.dlib-emo-face { font-size: 1.15rem; }
.dlib-emo-ko { font-size: .82rem; font-weight: 600; }
.dlib-emo-en { font-size: .64rem; color: var(--muted); }
.dlib-filters { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; font-size: .82rem; }
.dlib-fmt-chips { display: flex; gap: .25rem; }
.dlib-fmt-chip {
  border: 1px solid var(--line); border-radius: 999px; padding: .1rem .55rem;
  background: var(--panel); cursor: pointer; font-size: .78rem;
}
.dlib-fmt-chip.on { border-color: var(--accent); color: var(--accent); }
.dlib-selcount { color: var(--muted); }
.dlib-cell.dlib-selected { outline: 2px solid var(--accent); outline-offset: 1px; }
.dlib-select {
  position: absolute; left: .3rem; top: .3rem; z-index: 1;
  width: 1.05rem; height: 1.05rem; cursor: pointer;
}
.dlib-star {
  position: absolute; left: .3rem; bottom: .3rem; z-index: 1; border: 0; background: transparent;
  cursor: pointer; font-size: 1rem; color: var(--muted); text-shadow: 0 0 2px var(--bg);
}
.dlib-star.on { color: #e0a800; }
.dlib-emo-chip {
  align-self: flex-start; font-size: .68rem; border-radius: 999px; padding: 0 .4rem;
  background: var(--panel); border: 1px solid var(--line); color: var(--muted);
}
/* 크게 보기 — 격자 칸을 누르면 덮개 한 장 */
.dlib-box { cursor: zoom-out; }
.dlib-big { margin: 0; max-width: calc(100vw - 3rem); max-height: calc(100vh - 3rem); text-align: center; }
.dlib-big img { max-width: 100%; max-height: calc(100vh - 5rem); object-fit: contain; border-radius: 6px; }
.dlib-big figcaption { margin-top: .4rem; color: var(--muted); font-size: .85rem; }

/* 「날짜 빼기…」·「규칙 이름으로 바꾸기」 미리보기 창 — **표만 스크롤**, 머리글·단추 줄은 늘 보인다
   (링고 09-21 「스크롤 불가능 · 버튼 안 보임」 · 「가져오기」 창(`.import-pop`)과 같은 꼴: 카드를
   flex-column 으로 세워 자식은 기본 flex:none 으로 박고, 표 담는 자리만 flex:1·min-height:0·overflow
   auto 로 자라게 한다 — min-height:0 이 없으면 flex 아이가 안 줄어들어 overflow 가 안 걸린다). */
.ask-card.dlib-rule-card {
  width: min(56rem, calc(100vw - 2.4rem));
  max-height: min(85vh, calc(100vh - 2rem));
  display: flex; flex-direction: column;
}
.ask-card.dlib-rule-card > * { flex: none; }
.ask-card.dlib-rule-card .folder-roots-wrap {
  flex: 1 1 auto; min-height: 0; overflow: auto;
  border: 1px solid var(--line); border-radius: 9px;
}
.ask-card.dlib-rule-card .dlib-rule-table { margin: 0; }
.ask-card.dlib-rule-card .dlib-rule-table thead th {
  position: sticky; top: 0; z-index: 1; background: var(--panel);
}
.ask-card.dlib-rule-card .dlib-rule-sum { margin: .3rem 0; font-weight: 600; }
.ask-card.dlib-rule-card .ask-foot {
  position: sticky; bottom: 0; z-index: 2; background: var(--panel);
}

/* 2.178.0 · 그록 옆 도우미(grok_menu.js·grok_detail.js) — F1/F2/F3 표시 · 머리줄 지금 컷 · 상세 md 칸 */
.grok-frame { display: inline-block; min-width: 1.9em; padding: 0 .3em; margin-left: .25em; border-radius: 4px;
  border: 1px solid var(--muted); color: var(--muted); font-size: .75em; text-align: center; line-height: 1.5; }
.grok-frame.on { border-color: var(--st-done); color: var(--st-done); font-weight: 600; }
.grok-now { display: inline-flex; align-items: center; gap: .2em; margin-right: .5em; }
.grok-now.hidden { display: none; }
.grok-box { margin: .6rem 0; }
.grok-box.hidden { display: none; }
.grok-head { display: flex; align-items: center; gap: .3em; flex-wrap: wrap; }
.grok-head .grok-path { margin-left: .6em; font-size: .8em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 60%; }
.grok-sec { margin: .35rem 0; }
.grok-sec-h { margin: .2rem 0; font-size: .85em; color: var(--muted); }
.grok-sec.unknown .grok-sec-h { font-style: italic; }
.grok-sec-body { white-space: pre-wrap; font-size: .9em; }
.grok-ver-table { border-collapse: collapse; font-size: .8em; width: 100%; }
.grok-ver-table th, .grok-ver-table td { border-bottom: 1px solid var(--line, #8883); padding: .15em .4em; text-align: left; }
.grok-ver-table tr.odd-line td { color: var(--muted); }

/* 2.179.0 · AI 콘티 v2 판 1 (HQ [발주] 09-27) — 컷 상세 판(프롬프트·영상·그림 줄·판 표) · 도구 탭 설명서 창 · 타이틀 설정 묶음 */
.grok-sec-row { display: flex; align-items: center; gap: .5em; }
.grok-copy { display: inline-flex; align-items: center; gap: .15em; }
.grok-prompt { white-space: pre-wrap; font-size: .85em; max-height: 14em; overflow: auto; margin: .2rem 0;
  padding: .4em .6em; border: 1px solid var(--line, #8883); border-radius: 6px; background: var(--panel); }
.grok-video { width: 100%; max-height: 22rem; background: #000; border-radius: 6px; }
.grok-img-row { display: flex; gap: .4rem; flex-wrap: wrap; }
.grok-img { position: relative; width: 7.5rem; height: 4.3rem; border: 1px solid var(--line, #8883); border-radius: 6px;
  overflow: hidden; background: var(--panel); cursor: pointer; display: flex; align-items: center; justify-content: center; }
.grok-img.empty { border-style: dashed; color: var(--muted); }
.grok-img img { width: 100%; height: 100%; object-fit: cover; }
.grok-img-label { position: absolute; left: .25em; bottom: .15em; font-size: .75em; font-weight: 600;
  padding: 0 .3em; border-radius: 3px; background: color-mix(in srgb, var(--bg) 70%, transparent); }
.grok-name-bad { color: var(--st-retake); }
.manual-dialog { position: fixed; inset: 0; z-index: 120; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--bg) 62%, transparent); backdrop-filter: blur(2px); }
.manual-card { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
  width: min(62rem, 94vw); height: min(44rem, 90vh); display: flex; flex-direction: column; padding: .8rem 1rem; gap: .5rem; }
.manual-top { display: flex; align-items: center; gap: .6rem; }
.manual-top h3 { margin: 0; }
.manual-tools { flex: 1; display: flex; justify-content: flex-end; }
.manual-paste { display: inline-flex; align-items: center; gap: .2em; }
.manual-cols { flex: 1; min-height: 0; display: grid; grid-template-columns: 15rem 1fr; gap: .8rem; }
.manual-list { display: flex; flex-direction: column; gap: .3rem; overflow: auto; }
.manual-item { text-align: left; display: flex; flex-direction: column; gap: .15em; padding: .45em .6em; border-radius: 6px;
  border: 1px solid var(--line); background: transparent; color: inherit; cursor: pointer; }
.manual-item.on { border-color: var(--accent, #6366f1); }
.manual-item span { font-size: .78em; }
.manual-body { overflow: auto; min-height: 0; padding-right: .4rem; }
.manual-table { border-collapse: collapse; font-size: .88em; margin: .4rem 0; }
.manual-table th, .manual-table td { border: 1px solid var(--line, #8883); padding: .2em .5em; text-align: left; vertical-align: top; }
@media (max-width: 720px) { .manual-cols { grid-template-columns: 1fr; } .manual-list { max-height: 8rem; } }
.aiconti-set { display: flex; flex-direction: column; gap: .5rem; max-width: 46rem; }
.aiconti-field { display: flex; flex-direction: column; gap: .2rem; }
.aiconti-label { font-size: .85em; font-weight: 600; }
.aiconti-hint { font-size: .78em; }
.aiconti-rules { display: flex; flex-direction: column; gap: .25rem; }
.aiconti-rule { display: flex; align-items: center; gap: .4rem; }
.aiconti-rule .aiconti-pat { flex: 1; }
.aiconti-rule-foot, .aiconti-foot { display: flex; align-items: center; gap: .6rem; font-size: .85em; }

/* 10-10 쪼갠 단추(.split-tab) → 10-11 제목 줄 크럼(.type-crumb) · 유형 줄 끝 퀵탭(.qt-bar) — type_row.css */
/* 10-10 밤 · 올리기 창 「파일 이름은 CS_CA017_C001 인데 CS_CA016_C001 태스크로…」 — 다른 토막(타이틀·번호)은 굵은 빨강 · 「모두 파일 이름대로」 줄(upload_cut.js) */
.uc-conflict-text .uc-diff, .row-caution-text .uc-diff { color: var(--danger); font-weight: 700; }
.uc-all { display: flex; align-items: center; gap: .5rem; margin: .3rem 0; }
.app-tile .carousel-dot.ar-start { font-size: .75rem; opacity: 1; }   /* 10-11 · 꺼짐 「켜기」 알약은 AR 메이커와 같은 크기 */
