/* ════════════════════════════════════════════════════════════════════
   saju-stage.css — 사주집(하연) 무대 배치 (전체계획 #208 · 2026-09-05 전면 재배치)
   ────────────────────────────────────────────────────────────────────
   무대 엔진은 새로 만들지 않는다 — 도사집·타로집이 쓰는 `shop-stage.js` 한 벌을 그대로 쓴다
   (규칙 6). 이 파일은 그 위에 사주집만의 **비율·색·부속 UI**(칩 행·사주판 시트·음악 아이콘)를
   얹는 얇은 겹이다.

   2026-09-05 전면 재배치 — 사람 피드백: "기존 사주 결과 페이지 위에 하연 영상을 얹은 화면처럼
   보인다". 지시(§0) 화면 비율 = 하연 25~30% · 대화 50% · 데이터 20%. 도사집(38dvh)보다
   낮춘 27dvh 를 기본으로 삼는다. 톤도 다크 브라운 → 크림/라벤더로 옮긴다(saju-ui.css 와 짝).

   이 파일의 선택자는 전부 `body.sj-on` 으로 시작한다. 그 클래스는 `saju.js` 의
   무대세우기() 가 무대가 실제로 섰을 때만 붙인다 — ShopStage 로드 실패 등으로 무대가
   안 서면 이 파일은 한 줄도 안 걸리고 화면은 saju-ui.css 의 기본(사진 없는 크림 배경 +
   전체화면 채팅)으로 물러난다.
   ════════════════════════════════════════════════════════════════════ */

body.sj-on{
  /*  지시 §0·§4 — 하연 영역 25~30%. 중앙값 27% 를 기본으로 잡는다(도사집 38dvh보다 낮다 —
      상담사 얼굴/상반신은 보이되 화면을 반 넘게 먹지 않는다). */
  --sj-stage-h: 34dvh;   /* 2026-09-10 3차 보정 §1 — 31→34dvh. 크롭 창을 더 넓혀 어깨·가슴 위쪽까지 보이게 */
  --sj-bottom-h: 60px;     /* 입력칸(+칩 행) 높이 어림값 — 상시 노출이라 값이 거의 안 바뀐다 */
  --sj-col: 520px;
  --sj-face-y: 32%;   /* 2026-09-10 3차 보정 §1 — 24→32%. 무대가 커진 만큼 창을 아래로 내려 어깨를 담는다 */

  height: 100dvh;
  overflow: hidden;
  /* ★ 2026-09-10 사람 지시 [사주관 AI 상담화면 전체 UI 리뉴얼] — "새 배경 적용" §.
     사람이 준 [하연 사주관 AI 상담 전용 배경 MASTER](자산\신버전\사주집_상담화면_마스터_2026-09-10\
     상담화면_BACKGROUND_MASTER.png)를 화면 전체 배경으로 쓴다. cover · 비율 유지 · 보라 필터
     없음 · 회색 overlay 없음(스펙 그대로). 무대(.tj-stage)가 이 위 z-index:0 로 얹혀 상단
     27dvh 는 영상이 가리지만, 그 아래 대화/입력 영역은 이 그림이 그대로 비친다. */
  background: url("assets/village/entry/saju-consult-bg.jpg") center 30% / cover no-repeat !important;
}

/*  ★ 2026-09-05 2차 감리 #6 — reading.css 의 전역 토큰(--bg·--card·--accent 등)은
    `@media(prefers-color-scheme:dark)` 에서 다크 브라운으로 바뀐다(reading.css:9-16).
    그 토큰을 `.birth-form`·`#user-input`·`#send-btn`·`.saju-result` 가 그대로 쓰므로,
    실기기가 다크 모드면 이 화면만 어두운 갈색으로 보였다(입력창·전송버튼 포함) —
    화면 전체를 밝게 만든 의미가 없어진다. `body.sj-on` 은 `:root`(0,1,0)보다 특정성이
    높아(0,1,1) 여기서 다시 정해두면 시스템 설정과 무관하게 이 화면은 항상 밝다.
    2026-09-10 팔레트 교체 — 보라(#9b7fc7 등) → 애프리콧/샴페인골드(스펙 §색상 체계). */
body.sj-on{
  --bg: #fff8ef; --text: #53372c; --muted: #9c8268;
  --accent: #e8967f; --accent2: #f3b9aa; --border: rgba(217,183,123,.32);
  --card: #ffffff; --shadow: 0 4px 18px rgba(184,134,90,.16);
  --bubble-bot: #ffffff; --bubble-user: linear-gradient(135deg,#f3b9aa,#f8d7c4);
  /*  ★ 2026-09-13 사람 지시[배경 불일치 수정] §6 — hud-info(ⓘ)·tarot-coin-widget(은화·연속접속)·
      hud-note·bgm-chip 은 premium-hud.css 의 `--pg-glass`(rgba(38,28,56,.70) "딥 플럼" — 밤
      놀이터용 어두운 보라)를 그대로 물려받아, 밝은 사주방 위에서 진한 보라 pill 로 튀었다
      (실기기 실측). 그 파일 자체는 안 고친다(밤 놀이터는 그 색이 맞다) — 여기 `body.sj-on`
      범위에서만 같은 변수 이름을 warm ivory/champagne-gold 로 다시 정의한다(기능·구조 0줄 변경,
      globals.css 이중화 없음 — CSS 커스텀 프로퍼티 상속만 이용). */
  --pg-glass: rgba(255,250,240,.86);
  --pg-glass-soft: rgba(255,250,240,.72);
  --pg-line: rgba(217,183,123,.4);
  --pg-hi: rgba(255,255,255,.5);
  --pg-ink: #53372c;
  --pg-sh: 0 4px 16px rgba(184,134,90,.18);
}

/* ── 위 띠 · 하연 ────────────────────────────────────────────────── */
/*  2026-09-10 2차 보정 [하연 AI 사주상담 화면 2차 UI 보정] §1·§2 — 영상 자체(h264/yuv420p,
    `ffprobe` 실측 — 알파 채널 없음) 를 임의로 자르거나 필터를 씌우지 않는다(사람 지시대로).
    대신 [무대에 이미 꽉 채워 그린 결과물]을 통째로 `transform:scale()` 로 줄인다 —
    object-fit:cover 의 크롭 계산(어느 부분이 보이는지)은 그대로 두고 [보이는 그림의 크기]만
    줄이는 방식이라 예측 가능하다(inset 으로 상자 자체를 줄이는 방식은 `.tj-cam` 의 카메라
    흔들기 transform·scale(1.035) 과 겹쳐 돔 천장만 크게 확대되는 사고가 났다 — 2026-09-10
    1차 시도 실측, 되돌림). 축소분(0.80) × 카메라 배율(1.035) ≈ 0.828 → 원래보다 **-17%**
    (지시 §2 "15~20% 작게"). origin 을 위쪽(6%)에 둬 축소분이 전부 [머리 위 여백]으로 가고,
    그 여백·양옆에 `.tj-stage` 의 투명 배경 너머 body 의 새 사주관 배경이 비친다. */
body.sj-on .tj-stage{
  inset: 0 0 auto 0;
  height: var(--sj-stage-h);
  z-index: 0;
  overflow: hidden;
  /*  ★ 실측 — shop-tarojip.css:41 의 `.tj-stage{background:#5970b2 url(.../tarojip/base.jpg)...}`
      는 타로집 배경이다(전 상점 공용 셀렉터). 영상을 축소하면 그 여백에 **타로집 배경이
      비치는 사고**가 난다 — 여기서 투명으로 되짚어 새 배경(body)만 비치게 막는다. */
  background: transparent;
}
/*  띠 아랫단 — 무대(사진/영상)가 아래 배경 그림과 자연스럽게 이어지도록. 새 배경 MASTER 의
    윗부분 톤(warm ivory/apricot)에 맞춰 페이드한다(2026-09-10 · 보라 대신 아이보리). */
body.sj-on .tj-stage::after{
  content: ""; position: absolute; inset: auto 0 0 0; height: 38%;   /* 2026-09-13 [배경 불일치 수정] §3 — 30→38%, 영상의 짙은 돔 배경이 방 톤으로 더 확실히 녹아들게 */
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255,248,239,0) 0%, rgba(255,248,239,.94) 100%);   /* .86→.94 */
}
body.sj-on .tj-stage .tj-video,
body.sj-on .tj-stage .tj-still,
body.sj-on .tj-stage .tj-shot{
  object-position: 46% var(--sj-face-y);
  /*  2026-09-13 [배경 불일치 수정] §4 — .78→.72(약 7.7% 축소). 머리 위 여백·어깨가 더
      안정적으로 보이게(사람 지시 "5~10% 정도 작게"). origin 은 그대로 하단 — 축소분이
      전부 위쪽 여백으로 간다. */
  transform: scale(.72);
  /*  origin 을 [하단]에 두면 축소분이 전부 [위쪽 여백]으로 간다(상단 origin 은 반대로
      아래쪽에 여백이 생겨 얼굴이 헤더에 붙어 버렸다 — 2026-09-10 1차 조정 실측·되돌림). */
  transform-origin: 50% 100%;
}

/* ── 머리말 — 밝은 반투명 바 (§3 "← 사주집 · 하연 · 은화/불꽃/음악") ──────── */
body.sj-on header.char-header{
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 4;
  display: flex; align-items: center; justify-content: center;
  height: calc(52px + env(safe-area-inset-top,0px));
  padding: env(safe-area-inset-top,0px) 16px 0;
  background: rgba(255,255,255,.68);
  border-bottom: 1px solid rgba(217,183,123,.3);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
body.sj-on header.char-header .back,
body.sj-on header.char-header .char-name span{ display: none; }
body.sj-on header.char-header .char-name{
  flex: 0 0 auto; align-items: center; max-width: none;
}
body.sj-on header.char-header .char-name strong{
  height: auto; line-height: normal;
  font-size: .92rem; font-weight: 700; letter-spacing: .04em; color: var(--sj-ink, #53372c);
  text-shadow: none;
}
/*  npc.js 헤더채우기() 가 `.char-avatar` 를 header 의 첫 자식으로 넣어 둔다(그 파일:118-134).
    평소(무대가 크게 보일 때)엔 얼굴이 이미 무대 위에 있으니 헤더에서까지 또 보일 필요가
    없다 — sj-compact 일 때만 켠다(아래 §1 컴팩트 절). */
body.sj-on header.char-header .char-avatar{ display: none; }
/*  ★ 2026-09-06 4차 개편 §1 — "하연 (+작은 'AI 사주상담' 부제)" 는 스크롤 전 기본 헤더에서도
    보여야 한다(입력 단계는 애초에 스크롤이 없다). 아래 컴팩트 절의 것과 같은 의사 요소를
    여기서도 켠다 — 이유는 그 절의 주석과 같다(실제 `<span>` 은 saju.js 보다 늦게 채워져
    레이스가 생긴다). */
body.sj-on header.char-header .char-name strong::after{
  content: " · AI 사주상담";
  font-size: .68rem; font-weight: 500; color: var(--sj-sub, #9c8268);
  margin-left: 2px;
}

/* ════════════════════════════════════════════════════════════════════
   컴팩트 모드 (2026-09-05 2차 감리 #1·#7) — 스크롤이 내려가거나 키보드가 뜨면
   대형 영상을 접고 [원형 아바타 + "하연 · AI 사주상담"] 줄 하나로 바꾼다.
   `body.sj-compact` 는 saju.js 의 컴팩트갱신() 이 #chat 스크롤 위치·입력창 포커스를
   보고 붙였다 뗐다 한다. `--sj-stage-h` 하나만 0 으로 죽이면 그 변수를 쓰는 모든 자리
   (무대 높이·#chat 상단·HUD 위젯 위치)가 한꺼번에 접힌다 — 새 레이아웃 변수를 안 만든다.
   ════════════════════════════════════════════════════════════════════ */
/*  ★ 2026-09-05 2차 감리 실측 — 헤더를 그냥 52px 그대로 두고 그 한 줄 안에 아바타+이름을
    넣었더니, 왼쪽의 [‹ 마을] 알약(back-home.js 의 독립 `.ui-topbar`, fixed top:8px)과
    오른쪽의 은화/불꽃 위젯이 같은 줄을 다투어 이름 글자 위에 겹쳤다(코인 위젯이 x=260~400
    을 먹어 이름이 x=283 까지 번져 겹침). 그래서 컴팩트 헤더는 **두 줄**이다 — 위 44px 는
    지금까지처럼 back-pill·코인 위젯이 쓰고, 아바타+이름은 그 아래 새 줄에 앉는다. */
body.sj-on.sj-compact{ --sj-stage-h: calc(88px + env(safe-area-inset-top,0px)); }
body.sj-on.sj-compact .tj-stage{
  visibility: hidden;   /* display:none 은 안 쓴다 — ShopStage 의 영상 재생 상태를 죽이지 않는다 */
}
body.sj-on.sj-compact header.char-header{
  height: calc(88px + env(safe-area-inset-top,0px));
  align-items: flex-end; padding-bottom: 8px; justify-content: center;
}
body.sj-on.sj-compact header.char-header .char-avatar{
  display: block; width: 28px; height: 28px; border-radius: 50%;
  object-fit: cover; object-position: center 15%;
  margin-right: 7px; border: 1px solid rgba(217,183,123,.4); flex: 0 0 auto;
}
body.sj-on.sj-compact header.char-header .char-name{ max-width: min(70vw, 320px); }
body.sj-on.sj-compact header.char-header .char-name strong{
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
  display: inline-block; vertical-align: bottom;
}
body.sj-on.sj-compact header.char-header .char-name{ display: flex; align-items: baseline; gap: 4px; }
/*  ★ 실제 `<span>`(npc.js 헤더채우기() 가 채운 "사주 상담가 · …")은 계속 숨긴다 — 그 텍스트를
    saju.js 로 다시 덮어쓰려면 그 스크립트가 saju.js **뒤에** 도는 순서(saju.html 맨 끝
    인라인 스크립트)를 기다려야 해 레이스가 생긴다. 대신 고정 문구를 의사 요소로 붙인다 —
    지시 §1 이 원한 글자("하연 · AI 사주상담")는 이거 하나로 끝난다. */
body.sj-on.sj-compact header.char-header .char-name strong::after{
  content: " · AI 사주상담";
  font-size: .74rem; font-weight: 500; color: var(--sj-sub, #9c8268);
}
/*  HUD 위젯(BGM·은화·안내) — 무대 띠가 사라지면 그 아래에 붙던 자리도 같이 사라진다.
    컴팩트일 땐 헤더 줄(52px) 안쪽으로 옮긴다. */
body.sj-on.sj-compact.premium-hud .bgm-chip,
body.sj-on.sj-compact.premium-hud.bgm-chip-on .bgm-chip,
body.sj-on.sj-compact.premium-hud .tarot-coin-widget,
body.sj-on.sj-compact .hud-info{
  top: calc(env(safe-area-inset-top,0px) + 8px) !important; bottom: auto !important;
}
@media (prefers-reduced-motion: no-preference){
  body.sj-on .tj-stage{ transition: height .28s ease, visibility 0s linear .28s; }
  body.sj-on.sj-compact .tj-stage{ transition: height .28s ease, visibility 0s linear 0s; }
}

/* ════════════════════════════════════════════════════════════════════
   스크롤 컴팩트 모드 — 대화 중 하연 영상 지속 노출(2026-09-11 사람 지시)
   ────────────────────────────────────────────────────────────────────
   문제: 대화가 쌓여 #chat 을 스크롤하면(=포커스 없이 스크롤만 됐을 때) 위 sj-compact
   절이 걸려 무대가 `visibility:hidden` 으로 완전히 숨고 28px 원형 정지 이미지 하나만
   남았다 — 상담 중엔 하연 표정 영상을 전혀 못 봤다.
   해결: saju.js 컴팩트갱신() 이 그 경우엔 `sj-compact` 대신 이 `sj-scroll-compact` 를
   붙인다(둘은 동시에 서지 않는다 — 포커스가 최우선). 무대를 숨기지 않고 `--sj-stage-h`
   하나만 가로형 컴팩트 높이로 줄인다 — 그 변수를 쓰는 무대·HUD·#chat 이 전부 같이
   움직인다(§ sj-compact 머리말과 같은 원리, 새 레이아웃 변수를 안 만든다).
   0.9초 상태 크로스페이드·컴팩트갱신()의 히스테리시스 문턱·sj-compact 자체는 그대로다.
   ════════════════════════════════════════════════════════════════════ */
body.sj-on.sj-scroll-compact{
  --sj-stage-h: 150px;   /* 지시 §2 권장 범위(120~150px) 상한 — 실측 대상 */
  --sj-face-y: 30%;      /* 좁아진 창에서도 얼굴이 보이게 재조정(1차 시도 18%는 이마 위만 보여 되돌림) */
}
/*  큰 무대에서 쓰던 축소(scale .78)는 여기서 되돌린다 — 140px 처럼 좁은 띠에서는
    얼굴을 오히려 꽉 채워야 식별이 된다(지시 §2 "하연 얼굴은 충분히 식별되어야"). */
body.sj-on.sj-scroll-compact .tj-stage .tj-video,
body.sj-on.sj-scroll-compact .tj-stage .tj-still,
body.sj-on.sj-scroll-compact .tj-stage .tj-shot{
  transform: none;
}
/*  큰 무대용 아이보리 페이드(30% 높이)는 140px 안에서는 과하게 크다 — 얇게 줄인다. */
body.sj-on.sj-scroll-compact .tj-stage::after{
  height: 22%;
}
@media (prefers-reduced-motion: no-preference){
  body.sj-on.sj-scroll-compact .tj-stage{ transition: height .28s ease; }
}
/*  2026-09-15 [FINAL GATE 시각 감사] 실측 — 이 모드는 얼굴을 다시 꽉 채우므로(§ 위 transform:none)
    [‹ 마을] 알약이 그 얼굴 바로 위에 뜬다. 알약 배경(`--pg-glass`)이 86% 라 큰 무대(정적인
    방 그림)에서는 안 보이던 정도의 반투명이, 여기서는 하연 얼굴이 그 14% 틈으로 비쳐 알약
    뒤에서 유령처럼 겹쳐 보였다(실기기·헤드리스 공통 재현) — премиум한 채팅이 아니라 깨진
    화면처럼 읽힌다. 이 모드에서만 알약을 사실상 불투명으로 올린다(기본 275px 무대 위에서는
    안 건드린다 — 그 값은 그대로 유효했다). */
body.sj-on.sj-scroll-compact .backhome.jelly,
body.sj-on.sj-scroll-compact .backhome{
  background: linear-gradient(180deg, var(--pg-hi), transparent 42%), rgba(255,250,240,.97);
}

/* ── HUD 세 조각(BGM 아이콘·은화·안내)을 하연 얼굴에서 내린다 ─────────── */
body.sj-on.premium-hud .bgm-chip,
body.sj-on.premium-hud.bgm-chip-on .bgm-chip,
body.sj-on.premium-hud .tarot-coin-widget{
  top: auto;
  bottom: calc(100dvh - var(--sj-stage-h) + 8px);
}
body.sj-on .hud-info{ top: auto; bottom: calc(100dvh - var(--sj-stage-h) + 8px); }
/* 은화·🔥 알약이 ⓘ(36px · right 12px) 밑에 깔려 "+10" 칸을 덮던 것(2026-10-12 실기기 지적) —
   ⓘ 왼쪽에 나란히 세우고, 숫자가 길어져도 왼쪽 칩(음악 12~52 · 마이크 60~100)을 넘지 않게 폭 상한을 둔다. */
body.sj-on.premium-hud .tarot-coin-widget{
  right: calc(12px + 36px + 8px + env(safe-area-inset-right,0px));
  max-width: calc(100vw - 164px); box-sizing: border-box; overflow: hidden; white-space: nowrap;
}
/* 좁은 폰(≤400px)에서는 "2일 뒤 +10" 꼬리를 접는다 — 은화 네 자리·🔥 세 자리가 한 줄에 들어가야 줄바꿈으로 알약이 깨지지 않는다(다른 화면에는 그대로) */
@media (max-width: 400px){
  body.sj-on.premium-hud .tarot-coin-widget .coin-streak-next{ display: none; }
}

/* ── 소리 위젯(`.tarot-audio-widget` · audio.js) — 2026-09-10 2차 보정 §7 ──────────────
   지시: "화면 하단 왼쪽에 혼자 떨어져 있는 [음성 버튼]을 제거하고 상단 네비게이션의
   음악 버튼과 동일한 컨트롤 그룹으로 배치한다. 기능과 handler는 그대로 유지한다."
   ★ 이 위젯의 실제 기능은 [배경음악/효과음/볼륨 설정](audio.js:1153 aria-label) 이다 —
   TTS 같은 "음성" 기능은 이 앱에 없다(1차 보정 보고서에서 이미 확인). 스피커 모양(🔊/🔇)을
   보고 [음성]으로 부른 것으로 보인다 — 명칭은 그대로 두고 자리·아이콘만 옮긴다.
   JS(`audio.js`)는 위치를 몰라도 되게 짜여 있다(CSS 로만 위치가 정해진다) — 여기서
   `position:fixed` 좌표만 bgm-chip 옆(같은 bottom·오른쪽 8px)으로 바꾼다. 이모지 텍스트는
   숨기고 전용 마이크형 아이콘(mic.webp)으로 바꿔 음악 아이콘과 헷갈리지 않게 한다. */
body.sj-on.premium-hud .tarot-audio-widget{
  position: fixed; z-index: 21;
  top: auto; bottom: calc(100dvh - var(--sj-stage-h) + 8px);
  left: 60px; right: auto;
  width: 40px; height: 40px; min-width: 0; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(255,255,255,.7); border: 1px solid rgba(217,183,123,.35);
  box-shadow: none; font-size: 0;   /* JS 가 채우는 🔊/🔇 텍스트를 감춘다 — 요소·handler 는 그대로 */
}
body.sj-on.premium-hud .tarot-audio-widget::before{
  content: ""; width: 20px; height: 20px;
  background: url("assets/ui/mini-icons/saju-mic.webp") center / contain no-repeat;
  opacity: .92;
}
body.sj-on.sj-compact.premium-hud .tarot-audio-widget{
  top: calc(env(safe-area-inset-top,0px) + 8px) !important; bottom: auto !important;
}

/* ── 음악 UI — 곡 제목 줄을 지우고 아이콘 하나로 (§3) ──────────────────
   `.bgm-chip-title`(곡 제목 글자) · `.bgm-eq`(막대 이퀄라이저)를 감추고, 재생 상태는
   이미 있는 `.is-playing` 클래스로 CSS 만으로 가른다 — bgm-player.js/css 는 한 글자도
   안 고친다(그 파일은 index.html 등 다른 화면과도 공유한다 · 규칙 6). */
/*  ★ premium-hud.css:105-ish 의 `body.premium-hud.bgm-chip-on .bgm-chip{width:auto}` 가
    (0,3,1) 특정성이라 `body.sj-on .bgm-chip`(0,2,1) 만으로는 안 이긴다(2026-09-05 실측 —
    아이콘 규칙을 걸어도 곡 제목이 그대로 보였다). 같은 세 클래스 조합으로 맞춘다. */
body.sj-on.premium-hud .bgm-chip,
body.sj-on.premium-hud.bgm-chip-on .bgm-chip{
  width: 40px; height: 40px; min-width: 0; padding: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: rgba(255,255,255,.7); border: 1px solid rgba(217,183,123,.35);
}
/*  ★ 2026-09-10 실측 — premium-hud.css:103·108 의 `body.premium-hud .bgm-chip .bgm-chip-title`·
    `.bgm-eq`(둘 다 특정성 0,3,0)가 아래 규칙(옛 0,2,0)보다 높아 곡 제목 글자("bgm_shop4_muk.mp3")가
    무대 위에 그대로 보였다(스크린샷 실측 · saju-stage.css:164 의 옛 주석이 같은 함정을 .bgm-chip
    자체에서는 이미 경고했는데 title·eq 는 놓쳤다). body.sj-on.premium-hud 로 특정성을 0,4,0 까지
    올려 이긴다. */
body.sj-on.premium-hud .bgm-chip-title,
body.sj-on.premium-hud .bgm-chip .bgm-eq{ display: none; }
/*  2026-09-10 [전용 에셋 적용] — 이모지 대신 새 음악 아이콘(아이콘시트 슬라이스)을 쓴다.
    기능(재생/음소거 토글)은 그대로 — .is-playing 클래스로 이미지만 바뀐다(새 로직 0줄). */
body.sj-on .bgm-chip::before{
  content: ""; width: 22px; height: 22px;
  background: url("assets/ui/mini-icons/saju-music.webp") center / contain no-repeat;
  opacity: .92;
}
body.sj-on .bgm-chip:not(.is-playing)::before{ opacity: .4; filter: grayscale(.6); }

/* ── 아래 띠 · 대화 ──────────────────────────────────────────────── */
body.sj-on{ padding-top: 0; }
body.sj-on #chat{
  position: fixed; left: 0; right: 0;
  top: var(--sj-stage-h);
  bottom: calc(var(--sj-bottom-h) + var(--banner-ad-height, 0px));
  margin: 0; max-width: none;
  padding: 10px max(16px, calc(50% - var(--sj-col) / 2)) 10px;   /* 2026-09-13 [배경 불일치 수정] §5 — 18→10px, 말풍선을 하연 쪽으로 더 붙인다(2026-09-10 §8 의 넓은 여백을 다시 좁힘 — 최근 지시 우선) */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  z-index: 2;
  background: transparent;
}

/* ── 아래 고정 바 — 칩 행 + 입력칸 (지시 §10 · 2026-09-06 §12 재조정) ────────────
   `.sj-bottom` 이 `<div class="sj-chips">` 와 `<form id="composer">` 를 감싼다(saju.js
   사주바닥세우기() 가 만든다 — 도사집 `.dj-bottom` 과 같은 틀). ★ 2026-09-06 최종 개편
   §12 — 생년월일 입력 단계에는 채팅 입력창이 없다. 그 사이엔 `.sj-bottom` 자체를 숨긴다 —
   안 그러면 composer 도 칩도 없는 빈 그라디언트 띠만 화면 아래 남는다. `body.sj-composer-on`
   은 saju.js 상담칸열기() 가 실제 상담이 시작되는 자리에서만 붙인다. */
body.sj-on .sj-bottom{ display: none; }
body.sj-on.sj-composer-on .sj-bottom{
  display: block;
  position: fixed; left: 0; right: 0;
  bottom: var(--banner-ad-height, 0px);
  z-index: 3;
  background: linear-gradient(180deg, rgba(248,228,214,.35) 0%, #f8e4d6 42%);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
body.sj-on #composer{
  position: static; max-width: var(--sj-col); margin: 0 auto;
  background: transparent; border-top: 0;
}
body.sj-on #composer.hidden{ display: none; }   /* 안전망 — saju.js 는 이제 이 클래스를 안 건드린다 */
body.sj-on #user-input:disabled{ opacity: .55; }

/* ── quick-reply 칩 행(§10 동적 빠른 선택지) — 입력칸 바로 위 한 줄 ────────
   도사집 `.dj-chips` 와 같은 규격(자유입력이 기본 · chip 은 보조). 색만 밝게. */
body.sj-on .sj-chips{
  display: flex; gap: 8px;
  max-width: var(--sj-col); margin: 0 auto;
  padding: 8px max(16px, calc(50% - var(--sj-col) / 2)) 2px;
  overflow-x: auto; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
body.sj-on .sj-chips::-webkit-scrollbar{ display: none; }
body.sj-on .sj-chips:empty{ display: none; padding: 0; }
body.sj-on .sj-chips button{
  flex: 0 0 auto;
  min-height: 36px; padding: 0 14px;
  border-radius: 999px;
  border: 1px solid rgba(217,183,123,.4);
  background: rgba(255,255,255,.82);
  color: var(--sj-ink, #53372c);
  font: inherit; font-size: .84rem; line-height: 1;
  cursor: pointer; white-space: nowrap;
}
body.sj-on .sj-chips button:active{ background: var(--sj-lav, #fbe3d8); }
/*  선택된 칩 — 연피치 fill (2026-09-10 팔레트 교체 · 옛 라벤더 자리). */
body.sj-on .sj-chips button.is-on{
  background: var(--sj-lav, #fbe3d8); border-color: rgba(217,183,123,.7);
  font-weight: 600;
}

/* ── 분석 로딩 카드 (2026-09-05 2차 감리 #2) — 채팅 기록에 안 남는다 ─────────────
   saju.js 로딩카드세우기() 가 #chat 에 직접 붙인다(Dialogue.addMessage 를 안 거친다 —
   addTyping() 과 같은 자리). 문구가 그 안에서 바뀌고, 끝나면 카드째 사라진다. */
body.sj-on .sj-loading{
  align-self: flex-start; margin-left: 34px; max-width: min(84%, 340px);
  display: flex; align-items: center; gap: 8px;
  padding: 12px 15px; border-radius: 18px; border-bottom-left-radius: 4px;
  background: var(--sj-card, #fff); border: 1px solid var(--sj-line, rgba(217,183,123,.32));
  color: var(--sj-sub, #9c8268); font-size: .86rem;
}
body.sj-on .sj-loading-dot{
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  background: var(--sj-gold, #c9a961);
}
@media (prefers-reduced-motion: no-preference){
  body.sj-on .sj-loading-dot{ animation: sj-loading-pulse 1.1s ease-in-out infinite; }
}
@keyframes sj-loading-pulse{ 0%,100%{ opacity:.35; transform:scale(.85); } 50%{ opacity:1; transform:scale(1); } }

/* ── 면책 줄 — 짧은판(2026-09-05 2차 감리 #8) ────────────────────────────────
   safety-gate.js 면책줄붙이기(chat,"saju",true) 로 이미 짧은 문장을 받는다(safety-gate.js:82
   짧은면책문). 옛 레이아웃(무대 없음) 시절 40px 오프셋(safety-gate.css:47-50)은 지금
   무대 띠 아래에서는 필요 없다 — 여기서 지운다. 상세 전문은 헤더 ⓘ(#sj-info/#sj-note)가 맡는다. */
body.sj-on .sg-disclaimer[data-screen="saju"]{
  margin: 0 0 8px; padding: 5px 12px; font-size: .68rem;
  border-radius: 999px; display: inline-block;
  background: rgba(217,183,123,.14); color: var(--sj-sub, #9c8268);
}

/* ── 메시지 그룹 아바타 (2026-09-05 2차 감리 #9) ─────────────────────────────
   reading.css:69 의 `.msg.bot::before{content:"🔮"}` 는 전 화면 공통이라 안 건드린다
   (그 파일은 reading/mbti/physiognomy/playground 도 같이 쓴다). 여기서는 사주집 화면 안에서만
   ① 아이콘을 하연 얼굴로 바꾸고 ② saju.js 메시지그룹표시() 가 [연속된 두 번째 이후 답]에
   붙이는 `.msg-cont` 에서는 아예 감춘다. */
/*  2026-09-10 [전용 에셋 적용] §3 — 새 [하연 프로필 아이콘 MASTER](원형 프레임까지 그림
    안에 이미 있다)로 교체. 기존 yeonhui.png(전신 컷아웃)를 얼굴 위주로 잘라 쓰던 것보다
    원형 아바타 자리에 더 맞는다. */
body.sj-on #chat .msg.bot::before{
  background: var(--sj-profile, url("assets/village/npc/icons/yeonhui-profile.webp")) center / cover no-repeat;   /* Android 치비무대(shop-stage.js)만 --sj-profile 을 건다 · iOS 는 옛 아이콘 그대로 */
  content: "";
}
body.sj-on #chat .msg.bot.msg-cont::before{ display: none; }

/* ── 말풍선 폭·색 분리 (2026-09-06 Round5 §4·§8·§22-5) ─────────────────────────
   reading.css:61 의 `.msg{max-width:82%}` 하나를 bot/user 가 같이 썼다 — 폭이 같으니
   [누가 말했는지]가 잘 안 갈렸다. bot 은 넓게, user 는 좁게 갈라 시선이 자연히 정렬을
   따라가게 한다. user 말풍선 색도 흰 글자+진한 보라 그라디언트(reading.css:74-76)에서
   지시(§8) 그대로 [연라벤더 배경 + 딥퍼플 글자]로 바꾼다 — bot(흰 카드)과 더 확실히 갈린다. */
body.sj-on .msg.bot{ max-width: min(76%, 300px); }   /* 2026-09-10 2차 보정 §3 — 폭 축소 */
body.sj-on .msg.user{
  max-width: 70%;
  background: #fdece2; color: #6b3d2e;
  box-shadow: none; border: 1px solid rgba(217,183,123,.24);
}

/* ── typing indicator 축소 (2026-09-06 Round5 §13·§22-8) ─────────────────────
   `.typing-msg` 는 dialogue.js addTyping() 이 `.msg.bot` 그대로 붙인다(reading.css 공용이라
   그 파일은 안 건드린다) — 점 3개(각 6px)만 담는데도 일반 말풍선과 같은 padding·max-width를
   써서 상자가 컸다. 여기서만 작은 필로 좁힌다. */
body.sj-on .msg.bot.typing-msg{
  max-width: 56px; min-width: 0; padding: 9px 14px;
}

/* ── "새 메시지 ↓" (2026-09-06 Round5 §19) — saju.js addMessage() 가 사용자가 위로 스크롤한
   상태에서 새 말풍선이 오면 강제로 끌어내리지 않고 이 pill 을 띄운다(dialogue.js 는 안 건드린다). */
body.sj-on .sj-new-msg{
  position: fixed; left: 50%; transform: translateX(-50%) translateY(6px);
  bottom: calc(var(--sj-bottom-h, 60px) + var(--banner-ad-height, 0px) + 12px);
  z-index: 5;
  display: flex; align-items: center; gap: 5px;
  padding: 7px 14px; border-radius: 999px; border: none;
  background: linear-gradient(135deg, #f3b9aa, #e8967f); color: #4a2a1e;
  font-size: .78rem; font-weight: 600;
  box-shadow: 0 6px 16px rgba(184,134,90,.32);
  opacity: 0; pointer-events: none; transition: opacity .18s ease, transform .18s ease;
}
body.sj-on .sj-new-msg.is-on{ opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }

/* ── "🔎 사주식으로 보면?" 토글 (2026-09-06 Round5 §6) — reading.css:157 .ai-report 와
   같은 결의 작은 밑줄 링크. 34px 왼쪽 여백은 하연 아바타(msg.bot::before) 폭과 맞춘 것이다. */
body.sj-on .sj-jargon-btn{
  display: block; margin: 4px 0 0 34px;
  background: none; border: none; padding: 2px 0; font-family: inherit;
  font-size: .74rem; color: #a86a3a; text-decoration: underline; cursor: pointer;
}

/* ── 면책 [자세히 보기] (2026-09-06 Round5 §15) — safety-gate.js 는 안 건드린다.
   그 함수가 만든 `.sg-disclaimer` 엘리먼트를 saju.js 가 `.sj-bottom` 칩 행 위로 옮기고
   그 옆에 붙이는 토글 버튼·상세 패널만 여기서 그린다. */
body.sj-on .sj-bottom .sg-disclaimer[data-screen="saju"]{
  margin: 6px auto 0; max-width: var(--sj-col);
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 5px 14px; width: fit-content;
}
body.sj-on .sj-disclaimer-more{
  border: none; background: none; padding: 0; margin: 0;
  font-size: .68rem; font-weight: 600; color: #a86a3a; white-space: nowrap; cursor: pointer;
}
body.sj-on .sj-disclaimer-detail{
  margin: 4px auto 0; max-width: var(--sj-col);
  background: #fff; border: 1px solid rgba(217,183,123,.3); border-radius: 12px;
  padding: 10px 14px; font-size: .74rem; line-height: 1.5; color: var(--sj-sub, #9c8268);
}
body.sj-on .sj-disclaimer-detail[hidden]{ display: none; }
body.sj-on .sj-disclaimer-detail p{ margin: 0 0 6px; }
body.sj-on .sj-disclaimer-detail p:last-child{ margin-bottom: 0; }
body.sj-on .sj-disclaimer-detail button{
  border: none; background: none; padding: 0; margin-top: 2px;
  font-size: .74rem; font-weight: 600; color: #a86a3a; cursor: pointer; text-decoration: underline;
}

/* ── 입력창 바 (2026-09-06 Round5 §16) — `.sj-bottom` 그라디언트 위에 테두리 없이 떠 있던 것을
   흰 배경 + 연라벤더 테두리의 독립된 알약 바로 바꾼다. "+"·🎙 버튼은 실제 동작(첨부·음성인식)이
   없어 안 만든다(§23 새 기능 금지) — 바탕·테두리·포커스 색만 시안에 맞춘다. */
body.sj-on #composer{
  background: #ffffff; border: 1px solid rgba(217,183,123,.35);
  border-radius: 999px; padding: 6px 6px 6px 16px; gap: 8px;
  box-shadow: 0 2px 10px rgba(184,134,90,.12);
}
body.sj-on #user-input{ background: transparent; border: none; padding: 8px 0; }
body.sj-on #user-input:focus{ outline: none; }
body.sj-on #composer:focus-within{ border-color: #e8967f; box-shadow: 0 2px 12px rgba(184,134,90,.22); }
body.sj-on #send-btn{ border-radius: 999px; min-height: 40px; }

/* ── 사주판 bottom sheet (§15) ────────────────────────────────────────
   전문 사주 정보(4기둥·오행·구간탐색 그리드)는 여기 안에서만 보인다. */
body.sj-on .sj-sheet[hidden]{ display: none; }
body.sj-on .sj-sheet{
  position: fixed; inset: 0; z-index: 40;
}
body.sj-on .sj-sheet-scrim{
  position: absolute; inset: 0; background: rgba(60,42,30,.32);
}
body.sj-on .sj-sheet-box{
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: min(78dvh, 640px);
  background: #fffaf3;
  border-radius: 20px 20px 0 0;
  border: 1px solid rgba(217,183,123,.32); border-bottom: 0;
  box-shadow: 0 -8px 28px rgba(60,42,30,.2);
  display: flex; flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
body.sj-on .sj-sheet-head{
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px 8px; border-bottom: 1px solid rgba(217,183,123,.22);
}
body.sj-on .sj-sheet-head h3{ margin: 0; font-size: .92rem; font-weight: 700; color: var(--sj-ink, #53372c); }
body.sj-on .sj-sheet-close{
  border: 0; background: rgba(217,183,123,.16); color: var(--sj-ink, #53372c);
  width: 30px; height: 30px; border-radius: 50%; font: inherit; font-size: .82rem; cursor: pointer;
}
body.sj-on .sj-sheet-body{
  flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 12px 16px calc(16px + env(safe-area-inset-bottom,0px));
  display: flex; flex-direction: column; gap: 12px;
}
/*  시트 안에서는 결과 카드가 대화 로그 카드가 아니라 그냥 패널이다 — 왼쪽 들여쓰기(margin-left)를 지운다. */
body.sj-on .sj-sheet-body .saju-result{ margin-left: 0; max-width: none; align-self: stretch; }
body.sj-on .sj-sheet-body .sf-card{ margin: 0; }
/*  2026-09-07 #153 (art-director 조건 2) — 이 한 줄이 없어서 saju.js 사주판열기() 가 만든
    <p class="sj-sheet-intro"> 가 브라우저 기본값(1rem · margin 1em 0)으로 떨어졌다. 시트 안에서
    가장 큰 글자가 되고 위아래 32px 를 먹어, 표가 둘인 궁합에서는 흐름 그리드가 시트 바닥에
    21px 만 걸쳤다(실측). 숫자는 전부 이미 있는 것이다 — .92rem · 1.5 · --sj-ink 는
    saju-ui.css:128 의 .sj-mini-line 과 같은 값이고 gap 12 는 .sj-sheet-body 가 이미 준다. */
body.sj-on .sj-sheet-intro{ margin: 0; font-size: .92rem; line-height: 1.5; color: var(--sj-ink); }

/* ════════════════════════════════════════════════════════════════════
   생년월일 카드 — 최종 개편(2026-09-06) §4~§11
   ────────────────────────────────────────────────────────────────────
   `.birth-form` 이하 기본 뼈대(`saju.css`)는 도사집과 같이 쓰는 공용 정본이라 그 파일은
   안 건드린다. 여기서는 사주집 화면(body.sj-on) 안에서만 겉모습을 덧입힌다 — DOM 은
   saju.js 생일폼꾸미기() 가 만들고(제목·부제·도움말·개인정보 문구), 나머지는 이미 있는
   클래스(.birth-row·.birth-checkbox·.birth-gender·.birth-submit)를 다시 그린다.
   ════════════════════════════════════════════════════════════════════ */

/* §4 — 카드 자체: 더 압축하고 밝게. 진한 갈색 카드 금지.
   ★ 2026-09-06 실기기 실측 — 배너 광고(64~80px, ads.js 실측값)가 #chat 아래를 추가로
   먹어 카드가 스크롤 없이 다 안 보였다(scrollHeight 733 / clientHeight 608 · 폴드 실측).
   글자 크기는 그대로 두고 여백만 더 줄인다(§19 아래 720px 조건과 같은 값을 기본으로 올린다 —
   배너 유무는 CSS 미디어쿼리로 못 재므로 화면 높이와 무관하게 항상 적용).
   2026-09-10 팔레트 교체(사람 지시 [사주관 AI 상담화면 전체 UI 리뉴얼]) — 보라 테두리/그림자를
   샴페인골드로. 카드 상단에 [하연 사주 심볼](starflower) 을 얹는다(스펙 §4 "카드 상단에는
   새롭게 제작한 [하연 사주 심볼]을 작게 배치"). */
/*  2026-09-10 2차 보정 §4 — 입력카드가 하연보다 시각적 비중이 커 보인다는 지적. 패딩·행간만
    줄인다(글자 크기·터치영역은 그대로) — 카드 전체 높이가 대략 12% 준다(실측 대상). */
/*  2026-09-10 3차 보정 §4 — 추가로 15~20% 더 압축(패딩·행간만, 글자 크기·터치영역은 그대로). */
body.sj-on .birth-form{
  position: relative;
  margin: 6px auto; padding: 12px 15px 8px; gap: 4px;
  border-radius: 20px;
  background: linear-gradient(180deg, #fffdf9 0%, #fff6ec 100%);
  border: 1px solid rgba(217,183,123,.34);
  box-shadow: 0 6px 20px rgba(184,134,90,.16);
}
body.sj-on .birth-form::before{
  content: ""; position: absolute; top: -12px; left: 50%; transform: translateX(-50%);
  width: 24px; height: 24px;
  background: url("assets/ui/mini-icons/saju-starflower.webp") center / contain no-repeat;
  pointer-events: none;
}
/* §5 — 큰 음양 아이콘(기존 SVG)은 감춘다 — 위 ::before 심볼이 그 자리를 대신한다(스펙 §4). */
body.sj-on .birth-form .saju-icon{ display: none; }
body.sj-on .birth-form .birth-intro.sj-birth-title{
  margin: 0; font-size: .98rem; font-weight: 700; color: var(--sj-ink, #53372c);
}
body.sj-on .birth-form .sj-birth-sub{
  margin: -4px 0 2px; font-size: .74rem; color: var(--sj-sub, #9c8268); text-align: center; line-height: 1.4;
}
/*  2026-09-10 2차 보정 §5 — "아주 소량의 blue-hour navy" 포인트. 카드 전체를 아이보리/피치
    한 톤으로만 두지 않는다는 지시라 딱 한 글자(강조 단어)에만 쓴다. */
body.sj-on .birth-form .sj-birth-sub b{ color: #53657a; font-weight: 700; }

/* §5-2 — 양력/음력 토글(스펙 §5) — sun/moon 아이콘 두 개짜리 세그먼트. 실제 계산 경로는
   `saju.js` 생일폼꾸미기() 의 제출 가로채기(§12) 하나뿐 — 새 계산식은 여기서 만들지 않는다. */
body.sj-on .sj-cal-toggle{
  display: flex; gap: 6px; margin: 0 0 2px;
}
body.sj-on .sj-cal-opt{
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
  min-height: 36px; border-radius: 999px; cursor: pointer;
  border: 1px solid rgba(217,183,123,.32); background: #fdf8f0;
  color: var(--sj-sub, #9c8268); font-size: .82rem; font-weight: 600;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
body.sj-on .sj-cal-opt input[type="radio"]{ position: absolute; opacity: 0; width: 0; height: 0; }
body.sj-on .sj-cal-opt .sj-cal-ico{ width: 16px; height: 16px; object-fit: contain; flex: 0 0 auto; }
body.sj-on .sj-cal-opt.is-on{
  background: linear-gradient(135deg, #fbe3d8, #f8d7c4);
  border-color: rgba(217,183,123,.6); color: var(--sj-ink, #53372c);
}
body.sj-on .sj-cal-note{
  margin: 0 0 2px; font-size: .68rem; color: var(--sj-sub, #9c8268); text-align: center;
}

/* §6·§7 — 입력칸을 picker 처럼. 실제 <input type=number> 는 그대로, 겉모습만 바꾼다.
   2026-09-10 3차 보정 §5 — 라벨-입력창 간격 축소, 숫자 중앙정렬, 미선택 테두리를 더 연하게. */
body.sj-on .birth-row{ gap: 6px; }
body.sj-on .birth-row.sj-picker,
body.sj-on .birth-row label.sj-picker{ font-size: .72rem; color: var(--sj-sub, #9c8268); gap: 2px; }
body.sj-on .birth-row label.sj-picker{ position: relative; }
body.sj-on .birth-row label.sj-picker input{
  background: #fdf9f2; border: 1px solid rgba(217,183,123,.2);
  color: var(--sj-ink, #53372c); font-weight: 600; text-align: center;
  padding: 8px 18px 8px 8px;   /* 오른쪽에 ▼ 자리를 비운다 */
  border-radius: 12px;
}
body.sj-on .birth-row label.sj-picker::after{
  content: "▾"; position: absolute; right: 8px; bottom: 10px;
  font-size: .72rem; color: rgba(184,134,90,.55); pointer-events: none;
}
body.sj-on .birth-row label.sj-picker input:focus{ outline: 2px solid #e8967f; }
body.sj-on .birth-row label.sj-picker input:disabled{
  background: #f5ede1; color: rgba(83,55,44,.4); border-color: rgba(217,183,123,.22);
}
/*  2026-09-15 [FINAL GATE 시각 감사] — placeholder(1990·5·15 예시 숫자)가 실제 입력값과
    같은 진한 잉크색(font-weight:600)이라 [이미 채워진 값]처럼 보였다(실측 — 그대로 제출
    버튼을 눌러 버림). 예시임을 눈으로 갈라 보이게 옅고 가늘게만 낮춘다 — 값 자체·계산은
    그대로, 색·굵기만. */
body.sj-on .birth-row label.sj-picker input::placeholder{
  color: rgba(156,130,104,.62); font-weight: 500;
}
/*  빈 칸 제출 시도 — 브라우저 기본 팝업 대신 이 화면 톤으로. 300ms 이내 짧은 흔들림
    한 번(§7 Micro Interaction 100~350ms) + 테두리 경고색. 반복 재생하지 않는다. */
body.sj-on .birth-row label.sj-picker input.birth-input-shake{
  border-color: #e8967f; animation: sj-input-shake .3s ease;
}
@keyframes sj-input-shake{
  0%, 100%{ transform: translateX(0); }
  20%{ transform: translateX(-4px); }
  40%{ transform: translateX(3px); }
  60%{ transform: translateX(-2px); }
  80%{ transform: translateX(2px); }
}
@media (prefers-reduced-motion: reduce){
  body.sj-on .birth-row label.sj-picker input.birth-input-shake{ animation: none; }
}

/* §8 — 커스텀 체크박스 + 도움말. 2026-09-10 3차 보정 §6 — "[□] 태어난 시간을 몰라요  [ⓘ]"
   한 줄로. `.sj-time-row`(saju.js 생일폼꾸미기() 가 감싸는 wrapper)가 체크박스 label 과
   도움말 버튼을 한 flex 줄에 나란히 둔다 — 각 요소 자체(birth-checkbox·sj-birth-help)의
   기능·handler 는 그대로다. */
body.sj-on .sj-time-row{
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
body.sj-on .birth-checkbox{ position: relative; font-size: .82rem; color: var(--sj-ink, #53372c); }
body.sj-on .birth-checkbox input[type="checkbox"]{
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 5px;
  border: 1.5px solid rgba(217,183,123,.5); background: #fff;
  display: inline-grid; place-content: center; margin: 0; cursor: pointer;
}
body.sj-on .birth-checkbox input[type="checkbox"]::before{
  content: ""; width: 10px; height: 10px; border-radius: 2px;
  transform: scale(0); transition: transform .12s ease-in;
  background: #d9a054;
}
body.sj-on .birth-checkbox input[type="checkbox"]:checked{ border-color: #d9a054; background: #fbeed9; }
body.sj-on .birth-checkbox input[type="checkbox"]:checked::before{ transform: scale(1); }
body.sj-on .sj-birth-help{
  flex: 0 0 auto; width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid rgba(217,183,123,.4); background: #fff; color: var(--sj-sub, #9c8268);
  font: inherit; font-size: .74rem; line-height: 1; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
body.sj-on .sj-birth-help-note{
  display: block; margin-top: 4px; font-size: .72rem; line-height: 1.4;
  color: var(--sj-sub, #9c8268); background: #fbf1e2; border-radius: 10px; padding: 7px 10px;
}
/*  ★ 실측 — 위 규칙(0,2,1)이 [hidden] 속성의 기본 display:none 보다 특정성이 높아 이겨버려
    도움말이 항상 펼쳐진 채로 보였다. hidden 이면 다시 숨긴다. */
body.sj-on .sj-birth-help-note[hidden]{ display: none; }

/* §9 — 성별 chip(스펙 §8 — 유아적 캐릭터 그림 없이 텍스트 칩 그대로, 색만 교체) */
body.sj-on .birth-gender{ gap: 10px; margin-top: 0; }
body.sj-on .birth-gender legend{ display: none; }   /* "성별" 글자는 chip 두 개로 이미 뜻이 보인다 */
body.sj-on .birth-gender label{
  flex: 1; justify-content: center; gap: 6px;
  min-height: 42px; border-radius: 12px;
  border: 1px solid rgba(217,183,123,.3); background: #fff; color: var(--sj-ink, #53372c);
  font-size: .88rem; font-weight: 600;
  transition: background-color .15s ease, border-color .15s ease;
}
body.sj-on .birth-gender label input[type="radio"]{ position: absolute; opacity: 0; width: 0; height: 0; }
body.sj-on .birth-gender label.is-on{
  background: #fbe3d8; border-color: #d9b77b; color: #8a4a2e;
}

/* §10 — CTA(가장 강한 버튼). 2026-09-10 3차 보정 §8 — soft peach → apricot pink 방향을
   명확히 하고(피치에서 시작해 애프리콧으로 짙어진다) 대비를 조금 더 올린다. 높이는 살짝
   줄여 카드를 압축하되 44px 터치 하한은 지킨다. */
body.sj-on .birth-submit{
  margin-top: 3px; min-height: 44px; border-radius: 999px;
  background: linear-gradient(135deg, #f8d7c4 0%, #f3b9aa 55%, #ec9d8a 100%);
  box-shadow: 0 6px 16px rgba(211,140,108,.4);   /* 과한 glow 금지(지시 §6/§8) — 이 값 그대로 */
  color: #3a1f16; font-size: .95rem; letter-spacing: .01em; font-weight: 800;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
body.sj-on .birth-submit:active{ filter: brightness(.96); }
/*  2026-09-10 2차 보정 §6 — OS 기본 ✨ 대신 전용 별꽃 아이콘(saju.js CTA_START_LABEL). */
body.sj-on .birth-submit .sj-cta-ico{ width: 16px; height: 16px; object-fit: contain; flex: 0 0 auto; }

/* §11 — 개인정보 안내(작게, CTA 와 광고 사이 여백 확보) — 스펙 §10 미니 자물쇠 아이콘. */
body.sj-on .sj-birth-privacy{
  display: flex; align-items: center; justify-content: center; gap: 4px;
  margin: 2px 0 0; font-size: .68rem; text-align: center; color: var(--sj-sub, #9c8268);
}
body.sj-on .sj-birth-privacy .sj-lock-ico{
  width: 12px; height: 12px; object-fit: contain; flex: 0 0 auto;
}

/* §19 — 화면이 더 짧을 때(작은 폰) 카드 안 여백을 한 번 더 줄인다(글자 크기는 그대로 둔다). */
@media (max-height: 720px){
  body.sj-on .birth-form{ padding: 9px 13px 6px; gap: 3px; margin: 2px auto; }
}

/* ── 화면이 짧을 때 / 세로가 긴 폴드 / 가로 자세 ──────────────────────── */
@media (max-height: 700px){
  body.sj-on{ --sj-stage-h: 25dvh; }
}
@media (max-aspect-ratio: 1/2){
  body.sj-on{ --sj-stage-h: 30dvh; }
}
@media (orientation: landscape) and (max-height: 520px){
  body.sj-on{ --sj-stage-h: 40dvh; --sj-col: 620px; }
}
@media (prefers-reduced-motion: no-preference){
  body.sj-on .tj-stage{ transition: height .28s ease; }
}
@media (min-aspect-ratio: 3/4){
  body.sj-on .tj-stage .tj-video,
  body.sj-on .tj-stage .tj-still,
  body.sj-on .tj-stage .tj-shot{ object-position: 46% 0%; }
}

/* ── 소리 위젯이 입력칸을 덮지 않게(도사집과 같은 실측 이유) ──────── */
@media (max-width: 600px){
  body.sj-on #composer{ padding-left: 64px; }
}
