/* slides-html 공용 기반 — html-slides-spec §1-4 가독성 실측 기준(1920×1080: 본문 ≥32px·제목 ≥64px·대비 ≥4.5:1·넘침 0)
 * 차시별 theme.css(index.html 안 <style>)가 :root 변수를 덮어쓴다. 여기 값은 "최소 보장"이다. */
:root {
  --slide-w: 1920px;
  --slide-h: 1080px;
  /* 글자 크기 하한 — 75인치 TV, 교실 뒤에서 읽힘 (html_check.py가 computed style로 실측) */
  --fs-body: 36px;      /* 본문 하한 32px보다 여유 */
  --fs-body-lg: 44px;
  --fs-title: 72px;     /* 제목 하한 64px보다 여유 */
  --fs-display: 120px;
  --fs-caption: 32px;   /* 출처·캡션도 32px 아래로 내리지 않는다 */
  --lh-body: 1.55;
  --lh-title: 1.15;
  /* 여백 — spec §1-17: 안전 여백 상하좌우 72px 전 장 동일(2026-08-23 체계 3차). --pad 는 --safe 의 별칭 */
  --safe: 72px;
  --pad: var(--safe);
  --gap: 40px;
  /* 쪽 탭(spec §1-15) — 차시 테마가 밤 장 등에서 덮어쓴다 */
  --tab-ink: var(--ink-soft);
  --tab-bg: var(--surface);
  --tab-line: var(--line);
  /* 모션 다이얼 9~10(spec §1-18) — 정답 빛 번짐 색·스포트라이트 밖 어둡기 */
  --glow: rgba(246, 196, 83, .55);
  --spot-dim: rgba(20, 16, 30, .42);
  /* 색 — 차시 테마가 덮어쓴다. 기본값은 대비 ≥4.5:1 을 만족하는 안전 세트 */
  --bg: #fffdf7;
  --ink: #1d1d1b;
  --ink-soft: #4a4a46;
  --accent: #b3321b;
  --accent-ink: #ffffff;
  --surface: #ffffff;
  --line: #d9d4c7;
  /* 글꼴 — 차시 @font-face 로 덮어쓴다. 시스템 폴백은 한글 산세리프 */
  --font-title: "Pretendard", "Noto Sans KR", "Malgun Gothic", sans-serif;
  --font-body: "Pretendard", "Noto Sans KR", "Malgun Gothic", sans-serif;
  --font-accent: var(--font-title);
  /* 모션 — animate 스킬 표의 값만 (진입 ease-out, 250~400ms). 장 연출은 3초 내 안정 */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);      /* animate 스킬 표 — strong ease-out */
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);  /* animate 스킬 표 — on-screen movement */
  --dur-fast: 200ms;
  --dur: 320ms;
  --dur-slow: 600ms;
  --dur-spot: 1200ms;   /* 캡처 스포트라이트 줌·팬 */
  --dur-glow: 600ms;    /* 정답 등장 빛 번짐 */
}

html, body { background: var(--bg); color: var(--ink); }
/* Reveal 겉틀도 같은 값으로 — 어두운 덱에서 이 두 줄이 없으면 대비가 전 장 1.1:1 로 떨어진다
   (2026-08-31 soc1-02 제작자 상신 · 지휘 승인). 밝은 덱은 값이 같아 달라지지 않는다. */
.reveal-viewport { background-color: var(--bg); color: var(--ink); }
.reveal { font-family: var(--font-body); font-size: var(--fs-body); line-height: var(--lh-body); color: var(--ink); }
.reveal .slides { text-align: left; }
.reveal .slides section { box-sizing: border-box; padding: var(--pad); height: var(--slide-h); width: var(--slide-w); overflow: hidden; }
.reveal .slides section.stack { padding: 0; }

.reveal h1, .reveal h2, .reveal h3 { font-family: var(--font-title); line-height: var(--lh-title); margin: 0 0 var(--gap); color: var(--ink); text-transform: none; letter-spacing: -0.01em; word-break: keep-all; }
.reveal h1 { font-size: var(--fs-display); }
.reveal h2 { font-size: var(--fs-title); }
.reveal h3 { font-size: var(--fs-body-lg); }
.reveal p, .reveal li { font-size: var(--fs-body); margin: 0 0 0.6em; word-break: keep-all; }
.reveal p.lg { font-size: var(--fs-body-lg); }
.reveal small, .reveal .caption, .reveal figcaption { font-size: var(--fs-caption); color: var(--ink-soft); }
.reveal ul, .reveal ol { margin: 0 0 0 1.2em; }
.reveal a { color: var(--accent); }
.reveal img, .reveal video { max-width: 100%; max-height: 100%; object-fit: contain; }
.reveal .accent { font-family: var(--font-accent); color: var(--accent); }

/* 레이아웃 골격 — section[data-layout] 는 모든 장에 필수(html_variety.py). 아래는 자주 쓰는 것만; 차시가 새 이름을 자유로 만든다.
 * ⚠ section 자체의 display 는 반드시 `!important` — Reveal 이 현재 장에 inline style display:block 을 박기 때문(2026-08-23 실측). 안쪽 요소는 불필요. */
/* 글만 있는 장은 내용 묶음 세로 중앙(spec §1-17) — 차시 레이아웃 규칙이 뒤에서 덮어쓴다(같은 특이도·뒤 순서) */
.reveal .slides section[data-kind="question"], .reveal .slides section[data-kind="knowledge"], .reveal .slides section[data-kind="title"], .reveal .slides section[data-kind="activity"] { display: grid !important; align-content: center; }
section[data-layout="capture-full"] { padding: 0; background: var(--surface); }
section[data-layout="capture-full"] img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; }
section[data-layout="capture-full"] .caption { position: absolute; left: var(--pad); bottom: 40px; background: var(--surface); padding: 8px 20px; border-radius: 12px; }
section[data-layout="question"] { display: grid !important; place-items: center; text-align: center; }
section[data-layout="question"] h2 { font-size: 96px; }
section[data-layout="knowledge"] { display: grid !important; grid-template-columns: 1fr 1fr; grid-template-rows: auto minmax(0, 1fr); gap: var(--gap); align-content: start; }
section[data-layout="knowledge"] figure { margin: 0; min-height: 0; display: grid !important; grid-template-rows: minmax(0, 1fr) auto; }
section[data-layout="knowledge"] figure img { min-height: 0; height: 100%; width: 100%; object-fit: cover; }
section[data-layout="knowledge"] > h2 { grid-column: 1 / -1; }
section[data-layout="video"] { display: grid !important; grid-template-rows: auto minmax(0, 1fr) auto; gap: 24px; }
section[data-layout="video"] video { width: 100%; height: 100%; min-height: 0; background: #000; border-radius: 16px; }
section[data-layout="video"] h2 { margin-bottom: 0; }
section[data-layout="sources"] { font-size: var(--fs-caption); }
section[data-layout="sources"] h2 { font-size: 64px; margin-bottom: 24px; }
section[data-layout="sources"] ul { columns: 2; column-gap: var(--gap); margin: 0; padding-left: 1em; }
section[data-layout="sources"] li { font-size: var(--fs-caption); line-height: 1.35; margin-bottom: 0.5em; break-inside: avoid; word-break: break-all; }
section[data-layout="title"] { display: grid !important; align-content: center; }
section[data-layout="illust-scene"] { display: grid !important; grid-template-columns: 1fr 1fr; gap: var(--gap); align-items: center; }
section[data-layout="illust-scene"] > img { width: 100%; max-height: 820px; object-fit: contain; }

/* ── 체계 3차(2026-08-23 밤, spec §1-15~18) ─────────────────────────────────── */
/* 쪽 탭 — 전 장 오른쪽 위 구석 고정, 장당 1개, 형식 "N쪽[ · 항목]"(screen_text_check.py 가 검사). 본문보다 작게(24px) — html_check 는 .page-tab 을 글자 하한 검사에서 뺀다(대비는 본다) */
.reveal .page-tab { position: absolute; top: 22px; right: 28px; z-index: 5; font-family: var(--font-body); font-size: 24px; line-height: 1; letter-spacing: 0.02em; color: var(--tab-ink); background: var(--tab-bg); border: 2px solid var(--tab-line); border-radius: 999px; padding: 9px 18px; margin: 0; word-break: keep-all; white-space: nowrap; }

/* 캡처 장 기본 틀 2종(spec §1-16) — data-layout="capture-wide|capture-tall" 또는 같은 이름의 class. 제목(교과서 소제목 원문) → 캡처(남은 높이 채움) → (클릭) 정답(캡처 바로 아래). 제목 오버레이 금지
 * wide 의 img 크기는 base.js fitCaptures() 가 figure 상자(폭 85%·남은 높이)에 **비율 유지로 꽉 차게(작은 원본은 확대)** 잡는다 — CSS 만으로는 확대가 안 된다(max-* 는 축소만). */
.reveal .slides section[data-layout="capture-wide"], .reveal .slides section.layout-capture-wide { display: grid !important; grid-template-rows: auto minmax(0, 1fr) auto; gap: 28px; padding: var(--safe); }
.reveal .slides section[data-layout="capture-wide"] > h2, .reveal .slides section.layout-capture-wide > h2 { margin: 0; font-size: var(--fs-title); }
.reveal .slides section[data-layout="capture-wide"] > figure, .reveal .slides section.layout-capture-wide > figure { margin: 0; min-height: 0; display: flex !important; align-items: center; justify-content: center; } /* flex 여야 img max-height 100% 가 확정 높이에 먹는다(실측, kr1-01 수정 1회) */
.reveal .slides section[data-layout="capture-wide"] > figure img, .reveal .slides section.layout-capture-wide > figure img { max-width: 85%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: 12px; box-shadow: 0 12px 36px rgba(0,0,0,.14); }
.reveal .slides section[data-layout="capture-wide"] > figure .spot img, .reveal .slides section.layout-capture-wide > figure .spot img, .reveal .slides section[data-layout="capture-wide"] > figure.spot img, .reveal .slides section.layout-capture-wide > figure.spot img { max-width: none; max-height: none; border-radius: 0; box-shadow: none; display: block; }
.reveal .slides section[data-layout="capture-wide"] > figure .spot, .reveal .slides section.layout-capture-wide > figure .spot, .reveal .slides section[data-layout="capture-wide"] > figure.spot, .reveal .slides section.layout-capture-wide > figure.spot { box-shadow: 0 12px 36px rgba(0,0,0,.14); } /* figure.spot 도 포함(2026-08-24 A2 — 종전엔 figure 안의 .spot 만 맞아 figure.spot 의 img 가 85% 로 눌렸다) */
/* figure 자체가 .spot 인 wide 장: base.js fitFigure() 가 img 를 맞춘 뒤 figure 를 img 와 같은 px 크기로 줄여 렌즈 %·그림자·모서리가 img 에 딱 맞게 한다(A2). 줄인 상자는 셀 가운데 */
.reveal .slides section[data-layout="capture-wide"] > figure.spot, .reveal .slides section.layout-capture-wide > figure.spot { justify-self: center; align-self: center; }
.reveal .slides section[data-layout="capture-wide"] > .answer, .reveal .slides section.layout-capture-wide > .answer { margin-top: 0; justify-self: center; width: 85%; }
.reveal .slides section[data-layout="capture-tall"], .reveal .slides section.layout-capture-tall { display: grid !important; grid-template-columns: auto minmax(0, 1fr); column-gap: 64px; padding: var(--safe); align-items: start; }
.reveal .slides section[data-layout="capture-tall"] > figure, .reveal .slides section.layout-capture-tall > figure { margin: 0; height: calc(var(--slide-h) - 2 * var(--safe)); min-height: 0; }
.reveal .slides section[data-layout="capture-tall"] > figure img, .reveal .slides section.layout-capture-tall > figure img { height: 100%; width: auto; max-width: 100%; object-fit: contain; border-radius: 12px; box-shadow: 0 12px 36px rgba(0,0,0,.14); }
.reveal .slides section[data-layout="capture-tall"] > div, .reveal .slides section.layout-capture-tall > div { display: grid !important; align-content: start; gap: 28px; min-width: 0; }
.reveal .slides section[data-layout="capture-tall"] h2, .reveal .slides section.layout-capture-tall h2 { margin: 0; font-size: var(--fs-title); }
.reveal .slides section[data-layout="capture-tall"] .answer, .reveal .slides section.layout-capture-tall .answer { margin-top: 0; }

/* 캡처 스포트라이트(spec §1-18 꺼내 쓸 수 있는 것, 2026-08-24 공용층 보수 A1·A2) — <figure class="spot" style="--sx:…%;--sy:…%;--sw:…%;--sh:…%"><img …></figure>
 * 장 진입 0.4초 뒤 지면이 발문 영역(--sx/--sy 왼쪽 위, --sw/--sh 크기, **이미지 기준 %**)을 향해 1.04배 줌·팬(1.2s)하며 영역 밖이 옅게 어두워진다.
 * 안정 상태 = 밝은 지면: 어두운 비네트는 나타난 뒤 1.5초 안에 스스로 걷힌다(2.6s 안정). 조각이 없는 장은 줌도 제자리로 돌아온다(2.8s 안정).
 * 조각이 있는 장(base.js 가 section.spot-hold)은 발문 줌·금테만 첫 클릭까지 유지하고 첫 조각에서 .spot-off 로 풀린다.
 * 좌표: base.js spotFit() 이 img 의 실제 렌더 상자를 재서 --spot-l/-t/-w/-h 를 px 로 환산한다(.spot 상자가 img 보다 클 때 % 가 빗나가던 문제, A2). 없으면 % 그대로.
 * 자동 연출은 현재 장(section.present)에서만 시작한다 — 아래 「자동 연출 진입 조건」(A3). */
.reveal .spot { position: relative; display: inline-block; line-height: 0; max-width: 100%; max-height: 100%; overflow: hidden; border-radius: 12px; transform-origin: calc(var(--spot-l, var(--sx)) + var(--spot-w, var(--sw)) / 2) calc(var(--spot-t, var(--sy)) + var(--spot-h, var(--sh)) / 2); }
.reveal .spot::after { content: ""; position: absolute; left: var(--spot-l, var(--sx)); top: var(--spot-t, var(--sy)); width: var(--spot-w, var(--sw)); height: var(--spot-h, var(--sh)); border-radius: 14px; box-shadow: 0 0 0 1500px var(--spot-dim), 0 0 0 3px rgba(246,196,83,.6); opacity: 0; pointer-events: none; }
.reveal section.present .spot { animation: spot-tour 2400ms var(--ease-in-out) 400ms both; }
.reveal section.present .spot::after { animation: spot-lens 2000ms var(--ease-out) 600ms both; }
.reveal section.present.spot-hold .spot { animation: spot-zoom var(--dur-spot) var(--ease-in-out) 400ms both; }
.reveal section.present.spot-hold .spot::after { animation: spot-lens-hold 2000ms var(--ease-out) 600ms both; }
.reveal section.present .spot.spot-off, .reveal section.present.spot-off .spot { animation: spot-zoom-off var(--dur) var(--ease-out) both; }
.reveal section.present .spot.spot-off::after, .reveal section.present.spot-off .spot::after { animation: spot-lens-off var(--dur) var(--ease-out) both; }
/* 조각 없는 장: 줌 들어갔다(0.4~1.6s) 머물고(~2.2s) 제자리로(2.8s) */
@keyframes spot-tour { 0% { transform: scale(1); } 50% { transform: scale(1.04); } 75% { transform: scale(1.04); } 100% { transform: scale(1); } }
/* 비네트: 나타나(0.6~1.1s) 머물고(~1.5s) 걷힌다(2.6s) */
@keyframes spot-lens { 0% { opacity: 0; } 25% { opacity: 1; } 45% { opacity: 1; } 100% { opacity: 0; } }
/* 조각 있는 장: 줌은 유지, 어두운 비네트만 걷히고 금테는 남는다(첫 클릭까지) */
@keyframes spot-lens-hold { 0% { opacity: 0; } 25% { opacity: 1; } 45% { opacity: 1; box-shadow: 0 0 0 1500px var(--spot-dim), 0 0 0 3px rgba(246,196,83,.6); } 100% { opacity: 1; box-shadow: 0 0 0 1500px rgba(0,0,0,0), 0 0 0 3px rgba(246,196,83,.6); } }
@keyframes spot-zoom { from { transform: scale(1); } to { transform: scale(1.04); } }
@keyframes spot-zoom-off { from { transform: scale(1.04); } to { transform: scale(1); } }
@keyframes spot-lens-off { from { opacity: 1; } to { opacity: 0; } }

/* 자동 연출 진입 조건(spec §1-18, 2026-08-24 A3) — Reveal 은 모든 장을 미리 그리므로 keyframe 이 진입 전에 끝나 버린다(02편 먹선·두루마리 실측).
 * 현재 장(section.present)이 아닌 장의 자동 animation 은 전부 멈춰 두고(none), 들어오는 순간 처음부터 돈다. 떠나면 다시 none → 되돌아와도 재생.
 * 조각(.fragment 과 그 안)은 제외 — 조각 상태는 Reveal 이 장마다 기억하므로 되돌아올 때 다시 찍히면 안 된다. 차시 CSS 의 자동 keyframe 은 따로 손대지 않아도 된다. */
.reveal .slides section:not(.present) :not(.fragment):not(.fragment *), .reveal .slides section:not(.present) :not(.fragment)::before, .reveal .slides section:not(.present) :not(.fragment)::after { animation: none !important; }

/* 정답 등장 빛 번짐(spec §1-18 꺼내 쓸 수 있는 것) — .answer 가 fragment 로 켜질 때 별빛 glow 가 0.6초 번지고 꺼진다(opacity 만 움직임) */
.reveal .answer { position: relative; }
.reveal .answer::before { content: ""; position: absolute; inset: -4px; border-radius: inherit; box-shadow: 0 0 48px 16px var(--glow); opacity: 0; pointer-events: none; }
.reveal .fragment.answer.visible::before { animation: answer-glow var(--dur-glow) var(--ease-out) both; }
@keyframes answer-glow { 0% { opacity: 0; } 35% { opacity: 1; } 100% { opacity: 0; } }
/* 장면 맞춤 모션(spec §1-18, 2026-09-30) — <body data-motion="scene"> 덱은 빛 번짐을 .glow 를 단 정답에만 건다. 속성 없는 옛 덱은 그대로 */
body[data-motion="scene"] .reveal .fragment.answer.visible:not(.glow)::before { animation: none; }

/* 장 전환(spec §1-18 꺼내 쓸 수 있는 것) — <section data-transition="zoom|concave|fade|slide"> Reveal 원래 기능. 밤↔종이 경계는 zoom 권장. base.js 기본 fade */
/* 배경 시차(§1-18) — 밤 장의 별밭 .parallax 가 장 넘길 때 전환보다 느리게(1.4s) 제자리로 미끄러진다. base.js 가 html[data-dir=back|fwd] 로 방향을 준다 */
.reveal .parallax { will-change: transform; animation: par-fwd 1400ms var(--ease-out) both; }
html[data-dir="back"] .reveal .parallax { animation-name: par-back; }
@keyframes par-fwd { from { transform: translateX(48px); } to { transform: none; } }
@keyframes par-back { from { transform: translateX(-48px); } to { transform: none; } }

/* 영상 시네마(§1-18) — 재생 중(base.js 가 section 에 .playing) 주변 글이 옅어지고 영상이 살짝 커진다 */
.reveal section[data-kind="video"] > :not(video) { transition: opacity var(--dur-slow) var(--ease-out); }
.reveal section[data-kind="video"].playing > :not(video):not(.page-tab) { opacity: .35; }
.reveal section[data-kind="video"] video { transition: transform var(--dur-slow) var(--ease-in-out); }
.reveal section[data-kind="video"].playing video { transform: scale(1.03); }

/* 아이콘 — assets/icons/*.svg 를 <img> 또는 인라인 svg. 색은 currentColor */
.reveal .icon { width: 1.4em; height: 1.4em; vertical-align: -0.3em; fill: currentColor; }
.reveal .icon-lg { width: 120px; height: 120px; }

/* 정답·예시 답 칸 — spec §1-9 ②·§1-10: 발문 장 안에서 클릭 1회로 등장. data-kind="answer" data-source="지도서 NN쪽|claims:C12" 필수(screen_text_check.py) */
.reveal .answer { margin-top: var(--gap); padding: 28px 40px; border-left: 12px solid var(--accent); background: var(--surface); color: var(--ink); font-size: var(--fs-body-lg); line-height: 1.4; border-radius: 0 20px 20px 0; word-break: keep-all; }
.reveal .answer .tag { display: inline-block; font-family: var(--font-title); font-size: var(--fs-caption); color: var(--accent-ink); background: var(--accent); padding: 4px 18px; border-radius: 999px; margin-right: 20px; vertical-align: middle; }

/* 정답 글자 크기(spec §1-10 📏, 2026-08-30 신설) — 반 뒷자리까지 읽어야 하는 글자라 본문 하한(32px)보다 한 단계 위에 둔다.
   장에 든 정답 칸 수로 정한다: 1칸 46px · 2~3칸 42px · 4칸 이상 40px. data-answers 는 제작 때 장마다 붙인다(없으면 --fs-body-lg).
   덱 안에서 이 값을 다시 정하지 않는다 — 넘치는 장만 그 장에 직접 내려 적는다. */
.reveal .slides section[data-answers="1"] .answer { font-size: 46px; }
.reveal .slides section[data-answers="2"] .answer,
.reveal .slides section[data-answers="3"] .answer { font-size: 42px; }
.reveal .slides section[data-answers="4"] .answer,
.reveal .slides section[data-answers="5"] .answer,
.reveal .slides section[data-answers="6"] .answer { font-size: 40px; }

/* ── 걸음(spec §1-21, 2026-08-31 공용층 이관) ───────────────────────────────────────────
 * 강의안의 마디를 화면에 되살려 「지금 무슨 이야기를 하고 어디로 가는지」를 교사가 화면만 보고 알게 하는 장치.
 * 표본은 slides-html/kr1-02 (35장·6걸음 — design-log.md ## 11·## 12).
 * 여기 두는 것은 **자리·크기·움직임 같은 뼈대**뿐이다. 색·글꼴은 전부 변수(--ink·--ink-soft·--line·--font-title…)라
 * 덱이 :root 에서 정한 값을 그대로 따른다 → **덱은 이 규칙을 다시 적지 않는다.** 덧입힐 것이 있으면 색만 덮어쓴다.
 *
 * ⚠ 선택자는 `.step-tag` 와 `step-gate`·`half-rest` **장 안쪽으로만** 좁혀 두었다.
 *   `.gate`·`.marks`·`.seam` 은 흔한 이름이라(kr1-04 는 `.marks` 를 「금 긋기」 장치에 쓴다) 밖으로 새면 남의 덱이 망가진다.
 *   걸음을 쓰지 않는 덱에는 이 절이 한 줄도 걸리지 않는다.
 *
 * 마크업 뼈대는 `_template/index.html` 에 있다(간지 한 장 + 걸음 표시 한 줄).
 * 검사: `html_variety` — `.step-tag` 가 하나라도 있으면 내용 장 전부에 있어야 하고, `step-gate` 장에는 쪽 탭이 있어야 한다. */

/* ① 걸음 표시 — 내용 장 왼쪽 위. 쪽 탭(오른쪽 위)의 **거울 자리**다(왼쪽 22px 은 세로 띠 장치들이 쓰므로 44px 부터).
   알약(바탕·테두리)을 걷고 글자만 두어 쪽 탭보다 조용하게 — 주인공은 교과서다.
   32px 인 이유: html_check 의 본문 하한 32px 예외는 `.page-tab` 하나뿐이라 쪽 탭의 24px 로는 내릴 수 없다.
   한 줄로 붙여 둔다(ui-ux-pro-max ux 「Compact Label Overflow」 — 압축 이름표는 두 줄로 넘기지 않는다).
   22~54px 띠에만 앉으므로 안전 여백 72px 안쪽 내용과 겹치지 않는다(같은 스킬 「Sticky Navigation」). */
.reveal .step-tag { position: absolute; top: 22px; left: 44px; z-index: 5; margin: 0;
  font-family: var(--font-body); font-size: 32px; line-height: 1; letter-spacing: .01em;
  color: var(--ink-soft); white-space: nowrap; word-break: keep-all; }
.reveal .step-tag .no { font-family: var(--font-title); font-weight: 700; margin-right: .34em; }

/* ② 걸음 간지(step-gate)·시간 경계 장(half-rest) — 한 묶음(.gate)을 화면 한가운데 놓는다.
      간지에는 걸음 번호 + 이름(제목 <h2> + 부제 <p class="sub"> 두 줄, §1-21 2026-09-06 저녁 개정) + 진행 점 + 쪽 탭뿐
      (물음·설명·절차 금지, spec §1-21 ⓐ). */
.reveal .slides section[data-layout="step-gate"],
.reveal .slides section[data-layout="half-rest"] { display: grid !important; align-content: center; justify-items: center; }
.reveal .slides section[data-layout="step-gate"] .gate,
.reveal .slides section[data-layout="half-rest"] .gate { display: grid; justify-items: center; gap: 26px; text-align: center; }
.reveal .slides section[data-layout="step-gate"] h2,
.reveal .slides section[data-layout="half-rest"] h2 { margin: 0; font-size: 120px; line-height: 1.16; color: var(--ink); }
.reveal .slides section[data-layout="step-gate"] .gate-no,
.reveal .slides section[data-layout="half-rest"] .gate-no { margin: 0; font-family: var(--font-title); font-size: 96px; line-height: 1; color: var(--ink-soft); }

/* ②-2 걸음 이름 = 제목 + 부제 두 줄(spec §1-21, 2026-09-06 저녁 개정) —
      <h2> 제목(명사구, 크게) 아래 <p class="sub"> 부제(「하는 일 ~기」, 작게·흐리게).
      크기 56px = 제목 120px 의 0.47(정본이 준 0.45~0.55 안, 본문 하한 32px 위).
      ⚠ 선택자를 `step-gate` 장 안으로만 좁혀 둔다 — `.sub` 는 표지·시간 경계 장에서 덱마다 이미 쓰는 흔한 이름이다.
      부제가 없는 옛 편은 이 규칙이 한 줄도 걸리지 않아 종전대로 제목 한 줄로 그려진다. */
.reveal .slides section[data-layout="step-gate"] .sub {
  margin: 0; font-family: var(--font-body); font-size: 56px; line-height: 1.3;
  color: var(--ink-soft); word-break: keep-all; }

/* ③ 진행 점 — 지나온 걸음은 옅게(.done), 지금 걸음만 먹으로 한 칸 크게(.on).
      글자 없는 장식이라 마크업에 aria-hidden 을 붙인다(ui-ux-pro-max ux 「Progress Indicators」·「Active State」). */
.reveal .slides section[data-layout="step-gate"] .marks,
.reveal .slides section[data-layout="half-rest"] .marks { display: flex; gap: 22px; justify-content: center; align-items: center; height: 40px; }
.reveal .slides section[data-layout="step-gate"] .marks i,
.reveal .slides section[data-layout="half-rest"] .marks i { width: 26px; height: 26px; border-radius: 7px; border: 3px solid var(--line); box-sizing: border-box; }
.reveal .slides section[data-layout="step-gate"] .marks i.done,
.reveal .slides section[data-layout="half-rest"] .marks i.done { background: var(--line); }
.reveal .slides section[data-layout="step-gate"] .marks i.on,
.reveal .slides section[data-layout="half-rest"] .marks i.on { background: var(--ink); border-color: var(--ink); transform: scale(1.34); }

/* ④ 이음매 선 — 시간 경계 장에서 선 하나가 그어지고 멈춘다. <svg class="seam" viewBox="0 0 1160 40"><path pathLength="1" …> */
.reveal .slides section[data-layout="half-rest"] .seam { width: 1160px; height: 40px; overflow: visible; }
.reveal .slides section[data-layout="half-rest"] .seam path { fill: none; stroke: var(--ink); stroke-width: 7; stroke-linecap: round;
  stroke-dasharray: 1 2; stroke-dashoffset: 1; animation: step-draw 900ms var(--ease-in-out) 200ms forwards; }

/* ⑤ 등장 차례 — 간지는 번호 → 이름 → 진행 점(1.14초), 시간 경계 장은 선이 그어진 뒤 글자(1.4초). 전부 3초 안에 멎는다(spec §1-3).
      keyframe 이름에 step- 을 붙인 이유: 덱마다 제 나름의 `rise`·`draw` 를 따로 두고 있어 이름이 부딪히면 안 된다. */
.reveal .slides section[data-layout="step-gate"] .gate-no { animation: step-rise 560ms var(--ease-out) 200ms both; }
.reveal .slides section[data-layout="step-gate"] h2 { animation: step-rise 640ms var(--ease-out) 360ms both; }
.reveal .slides section[data-layout="step-gate"] .sub { animation: step-rise 600ms var(--ease-out) 500ms both; }
.reveal .slides section[data-layout="step-gate"] .marks,
.reveal .slides section[data-layout="half-rest"] .marks { animation: step-rise 520ms var(--ease-out) 620ms both; }
.reveal .slides section[data-layout="half-rest"] h2 { animation: step-rise 640ms var(--ease-out) 760ms both; }
@keyframes step-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes step-draw { to { stroke-dashoffset: 0; } }

/* fragment — Reveal 기본은 opacity만. 진입은 ease-out, 12px 위로 */
/* ⚠ transform 을 쓰지 않는다 — 요소가 자기 자리를 transform 으로 잡고 있으면(예: 지도 핀의
   translate(-50%,-50%)) 조각이 켜지는 순간 그 자리잡기가 통째로 지워진다(2026-08-31 soc1-02 지도 점 7개 실측).
   독립 속성 translate 는 요소의 transform 과 따로 곱해지므로 안전하다. */
.reveal .fragment.rise { opacity: 0; translate: 0 12px; transition: opacity var(--dur) var(--ease-out), translate var(--dur) var(--ease-out); }
.reveal .fragment.rise.visible { opacity: 1; translate: none; }

/* 장 배경 모션(자동 허용) — 3초 안에 끝나거나 멈춰 보여야 한다(spec §1-3). 점멸 금지. */
@keyframes bg-drift { from { background-position: 0 0; } to { background-position: 60px 40px; } }

/* 발표자 노트는 화면에 그리지 않는다 */
.reveal aside.notes { display: none; }

/* 장 번호(spec §1-24, 2026-09-03) — <body data-slide-num> 인 덱만 base.js 가 .slide-num 텍스트를 채운다 */
.slide-num { position: fixed; right: 18px; bottom: 12px; font-size: 14px; opacity: .55; font-family: inherit; pointer-events: none; z-index: 50; }

/* 인쇄(?print-pdf) */
@media print { .reveal .slides section { page-break-after: always; } .slide-num { display: none; } }

/* 움직임 줄이기 — 모든 자동 모션·전환 정지, fragment 는 즉시 표시 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition-duration: 1ms !important; }
  .reveal .fragment.rise { transform: none; }
  .reveal .spot { transform: none; }
  .reveal .spot::after { opacity: 0; }
  .reveal .answer::before { opacity: 0; }
  .reveal .parallax { transform: none; }
  .reveal section[data-kind="video"].playing video { transform: none; }
  /* 걸음(spec §1-21) — 움직임을 끄면 마지막 상태로 바로 간다.
     이음매 선은 stroke-dashoffset 을 되돌려 주지 않으면 선이 아예 안 보인다(움직임이 그리는 선이라서). */
  .reveal .slides section[data-layout="step-gate"] .gate-no,
  .reveal .slides section[data-layout="step-gate"] h2,
  .reveal .slides section[data-layout="step-gate"] .sub,
  .reveal .slides section[data-layout="step-gate"] .marks,
  .reveal .slides section[data-layout="half-rest"] .marks,
  .reveal .slides section[data-layout="half-rest"] h2 { opacity: 1; transform: none; }
  .reveal .slides section[data-layout="half-rest"] .seam path { stroke-dasharray: none; stroke-dashoffset: 0; }
}
