/* ===========================================================================
   보부상 게임 — 타이틀 화면 V9  (2026-08-16 확정 · 전면 교체)
   출처: graphics/output/title/TITLE_V9_APPLY.md
   동작 레퍼런스: graphics/drafts/title/rw_v9_final.html — CSS/JS 그대로 이식
   [개정 2026-08-17 · SPLASH_SPEC_0817.md] 스플래시 크레딧(.ti-splash) 추가,
     등장 연출을 V9 페이드 → C안 「무대 세우기」(순차 내려앉음)로 교체. 좌표·크기는 그대로
   사용자 확정: 배경 E안 · 등장 V9(총 1.5s) · 아이들 리치 · 옷자락 8프레임 · 좌표 아래

   구판(6레이어·스캔 등장)에서 바뀐 것
     · 배경 title_bg.png(행상인 포함) — 별도 peddler·tagline 레이어 없음
     · 옷자락 나부낌: 행상인 영역(400×380)만 8프레임으로 갈아 끼움 (JS setInterval 125ms)
     · 여명 펄스(dawn 프레임) · 새 3마리 · 먼지 8개 · 구름 그림자 스윕
     · 모든 페이드는 steps() 계단 — 도트 룩 유지, 부드러운 보간 금지

   ⚠️ 컨테이닝 블록 함정 (APPLY.md 2번) — 로고 래퍼(.ti-lkoW/.ti-lenW)에 transform
      애니메이션(부유)이 걸리는 순간 래퍼가 absolute 자식의 기준 박스가 된다.
      래퍼는 반드시 position:absolute; inset:0 으로 무대 전체를 덮어야 자식의
      left/top% 가 무대 기준으로 남는다. 래퍼를 로고 크기로 줄이면 top% 가 전부 깨진다.
   되돌리기: git 없음 — 구판은 이 파일의 2026-08-14 판. 구판 아트(bg.png·peddler.png·
            tagline.png)는 title_layers/ 에 그대로 있다.
   =========================================================================== */

/* 배경이 1536×1024(3:2)다. 16:9로 자르면 행상인 발밑이 잘리고 좌표가 전부 어긋난다 */
.ti-stage{position:relative;width:100%;aspect-ratio:3/2;overflow:hidden;background:#0c0a08}
.ti-stage img{image-rendering:pixelated}

/* ── 레이어 (아래→위): bg → 옷자락·구름(z2) → dawn(z3) → 새(z4) → 로고(z6) → 메뉴(z7) → veil(z30) ── */
.ti-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:fill}
/* 옷자락 프레임 — 배경 원본 px (952,520) 400×380 영역. 배경 위에 정확히 겹친다.
   src 는 game.jsx 가 125ms 간격으로 f1~f8 을 순환시킨다(핑퐁 금지·프리로드 필수) */
.ti-pfw{position:absolute;left:61.979%;top:50.781%;width:26.042%;height:37.109%;z-index:2}
/* 여명 프레임 — 하늘만 +14 리프트된 밝은 배경. 펄스가 켤 때만 보인다 */
.ti-dawn{position:absolute;inset:0;width:100%;height:100%;object-fit:fill;opacity:0;z-index:3}

/* 로고 — 래퍼가 등장·부유(div), 이미지가 배치(img). ⚠️ 래퍼는 inset:0 (위 함정 참조) */
.ti-lkoW,.ti-lenW{position:absolute;inset:0;opacity:0;pointer-events:none;z-index:6}
/* [2026-08-22 · 원화가] 로고 교체 — A-1 필사본 세리프(logo_ko.png 1798×366).
   ⚠️ 새 로고에는 영문 부제 「A PEDDLER'S TALE」가 **그림 안에 들어 있다** — 별도 영문 로고를
      같이 띄우면 부제가 두 번 나온다. 그래서 .ti-lenW 를 숨긴다(마크업·등장 연출은 그대로 둔다).
   ⚠️ image-rendering:auto — 1798px 원본이 742px 로 **비정수 축소**된다. 무대의 pixelated(25행)를
      그대로 두면 최근접 축소가 도트를 불규칙하게 버려 획이 부서진다 (charanim.css 140행 규칙,
      GFX_BUGS #1·#3 과 같은 함정). 되돌리려면 표시 크기의 정수배 판을 새로 구워야 한다 */
.ti-lko{position:absolute;left:21%;top:12%;width:58%;image-rendering:auto}
.ti-lenW{display:none}
.ti-len{position:absolute;left:34.5%;top:28%;width:31%;opacity:.92}

/* 메뉴 — 배경 위 텍스트(확정 목업 .mi 스타일). 판·테두리 없음 */
/* [2026-08-20 사용자 확정 · 그래픽] 메뉴 글자를 **무대 폭에 비례**시킨다 — 비율 문제 해결.
   증상: 큰 창(전체화면)에서 무대는 min(100vw,150vh)로 커지는데 글자만 고정 px 라
   배경·로고 대비 메뉴가 점점 작아 보였다.
   해법: font-size = 무대폭(--bs-w32) × 계수. 1280 무대 기준 b1 24px(0.01875) · 나머지 15px(0.01171875).
   - 작은 창(k32<1): --bs-w32=1280px 로 고정이라 계산값도 24/15px — transform scale 로 무대와 함께 준다 ✓
   - 큰 창: 무대가 커지는 만큼 글자도 같이 큰다 (1920×1080 전체화면 → b1 ≈ 30px) ✓
   ⚠️ 프리픽스(.pre) 폭도 같은 계수로 묶어야 한다 — 아래 참조 */
.ti-btn{position:absolute;left:35%;width:30%;opacity:0;z-index:7;
  background:none;border:0;cursor:pointer;text-align:center;
  font-family:inherit;   /* 없으면 버튼만 브라우저 기본 글꼴로 튄다 */
  font-size:calc(var(--bs-w32, 1280px) * 0.01640625);   /* [0820 3차] 18→21px(1280 기준) — 사용자 「좀 더」 */
  font-weight:700;color:#2e3a1c;letter-spacing:2px;
  text-shadow:1px 1px 0 rgba(246,244,210,.5);
  padding:clamp(2px,.5cqw,6px) 0}
.ti-b1{top:46%;font-size:calc(var(--bs-w32, 1280px) * 0.01875)}   /* 주 항목 — 1280 기준 24px */
.ti-b2{top:52.5%}
.ti-b3{top:59%}
.ti-btn:hover:not(:disabled){color:#556031}
/* 비활성 — 목업의 .dim(op .55)을 색으로 옮긴다. opacity 는 등장 애니메이션이 쓰는
   속성이라 서로 덮어쓴다(구판에서 겪은 것) — 색·그림자만 낮춘다 */
.ti-btn:disabled{cursor:default;color:rgba(46,58,28,.45);text-shadow:none}
.ti-b1:focus-visible{outline:3px solid #f0b03c;outline-offset:-3px}

/* ── 버튼 3상태 [2026-08-17 · TITLE_BTN_APPLY_0817.md · A안 「프리픽스가 다가온다」] ──
   ⚠️ 프리픽스는 width 16px 를 **항상 차지**하고 opacity 로만 나타난다 — 0→16px 로 늘리면
      글자가 리플로우돼 튄다. 「밀리는 느낌」은 라벨의 translateX 3px 이 낸다
   ⚠️ 등장(tiDropM)은 **버튼 자체**에, 이 상태 연출은 **안쪽 span** 에 걸린다. 반대로 하면 충돌한다
   ⚠️ press 는 transform 만 쓴다 — padding/margin 을 건드리면 줄 간격(46/52.5/59%)이 흔들린다 */
.ti-btn .pre{display:inline-block;width:calc(var(--bs-w32, 1280px) * 0.0125);opacity:0}   /* 1280 기준 16px */
/* b1 은 글자가 크므로 프리픽스 폭도 같은 비율로 넓힌다 — 공통을 넓히면 b2·b3 이 리플로우된다 */
.ti-b1 .pre{opacity:.55;width:calc(var(--bs-w32, 1280px) * 0.01875)}   /* 주 항목 표시(확정) — 1280 기준 24px */
.ti-btn .lb{display:inline-block}

.ti-btn:hover:not(:disabled) .pre{opacity:1;animation:tiPreIn .12s steps(2) both}
@keyframes tiPreIn{from{transform:translateX(-6px)}to{transform:translateX(0)}}
.ti-btn:hover:not(:disabled) .lb{animation:tiLbIn .12s steps(2) both}
@keyframes tiLbIn{from{transform:translateX(0)}to{transform:translateX(3px)}}

/* 누름 — ⚠️ animation:none 이 반드시 있어야 한다(지시서 3절 코드에서 이 한 줄만 더했다).
   마우스로 누르면 hover 가 늘 함께 걸려 있는데, CSS 는 **fill 로 남은 애니메이션의 transform 을
   일반 선언보다 우선**한다 — 실측으로 확인했다(애니메이션 있을 때 -6px/0 이 이기고 3px/2px 이 죽었다).
   그대로 두면 press 가 화면에 안 나타난다. 없애려던 바로 그 증상이다.
   애니메이션을 끄면 아래 transform 이 살아난다. 좌표값은 지시서 1절 표 그대로다 */
.ti-btn:active:not(:disabled){color:#1e2612}
.ti-btn:active:not(:disabled) .lb{animation:none;transform:translate(3px,2px)}
.ti-btn:active:not(:disabled) .pre{animation:none;opacity:1;transform:translateY(2px)}

/* ── 새 [2026-08-24 · 사용자 결재 · 원화 graphics\output\TITLE_BIRDS_APPLY_0824.md] ──
   옛 판은 셋이 top 고정(24/18/12%) + 같은 방향 같은 속도라 「일자로 3마리」로 보였다.
   이제 JS 스케줄러(game.jsx 타이틀 effect)가 패턴 다섯 중 하나를 골라 그때그때 심는다.
   ⚠️ 속도·간격만 흩는 것으로는 안 된다 — 1차 시안에서 그렇게 냈다가 기각됐다. 방향과 사건을 늘린다.
   ⚠️ 이동은 left/top(linear) · 날갯짓만 transform(steps) — 현행 문법 그대로다.
   ⚠️ 크기를 transform:scale 로 주지 마라. 날갯짓이 transform 을 쓴다. width/height 로 바꾼다(패턴 ⑤). */
.ti-birds{position:absolute;inset:0;pointer-events:none;z-index:4}
.bd{
  position:absolute; z-index:4; pointer-events:none;
  width:var(--w,13px); height:var(--h,8px); background:#3a4423;
  clip-path:polygon(0 60%,25% 0,50% 55%,75% 0,100% 60%,50% 100%);
  animation-timing-function:linear;
}
@keyframes bdFlap{ 50%{ transform:scaleY(.45) } }

/* ① 가로지르기 — 옆으로 가되 높이가 오르내린다. 이것만으로도 「선」이 사라진다 */
@keyframes bdCross{
  0%   { left:-6%;  top:var(--y0) }
  25%  {            top:calc(var(--y0) - 3%) }
  50%  {            top:var(--y0) }
  75%  {            top:calc(var(--y0) + 2.5%) }
  100% { left:106%; top:var(--y0) }
}

/* ② 숲에서 날아오름 — 요청의 핵심.
   ⚠️ 처음이 가장 가파르다(18% 지점에 -9%). 등속으로 올리면 「놀라서 날았다」가 안 된다.
   ⚠️ --dx 를 마리마다 다르게 줘라(game.jsx). 같은 각도로 올리면 그것도 자로 그은 선이 된다. */
@keyframes bdRise{
  0%   { left:var(--x0); top:var(--y0); opacity:0 }
  4%   { opacity:1 }
  18%  { left:calc(var(--x0) + (var(--dx) * 0.10)); top:calc(var(--y0) - 9%) }
  55%  { left:calc(var(--x0) + (var(--dx) * 0.55)); top:calc(var(--y0) - 34%) }
  88%  { opacity:1 }
  100% { left:calc(var(--x0) + var(--dx));          top:var(--y1); opacity:0 }
}

/* ③ 먼 무리 — 6×4px 대여섯. ⚠️ V자로 줄 세우지 마라. 그러면 또 「선」이다 */
@keyframes bdFlock{
  0%   { left:-8%;  top:var(--y0); opacity:0 }
  8%   { opacity:.85 }
  50%  {            top:calc(var(--y0) - 4%) }
  92%  { opacity:.85 }
  100% { left:108%; top:calc(var(--y0) - 7%); opacity:0 }
}

/* ④ 선회 — 아주 가끔. 오래 보는 사람에게 주는 상이다 */
@keyframes bdCircle{
  0%{left:20%;top:26%;opacity:0} 6%{opacity:1}
  12%{left:33%;top:19%}  25%{left:47%;top:17%}  38%{left:58%;top:23%}
  50%{left:61%;top:32%}  62%{left:52%;top:38%}  75%{left:37%;top:37%}
  88%{left:24%;top:31%;opacity:1} 100%{left:18%;top:26%;opacity:0}
}

/* ⑤ 멀리서 가까이 — 크기로만 거리를 낸다 */
@keyframes bdNear{
  0%   { left:88%; top:22%; width:5px;  height:3px;  opacity:0 }
  8%   { opacity:.9 }
  55%  { left:48%; top:26%; width:11px; height:7px }
  100% { left:-8%; top:34%; width:22px; height:13px; opacity:1 }
}
/* 먼지 — 3×3px, 행상인 주변에서 상승 소멸. 위치·지연은 game.jsx 가 mount 때 1회 굴려 인라인으로 준다 */
.ti-dust{position:absolute;width:3px;height:3px;background:#e6e4b4;opacity:.45;z-index:3}
/* 구름 그림자 — 폭 34% 띠. ⚠️ 이 그라데이션은 STYLE_SPEC 예외로 확정본(APPLY.md 5절)에
   명시된 값이다 — 단색으로 바꾸면 띠 경계가 줄로 보인다 */
.ti-cs{position:absolute;top:0;bottom:0;width:34%;left:-40%;z-index:2;
  background:linear-gradient(90deg,transparent,rgba(20,24,12,.15) 30%,rgba(20,24,12,.15) 70%,transparent)}

.ti-veil{position:absolute;inset:0;background:#0c0a08;z-index:30;pointer-events:none}

/* ── 스플래시 크레딧 [2026-08-17 · graphics/output/SPLASH_SPEC_0817.md] ──
   타이틀 전, veil(z30)보다 위(z40)의 검은 막. 카드 두 장이 디더 계단으로 떴다 사라진다.
   타임라인은 전부 CSS 지연 — JS(game.jsx)는 끝나는 시각(7.6s)과 스킵만 안다. 소리 없음(5절).
   글자 규격(3절): 본문 24px 자간 3px · 작은 글씨 12px 자간 5px — type.css 12 격자 준수 */
.ti-splash{position:absolute;inset:0;background:#000;z-index:40}
.ti-sp-card{position:absolute;inset:0;opacity:0;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px}
.ti-sp-card .s{font-size:12px;letter-spacing:5px;color:#8fa06a}
.ti-sp-card .b{font-size:24px;letter-spacing:3px;color:#f6f4d2}
.ti-sp-card .b .gold{color:#f0b03c}
/* 카드1 인 0.4s → 머묾 → 아웃 3.4s · 카드2 인 4.1s → 아웃 7.1s (2절 표 그대로).
   인·아웃이 같은 opacity 를 만진다 — 아웃을 **뒤에** 선언해야 겹치는 순간 아웃이 이긴다 */
.ti-sp-c1{animation:tiSpIn .6s steps(5) .4s both, tiSpOut .5s steps(4) 3.4s forwards}
.ti-sp-c2{animation:tiSpIn .6s steps(5) 4.1s both, tiSpOut .5s steps(4) 7.1s forwards}
.ti-sp-hint{position:absolute;right:3%;bottom:4%;font-size:12px;letter-spacing:2px;color:#4a5c2e;
  opacity:0;animation:tiSpIn .6s steps(5) .4s both}   /* 카드1 등장과 함께(4절) */
/* 🚨 [2026-08-24 · 실측 수정] 80% 지점을 빼지 마라 — 빼면 **카드2가 0.8 에서 멈춘다.**
   원인은 부동소수 오차 + steps(end) 다. 애니메이션이 끝났을 때 진행도가
   카드1(지연 .4s)은 정확히 1 인데 카드2(지연 4.1s)는 0.9999999999999994 로 나온다(실측).
   steps(5,end) 는 1 에 아주 조금만 못 미쳐도 마지막 계단을 못 밟고 4/5 = 0.8 로 바닥친다 —
   그래서 「MADE BY CODEX」 만 80% 로 흐리게 떴다. OpenAI 제출작에서 하필 그 카드였다.
   80% 지점을 주면 마지막 계단(0.8)이 이미 opacity 1 에 닿아 오차와 무관해진다.
   ⚠️ 계단 수(5)는 그대로다 — 0 → .25 → .5 → .75 → 1 로 여전히 다섯 칸이다.
   ⚠️ 아래 tiSpOut(steps(4))도 같은 함정을 안고 있다. 지금은 카드2의 아웃이 끝나는 순간
      스플래시가 통째로 언마운트돼서 안 드러날 뿐이다 — 타임라인을 건드리면 여기부터 의심해라 */
@keyframes tiSpIn{from{opacity:0}80%{opacity:1}to{opacity:1}}
@keyframes tiSpOut{from{opacity:1}to{opacity:0}}

/* ── 등장 C안 「무대 세우기」 [개정 2026-08-17 · SPLASH_SPEC_0817.md 6-T · 구 V9 대체] ──
   t0 = 스플래시가 걷힌 순간(.play 부여). 스펙 표는 CODEX 카드 아웃 **시작**(t0-0.5s) 기준이라
   아래 지연값은 표에서 0.5s 뺀 것이다. 「배경 페이드 인」= 검은 veil 아웃(계단값 동일).
   ⚠️ 내려앉음(등장)은 래퍼가 아니라 **안쪽 img** 에 건다 — 래퍼는 inset:0 + 부유 전용
      (컨테이닝 블록 함정, 파일 머리 주석·game.jsx 타이틀 주석 참조) */
.ti-stage.play .ti-veil{animation:tiVeil .6s steps(5) .2s forwards}
.ti-stage.play .ti-lkoW{opacity:1;animation:tiFloat 2.4s steps(2) infinite 1.6s}  /* 부유는 내려앉음이 끝난 1.6s 부터 */
.ti-stage.play .ti-lenW{opacity:1}
.ti-stage.play .ti-lko{animation:tiDrop .3s steps(3) 1.3s both}
.ti-stage.play .ti-len{animation:tiDrop .3s steps(3) 1.75s both}
@keyframes tiVeil{to{opacity:0}}
/* to 블록 없음 — 소재의 원래 opacity(한글 1 · 영문 .92)로 안착한다. both 라 시작 전엔 숨김.
   to{opacity:1} 로 적으면 both 필이 영문 로고를 영영 1 에 붙들어 .92 가 안 돌아온다 */
@keyframes tiDrop{from{opacity:0;transform:translateY(-14px)}}

/* 메뉴 3줄 순차 내려앉음 — 줄마다 0.2s 간격. 버튼은 base opacity 0 이라 to 를 명시한다.
   등장 중에는 메뉴를 누를 수 없다 — 버튼은 opacity:0 이어도 클릭이 먹는다(사고 전례).
   각 줄은 자기 등장이 끝난 직후에 활성화된다(스펙 6-T 구현 주의) */
.ti-stage.play .ti-btn{pointer-events:none}
.ti-stage.play .ti-b1{animation:tiDropM .25s steps(2) 2.25s both, tiPtr .01s linear 2.5s both}
.ti-stage.play .ti-b2{animation:tiDropM .25s steps(2) 2.45s both, tiPtr .01s linear 2.7s both}
.ti-stage.play .ti-b3{animation:tiDropM .25s steps(2) 2.65s both, tiPtr .01s linear 2.9s both}
@keyframes tiDropM{from{opacity:0;transform:translateY(-14px)}to{opacity:1;transform:none}}
@keyframes tiPtr{to{pointer-events:auto}}

/* 스플래시 동안(play 이전) — 안 보이는 메뉴가 클릭 먹는 사고 방지. 막은 z40 이지만 이중 안전 */
.ti-stage:not(.play):not(.done) .ti-btn{pointer-events:none}

/* ── 건너뛰기 / 두 번째 진입: 등장 없이 최종 상태 (부유·아이들은 계속) ── */
.ti-stage.done .ti-lkoW{opacity:1;animation:tiFloat 2.4s steps(2) infinite}
.ti-stage.done .ti-lenW{opacity:1}
.ti-stage.done .ti-btn{opacity:1}
.ti-stage.done .ti-veil{opacity:0}

/* ── 아이들 루프 (마스터 4800ms 계열 — 등장이 끝나도 계속) ── */
.ti-stage.play .ti-dawn,
.ti-stage.done .ti-dawn{animation:tiDawn 4.8s steps(2) infinite 2.4s}
@keyframes tiDawn{0%,58%{opacity:0}59%,100%{opacity:.55}}
@keyframes tiFloat{50%{transform:translateY(-2px)}}
/* 새는 여기서 빠졌다 [2026-08-24 · TITLE_BIRDS_APPLY_0824.md] — 옛 tiFly/tiFlap 바인딩은
   .ti-bird 셋을 같은 속도로 밀던 규칙이라 「일자로 3마리」의 원인이었다.
   이제 game.jsx 스케줄러가 .bd 를 심고 애니메이션도 인라인으로 준다(위 .bd 절) */
.ti-stage.play .ti-dust,
.ti-stage.done .ti-dust{animation:tiDust 6s steps(6) infinite}
@keyframes tiDust{from{transform:translateY(0);opacity:.5}50%{opacity:.3}to{transform:translateY(-42px);opacity:0}}
.ti-stage.play .ti-cs,
.ti-stage.done .ti-cs{animation:tiCsweep 14.4s linear infinite 3s}
@keyframes tiCsweep{from{left:-40%}to{left:110%}}

/* 접근성 — 움직임을 싫어하는 사용자를 위해 */
@media (prefers-reduced-motion: reduce){
  .ti-stage *{animation:none !important}
  .ti-stage .ti-lkoW,.ti-stage .ti-lenW,.ti-stage .ti-btn{opacity:1}
  .ti-stage .ti-veil{opacity:0}
  /* ⚠️ CSS 로 숨기는 것만으로는 부족하다 — 스케줄러 타이머가 계속 돈다.
     game.jsx 의 matchMedia 조기 반환이 짝이다. 둘 다 있어야 한다 */
  .ti-stage .ti-birds,.ti-stage .ti-dust{display:none}
  /* tiPtr 애니메이션이 안 돌므로 위 pointer-events:none 이 영영 안 풀린다 — 여기서 직접 푼다
     (스플래시 중에는 z40 막이 클릭을 다 받아서 아래 버튼까지 안 간다) */
  .ti-stage.play .ti-btn{pointer-events:auto}
  /* 스플래시(스펙 4절): 페이드 없이 카드1 1.5s → 카드2 1.5s 정지 표시.
     위 전역 animation:none 을 뚫어야 해서 !important — JS 종료 타이머도 3s 로 준다(game.jsx) */
  .ti-splash .ti-sp-c1{animation:tiSpFlat 1.5s linear 0s !important}
  .ti-splash .ti-sp-c2{animation:tiSpFlat 1.5s linear 1.5s !important}
  .ti-splash .ti-sp-hint{opacity:1}
}
/* fill 없음 — 도는 동안만 1, 끝나면 base 0 으로 돌아간다(카드 교대가 이걸로 된다) */
@keyframes tiSpFlat{from{opacity:1}to{opacity:1}}

/* ═══════════════════════════════════════════════════════════════
   엔딩 도감 [확정 2026-08-17 · HANDOFF_ending_gallery]
   그림 20장은 run\output\endings\ 에 이미 있다. 새 에셋 없음.
   ⚠️ 팔레트 변수는 .bs-screen 에만 선언돼 있다 — 여기서 다시 선언한다
   ⚠️ .bs-dex 는 position:fixed 라 **무대 밖(S.wrap 직속)** 에 붙여야 한다.
      .bs-title 안에 넣으면 type.css 의 transform:scale 이 컨테이닝 블록이 되어
      fixed 가 뷰포트가 아니라 무대 기준이 된다(로고 래퍼와 같은 함정) */
.bs-dex{
  position:fixed; inset:0;
  /* [실측 수정 2026-08-17] 문서값은 60 이었으나 index.html 의 전역 바가 더 위였다 —
     #audiobar 101 · #keybanner 99. 60 이면 좌하단 「돌아가기」가 음량 바에 그대로 덮여
     **눌리지 않는다**(elementFromPoint 가 #bgmbtn 을 돌려줬다).
     도감은 전체 화면 모달이니 그 위가 맞다. 여는 동안 음량 바가 가려지는 것은 의도다 */
  z-index:120;
  --c1:#1a2612; --c3:#556031; --c4:#8b8f4c; --c5:#b5b571;
  --c7:#e6e4b4; --c8:#f6f4d2; --gold:#f0b03c; --danger-txt:#ff9d8f;
  background:rgba(10,14,6,.93); color:var(--c7);
  padding:26px 34px; font-family:"Galmuri11",monospace; letter-spacing:1px;
  container-type:inline-size;
}
.bs-dex .dex-hd{ display:flex; justify-content:space-between; align-items:baseline;
  border-bottom:1px solid var(--c3); padding-bottom:9px; margin-bottom:14px }
.bs-dex .dex-hd .t{ font-size:18px; letter-spacing:7px; color:var(--gold) }
.bs-dex .dex-hd .n{ font-size:14px; color:var(--c5) }
.bs-dex .dex-hd .n b{ color:var(--c8); font-weight:400 }

.bs-dex .dex-g{ display:grid; grid-template-columns:repeat(5,1fr); gap:11px }
.bs-dex .dex-c{ position:relative; background:none; border:0; padding:0;
  font-family:inherit; text-align:left; cursor:pointer; color:inherit }
.bs-dex .dex-c img{ width:100%; aspect-ratio:16/9; object-fit:cover; display:block;
  image-rendering:pixelated; box-shadow:0 0 0 1px var(--c3) }
.bs-dex .dex-c .nm{ font-size:12px; color:var(--c7); margin-top:4px;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis }
.bs-dex .dex-c .no{ position:absolute; left:3px; top:2px; font-size:11px; color:var(--c5);
  text-shadow:1px 1px 0 rgba(10,14,6,.9) }
/* 미획득 — 로비 잠긴 명패와 같은 문법. 그림은 아예 안 그린다(스포일러) */
.bs-dex .dex-c.lock{ cursor:default }
.bs-dex .dex-c.lock .shade{ width:100%; aspect-ratio:16/9; background:var(--c1);
  box-shadow:inset 0 0 0 1px var(--c3); display:grid; place-items:center;
  color:var(--c3); font-size:15px;
  background-image:repeating-linear-gradient(45deg,
    rgba(85,96,49,.34) 0 3px, rgba(0,0,0,0) 3px 8px) }
.bs-dex .dex-c.lock .nm{ color:var(--c3) }
/* 방금 채운 칸 */
.bs-dex .dex-c.fresh img{ box-shadow:0 0 0 2px var(--gold) }
.bs-dex .dex-c.fresh .nm{ color:var(--gold) }

.bs-dex .dex-love{ margin-top:10px; padding:9px 12px; background:var(--c1);
  box-shadow:inset 0 0 0 1px var(--c3); display:flex; justify-content:space-between;
  align-items:center; font-size:13px; color:var(--c5) }
.bs-dex .dex-love b{ color:var(--c8); font-weight:400 }

.bs-dex .dex-foot{ position:absolute; left:34px; right:34px; bottom:20px;
  display:flex; justify-content:space-between; align-items:center }
.bs-dex .dex-foot button{ padding:7px 22px; font-size:13px; letter-spacing:3px;
  font-family:inherit; cursor:pointer;
  background:var(--c1); border:2px solid var(--c3); color:var(--c5);
  transition:filter .08s steps(2), transform .06s steps(1) }
.bs-dex .dex-foot button:hover{ filter:brightness(1.18) }
.bs-dex .dex-foot button:active{ transform:translateY(2px); filter:brightness(.82) }
.bs-dex .dex-foot .hint{ color:var(--c4); font-size:12px }

/* ── 진입점 E1 — 타이틀 좌하단 ──
   ⚠️ 어두운 숲 위다. 메뉴의 어두운 잉크를 쓰면 묻힌다 — 밝은 글자 + 1px 어두운 그림자
   ⚠️ .ti-btn 이 아니라 별도 클래스인 것이 요점이다 — 메뉴 3줄의 좌표·등장 연출
      (tiDropM/tiPtr)과 pointer-events 잠금을 하나도 건드리지 않는다 */
.ti-dexbtn{ position:absolute; left:5%; bottom:6%; z-index:8;
  background:none; border:0; padding:0; cursor:pointer; text-align:left;
  font-family:inherit; font-size:14px; letter-spacing:2px;
  color:#f6f4d2; text-shadow:1px 1px 0 rgba(10,14,6,.85);
  transition:filter .08s steps(2), transform .06s steps(1) }
.ti-dexbtn b{ font-weight:400; color:#f0b03c }
.ti-dexbtn i{ display:block; font-style:normal; font-size:12px; color:#cfcd8f;
  letter-spacing:1px; margin-top:2px }
.ti-dexbtn:hover{ filter:brightness(1.15) }
.ti-dexbtn:active{ transform:translateY(2px); filter:brightness(.85) }
