/* 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 {
  /* ======================================================================
     색 토큰 — guide-v1 2장(밝음/어두움 자동 전환).

     전에는 보라(#6c52e1)가 강조색이었다. 스토리 개발 2차 화면(story-dev.css .cv2-*)이
     이미 금색(#C0905A 계열)으로 바뀌어서, 메인 화면만 보라로 남아 두 화면이 어긋났다.
     이제 두 화면이 같은 체계를 쓰도록 바꾼다:
       · 주 버튼 = 반전색(--invert-bg / --invert-ink). 보라 대신.
       · 데이터 · 진행 강조 = 금색(--gold). story-dev 의 --cv2-gold 와 **같은 값**이다
         (밝음 #b3803f/#85592a/#f6ede1, 어두움 #c8975e/#e2b47c/#2a2117). story-dev.css 는
         수정 금지라 값을 여기서 똑같이 둔다.

     색 값은 JS/HTML 에 직접 쓰지 않고 항상 var(--…). 어두움은 아래 @media 와
     [data-theme] 블록이 같은 이름을 덮어쓴다(:root 뒤). */
  color-scheme: light dark;
  /* 표면 단계(밝음 기본). 카드 구분은 그라데이션·그림자가 아니라 한 단계 밝기 차이로. */
  --ground: #ffffff; --surface: #f5f5f4; --raised: #ebebea; --nested: #e2e2e1;
  --border: #ececeb; --rule: #e6e6e5; --control: #cfcfce; --control-hover: #a9a9a8;
  --text: #0b0b0b; --muted: #4f4f4f; --faint: #6a6a6a;
  --invert-bg: #0b0b0b; --invert-ink: #ffffff; --invert-hover: #2c2c2c;   /* primary 버튼 */
  --row-hover: #fafaf9; --dash: #d6d6d5; --track-empty: #e4e4e3; --knob-off: #9a9a99;
  --scrim: rgba(0,0,0,.32); --float-shadow: 0 16px 40px rgba(0,0,0,.14);
  /* 100av: 창(.modal) · 메인 화면 알림(.toast) 바탕 — 밝음은 흰색, 어두움은 페이지(--surface)와 막보다 한 단계 밝은 표면(--raised 와 같은 값).
     예전 .modal { background: #fff } 은 테마를 따르지 않아 어두운 테마에서 물려받은 흰 글자가 흰 바탕 위에 섰다(test1106-2). */
  --modal-bg: #ffffff;
  /* KEYEAST 로고 금색(#C0905A) — 데이터·진행 표시에만. story-dev --cv2-gold 와 같은 값. */
  --gold: #b3803f; --gold-ink: #85592a; --gold-soft: #f6ede1;
  --negative: #d13a45;
  --pill-neg-bg: #fde8ea; --pill-neg-ink: #b0222e;
  --pill-warn-bg: #fbf0dc; --pill-warn-ink: #855600;
  --pill-neutral-bg: #ebebea; --pill-neutral-ink: #111111;
  --pill-gold-bg: #f3e7d6; --pill-gold-ink: #7a5226;
  --p1-bg: #e2f3e8; --p1-ink: #1f6b3d; --p2-bg: #e3ecf9; --p2-ink: #24518f; --p3-bg: #f8e3f4; --p3-ink: #8a2f7c;

  /* --- 2-2 별칭: 기존 이름 → 새 토큰. 다른 화면(상세·관리자·로그인)이 안 깨지게.
     보라(--accent*)·어두운 사이드바(--sidebar)·주황(--orange)을 전부 새 토큰으로 돌린다.
     '--accent' 는 참조가 많아 **버튼 맥락**이면 반전색, **연배경·테두리**면 금색으로 매핑한다.
     한 이름에 쓰임이 두 가지라 가장 흔한 쪽(버튼 배경)을 반전색으로 둔다. 연배경은
     --accent-soft 가 따로 금색 연배경을 준다. */
  --text-muted: var(--muted);
  --text-subtle: var(--faint);
  --on-dark: var(--text);          /* 사이드바가 밝은 바탕이 되므로 본문색과 같다 */
  --on-dark-muted: var(--muted);
  --on-dark-accent: var(--gold-ink);

  --accent: var(--invert-bg);      /* 주 버튼 배경 = 반전색(보라 제거) */
  --accent-strong: var(--invert-hover);
  --accent-soft: var(--pill-gold-bg);  /* 강조 연배경 = 금색 연배경 */
  --accent-line: var(--gold);          /* 강조 계열 테두리 = 금색 */

  --danger: var(--negative);
  --danger-soft: var(--pill-neg-bg);
  --ok: var(--gold);               /* 금색이 긍정 표시를 겸한다(2-2) */
  --ok-soft: var(--pill-gold-bg);

  --line-strong: var(--control);   /* 입력 테두리 · 체크박스 */

  /* 글자 크기 척도.
     전에는 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); /* 눌림 */

  /* 아래는 기존 이름. 위 토큰을 가리키게 두어 남은 참조가 깨지지 않게 한다.
     보라(--violet*)·사이드바(--sidebar)·주황(--orange)을 전부 새 토큰으로 돌린다. */
  --ink: var(--text);
  --line: var(--rule);
  --soft: var(--surface);
  --paper: var(--ground);
  --violet: var(--invert-bg);      /* 보라 제거: 버튼 맥락은 반전색 */
  --violet-dark: var(--invert-hover);
  --violet-soft: var(--pill-gold-bg);  /* 보라 연배경 → 금색 연배경 */
  --green: var(--gold);
  --orange: var(--gold);           /* 주황 제거 → 금색 */
  --sidebar: var(--ground);        /* 사이드바는 본문과 같은 바탕(2-2) */

  /* 굵기 척도. 전에는 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;
  font-variant-numeric: tabular-nums;   /* 숫자 폭 고정(guide 2-3) */
  color: var(--ink);
  background: var(--surface);
  /* 가변 폰트가 실제 굵기를 갖고 있으므로 가짜 볼드를 만들지 않는다. */
  font-synthesis: none;
}

/* --- 어두움(guide 2-1). prefers-color-scheme 로 새로고침 없이 전환된다.
   data-theme="light" 가 명시되면 강제로 밝음을 쓴다(검토용). 색 이름은 :root 와 같다. --- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #000000; --surface: #111111; --raised: #1d1d1d; --nested: #2a2a2a;
    --border: #1a1a1a; --rule: #1c1c1c; --control: #444444; --control-hover: #5a5a5a;
    --text: #ffffff; --muted: #b4b4b4; --faint: #949494;
    --invert-bg: #ffffff; --invert-ink: #000000; --invert-hover: #e6e6e6;
    --row-hover: #151515; --dash: #262626; --track-empty: #2a2a2a; --knob-off: #8a8a8a;
    --scrim: rgba(0,0,0,.72); --float-shadow: 0 16px 40px rgba(0,0,0,.6); --modal-bg: #1d1d1d;
    --gold: #c8975e; --gold-ink: #e2b47c; --gold-soft: #2a2117; --negative: #e5484d;
    --pill-neg-bg: #2c1a20; --pill-neg-ink: #f0707f; --pill-warn-bg: #2b2414; --pill-warn-ink: #e5a93b;
    --pill-neutral-bg: #222222; --pill-neutral-ink: #ffffff; --pill-gold-bg: #2a2117; --pill-gold-ink: #e2b47c;
    --p1-bg: #1d2a22; --p1-ink: #8fd1a8; --p2-bg: #1d2430; --p2-ink: #8fb4e8; --p3-bg: #2c1d2a; --p3-ink: #e09ad4;
  }
}
/* 검토용 강제 전환: <html data-theme="dark|light">. dark 값을 그대로 복사해 둔다. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #000000; --surface: #111111; --raised: #1d1d1d; --nested: #2a2a2a;
  --border: #1a1a1a; --rule: #1c1c1c; --control: #444444; --control-hover: #5a5a5a;
  --text: #ffffff; --muted: #b4b4b4; --faint: #949494;
  --invert-bg: #ffffff; --invert-ink: #000000; --invert-hover: #e6e6e6;
  --row-hover: #151515; --dash: #262626; --track-empty: #2a2a2a; --knob-off: #8a8a8a;
  --scrim: rgba(0,0,0,.72); --float-shadow: 0 16px 40px rgba(0,0,0,.6); --modal-bg: #1d1d1d;
  --gold: #c8975e; --gold-ink: #e2b47c; --gold-soft: #2a2117; --negative: #e5484d;
  --pill-neg-bg: #2c1a20; --pill-neg-ink: #f0707f; --pill-warn-bg: #2b2414; --pill-warn-ink: #e5a93b;
  --pill-neutral-bg: #222222; --pill-neutral-ink: #ffffff; --pill-gold-bg: #2a2117; --pill-gold-ink: #e2b47c;
  --p1-bg: #1d2a22; --p1-ink: #8fd1a8; --p2-bg: #1d2430; --p2-ink: #8fb4e8; --p3-bg: #2c1d2a; --p3-ink: #e09ad4;
}
:root[data-theme="light"] { color-scheme: light; }

* { box-sizing: border-box; }
html, body { margin: 0; min-height: 100%; }
body { overflow-x: hidden; background: var(--surface); }
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 =====================================================================
   메인·스토리 화면과 같은 토큰을 쓴다(guide 2장). 보라·하드코딩 색을 전부 걷고
   var(--…) 만 쓴다. 단 하나의 예외는 **무대 바탕의 검정**이다 — 나비 영상이 검정
   바탕이라 밝음 테마에서도 무대만 항상 검정으로 둔다(guide 5-1).

   2단: 왼쪽 1fr 영상 무대(검정 고정) · 오른쪽 520px 폼 패널(--surface, 테마 따름). */
.login-screen { min-height: 100dvh; display: grid; grid-template-columns: 1fr 520px; background: var(--surface); }
.login-showcase { position: relative; isolation: isolate; display: flex; flex-direction: column; align-items: flex-start; min-height: 100dvh; padding: 42px 48px; overflow: hidden; color: #fff; background: #000; }
/* 가독성 스크림(z 2): 영상(z 1) 위, 글자(z 4) 아래. 글자가 몰린 좌하단만 어둡게 하고
   위쪽·꽃 영역은 건드리지 않는다. 세로(아래→위)와 가로(왼→오) 그라디언트를 겹친다. */
.login-showcase::before { content: ""; position: absolute; z-index: 2; inset: 0; pointer-events: none; background: linear-gradient(0deg, rgba(0,0,0,.72) 0%, rgba(0,0,0,.35) 30%, transparent 55%), linear-gradient(90deg, rgba(0,0,0,.45) 0%, transparent 45%); }

/* 브랜드 로고(로그인 무대 · 좁은 화면 로그인 · 사이드바 · 상단 바 공용) — KEYING 로고 하나(100ae · 고객 요청 261105 1번).
   그림은 assets/brand/keying-logo.png(655×64, 배경 투명 · 금색 KEYING + 밑줄). 가로가 약 10:1 이라 폭만 정하고 높이는 비율로 둔다.
   금색은 밝은 바탕(#fff · #f5f5f4)과 어두운 바탕(#000 · #111 · 로그인 무대 검정) 모두에서 보여 흰 판(.brand-logo-surface)을 두지 않는다. */
.brand { display: inline-flex; align-items: center; color: var(--text); text-decoration: none; }
.brand-logo { display: block; max-width: 100%; height: auto; }
.brand-light { position: relative; z-index: 4; }
.brand-logo-login { width: clamp(240px, 20vw, 320px); }

/* 무대 카피: 로고 아래가 아니라 무대 하단에 붙인다(헤드라인은 좌하단). */
.showcase-copy { position: relative; z-index: 4; margin-top: auto; max-width: 680px; text-shadow: 0 2px 22px rgba(0,0,0,.6); }
/* 헤드라인 2줄. 각 줄은 마스크(overflow:hidden) 안에서 span 이 올라온다. */
.showcase-headline { margin: 0 0 20px; font-size: clamp(52px, 5.6vw, 84px); line-height: var(--lh-tight); letter-spacing: -.045em; font-weight: var(--w-bold); }
.showcase-headline .line { display: block; overflow: hidden; }
.showcase-headline .line > span { display: block; }
.showcase-lede { margin: 0 0 24px; max-width: 540px; color: rgba(255,255,255,.82); font-size: var(--fs-h4); line-height: var(--lh-body); }
/* 사실 3개. 가운뎃점으로 구분한 가로 목록. */
.showcase-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; margin: 0; padding: 0; list-style: none; color: rgba(255,255,255,.72); font-size: var(--fs-small); }
.showcase-facts li { position: relative; padding-left: 20px; }
.showcase-facts li::before { content: ""; position: absolute; left: 6px; top: 50%; width: 5px; height: 5px; border-radius: 50%; background: var(--gold); transform: translateY(-50%); }

/* 백합 영상. 무대(.login-showcase) 전체를 채우는 배경 레이어(z 1)로, 글자(z 4) 뒤에 깔린다.
   영상 바탕이 순수 검정이라 무대 검정(background:#000)과 이어져 테두리(사각 경계)가 보이지 않는다.
   object-fit:contain 이라 영상이 잘리지 않고 꽃 전체가 보이고, 남는 영역은 검정으로 메워진다. */
.login-motion { position: absolute; z-index: 1; inset: 0; width: 100%; height: 100%; overflow: hidden; pointer-events: none; background: #000; border-radius: 0; -webkit-mask-image: radial-gradient(ellipse 75% 85% at 62% 50%, #000 60%, transparent 100%); mask-image: radial-gradient(ellipse 75% 85% at 62% 50%, #000 60%, transparent 100%); }
/* contain: 영상 전체를 보이게(잘림 없음). object-position 62% — 꽃을 가운데보다 약간 오른쪽으로 밀어 좌하단 헤드라인과 덜 겹치게. */
.login-motion-poster, .login-motion-video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; object-position: 62% 50%; }
.login-motion-poster { z-index: 0; }
/* 영상은 포스터 위에서 페이드 인한다. JS 가 .is-playing 을 붙이면 보인다(헤드라인 모션 후).
   .js 가 없거나 축소 모션이면 아래 분기에서 그냥 보인다. */
.login-motion-video { z-index: 1; background: #000; opacity: 0; transition: opacity .9s var(--ease-out); }
.login-motion.is-playing .login-motion-video { opacity: 1; }

/* 영상 일시정지/재생 버튼. 우하단. 아이콘은 상태에 따라 하나만 보인다. */
.showcase-pause { position: absolute; z-index: 4; right: 48px; bottom: 40px; display: grid; place-items: center; width: 44px; height: 44px; color: #fff; background: rgba(0,0,0,.42); border: 1px solid rgba(255,255,255,.28); border-radius: var(--r-pill); cursor: pointer; backdrop-filter: blur(6px); transition: background var(--t-hover) var(--ease-out), transform var(--t-press) var(--ease-out); }
.showcase-pause:hover { background: rgba(0,0,0,.6); }
.showcase-pause:active { transform: scale(.94); }
.showcase-pause svg { width: 18px; height: 18px; fill: currentColor; }
.showcase-pause .icon-pause { display: none; }
/* 재생 중이면(aria-pressed=true) 멈춤 아이콘을 보인다. */
.showcase-pause[aria-pressed="true"] .icon-play { display: none; }
.showcase-pause[aria-pressed="true"] .icon-pause { display: block; }

/* 폼 패널. 테마를 따른다(--surface). */
.login-panel { display: grid; place-items: center; min-height: 100dvh; padding: 40px; background: var(--surface); }
.login-box { width: min(100%, 400px); }
.mobile-brand { display: none; }
.brand-logo-mobile { width: min(260px, 70vw); }
.login-heading h2 { margin: 0 0 9px; color: var(--text); font-size: var(--fs-h1); letter-spacing: -.02em; font-weight: var(--w-bold); }
.login-heading p { margin: 0 0 30px; color: var(--muted); font-size: var(--fs-lead); line-height: var(--lh-normal); }

.auth-field { margin-bottom: 16px; }
.field-label { display: block; margin: 0 0 8px; color: var(--text); font-size: var(--fs-small); font-weight: var(--w-semibold); }
.field-label .required { margin-left: 4px; padding: 1px 6px; border-radius: var(--r-xs); color: var(--gold-ink); background: var(--gold-soft); font-size: var(--fs-micro); font-weight: var(--w-bold); }
.field-hint { margin: 8px 0 0; color: var(--faint); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.input-wrap { position: relative; }
.input-wrap > svg { position: absolute; left: 14px; top: 50%; width: 18px; height: 18px; color: var(--faint); transform: translateY(-50%); }
.input-wrap input { width: 100%; min-height: 50px; padding: 0 46px 0 42px; border: 1px solid var(--control); border-radius: var(--r-md); outline: 0; color: var(--text); background: var(--ground); font-size: var(--fs-body); transition: border-color var(--t-hover) var(--ease-out); }
.input-wrap input::placeholder { color: var(--faint); }
.input-wrap input:hover { border-color: var(--control-hover); }
.input-wrap input:focus-visible { border-color: var(--text); outline: 2px solid var(--text); outline-offset: 1px; }
.password-toggle { position: absolute; top: 0; right: 4px; display: grid; place-items: center; width: 42px; min-height: 50px; border: 0; color: var(--faint); background: transparent; cursor: pointer; }
.password-toggle:hover { color: var(--text); }
.password-toggle svg { width: 18px; height: 18px; }

/* 회사 코드 펼침. 닫히면 높이 0, 열리면 내용 높이까지. 높이·페이드로 연다. */
.auth-reveal { overflow: hidden; }
.auth-reveal[hidden] { display: block; height: 0; opacity: 0; visibility: hidden; }  /* visibility: 접힌 칸이 Tab·스크린 리더에 잡히지 않게 */
.auth-reveal:not([hidden]) { height: auto; opacity: 1; }

.login-error { min-height: 18px; margin-top: 4px; color: var(--negative); font-size: var(--fs-small); line-height: var(--lh-normal); }
/* 오류 안에 붙는 가입 링크(로그인 실패 시). 오류 색과 분리해 밑줄 링크로 보인다. */
.login-error .auth-switch-link { margin-left: 6px; color: var(--text); }
.login-success { min-height: 18px; margin-top: 4px; color: var(--gold-ink); font-size: var(--fs-small); line-height: var(--lh-normal); }

/* 주 버튼(로그인/가입 공용). 꽉 찬 반전색. 메인 화면 primary 와 같은 토큰. */
.primary-button { border: 0; border-radius: var(--r-md); color: var(--invert-ink); 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); }
.primary-button:active { background: var(--accent-strong); transform: scale(.97); 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: 8px; width: 100%; min-height: 50px; margin-top: 8px; font-size: var(--fs-body); font-weight: var(--w-semibold); }
.login-button svg { width: 18px; height: 18px; }

/* 로그인 ↔ 가입 전환 링크 + 하단 안내. */
.auth-switch { margin: 16px 0 0; text-align: center; }
.auth-switch-link { padding: 2px 4px; border: 0; color: var(--text); background: transparent; font-size: var(--fs-small); font-weight: var(--w-semibold); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.auth-switch-link:hover { color: var(--muted); }
.auth-foot { margin: 22px 0 0; color: var(--faint); font-size: var(--fs-caption); text-align: center; }

/* 모션 ----------------------------------------------------------------------
   JS(.js 클래스가 <html> 에 붙을 때)가 있을 때만 숨겼다 등장시킨다. 스크립트가 없거나
   실패해도 내용이 보여야 하므로, .js 가 없으면 아래 초기 상태를 적용하지 않는다.
   transform/opacity 만 움직인다. */
html.js .login-screen [data-rise] { opacity: 0; transform: translateY(16px); }
html.js .login-screen.is-ready [data-rise] { opacity: 1; transform: none; transition: opacity var(--t-reveal) var(--ease-out), transform var(--t-reveal) var(--ease-out); }
/* 순차 등장: 60ms 간격. 등장 지연은 JS 가 아니라 CSS 변수(--rise-i)로 준다. */
html.js .login-screen.is-ready [data-rise] { transition-delay: calc(var(--rise-i, 0) * 60ms); }
/* 헤드라인 줄 단위 등장. */
html.js .showcase-headline .line > span { transform: translateY(105%); }
html.js .login-screen.is-ready .showcase-headline .line > span { transform: none; transition: transform 1s var(--ease-expo); }
html.js .login-screen.is-ready .showcase-headline .line:nth-child(2) > span { transition-delay: 90ms; }
/* 회사 코드 펼침 모션: 높이·페이드. */
html.js .auth-reveal { transition: height var(--t-ui) var(--ease-out), opacity var(--t-ui) var(--ease-out); }
html.js .auth-reveal [data-rise-reveal] { opacity: 0; transform: translateY(10px); transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out); }
html.js .auth-reveal:not([hidden]) [data-rise-reveal] { opacity: 1; transform: none; }

/* 축소 모션: 모든 등장을 끄고 최종 상태로 둔다. 영상도 자동 재생하지 않는다(JS). */
@media (prefers-reduced-motion: reduce) {
  html.js .login-screen [data-rise],
  html.js .login-screen.is-ready [data-rise],
  html.js .showcase-headline .line > span,
  html.js .auth-reveal [data-rise-reveal] { opacity: 1; transform: none; transition: none; }
  .login-motion-video { transition: none; }
}

/* 타자기 커서(motion.js typewriter / window.KMotion). 금색 막대 `▍`.
   깜빡임은 opacity 만 쓰고, 축소 모션이면 켜 둔 채로 멈춘다. */
.sd-type-cursor { color: var(--gold, #b3803f); font-weight: 600; animation: sd-cursor-blink 1s steps(1, end) infinite; }
@keyframes sd-cursor-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .sd-type-cursor { animation: none; opacity: 1; } }

/* 좁은 화면(≤820px): 무대는 위쪽 짧은 띠, 폼은 아래. 가로 스크롤 없음. */
@media (max-width: 820px) {
  .login-screen { grid-template-columns: 1fr; }
  .login-showcase { min-height: auto; padding: 24px 20px 28px; }
  .showcase-copy { margin-top: 16px; }
  .showcase-headline { font-size: clamp(30px, 8vw, 44px); margin-bottom: 12px; }
  .showcase-headline .line:nth-child(2) { display: none; }
  .showcase-lede { font-size: var(--fs-body); margin-bottom: 14px; }
  .showcase-pause { right: 20px; bottom: 20px; }
  .login-panel { min-height: auto; padding: 28px 20px 40px; }
  .mobile-brand { display: block; margin-bottom: 20px; }
}
/* 로그인 화면의 테스트 계정 안내(.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(--text); background: var(--ground); border-right: 1px solid var(--border); }
.sidebar-head { padding: 0 7px; }
.sidebar .app-brand { min-width: 0; flex-direction: column; align-items: flex-start; gap: 5px; }
/* 넓은 화면 머리: 사이드바 242 − 안쪽 여백(17×2 + 7×2) − 접기 버튼 28 − 틈 8 = 158px 안에 든다. 좁은 화면 서랍(270px)도 같은 폭. */
.brand-logo-sidebar { width: 156px; }
.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; }
/* text-decoration 을 끄는 이유: 이 클래스를 <button> 이 아니라 <a> 로도 쓴다.
   스토리 개발 메뉴는 SPA 뷰가 아니라 별 페이지(/story-dev/)로 이동해서 링크여야 하고,
   전역 `a` 규칙이 없어 그대로 두면 메뉴에 밑줄이 생긴다. 버튼에는 영향이 없다. */
.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(--muted); background: transparent; font-size: var(--fs-lead); text-decoration: none; cursor: pointer; transition: color .2s, background .2s, font-weight .2s; }
.nav-item:hover { color: var(--text); background: var(--row-hover); }
/* 활성 표시: 색 배경·좌측 막대를 없애고 글자색 + 굵게로만 표시한다(guide 4장). */
.nav-item.active { color: var(--text); background: transparent; box-shadow: none; font-weight: var(--w-bold); }
.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(--gold-ink); background: var(--gold-soft); 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(--muted); background: var(--nested); font-size: var(--fs-small); }
/* 프로젝트 묶음 헤더. `.main-nav > p` 는 **직계** p 만 잡는데 이 헤더는
   #navProjectsGroup 안에 있어 잡히지 않는다. 관리자 묶음 헤더(.admin-nav-section > p)와
   같은 모양으로 맞춘다. */
#navProjectsGroup > 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 i)와 달리 배경을
   주지 않아 "링크가 밖으로 나간다" 는 신호만 준다. */
.nav-item .nav-external-mark { margin-left: auto; padding: 0; color: var(--on-dark-muted); background: transparent; font-size: var(--fs-small); font-style: normal; font-weight: var(--w-bold); }
.nav-item-external:hover .nav-external-mark { color: var(--on-dark); }/* 아이콘 버튼이 둘(비밀번호 변경, 로그아웃)이라 마지막 두 열을 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 var(--border); }
.avatar, .top-avatar { display: grid; place-items: center; border-radius: var(--r-sm); color: var(--gold-ink); background: var(--gold-soft); 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(--text); font-size: var(--fs-small); text-overflow: ellipsis; }
.sidebar-user div span { margin-top: 3px; color: var(--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(--muted); }
.nav-collapse:hover { color: var(--text); background: var(--row-hover); }
.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 var(--border); background: color-mix(in srgb, var(--ground) 90%, transparent); backdrop-filter: blur(14px); }
.breadcrumb { display: flex; align-items: center; gap: 11px; font-size: var(--fs-small); }
/* 100bg: 상단 바 제목은 한 줄 · 넘치면 말줄임(전체 제목은 #pageTitle 의 title 속성). 줄어드는 것은 제목뿐이고
   메뉴 버튼 · 로고 · 점 · 오른쪽 묶음(진행 칩 · 아바타)은 줄지 않아 375px 에서도 화면 안에 남는다(예전에는 긴 제목이 줄을 바꿔
   상단 바 높이를 넘었고 메뉴 버튼이 32px → 17px 로 줄었다). */
.breadcrumb { flex: 1 1 auto; min-width: 0; }
.breadcrumb strong { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.breadcrumb i { flex: none; }
.topbar > .menu-button { flex: none; }
.breadcrumb-brand { display: inline-flex; flex: none; align-items: center; }
/* 상단 바 로고: 글자 높이가 옆 쪽 제목(--fs-body)과 비슷해지는 폭. */
.brand-logo-breadcrumb { width: 150px; }
.breadcrumb i { width: 3px; height: 3px; border-radius: 50%; background: var(--control); }
.breadcrumb strong { font-size: var(--fs-body); }
.top-actions { display: flex; align-items: center; gap: 16px; margin-left: auto; }
/* 100bg: 넓어진 .breadcrumb 옆에서도 줄지 않고, 긴 제목과 붙지 않게 사이를 둔다. */
.top-actions { flex: none; padding-left: 12px; }
.system-status { display: flex; align-items: center; gap: 7px; padding: 7px 10px; border: 1px solid var(--border); border-radius: var(--r-pill); color: var(--faint); background: var(--ground); font-size: var(--fs-caption); }
.system-status i { width: 6px; height: 6px; border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 3px color-mix(in srgb, var(--gold) 20%, transparent); }.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: var(--faint); transition: .2s; }
.menu-button:hover span { background: var(--text); }
.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(소제목 라벨) — 로그인에서는 제거했지만 콘티·라이브러리·관리자 화면이 쓴다.
   원래 로그인 블록에 있던 기본 규칙을, 그 화면들이 깨지지 않게 여기로 옮겨 둔다. */
.eyebrow { display: inline-flex; align-items: center; gap: 9px; color: rgba(255,255,255,.72); font-size: var(--fs-body); font-weight: var(--w-bold); letter-spacing: 1.8px; }
.eyebrow i { width: 22px; height: 1px; background: currentColor; }
.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: var(--surface); }
.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(--text); background: var(--ground); 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; }/* 100av: 보라 그라디언트(guide 2-2 보라 정리의 잔재 — 어두운 테마에서 흰 바탕 · 흰 글자) → 표면 토큰 · 금색 아이콘. */
.tip-card { display: flex; gap: 12px; padding: 15px 17px; border: 1px solid var(--rule); border-radius: var(--r-lg); background: var(--surface); }
.tip-card > span { display: grid; place-items: center; flex: 0 0 31px; height: 31px; border-radius: var(--r-sm); color: var(--gold-ink); background: var(--gold-soft); }
.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 var(--control); border-radius: var(--r-sm); color: var(--text-muted); background: var(--ground); 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 */
/* 100ce: 가운데 칸은 minmax(0, 1fr) — 예전 minmax(220px, 1fr) 은 화면 344px 아래(창 폭 100vw - 32px)에서 34 + 220 + 22 + 틈 · 여백이
   창보다 넓어져 닫기 버튼이 창 밖 · 화면 밖(320px 에서 x=328)으로 밀렸다. 390px 창(넓은 화면)에서는 가운데 칸이 284px 이라 그대로다. */
.toast { position: fixed; z-index: 100; right: 24px; bottom: 24px; display: grid; grid-template-columns: 34px minmax(0, 1fr) 22px; gap: 11px; align-items: center; width: min(390px, calc(100vw - 32px)); padding: 13px; border: 1px solid var(--rule); border-radius: var(--r-md); color: var(--text); background: var(--modal-bg); 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: var(--faint); }
  .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(220px, 64vw); }
  .brand-logo-breadcrumb { width: 112px; }
  .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 var(--border); }
.admin-nav-section > p { margin: 0 11px 10px; color: var(--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) { }

/* ===== 회원가입 보조 스타일 (로그인 폼 공용) ===== */
.required { margin-left: 5px; padding: 2px 5px; border-radius: var(--r-xs); color: var(--danger); background: var(--pill-neg-bg); 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: var(--nested); font-size: var(--fs-small); }

/* ===== 프로젝트 메인 ===== */
.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; }
/* 만들기 버튼 두 개(스토리 개발 / 일반)를 나란히 둔다. 좁은 화면에서는 줄로 떨어진다. */
.page-intro-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* 스토리 개발이 이 환경의 주 기능이다. 일반 프로젝트 버튼보다 앞에 두고 강조한다. */
#newStoryDevButton { background: var(--accent, #5234c1); }
.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; }
/* overflow 는 보이게 둔다 — '…' 메뉴(176px)가 좁은 카드보다 넓어 잘렸다(2026-10-23 dev).
   모서리 둥글림은 표지(위)·본문(아래)이 각자 잘라 낸다. 메뉴가 열린 카드는 옆 카드 위로 올린다. */
.poster-card { position: relative; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--ground); box-shadow: var(--e-2); transition: transform .2s, box-shadow .2s; }
.poster-card:hover { transform: translateY(-3px); box-shadow: var(--e-3); }
.poster-card:focus-within, .poster-card:has(.menu-list:not([hidden])) { z-index: 5; }
.poster-card .cover { position: relative; aspect-ratio: 2 / 3; overflow: hidden; background: var(--nested); border-radius: var(--r-lg) var(--r-lg) 0 0; }
.poster-card .card-body { border-radius: 0 0 var(--r-lg) var(--r-lg); }

/* 개인: 정사각형에 가깝게(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 var(--border); border-radius: var(--r-md); background: var(--ground); 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: var(--nested); }
.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; }
/* 표지가 없으면 그라데이션 대신 --surface 바탕에 제목 글자만(guide 5-2). */
.cover-placeholder { display: flex; align-items: center; flex-direction: column; justify-content: center; gap: 9px; height: 100%; padding: 16px; text-align: center; color: var(--text); background: var(--surface); }
.cover-placeholder span { padding: 4px 8px; border: 1px solid var(--border); border-radius: var(--r-pill); color: var(--gold-ink); background: var(--gold-soft); font-size: var(--fs-caption); font-weight: var(--w-bold); letter-spacing: 1px; }
.cover-placeholder strong { color: var(--text); 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: rgba(30,30,38,.78); color: var(--gold); }
.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 var(--border); border-radius: var(--r-sm); color: var(--muted); background: var(--ground); font-size: var(--fs-caption); font-weight: var(--w-semibold); cursor: pointer; }
.card-actions button:hover, .upload-cover:hover { border-color: var(--gold); color: var(--gold-ink); }
.card-actions button.primary { color: var(--invert-ink); border-color: var(--invert-bg); background: var(--invert-bg); }
.card-actions button.danger { color: var(--negative); border-color: var(--pill-neg-bg); }
.empty-block { display: flex; align-items: center; flex-direction: column; justify-content: center; min-height: 190px; padding: 34px; border: 1px dashed var(--control); border-radius: var(--r-lg); background: var(--ground); 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(--gold-ink); background: var(--gold-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); }

/* ===== 프로젝트 목록 2차(guide 5-2) ===== */
/* 제목 행의 부제. */
#projectsSummary { margin: 0; color: var(--muted); font-size: var(--fs-lead); }
/* 새 프로젝트 = 테두리 버튼(설계자 결정: 주 버튼은 스토리 개발 하나). */
.secondary-button { display: inline-flex; align-items: center; gap: 8px; min-height: var(--control-h, 36px); padding: 8px 16px; border: 1px solid var(--control); border-radius: var(--r-md); color: var(--text); background: var(--ground); font-weight: var(--w-semibold); cursor: pointer; transition: border-color .15s, background .15s, transform .12s; }
.secondary-button:hover { border-color: var(--text); background: var(--row-hover); transform: translateY(-1px); }
.secondary-button:active { transform: translateY(1px); }
.secondary-button svg { width: 18px; height: 18px; }

/* 세그먼트 필터(전체/공유/개인). 제목 행 오른쪽에 둔다. */
.block-head .project-filter { margin-left: auto; }
.project-filter b { margin-left: 4px; font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }

/* 포스터 벽: 넓은 화면 6열, 좁아지면 자동으로 줄어든다. 표지 2:3.
   100ce: 칸은 minmax(0, 1fr) 이다. 그냥 1fr 은 minmax(auto, 1fr) 이라 칸이 카드의 최소 내용 폭보다 좁아지지 못했다 —
   한 줄 말줄임(nowrap) 제목 · '스토리 개발 · 원작 기반' 배지가 카드를 162px 아래로 줄지 못하게 해서 320px(2열) · 821~990px(4열,
   메뉴 펼침) · 1201~1280px(6열, 프로젝트 6개 이상)에서 벽이 화면 밖으로 밀렸고, 긴 제목 하나면 1600px 에서도 넘쳤다.
   이제 칸은 늘 같은 폭이고 제목 · 배지가 그 안에서 말줄임된다. */
.poster-wall { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 28px 18px; }
@media (max-width: 1200px) { .poster-wall { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .poster-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 14px; } }
/* 100ce: 칸이 줄면 '…' 메뉴(176px)가 카드보다 넓다. 메뉴는 '…' 오른쪽 끝에 맞춰 왼쪽으로 열리므로 첫 열 카드에서는
   화면 왼쪽 끝(2열 · 560px 이하) 또는 펼친 왼쪽 메뉴 밑(4열 · 821~1099px)으로 들어갔다. 그 폭의 첫 열만 오른쪽으로 연다. */
@media (max-width: 560px) {
  .poster-wall > .poster-card:nth-child(2n+1) .card-actions .menu-list { right: auto; left: 0; }
}
@media (min-width: 821px) and (max-width: 1099.98px) {
  .poster-wall > .poster-card:nth-child(4n+1) .card-actions .menu-list { right: auto; left: 0; }
}

/* 표지 왼쪽 아래 현재 단계 알약(검정 72% + 금색 점). */
.stage-pill { position: absolute; left: 10px; bottom: 10px; display: inline-flex; align-items: center; gap: 6px; max-width: calc(100% - 20px); padding: 4px 9px; border-radius: var(--r-pill); color: #fff; background: rgba(16,16,20,.72); backdrop-filter: blur(8px); font-size: var(--fs-caption); font-weight: var(--w-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stage-pill::before { content: ""; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 50%; background: var(--gold); }

/* 카드 오른쪽 위 '…' 하나로 모은 액션. 호버·키보드 포커스에서만 보인다(guide 결정 4번). */
.poster-card .card-actions, .tile-card .card-actions { position: absolute; top: 8px; right: 8px; z-index: 3; flex-wrap: nowrap; opacity: 0; transform: translateY(-4px); transition: opacity .18s var(--ease-out, ease), transform .18s var(--ease-out, ease); }
.poster-card:hover .card-actions, .tile-card:hover .card-actions,
.poster-card:focus-within .card-actions, .tile-card:focus-within .card-actions { opacity: 1; transform: none; }
/* 카드 본문 안에 있던 액션을 표지 위로 올렸으므로 본문에는 액션 자리를 비운다. */
.poster-card .card-body .card-actions, .tile-card .card-body .card-actions { display: none; }

/* 이어서 하기 카드 — 왼쪽 표지(2:3) · 오른쪽 정보. 카드 전체가 열기. */
.continue-card { display: grid; grid-template-columns: 200px 1fr; gap: 22px; margin-bottom: 30px; padding: 18px; border: 1px solid var(--border); border-radius: var(--radius-card, var(--r-xl)); background: var(--ground); box-shadow: var(--e-2); cursor: pointer; transition: transform .2s, box-shadow .2s; }
.continue-card:hover { transform: translateY(-2px); box-shadow: var(--e-3); }
.continue-card .cc-cover { position: relative; aspect-ratio: 2 / 3; overflow: hidden; border-radius: var(--r-lg); background: var(--nested); }
.continue-card .cc-cover img { width: 100%; height: 100%; object-fit: cover; }
/* 100ce: 본문 칸을 크기 질의 컨테이너로 둔다 — 진행 막대 이름표를 화면 폭이 아니라 이 칸의 실제 폭으로 감춘다
   (821px 이상에서는 왼쪽 메뉴가 펼쳐져 있어 화면이 넓어도 칸이 좁다). 칸 폭은 격자가 정하므로(min-width: 0) 바뀌지 않는다. */
.continue-card .cc-body { display: flex; flex-direction: column; justify-content: center; min-width: 0; gap: 8px; container: cc-body / inline-size; }
.continue-card .cc-eyebrow { color: var(--gold-ink); font-size: var(--fs-small); font-weight: var(--w-bold); }
.continue-card .cc-title { margin: 0; font-size: var(--fs-h3); letter-spacing: -.4px; }
.continue-card .cc-logline { margin: 0; color: var(--muted); font-size: var(--fs-body); line-height: var(--lh-normal); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.continue-card .cc-next { color: var(--text); font-size: var(--fs-small); font-weight: var(--w-semibold); }
.continue-card .cc-meta { color: var(--faint); font-size: var(--fs-small); }
@media (max-width: 820px) { .continue-card { grid-template-columns: 120px 1fr; gap: 16px; } }

/* 8단계 진행 막대 — 완료 회색 · 현재 금색 · 남은 단계 빈 트랙(guide 5-2). */
.cc-progress { display: flex; gap: 6px; margin: 2px 0; }
.cc-progress .cc-seg { flex: 1 1 0; }
.cc-progress .cc-seg i { display: block; height: 5px; border-radius: var(--r-pill); background: var(--track-empty); }
.cc-progress .cc-seg.done i { background: var(--control); }
.cc-progress .cc-seg.current i { background: var(--gold); }
.cc-progress .cc-seg span { display: block; margin-top: 5px; color: var(--faint); font-size: var(--fs-caption); text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-progress .cc-seg.current span { color: var(--gold-ink); font-weight: var(--w-semibold); }
/* A6(계획서 2026-10-26): 대본 "개발 중" 잠김 칸. 남은 칸(빈 트랙) 위에 "개발 중" 작은 배지를 둔다.
   색은 테마 변수를 써 밝음·어두움 모두 따라온다. 정적 표시라 모션이 없어 reduced-motion 영향이 없다. */
.cc-progress .cc-seg.is-dev i { background: var(--track-empty); }
.cc-progress .cc-seg.is-dev span { color: var(--faint); }
.cc-progress .cc-seg .cc-seg-dev {
  display: inline; margin-left: 4px;
  font-size: var(--fs-caption); font-weight: var(--w-semibold);
  color: var(--gold-ink);
}
/* 100ce: 칸은 flex: 1 1 0 이지만 min-width 가 auto 라 이름표(nowrap) 폭 아래로 줄지 못했다. 여덟 칸 최소 폭 합이 437px 이라
   본문 칸이 그보다 좁은 폭(320~600px, 왼쪽 메뉴를 편 821~985px)에서 막대가 x=609 까지 나가 화면 전체가 옆으로 밀렸다.
   1100px 아래에서만 칸이 이름표보다 좁아질 수 있게 하고 이름표는 말줄임한다. 1100px 이상은 예전 그대로(긴 이름 칸이 조금 넓다). */
@media (max-width: 1099.98px) {
  .cc-progress .cc-seg { min-width: 0; }
}
/* 100ce: 본문 칸이 360px 아래면 칸당 40px 이 안 돼 이름표가 한 글자도 안 남는다. 이름표를 감추고 막대 아래에
   "8단계 중 3단계 · 스토리 설정" 한 줄(app.js fillContinueProgress)을 보인다. 넓은 화면에서는 감춘다. */
.cc-progress-summary { display: none; margin: 4px 0 0; color: var(--faint); font-size: var(--fs-caption); }
.cc-progress-summary b { color: var(--gold-ink); font-weight: var(--w-semibold); }
@container cc-body (max-width: 359.98px) {
  .cc-progress .cc-seg span { display: none; }
  .cc-progress-summary { display: block; }
}

/* 등장 순차 rise(guide 3·5-2). JS 없이 CSS 만으로 — 진입 시 한 번 올라온다. */
@keyframes listRise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
#homeView[data-view="home"].active [data-rise] { animation: listRise .5s var(--ease-out, ease) both; }
#homeView [data-rise]:nth-child(1) { animation-delay: 0ms; }
#homeView [data-rise]:nth-child(2) { animation-delay: 50ms; }
#homeView [data-rise]:nth-child(3) { animation-delay: 100ms; }
/* 포스터 호버 scale 1.045(guide 5-2). */
.poster-wall .poster-card .cover img, .poster-wall .poster-card .cover-placeholder { transition: transform .6s var(--ease-out, ease); }
.poster-wall .poster-card:hover .cover img, .poster-wall .poster-card:hover .cover-placeholder { transform: scale(1.045); }
/* 필터 전환 페이드 — 새로 채워질 때 카드가 부드럽게 들어온다. */
@keyframes cardIn { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
.poster-wall .poster-card.enter { animation: cardIn .22s var(--ease-out, ease) both; }

/* reduced-motion: 모든 등장·호버 이동을 끄고 최종 상태만(guide 3·6). */
@media (prefers-reduced-motion: reduce) {
  #homeView [data-rise], .poster-wall .poster-card.enter { animation: none; }
  .poster-wall .poster-card .cover img, .poster-wall .poster-card .cover-placeholder,
  .poster-card, .tile-card, .continue-card { transition: none; }
  .poster-wall .poster-card:hover .cover img, .poster-wall .poster-card:hover .cover-placeholder { transform: none; }
}
/* 포커스 표시(guide 2-3). 카드·필터·버튼이 키보드에서 보이게. */
.poster-card:focus-visible, .continue-card:focus-visible, .project-filter button:focus-visible,
.secondary-button:focus-visible, .card-actions button:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }


/* ===== 모달 =====
   100av(test1106-2): 바탕 · 글자는 테마 토큰이다 — 예전 바탕 #fff 고정 + 물려받은 --text(어두운 테마 #fff)로 모든 창(11개)이 어두운
   테마에서 흰 바탕 · 흰 글자였다. 창 안 부품(아래 .delete-target · .tip-card · .outline-item · .reader-page …)도 토큰으로 맞췄다. */
.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); color: var(--text); background: var(--modal-bg); 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; color: var(--text); background: var(--ground); 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; }
/* 100av: 창 안 오류 글자 — --negative(#d13a45 · #e5484d)는 어두운 창 바탕(#1d1d1d) 위 4.3:1 이라 알약 글자 토큰(두 테마 5.7:1 이상)을 쓴다. */
.modal .login-error { color: var(--pill-neg-ink); }
.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); }

/* ===== 스토리 개발 프로젝트 만들기 모달 =====
   이름 · 공개 범위만 받는다(uiux-261029-a 항목 2 — 기획 방식 카드 세 장과 그 규칙을 지웠다).
   '다른 이야기로' 창과 같은 폭을 쓴다. */
.modal.story-dev-modal { width: min(100%, 640px); }
/* "다른 이야기로" 창의 안내 카드(읽기 전용). 무엇이 오고 무엇이 안 오는지 미리 보여 준다.
   예전 window.prompt 문구를 창 안으로 옮긴 것이라 본문 크기로 읽히게 한다. */
.story-derive-note { margin: 2px 0 14px; padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: var(--r-md); background: var(--accent-soft); }
.story-derive-note > p { margin: 0; font-size: var(--fs-caption); line-height: var(--lh-normal, 1.4); color: var(--text); }
.story-derive-note > p + p { margin-top: 6px; }
.story-derive-note .story-derive-origin { font-size: var(--fs-small); color: var(--text-subtle); }
/* 가져옴/안 가져옴을 한눈에 가르는 꼬리표. 초록=온다, 회색=두고 간다. */
.story-derive-tag { display: inline-block; margin-right: 6px; padding: 1px 7px; border-radius: 999px; font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.story-derive-tag.carry { color: var(--p1-ink); background: var(--p1-bg); }
.story-derive-tag.skip { color: var(--muted); background: var(--pill-neutral-bg); }
/* 일회성 안내 팝업 본문. 짧은 안내 문장이라 hint 크기(작은 글씨)보다 본문 크기로 읽히게 한다.
   색·줄간격은 기존 토큰을 그대로 쓴다(.field-hint 가 쓰는 --text-subtle 대신 본문색). */
#noticeModalBody { margin: 0; color: var(--text); font-size: var(--fs-body); line-height: var(--lh-relaxed, var(--lh-normal)); }
/* 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(--pill-neg-ink); font-size: var(--fs-body); }
.danger-banner p { margin: 5px 0 0; color: var(--pill-neg-ink); font-size: var(--fs-small); line-height: var(--lh-normal); }
/* 100av: 고정 #f7f7f9 → 표면 토큰(두 테마). 글자는 창 글자(--text)를 물려받는다. */
.delete-target { margin: 0 0 18px; padding: 11px 13px; border-radius: var(--r-sm); background: var(--surface); 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); }
/* 사용자 삭제 범위는 이제 선택이 아니라 고정 안내다. 프로젝트를 남기는 선택지가
   소유자 없는(=화면에서 찾을 수 없는) 프로젝트를 만들어서 없앴다. */
.delete-scope-note { margin: 0; padding: 12px 13px; border: 1px solid #e3e2e9; border-radius: var(--r-md); color: var(--text-subtle); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.delete-scope-note strong { color: var(--pill-neg-ink); }
.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; }


/* 보강 전후. 원문은 흐리게, 결과는 또렷하게 두어 무엇이 바뀌었는지 한눈에 보이게 한다. */
.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); }


/* ===== 롱테이크 ===== */
.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; }
  .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; }

/* 100av: 콘티 표는 두 테마 모두 밝은 종이다(인쇄 · PDF 와 같은 모양) — 칸 글자를 물려받으면 어두운 테마에서 흰 바탕 · 흰 글자라 글자색을 정한다. */
.sb-sheet-wrap { overflow-x: auto; border: 1px solid #d8d8de; border-radius: 10px; color: #2c2c33; 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: var(--invert-ink); 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: var(--ground);
  box-shadow: var(--e-3);
}
.menu-list[hidden] { display: none; }
/* 카드 '…'은 표지 오른쪽 위에 있어 위로 열면 카드(overflow:hidden) 밖으로 잘려 안 보였다
   (2026-10-23 dev). 카드 안에서는 아래로 연다. */
.poster-card .card-actions .menu-list, .tile-card .card-actions .menu-list { top: calc(100% + 6px); bottom: auto; }

.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);
  color: var(--muted);
  font-size: 13px;
}

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

/* AI 속도별 모델 (관리자 · speed-bar-admin-models 2026-10-29) ----------------------- */
/* 예전 '프롬프트 관리' 카드 규칙(.prompt-group ~ .prompt-history-item)은 화면과 함께 지웠다. 세 속도 줄을
   한 카드 안 표처럼 둔다(이름 · 모델 · 생각 모드). 색은 테마 토큰만 써서 두 테마에서 맞는다. */
.speed-model-list {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}
.speed-model-row {
  display: grid;
  grid-template-columns: minmax(180px, 1.2fr) minmax(200px, 1.4fr) minmax(140px, .8fr);
  gap: 10px 16px;
  align-items: end;
  padding: 14px 16px;
  border-top: 1px solid var(--line);
}
.speed-model-row:first-child { border-top: 0; }
.speed-model-name strong { display: block; color: var(--text); font-size: var(--fs-body); }
.speed-model-name small { display: block; margin-top: 3px; color: var(--muted); font-size: var(--fs-caption); line-height: var(--lh-normal); }
.speed-model-field { display: flex; flex-direction: column; gap: 5px; color: var(--muted); font-size: var(--fs-caption); font-weight: var(--w-semibold); }
.speed-model-select {
  min-height: 37px;
  padding: 0 10px;
  border: 1px solid var(--control);
  border-radius: var(--r-sm);
  color: var(--text);
  background: var(--surface);
  font: inherit;
  font-size: var(--fs-small);
}
.speed-model-actions { display: flex; justify-content: flex-end; align-items: center; gap: 10px; margin-top: 12px; }
/* 사용량 모델별 표의 '기타' 줄 — 쓰는 모델 목록 밖 기록의 합계. 다른 줄과 구분되게 바탕만 옅게. */
.model-table tr.usage-other td { background: var(--nested); }
@media (max-width: 720px) {
  .speed-model-row { grid-template-columns: 1fr; }
}

/* 대본 아웃라인 모달 등 열이 많은 모달은 기본 폭으로는 가로 스크롤만 생긴다. */
.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: var(--ground); }
.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: var(--paper);       /* 100av: 종이 바탕도 테마 토큰(예전 #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 var(--dash); }
.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;
  }
}
/* 100av: 콘티 표 보기는 두 테마 모두 밝은 종이(.sb-sheet-wrap 과 같은 규칙 — 표 머리 글자가 고정 어두운 색이다). 글자를 물려받지 않게 정한다. */
.reader-page.is-sheet { padding: 18px 20px; color: #2c2c33; 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); }
.reader-page.is-sheet .reader-sheet-meta { color: #6b6b76; }

@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; }


/* ================= 공용 말풍선(툴팁) =================
   help-tip.js 가 만들어 body 끝에 붙이는 단 하나의 요소다. 메인 화면과 스토리
   개발이 같은 모양을 쓴다(스토리 개발은 이 styles.css 를 함께 읽는다).

   색·폰트는 기존 토큰을 그대로 쓴다: 어두운 표면 --sidebar(#111116) 위에 밝은
   본문 --on-dark. position:fixed 로 흐름 밖에 두고, z-index 는 모달(200)·토스트
   (100)보다 위에 둔다 — 모달 안의 버튼 설명도 가려지면 안 된다. */
.help-tip {
  position: fixed;
  z-index: 2147483000;          /* 어떤 모달·토스트보다도 위 */
  left: 0; top: 0;
  max-width: 280px;
  padding: 8px 11px;
  border-radius: var(--r-sm);
  background: var(--sidebar);
  color: var(--on-dark);
  font-size: var(--fs-caption);
  line-height: var(--lh-normal);
  box-shadow: var(--e-3);
  pointer-events: none;         /* 말풍선이 마우스를 가로채지 않는다 */
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity .12s ease, transform .12s ease;
}
.help-tip.is-visible {
  opacity: 1;
  transform: translateY(0);
}
/* 설명 본문. 긴 문장은 줄바꿈하고, 공백·줄바꿈을 자연스럽게 흘린다. */
.help-tip-body {
  display: block;
  white-space: normal;
  word-break: break-word;
}
/* 작은 화살표. 기본은 위를 가리킨다(말풍선이 대상 아래 있을 때).
   left 는 help-tip.js 가 대상 중앙에 맞춰 넣는다. */
.help-tip-arrow {
  position: absolute;
  top: -5px;
  width: 10px; height: 10px;
  background: var(--sidebar);
  transform: rotate(45deg);
  border-radius: 2px;
}
/* 말풍선이 대상 위로 뒤집혔을 때는 화살표도 아래로 간다. */
.help-tip.is-above .help-tip-arrow {
  top: auto;
  bottom: -5px;
}
/* 모션을 줄이는 사용자에게는 움직임을 없앤다. */
@media (prefers-reduced-motion: reduce) {
  .help-tip { transition: opacity .12s ease; transform: none; }
  .help-tip.is-visible { transform: none; }
}
