/* Pretendard Variable — 자가 호스팅.
   외부 CDN을 쓰지 않는 이유: nginx.conf의 CSP가 font-src 'self' 이고, 사내망에서 외부 폰트
   호스트에 의존하고 싶지 않다. 라이선스는 fonts/OFL.txt (SIL Open Font License 1.1).

   전에는 font-family에 Pretendard가 적혀만 있고 @font-face도 폰트 파일도 없었다.
   그래서 Windows는 맑은 고딕, macOS는 Apple SD Gothic Neo로 갈렸고, 두 폰트 모두 정적이라
   font-synthesis:none 과 맞물려 550~850의 굵기 차이가 렌더 단계에서 전부 한 단계로 뭉갰다.

   URL에 ?v= 를 붙이지 않는다. Dockerfile의 sed는 index.html만 치환하므로
   styles.css 안의 __ASSET_VERSION__ 은 리터럴로 배포된다. 캐시 무효화는 파일명으로 한다. */
@font-face {
  font-family: "Pretendard Variable";
  src: url("/fonts/PretendardVariable.woff2") format("woff2-variations");
  font-weight: 45 920;          /* 가변 축 전체 범위 */
  font-style: normal;
  font-display: swap;           /* 폰트가 늦어도 글자는 먼저 보인다 */
  unicode-range: U+0000-10FFFF;
}

:root {
  /* 색 토큰. 값은 tools/palette.py 가 WCAG 대비를 풀어서 정했다. 눈으로 고르지 않았다.
     기준 표면: #ffffff / #f8f8fa(페이지) / #f1f1f4(세그먼트) / #f0edff(강조 연배경)
     본문 4.5:1, 비텍스트 3:1. 여유 0.15를 두어 반올림으로 미달하지 않게 했다.

     강조색은 교체가 아니라 재조정이다. hue 251 -> 250 으로 사실상 유지하고
     채도만 89% -> 70% 로 낮췄다. 사용자가 학습한 "보라 = 이 도구"는 지키되,
     LLM이 기본으로 뱉는 형광 보라의 인상은 걷어낸다. */
  --text: #17171d;              /* 본문·제목 */
  --text-muted: #4e4e56;        /* 보조 텍스트. 흰 배경 8.24:1 */
  --text-subtle: #6a6a77;       /* 힌트·캡션·플레이스홀더. 가장 밝은 표면에서도 4.63:1 */
  --on-dark: #e9e9ef;           /* 어두운 표면 위 본문 */
  /* 어두운 표면 위 보조 텍스트. 사이드바(#111116)만 보고 정하면 안 된다.
     밝은 글자에는 "덜 어두운 어두운 표면"이 최악이다. 실측한 가장 밝은 어두운 표면은
     scene-front(#322864)와 empty-output(#30303d)이고, 거기서도 4.64:1 을 넘긴다. */
  --on-dark-muted: #9a9aa4;
  --on-dark-accent: #a99afd;    /* 어두운 표면 위 강조 */

  --accent: #6c52e1;            /* 흰 글자 5.34:1 / 강조 글자는 밝은 표면에서 4.64:1 이상 */
  --accent-strong: #5638dc;     /* hover · pressed */
  --accent-soft: #f0edff;       /* 강조 연배경 */
  --accent-line: #d8cffb;       /* 강조 계열 테두리 */

  --danger: #c7303f;            /* 흰 글자 5.35:1 */
  --danger-soft: #fdeaee;
  --ok: #1b7953;                /* 연녹 배경 위 4.81:1 */
  --ok-soft: #e6f6ee;

  --line-strong: #84849f;       /* 입력 테두리 · 체크박스. 3.16:1 이상 */

  /* 글자 크기 척도.
     전에는 199개 선언 중 160개(80%)가 10px 이하였고 최솟값이 6px였다.
     한글은 라틴보다 자소가 조밀해서 같은 픽셀에서 더 읽기 어렵다. 8px 한글은 업무용으로 성립하지 않는다.
     기존 위계를 무너뜨리지 않으려고 단계를 합치지 않고 그대로 위로 밀었다.
       6,7 -> 11 / 8 -> 12 / 9 -> 13 / 10 -> 14 / 11 -> 15 / 12 -> 16 / 13,14 -> 18 ...
     11px는 라틴 대문자 마이크로 라벨(ADMIN, WORKSPACE 등)에만 쓴다. 한글 최솟값은 12px다. */
  --fs-micro: 11px;             /* 라틴 대문자 마이크로 라벨 전용 */
  --fs-caption: 12px;           /* 캡션 · 힌트 · 보조 정보 */
  --fs-small: 13px;             /* 칩 · 배지 · 표 보조 */
  --fs-body: 14px;              /* 본문 · 표 본문 · 버튼 */
  --fs-body-lg: 15px;           /* 강조 본문 */
  --fs-lead: 16px;              /* 리드 문장 */
  --fs-h4: 18px;                /* 카드 제목 */
  --fs-h3: 20px;                /* 패널 제목 */
  --fs-h2: 24px;                /* 섹션 제목 */
  --fs-h1: 28px;                /* 페이지 제목 */
  --fs-display: 32px;
  --fs-display-lg: 36px;
  --fs-hero: 48px;

  /* 행간. 전에는 13종이 흩어져 있었다. 한글은 라틴보다 행간을 넉넉히 준다. */
  --lh-tight: 1.15;             /* 큰 제목 */
  --lh-snug: 1.35;              /* 소제목 · 버튼 */
  --lh-normal: 1.55;            /* 기본 */
  --lh-body: 1.75;              /* 본문 문단 */

  /* 모서리 반경. 전에는 23종이 섞여 있었다(3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,24...).
     1px 차이는 눈에 보이지 않으면서 값만 늘린다. 6단계로 줄인다.
     글자를 키웠으므로 반경도 비례해서 조금씩 올렸다. */
  --r-xs: 6px;                  /* 코드 조각 · 작은 배지 */
  --r-sm: 10px;                 /* 칩 · 작은 버튼 · 표 셀 */
  --r-md: 14px;                 /* 버튼 · 입력 */
  --r-lg: 18px;                 /* 패널 · 카드 */
  --r-xl: 24px;                 /* 큰 카드 · 모달 */
  --r-pill: 99px;               /* 알약 */

  /* 그림자. 전에는 21개 선언이 전부 다른 값이었다. 높이 3단계로 줄인다.
     색조는 배경(보라 기운의 회색)을 따라간다. 순수 검정 그림자는 밝은 배경에서 탁해진다. */
  --e-1: 0 3px 10px rgba(26,23,50,.08);    /* 낮음: 카드 · 패널 */
  --e-2: 0 12px 32px rgba(26,23,50,.10);   /* 중간: 떠 있는 카드 · 버튼 */
  --e-3: 0 22px 60px rgba(26,23,50,.16);   /* 높음: 모달 · 드롭다운 */
  --e-press: 0 3px 8px rgba(25,20,55,.18); /* 눌림 */

  /* 아래는 기존 이름. 위 토큰을 가리키게 두어 남은 참조가 깨지지 않게 한다. */
  --ink: var(--text);
  --muted: var(--text-muted);
  --line: #e8e8ed;
  --soft: #f6f6f8;
  --paper: #ffffff;
  --violet: var(--accent);
  --violet-dark: var(--accent-strong);
  --violet-soft: var(--accent-soft);
  --green: var(--ok);
  --orange: #ff8e58;
  --sidebar: #111116;

  /* 굵기 척도. 전에는 400/550/700/750/780/800/850 일곱 값이 근거 없이 섞여 있었고,
     정적 한글 폰트에서는 어차피 전부 같게 렌더됐다. 다섯 단계로 정리한다.
     값을 바꾸려면 여기만 고친다. */
  --w-regular: 400;    /* 본문, 입력 필드 */
  --w-medium: 500;     /* 약한 강조 */
  --w-semibold: 600;   /* 버튼, 라벨, 탭, 칩 */
  --w-bold: 700;       /* 제목, 표 헤더, 상태 배지 */
  --w-heavy: 800;      /* 브랜드, 아바타 — 최상위 */

  font-family: "Pretendard Variable", Pretendard, "Noto Sans KR", "Apple SD Gothic Neo", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: var(--ink);
  background: #f8f8fa;
  /* 가변 폰트가 실제 굵기를 갖고 있으므로 가짜 볼드를 만들지 않는다. */
  font-synthesis: none;
}

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body { overflow-x: hidden; background: #f8f8fa; }
button, input, textarea { font: inherit; }
button { color: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
svg { display: block; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.is-hidden { display: none !important; }
/* 배경의 보라·민트 블러 블롭 두 개를 없앴다.
   이유 세 가지.
     1) 강조색과 같은 계열의 거대 발광은 LLM이 기본으로 뱉는 인상이다
     2) 강조색이 하나여야 하는데 민트(#5fdac0)가 두 번째 강조색으로 작동하고 있었다
     3) blur(80px) 짜리 520px 원 두 개는 스크롤할 때마다 GPU 재합성을 유발한다
   요소 자체는 index.html에 남아 있으므로 규칙만 무력화한다.
   배경에 깊이가 필요하면 색이 아니라 표면 단차(--soft/--paper)로 만든다. */
.ambient { display: none; }

/* Login */
.login-screen { min-height: 100dvh; display: grid; grid-template-columns: minmax(480px, 1.15fr) minmax(420px, .85fr); background: #050506; }
.login-showcase { position: relative; isolation: isolate; min-height: 100dvh; padding: 42px 5vw; overflow: hidden; color: #fff; background: #050506; }
/* 글자가 유리 위에서도 읽히게 왼쪽만 어둡게 한다. 그리드·동심원 장식은 기준 이미지와
   경쟁해서 제거했다. */
.login-showcase::before { content: ""; position: absolute; z-index: 2; inset: 0; pointer-events: none; background: linear-gradient(90deg, rgba(3,3,5,.91) 0%, rgba(3,3,5,.72) 32%, rgba(3,3,5,.23) 60%, transparent 82%), linear-gradient(180deg, rgba(0,0,0,.24), transparent 24%, transparent 74%, rgba(0,0,0,.44)); }
.login-showcase::after { content: ""; position: absolute; z-index: 0; inset: 8% 5% 4% 22%; pointer-events: none; opacity: .52; background: radial-gradient(ellipse at 58% 42%, rgba(157,148,255,.13), transparent 42%), radial-gradient(ellipse at 69% 65%, rgba(73,220,255,.08), transparent 36%); }
.brand { display: inline-flex; align-items: center; color: #1a1a20; text-decoration: none; }
.brand-logo { display: block; max-width: 100%; height: auto; }
.brand-logo-surface { display: grid; place-items: center; flex: 0 0 auto; border: 1px solid rgba(255,255,255,.48); border-radius: var(--r-md); background: rgba(255,255,255,.91); box-shadow: 0 10px 32px rgba(0,0,0,.2), inset 0 1px rgba(255,255,255,.9); }
.brand-light { position: relative; z-index: 4; }
.brand-light .brand-logo-surface { width: clamp(174px, 13vw, 210px); padding: 10px 14px; backdrop-filter: blur(12px) saturate(1.1); }
.brand-logo-login { width: 100%; }
.brand small { color: var(--on-dark-muted); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: 2px; }
.showcase-copy { position: relative; z-index: 4; max-width: 650px; margin-top: clamp(82px, 13vh, 150px); text-shadow: 0 2px 22px rgba(0,0,0,.68); }
.eyebrow { display: inline-flex; align-items: center; gap: 9px; color: #b9adff; font-size: var(--fs-body); font-weight: var(--w-bold); letter-spacing: 1.8px; }
.eyebrow i { width: 22px; height: 1px; background: currentColor; }
.showcase-copy h1 { margin: 25px 0 22px; font-size: clamp(42px, 5vw, 72px); line-height: var(--lh-tight); letter-spacing: -4px; font-weight: var(--w-bold); }
.showcase-copy h1 em { color: #c9c1ff; font-style: normal; }
.showcase-copy p { color: rgba(234,234,242,.74); font-size: var(--fs-h3); line-height: var(--lh-body); }

/* 로그인 나비 모션 -------------------------------------------------------
   검은 배경과 흰 나비 효과는 영상 자체에 렌더링되어 있다. 정적 포스터를 영상 아래에
   항상 두면 디코딩 전·재생 실패·축소 모션 환경에서도 빈 화면이 생기지 않는다. */
.login-motion { position: absolute; z-index: 1; inset: 0; overflow: hidden; pointer-events: none; background: #000; }
.login-motion-poster, .login-motion-video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.login-motion-poster { z-index: 0; }
.login-motion-video { z-index: 1; background: #000; filter: contrast(1.03); }
.showcase-foot { position: absolute; z-index: 4; left: 5vw; bottom: 40px; display: flex; align-items: center; gap: 12px; color: rgba(229,229,239,.61); font-size: var(--fs-caption); letter-spacing: 1.8px; text-shadow: 0 1px 10px #000; }
.showcase-foot span { width: 3px; height: 3px; border-radius: 50%; background: #6a6a76; }
.login-panel { display: grid; place-items: center; min-height: 100dvh; padding: 40px; background: #fff; }
.login-box { width: min(100%, 390px); }
.mobile-brand { display: none; }
.brand-logo-mobile { width: min(190px, 56vw); }
.login-heading h2 { margin: 17px 0 9px; font-size: var(--fs-display-lg); letter-spacing: -1.7px; }
.login-heading p { margin: 0 0 38px; color: var(--muted); font-size: var(--fs-h4); }
.field-label { display: block; margin: 20px 0 9px; font-size: var(--fs-lead); font-weight: var(--w-semibold); }
.input-wrap { position: relative; }
.input-wrap > svg { position: absolute; left: 15px; top: 50%; width: 19px; height: 19px; color: var(--text-subtle); transform: translateY(-50%); }
.input-wrap input { width: 100%; min-height: 52px; padding: 0 48px 0 45px; border: 1px solid var(--line-strong); border-radius: var(--r-md); outline: 0; color: var(--ink); background: #fff; font-size: var(--fs-h4); transition: .2s; }
.input-wrap input:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.password-toggle { position: absolute; top: 0; right: 4px; display: grid; place-items: center; width: 44px; min-height: 52px; border: 0; color: var(--text-subtle); background: transparent; cursor: pointer; }
.password-toggle svg { width: 19px; height: 19px; }
.login-error { min-height: 19px; margin-top: 9px; color: var(--danger); font-size: var(--fs-body-lg); }
/* 그라디언트를 단색으로 바꿨다. 그라디언트의 밝은 끝(#8065fb)에서 흰 글자가 4.06:1 로
   AA에 미달했기 때문이다. 버튼 한쪽 끝에서만 읽히지 않는 것도 실패다.
   보라 글로우 섀도도 걷어냈다. 강조색과 같은 색의 외곽 발광은 LLM이 기본으로 뱉는 인상이고,
   실제로 깊이를 만들지도 않는다. 그림자는 배경 색조로 틴트한 중립 그림자만 남긴다. */
.primary-button { border: 0; border-radius: var(--r-md); color: #fff; background: var(--accent); box-shadow: var(--e-2); cursor: pointer; transition: background .15s, transform .12s, box-shadow .15s, opacity .2s; }
.primary-button:hover { background: var(--accent-strong); transform: translateY(-1px); box-shadow: var(--e-2); }
/* 눌림 피드백. 이전에는 :active 상태가 한 곳도 없었다. */
.primary-button:active { background: var(--accent-strong); transform: translateY(1px); box-shadow: var(--e-press); }
.primary-button:disabled { cursor: wait; opacity: .65; transform: none; }
.login-button { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 54px; margin-top: 5px; font-weight: var(--w-semibold); }
.login-button svg { width: 18px; height: 18px; }
/* 로그인 화면의 테스트 계정 안내(.test-account)는 제거했다.
   인터넷에 열린 화면에 사용 가능한 자격증명을 인쇄하고 자동 입력까지 해 주고 있었다. */

/* App shell */
/* 사이드바 폭을 변수로 둔다. 접기는 이 변수 하나만 0으로 바꾸면 되고,
   본문 그리드가 같은 변수를 쓰므로 둘이 어긋나 겹치는 일이 없다. */
.app-shell { --nav-w: 242px; display: grid; grid-template-columns: var(--nav-w) 1fr; min-height: 100dvh; }
.sidebar { position: fixed; z-index: 30; inset: 0 auto 0 0; display: flex; flex-direction: column; width: 242px; padding: 25px 17px 18px; color: var(--on-dark); background: var(--sidebar); border-right: 1px solid #202028; }
.sidebar-head { padding: 0 7px; }
.sidebar .app-brand { min-width: 0; flex-direction: column; align-items: flex-start; gap: 5px; }
.sidebar .app-brand .brand-logo-surface { width: 128px; padding: 6px 9px; border-color: rgba(255,255,255,.26); border-radius: var(--r-sm); box-shadow: 0 6px 20px rgba(0,0,0,.24), inset 0 1px rgba(255,255,255,.9); }
.brand-logo-sidebar { width: 100%; }
.sidebar .app-brand small { color: var(--on-dark-muted); font-size: var(--fs-micro); line-height: 1; letter-spacing: .9px; white-space: nowrap; }
.sidebar-close { display: none !important; }
.main-nav { margin-top: 44px; }
.main-nav > p { margin: 0 11px 12px; color: var(--on-dark-muted); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: 1.8px; }
.nav-item { display: flex; align-items: center; width: 100%; min-height: 46px; margin: 4px 0; padding: 0 12px; border: 0; border-radius: var(--r-md); color: var(--on-dark-muted); background: transparent; font-size: var(--fs-lead); cursor: pointer; transition: .2s; }
.nav-item:hover { color: var(--on-dark); background: #1a1a21; }
.nav-item.active { color: #fff; background: linear-gradient(90deg, rgba(117,84,246,.23), rgba(117,84,246,.07)); box-shadow: inset 2px 0 var(--on-dark-accent); }
.nav-item svg { width: 19px; height: 19px; margin-right: 12px; }
.nav-item i { margin-left: auto; padding: 3px 6px; border-radius: var(--r-xs); color: var(--on-dark-accent); background: rgba(116,84,245,.16); font-size: var(--fs-micro); font-style: normal; font-weight: var(--w-heavy); }
.nav-item b { margin-left: auto; display: grid; place-items: center; min-width: 20px; min-height: 20px; border-radius: var(--r-sm); color: var(--on-dark-muted); background: #25252d; font-size: var(--fs-small); }/* 아이콘 버튼이 둘(비밀번호 변경, 로그아웃)이라 마지막 두 열을 auto 로 둔다.
   고정폭으로 두면 버튼을 더 넣을 때마다 폭을 다시 계산해야 하고, 넘치면 다음 줄로 떨어진다. */
.sidebar-user { display: grid; grid-template-columns: 34px 1fr auto auto; align-items: center; gap: 7px; margin-top: 13px; padding: 14px 7px 0; border-top: 1px solid #23232b; }
.avatar, .top-avatar { display: grid; place-items: center; border-radius: var(--r-sm); color: var(--on-dark-accent); background: #30294d; font-size: var(--fs-small); font-weight: var(--w-heavy); }
.avatar { width: 34px; height: 34px; }
.sidebar-user div:nth-child(2) { display: flex; flex-direction: column; min-width: 0; }
.sidebar-user strong { overflow: hidden; color: var(--on-dark); font-size: var(--fs-small); text-overflow: ellipsis; }
.sidebar-user div span { margin-top: 3px; color: var(--on-dark-muted); font-size: var(--fs-caption); }
.icon-button { display: grid; place-items: center; padding: 0; border: 0; color: var(--text-subtle); background: transparent; cursor: pointer; }
.icon-button svg { width: 18px; height: 18px; }
.sidebar-scrim { display: none; }
.workspace { grid-column: 2; min-width: 0; }

/* --- 왼쪽 메뉴 접기 --- */
/* 넓은 화면에서도 메뉴를 접을 수 있어야 한다. 본문이 2단(입력 + 결과)인 화면은
   242px 이 그대로 결과 패널의 잘림으로 이어진다. */
.nav-collapse { width: 28px; height: 28px; margin-left: auto; border-radius: var(--r-sm); color: var(--on-dark-muted); }
.nav-collapse:hover { color: var(--on-dark); background: #1f1f27; }
.nav-collapse svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
@media (min-width: 821px) {
  .sidebar-head { display: flex; align-items: center; gap: 8px; }
  .app-shell, .sidebar { transition: grid-template-columns .22s ease, transform .22s ease; }
  .app-shell.nav-collapsed { --nav-w: 0px; }
  .app-shell.nav-collapsed .sidebar { transform: translateX(-101%); }
  /* 접힌 상태에서는 감춰진 메뉴가 탭 순서에 남지 않도록 한다. */
  .app-shell.nav-collapsed .sidebar { visibility: hidden; }
}
.topbar { position: sticky; z-index: 20; top: 0; display: flex; align-items: center; height: 65px; padding: 0 31px; border-bottom: 1px solid #e9e9ed; background: rgba(255,255,255,.9); backdrop-filter: blur(14px); }
.breadcrumb { display: flex; align-items: center; gap: 11px; font-size: var(--fs-small); }
.breadcrumb-brand { display: inline-flex; align-items: center; gap: 8px; color: var(--text-subtle); letter-spacing: 1.1px; }
.breadcrumb-brand b { font-size: var(--fs-small); white-space: nowrap; }
.brand-logo-breadcrumb { width: 72px; }
.breadcrumb i { width: 3px; height: 3px; border-radius: 50%; background: #c5c5cb; }
.breadcrumb strong { font-size: var(--fs-body); }
.top-actions { display: flex; align-items: center; gap: 16px; margin-left: auto; }
.system-status { display: flex; align-items: center; gap: 7px; padding: 7px 10px; border: 1px solid #e9e9ed; border-radius: var(--r-pill); color: var(--text-subtle); background: #fff; font-size: var(--fs-caption); }
.system-status i { width: 6px; height: 6px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 3px rgba(27,121,83,.16); }.top-avatar { width: 31px; height: 31px; }
/* 예전에는 좁은 화면에서만 보였다. 이제 넓은 화면에서도 메뉴 접기 토글로 쓴다. */
.menu-button { display: flex; flex-direction: column; gap: 4px; width: 32px; margin-right: 10px; }
.menu-button span { width: 17px; height: 1px; background: #60606a; transition: .2s; }
.menu-button:hover span { background: var(--violet); }
.content { width: min(1440px, 100%); margin: 0 auto; padding: 36px clamp(24px, 3.2vw, 48px) 60px; }
.view { display: none; animation: viewIn .28s ease; }
.view.active { display: block; }
@keyframes viewIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.page-intro { display: flex; align-items: flex-end; justify-content: space-between; gap: 30px; margin-bottom: 27px; }
.page-intro.compact { align-items: center; }
.eyebrow.dark { color: var(--violet); }
.page-intro h1 { margin: 10px 0 8px; font-size: clamp(26px, 3vw, 36px); line-height: var(--lh-tight); letter-spacing: -2px; }
.page-intro p { margin: 0; color: var(--muted); font-size: var(--fs-lead); }
.quota { width: 190px; padding: 13px 15px; border: 1px solid #e8e8ed; border-radius: var(--r-md); background: rgba(255,255,255,.75); }
.quota > span { color: var(--text-subtle); font-size: var(--fs-caption); }
.quota strong { float: right; font-size: var(--fs-small); }
.quota strong b { color: var(--violet); }
.quota > div { clear: both; height: 4px; margin-top: 11px; overflow: hidden; border-radius: var(--r-pill); background: #e9e8ed; }
.quota > div i { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--accent)); transition: width .5s; }
/* --- 좌우 분할 레이아웃 (드래그로 폭 조절) --- */
/* 예전 값은 minmax(520px, 1.25fr) minmax(340px, .75fr) 였다. 하한이 고정 픽셀이라
   두 열 합계 880px 아래로는 줄어들지 못하고 컨테이너를 넘쳤다. 1100~1220px 구간에서
   결과 패널 오른쪽이 잘려 보인 원인이 이것이다. minmax(0, ...) 로 바꿔 실제로 줄어들게 하고,
   비율은 사용자가 가운데 바를 끌어 정한다. */
.split-layout {
  display: grid;
  grid-template-columns: minmax(0, var(--split, 62%)) var(--split-gap, 20px) minmax(0, 1fr);
  align-items: start;
  gap: 0;
}
.studio-grid { --split: 62%; --split-gap: 20px; }
.studio-layout { --split: 60%; --split-gap: 20px; }

/* 바 자체가 열 사이 여백을 차지한다. 여백을 따로 두면 잡을 수 있는 폭이 좁아진다. */
.split-bar {
  position: relative;
  align-self: stretch;
  min-height: 120px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: col-resize;
  touch-action: none;
}
.split-bar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  border-radius: var(--r-pill);
  background: #e4e3ea;
  transform: translateX(-50%);
  transition: background .18s, width .18s;
}
.split-bar:hover::before, .split-bar:focus-visible::before, .split-bar.dragging::before { width: 5px; background: var(--violet); }
/* 잡을 수 있다는 것이 보여야 한다. 가운데 손잡이 점. */
.split-bar::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 9px;
  height: 34px;
  border: 1px solid #dcdbe4;
  border-radius: var(--r-pill);
  background: #fff;
  box-shadow: var(--e-1);
  transform: translate(-50%, -50%);
  transition: border-color .18s;
}
.split-bar:hover::after, .split-bar:focus-visible::after, .split-bar.dragging::after { border-color: var(--violet); }
/* 끄는 동안 텍스트가 선택되면 드래그가 끊긴다. */
body.split-dragging { cursor: col-resize; user-select: none; }
.panel { border: 1px solid #e9e9ee; border-radius: var(--r-lg); background: rgba(255,255,255,.94); box-shadow: var(--e-2); }
.creation-panel { padding: 27px; }
.step-heading { display: flex; align-items: center; gap: 12px; }
.step-heading > span { display: grid; place-items: center; flex: 0 0 29px; min-height: 29px; border-radius: var(--r-sm); color: var(--violet); background: var(--violet-soft); font-size: var(--fs-small); font-weight: var(--w-heavy); }
.step-heading h2, .panel-title h2 { margin: 0; font-size: var(--fs-h4); letter-spacing: -.4px; }
.step-heading p, .panel-title p { margin: 4px 0 0; color: var(--text-subtle); font-size: var(--fs-small); }
.cache-badge { display: inline-flex; align-items: center; gap: 5px; margin-left: auto; color: var(--text-subtle); font-size: var(--fs-caption); }
.cache-badge svg { width: 13px; height: 13px; }
.dropzone { position: relative; width: 100%; height: 230px; margin-top: 18px; padding: 0; overflow: hidden; border: 1.5px dashed #d6d3e5; border-radius: var(--r-lg); color: inherit; background: linear-gradient(145deg, var(--accent-soft), #f7f7fa); cursor: pointer; transition: .25s; }
.dropzone:hover, .dropzone.dragging { border-color: var(--violet); background: #f6f3ff; }
.drop-empty { display: flex; align-items: center; flex-direction: column; justify-content: center; height: 100%; }
.upload-icon { display: grid; place-items: center; width: 47px; height: 47px; margin-bottom: 13px; border-radius: var(--r-md); color: var(--violet); background: var(--violet-soft); }
.upload-icon svg { width: 24px; height: 24px; }
.drop-empty strong { font-size: var(--fs-lead); }
.drop-empty p { margin: 7px 0 14px; color: var(--text-subtle); font-size: var(--fs-small); }
.outline-button { padding: 7px 13px; border: 1px solid #dedce9; border-radius: var(--r-sm); color: var(--accent); background: #fff; font-size: var(--fs-small); font-weight: var(--w-semibold); }
.image-preview { position: relative; width: 100%; height: 100%; background: #17171c; }
.image-preview img { width: 100%; height: 100%; object-fit: contain; }
.change-image { position: absolute; top: 12px; right: 12px; padding: 6px 10px; border-radius: var(--r-sm); color: #fff; background: rgba(16,16,21,.72); backdrop-filter: blur(8px); font-size: var(--fs-caption); }
.file-chip { position: absolute; left: 12px; right: 12px; bottom: 11px; display: flex; align-items: center; justify-content: space-between; padding: 9px 11px; border-radius: var(--r-sm); color: #fff; background: rgba(15,15,20,.76); backdrop-filter: blur(8px); }
.file-chip strong { max-width: 70%; overflow: hidden; font-size: var(--fs-caption); text-overflow: ellipsis; white-space: nowrap; }
.file-chip small { color: var(--text-subtle); font-size: var(--fs-caption); }
.divider { height: 1px; margin: 28px 0; background: #eeeeF2; }
.prompt-wrap { margin-top: 17px; overflow: hidden; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: #fff; transition: .2s; }
.prompt-wrap:focus-within { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.prompt-wrap textarea { display: block; width: 100%; min-height: 112px; padding: 15px; resize: vertical; border: 0; outline: 0; color: var(--text); background: transparent; font-size: var(--fs-body-lg); line-height: var(--lh-body); }
.prompt-wrap textarea::placeholder { color: var(--text-subtle); }
.prompt-foot { display: flex; justify-content: space-between; padding: 9px 14px; border-top: 1px solid #efeff2; color: var(--text-subtle); background: #fafafa; font-size: var(--fs-caption); }
.prompt-foot b { color: var(--text-subtle); font-weight: var(--w-medium); }
.prompt-foot i { color: var(--violet); font-style: normal; }
.suggestions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.suggestions button { padding: 6px 9px; border: 1px solid #e4e3e9; border-radius: var(--r-pill); color: var(--text-subtle); background: #fafafa; font-size: var(--fs-caption); cursor: pointer; }
.suggestions button:hover { color: var(--violet); border-color: #cfc8f9; background: var(--violet-soft); }
.options-row { display: grid; grid-template-columns: 1fr 1.35fr; gap: 17px; margin-top: 21px; }
.options-row fieldset { margin: 0; padding: 0; border: 0; }
.options-row legend { margin-bottom: 8px; font-size: var(--fs-small); font-weight: var(--w-semibold); }
/* 세그먼트는 선택지 묶음이다. 컨테이너를 꽉 채우면 버튼 하나가 과도하게 넓어져
   "여러 개 중 하나"로 읽히지 않는다. 내용 폭에 맞추고, 폭이 모자라면 균등 분할한다. */
.segmented { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(max-content, 1fr); justify-self: start; max-width: 100%; padding: 3px; border-radius: var(--r-sm); background: #f1f1f4; }
.segmented button { min-height: 31px; padding: 0 7px; border: 0; border-radius: var(--r-sm); color: var(--text-subtle); background: transparent; font-size: var(--fs-caption); cursor: pointer; }
.segmented button.active { color: var(--accent); background: #fff; box-shadow: var(--e-1); font-weight: var(--w-semibold); }
/* 고를 수 없는 선택지. 720p 3·5초처럼 GPU 메모리에 들어가지 않는 조합에 쓴다.
   감추지 않고 비활성으로 남긴다. 사라지면 왜 없는지 알 수 없고, title 로 이유를 읽을 수 있다. */
.segmented button:disabled { color: #a8a8b2; cursor: not-allowed; text-decoration: line-through; }
.segmented button:disabled:active { transform: none; }
/* 선택지 아래 붙는 설명. 해상도의 비율 안내처럼 "이건 고를 수 있는 값이 아니다"를 알린다.
   legend 와 같은 폭 안에 두고 줄바꿈을 허용한다(문장이 길다). */
.field-note { margin: 7px 0 0; max-width: 42ch; color: var(--text-subtle); font-size: var(--fs-caption); line-height: 1.5; }
.generate-button { display: grid; grid-template-columns: 35px 1fr 20px; align-items: center; width: 100%; min-height: 62px; margin-top: 24px; padding: 10px 17px; text-align: left; }
.generate-button .spark { grid-row: 1 / 3; display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm); background: rgba(255,255,255,.15); }
.generate-button .spark svg { width: 20px; height: 20px; fill: currentColor; stroke-width: 0; }
.generate-button > span:nth-child(2) { padding-left: 11px; font-size: var(--fs-lead); font-weight: var(--w-bold); }
.generate-button small { grid-column: 2; padding-left: 11px; color: rgba(255,255,255,.92); font-size: var(--fs-caption); }
.generate-button .arrow { grid-column: 3; grid-row: 1 / 3; width: 17px; height: 17px; }
.preview-column { display: grid; gap: 15px; }
.output-panel { padding: 20px; }
.panel-title { display: flex; align-items: flex-start; justify-content: space-between; }
.status-badge { display: inline-flex; align-items: center; gap: 5px; padding: 5px 8px; border-radius: var(--r-pill); font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.status-badge i { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.status-badge.idle { color: var(--text-subtle); background: #f0f0f3; }
.status-badge.success { color: var(--ok); background: #e8f8f1; }
.status-badge.working { color: var(--accent); background: var(--accent-soft); }
.output-stage { position: relative; display: grid; place-items: center; min-height: 267px; margin-top: 16px; overflow: hidden; border-radius: var(--r-md); color: #fff; background: radial-gradient(circle at 50% 38%, #30303d, #17171f 70%); }
.output-stage::after { content: ""; position: absolute; inset: 0; opacity: .16; pointer-events: none; background-image: linear-gradient(rgba(255,255,255,.08) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.08) 1px, transparent 1px); background-size: 30px 30px; }
.empty-output { position: relative; z-index: 2; text-align: center; }
.empty-output > span { display: grid; place-items: center; width: 53px; height: 53px; margin: 0 auto 13px; border: 1px solid #3c3c49; border-radius: var(--r-lg); color: var(--on-dark-muted); background: #292833; }
.empty-output svg { width: 29px; height: 29px; }
.empty-output strong { display: block; font-size: var(--fs-body); }
.empty-output p { margin: 7px 0 0; color: var(--on-dark-muted); font-size: var(--fs-caption); line-height: var(--lh-normal); }@keyframes scan { to { top: 75%; } }.output-meta { display: flex; align-items: center; justify-content: center; gap: 20px; margin-top: 13px; color: var(--text-subtle); font-size: var(--fs-caption); }
.output-meta span { display: flex; align-items: center; gap: 6px; }
.output-meta i { width: 4px; height: 4px; border-radius: 50%; background: #c2c2c9; }.tip-card { display: flex; gap: 12px; padding: 15px 17px; border: 1px solid #ded9fb; border-radius: var(--r-lg); background: linear-gradient(135deg, #f4f1ff, var(--accent-soft)); }
.tip-card > span { display: grid; place-items: center; flex: 0 0 31px; height: 31px; border-radius: var(--r-sm); color: var(--violet); background: #e7e1ff; }
.tip-card svg { width: 17px; height: 17px; }
.tip-card strong { font-size: var(--fs-small); }
.tip-card p { margin: 4px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }

/* Library and history */
.outline-action { display: inline-flex; align-items: center; gap: 7px; min-height: 37px; padding: 0 13px; border: 1px solid #dedee5; border-radius: var(--r-sm); color: var(--text-muted); background: #fff; font-size: var(--fs-small); font-weight: var(--w-semibold); cursor: pointer; }
.outline-action svg { width: 15px; height: 15px; }.video-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 17px; }
.video-card { overflow: hidden; border: 1px solid #e7e7ec; border-radius: var(--r-lg); background: #fff; box-shadow: var(--e-2); }
.video-thumb { position: relative; aspect-ratio: 16/9; overflow: hidden; background: #1b1b22; }
.video-thumb video { width: 100%; height: 100%; object-fit: cover; }
.video-card-info { padding: 14px; }
.video-card-info strong { display: block; overflow: hidden; font-size: var(--fs-body); text-overflow: ellipsis; white-space: nowrap; }
.video-card-info p { margin: 6px 0 12px; color: var(--text-subtle); font-size: var(--fs-caption); }
.video-actions { display: flex; gap: 7px; }
.video-actions a { flex: 1; padding: 7px; border: 1px solid #e3e2e8; border-radius: var(--r-sm); color: var(--text-muted); text-align: center; text-decoration: none; font-size: var(--fs-caption); }
.video-actions a:first-child { color: #fff; border-color: var(--violet); background: var(--violet); }.text-action { border: 0; background: transparent; font-size: var(--fs-small); cursor: pointer; }
.text-action.danger { color: var(--danger); }.history-item { display: grid; grid-template-columns: 66px 1fr auto auto; align-items: center; gap: 14px; padding: 12px; border: 1px solid #e8e8ed; border-radius: var(--r-md); background: #fff; }
.history-item img { width: 66px; height: 48px; border-radius: var(--r-sm); object-fit: cover; background: #eee; }
.history-item h3 { margin: 0 0 5px; font-size: var(--fs-body); }
.history-item p { max-width: 700px; margin: 0; overflow: hidden; color: var(--text-subtle); font-size: var(--fs-caption); text-overflow: ellipsis; white-space: nowrap; }
.history-item time { color: var(--text-subtle); font-size: var(--fs-caption); }

/* Toast */
.toast { position: fixed; z-index: 100; right: 24px; bottom: 24px; display: grid; grid-template-columns: 34px minmax(220px, 1fr) 22px; gap: 11px; align-items: center; width: min(390px, calc(100vw - 32px)); padding: 13px; border: 1px solid #e3e3e9; border-radius: var(--r-md); background: rgba(255,255,255,.96); box-shadow: var(--e-3); backdrop-filter: blur(15px); opacity: 0; pointer-events: none; transform: translateY(18px); transition: .28s; }
.toast.show { opacity: 1; pointer-events: auto; transform: none; }
.toast > span { display: grid; place-items: center; width: 34px; height: 34px; border-radius: var(--r-sm); color: #fff; background: var(--green); }
.toast > span::before { content: "✓"; font-size: var(--fs-h3); font-weight: var(--w-bold); }
.toast.error > span { background: #e05260; }
.toast.error > span::before { content: "!"; }
.toast strong { display: block; font-size: var(--fs-small); }
.toast p { margin: 4px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-snug); }
.toast button { border: 0; color: var(--text-subtle); background: transparent; cursor: pointer; }

@media (max-width: 1100px) {
  .login-screen { grid-template-columns: 1fr 440px; }
  .showcase-copy h1 { font-size: var(--fs-hero); }
  /* 이 폭 아래에서는 두 열을 나란히 두는 것 자체가 무리다. 위아래로 쌓고 바를 감춘다. */
  .studio-grid, .studio-layout { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .studio-grid > .split-bar, .studio-layout > .split-bar { display: none; }
  .preview-column { grid-template-columns: 1fr 1fr; }
  .output-panel { grid-row: span 2; }
  .tip-card { grid-column: 2; }
  .video-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 820px) {
  .login-screen { display: block; background: #fff; }
  .login-showcase { display: none; }
  .login-panel { min-height: 100dvh; padding: 28px 22px; }
  .mobile-brand { display: flex; align-items: center; margin-bottom: 60px; }
  .app-shell { display: block; }
  .workspace { width: 100%; }
  .sidebar { width: 270px; transform: translateX(-101%); transition: transform .25s ease; }
  .sidebar.open { transform: none; }
  .sidebar-head { display: flex; align-items: center; justify-content: space-between; }
  .sidebar-close { display: grid !important; position: relative; width: 30px; height: 30px; }
  .sidebar-close span { position: absolute; width: 17px; height: 1px; background: #aaa; transform: rotate(45deg); }
  .sidebar-close span:last-child { transform: rotate(-45deg); }
  /* 좁은 화면은 서랍식이라 접기 버튼이 필요 없다. 닫기(X)가 그 역할을 한다. */
  .nav-collapse { display: none !important; }
  .sidebar-scrim { position: fixed; z-index: 25; inset: 0; display: block; visibility: hidden; background: rgba(0,0,0,.48); opacity: 0; transition: .25s; }
  .sidebar-scrim.show { visibility: visible; opacity: 1; }
  .menu-button { display: flex; flex-direction: column; gap: 4px; width: 32px; margin-right: 10px; }
  .menu-button span { width: 17px; height: 1px; background: #60606a; }
  .topbar { height: 58px; padding: 0 18px; }
  .system-status { display: none; }
  .content { padding: 28px 18px 50px; }
  .preview-column { grid-template-columns: 1fr; }
  .output-panel { grid-row: auto; }
  .tip-card { grid-column: auto; }}

@media (max-width: 560px) {
  .brand-logo-mobile { width: min(168px, 54vw); }
  .brand-logo-breadcrumb { width: 62px; }
  .breadcrumb-brand { gap: 6px; }
  .login-heading h2 { font-size: var(--fs-display); }
  .page-intro { align-items: flex-start; flex-direction: column; }
  .quota { width: 100%; }
  .creation-panel { padding: 20px 16px; }
  .dropzone { height: 210px; }
  .cache-badge { display: none; }
  .options-row { grid-template-columns: 1fr; }
  .output-stage { height: 235px; }
  .top-actions { gap: 7px; }  .video-grid { grid-template-columns: 1fr; }  .history-item { grid-template-columns: 56px 1fr; }
  .history-item img { width: 56px; height: 48px; }
  .history-item > time { display: none; }
  .toast { right: 16px; bottom: 16px; }
}/* Model selection and admin model management */
.model-picker { display: grid; gap: 8px; margin-top: 17px; }
.model-option { display: grid; grid-template-columns: 18px 1fr; gap: 11px; align-items: center; padding: 13px 14px; border: 1px solid #e2e1e9; border-radius: var(--r-md); background: #fff; text-align: left; cursor: pointer; transition: .2s; }
.model-option:hover { border-color: #c9c0f7; background: var(--accent-soft); }
.model-option.active { border-color: var(--violet); background: var(--violet-soft); }
.model-radio { display: grid; place-items: center; width: 16px; height: 16px; border: 1.5px solid #c9c9d3; border-radius: 50%; }
.model-option.active .model-radio { border-color: var(--violet); }
.model-option.active .model-radio::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--violet); }
.model-option-body { display: flex; flex-direction: column; }
.model-option strong { font-size: var(--fs-body); }
.model-option small { margin-top: 4px; color: var(--text-subtle); font-size: var(--fs-caption); }
.model-empty { margin: 0; padding: 15px; border: 1px dashed #dcdce3; border-radius: var(--r-md); color: var(--text-subtle); font-size: var(--fs-small); text-align: center; }
.admin-nav-section { margin-top: 20px; padding-top: 14px; border-top: 1px solid #23232b; }
.admin-nav-section > p { margin: 0 11px 10px; color: var(--on-dark-muted); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: 1.8px; }.model-table-wrap { margin-bottom: 20px; overflow-x: auto; border: 1px solid #e8e8ed; border-radius: var(--r-lg); background: #fff; }
.model-table { width: 100%; min-width: 760px; border-collapse: collapse; }
.model-table th { padding: 12px 14px; border-bottom: 1px solid #eeeef2; color: var(--text-subtle); background: #fafafc; font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: .6px; text-align: left; }
.model-table td { padding: 12px 14px; border-bottom: 1px solid #f2f2f5; font-size: var(--fs-small); vertical-align: middle; }
.model-table tr:last-child td { border-bottom: 0; }
.model-table strong { display: block; font-size: var(--fs-body); }
.model-table small { display: block; margin-top: 3px; color: var(--text-subtle); font-size: var(--fs-caption); }
.model-table code { color: var(--accent); font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: var(--fs-caption); }
.source-tag { padding: 4px 7px; border-radius: var(--r-xs); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-micro); font-weight: var(--w-semibold); }
/* 카탈로그에서 거부된 정의. 표의 정상 행과 확실히 달라 보여야 한다 —
   이 줄이 떠 있으면 어떤 기능이 지금 죽어 있다는 뜻이다. */
.model-table tr.model-rejected td { border-left: 3px solid var(--danger); background: var(--danger-soft); }
.model-table tr.model-rejected strong { color: var(--danger); }
.state-on { color: var(--ok); font-weight: var(--w-bold); }
.state-off { color: var(--text-subtle); font-weight: var(--w-semibold); }
.state-default { margin-left: 6px; padding: 3px 6px; border-radius: var(--r-xs); color: var(--violet); background: var(--violet-soft); font-size: var(--fs-caption); font-weight: var(--w-bold); }
.row-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.row-actions button { white-space: nowrap; padding: 6px 9px; border: 1px solid #e0dfe6; border-radius: var(--r-sm); color: var(--text-muted); background: #fff; font-size: var(--fs-caption); cursor: pointer; }
.row-actions button:hover { border-color: var(--accent-line); color: var(--violet); }
.row-actions button.primary { color: #fff; border-color: var(--violet); background: var(--violet); }.checkbox { flex-direction: row !important; align-items: center; gap: 8px !important; font-size: var(--fs-small); }
.checkbox input { width: 15px; height: 15px; accent-color: var(--violet); }

@media (max-width: 1100px) { }
@media (max-width: 560px) { }

/* ===== 인증 탭 / 회원가입 ===== */
.auth-tabs { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 4px; margin-bottom: 30px; padding: 4px; border-radius: var(--r-md); background: #f1f1f4; }
.auth-tab { min-height: 36px; border: 0; border-radius: var(--r-sm); color: var(--text-subtle); background: transparent; font-size: var(--fs-body); font-weight: var(--w-semibold); cursor: pointer; transition: .2s; }
.auth-tab.active { color: var(--accent); background: #fff; box-shadow: var(--e-1); }
.auth-pane { animation: viewIn .2s ease; }
.required { margin-left: 5px; padding: 2px 5px; border-radius: var(--r-xs); color: var(--danger); background: #fdeaee; font-size: var(--fs-caption); font-weight: var(--w-bold); }
.field-hint { margin: 9px 0 0; color: var(--text-subtle); font-size: var(--fs-small); line-height: var(--lh-normal); }
.field-hint code { padding: 1px 4px; border-radius: var(--r-xs); background: #f2f2f5; font-size: var(--fs-small); }
.login-success { min-height: 18px; margin-top: 9px; color: var(--ok); font-size: var(--fs-body-lg); }

/* ===== 프로젝트 메인 ===== */
.new-project-button { display: inline-flex; align-items: center; gap: 8px; padding: 12px 17px; font-size: var(--fs-body-lg); font-weight: var(--w-semibold); }
.new-project-button svg { width: 16px; height: 16px; }
.project-block { margin-bottom: 38px; }
.block-head { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 16px; }
.block-head h2 { margin: 0; font-size: var(--fs-h3); letter-spacing: -.5px; }
.block-count { display: grid; place-items: center; min-width: 22px; min-height: 22px; padding: 0 7px; border-radius: var(--r-pill); color: var(--violet); background: var(--violet-soft); font-size: var(--fs-small); font-weight: var(--w-bold); }
.block-head p { flex: 1 1 240px; margin: 0; color: var(--text-subtle); font-size: var(--fs-small); }

/* 공유: 포스터 비율(2:3), 크게 */
.poster-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; }
.poster-card { overflow: hidden; border: 1px solid #e7e7ec; border-radius: var(--r-lg); background: #fff; box-shadow: var(--e-2); transition: transform .2s, box-shadow .2s; }
.poster-card:hover { transform: translateY(-3px); box-shadow: var(--e-3); }
.poster-card .cover { position: relative; aspect-ratio: 2 / 3; overflow: hidden; background: #1b1b22; }

/* 개인: 정사각형에 가깝게(4:5), 작게 */
/* 글자를 키운 만큼 칸도 넓힌다. 150px 에서는 "진입점 2 · 소재 · 로그라인" 배지가 넘쳤다. */
.tile-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
.tile-card { overflow: hidden; border: 1px solid #e9e9ee; border-radius: var(--r-md); background: #fff; box-shadow: var(--e-1); transition: transform .2s; }
.tile-card:hover { transform: translateY(-2px); }
.tile-card .cover { position: relative; aspect-ratio: 4 / 5; overflow: hidden; background: #1b1b22; }
.tile-card .card-body { padding: 11px; }
.tile-card .card-body strong { font-size: var(--fs-small); }
.tile-card .card-body p { display: none; }
.tile-card .card-actions button, .tile-card .upload-cover { font-size: var(--fs-caption); padding: 5px 6px; }

.cover img { width: 100%; height: 100%; object-fit: cover; }
.cover-placeholder { display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 9px; height: 100%; padding: 16px; text-align: center; background: radial-gradient(circle at 50% 30%, #322864, #14131d 72%); }
.cover-placeholder span { padding: 4px 8px; border: 1px solid rgba(255,255,255,.2); border-radius: var(--r-pill); color: #b6a9ff; font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: 1px; }
.cover-placeholder strong { color: #fff; font-size: var(--fs-body-lg); line-height: var(--lh-snug); }
/* 기본 배경을 준다. 전에는 .shared / .private 가 붙기 전까지 배경이 없어서
   흰 글자가 밝은 표면 위에 그대로 놓였다(대비 1.06). JS가 클래스를 붙이기 전 한 프레임,
   그리고 렌더가 실패한 경우에 글자가 사라진다. */
.visibility-badge { position: absolute; top: 10px; left: 10px; padding: 4px 8px; border-radius: var(--r-pill); color: #fff; background: rgba(30,30,38,.78); font-size: var(--fs-caption); font-weight: var(--w-bold); backdrop-filter: blur(8px); }
.visibility-badge.shared { background: var(--accent); }
.visibility-badge.private { background: rgba(30,30,38,.78); }
/* 카드에서 사람이 찾는 것은 제목이다. 배지는 부가 정보인데 자리를 먼저 차지하고 있었다.
   제목 -> 배지 -> 메타 -> 요약 순으로 바꾸고 간격을 다시 잡는다. */
.card-body { padding: 14px; }
.card-body strong { display: block; margin-bottom: 6px; overflow: hidden; font-size: var(--fs-body-lg); text-overflow: ellipsis; white-space: nowrap; }
.card-body small { display: block; margin-top: 5px; color: var(--text-subtle); font-size: var(--fs-caption); }
.card-body p { margin: 9px 0 12px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card-actions { display: flex; flex-wrap: wrap; gap: 5px; }
.card-actions button, .upload-cover { padding: 6px 8px; border: 1px solid #e2e1e9; border-radius: var(--r-sm); color: var(--text-muted); background: #fff; font-size: var(--fs-caption); font-weight: var(--w-semibold); cursor: pointer; }
.card-actions button:hover, .upload-cover:hover { border-color: var(--accent-line); color: var(--violet); }
.card-actions button.primary { color: #fff; border-color: var(--violet); background: var(--violet); }
.card-actions button.danger { color: var(--danger); border-color: #f2d6dd; }
.empty-block { display: flex; align-items: center; flex-direction: column; justify-content: center; min-height: 190px; padding: 34px; border: 1px dashed #dbdbe2; border-radius: var(--r-lg); background: rgba(255,255,255,.6); text-align: center; }
.empty-block > span { display: grid; place-items: center; width: 50px; height: 50px; margin-bottom: 14px; border-radius: var(--r-lg); color: var(--accent); background: var(--violet-soft); }
.empty-block svg { width: 26px; height: 26px; }
.empty-block strong { font-size: var(--fs-lead); }
.empty-block p { margin: 7px 0 0; color: var(--text-subtle); font-size: var(--fs-small); }

/* ===== 모달 ===== */
.modal-scrim { position: fixed; z-index: 200; inset: 0; display: grid; place-items: center; padding: 20px; background: rgba(14,14,20,.55); backdrop-filter: blur(4px); }
.modal { width: min(100%, 470px); max-height: 90vh; overflow-y: auto; padding: 24px; border-radius: var(--r-lg); background: #fff; box-shadow: var(--e-3); animation: viewIn .2s ease; }
.modal.danger { width: min(100%, 520px); }
.modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.modal-head h2 { margin: 0; font-size: var(--fs-h3); letter-spacing: -.5px; }
.modal-head .icon-button { position: relative; width: 28px; height: 28px; }
.modal-head .icon-button span { position: absolute; width: 15px; height: 1.5px; background: #9a9aa4; transform: rotate(45deg); }
.modal-head .icon-button span:last-child { transform: rotate(-45deg); }
.modal textarea { display: block; width: 100%; padding: 12px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); outline: 0; resize: vertical; font-size: var(--fs-body-lg); line-height: var(--lh-body); }
.modal textarea:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.modal .input-wrap input { padding-left: 14px; }
.segmented.visibility { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: 1fr 1fr; justify-self: stretch; }
.segmented.visibility button { min-height: 38px; font-size: var(--fs-small); }
.modal-actions { display: flex; align-items: center; justify-content: flex-end; gap: 12px; margin-top: 22px; }
.modal-actions .primary-button { padding: 11px 19px; font-size: var(--fs-body); font-weight: var(--w-semibold); }
/* primary-button 과 같은 이유로 단색. 그라디언트 밝은 끝에서 3.61:1 이었다. */
.danger-button { padding: 11px 19px; border: 0; border-radius: var(--r-sm); color: #fff; background: var(--danger); font-size: var(--fs-body); font-weight: var(--w-semibold); cursor: pointer; transition: background .15s, transform .12s; }
.danger-button:hover { background: #a8232f; }
.danger-button:active { transform: translateY(1px); }
.danger-button:disabled { opacity: .5; cursor: not-allowed; }
.danger-banner { display: grid; grid-template-columns: 34px 1fr; gap: 12px; margin-bottom: 18px; padding: 15px; border: 1px solid #f4d2d9; border-radius: var(--r-md); background: var(--danger-soft); }
.danger-banner > span { display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; color: #fff; background: var(--danger); }
.danger-banner svg { width: 18px; height: 18px; }
.danger-banner strong { display: block; color: var(--danger); font-size: var(--fs-body); }
.danger-banner p { margin: 5px 0 0; color: var(--danger); font-size: var(--fs-small); line-height: var(--lh-normal); }
.delete-target { margin: 0 0 18px; padding: 11px 13px; border-radius: var(--r-sm); background: #f7f7f9; font-size: var(--fs-body); }
.delete-target span { color: var(--text-subtle); font-size: var(--fs-small); }
.delete-options { display: grid; gap: 9px; margin-top: 9px; }
.radio-row { display: grid; grid-template-columns: 18px 1fr; gap: 11px; align-items: start; padding: 12px 13px; border: 1px solid #e3e2e9; border-radius: var(--r-md); cursor: pointer; }
.radio-row:has(input:checked) { border-color: var(--violet); background: var(--accent-soft); }
.radio-row input { width: 16px; height: 16px; margin-top: 1px; accent-color: var(--violet); }
.radio-row strong { display: block; font-size: var(--fs-body); }
.radio-row small { display: block; margin-top: 4px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.confirm-row { display: flex; align-items: center; gap: 9px; margin-top: 16px; font-size: var(--fs-small); }
.confirm-row input { width: 15px; height: 15px; accent-color: var(--danger); }

/* ===== 관리자: 회사 코드 ===== */
.code-panel { margin-bottom: 20px; padding: 22px; }
.code-form { display: grid; grid-template-columns: 1fr auto; gap: 11px; align-items: center; margin-top: 16px; }
.code-form .input-wrap { margin: 0; }
.code-form .primary-button { padding: 0 19px; min-height: 52px; font-size: var(--fs-body); font-weight: var(--w-semibold); }

/* ===== 생성 진행 ===== */
.result-video { width: 100%; height: 100%; object-fit: contain; background: #000; }
.job-progress { margin-top: 13px; }
.job-bar { height: 5px; overflow: hidden; border-radius: var(--r-pill); background: #e9e8ed; }
.job-bar i { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--accent)); transition: width .6s ease; }
.job-progress span { display: block; margin-top: 8px; color: var(--text-subtle); font-size: var(--fs-caption); }

@media (max-width: 820px) {
  /* 본문 그리드와 같은 이유로 넓혔다. 150px 는 8px 글자 시절 값이다. */
  .poster-grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 13px; }
  .tile-grid { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
  .code-form { grid-template-columns: 1fr; }
  .code-form .primary-button { min-height: 46px; }
}

/* ===== 프로젝트 카드 진입 ===== */
.poster-card.clickable, .tile-card.clickable { cursor: pointer; }
.poster-card.clickable:focus-visible, .tile-card.clickable:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.cover-open { position: absolute; right: 10px; bottom: 10px; padding: 5px 10px; border-radius: var(--r-pill); color: #fff; background: rgba(18,18,24,.72); backdrop-filter: blur(6px); font-size: var(--fs-caption); font-weight: var(--w-bold); opacity: 0; transform: translateY(4px); transition: .2s; }
.poster-card.clickable:hover .cover-open, .tile-card.clickable:hover .cover-open,
.poster-card.clickable:focus-visible .cover-open, .tile-card.clickable:focus-visible .cover-open { opacity: 1; transform: none; }

/* ===== 프로젝트 상세 ===== */
.back-link { display: inline-flex; align-items: center; gap: 7px; margin-bottom: 20px; padding: 8px 12px; border: 1px solid #e4e3ea; border-radius: var(--r-sm); color: var(--text-muted); background: #fff; font-size: var(--fs-small); font-weight: var(--w-semibold); cursor: pointer; }
.back-link:hover { border-color: var(--accent-line); color: var(--violet); }
.back-link svg { width: 14px; height: 14px; }
/* 표지 열은 원래 minmax(230px, 320px) 고정이었다. 분할 바를 붙이면서 비율로 바꾼다. */
.detail-layout { --split: 25%; --split-gap: 28px; }
.detail-cover-frame { overflow: hidden; border: 1px solid #e7e7ec; border-radius: var(--r-lg); background: #1b1b22; box-shadow: var(--e-2); }
.detail-cover-frame.poster { aspect-ratio: 2 / 3; }
.detail-cover-frame.tile { aspect-ratio: 4 / 5; }
.detail-cover-frame img { width: 100%; height: 100%; object-fit: cover; }
.detail-cover-actions { display: grid; gap: 8px; margin-top: 13px; }
.detail-cover-actions .primary-button { padding: 11px; font-size: var(--fs-body); font-weight: var(--w-semibold); }
.upload-cover.block { display: block; text-align: center; padding: 10px; }
.detail-main { min-width: 0; }
.detail-head { display: flex; align-items: center; gap: 11px; margin-bottom: 13px; }
.detail-head .visibility-badge { position: static; }
.detail-meta { color: var(--text-subtle); font-size: var(--fs-small); }
.detail-title { width: 100%; margin-bottom: 20px; padding: 10px 12px; border: 1px solid transparent; border-radius: var(--r-sm); outline: 0; color: var(--ink); background: transparent; font-size: var(--fs-h1); font-weight: var(--w-bold); letter-spacing: -1.2px; }
.detail-title:hover:not([readonly]) { border-color: #e6e5ec; }
.detail-title:focus { border-color: var(--violet); background: #fff; outline: 2px solid var(--accent); outline-offset: 1px; }
.detail-title[readonly] { cursor: default; }
.detail-main textarea { display: block; width: 100%; margin-top: 9px; padding: 15px; border: 1px solid var(--line-strong); border-radius: var(--r-md); outline: 0; resize: vertical; color: var(--text); background: #fff; font-size: var(--fs-body-lg); line-height: var(--lh-body); }
.detail-main textarea:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.detail-main textarea[readonly] { background: #fafafb; color: var(--text-muted); }
.detail-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 16px; }
.detail-hint { color: var(--ok); font-size: var(--fs-small); }
.detail-buttons { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-left: auto; }
.detail-buttons .primary-button { padding: 10px 20px; font-size: var(--fs-body); font-weight: var(--w-semibold); }
.readonly-note { margin-top: 14px; padding: 12px 14px; border: 1px solid #e2e1e9; border-radius: var(--r-sm); color: var(--text-subtle); background: #fafafb; font-size: var(--fs-small); }

@media (max-width: 820px) {
  .detail-layout { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .detail-layout > .split-bar { display: none; }
  .detail-cover { max-width: 260px; }
  .detail-title { font-size: var(--fs-h2); }
  .detail-buttons { margin-left: 0; }
}

/* ===== 표지 이력 ===== */
.cover-history { margin-top: 18px; padding-top: 16px; border-top: 1px solid #eeeef2; }
.cover-history-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 11px; }
.cover-history-head strong { font-size: var(--fs-body); }
.cover-history-head span { padding: 3px 7px; border-radius: var(--r-pill); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.cover-history-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.cover-history-item { position: relative; margin: 0; overflow: hidden; border: 1px solid #e7e7ec; border-radius: var(--r-sm); background: #1b1b22; }
.cover-history-item img { display: block; width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }
.cover-history-item figcaption { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; padding: 6px 7px; background: #fff; }
.cover-history-item figcaption span { color: var(--violet); font-size: var(--fs-caption); font-weight: var(--w-bold); }
.cover-history-item figcaption small { color: var(--text-subtle); font-size: var(--fs-caption); }
.cover-history-item button { position: absolute; inset: 0 0 auto 0; aspect-ratio: 3 / 4; border: 0; color: #fff; background: rgba(18,18,24,.62); backdrop-filter: blur(2px); font-size: var(--fs-caption); font-weight: var(--w-bold); opacity: 0; cursor: pointer; transition: opacity .18s; }
.cover-history-item:hover button, .cover-history-item button:focus-visible { opacity: 1; }
.cover-history-item button:disabled { opacity: 1; cursor: wait; }
/* ===== 진입점 선택 ===== */
.field-hint.tight { margin: 4px 0 10px; }
.input-type-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.input-type { display: flex; flex-direction: column; gap: 4px; padding: 13px; border: 1px solid #dddde5; border-radius: var(--r-md); text-align: left; background: #fff; cursor: pointer; transition: .16s; }
.input-type:hover { border-color: var(--accent-line); background: #fcfbff; }
.input-type.active { border-color: var(--violet); background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: 1px; }
.input-type-step { color: var(--violet); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: .6px; }
.input-type strong { color: var(--ink); font-size: var(--fs-body); font-weight: var(--w-semibold); }
.input-type small { color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }

/* 진입점 배지 */
.stage-badge { display: inline-block; max-width: 100%; padding: 4px 9px; border-radius: var(--r-pill); color: var(--accent); background: var(--accent-soft); font-size: var(--fs-caption); font-weight: var(--w-bold); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.stage-badge.small { padding: 3px 7px; font-size: var(--fs-caption); }

/* ===== 상세: 원본 자료 / 기획 방향 패널 ===== */
/* 위쪽 .panel 규칙과 함께 읽어야 한다. 두 규칙이 나뉘어 있어 반경이 서로 달랐고,
   뒤쪽이 이기면서 --radius 토큰이 아무 효과가 없었다. 둘 다 --r-lg 를 보게 맞췄다. */
.panel { margin-top: 26px; padding: 19px; border: 1px solid var(--line); border-radius: var(--r-lg); background: #fff; }
.panel-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.panel-head h2 { margin: 0; font-size: var(--fs-lead); font-weight: var(--w-bold); letter-spacing: -.3px; }
.panel-head p { margin: 5px 0 0; color: var(--text-subtle); font-size: var(--fs-small); line-height: var(--lh-normal); }
.panel-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 14px; }
.panel-foot .detail-hint { color: var(--text-subtle); }
.panel-foot .detail-buttons { margin-left: auto; }
.panel .upload-cover { padding: 9px 15px; font-size: var(--fs-small); }

.segmented.input-type-switch { grid-auto-flow: row; grid-template-columns: repeat(4, 1fr); justify-self: stretch; margin-bottom: 12px; }
.segmented.input-type-switch button { min-height: 34px; font-size: var(--fs-caption); }
.segmented.input-type-switch button:disabled { cursor: default; opacity: .55; }

.direction-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 13px; }
.direction-field.wide { grid-column: 1 / -1; }
.direction-field .field-label { display: block; margin-bottom: 6px; }
.direction-field .input-wrap input { min-height: 44px; padding: 0 14px; font-size: var(--fs-body); }
.direction-field .input-wrap input[readonly] { color: var(--text-muted); background: #fafafb; }
.direction-field textarea { margin-top: 0 !important; }

@media (max-width: 820px) {
  .input-type-grid { grid-template-columns: 1fr; }
  .direction-grid { grid-template-columns: 1fr; }
  .segmented.input-type-switch { grid-template-columns: 1fr 1fr; }
  .panel-foot .detail-buttons { margin-left: 0; }
}
/* ===== AI 작업 (산출물 단계) ===== */
.doc-steps { display: grid; gap: 10px; }
.doc-step { padding: 15px; border: 1px solid #e6e6ec; border-radius: var(--r-md); background: #fcfcfd; }
.doc-step.status-ready { border-color: #cfe8dc; background: #fbfefc; }
.doc-step.status-generating { border-color: var(--accent-line); background: var(--accent-soft); }
.doc-step.status-failed { border-color: var(--danger-soft); background: #fffbfc; }
.doc-step-head { display: flex; align-items: center; gap: 10px; }
.doc-order { display: grid; place-items: center; min-width: 22px; min-height: 22px; border-radius: var(--r-sm); color: var(--accent); background: #efecff; font-size: var(--fs-small); font-weight: var(--w-bold); }
.doc-step-title { flex: 1; min-width: 0; }
.doc-step-title strong { display: block; font-size: var(--fs-body-lg); font-weight: var(--w-semibold); }
.doc-step-title small { display: block; margin-top: 2px; color: var(--text-subtle); font-size: var(--fs-caption); }
.doc-step-meta { margin: 9px 0 0; color: var(--text-subtle); font-size: var(--fs-small); }
.doc-step-error { margin: 9px 0 0; padding: 9px 11px; border-radius: var(--r-sm); color: var(--danger); background: var(--danger-soft); font-size: var(--fs-small); line-height: var(--lh-normal); }
.doc-step-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.doc-step-actions .primary-button { padding: 9px 17px; font-size: var(--fs-small); font-weight: var(--w-semibold); }

/* 생성 옵션. 콘티 옵션(.storyboard-options)과 같은 연보라 박스로 통일해
   "누르기 전에 정하는 값"이라는 성격이 같다는 것을 시각적으로 맞춘다. */
.doc-options { margin-top: 12px; }
.doc-options-toggle { font-size: var(--fs-small); }
.doc-options-body { margin-top: 10px; padding: 14px 15px; border: 1px solid #e4e0f7; border-radius: 13px; background: #fbfaff; }
.doc-options-body .options-row { margin-top: 0; }
.doc-options-body .field-label { display: block; margin-top: 14px; }
.doc-options-body .panel-textarea { margin-top: 7px; }
.doc-progress { color: var(--accent); font-size: var(--fs-small); }
.doc-chip { padding: 3px 8px; border-radius: var(--r-pill); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-caption); font-weight: var(--w-bold); white-space: nowrap; }
.doc-chip.ready { color: var(--ok); background: var(--ok-soft); }
.doc-chip.generating { color: var(--accent); background: var(--accent-soft); }
.doc-chip.failed { color: var(--danger); background: var(--danger-soft); }

/* 산출물 본문 */
.doc-body:empty { display: none; }
.doc-content { margin-top: 14px; padding-top: 14px; border-top: 1px dashed #e2e2e9; }
.doc-section { margin-top: 16px; }
.doc-section h3 { margin: 0 0 8px; color: var(--accent); font-size: var(--fs-small); font-weight: var(--w-bold); letter-spacing: .4px; }
.doc-text { margin: 0 0 7px; color: var(--text-muted); font-size: var(--fs-body); line-height: var(--lh-body); }
.doc-text b, .doc-pair-extra b { color: var(--ink); font-weight: var(--w-semibold); }
.doc-list { margin: 0; padding-left: 16px; color: var(--text-muted); font-size: var(--fs-body); line-height: var(--lh-body); }
.doc-list li { margin-bottom: 3px; }
.doc-pairs { display: grid; gap: 9px; }
.doc-pair { padding: 11px 13px; border-radius: var(--r-sm); background: #f7f7fa; }
.doc-pair strong { display: block; margin-bottom: 4px; font-size: var(--fs-body); font-weight: var(--w-semibold); }
.doc-pair p { margin: 0; color: var(--text-muted); font-size: var(--fs-body); line-height: var(--lh-body); }
.doc-pair-extra { margin: 6px 0 0; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }
.doc-chips { display: flex; flex-wrap: wrap; gap: 6px; }

.doc-verdict { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.doc-verdict-badge { padding: 6px 13px; border-radius: var(--r-pill); color: #fff; background: var(--violet); font-size: var(--fs-body); font-weight: var(--w-bold); }
.doc-score b { font-size: var(--fs-h2); font-weight: var(--w-bold); letter-spacing: -1px; }
.doc-score small { margin-left: 2px; color: var(--text-subtle); font-size: var(--fs-small); }

.doc-option { margin-bottom: 10px; padding: 14px; border: 1px solid #e6e6ec; border-radius: var(--r-md); background: #fff; }
.doc-option.recommended { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.doc-option-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
.doc-option-head strong { font-size: var(--fs-body-lg); font-weight: var(--w-bold); }
.doc-option-logline { margin: 0 0 8px; color: var(--accent); font-size: var(--fs-body); font-style: italic; line-height: var(--lh-body); }
.doc-option-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 11px; margin-top: 10px; }
.doc-option-grid h4 { margin: 0 0 5px; color: var(--text-subtle); font-size: var(--fs-caption); font-weight: var(--w-bold); }

.doc-logline { margin: 0 0 14px; padding: 14px 16px; border-left: 3px solid var(--violet); border-radius: 0 9px 9px 0; color: var(--ink); background: var(--accent-soft); font-size: var(--fs-lead); font-weight: var(--w-semibold); line-height: var(--lh-body); }

.doc-character { margin-bottom: 10px; padding: 14px; border: 1px solid #e6e6ec; border-radius: var(--r-md); background: #fff; }
.doc-character-head { display: flex; align-items: center; flex-wrap: wrap; gap: 7px; margin-bottom: 8px; }
.doc-character-head strong { font-size: var(--fs-lead); font-weight: var(--w-bold); }
.doc-character-head small { color: var(--text-subtle); font-size: var(--fs-caption); }
.doc-character-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 5px 13px; margin: 9px 0; }
.doc-character-grid p { margin: 0; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }
.doc-speech { margin: 8px 0; padding: 9px 11px; border-radius: var(--r-sm); color: var(--text-muted); background: #f7f7fa; font-size: var(--fs-small); line-height: var(--lh-body); }
.doc-quotes { display: grid; gap: 5px; margin: 8px 0; }
.doc-quotes span { padding: 6px 10px; border-left: 2px solid var(--accent-line); color: var(--accent); background: var(--accent-soft); font-size: var(--fs-small); line-height: var(--lh-normal); }
.doc-relations { margin-top: 8px; }
.doc-relations p { margin: 0 0 3px; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }

.doc-raw { margin-top: 16px; }
.doc-raw summary { color: var(--text-subtle); font-size: var(--fs-caption); cursor: pointer; }
.doc-raw pre { margin: 8px 0 0; max-height: 320px; overflow: auto; padding: 12px; border-radius: var(--r-sm); color: var(--text-muted); background: #f7f7fa; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-size: var(--fs-caption); line-height: var(--lh-body); }

@media (max-width: 820px) {
  .doc-option-grid, .doc-character-grid { grid-template-columns: 1fr; }
}
/* ===== 트리트먼트: 화별 시놉시스 ===== */
.doc-episode { margin-bottom: 9px; padding: 13px 14px; border: 1px solid #e6e6ec; border-left: 3px solid var(--violet); border-radius: 0 11px 11px 0; background: #fff; }
.doc-episode-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 7px; }
.doc-episode-no { padding: 3px 8px; border-radius: var(--r-xs); color: #fff; background: var(--violet); font-size: var(--fs-caption); font-weight: var(--w-bold); }
.doc-episode-head strong { font-size: var(--fs-body-lg); font-weight: var(--w-bold); }
.doc-episode-head small { color: var(--text-subtle); font-size: var(--fs-caption); }
.doc-episode-scenes { margin-top: 8px; }
.doc-episode-scenes h4 { margin: 0 0 4px; color: var(--text-subtle); font-size: var(--fs-caption); font-weight: var(--w-bold); }

/* 트리트먼트 본문. 서론 / 등장인물 소개 / 주요 사건 / 클라이맥스 / 결말 순서로 읽는 산문이라
   목록형 산출물보다 행간을 넓히고 섹션 제목을 크게 둔다. 인쇄해서 회의에 들고 간다. */
.doc-narrative-body { margin-top: 14px; }
.doc-narrative { margin-top: 20px; padding-top: 15px; border-top: 1px solid #ececf1; }
.doc-narrative:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.doc-narrative h3 { margin: 0 0 10px; color: var(--ink); font-size: var(--fs-body-lg); font-weight: var(--w-bold); }
.doc-narrative .doc-text { margin-bottom: 11px; line-height: 1.85; text-align: justify; }
.doc-narrative .doc-text:last-of-type { margin-bottom: 0; }
.doc-episode-hook { margin: 8px 0 0; padding: 8px 10px; border-radius: var(--r-sm); color: var(--accent); background: var(--accent-soft); font-size: var(--fs-small); line-height: var(--lh-body); }
.doc-episode-hook b { color: var(--accent); font-weight: var(--w-bold); }
/* ===== 모델에 전달된 프롬프트 ===== */
.sent-prompt { margin-top: 14px; padding-top: 13px; border-top: 1px solid #eeeef2; }
.sent-prompt summary { color: var(--text-subtle); font-size: var(--fs-caption); font-weight: var(--w-semibold); cursor: pointer; }
.sent-prompt p { margin: 9px 0 0; padding: 11px 12px; border-radius: var(--r-sm); color: var(--text-muted); background: #f7f7fa; font-size: var(--fs-small); line-height: var(--lh-body); }
.sent-prompt small { display: block; margin-top: 7px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.sent-prompt h3 { margin: 0 0 8px; color: var(--accent); font-size: var(--fs-small); font-weight: var(--w-bold); letter-spacing: .4px; }
.sent-prompt pre { margin: 0; padding: 11px 12px; overflow-x: auto; border-radius: var(--r-sm); color: var(--text-muted); background: #f7f7fa; font-size: var(--fs-small); line-height: var(--lh-body); white-space: pre-wrap; word-break: break-word; }

/* ===== 참고 이미지 갤러리 + 분석 + 확인 질문 =====
   두 영상 화면이 각자의 영역에서 같은 모양으로 쓴다. 상태와 DOM은 분리되어 있고
   여기 있는 것은 생김새뿐이다. */
.dropzone.compact { min-height: 132px; padding: 18px; }
/* 파일 이름이 분석의 근거라는 것을 눈에 띄게 알린다. */
.name-hint { padding: 10px 12px; border-left: 3px solid var(--accent); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--accent-soft); }
.name-hint b { color: var(--ink); }
.name-hint code { padding: 1px 5px; border-radius: var(--r-xs); background: #fff; font-size: var(--fs-caption); }

.ref-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(146px, 1fr)); gap: 11px; margin-top: 13px; }
.ref-card { display: flex; flex-direction: column; margin: 0; overflow: hidden; border: 1px solid #e6e6ec; border-radius: 11px; background: #fff; }
/* 첫 프레임은 한 장뿐이라 한눈에 구분되어야 한다. */
.ref-card.is-primary { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.ref-card.pending { align-items: center; justify-content: center; min-height: 150px; color: var(--text-subtle); font-size: var(--fs-small); }
.ref-thumb { position: relative; aspect-ratio: 4 / 3; background: #f4f4f7; }
.ref-thumb img { width: 100%; height: 100%; object-fit: cover; }
.ref-badge { position: absolute; padding: 2px 7px; border-radius: var(--r-pill); font-size: 9px; font-weight: var(--w-bold); }
.ref-badge.primary { top: 6px; left: 6px; color: #fff; background: var(--accent); }
.ref-badge.role { right: 6px; bottom: 6px; color: var(--ink); background: rgba(255, 255, 255, .92); }
.ref-card figcaption { flex: 1; padding: 9px 10px; }
.ref-card figcaption strong { display: block; overflow: hidden; font-size: var(--fs-caption); font-weight: var(--w-semibold); text-overflow: ellipsis; white-space: nowrap; }
.ref-card figcaption small { display: block; margin-top: 2px; color: var(--text-subtle); font-size: 9px; }
.ref-desc { margin: 6px 0 0; color: var(--text-muted); font-size: 10px; line-height: 1.5; }
.ref-warn { margin: 6px 0 0; color: var(--danger); font-size: 10px; line-height: 1.5; }
.ref-card-actions { display: flex; gap: 8px; padding: 0 10px 9px; }
.ref-card-actions .text-action { font-size: 10px; }

.ref-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 11px; margin-top: 13px; }

/* 분석 결과와 확인 질문. 콘티 옵션과 같은 연보라 박스로 통일한다. */
.ref-brief { margin-top: 15px; padding: 15px 16px; border: 1px solid #e4e0f7; border-radius: 13px; background: #fbfaff; }
.ref-brief-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.ref-brief-head h3 { margin: 0; color: var(--accent); font-size: var(--fs-small); font-weight: var(--w-bold); letter-spacing: .4px; }
.ref-brief-summary { margin: 9px 0 0; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }

.ref-questions { display: grid; gap: 10px; margin-top: 13px; }
.ref-question { padding: 11px 12px; border: 1px solid #eaeaf0; border-radius: var(--r-sm); background: #fff; }
/* 답한 질문은 표시해 둔다. 무엇이 남았는지 세지 않아도 보이게 한다. */
.ref-question.is-answered { border-color: #cfe8d8; background: #fbfefc; }
.ref-question-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.ref-question-head strong { flex: 1; min-width: 0; font-size: var(--fs-small); font-weight: var(--w-semibold); }
.ref-skip { font-size: 10px; }
.ref-question-why { margin: 6px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.ref-question-options { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ref-option { padding: 5px 10px; border: 1px solid #e4e3e9; border-radius: var(--r-pill); color: var(--text-subtle); background: #fafafa; font-size: var(--fs-caption); cursor: pointer; transition: .14s; }
.ref-option:hover { color: var(--accent); border-color: #cfc8f9; background: var(--violet-soft); }
.ref-option.active { color: #fff; border-color: var(--accent); background: var(--accent); }
.ref-question-input { margin-top: 8px; }

/* ===== NEW_영상 제작 (자체 GPU / Wan 2.2) =====
   기존 스튜디오 클래스를 최대한 재사용하고, 이 화면에만 필요한 것만 여기 둔다. */
/* GPU 서버 상태 줄. 노드가 스케줄로 꺼져 있는 것이 정상 동작이라 눈에 띄게 알려야 한다. */
.wan-server { display: flex; align-items: center; gap: 11px; margin-bottom: 18px; padding: 12px 15px; border: 1px solid #e4e0f7; border-radius: 13px; background: #fbfaff; }
.wan-server p { margin: 0; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-normal); }

.wan-jobs { display: grid; gap: 10px; }
.wan-job { padding: 13px 14px; border: 1px solid #ececf1; border-radius: var(--r-sm); background: #fff; }
.wan-job.status-failed { border-color: var(--danger-soft); }
.wan-job.status-ready { border-color: var(--ok-soft); }
.wan-job-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.wan-job-head strong { flex: 1; min-width: 0; overflow: hidden; font-size: var(--fs-body); font-weight: var(--w-semibold); text-overflow: ellipsis; white-space: nowrap; }
.wan-job-meta { margin: 7px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); }
.wan-job-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 9px; }
.wan-job-actions a { text-decoration: none; }

/* 보강 전후. 원문은 흐리게, 결과는 또렷하게 두어 무엇이 바뀌었는지 한눈에 보이게 한다. */
.boost-before { color: var(--text-subtle) !important; background: #f4f4f7 !important; text-decoration: line-through; text-decoration-color: #c9c9d2; }
.boost-after { color: var(--text-muted) !important; background: var(--accent-soft) !important; }

/* ===== 영상 삭제 ===== */
.video-delete { padding: 7px 13px; border: 1px solid var(--danger-soft); border-radius: var(--r-sm); color: var(--danger); background: #fff; font-size: var(--fs-small); font-weight: var(--w-semibold); cursor: pointer; transition: .16s; }
.video-delete:hover:not(:disabled) { border-color: #c2415a; background: var(--danger-soft); }
.video-delete:disabled { cursor: wait; opacity: .6; }

/* ===== 사용량 대시보드 ===== */
.usage-controls { display: flex; align-items: center; gap: 11px; }
.usage-controls .segmented { min-width: 210px; }
.usage-cards { display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; margin-bottom: 26px; }
.usage-card { padding: 15px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fff; }
.usage-card span { display: block; color: var(--text-subtle); font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.usage-card strong { display: block; margin-top: 7px; font-size: var(--fs-h2); font-weight: var(--w-bold); letter-spacing: -.8px; }
.usage-card small { color: var(--text-subtle); font-size: var(--fs-caption); }
.usage-heading { margin: 0 0 11px; font-size: var(--fs-body-lg); font-weight: var(--w-bold); }
.model-table-wrap + .usage-heading { margin-top: 26px; }
.usage-empty { padding: 22px !important; color: var(--text-subtle); text-align: center; }

@media (max-width: 1100px) {
  .usage-cards { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 820px) {
  .usage-cards { grid-template-columns: repeat(2, 1fr); }
  .usage-controls { flex-wrap: wrap; }
}
/* ===== 그림체 선택 ===== */
/* 스튜디오 패널의 단독 textarea(그림체, AI 이미지 설명).
   전용 규칙이 없어 브라우저 기본 폭(cols=20, 약 180px)으로 렌더링되어 패널 폭과 어긋났다.
   02단계 디렉션 입력창(.prompt-wrap textarea)과 같은 모양을 쓰되 높이만 용도에 맞춘다. */
.panel-textarea { display: block; width: 100%; margin-top: 13px; padding: 13px 15px; border: 1px solid var(--line-strong); border-radius: var(--r-md); outline: 0; color: var(--text); background: #fff; font-size: var(--fs-body-lg); line-height: var(--lh-body); resize: vertical; transition: .2s; }
.panel-textarea:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.panel-textarea::placeholder { color: var(--text-subtle); }

/* 한 줄 입력. 확인 질문의 답변 칸이 쓴다. textarea와 같은 모양으로 두어
   같은 패널 안에서 두 입력이 어긋나 보이지 않게 한다. */
.panel-input { display: block; width: 100%; padding: 10px 13px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); outline: 0; color: var(--text); background: #fff; font-size: var(--fs-small); line-height: var(--lh-normal); transition: .2s; }
.panel-input:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
.panel-input::placeholder { color: var(--text-subtle); }
#videoStyle { min-height: 62px; }
#frameAiPrompt { min-height: 84px; }

.style-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 11px; }
.style-chip { padding: 7px 12px; border: 1px solid #dddde5; border-radius: var(--r-pill); color: var(--text-muted); background: #fff; font-size: var(--fs-small); font-weight: var(--w-semibold); cursor: pointer; transition: .16s; }
.style-chip:hover { border-color: var(--accent-line); color: var(--violet); }
.style-chip.active { border-color: var(--violet); color: #fff; background: var(--violet); }
.step-heading .optional { margin-left: 5px; padding: 2px 6px; border-radius: var(--r-xs); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-caption); font-weight: var(--w-bold); }

.reference-row { display: flex; align-items: center; flex-wrap: wrap; gap: 13px; margin-top: 11px; }
.reference-preview { display: flex; align-items: center; gap: 11px; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fcfcfd; }
.reference-preview img { width: 52px; height: 52px; border-radius: var(--r-sm); object-fit: cover; }
.reference-preview strong { display: block; max-width: 190px; overflow: hidden; font-size: var(--fs-small); text-overflow: ellipsis; white-space: nowrap; }
.reference-preview button { margin-top: 4px; }

/* ===== 이미지 생성 결과 ===== */
.result-image { display: block; width: 100%; border-radius: var(--r-md); }
.style-result { margin-top: 15px; padding-top: 14px; border-top: 1px solid #eeeef2; }
.style-result-head { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 9px; }
.style-result p { margin: 0 0 6px; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }
.style-result small { display: block; color: var(--text-subtle); font-size: var(--fs-caption); }
.style-result-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }

/* ===== 생성 이미지 갤러리 ===== */
.image-gallery-head { margin-top: 30px; }
.image-gallery-head .usage-heading { margin: 0; }
.image-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 15px; }
.image-card { overflow: hidden; border: 1px solid var(--line); border-radius: var(--r-md); background: #fff; }
.image-thumb { background: #f1f1f4; }
.image-thumb img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.image-card-info { padding: 13px; }
.image-card-info strong { display: block; overflow: hidden; font-size: var(--fs-body); text-overflow: ellipsis; white-space: nowrap; }
.image-card-info p { margin: 5px 0 10px; color: var(--text-subtle); font-size: var(--fs-caption); }
.image-actions { display: flex; flex-wrap: wrap; gap: 7px; }
.image-actions a, .image-actions button { padding: 7px 11px; border: 1px solid #dddde5; border-radius: var(--r-sm); color: var(--text-muted); background: #fff; font-size: var(--fs-caption); font-weight: var(--w-semibold); text-decoration: none; cursor: pointer; transition: .16s; }
.image-actions a:hover, .image-actions button:hover:not(:disabled) { border-color: var(--violet); color: var(--violet); }
.image-actions .video-delete { padding: 7px 11px; font-size: var(--fs-caption); }
/* ===== 첫 프레임 모드 (텍스트만 / 업로드 / AI) ===== */
.segmented.source-mode { grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); margin-top: 11px; }
.segmented.source-mode button { min-height: 36px; font-size: var(--fs-small); }
.frame-mode-body { margin-top: 13px; }
.frame-ai-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 11px; }
.frame-ai-actions .outline-action svg { width: 15px; height: 15px; }
.frame-ai-result { display: flex; align-items: flex-start; gap: 13px; margin-top: 13px; padding: 11px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fcfcfd; }
.frame-ai-result img { width: 132px; border-radius: var(--r-sm); object-fit: cover; }
.frame-ai-result strong { display: block; font-size: var(--fs-body); }
.frame-ai-result small { display: block; margin: 5px 0 8px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }

/* ===== 화풍 변환 (NEW_영상 제작 1단계) =====
   결과 미리보기는 .frame-ai-result 와 같은 위계이므로 그 규칙을 함께 쓴다.
   같은 모양을 두 번 정의하면 한쪽만 고쳐져 화면이 갈린다. */
.convert-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: 11px; }
.convert-actions .outline-action svg { width: 15px; height: 15px; }
.convert-result { display: flex; align-items: flex-start; gap: 13px; margin-top: 13px; padding: 11px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fcfcfd; }
.convert-result img { width: 176px; border-radius: var(--r-sm); object-fit: cover; }
.convert-result > div { flex: 1; min-width: 0; }
.convert-result strong { display: block; font-size: var(--fs-body); }
.convert-result small { display: block; margin: 5px 0 8px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.convert-result-actions { display: flex; flex-wrap: wrap; gap: 12px; }
.convert-result details { margin-top: 9px; }
.convert-result summary { color: var(--text-subtle); font-size: var(--fs-caption); cursor: pointer; }
.convert-result pre { margin: 7px 0 0; padding: 9px; border-radius: var(--r-sm); background: #f4f4f7; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); white-space: pre-wrap; word-break: break-word; }
/* 강도 슬라이더. legend 안의 현재 값이 눈에 들어와야 조절이 의미를 갖는다. */
#wanStrengthField legend b { margin-left: 4px; color: var(--violet); font-variant-numeric: tabular-nums; }
#wanStrength { width: 100%; margin-top: 6px; accent-color: var(--violet); }

/* ===== 롱테이크 ===== */
.long-take-button { width: 100%; margin-top: 13px; }
.long-take-button svg { width: 16px; height: 16px; }
.sequence-panel { margin-top: 15px; padding-top: 14px; border-top: 1px solid #eeeef2; }
.sequence-head { display: flex; align-items: center; justify-content: space-between; gap: 9px; margin-bottom: 9px; }
.sequence-head strong { overflow: hidden; font-size: var(--fs-body); text-overflow: ellipsis; white-space: nowrap; }
.sequence-panel .job-bar { height: 6px; overflow: hidden; border-radius: var(--r-pill); background: #eeeef2; }
.sequence-panel .job-bar i { display: block; height: 100%; width: 0; border-radius: var(--r-pill); background: var(--violet); transition: width .4s; }
.sequence-shots { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 11px; }
.shot-chip { display: grid; place-items: center; min-width: 22px; min-height: 22px; border-radius: var(--r-xs); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.shot-chip.done { color: #fff; background: var(--ok); }
.shot-chip.failed { color: #fff; background: #c2415a; }
.shot-chip.pending { color: var(--text-subtle); background: #f1f1f4; }

/* ===== 프로젝트 -> 제작 연결 ===== */
.handoff-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.handoff-card { display: flex; flex-direction: column; gap: 7px; padding: 16px 14px; border: 1px solid #dddde5; border-radius: var(--r-md); text-align: left; background: #fff; cursor: pointer; transition: .16s; }
.handoff-card:hover { border-color: var(--violet); background: var(--accent-soft); transform: translateY(-1px); }
.handoff-icon { display: grid; place-items: center; width: 32px; height: 32px; border-radius: var(--r-sm); color: var(--violet); background: var(--accent-soft); }
.handoff-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.handoff-card strong { font-size: var(--fs-body-lg); font-weight: var(--w-semibold); }
.handoff-card small { color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
/* [콘티]는 누르면 아래 옵션 칸이 열린다. 어느 카드 때문에 칸이 열렸는지 표시해 둔다. */
.handoff-card.active { border-color: var(--violet); background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--violet); }
.handoff-card:disabled { opacity: .5; cursor: not-allowed; }
.handoff-card:disabled:hover { border-color: #dddde5; background: #fff; transform: none; }

/* 모델 관리 안의 사용량 절 */
.usage-section { margin-top: 34px; padding-top: 26px; border-top: 1px solid var(--line); }

@media (max-width: 820px) {
  .handoff-grid { grid-template-columns: 1fr; }
  .segmented.source-mode { grid-template-columns: 1fr; }
  .frame-ai-result { flex-direction: column; }
  .frame-ai-result img { width: 100%; }
  .convert-result { flex-direction: column; }
  .convert-result img { width: 100%; }
}


/* ===========================================================================
   상태 · 접근성
   이 구획은 기존 규칙을 고치지 않고 뒤에 덧붙이기만 한다.
   되돌리려면 이 구획만 통째로 지우면 된다.
   =========================================================================== */

/* --- 포커스 --- */
/* 전에는 포커스 표시가 입력 8곳 + 카드 2곳뿐이었고, 알파 .08~.10 짜리 보라 발광이라
   배경 대비 1.13:1 로 사실상 보이지 않았다. 키보드로 조작하면 지금 어디에 있는지 알 수 없었다.
   :focus 가 아니라 :focus-visible 을 쓴다. 마우스 클릭에는 링이 뜨지 않고 키보드에만 뜬다. */
:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}
/* 어두운 표면 위에서는 강조색이 배경에 묻힌다. 밝은 링을 쓴다. */
:where(.sidebar, .login-showcase) :where(a, button, [tabindex]):focus-visible {
  outline-color: var(--on-dark);
}
/* 파일 입력을 감싼 라벨. 입력 자체가 화면에서 숨겨져 있으므로 라벨이 링을 대신 그린다. */
.upload-cover:focus-within,
.dropzone:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 화면에서는 감추되 키보드와 스크린리더에는 남긴다.
   전에는 hidden 속성을 써서 파일 입력이 포커스를 받지 못했고,
   그래서 표지 등록 · 원본 불러오기 · 참조 이미지를 키보드로 쓸 수 없었다. */
.sr-only-focusable {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* 본문 바로가기. 키보드 사용자가 사이드바 전체를 지나치지 않아도 되게 한다. */
.skip-link {
  position: absolute;
  left: 8px; top: -60px;
  z-index: 999;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  color: #fff;
  background: var(--accent);
  font-size: var(--fs-body);
  font-weight: var(--w-semibold);
  transition: top .15s;
}
.skip-link:focus { top: 8px; }

/* --- 눌림 피드백 --- */
/* 전에는 :active 가 3곳뿐이었다. 누른 순간의 반응이 없으면 클릭이 먹었는지 알 수 없다. */
:where(button, .nav-item, .style-chip, .segmented button, .doc-option, .handoff-card,
       .input-type, .suggestions button, .card-actions button, .row-actions button):active {
  transform: translateY(1px);
}

/* --- 한글 줄바꿈 --- */
/* 한글은 어절 중간에서 끊으면 읽기 어렵다. keep-all 로 어절 단위로 끊는다.
   긴 파일명·URL 은 어절이 없어 넘칠 수 있으므로 그런 곳만 anywhere 로 되돌린다. */
:where(h1, h2, h3, h4, p, li, small, strong, label, button, td, th, figcaption, summary) {
  word-break: keep-all;
  overflow-wrap: anywhere;
}
:where(code, .model-table code, .file-chip strong, .image-card-info strong,
       .video-card-info strong) {
  word-break: break-all;
}

/* --- 모션 --- */
/* 전정기관 장애가 있는 사용자를 위한 필수 대응. 전에는 대응이 없었다.
   전환과 애니메이션을 완전히 끄지 않고 즉시 끝나게 한다. 그래야 상태 변화 자체는 남는다. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  /* 영상 자체의 반복 모션은 정적 포스터로 대체한다. */
  .login-motion-video { display: none; }
  :where(button, .nav-item, .card-actions button):active { transform: none; }
}

/* --- Windows 고대비 모드 --- */
/* 고대비 모드에서는 배경색이 전부 시스템 색으로 치환되어 테두리 없는 요소가 사라진다. */
@media (forced-colors: active) {
  /* 장식용 영상은 시스템 색으로 의미 없는 윤곽만 남으므로 감춘다. */
  .login-motion { display: none; }
  .brand-logo-surface { forced-color-adjust: none; }
  .primary-button, .danger-button, .outline-action, .nav-item, .segmented button,
  .style-chip, .doc-chip, .stage-badge, .visibility-badge {
    border: 1px solid ButtonBorder;
  }
  :where(a, button, input, textarea, [tabindex]):focus-visible {
    outline: 3px solid Highlight;
  }
  .job-bar > i, .quota > div > i { forced-color-adjust: none; }
}

/* ===== 콘티 기획표 ===== */
/* 컷별 그림과 설명이 짝을 이루는 표. 실제 콘티 양식(Cut / Video / Context / Audio / Time)을 따랐다.
   인쇄해서 회의에 들고 가는 것이 목적이라 화면과 인쇄를 함께 고려한다. */
.storyboard-options { margin-top: 18px; padding: 15px 16px; border: 1px solid #e4e0f7; border-radius: 13px; background: #fbfaff; }
.storyboard-options .options-row { margin-top: 0; }
.storyboard-options .field-hint { margin-top: 10px; }
/* 결과물 만들기의 콘티 옵션 머리·발. 무엇의 설정인지 적고 실행 버튼을 옵션 안에 둔다. */
.storyboard-options-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.storyboard-options-head strong { font-size: var(--fs-body); font-weight: var(--w-semibold); }
.storyboard-options-head .text-action { margin-left: auto; color: var(--text-subtle); }
.storyboard-options-head .text-action:hover { color: var(--accent); }
.storyboard-options-foot { display: flex; justify-content: flex-end; margin-top: 13px; }

.storyboard-panel { margin-top: 26px; }
.sb-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.sb-actions .outline-action svg { width: 14px; height: 14px; }
.storyboard-panel .job-bar { height: 6px; margin-top: 12px; overflow: hidden; border-radius: 99px; background: #eeeef2; }
.storyboard-panel .job-bar i { display: block; width: 0; height: 100%; border-radius: 99px; background: var(--violet); transition: width .4s; }
.sb-error { margin-top: 10px; padding: 10px 12px; border-radius: 10px; color: #8d2f45; background: #fdeef1; font-size: var(--fs-small); }

.sb-sheet-head { display: flex; flex-wrap: wrap; gap: 20px; margin: 16px 0 10px; padding-bottom: 9px; border-bottom: 2px solid #2c2c33; font-size: var(--fs-small); color: #6b6b76; }
.sb-sheet-head b { color: #2c2c33; }

.sb-sheet-wrap { overflow-x: auto; border: 1px solid #d8d8de; border-radius: 10px; background: #fff; }
.sb-sheet { width: 100%; min-width: 720px; border-collapse: collapse; table-layout: fixed; }
.sb-sheet th { padding: 9px 10px; border-bottom: 2px solid #2c2c33; color: #2c2c33; background: #f6f6f8; font-size: var(--fs-small); font-weight: 800; text-align: center; }
.sb-sheet td { padding: 10px; border-bottom: 1px solid #ddddE3; border-right: 1px solid #eeeef2; font-size: var(--fs-small); line-height: 1.7; vertical-align: top; }
.sb-sheet td:last-child { border-right: 0; }
.sb-sheet tr:last-child td { border-bottom: 0; }

.sb-col-cut { width: 52px; text-align: center; }
.sb-col-video { width: 240px; }
.sb-col-context { width: auto; }
.sb-col-audio { width: 200px; }
.sb-col-time { width: 54px; text-align: center; }

.sb-cut-no { display: block; font-size: 13px; font-weight: 850; color: #2c2c33; }
.sb-col-cut small { display: block; margin-top: 4px; color: #9a9aa4; font-size: 8px; }

/* 그림 칸. 비율을 고정해 표가 컷마다 들쭉날쭉해지지 않게 한다. */
.sb-frame { display: grid; place-items: center; overflow: hidden; aspect-ratio: 16 / 9; border: 1.5px solid #2c2c33; border-radius: 4px; background: #f1f1f4; }
.sb-frame img { width: 100%; height: 100%; object-fit: cover; }
.sb-frame.pending { border-style: dashed; border-color: #b9b9c2; }
.sb-frame.failed { border-color: #d8a2ae; background: #fdeef1; }
.sb-frame-note { color: #9a9aa4; font-size: 8px; }
.sb-frame-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 5px; }
.sb-mode-body { margin-top: 13px; }
.storyboard-options .segmented.source-mode { grid-template-columns: repeat(2, 1fr); margin-top: 0; }

.sb-col-audio b { display: inline-block; min-width: 30px; margin-right: 4px; color: var(--violet); font-size: 8px; font-weight: 800; }
.sb-dim { color: #b9b9c2; }
.sb-row.failed .sb-col-context { color: #8d2f45; }

@media (max-width: 820px) {
  .sb-col-video { width: 160px; }
  .sb-col-audio { width: 140px; }
}

/* --- 인쇄 --- */
/* 기획 문서와 사용량 표를 회의에 들고 가는 일이 있다. 전에는 인쇄 대응이 전혀 없어서
   사이드바와 어두운 배경이 그대로 나갔다. */
@media print {
  .sidebar, .topbar, .menu-button, .sidebar-close, .toast, .modal-scrim,
  .ambient, .skip-link, .card-actions, .row-actions, .detail-cover-actions,
  .panel-foot, .detail-foot { display: none !important; }
  body, .app-shell, .workspace, .content { background: #fff !important; color: #000 !important; }
  .panel, .poster-card, .tile-card, .image-card, .video-card, .doc-step {
    border: 1px solid #999 !important;
    box-shadow: none !important;
    break-inside: avoid;
  }
  a[href]::after { content: ""; }
  .content { padding: 0 !important; }

  /* 콘티 기획표를 인쇄할 때는 표만 남긴다. 회의 자료로 쓰는 것이 목적이다. */
  .storyboard-panel ~ *, .page-intro, .studio-layout, .running-panel,
  .sb-actions, .storyboard-panel .job-bar, .sb-frame-actions { display: none !important; }
  .storyboard-panel { margin: 0 !important; border: 0 !important; }
  /* 여러 장으로 넘어갈 때 각 장에 머리행을 다시 그린다. */
  .sb-sheet thead { display: table-header-group; }
  .sb-sheet tr { break-inside: avoid; }
  /* overflow 래퍼는 인쇄에서 내용을 잘라낸다. */
  .sb-sheet-wrap { overflow: visible !important; border: 0 !important; }
  .sb-sheet { min-width: 0 !important; }
  .sb-frame { border-color: #000 !important; }

  /* 결과물 리더의 인쇄 규칙은 여기에 두지 않는다. 리더 스타일 구획의
     `body.reader-open` 블록 하나가 맡는다 — 같은 규칙을 두 곳에 두면 뒤에 오는
     쪽이 조용히 이기고, 실제로 그렇게 AI 생성 표기가 인쇄물에서 사라졌다. */

  /* A4 로 고정한다. 브라우저 기본 용지는 지역에 따라 Letter(216×279mm) 라서,
     같은 콘티를 뽑아도 사람마다 표 폭과 페이지 나눔이 달라진다. 회의 자료로 돌리는
     문서라 규격이 흔들리면 안 된다. 참고 문서(콘티_러프)도 A4 다.
     사용자가 인쇄 대화상자에서 다른 용지를 고를 수는 있다 — 기본값만 정한다. */
  @page { size: A4 portrait; margin: 12mm; }
}

/* --- 뷰포트 안정 --- */
/* 100dvh 는 iOS Safari 에서 주소창 높이를 포함해 스크롤이 튄다. 100dvh 로 바꾼다. */

/* 결과가 아직 없을 때 무대를 줄인다.
   콘티 화면에서는 이 검은 상자 바로 아래에 실제 이미지 목록이 있어서,
   비어 있는 상자가 실제 결과보다 큰 자리를 차지하고 있었다. */
.output-stage:has(.empty-output:not(.is-hidden)) { min-height: 168px; }
.output-stage:has(.empty-output:not(.is-hidden)) .empty-output > span { width: 42px; height: 42px; margin-bottom: 9px; }
.output-stage:has(.empty-output:not(.is-hidden)) .empty-output svg { width: 22px; height: 22px; }

/* ===========================================================================
   스켈레톤 로딩
   전에는 로딩 표시가 "버튼 비활성화"뿐이었다. 목록을 불러오는 동안 화면이 비어 있다가
   갑자기 채워져서, 느린 회선에서는 "빈 목록"과 "아직 로딩 중"을 구분할 수 없었다.
   원형 스피너 대신 실제 카드와 같은 모양을 그린다. 그래야 레이아웃이 튀지 않는다.
   =========================================================================== */
.skel {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: #fff;
}
.skel::before,
.skel::after {
  content: "";
  display: block;
  border-radius: var(--r-sm);
  background: #edecf1;
}
/* 표지 자리 */
.skel::before { border-radius: var(--r-lg) var(--r-lg) 0 0; }
/* 제목 자리 */
.skel::after { height: 13px; margin: 14px 14px 20px; }

.skel-poster::before { aspect-ratio: 2 / 3; }
.skel-tile::before { aspect-ratio: 4 / 5; }
.skel-image::before { aspect-ratio: 4 / 3; }
.skel-video::before { aspect-ratio: 16 / 9; }

/* 표 행 */
.skel-row { display: block; position: relative; overflow: hidden; height: 30px; border: 0; border-radius: var(--r-xs); background: #edecf1; }
.skel-row::before, .skel-row::after { display: none; }

/* 빛 훑기. 반복 애니메이션이므로 prefers-reduced-motion 에서 자동으로 멈춘다
   (앞의 접근성 구획이 transition/animation 을 .01ms 로 만든다). */
.skel-shimmer { position: absolute; inset: 0; background: linear-gradient(90deg, transparent, rgba(255,255,255,.75), transparent); animation: skelShimmer 1.25s ease-in-out infinite; }
@keyframes skelShimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* 확인 모달의 경고(비용 발생) 변형. 삭제가 아니므로 붉은색을 쓰지 않는다.
   되돌릴 수 없는 삭제와 비용이 드는 작업은 무게가 다르고, 색으로 구분한다. */
#confirmBanner.warn { border-color: var(--accent-line); background: var(--accent-soft); }
#confirmBanner.warn > span { color: #fff; background: var(--accent); }
#confirmBanner.warn strong { color: var(--text); }

/* 모달이 열려 있는 동안 뒤 페이지가 스크롤되지 않게 한다. */
body.modal-open { overflow: hidden; }

/* ===========================================================================
   오버플로 메뉴
   카드마다 액션 4개를 늘어놓던 것을 주 액션 1개 + 이 메뉴로 접었다.
   프로젝트 10개짜리 홈 화면에서 버튼 40개가 20개로 줄고, 되돌릴 수 없는 삭제가
   "새 창 열기"와 같은 무게로 보이던 문제도 사라진다.
   =========================================================================== */
.menu { position: relative; display: inline-flex; }

.menu-trigger {
  display: grid;
  place-items: center;
  width: 30px;
  min-height: 30px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--text-muted);
  background: #fff;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}
.menu-trigger:hover { border-color: var(--line-strong); background: var(--soft); }
.menu-trigger svg { width: 16px; height: 16px; fill: currentColor; stroke: none; }

.menu-list {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px);
  z-index: 40;
  display: grid;
  min-width: 176px;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: #fff;
  box-shadow: var(--e-3);
}
.menu-list[hidden] { display: none; }

.menu-item {
  display: block;
  width: 100%;
  padding: 9px 11px;
  border: 0;
  border-radius: var(--r-sm);
  color: var(--text-muted);
  background: transparent;
  font: inherit;
  font-size: var(--fs-caption);
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.menu-item:hover { background: var(--soft); color: var(--text); }
/* 삭제는 목록의 마지막에 두고 위에 선을 그어 손이 미끄러지지 않게 한다. */
.menu-item.danger { color: var(--danger); margin-top: 4px; border-top: 1px solid var(--line); border-radius: 0 0 var(--r-sm) var(--r-sm); padding-top: 11px; }
.menu-item.danger:hover { background: var(--danger-soft); color: var(--danger); }

/* 카드 액션 줄: 주 액션은 왼쪽, 메뉴는 오른쪽 끝. */
.card-actions, .image-actions, .video-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.card-actions > .menu, .image-actions > .menu, .video-actions > .menu { margin-left: auto; }

/* ===========================================================================
   제품 흐름 (진행률 · 진행 중 작업 · 프로젝트 맥락 · 산출물 의존)

   여기까지의 작업이 "보기 좋게"였다면 이 구획은 "일이 되게"다.
   전부 기존 API 안에서 해결한다. 백엔드 변경은 없다.
   =========================================================================== */

/* --- 프로젝트 진행률 --- */
/* 원본 자료 -> 기획 방향 -> AI 산출물 -> 제작.
   전에는 긴 스크롤을 끝까지 훑어야 어디까지 왔는지 알 수 있었다. */
.progress-track {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 14px 0 18px;
  padding: 0;
  list-style: none;
}
.progress-step {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  color: var(--text-subtle);
  background: #fff;
  font-size: var(--fs-caption);
}
.progress-mark {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border: 2px solid var(--line-strong);
  border-radius: 50%;
  background: #fff;
}
/* 완료: 체크. 배경색만으로 구분하지 않는다(색각 이상과 고대비 모드) */
.progress-step.done { border-color: var(--ok); color: var(--ok); }
.progress-step.done .progress-mark { border-color: var(--ok); background: var(--ok); }
.progress-step.done .progress-mark::after {
  content: "";
  width: 4px; height: 7px;
  margin-top: -2px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
/* 진행 중: 반쯤 채운 표시 */
.progress-step.partial { border-color: var(--accent); color: var(--accent); }
.progress-step.partial .progress-mark { border-color: var(--accent); background: linear-gradient(90deg, var(--accent) 50%, #fff 50%); }
/* 다음에 할 수 있는 것 */
.progress-step.next { border-color: var(--accent-line); color: var(--accent); }
.progress-step b { font-variant-numeric: tabular-nums; }

/* --- 산출물 의존 안내 --- */
/* documents.py 확인 결과 앞 단계를 참고하는 것은 트리트먼트 하나뿐이다.
   UI가 이 사실을 전혀 알려주지 않아 사용자는 아무거나 먼저 눌러도 되는 줄 알았다. */
.doc-step-context {
  margin: 8px 0 0;
  padding: 8px 11px;
  border-radius: var(--r-sm);
  color: var(--accent);
  background: var(--accent-soft);
  font-size: var(--fs-caption);
  line-height: var(--lh-normal);
}
.doc-step-context.ok { color: var(--ok); background: var(--ok-soft); }

/* --- 진행 중 작업: 상단바 칩 --- */
/* 롱테이크는 목표 10분이면 예상 335분이다. 어느 화면에 있든 보여야 한다. */
.running-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 12px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  color: var(--accent);
  background: var(--accent-soft);
  font-size: var(--fs-caption);
  font-weight: var(--w-semibold);
  cursor: pointer;
}
.running-chip:hover { background: #e7e1ff; }
.running-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: runningPulse 1.6s ease-in-out infinite;
}
@keyframes runningPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* --- 진행 중 작업: 라이브러리 패널 --- */
.running-panel {
  margin-bottom: 22px;
  padding: 19px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: var(--e-1);
}
.running-list { display: grid; gap: 13px; margin-top: 15px; }
.running-item {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--soft);
}
.running-item-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 9px; }
.running-item-head strong { font-size: var(--fs-body); }
.running-meta { margin: 8px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); font-variant-numeric: tabular-nums; }
.shot-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 10px; }

/* --- 프로젝트 맥락 배너 --- */
/* 주의: 이건 화면 맥락이지 저장 위치가 아니다.
   생성한 이미지·영상은 여전히 사용자 단위로 저장된다(S3 키에 프로젝트가 없다).
   그래서 "이 프로젝트에 저장됩니다"라고 쓰지 않는다. */
.from-project {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  padding: 9px 9px 9px 14px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  font-size: var(--fs-caption);
}
.from-project-label { color: var(--text-subtle); }
.from-project strong { color: var(--text); font-size: var(--fs-small); }
.from-project .text-action { margin-left: auto; color: var(--accent); }
.from-project-clear { width: 24px; height: 24px; }

@media (max-width: 560px) {
  .progress-track { gap: 5px; }
  .progress-step { padding: 6px 10px 6px 8px; }
  .from-project { flex-wrap: wrap; border-radius: var(--r-md); }
}

/* --- 생성 중 상단 배너 + 입력창 간략히 보기 --- */
/* 결과를 만들기 시작하면 입력창은 더 볼 일이 없고, 좁은 화면에서는 그것 때문에
   결과 패널이 밀려 잘렸다. 그래서 생성이 시작되면 화면 맨 위에 진행 상태를 띄우고
   입력 패널을 접어 결과만 남긴다. 접힌 상태는 언제든 다시 펼칠 수 있다. */
.run-banner {
  position: sticky;
  z-index: 15;
  top: 65px;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  margin-bottom: 20px;
  padding: 15px 18px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .97);
  box-shadow: var(--e-2);
  backdrop-filter: blur(14px);
}
.run-banner.done { border-color: rgba(27, 121, 83, .32); }
.run-banner.failed { border-color: rgba(224, 82, 96, .38); }

.run-spinner {
  width: 26px;
  height: 26px;
  border: 2px solid var(--accent-soft);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: runSpin .85s linear infinite;
}
@keyframes runSpin { to { transform: rotate(360deg); } }
/* 끝난 뒤에는 돌지 않는다. 계속 돌면 아직 진행 중으로 읽힌다. */
.run-banner.done .run-spinner { border-color: rgba(27,121,83,.24); border-top-color: var(--green); animation: none; }
.run-banner.failed .run-spinner { border-color: rgba(224,82,96,.24); border-top-color: #e05260; animation: none; }

.run-body { min-width: 0; }
.run-title { display: flex; align-items: center; gap: 9px; }
.run-title strong { font-size: var(--fs-body); }
.run-elapsed { color: var(--text-subtle); font-size: var(--fs-caption); font-variant-numeric: tabular-nums; }
.run-note { margin: 5px 0 0; overflow: hidden; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-snug); text-overflow: ellipsis; }
.run-banner.failed .run-note { color: var(--danger); }
.run-track { height: 4px; margin-top: 9px; overflow: hidden; border-radius: var(--r-pill); background: #ecebf1; }
.run-track i { display: block; width: 0; height: 100%; border-radius: inherit; background: var(--accent); transition: width .4s ease; }
.run-banner.done .run-track i { background: var(--green); }
.run-banner.failed .run-track i { background: #e05260; }
.run-actions { display: flex; align-items: center; gap: 8px; }

/* 접힌 입력 패널. display:none 이면 안에 있는 오류 문구까지 사라지므로
   실패했을 때는 자동으로 다시 펼친다(app.js endRun). */
.view.run-compact .split-layout > .split-input { display: none; }
.view.run-compact .split-layout { grid-template-columns: minmax(0, 1fr); }
.view.run-compact .split-layout > .split-bar { display: none; }
/* 결과 열이 전체 폭을 쓰게 되면 내부 2단은 오히려 읽기 좋다. */
.view.run-compact .preview-column { grid-template-columns: minmax(0, 1fr); }

@media (max-width: 820px) {
  .run-banner { top: 58px; grid-template-columns: 26px minmax(0, 1fr); padding: 13px 14px; }
  .run-spinner { width: 22px; height: 22px; }
  .run-actions { grid-column: 1 / -1; }
}

@media print {
  .run-banner { display: none !important; }
}

/* 생성 한도 조정 모달 ------------------------------------------------------- */
/* 두 항목을 나란히 둔다. 위아래로 쌓으면 "영상 10 / 이미지 50" 이 한눈에 비교되지 않아
   어느 쪽을 고치는지 헷갈린다. 좁은 화면에서는 한 줄로 떨어진다. */
.quota-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  margin: 12px 0;
}

/* 지금까지 쓴 건수. 한도 값과 사용량은 별개라, 저장 전에 현재 상태가 보여야
   "한도만 올려도 이미 쓴 건수는 남는다"를 이해할 수 있다. */
.quota-used {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  padding: 10px 12px;
  margin-bottom: 12px;
  border-radius: 8px;
  background: var(--surface-2, #f4f5f7);
  color: var(--text-2, #4a5160);
  font-size: 13px;
}

.quota-used:empty {
  display: none;
}

/* 프롬프트 두 계층 관리 --------------------------------------------------- */
/* 용도가 스무 개가 넘어 종류로 묶고, 각 항목을 카드로 분리한다. 한 표에 넣으면
   백엔드 원문이 길어 행 높이가 제각각이 되고 어디까지가 한 용도인지 읽히지 않는다. */
.prompt-group {
  margin: 20px 0 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-2, #4a5160);
}

.prompt-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.prompt-card {
  padding: 14px 16px;
  border: 1px solid var(--border, #e3e6ec);
  border-radius: 10px;
  background: var(--surface, #fff);
}

.prompt-card-head {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}

.prompt-card-head strong { display: block; }
.prompt-card-head small { color: var(--text-2, #4a5160); }

.prompt-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

/* 두 계층의 경계를 눈에 보이게 한다. 이 구분이 흐리면 관리자가 백엔드 내용을
   프론트엔드 칸에 다시 적어 같은 지시가 두 번 들어간다. */
.prompt-section-label {
  margin: 12px 0 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2, #4a5160);
}

/* 백엔드는 기본으로 접어 둔다. 원문이 수십 줄이라 펼친 상태로 두면 프론트엔드 편집
   칸이 화면 밖으로 밀린다. 감추지는 않는다(무엇이 고정인지 알아야 한다). */
.prompt-backend {
  margin-bottom: 6px;
  border: 1px solid var(--border, #e3e6ec);
  border-radius: 8px;
  background: var(--surface-2, #f7f8fa);
}

.prompt-backend > summary {
  padding: 8px 10px;
  cursor: pointer;
  font-size: 13px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.prompt-backend > summary small {
  display: block;
  margin-top: 2px;
  font-family: inherit;
  color: var(--text-2, #4a5160);
}

.prompt-backend pre {
  margin: 0;
  padding: 10px 12px;
  max-height: 320px;
  overflow: auto;
  border-top: 1px solid var(--border, #e3e6ec);
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
  line-height: 1.6;
}

.prompt-frontend textarea {
  width: 100%;
  resize: vertical;
  font-family: inherit;
  font-size: 13px;
}

.prompt-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-top: 8px;
}

.prompt-spacer { flex: 1; }
.prompt-actions .prompt-updated { color: var(--text-2, #4a5160); font-size: 12px; }

/* 백엔드 프롬프트 누락 경고. 지시서 8-2 는 이것이 0건이어야 한다고 요구한다. */
.prompt-alert {
  padding: 10px 12px;
  margin-bottom: 12px;
  border-radius: 8px;
  border: 1px solid #f0c36d;
  background: #fdf6e3;
  color: #7a5b00;
  font-size: 13px;
}

.prompt-history { display: flex; flex-direction: column; gap: 10px; max-height: 60vh; overflow: auto; }
.prompt-history-item { border: 1px solid var(--border, #e3e6ec); border-radius: 8px; }
.prompt-history-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 10px;
  background: var(--surface-2, #f7f8fa);
  font-size: 13px;
}
.prompt-history-item pre {
  margin: 0;
  padding: 10px 12px;
  border-top: 1px solid var(--border, #e3e6ec);
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
}

/* 매핑표는 열이 많아 기본 모달 폭으로는 가로 스크롤만 생긴다. */
.modal.wide { max-width: 960px; width: calc(100vw - 48px); }

/* 두 영상 기능의 비교 안내 ------------------------------------------------- */
/* 영상 기능이 둘이라(Bedrock 짧은 컷 / 자체 GPU 원작 화풍) 어느 쪽을 골라야 하는지
   각 화면에서 알려 준다. 본문보다 약하게 보이되 읽히게 한다. 두 기능은 공존한다. */
.feature-compare {
  margin-top: 8px;
  padding: 8px 10px;
  border-left: 3px solid var(--border, #e3e6ec);
  background: var(--surface-2, #f7f8fa);
  border-radius: 0 6px 6px 0;
  font-size: 13px;
  color: var(--text-2, #4a5160);
}

/* 문장 안에 들어가는 이동 버튼. button 이라 기본 스타일을 지우고 링크처럼 보이게 한다
   (a 태그를 쓰면 SPA 라우팅을 우회해 새로고침이 일어난다). */
.link-action {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--accent, #2f6feb);
  text-decoration: underline;
  cursor: pointer;
}

.link-action:hover { text-decoration: none; }

/* 화풍 변환 모델을 쓸 수 없을 때의 안내 --------------------------------------
   경고로 보이되 화면을 막지는 않는다. [원본 그대로]로 계속할 수 있기 때문이다. */
.convert-unavailable {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid #f0c36d;
  background: #fdf6e3;
  color: #7a5b00;
  font-size: 13px;
}


/* ===========================================================================
   스토리 개편 (로그라인 / 콘티 / 대본)
   기존 클래스를 최대한 재사용하고 이 화면에만 필요한 것만 둔다.
   되돌리려면 이 구획만 통째로 지우면 된다.
   =========================================================================== */

/* 요약 스토리 아래 줄. 글자 수와 자동 요약 버튼을 양끝에 둔다. */
.story-summary-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 7px; }
.story-summary-foot .field-hint { margin: 0; }

/* 이미지 첨부 구획 */
.story-attach { margin-top: 16px; }

/* 분석 카드. 지시서 3절이 요구한 항목(종류·인물·배경·분위기·화풍·이미지 속 텍스트·용도)을
   한 카드에 담고 편집 가능하게 한다. */
.story-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px; margin-top: 13px; }
.story-card { display: flex; flex-direction: column; border: 1px solid var(--line); border-radius: var(--r-md); background: #fff; overflow: hidden; }
.story-card.edited { border-color: var(--violet); box-shadow: inset 2px 0 var(--violet); }
.story-card-thumb { position: relative; aspect-ratio: 4/3; background: #f1f1f4; }
.story-card-thumb img { width: 100%; height: 100%; object-fit: cover; }
.story-card-kind { position: absolute; left: 8px; top: 8px; }
.story-card-body { display: grid; gap: 7px; padding: 12px; }
.story-card-body strong { font-size: var(--fs-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.story-field { display: grid; gap: 3px; }
.story-field label { color: var(--text-subtle); font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.story-field textarea { width: 100%; min-height: 44px; padding: 7px 9px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); outline: 0; color: var(--text); background: #fff; font-size: var(--fs-caption); line-height: var(--lh-normal); resize: vertical; }
.story-field textarea:focus { border-color: var(--violet); outline: 2px solid var(--accent); outline-offset: 1px; }
/* 말풍선 전사는 길다. 다른 칸보다 크게 둔다. */
.story-field.tall textarea { min-height: 76px; }
.story-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 12px 12px; }
.story-card-flags { display: flex; flex-wrap: wrap; gap: 4px; }
/* 안전 플래그. 이 표시가 있으면 생성이 막힌다. 눈에 띄어야 한다. */
.story-flag { padding: 2px 7px; border-radius: var(--r-pill); color: var(--danger); background: var(--danger-soft); font-size: var(--fs-caption); font-weight: var(--w-bold); }

/* 결과물 목록 */
.story-outputs { display: grid; gap: 11px; }
.story-output { padding: 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fff; }
.story-output.needs-review { border-color: #f0c36d; background: #fffdf7; }
.story-output.failed { border-color: var(--danger-soft); }
.story-output-head { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.story-output-head strong { flex: 1; min-width: 0; overflow: hidden; font-size: var(--fs-body-lg); text-overflow: ellipsis; white-space: nowrap; }
.story-output-meta { margin: 7px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); }
.story-output-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.story-output-actions a { text-decoration: none; }

/* AI 생성 표기. 지시서 0절이 모든 생성물에 요구한다.
   뱃지를 눈에 띄지만 방해되지 않게 둔다 — 모든 결과물에 붙으므로 시끄러우면 안 된다. */
.ai-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: var(--r-pill); color: var(--violet); background: var(--accent-soft); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: .3px; }
.ai-badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* 스토리 계보 표시 ---------------------------------------------------------
   프로젝트는 고유한 스토리 하나를 갖고, 결과물은 그 스토리로 만든 것만 보관한다.
   스토리 수정을 막지는 않으므로(막으면 프로젝트가 잠긴다) 어긋났다는 사실을 보인다.

   danger 색을 쓰지 않는다. 이것은 오류가 아니라 사실 안내다 — 결과물은 정상이고,
   근거가 된 스토리가 그 뒤에 바뀌었을 뿐이다. 실패(빨강)와 같은 색이면 사용자는
   결과물이 잘못된 줄 알고 지운다. */
.doc-chip.drift { color: #8a5a00; background: #fdf1d8; }
.story-drift { display: grid; gap: 4px; margin-top: 10px; padding: 10px 12px; border-left: 3px solid #e0a83a; border-radius: 0 var(--r-sm) var(--r-sm) 0; background: #fffaf0; }
.story-drift p { margin: 0; color: #7a5b00; font-size: var(--fs-caption); line-height: var(--lh-body); }
.story-drift b { font-weight: var(--w-bold); }
.story-drift-snapshot { overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; color: #8a6a10 !important; }
.story-drift-hint { color: var(--text-subtle) !important; }

/* 검수 메모. needs_review 인 결과물에 무엇이 걸렸는지 보여준다(지시서 3절). */
.review-notes { display: grid; gap: 6px; margin-top: 10px; padding: 10px 12px; border-radius: var(--r-sm); background: #fdf6e3; }
.review-note { color: #7a5b00; font-size: var(--fs-caption); line-height: var(--lh-normal); }
.review-note b { font-weight: var(--w-bold); }
.review-note .fix { display: block; margin-top: 2px; color: #8a6a10; }

/* 아웃라인 승인 목록 */
.outline-list { display: grid; gap: 10px; max-height: 52vh; overflow-y: auto; margin: 12px 0; }
.outline-item { padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--r-md); background: #fff; }
.outline-item h3 { margin: 0 0 5px; font-size: var(--fs-body-lg); }
.outline-item p { margin: 0 0 7px; color: var(--text-muted); font-size: var(--fs-body); line-height: var(--lh-body); }
.outline-beats { margin: 0; padding-left: 17px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-body); }
.outline-hook { margin: 8px 0 0; padding: 7px 10px; border-left: 3px solid var(--violet); border-radius: 0 6px 6px 0; color: var(--accent); background: var(--accent-soft); font-size: var(--fs-caption); }

/* 회차 진행률 */
.episode-list { display: grid; gap: 8px; margin-top: 11px; }
.episode-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; }
.episode-row strong { flex: 1; min-width: 0; overflow: hidden; font-size: var(--fs-body); text-overflow: ellipsis; white-space: nowrap; }
.episode-row.done { border-color: var(--ok-soft); }
.episode-row.failed { border-color: var(--danger-soft); }
.episode-no { display: grid; place-items: center; min-width: 30px; min-height: 24px; border-radius: var(--r-xs); color: var(--text-subtle); background: #f1f1f4; font-size: var(--fs-caption); font-weight: var(--w-bold); }

/* 역할별 사용량(trace). 지시서 9절이 trace 확인을 수용 기준으로 둔다. */
.trace-table { width: 100%; margin-top: 11px; border-collapse: collapse; font-size: var(--fs-caption); }
.trace-table th, .trace-table td { padding: 6px 8px; border-bottom: 1px solid #eeeef2; text-align: left; }
.trace-table th { color: var(--text-subtle); font-weight: var(--w-semibold); }
.trace-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.trace-cache { color: var(--ok); font-weight: var(--w-bold); }

@media (max-width: 820px) {
  .story-cards { grid-template-columns: 1fr; }
  .story-summary-foot { flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* ===========================================================================
   결과물 읽기 뷰어 (#readerModal)

   전에는 확인 모달(confirmDialog)을 재사용했다. 그 모달의 본문은 danger-banner
   안의 <p> 하나였다 — 대본이 붉은 경고문처럼 보이고, textContent 로 넣은 줄바꿈이
   전부 공백으로 뭉개졌다. 여기서는 읽는 것만 한다.

   원고지처럼 보이게 하려고 본문 배경을 살짝 따뜻한 흰색으로 두고, 씬 제목 ·
   지문 · 대사에 각각 다른 위계를 준다. 줄바꿈은 pre-wrap 으로 그대로 살린다.
   =========================================================================== */
.modal.reader {
  display: flex; flex-direction: column;
  width: min(100%, 780px); max-height: min(90vh, 940px);
  padding: 22px 22px 18px;
  overflow: hidden;               /* 스크롤은 .reader-page 안에서만 일어난다 */
}
.modal.reader .modal-head { flex: none; align-items: flex-start; gap: 14px; margin-bottom: 14px; }
.reader-title { min-width: 0; }
.reader-title h2 { margin: 0; font-size: var(--fs-h3); letter-spacing: -.5px; overflow-wrap: anywhere; }
.reader-meta { margin: 5px 0 0; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.reader-meta:empty { display: none; }

.reader-toolbar { flex: none; display: flex; align-items: center; flex-wrap: wrap; gap: 10px; padding-bottom: 13px; border-bottom: 1px solid var(--line); }
.reader-count { color: var(--text-subtle); font-size: var(--fs-caption); font-variant-numeric: tabular-nums; }
.reader-toolbar-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.reader-toolbar-actions .text-action { color: var(--text-muted); }
.reader-toolbar-actions .text-action:hover { color: var(--accent); }
.reader-toolbar-actions .outline-action svg { width: 15px; height: 15px; }
.reader-toolbar-actions .outline-action:hover:not(:disabled) { border-color: var(--accent-line); color: var(--accent); background: var(--accent-soft); }
/* 본문이 비면 버튼을 끈다. 눌러도 되는 것처럼 보이면 빈 파일을 받고 원인을 못 찾는다. */
.reader-toolbar-actions button:disabled { opacity: .45; cursor: not-allowed; }

.reader-page {
  flex: 1 1 auto; min-height: 180px; overflow-y: auto;
  margin-top: 15px; padding: 26px 30px;
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: #fffdf8;            /* 종이 느낌. 순백보다 눈이 덜 시리다 */
  color: var(--text);
  font-size: var(--fs-body-lg); line-height: 1.85;
}
.reader-page:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* 씬(슬러그). 대본에서 위치를 잡아 주는 유일한 표지라 가장 강한 위계를 준다. */
.reader-scene + .reader-scene { margin-top: 26px; padding-top: 22px; border-top: 1px dashed #e4ded0; }
.reader-slug {
  margin: 0 0 12px; padding-left: 11px;
  border-left: 3px solid var(--violet); border-radius: 0 4px 4px 0;
  color: var(--accent-strong); font-size: var(--fs-body-lg); font-weight: var(--w-bold);
  letter-spacing: .2px; line-height: var(--lh-snug); overflow-wrap: anywhere;
  white-space: pre-wrap;
}

/* 지문. 모델이 넣은 줄바꿈을 그대로 살린다 — 문단을 한 줄로 이어 붙이면
   "무엇이 한 동작인지"가 사라진다. */
.reader-action { margin: 0 0 12px; color: var(--text-muted); white-space: pre-wrap; overflow-wrap: anywhere; }
.reader-action:last-child { margin-bottom: 0; }

/* 대사. 인물명을 위에 두고 대사를 한 단 들여 쓴다(한국 드라마 대본 관습). */
.reader-cue { margin: 0 0 14px; padding-left: 26px; }
.reader-cue:last-child { margin-bottom: 0; }
.reader-character { display: block; color: var(--text); font-size: var(--fs-body); font-weight: var(--w-bold); letter-spacing: .4px; }
.reader-line { margin: 1px 0 0; padding-left: 14px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }

/* 보조 정보(장르 · 톤 · 영어 프롬프트 등). 본문보다 한 단 낮춘다. */
.reader-note { display: flex; gap: 7px; margin: 0 0 7px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-body); }
.reader-note b { flex: none; color: var(--text-muted); font-weight: var(--w-semibold); }
.reader-note span { min-width: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* 엔딩 훅. 회차의 끝이라는 것이 보여야 한다. */
.reader-hook { margin: 20px 0 0; padding: 11px 14px; border-left: 3px solid var(--violet); border-radius: 0 var(--r-sm) var(--r-sm) 0; background: var(--accent-soft); color: var(--accent-strong); font-size: var(--fs-body); line-height: var(--lh-body); white-space: pre-wrap; overflow-wrap: anywhere; }
.reader-hook b { display: block; margin-bottom: 3px; font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: .3px; }

.reader-empty { margin: 0; color: var(--text-subtle); font-size: var(--fs-body); }

/* 콘티 기획표 모드 -------------------------------------------------------
   콘티는 글이 아니라 표다. .sb-sheet 가 최소 720px를 요구하고 컬럼이 다섯이라
   대본용 폭(780px)으로는 가로 스크롤만 생긴다. 표일 때만 넓힌다.

   표 자체의 모양은 .sb-sheet 계열이 갖고 있다(콘티 기획표 화면과 공유). 여기서는
   리더 안에 놓기 위한 여백과 배경만 손댄다 — 같은 표를 두 번 정의하지 않는다. */
.modal.reader.is-sheet { width: min(100%, 1120px); }

/* 리더를 열어 둔 채 브라우저 인쇄(Ctrl+P)를 눌렀을 때.
   `body.reader-open` 은 openReader 가 붙인다.

   **화면의 인쇄 버튼은 없앴다.** 콘티·대본은 서버가 만든 PDF 를 내려받는다 — 인쇄
   대화상자는 문서에 접속 URL 과 시각을 찍고 사람마다 다른 결과를 냈다
   (app/src/pdf_export.py 주석 참고).

   **그래도 이 블록은 남긴다.** Ctrl+P 는 브라우저가 주는 동작이라 막을 수 없다. 그리고
   위쪽 @media print 가 `.modal-scrim` 을 숨기기 때문에, 규칙이 없으면 **모달이 아니라
   뒤에 있던 앱 화면이 찍힌다.** 사용자가 보고 있는 것과 종이가 다른 상태를 두지 않는다. */
@media print {
  /* 모달만 남긴다. .ambient / .app-shell / #loginScreen / .toast 가 body 직계다. */
  body.reader-open > *:not(.modal-scrim) { display: none !important; }
  body.reader-open .modal-scrim.is-hidden { display: none !important; }
  body.reader-open .modal-scrim {
    display: block !important; position: static !important;
    padding: 0 !important; background: none !important; backdrop-filter: none !important;
  }
  body.reader-open .modal.reader {
    width: auto !important; max-height: none !important; padding: 0 !important;
    overflow: visible !important; border: 0 !important; box-shadow: none !important;
  }
  /* 닫기 버튼과 아래 버튼은 종이에 필요 없다. 제목·표기·표만 남긴다. */
  body.reader-open .modal.reader .modal-head .icon-button,
  body.reader-open .reader-toolbar-actions,
  body.reader-open .modal.reader .modal-actions { display: none !important; }
  /* 도구줄 자체는 남긴다. 지시서 0절이 생성물에 AI 생성 표기를 요구하고,
     인쇄물은 앱을 떠나 따로 돌아다니므로 그 표기가 가장 필요한 곳이다. */
  body.reader-open .reader-toolbar { padding-bottom: 6px !important; border-bottom: 0 !important; }
  body.reader-open .reader-page {
    max-height: none !important; overflow: visible !important;
    padding: 0 !important; border: 0 !important; background: #fff !important;
  }
}
.reader-page.is-sheet { padding: 18px 20px; background: #fff; font-size: var(--fs-body); line-height: var(--lh-normal); }
.reader-page.is-sheet .sb-sheet-head { margin-top: 0; }
.reader-sheet-meta { margin: 0 0 12px; color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }

@media (max-width: 1180px) {
  .modal.reader.is-sheet { width: calc(100vw - 40px); }
}

@media (max-width: 820px) {
  .modal.reader { max-height: 94vh; padding: 18px 16px 14px; }
  .reader-page { padding: 18px 16px; }
  .reader-toolbar-actions { width: 100%; margin-left: 0; }
  .reader-cue { padding-left: 12px; }
}

/* ===================== 베타 표기 · 이전 방식 안내 =====================
   발주 요청: Bedrock 영상 만들기는 베타이며, AWS Bedrock 모델을 체험하게 하는
   기능이라는 것을 화면 상단에서 밝힌다. 경고가 아니라 안내이므로 danger 색을 쓰지 않는다. */
.beta-tag { display: inline-block; margin-left: 8px; padding: 3px 8px; border-radius: var(--r-pill); color: #fff; background: var(--orange); font-size: var(--fs-micro); font-weight: var(--w-bold); letter-spacing: 1px; vertical-align: middle; }
.beta-banner { display: grid; gap: 5px; max-width: 720px; margin: 14px 0 16px; padding: 13px 15px; border: 1px solid var(--accent-line); border-radius: var(--r-md); background: var(--accent-soft); }
.beta-banner strong { color: var(--accent-strong); font-size: var(--fs-body); }
.beta-banner p { margin: 0; color: var(--text-muted); font-size: var(--fs-small); line-height: var(--lh-body); }

/* 프로젝트 상세에서 새 스토리 흐름과 옛 작업 구획을 가르는 접이식 구획.
   옛 구획은 아직 동작하므로 지우지 않고 접어서 최소화한다(기본 닫힘). */
.legacy-section { margin: 34px 0 0; padding-top: 18px; border-top: 1px dashed var(--line); }
.legacy-summary {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  padding: 11px 14px; border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--soft); cursor: pointer; list-style: none;
}
.legacy-summary::-webkit-details-marker { display: none; }
.legacy-summary::before {
  content: ""; flex: none; align-self: center; width: 7px; height: 7px; margin-right: 3px;
  border-right: 1.6px solid var(--text-subtle); border-bottom: 1.6px solid var(--text-subtle);
  transform: rotate(-45deg); transition: transform .16s;
}
.legacy-section[open] > .legacy-summary::before { transform: rotate(45deg); }
.legacy-summary:hover { border-color: var(--accent-line); background: var(--accent-soft); }
.legacy-summary b { color: var(--text-muted); font-size: var(--fs-small); font-weight: var(--w-semibold); }
.legacy-summary small { color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.legacy-body > .panel:first-child { margin-top: 16px; }

/* 이매지너스 워드마크 -----------------------------------------------------
   SVG 자체가 투명 배경의 #5234c1 도형이므로 별도 카드 표면을 만들지 않는다.
   로그인과 사이드바 모두 배경·테두리·그림자 없이 보라색 로고만 표시한다. */
.brand-logo-surface,
.brand-light .brand-logo-surface,
.sidebar .app-brand .brand-logo-surface {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* =========================================================================
   병합 복원 — 로그인 비주얼과 브랜드 텍스트 (Phase 1)
   =========================================================================

   Overlay(이매지너스)는 로그인 좌측을 나비 영상으로, 브랜드를 로고 이미지 하나로 바꾸면서
   아래 규칙들을 지웠다. 이 병합본은 두 가지를 다르게 결정했다.

     - 로그인 화면과 글귀는 Base 그대로 둔다. Base 는 CSS 로 그린 일러스트라
       외부 자산이 필요 없고, 나비 영상은 고객사 자산이라 반영하지 않는다(D-09).
     - 브랜드는 Overlay 의 `<img class="brand-logo">` 구조를 쓰되 자산은
       `assets/brand/logo.svg`(의도적으로 빈 자리표시자)를 가리킨다.
       **텍스트 라벨을 함께 남겨** 로고가 비어 있어도 제품을 식별할 수 있게 했다.

   그래서 지워진 규칙 중 **병합본 마크업이 실제로 쓰는 것만** 되살린다.
   `brand-mark`(Base 의 인라인 SVG) 규칙은 그 마크업을 쓰지 않으므로 되살리지 않았다.
   `login-motion*` 규칙은 이제 실제로 쓰인다. 병합 시점에는 대응 마크업이 없어 죽은
   규칙이었으나, 사용자 지시로 나비 영상을 적용해 `index.html` 에 마크업을 넣었다.

   이 블록이 파일 끝에 있는 이유: 같은 선택자가 위에 있으면 나중 규칙이 이겨
   Base 값이 적용된다. 순서에 의존하므로 위로 옮기지 않는다.
   ========================================================================= */

/* 로고 이미지와 텍스트 라벨을 나란히 두려면 간격이 필요하다.
   Overlay 는 로고만 남겨서 gap 을 지웠다. */
.brand { display: inline-flex; align-items: center; gap: 11px; color: #1a1a20; text-decoration: none; font-weight: var(--w-heavy); letter-spacing: -.4px; }
.brand > span:last-child { display: flex; flex-direction: column; line-height: var(--lh-tight); }
.sidebar .brand { color: #fff; font-size: var(--fs-h4); }
.breadcrumb span { color: var(--text-subtle); letter-spacing: 1.1px; }

/* 로그인 좌측 일러스트 (Base). 자산 없이 CSS 로만 그린다. */
.scene-stack { position: absolute; z-index: 1; width: min(42vw, 570px); height: 350px; right: -3%; bottom: 3%; transform: rotate(-4deg); }
.scene-card { position: absolute; border: 1px solid rgba(255,255,255,.14); border-radius: var(--r-xl); overflow: hidden; }
.scene-back { inset: 12% 16% -8% -2%; transform: rotate(-7deg); background: #1b1b25; color: var(--on-dark-muted); padding: 24px; font-size: var(--fs-small); letter-spacing: 2px; }
.scene-front { inset: 0; background: linear-gradient(#322864 0 45%, #13121d 45%); box-shadow: 0 35px 80px rgba(0,0,0,.55); }
.scene-sky { position: absolute; inset: 0; background: radial-gradient(circle at 70% 20%, rgba(180,152,255,.7), transparent 7%), linear-gradient(160deg, transparent 50%, rgba(92,61,187,.32)); }
.scene-moon { position: absolute; right: 18%; top: 12%; width: 42px; height: 42px; border-radius: 50%; background: #fff5d8; box-shadow: 0 0 28px rgba(255,238,193,.7); }
.scene-city { position: absolute; left: 0; right: 0; bottom: 0; height: 50%; opacity: .58; background: linear-gradient(90deg, transparent 4%, #090911 4% 12%, transparent 12% 15%, #090911 15% 25%, transparent 25% 30%, #090911 30% 38%, transparent 38% 43%, #090911 43% 55%, transparent 55% 61%, #090911 61% 72%, transparent 72% 76%, #090911 76% 91%, transparent 91%); clip-path: polygon(0 37%,8% 37%,8% 18%,18% 18%,18% 45%,30% 45%,30% 8%,40% 8%,40% 36%,54% 36%,54% 16%,65% 16%,65% 42%,78% 42%,78% 3%,90% 3%,90% 31%,100% 31%,100% 100%,0 100%); }
.scene-character { position: absolute; left: 18%; bottom: -12%; width: 145px; height: 275px; border-radius: 48% 48% 20% 20%; transform: rotate(7deg); background: radial-gradient(circle at 49% 22%, #e9c1b4 0 12%, transparent 12.5%), radial-gradient(ellipse at 50% 18%, #19131e 0 22%, transparent 22.5%), linear-gradient(115deg, transparent 32%, #6244b8 33% 66%, transparent 67%); filter: drop-shadow(0 20px 25px rgba(0,0,0,.4)); }
.play-orbit { position: absolute; left: 54%; top: 40%; display: grid; place-items: center; width: 68px; height: 68px; border: 1px solid rgba(255,255,255,.5); border-radius: 50%; background: rgba(255,255,255,.12); backdrop-filter: blur(8px); box-shadow: 0 0 0 10px rgba(255,255,255,.04); }
.play-icon { width: 0; height: 0; margin-left: 4px; border-top: 9px solid transparent; border-bottom: 9px solid transparent; border-left: 15px solid white; }
.motion-line { position: absolute; height: 1px; background: linear-gradient(90deg, transparent, #cbbcff, transparent); transform: rotate(-12deg); }
.line-one { width: 150px; right: 3%; top: 35%; }
.line-two { width: 110px; right: 8%; top: 56%; }
.scene-caption { position: absolute; right: 22px; bottom: 19px; display: flex; flex-direction: column; padding-left: 12px; border-left: 2px solid #9c86ff; }
.scene-caption strong { font-size: var(--fs-body); letter-spacing: 1.6px; }
.scene-caption small { color: var(--on-dark-muted); font-size: var(--fs-small); margin-top: 3px; }

/* Base 가 좁은 화면에서 일러스트를 흐리게 했다. Overlay 가 지운 한 줄이다. */
@media (max-width: 1180px) {
  .scene-stack { opacity: .8; }
}
