# signal — 슬라이드 만들기 지시서 (채팅 AI용)

> 이 파일은 **ChatGPT·Claude·Gemini 같은 채팅 AI**에게 통째로 주면, 이 디자인(`signal`)으로 수업 슬라이드를 만들어 주도록 쓴 지시서입니다.
> 파일을 읽고 쓸 수 있는 에이전트 AI(Claude Code 등)를 쓴다면 갤러리의 **받기 .zip**을 쓰세요.

## 사용법 (사람이 읽는 안내)

1. 채팅 AI 대화창에 **이 파일을 첨부**합니다. 첨부가 안 되면 파일 내용을 **전부 복사해 붙여 넣습니다**(끝까지 빠짐없이).
2. 이어서 만들고 싶은 수업을 말합니다(**"결과는 .html 파일로 만들어 줘"**도 같이 말하면 좋습니다). 예) "6학년 2학기 과학 1단원 3~4차시, 학습 목표는 ○○○, 00초등학교, 슬라이드로 만들어 줘(장 수와 구성은 내용에 맞게 정해 줘)."
3. AI가 먼저 **장별 구성안**(장마다 제목·내용·쓸 부품)을 보여 줍니다. 마음에 들면 "좋아, 만들어 줘", 고칠 곳이 있으면 "3장은 빼고 퀴즈를 하나 더 넣어 줘"처럼 말합니다. 구성 확인 없이 바로 받고 싶으면 2번에서 "구성 확인 없이 바로 만들어 줘"라고 하세요.
4. AI가 **슬라이드.html 파일**을 만들어 줍니다. 내려받아 더블클릭하면 브라우저에서 열립니다. 방향키(→ ←)와 스페이스로 넘깁니다. 만약 파일 대신 **코드만 글로 보여 주면** "코드 말고 .html 파일로 만들어서 내려받게 해 줘"라고 다시 요청하세요. 그래도 안 되면 코드를 모두 복사해 메모장에 붙여 넣고 `슬라이드.html`로 저장합니다(파일 형식은 '모든 파일', 인코딩은 UTF-8).
5. 고치고 싶으면 AI에게 "2장 제목을 ○○로 바꿔 줘"처럼 말하면 됩니다. 중간에 코드가 끊기면 "끊긴 곳부터 이어서 출력해 줘"라고 하세요.

서비스별 팁 (메뉴 이름은 서비스마다 바뀔 수 있습니다)
- 공통: 고를 수 있다면 **생각하는(추론) 모드**나 상위 모델을 쓰세요. 긴 코드를 끝까지 정확하게 쓰는 데 차이가 큽니다.
- ChatGPT: "캔버스로 만들어 줘" 또는 "다운로드할 수 있는 .html 파일로 만들어 줘"라고 요청합니다.
- Gemini: 입력창의 **Canvas**를 켜고 요청하면 화면에서 바로 보고 내려받을 수 있습니다.
- Claude: 결과가 **아티팩트**(오른쪽 창)로 열리면 거기서 내려받습니다.
- AI가 그림 파일(이미지)을 따로 만들어 주더라도 슬라이드에는 들어가지 않습니다. 슬라이드는 .html 파일입니다.
- **AI 화면 안의 미리보기에서는 색·모양·버튼이 안 나올 수 있습니다.** 이 디자인의 공통 모양과 동작은 슬라이드를 열 때 인터넷(`https://k-slide.web.app`)에서 불러오는데, 일부 서비스의 미리보기 창은 바깥 파일을 막기 때문입니다. **내려받아 브라우저(크롬·엣지 등)로 열면 정상**으로 보입니다.

알아 둘 점
- 이 디자인의 한글 글씨체는 제목 NanumMyeongjo Bold(700) · 본문 프리텐다드 Pretendard-Regular(400)입니다. 글씨체와 공통 모양·동작은 **인터넷에서 불러오므로 슬라이드를 열 때 인터넷이 필요**합니다(영문 글꼴도 마찬가지). 인터넷 없이 발표하려면 갤러리의 **받기 .zip**(모든 것이 파일 안에 들어 있음)을 쓰세요.
- AI가 긴 코드를 일부 생략하거나 어긋나게 쓸 수 있습니다. 열어서 한 번 확인하세요. 안 열리거나 깨지면 "코드가 생략되었어. 완성된 HTML 하나로 처음부터 끝까지 다시 출력해 줘"라고 요청합니다.
- 사진·학생 이름 같은 개인정보는 AI에게 넣지 마세요.

## 라이선스

폰트 라이선스 안내
==================

- NanumMyeongjo Bold: NanumMyeongjo — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright © 2010 NHN Corporation. All rights reserved. Font designed by FONTRIX.
  파일: NanumMyeongjoBold.ttf
- 프리텐다드 Pretendard-Regular: 프리텐다드 — 프리텐다드 (Pretendard) — 길형진 (orioncactus) / 눈누: https://noonnu.cc/font_page/694
  파일: Pretendard-Regular.ttf

SIL Open Font License 1.1 요약
- 폰트를 자유롭게 사용·복제·수정·재배포할 수 있습니다(폰트 파일 단독 판매는 불가).
- 수정본(글자를 줄인 서브셋 포함)은 원래 폰트의 '예약 이름'을 쓰지 못할 수 있습니다.
- 재배포할 때는 저작권 표시와 라이선스 문구를 함께 넣어야 합니다.
- 전문: https://openfontlicense.org

학교안심 글꼴과 easy3D 폴더의 글꼴은 사용자가 OFL로 확인한 내용을 따랐습니다. 배포 전에 각 배포처에서 최신 라이선스를 다시 확인하세요.

design.md 라이선스 (MIT)
=======================
design.md는 frontend-slides(https://github.com/zarazhangrui/frontend-slides)의 템플릿을 바탕으로 한 것이며, 아래 MIT 라이선스를 따릅니다.

MIT License

Copyright (c) 2025 Zara Zhang

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

# ▼▼▼ 여기부터 AI에게 주는 지시서 ▼▼▼

(이 줄 위의 '사용법'과 '라이선스'는 사람을 위한 안내입니다. AI는 아래 지시서를 따르세요.)

## 0. 당신(AI)의 일

당신은 슬라이드 제작 도우미입니다. 사용자가 알려 주는 수업 내용으로, 아래 **디자인 규칙(1)**, **부품 사전(3)**, **HTML 뼈대(4)**를 지켜 **브라우저에서 바로 열리는 슬라이드 HTML 파일 하나**를 만듭니다.
이 디자인의 공통 CSS(글씨체·색·부품 모양)와 동작 엔진은 사이트에 올려 둔 파일이라, 뼈대의 `<link>`·`<script src>` 두 줄이 불러옵니다. **당신이 쓰는 것은 슬라이드 HTML(`<section class="slide">`들과 내비)과, 꼭 필요할 때만 '추가 부품' CSS뿐입니다.** 공통 CSS의 내용은 참고용으로 5에 있습니다.

### 진행 순서
1. 사용자가 아직 수업 내용을 말하지 않았다면, 먼저 아래를 짧게 물어보세요: 학교급·학년·과목, 단원과 차시, 학습 목표, 학교 이름(선택), 원하는 장 수(말하지 않으면 내용 분량에 맞게 정함).
2. **장별 구성안을 먼저 보여 주고 확인을 받습니다**(아래 '구성은 내용이 정합니다'). 이때는 코드를 쓰지 마세요.
3. 확인을 받으면 HTML을 만들고, 내보내기 전에 아래 '내보내기 전 점검'을 하나씩 확인합니다.
- 내용은 사용자가 준 것만 쓰고, **숫자·사실·출처를 지어내지 마세요.** 모르면 묻거나 "(예시)"라고 표시하세요.
- **사용자가 주지 않은 사실(연도·기록·수치·등재·'세계 최고'·'가장 ○○하다' 같은 말)을 덧붙이고 싶으면, 구성안에 '추가 사실'로 따로 적어 확인을 받으세요.** 확인받지 않은 사실은 슬라이드에 넣지 않습니다. 널리 알려진 이야기라도 정확한 대상을 쓰세요(예: 유네스코 세계기록유산에 오른 것은 '한글'이 아니라 《훈민정음》 해례본이라는 책).

### 반드시 지킬 것
1. **디자인 규칙(1)을 어기지 마세요.** 색·글꼴·배치·장식·움직임 규칙과 '하지 말 것'을 그대로 따릅니다. 규칙에 없는 효과(임의의 애니메이션, 새 색, 새 장식)를 더하지 마세요.
2. **뼈대(4)의 공통 파일 두 줄을 그대로 두세요.** `<link rel="stylesheet" href="https://k-slide.web.app/kit/v1/signal.css">`(head 안)와 `<script src="https://k-slide.web.app/kit/v1/signal.js"></script>`(body 맨 끝)는 주소 한 글자도 바꾸거나 지우지 마세요. **공통 CSS(5)나 엔진을 HTML 안에 옮겨 쓰거나, 줄이거나, 비슷하게 새로 짜지 마세요**(이미 불러오므로 같은 규칙을 또 쓰면 서로 부딪혀 깨집니다). `<style>`에는 '추가 부품' 줄과 그 아래에 직접 정의한 클래스만 둡니다. 엔진이 쓰는 속성 이름(`data-steps`, `data-s`, `data-quiz`, `data-opt`, `data-act`, `data-blank` 등)은 5의 엔진 사용법대로 씁니다.
3. **클래스는 부품 사전(3)과 공통 CSS(5)에 있는 것만 쓰세요.** 없는 클래스 이름을 지어 쓰면 아무 모양도 적용되지 않아 배치가 무너집니다(창이 좁아지고 빈 공간이 생김). 새 부품이 꼭 필요하면 `<style>`의 '추가 부품' 주석 줄 **아래에** 그 클래스를 직접 정의하세요(디자인 규칙의 색·선·글꼴만 사용). 모양을 `style="…"`로 하나하나 지정하는 것보다 부품 클래스를 쓰는 쪽이 낫습니다.
   - **새 배치를 만들기 전에, 예시 장의 배치 클래스로 할 수 있는지 먼저 보세요.** 직접 만든 배치는 화면을 볼 수 없는 상태에서 쓰기 때문에 깨질 위험이 큽니다. 예시 배치로 안 될 때만 새로 정의합니다.
4. **슬라이드의 장 수·순서·내용은 사용자 수업에 맞게 새로 구성하세요.** 뼈대의 슬라이드는 '계절의 변화' 예시이므로 그 문구는 하나도 남기지 마세요. 장을 늘리거나 줄이거나 순서를 바꾸면 **내비 점 개수와 쪽 표시(예: 01 / 06)를 실제 장 수에 맞추세요.** 뼈대의 6번째 장은 이 디자인의 대표 장치를 눌러 보여 주는 안내 장이므로, 그 부품·움직임(예: data-demo 시연 버튼과 .play 상태)만 참고하고 디자인 안내 문구는 남기지 마세요. 아래 '구성은 내용이 정합니다'를 따르세요.
5. **글씨체는 바꾸지 마세요.** 한글 글씨체(제목 NanumMyeongjo Bold(700) · 본문 프리텐다드 Pretendard-Regular(400))는 공통 CSS가 불러옵니다. `@font-face`를 새로 쓰지 말고, 글꼴은 `var(--kt)`(제목)·`var(--kb)`(본문)·`var(--ka)`(포인트) 변수로만 지정하세요.
6. **글자 크기와 화면 채우기** (슬라이드는 1920×1080 기준으로 그려져 화면 크기에 맞게 통째로 줄어듭니다)
   - 읽어야 하는 글(본문·설명·표 내용·보기)은 **28px 이상**, 보조 글(캡션·주석)은 **22px 이상**으로 씁니다. 창 제목줄·쪽 번호·작은 라벨 같은 장식 글자는 디자인 규칙의 크기를 따릅니다.
   - 창·판·카드가 **화면의 대부분을 채우게** 하세요. 한쪽에 작게 몰리거나 큰 빈 공간이 남으면 안 됩니다. 내용이 적은 장은 글자와 그림을 키우거나 다른 장과 합칩니다.
   - **높이 예산**: 장 제목과 아래 내비를 빼면 본문에 쓸 수 있는 높이는 대략 **650~750px**입니다. 모든 내용이 1920×1080 안에 들어가야 하고, 넘친 부분은 잘려서 보이지 않습니다. 쓰기 전에 줄 수 × 줄 높이(글자 크기의 약 1.5배)로 높이를 어림해 보세요.
   - **카드 규칙**: 한 장에 카드(칸)를 4개 이상 놓으면 카드마다 글은 **3줄 이하**로 줄입니다. 글이 들어가는 칸은 **너비 400px 이상**으로 두고(그림+글을 나란히 놓을 때는 글 칸 기준), 한 줄에 몇 글자밖에 안 들어가게 좁히지 마세요. 카드를 두 줄로 쌓아야 하면 그 줄들의 높이 합이 높이 예산 안에 드는지 확인합니다.
   - 제목은 **두 줄 이내**로 씁니다. 표지 제목은 한 줄에 15자 안팎으로 끊어 줄을 바꾸세요. 글이 창 밖으로 넘치거나 잘리면 글자를 줄이지 말고 문장을 짧게 고칩니다.
   - 한글은 단어 중간에서 줄이 바뀌지 않게(`word-break:keep-all`) 합니다(공통 CSS에 이미 들어 있음).
7. 저작권이 있는 글·그림·사진을 가져오지 마세요. **사용자가 요청하지 않으면 그림 파일(이미지 생성)을 따로 만들지 마세요. 슬라이드에 필요한 그림은 HTML 안에서 SVG·CSS로 그립니다.**

### 구성은 내용이 정합니다
- 예시 덱(deck.html)은 이 디자인의 **부품 견본**입니다. 따라야 할 장 구성이 아닙니다. 예시의 장 순서·장 수·제목 짜임·문장 구조를 그대로 따라 하지 마세요.
- 사용자가 준 내용을 먼저 살펴 **필요한 장 수와 장별 역할을 직접 정하세요.** 내용이 적으면 3~4장, 많으면 8장 이상도 괜찮습니다.
- **코드를 쓰기 전에 장별 구성안(장마다 제목 · 전할 내용 한 줄 · 쓸 부품)을 먼저 보여 주고 확인을 받으세요.** 사용자가 고치라고 하면 고친 구성안을 다시 보여 주고, "좋아", "만들어 줘"라고 하면 그때 만듭니다. 사용자가 처음부터 "구성 확인 없이 바로 만들어 줘"라고 했으면 이 단계는 건너뜁니다.
- 아래 부품 중 **필요한 것만 골라 쓰세요.** 안 쓰는 부품이 있어도 되고(예: 퀴즈 없는 덱), 같은 부품을 여러 장에 쓰거나 한 장에 섞어 써도 됩니다.
  · 표지 · 단계 버튼이 있는 흐름(data-steps) · 큰 숫자와 통계 · 그래프 · 비교와 표 · 목록과 인용 · 퀴즈와 다시 풀기 · 빈칸 채우기 · 시연 버튼(data-demo)
- 장마다 전하는 메시지는 하나로 하고, 같은 모양의 장이 연달아 나오지 않게 하세요.
- 지켜야 하는 것은 디자인 규칙(design.md)과 동작 엔진입니다. 자유로운 것은 장의 수·순서·구성입니다.

### 출력 방식
- **결과물은 '.html 파일'로 주세요.** 파일 이름은 슬라이드.html, 형식은 UTF-8 HTML 문서 하나입니다. 파일을 만들거나 내려받게 해 주는 기능(아티팩트·캔버스·코드 실행 환경·파일 첨부 등)이 있으면 **반드시 그 기능으로 .html 파일을 만들어 내려받거나 열 수 있게** 하세요. 코드만 글로 보여 주고 끝내지 마세요.
- 파일을 만들 수 있는 기능이 **전혀 없을 때만**, 설명은 한두 줄로 줄이고 **완성된 HTML 전체를 ```html 코드 블록 하나**로 출력하세요(이때 사용자가 직접 .html로 저장합니다).
- **`...`, "(이하 동일)", "(생략)" 같은 생략 표시를 쓰지 마세요.** `<!DOCTYPE html>`부터 `</html>`까지 전부 씁니다.
- 너무 길어 끊길 것 같으면 먼저 쓰지 말고, 사용자에게 "장 수를 줄일까요?"라고 묻거나, 끊기면 사용자가 "이어서"라고 할 때 **끊긴 글자 바로 다음부터** 이어 쓰세요.
- **미리보기 창에서 색·모양·버튼이 안 보여도 고치지 마세요.** 공통 CSS·엔진은 인터넷 주소(`https://k-slide.web.app`)에서 불러오는데, 일부 미리보기 창은 바깥 파일을 막습니다. 내려받아 브라우저로 열면 정상입니다. 이때 공통 CSS나 엔진을 HTML 안에 직접 써 넣으면 안 됩니다. 사용자에게 "내려받아 브라우저로 열어 보세요"라고 안내하세요.
- 파일을 코드(파이썬 등)로 써서 만든다면, HTML 전체를 **원문 그대로의 문자열**로 쓰세요(예: 파이썬은 따옴표 세 개짜리 raw 문자열). 백슬래시(`\`)가 다른 문자로 바뀌어 깨지는 일을 막기 위해서입니다. 새로 쓰는 CSS·JS에서도 `\00a0` 같은 이스케이프 대신 실제 문자를 쓰세요.
- 파일로 줬다면 "슬라이드.html을 내려받아 더블클릭하세요(열 때 인터넷 필요)"라고, 코드 블록으로 줬다면 "코드를 모두 복사해 메모장에 붙여 넣고 슬라이드.html로 저장한 뒤 더블클릭하세요(열 때 인터넷 필요)"라고 한 줄로 안내하세요.

### 내보내기 전 점검 (하나라도 아니면 고친 뒤 내보내기)
1. HTML에 쓴 클래스가 모두 부품 사전(3)·공통 CSS(5)·'추가 부품' 칸에 정의되어 있는가?
2. 공통 파일 두 줄(`<link>`·`<script src>`)이 주소 그대로 있고, 공통 CSS·엔진을 HTML 안에 옮겨 쓰지 않았는가? `@font-face`를 새로 쓰지 않았는가?
3. 장 수 = 내비 점 개수 = 쪽 표시 숫자인가?
4. 모든 장의 내용이 1920×1080 안에 들어가는가(높이 예산, 카드 규칙)? 제목·글이 창 밖으로 넘치거나 잘리지 않는가(특히 표지 제목과 마지막 장)? 읽는 글이 28px 이상이고, 화면에 큰 빈 공간이 없는가?
5. '계절의 변화' 예시 문구나 디자인 안내 문구가 남아 있지 않은가?
6. 사용자가 주지 않았고 확인도 받지 않은 사실을 넣지 않았는가?
7. `...`·"(생략)" 같은 생략이 없고, `<!DOCTYPE html>`부터 `</html>`까지 다 있는가?
8. 사용자가 요청하지 않은 그림 파일을 따로 만들지 않았는가?

---

## 1. 디자인 규칙 (`signal` design.md)

````markdown
---
version: alpha
name: Signal
description: A literary editorial presentation system in the spirit of a long-form magazine — The Economist's restraint crossed with a private intelligence briefing. Source Serif 4 carries every headline with roman/italic mixing mid-sentence in antique gold, DM Sans steps back for body, and IBM Plex Mono runs all the timestamps, kickers, and chrome. The dual surface system is warm cream paper (#F0ECE3) and deep editorial navy (#1C2644), connected by a single hot accent — antique gold (#C8A870) — used only on rules, italic emphasis, and numerical figures. A near-invisible 80px grid texture overlays every dark slide as a fingerprint. The effect is sober, considered, and a little bit aristocratic.

colors:
  navy: "#1C2644"
  navy-alt: "#232F55"
  cream: "#F0ECE3"
  cream-alt: "#E6E0D4"
  text-warm: "#E2DCD0"
  text-muted-dark: "#8A96A8"
  text-hint-dark: "#4E5A6E"
  ink: "#1A2030"
  text-muted-light: "#5A6270"
  text-hint-light: "#9AA0A8"
  gold: "#C8A870"
  border-dark: "#2E3D5C"
  border-light: "#CAC4B4"

color-aliases:
  c-bg: navy
  c-bg-alt: navy-alt
  c-bg-light: cream
  c-bg-light-alt: cream-alt
  c-fg: text-warm
  c-fg-2: text-muted-dark
  c-fg-3: text-hint-dark
  c-fg-light: ink
  c-fg-light-2: text-muted-light
  c-fg-light-3: text-hint-light
  c-accent: gold
  c-border: border-dark
  c-border-light: border-light

typography:
  display:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 9.5vw
    fontWeight: 700
    lineHeight: 0.96
    letterSpacing: -0.02em
  h1:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 5.2vw
    fontWeight: 600
    lineHeight: 1.08
    letterSpacing: -0.01em
  h2:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 3vw
    fontWeight: 600
    lineHeight: 1.18
  h3:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 1.9vw
    fontWeight: 500
    lineHeight: 1.3
  lead:
    fontFamily: "DM Sans, Noto Sans SC, system-ui, sans-serif"
    fontSize: 1.4vw
    fontWeight: 400
    lineHeight: 1.58
  body:
    fontFamily: "DM Sans, Noto Sans SC, system-ui, sans-serif"
    fontSize: 1.05vw
    fontWeight: 400
    lineHeight: 1.65
  caption:
    fontFamily: "DM Sans, Noto Sans SC, system-ui, sans-serif"
    fontSize: 0.82vw
    fontWeight: 400
    lineHeight: 1.5
  label:
    fontFamily: "IBM Plex Mono, JetBrains Mono, monospace"
    fontSize: 0.7vw
    fontWeight: 500
    letterSpacing: 0.14em
    textTransform: uppercase
  stat-value:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 5.5vw
    fontWeight: 600
    lineHeight: 1
    letterSpacing: -0.02em
  quote-text:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 3.6vw
    fontWeight: 400
    lineHeight: 1.28
    letterSpacing: -0.01em
  quote-mark:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 8vw
    fontWeight: 300
    lineHeight: 0.6
  editorial-headline:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 2.75vw
    fontWeight: 600
    lineHeight: 1.2
  dense-headline:
    fontFamily: "Source Serif 4, Noto Serif SC, Georgia, serif"
    fontSize: 2.4vw
    fontWeight: 600
    lineHeight: 1.2

spacing:
  pad-x: 7.5vw
  pad-y: 5.5vh
  gap-lg: 4vh
  gap-md: 2.5vh
  gap-sm: 1.2vh
  grid-cell: 80px

canvas:
  width: 100vw
  height: 100vh

components:
  rule-short:
    width: 36px
    height: 1px
    background: "{colors.gold}"
    description: "Short gold rule used as a kicker separator above headlines and as a chapter accent mark."
  rule-full:
    width: "100%"
    height: 1px
    background: "{colors.border-dark}"
    description: "Full-width hairline divider, color shifts to {colors.border-light} on cream surfaces."
  kicker:
    color: "{colors.gold}"
    typography: "{typography.label}"
    description: "Mono uppercase label in antique gold, sits above a headline."
  tag:
    border: "1px solid {colors.gold}"
    color: "{colors.gold}"
    padding: "0.3em 0.8em"
    typography: "{typography.label}"
    description: "Outlined gold pill containing a mono uppercase label."
  chrome-bar:
    borderBottom: "1px solid {colors.border-dark}"
    paddingBottom: "{spacing.gap-sm}"
    marginBottom: "{spacing.gap-md}"
    description: "Top chrome strip with mono label left, mono counter right, hairline rule beneath."
  foot-bar:
    borderTop: "1px solid {colors.border-dark}"
    paddingTop: "{spacing.gap-sm}"
    marginTop: "{spacing.gap-md}"
    description: "Bottom chrome strip, mirror of chrome-bar."
  stat-card:
    borderTop: "1px solid {colors.border-dark}"
    padding: "{spacing.gap-md} {spacing.gap-md} {spacing.gap-md} 0"
    description: "Stat tile with a top hairline rule, big gold serif numeral above a sans label and mono note."
  bullet-marker:
    content: "—"
    color: "{colors.gold}"
    fontFamily: "{typography.label.fontFamily}"
    description: "Em-dash bullet rendered in mono gold prefixes every list item."
  vt-spine:
    width: 1px
    background: "{colors.border-dark}"
    description: "Vertical hairline spine for timeline column, with a 9px gold dot marking each entry."
  vt-dot:
    width: 9px
    height: 9px
    borderRadius: 50%
    background: "{colors.gold}"
    description: "Gold node sitting on the timeline spine at each date."
  pie-donut:
    borderRadius: 50%
    innerCutout: "22% inset, painted to match slide background"
    description: "SVG/CSS donut chart, segments in palette colors with a 1px gold ring divider where used."
  bar-fill-default:
    background: "{colors.text-hint-dark}"
    description: "Default bar fill in muted slate; switches to gold for the highlighted bar."
  bar-fill-accent:
    background: "{colors.gold}"
  compare-divider:
    borderRight: "1px solid {colors.border-dark}"
    description: "Single vertical hairline separating two comparison panels."
  pyramid-band:
    borderLeft: "3px solid {colors.gold}"
    padding: "1.3vh 2.5vw"
    fillFunction: "color-mix(in srgb, {colors.gold} N%, {colors.navy})"
    description: "Horizontal band in pyramid layouts; opacity of gold mix decreases from top tier to bottom."
  grid-texture:
    background: "linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px)"
    backgroundSize: "80px 80px"
    description: "Near-invisible 80px grid overlay applied to every dark slide via ::before pseudo-element."
  cycle-step:
    borderTop: "2px solid {colors.gold}"
    padding: "{spacing.gap-md}"
    description: "Cycle/process step card with a 2px gold rule at top, gold numeral, serif title, sans body."
---

## Frontend Slides Fixed-Stage Policy

When this design system is used by the `frontend-slides` skill, generate the final deck as a **fixed 1920×1080 stage** that scales uniformly to the browser viewport. The deck should preserve a 16:9 slide canvas on every screen, including phones; it may letterbox or pillarbox, but it should not reflow slide content for mobile.

This policy has higher priority than any source-template responsive behavior described later in this file. If a later section says the original template is viewport-fluid, treat that as source history only, not as the target generation model for `frontend-slides`.

This policy applies even if the source template was originally implemented with viewport-fluid CSS such as `100vw`, `100vh`, `vw`, `vh`, or `clamp()`. Treat those values as design proportions to translate into 1920×1080 stage coordinates, not as live responsive rules in the generated deck.

Use `deck-stage.js` or an equivalent inline stage scaler for final output: render each slide at 1920×1080, scale the whole stage with one transform, and verify rendered screenshots for both text overflow and panel overlap.


## Overview

Signal is a **literary editorial** presentation system — what a long-form intelligence briefing or a quarterly review from a serious magazine would look like if it ran as a deck. The visual premise is the marriage of two faces: a Scottish-roast editorial serif (Source Serif 4) carrying the voice, and a precision grotesque (DM Sans) carrying the substance, with a condensed monospace (IBM Plex Mono) for every timestamp, kicker, and piece of chrome metadata. The result reads like a quiet authority — the deck does not need to shout because the typography already telegraphs seriousness.

The system runs on a **dual-surface** model. The dark surface is `{colors.navy}` (#1C2644) — a deep editorial blue that sits warmer than navy and cooler than midnight. The light surface is `{colors.cream}` (#F0ECE3) — a warm aged-paper tone, never pure white. Both surfaces carry the same typographic vocabulary at the same scale; what changes is the foreground color. On dark surfaces, primary text is `{colors.text-warm}` (a warm off-white, never pure white). On cream, primary text is `{colors.ink}` (a near-black with a navy bias). The two surfaces are interchangeable from slide to slide — adjacent slides may alternate without any explanation, and the cream surface acts as a "reset" within a longer dark run.

There is exactly one accent color: **antique gold** (`{colors.gold}` — #C8A870). Gold appears only in three contexts: the short rule that separates a kicker from a headline; an `<em>` tag mixed into a roman serif headline (the "Signal moment"); and any numerical figure. Gold never carries a body paragraph and never fills a background. It is a precision tool, used sparingly so that when it appears, it carries weight.

Depth is **flat plus hairline**. There are no drop shadows, no rounded card chrome, no elevation system. Regions separate via 1px hairline rules in `{colors.border-dark}` (or `{colors.border-light}` on cream). The only "texture" in the system is a near-invisible 80px grid overlay on dark slides at 3% white opacity — visible only to the eye that's looking for it. It is the system's fingerprint.

**Density philosophy: medium-low and asymmetric.** Signal is an editorial system; it breathes. A typical slide uses a small fraction of its real estate — a kicker, a headline, a single sentence, a footer. The cover and chapter slides are the sparsest (one display headline against acres of cream or navy). The dense editorial layouts are the exception, not the rule, and even those leave generous interior padding. A slide that feels broken in Signal is one that fills the canvas edge-to-edge with content; the correct register is "I have one thing to say and I will say it carefully."

**Key Characteristics:**
- Source Serif 4 carries every headline with a roman/italic mix mid-sentence; italics in headlines are always gold.
- DM Sans for body and IBM Plex Mono for every timestamp, kicker, label, and chrome element.
- Dual surfaces — `{colors.navy}` (dark) and `{colors.cream}` (light) — used interchangeably, never blended in the same slide except in special split layouts.
- Antique gold (`{colors.gold}`) is the only accent. It marks rules, italic emphasis, and numerical figures, and appears nowhere else.
- Hairline 1px borders in `{colors.border-dark}` / `{colors.border-light}` separate every region. No card chrome, no rounded panels.
- A near-invisible 80px grid texture overlays every dark slide as a barely-perceived fingerprint.
- Em-dash bullet markers in gold mono replace the standard list dot.
- Mono uppercase chrome at the top of every standard slide carries a section label and a slide counter.
- No drop shadows, no gradients (except the bottom-up scrim on fullbleed image slides), no rounded corners (except the donut chart).

## Colors

### Palette

- **Navy** (`{colors.navy}` — #1C2644): The dark surface. A deep editorial blue, warmer than midnight, cooler than indigo. The "intelligence" color — authority without aggression.
- **Navy Alt** (`{colors.navy-alt}` — #232F55): A slightly lifted navy reserved for secondary dark surfaces (placeholder panels, image fallbacks). Visually nearly identical to navy; only differs in close adjacency.
- **Cream** (`{colors.cream}` — #F0ECE3): The light surface. A warm aged-paper tone, never neutral and never bright. Reads as "broadsheet" or "manuscript," not "screen white."
- **Cream Alt** (`{colors.cream-alt}` — #E6E0D4): A slightly cooler cream for secondary light surfaces. Same role as navy alt but on the light side.
- **Text Warm** (`{colors.text-warm}` — #E2DCD0): Warm off-white. The primary text color on navy surfaces. Never `#FFFFFF` — pure white would clash with the warm paper logic of the system.
- **Text Muted Dark** (`{colors.text-muted-dark}` — #8A96A8): Muted blue-grey. Secondary text on navy — descriptions, lead paragraphs that want to recede.
- **Text Hint Dark** (`{colors.text-hint-dark}` — #4E5A6E): Tertiary text on navy. Used for stat notes, mono captions, and elements that should be readable but quiet.
- **Ink** (`{colors.ink}` — #1A2030): Near-black with a navy bias. Primary text on cream. Picks up the dark surface color rather than fighting it.
- **Text Muted Light** (`{colors.text-muted-light}` — #5A6270): Secondary text on cream.
- **Text Hint Light** (`{colors.text-hint-light}` — #9AA0A8): Tertiary text on cream.
- **Gold** (`{colors.gold}` — #C8A870): Antique gold. The single accent color of the system. Appears on rules, italic emphasis inside headlines, statistical numerals, kicker labels, and bullet markers. Never used as a fill, never used on body text.
- **Border Dark** (`{colors.border-dark}` — #2E3D5C): Hairline divider on navy surfaces. Visible but quiet.
- **Border Light** (`{colors.border-light}` — #CAC4B4): Hairline divider on cream surfaces. Warm greige.

### Defaults

- **Default surface**: alternate between `{colors.navy}` (dark) and `{colors.cream}` (light) across the deck. There is no "primary" surface — both are first-class. If unsure, reach for navy for chapter openers and statement slides, cream for dense editorial reads.
- **Default primary text on navy**: `{colors.text-warm}`.
- **Default primary text on cream**: `{colors.ink}`.
- **Default secondary text on navy**: `{colors.text-muted-dark}`.
- **Default secondary text on cream**: `{colors.text-muted-light}`.
- **Default tertiary/hint text**: `{colors.text-hint-dark}` on navy, `{colors.text-hint-light}` on cream — for mono captions, stat notes, footnotes.
- **Default accent**: `{colors.gold}` — applied to rules, italic emphasis inside headlines, statistical figures, kicker labels.
- **Default border**: `{colors.border-dark}` on navy, `{colors.border-light}` on cream.
- **Default kicker color**: `{colors.gold}`.

The two surfaces are interchangeable and carry the same gold accent — a gold rule on navy reads identically to a gold rule on cream. Body text never appears in gold. Gold never serves as a region fill.

## Typography

### Font Family

Signal runs four font families in carefully separated roles:

- **Source Serif 4** (`{typography.display.fontFamily}`) — a Scottish-roast editorial serif. Carries every headline at every scale (display, h1, h2, h3, editorial-headline, dense-headline, quote-text, stat-value). The face has a full italic axis, and the system's most distinctive typographic move is **mixing roman and italic mid-sentence**: the roman type carries the sentence and an `<em>` tag inside switches to italic in `{colors.gold}`. This is the "Signal moment."
- **DM Sans** (`{typography.body.fontFamily}`) — a humanist grotesque used for body, lead paragraphs, bullet items, and stat labels. DM Sans is the structural understudy — it never leads, it always supports. When `<em>` appears inside a sans `.lead` paragraph, the emphasis switches to **italic serif in gold** (a font-family change), not italic sans.
- **IBM Plex Mono** (`{typography.label.fontFamily}`) — a condensed editorial monospace. Carries every label, every kicker, every chrome element (top bar, footer, slide counter), every chapter number, every mono caption, every stat note, every timeline date. Mono is the system's "metadata voice."
- **Noto Serif SC / Noto Sans SC** — Chinese fallbacks for the serif and sans roles. Wired into every font-family stack so the system renders identically with Chinese content.

The emotional contrast is: serif = voice, sans = substance, mono = timestamp. Mixing them in one sentence (a sans lead with an italic serif gold `<em>` inside) is the system's small choreography.

### Type Scale

| Token | Size | Family | Weight | Use |
|---|---|---|---|---|
| `{typography.display}` | 9.5vw | Source Serif 4 | 700 | Hero cover headline at maximum scale |
| `{typography.h1}` | 5.2vw | Source Serif 4 | 600 | Chapter title or single-statement headline |
| `{typography.stat-value}` | 5.5vw | Source Serif 4 | 600 | Large statistical numeral in gold |
| `{typography.quote-mark}` | 8vw | Source Serif 4 | 300 | Decorative opening quotation glyph in gold |
| `{typography.quote-text}` | 3.6vw | Source Serif 4 | 400 | Pull-quote body |
| `{typography.h2}` | 3vw | Source Serif 4 | 600 | Primary slide headline |
| `{typography.editorial-headline}` | 2.75vw | Source Serif 4 | 600 | Headline for editorial / newsletter layouts |
| `{typography.dense-headline}` | 2.4vw | Source Serif 4 | 600 | Headline for two-column dense text layouts |
| `{typography.h3}` | 1.9vw | Source Serif 4 | 500 | Sub-headline, panel title, intra-region heading |
| `{typography.lead}` | 1.4vw | DM Sans | 400 | Lead paragraph, intro sentence, list item body |
| `{typography.body}` | 1.05vw | DM Sans | 400 | Paragraph body, bullet body |
| `{typography.caption}` | 0.82vw | DM Sans | 400 | Caption, footnote, source attribution |
| `{typography.label}` | 0.7vw | IBM Plex Mono | 500 | Mono uppercase chrome label, kicker, tag, mono metadata |

### Defaults

- **Default size for a primary section headline**: `{typography.h2}` (3vw).
- **Default size for a chapter opener**: `{typography.h1}` (5.2vw).
- **Default size for a cover hero**: `{typography.display}` (9.5vw).
- **Default size for a paragraph**: `{typography.body}` (1.05vw).
- **Default size for a lead sentence beneath a headline**: `{typography.lead}` (1.4vw).
- **Default size for any chrome, kicker, or metadata label**: `{typography.label}` (0.7vw).
- **Default size for a statistical numeral**: `{typography.stat-value}` (5.5vw), in `{colors.gold}`.
- **Default headline color**: primary text color for the surface (`{colors.text-warm}` on navy, `{colors.ink}` on cream). Never gold.

When unsure between `{typography.h2}` and `{typography.h3}` for a primary moment, reach for `{typography.h2}` — `h3` is for sub-headlines within a region, not for the slide's main statement.

### Signature Treatments

These treatments are **non-optional whenever the corresponding element type is used**:

- **An `<em>` tag inside any serif headline (`display`, `h1`, `h2`, `h3`, `editorial-headline`, `dense-headline`) must render in italic Source Serif 4 in `{colors.gold}`.** This is the system's most distinctive typographic moment — mixing roman and italic mid-sentence with a color shift. A headline with an emphasized phrase without this treatment reads as a different design system.
- **An `<em>` tag inside a sans `.lead` or body paragraph must switch font-family to Source Serif 4, italic, in `{colors.gold}`.** Emphasis in body never stays in DM Sans italic — the font switch is the emphasis.
- **Every kicker is mono uppercase in `{colors.gold}` with at least 0.14em letter-spacing.** A kicker that is sans, lowercase, or not in gold is not a kicker.
- **Every statistical numeral is in Source Serif 4 600 in `{colors.gold}` with -0.02em letter-spacing.** Stats in sans, or stats in primary text color, break the system.
- **Every chrome bar carries a 1px hairline rule beneath it in `{colors.border-dark}` / `{colors.border-light}`.** The hairline is what makes the chrome read as chrome rather than as floating text.
- **Every chapter slide carries a 36px gold rule between the chapter number and the chapter title.** The rule is the section break — no rule, no chapter.
- **Bullet lists use an em-dash in mono gold as the marker.** Standard dot bullets do not exist in this system.

### Typography Principles

The font ladder is fixed: serif for voice (display through h3), sans for substance (lead through caption), mono for metadata (label only). Never use serif for body, never use sans for headlines, never use mono outside metadata roles. Crossing those rails breaks the editorial separation.

Italic is structural, not decorative — it is the emphasis vehicle inside headlines and inside lead paragraphs. Underline does not exist. Bold within body does not exist; if body needs emphasis, switch to the italic serif gold `<em>` pattern.

Line-height runs tight at display scale (0.96 on display, 1.08 on h1) and opens as size decreases (1.5–1.72 on caption and body). Letter-spacing is negative on display and h1 (–0.01 to –0.02em) and zero on body. Mono labels carry tracking of 0.14em to 0.22em — generous letter-spacing is how mono reads as editorial rather than as code.

## Layout

### Canvas System

The system targets `100vw × 100vh` — full viewport. Each `.slide` flexes to fill the viewport exactly, and slides sit side-by-side in a horizontal strip that translates left/right on navigation. All sizes use viewport-relative units (`vw`, `vh`) so the layout scales with window size — there are no fixed pixel measurements except chrome dot/counter sizes.

### Padding and Gap Scale

| Token | Value | Use |
|---|---|---|
| `{spacing.pad-x}` | 7.5vw | Horizontal slide padding |
| `{spacing.pad-y}` | 5.5vh | Vertical slide padding |
| `{spacing.gap-lg}` | 4vh | Between major content sections |
| `{spacing.gap-md}` | 2.5vh | Between related elements |
| `{spacing.gap-sm}` | 1.2vh | Between tightly coupled elements |

Quote slides increase pad-x to 1.1× and pad-y to 1.2× to give the pull-quote extra breathing room. Compare layouts use `pad-x * 0.55` as inset padding on each panel.

### Chrome Frame

Standard slides carry a top chrome bar and a bottom foot bar — both are flex rows with a mono label left, mono counter right, separated from the body by a 1px hairline rule. The chrome and foot disappear on cover, chapter, statement, quote, and end slides — those layouts are chromeless and let the type breathe edge to edge.

Each slide is a CSS grid with `grid-template-rows: auto 1fr auto` — the chrome and foot are the auto rows, the body is the 1fr row that fills.

### Grid Texture

Every dark slide carries a near-invisible 80px × 80px grid overlay drawn with two linear-gradient backgrounds at 3% white opacity. The grid is the system's visual fingerprint — it is not meant to be consciously perceived, only sensed as "this slide has structure." Cream slides do not carry this overlay.

## Depth and Elevation

Signal is **flat by design**. There are no drop shadows. There are no rounded card elevations. There is no elevation system at all — every element sits flush with the surface.

What looks like depth is actually **hairline separation**. Regions separate via 1px solid borders in `{colors.border-dark}` (on navy) or `{colors.border-light}` (on cream). A stat tile, a chrome bar, an editorial column — all separated by hairlines, not by shadows or backgrounds.

The single exception is the **fullbleed gradient scrim**: on fullbleed image slides, a linear gradient from transparent to `rgba(15, 20, 36, 0.9)` runs bottom-up across the lower portion of the slide so the type beneath remains legible against the image. This is the only gradient in the system; everywhere else, surfaces are solid.

## Shapes and Treatment

### Border Radius

| Value | Use |
|---|---|
| 0 | Every shape in the system except donut charts and donut center wells |
| 50% (circle) | Donut chart shapes, the 9px timeline dots, the 2px round-ended border on swatches |
| 2px | Pie legend swatch (subtle softening only) |

Signal has effectively **no rounded chrome**. Stat tiles, chrome bars, compare panels, image frames — all rectangular with sharp corners.

### Border Weights

- **1px solid** — the universal hairline border. Used on every chrome bar, every stat tile top rule, every column divider, every compare panel divider, every editorial column boundary. Color follows the surface (`{colors.border-dark}` or `{colors.border-light}`).
- **1px dashed** — used only inside the chart plot for grid lines (rgba transparency, very low opacity).
- **2px solid `{colors.gold}`** — used on the top rule of a cycle/process step.
- **3px solid `{colors.gold}`** — used as the left-border on pyramid bands.

### Decorative Element Types

**Short gold rule** — a 36px × 1px solid gold horizontal bar. Sits between a kicker and a headline, or as a chapter accent mark. The smallest atomic decorative element in the system.

**Full hairline rule** — a 100% × 1px horizontal rule in `{colors.border-dark}` / `{colors.border-light}`. Used as section dividers, chrome separators, stat-tile top edges, column boundaries.

**Outlined gold tag** — a small inline-block with a 1px gold border around mono uppercase gold text. The "pill" version of a kicker — same typographic spec, with an outline.

**Editorial column divider** — a 1px hairline running floor-to-ceiling between two columns in editorial layouts. Padding inside the columns is `pad-x * 0.38`.

**Vertical timeline spine** — a 1px vertical hairline running the height of a vertical timeline, with 9px circular gold dots positioned at each entry along the spine.

**Pyramid band** — a horizontal band with a 3px solid gold left-border, filled with `color-mix(in srgb, gold N%, navy)` where N decreases from 70% at the top tier to 8% at the bottom tier. Each tier is also progressively wider (38% → 100%). This creates the visual pyramid through color saturation and width, without any actual triangular geometry.

**Donut center well** — the inner 22% inset of a pie donut is filled with the slide background color (navy or cream) to create the donut hole.

**Connector arrow** — in cycle and diagram layouts, a low-contrast arrow glyph in `{colors.border-dark}` (or `{colors.border-light}`) sits between sequential steps. The arrow is intentionally muted — the steps lead, the connector recedes.

**Mono dash bullet** — every list item carries an em-dash (`—`) in mono gold as the bullet marker, with a 1.2em column for the marker and 0.5em gap.

## Do's and Don'ts

### Do

- Mix roman and italic Source Serif 4 inside the same headline, with the italic in `{colors.gold}` — this is the Signal moment, and the system depends on it appearing throughout the deck.
- Use IBM Plex Mono for every kicker, label, tag, chrome element, slide counter, chapter number, and statistical note. Mono is the metadata voice.
- Render every kicker in mono uppercase gold with at least 0.14em letter-spacing — the tracking is what makes mono read as editorial.
- Set every chrome bar to carry a 1px hairline beneath it in the surface-appropriate border color. The hairline is non-negotiable; chrome without a rule reads as floating text.
- Alternate navy and cream surfaces freely across a deck. Neither is "the" background — both are first-class.
- Color every statistical numeral in `{colors.gold}` using Source Serif 4 600 with -0.02em tracking. Stats are the second most-recognizable element after the italic gold headline emphasis.
- Replace standard bullet dots with em-dashes in mono gold. Standard dots break the editorial register.
- Use the 36px gold rule as the chapter break and the kicker separator. It is the system's small punctuation.
- Apply the 80px grid texture overlay to every dark slide via `::before`. It is the system's fingerprint and should never be removed.
- Pad with `{spacing.pad-x}` 7.5vw / `{spacing.pad-y}` 5.5vh — Signal needs the breathing room; tight padding breaks the editorial restraint.

### Don't

- Don't use gold on body text or fill backgrounds with gold. Gold appears only on rules, italic emphasis, and numerical figures.
- Don't use pure white (`#FFFFFF`) for text on navy. Always use `{colors.text-warm}` — the warm off-white is what keeps the system tied to its paper register.
- Don't add drop shadows or rounded card chrome. The system is flat-plus-hairline; elevation breaks the editorial frame.
- Don't put serif type on body or paragraph text. The serif/sans separation is structural — serif leads, sans supports.
- Don't bold inside body text for emphasis. Use the italic serif gold `<em>` pattern instead — the font switch is the emphasis.
- Don't round corners on chrome, panels, stat tiles, or image frames. The only round shapes in the system are the donut chart and the 9px timeline dots.
- Don't introduce a second accent color. Antique gold is the only hot color; adding a second accent dilutes its weight.
- Don't fill more than half a typical slide with content. The system reads as broken when crowded — restraint is the register.
- Don't use mono outside metadata roles (label, kicker, chrome, counter, caption note). Mono in body or headline breaks the typographic ladder.
- Don't omit the 1px hairline beneath chrome or above a stat tile. Hairlines are the system's depth substitute; without them the elements float.

## Responsive Behavior

Signal targets a 1920×1080 viewport but is implemented entirely in viewport-relative units (`vw`, `vh`), so it scales fluidly between 1280×720 and 2560×1440 without breakpoints. The 80px grid texture is the only fixed-pixel measurement that persists across viewport changes — it becomes proportionally finer at larger viewports.

### Scaling Behavior

- Display headline scales with viewport: at 1920px, 9.5vw renders as ~182px. At 1280px, ~122px.
- Body text scales: 1.05vw → ~20px at 1920px, ~13px at 1280px.
- Padding scales: pad-x 7.5vw → ~144px at 1920px, ~96px at 1280px.

### Presenter Behavior

The deck is JS-driven. Slides advance via the navigation strip (translateX on the deck container), with nav dots and a slide counter fixed at the bottom. Each slide carries `is-active` when current; elements with `[data-anim]` attributes animate in via fade-up, fade-in, reveal-right, reveal-left, or scale-in keyframes with staggered `data-delay` (0–6). Animations are short (0.5–0.85s) and use a sharp `cubic-bezier(0.77, 0, 0.175, 1)` slide ease and a spring-y `cubic-bezier(0.16, 1, 0.3, 1)` entrance ease.

### Print Behavior

There is no dedicated print stylesheet. Static export should render each slide as a sequential page; the deck container's horizontal layout would need to be unwound for print fidelity.

## CJK & International Content

### Recommended Chinese Pairing

| Role | Latin | Chinese | Weight mapping |
|---|---|---|---|
| Display / Headlines (h1, h2, h3) / Stat-value / Quote-text / Editorial-headline / Dense-headline | Source Serif 4 (500–700) | **思源黑体 Noto Sans SC** | 700 |
| Lead / Body / Caption | DM Sans (400) | **思源黑体 Noto Sans SC** | 400 |
| Label / Kicker / Chrome / Slide counter | IBM Plex Mono (500) | **思源黑体 Noto Sans SC** | 500 (uppercase + tracking removed) |

### Mixed-Content Strategy

**Strategy A — single CJK family (思源黑体 Noto Sans SC) across all roles.** Signal's Latin system already wires Noto Serif SC and Noto Sans SC into every font-family stack as fallbacks — the system was designed with CJK in mind. The recommended consolidation is to use **Noto Sans SC for every role** rather than mixing Noto Serif SC (display) + Noto Sans SC (body) — and the reason is the system's most distinctive treatment: the gold italic `<em>` emphasis inside headlines. Noto Serif SC does not ship an italic axis, which means the Signal moment (roman-to-italic mid-sentence color shift) cannot be reproduced in Chinese. Collapsing to Noto Sans SC across the system and reserving the color-only emphasis (gold without italic) for CJK `<em>` lands cleaner than fighting an italic-less serif. The serif vs sans contrast that defines the Latin ladder is lost in CJK, but the editorial restraint of the system — hairlines, mono kickers, antique gold accents, dual surfaces — carries through unaffected.

### Loading

The system already loads Noto Sans SC via the existing font-family stacks. If using a CDN preconnect pattern:

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
```

The existing CSS variables already include Noto Sans SC and Noto Serif SC in every font stack. For a CJK-primary deck, swap the serif stacks to use Noto Sans SC as the active CJK face (rather than Noto Serif SC) so the entire system collapses to one Chinese family:
```css
/* Display / headline roles (CJK-primary) */
font-family: 'Source Serif 4', 'Noto Sans SC', Georgia, serif;
/* Body roles */
font-family: 'DM Sans', 'Noto Sans SC', system-ui, sans-serif;
/* Mono roles */
font-family: 'IBM Plex Mono', 'Noto Sans SC', monospace;
```

### Universal CJK Adjustments

- Line-height: body 1.75–1.85, display 1.15–1.25
- Letter-spacing: 0 on CJK
- Text-transform: no uppercase on CJK
- Full-width punctuation
- No period on display headlines
- Pangu spacing (盘古之白): `使用 Claude` not `使用Claude`
- One font per sentence

### Aesthetic Notes for This System

- **The Signal moment (italic gold `<em>` mid-sentence) becomes color-only on CJK.** Noto Sans SC has no italic variant; even Noto Serif SC ships without italic. For Chinese headlines, render `<em>` as a color shift to `{colors.gold}` *without* italic — the emphasis still lands because gold is the system's most-loaded color. Treat this as a deliberate translation of the Signal moment to its color-only essence in CJK.
- **Negative letter-spacing on display (-0.02em on display, -0.01em on h1/h2) must drop to 0 on CJK.** The system's tight tracking is a Latin-display convention that breaks CJK rendering.
- **Mono kickers in IBM Plex Mono uppercase with 0.14–0.22em tracking are Latin-only.** For CJK kickers, drop tracking to 0 and rely on the gold color + small size to signal "this is a kicker." A mixed CJK + Latin kicker (`第一章 / CHAPTER ONE`) can keep the Latin half tracked and the CJK half at 0 tracking — the asymmetric mono voice reads as editorial bilingualism.
- **Statistical numerals at Source Serif 4 600 in gold** remain Latin numerals (the Western-numeral convention for stats is universal in modern editorial design). Don't substitute Chinese numerals (一二三四) — they lose the catalogue-statistical voice.
- **The em-dash bullet (`—` in mono gold) translates perfectly** — em-dash bullets are equally idiomatic in Chinese typography.
- **The 80px grid texture, hairline borders, dual surface (navy + cream), gold rules, chapter slides, fullbleed image scrim, chromeless statement layouts** are all glyph-agnostic. The editorial restraint and intelligence-briefing register carry through unaffected.
- **Line-height on CJK body should open from 1.58–1.72 to 1.75–1.85** — Chinese characters fill their em-box and need additional vertical breathing for readability at the system's body sizes (1.05vw, 1.4vw).
- **Quote-mark glyph (the 8vw decorative opening quotation)** should switch to a Chinese opening guillemet (「) or curly quote (") — Latin opening-quote glyphs read as alien on Chinese pull-quotes.

### Known CJK Gap

The system's most distinctive typographic treatment (roman + italic-gold mid-sentence inside Source Serif 4 headlines) is fundamentally a Latin-typographic move that does not translate. Neither Noto Serif SC nor Noto Sans SC ships an italic axis, and inventing one via CSS `font-style: italic` produces an oblique/slanted glyph that reads as broken rather than as emphasis. Collapsing CJK `<em>` to a color-only shift (gold without italic) is the cleanest workaround; mixed-language headlines where the emphasized phrase is Latin (and therefore can take italic gold) and the surrounding sentence is Chinese will land as the strongest CJK execution of the Signal moment.

## Iteration Guide

1. Any new headline uses Source Serif 4 and is eligible for an `<em>` mid-sentence in italic gold. If the headline has no emphasized phrase, consider whether it should — the Signal voice depends on the gold italic moment appearing.
2. Any new region separator is a 1px hairline in `{colors.border-dark}` / `{colors.border-light}`. Never a thicker border, never a colored border, never a shadow.
3. Any new label, kicker, or chrome element is mono uppercase in `{colors.gold}` (for kickers) or surface-appropriate muted color (for chrome). Letter-spacing at least 0.14em.
4. Any new statistical figure uses Source Serif 4 600 in `{colors.gold}` at -0.02em tracking. Stats are always gold serif, regardless of surface.
5. Any new accent treatment uses `{colors.gold}` — there is no second accent. If a slide needs more visual differentiation, vary the surface (navy vs. cream) rather than adding color.
6. Any new bullet list uses the em-dash gold mono marker. Adding a different bullet style breaks the system.
7. Cover, chapter, statement, quote, and end layouts are chromeless. Standard layouts carry chrome and foot. Don't mix — a chromeless statement is correct; a chromed statement reads as a different system.
8. The 80px grid overlay is part of the dark-surface identity. Any new dark slide should inherit `.slide.dark` so the `::before` overlay applies automatically.
9. New layouts should keep the editorial breathing room. If a layout requires content edge-to-edge, reconsider — Signal is a restrained system.
10. Italic in body text always means font-family switch to Source Serif 4 italic in `{colors.gold}`. Italic DM Sans is not a system primitive.

## Known Gaps

- The four font families load from Google Fonts at runtime. If fonts fail to load (network issues, ad blockers), fallbacks are Georgia (for serif), system-ui (for sans), and Courier-style monospace — the resulting rendering loses much of the editorial character but remains legible.
- Chinese fallbacks (Noto Serif SC, Noto Sans SC) are wired into every font-family stack but render slightly different metrics from the Latin faces; pure Chinese decks will read slightly tighter.
- The 80px grid texture is a magic number tied to viewport scale; at very large viewports (>2560px), the grid may begin to feel coarse rather than imperceptible.
- The slide navigation is JavaScript-driven with hardcoded `transform: translateX(...)` on the deck container. The system depends on this engine; replacing it requires preserving the `is-active` class behavior for animations to fire.
- The `--c-bg-alt`, `--c-bg-light-alt`, and several muted color tokens are defined but used sparingly — they exist as a reserve for adjacent-surface differentiation that the source template uses only occasionally.
- The pyramid layout uses `color-mix(in srgb, ...)` which requires modern browser support; older browsers may render bands as flat fill rather than tiered.
- The fullbleed slide gradient is hardcoded to `rgba(15, 20, 36, 0.9)` (close to navy but not parameterized via a token). Changing the navy color requires updating this gradient in parallel.
````

---

## 2. 글씨체

- 이 디자인의 한글 글씨체: 제목 NanumMyeongjo Bold(700) · 본문 프리텐다드 Pretendard-Regular(400). (쓰는 폰트: NanumMyeongjo Bold, 프리텐다드 Pretendard-Regular)
- 글씨체 파일은 공통 CSS(5)의 `@font-face`가 인터넷의 폰트 창고(`https://maker-ssam.github.io/korean-ofl-fonts/…`)에서 불러옵니다. 설치하지 않아도 되지만 열 때 인터넷이 필요합니다.
- 글씨체 규칙(굵기·크기·자간)은 1의 디자인 규칙을 따르고, 한글 폰트는 변수(`--kt` 제목, `--kb` 본문, `--ka` 포인트)로만 지정하세요.

---

## 3. 부품 사전 (이 디자인의 CSS에 정의된 클래스)

이 목록과 공통 CSS(5)에 있는 클래스만 쓰세요. '○장'은 아래 뼈대에서 그 클래스를 쓴 예시 장이고, '예'는 그 장의 실제 태그입니다. 장 구성은 따라 하지 말고, 필요한 부품을 골라 어느 장에서든 쓰면 됩니다. 클래스를 조합하는 방법(어떤 부품 안에 어떤 부품이 들어가는지)은 뼈대의 예시 장을 보고 따르세요.
- 여러 장에서 쓰인 클래스는 이 디자인의 공통 부품입니다(창·제목줄·버튼·표 등).
- 한 장에서만 쓰인 클래스 중 크기·위치를 정하는 것(이름에 번호가 붙은 창·격자 등)은 **그 예시 장 전용 배치**입니다. 같은 배치를 다시 쓸 때만 쓰고, 새 배치가 필요하면 비슷한 이름을 지어 쓰지 말고 '추가 부품' 칸에 직접 정의하세요.
- 예시 장의 측정기 그림(`g-…` 클래스)은 예시 주제 전용이라 이 목록에 없습니다. 새 주제의 그림은 SVG로 새로 그리세요.

**1장(표지)에서 처음 나오는 부품**
- `.dark` — 1·3·5장 — 예: `<section class="slide dark">`
- `.gk` — 1장 — 예: `<em class="gk">`
- `.gl` — 1장 — 예: `<p class="mono gl" data-anim="fade-in" data-delay="3">`
- `.k1` — 1장 — 예: `<div class="kick k1" data-anim="fade-in" data-delay="0">`
- `.kick` — 1·2·3·4·5·6장 — 예: `<div class="kick k1" data-anim="fade-in" data-delay="0">`
- `.mono` — 1·2·3·4·5장 — 예: `<p class="mono gl" data-anim="fade-in" data-delay="3">`
- `.r1` — 1장 — 예: `<i class="rule r1" data-anim="reveal-right" data-delay="1">`
- `.rule` — 1·2·3·4·5·6장 — 예: `<i class="rule r1" data-anim="reveal-right" data-delay="1">`
- `.slide` — 1·2·3·4·5·6장 — 예: `<section class="slide dark">`
- `.t1` — 1장 — 예: `<h1 class="t1" data-anim="fade-up" data-delay="3">`
- `.tag` — 1·2·5·6장 — 예: `<span class="tag">`
- `.tags` — 1장 — 예: `<div class="tags" data-anim="fade-in" data-delay="5">`
- `.unit` — 1장 — 예: `<p class="unit" data-anim="fade-up" data-delay="2">`

**2장(흐름·단계)에서 처음 나오는 부품**
- `.bt` — 2·5·6장 — 예: `<button class="tag bt" data-act="step">`
- `.btns` — 2장 — 예: `<div class="btns" data-anim="fade-in" data-delay="5">`
- `.cap` — 2장 — 예: `<p class="cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quo…`
- `.chrome` — 2·3·4·5·6장 — 예: `<div class="chrome">`
- `.fig` — 2장 — 예: `<figure class="fig" data-anim="fade-in" data-delay="3">`
- `.foot` — 2·3·4·5·6장 — 예: `<div class="foot">`
- `.ghost` — 2·5장 — 예: `<button class="tag bt ghost" data-act="reset">`
- `.hd` — 2·3·4·5·6장 — 예: `<h2 class="hd" data-anim="fade-up" data-delay="2">`
- `.ld2` — 2장 — 예: `<p class="lead ld2" data-anim="fade-in" data-delay="4">`
- `.light` — 2·4·6장 — 예: `<section class="slide light" data-steps="4">`
- `.spine` — 2장 — 예: `<i class="spine">`
- `.vd` — 2장 — 예: `<i class="vd">`
- `.ve` — 2장 — 예: `<div class="ve" data-s="1">`
- `.vt` — 2장 — 예: `<div class="vt" data-anim="fade-up" data-delay="3">`

**3장(숫자와 그래프)에서 처음 나오는 부품**
- `.bar` — 3장 — 예: `<i class="bar" style="height:63%">`
- `.chart` — 3장 — 예: `<div class="chart" data-anim="fade-in" data-delay="5">`
- `.col` — 3장 — 예: `<div class="col">`
- `.cv` — 3장 — 예: `<span class="cv">`
- `.mx` — 3·6장 — 예: `<div class="col mx">`
- `.plot` — 3장 — 예: `<div class="plot">`
- `.rb` — 3장 — 예: `<span class="mono rl rb">`
- `.rl` — 3장 — 예: `<span class="mono rl rb">`
- `.sl` — 3장 — 예: `<span class="sl">`
- `.sn` — 3장 — 예: `<span class="mono sn">`
- `.stat` — 3장 — 예: `<div class="stat" data-anim="fade-up" data-delay="2">`
- `.stats` — 3장 — 예: `<div class="stats">`
- `.sv` — 3장 — 예: `<span class="sv">`
- `.tm` — 3장 — 예: `<div class="vr tm">`
- `.vr` — 3장 — 예: `<div class="vr tm">`

**4장(비교와 표)에서 처음 나오는 부품**
- `.bl` — 4·5·6장 — 예: `<p class="bl">`
- `.cmp` — 4장 — 예: `<div class="cmp" data-anim="fade-up" data-delay="3">`
- `.cp` — 4장 — 예: `<div class="cp">`
- `.dash` — 4·5·6장 — 예: `<span class="dash">`
- `.kk` — 4·5·6장 — 예: `<span class="mono kk">`
- `.lst` — 4장 — 예: `<div class="lst" data-anim="fade-up" data-delay="4">`
- `.qm` — 4장 — 예: `<b class="qm">`
- `.qt` — 4장 — 예: `<blockquote class="qt" data-anim="fade-up" data-delay="5">`
- `.tbl` — 4장 — 예: `<div class="tbl" data-anim="fade-in" data-delay="4">`
- `.th` — 4장 — 예: `<div class="tr th">`
- `.tr` — 4장 — 예: `<div class="tr th">`

**5장(확인(퀴즈·빈칸))에서 처음 나오는 부품**
- `.blank` — 5장 — 예: `<button class="blank" data-blank aria-pressed="false">`
- `.blk` — 5장 — 예: `<div class="blk" data-anim="fade-up" data-delay="4">`
- `.fb` — 5장 — 예: `<p class="fb" data-fb>`
- `.opt` — 5장 — 예: `<button class="opt" data-opt="0">`
- `.opts` — 5장 — 예: `<div class="opts">`
- `.ot` — 5장 — 예: `<span class="ot">`
- `.q` — 5장 — 예: `<h3 class="q">`
- `.quiz` — 5장 — 예: `<div class="quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다시 생각해…`
- `.rty` — 5장 — 예: `<button class="tag bt ghost rty" data-act="retry">`
- `.wl` — 5장 — 예: `<span class="mono kk wl">`
- `.words` — 5장 — 예: `<p class="words">`

**6장(디자인 안내(시연))에서 처음 나오는 부품**
- `.a` — 6장 — 예: `<div class="d6 a">`
- `.b` — 6장 — 예: `<div class="d6 b">`
- `.br6` — 6장 — 예: `<div class="br6" id="sg-bar">`
- `.c` — 6장 — 예: `<div class="d6 c">`
- `.d6` — 6장 — 예: `<div class="d6 a">`
- `.dh` — 6장 — 예: `<div class="dh">`
- `.em6` — 6장 — 예: `<p class="em6" id="sg-em">`
- `.g6` — 6장 — 예: `<div class="g6" data-anim="fade-in" data-delay="3">`
- `.in6` — 6장 — 예: `<div class="in6" id="sg-in">`
- `.sl6` — 6장 — 예: `<span class="kk sl6">`
- `.sm` — 6장 — 예: `<button class="tag bt sm" data-demo="#sg-in">`
- `.sw6` — 6장 — 예: `<span class="sw6">`

**직접 쓰지 말 것**: 엔진이 상태를 나타내려고 붙이는 클래스(`.on` `.now` `.open` `.right` `.wrong` `.play` `.solved` `.tried` `.active` `.visible` `.flash` `.in-frame`)와 내비 클래스(`.dk-…`)는 배치용으로 쓰지 마세요(뼈대의 내비 부분은 그대로 둡니다).

---

## 4. HTML 뼈대 (예시 덱 6장 — 부품 견본입니다. 장 구성은 따라 하지 말고, 공통 파일 두 줄은 그대로 두며, 장은 내용에 맞게 새로 구성)

```html
<!DOCTYPE html>
<html lang="ko" data-template="signal">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>계절의 변화</title>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,500&family=DM+Sans:wght@400;500&family=IBM+Plex+Mono:wght@500&display=swap">
<!-- 이 디자인의 공통 CSS(글씨체·색·부품 모양). 이 줄은 지우거나 바꾸지 마세요 -->
<link rel="stylesheet" href="https://k-slide.web.app/kit/v1/signal.css">
<style>
/* === 추가 부품: 새 클래스가 꼭 필요할 때만 이 줄 아래에 정의하세요(공통 CSS는 위 <link>가 이미 불러옴 — 여기에 옮겨 쓰지 않음) === */
</style>
</head>
<body>
<div class="deck-viewport">
  <main class="deck-stage" id="deckStage">
<section class="slide dark">
  <div class="kick k1" data-anim="fade-in" data-delay="0">초등 과학 · 6학년 2학기</div><i class="rule r1" data-anim="reveal-right" data-delay="1"></i>
  <p class="unit" data-anim="fade-up" data-delay="2">계절의 변화<span>Sun, Shadow & <em>Temperature</em></span></p>
  <p class="mono gl" data-anim="fade-in" data-delay="3">학습 목표</p>
  <h1 class="t1" data-anim="fade-up" data-delay="3">하루 동안 <em class="gk">태양 고도</em>,<br><em class="gk">그림자 길이</em>, <em class="gk">기온</em>의 관계</h1>
  <div class="tags" data-anim="fade-in" data-delay="5"><span class="tag">1단원 · 3~4차시</span><span class="tag">LESSON 03</span><span class="mono">00초등학교 · 2026</span></div>
</section>
<section class="slide light" data-steps="4">
  <div class="chrome"><span>계절의 변화 · 1단원 · 3~4차시</span><span>측정 준비</span></div>
  <div class="kick" data-anim="fade-in" data-delay="0">측정 준비</div><i class="rule" data-anim="reveal-right" data-delay="1"></i><h2 class="hd" data-anim="fade-up" data-delay="2">태양 고도 <em>측정기</em> 만들기</h2>
  <figure class="fig" data-anim="fade-in" data-delay="3"><figcaption class="mono">FIG. 01 — 태양 고도 측정기</figcaption><svg class="gauge" viewBox="0 0 1000 660" role="img" aria-label="태양 고도 측정기: 태양 빛, 수수깡, 실, 태양 고도, 그림자 길이, 자, 각도기">
  <line class="g-ground" x1="20" x2="980" y1="580" y2="580"/>
  <rect class="g-board" x="80" y="540" width="860" height="40"/>
  <g class="g-part" data-s="1"><rect class="g-ruler" x="110" y="524" width="800" height="16"/><line class="g-tick" x1="120" x2="120" y1="524" y2="536"/><line class="g-tick" x1="140" x2="140" y1="524" y2="530"/><line class="g-tick" x1="160" x2="160" y1="524" y2="530"/><line class="g-tick" x1="180" x2="180" y1="524" y2="530"/><line class="g-tick" x1="200" x2="200" y1="524" y2="530"/><line class="g-tick" x1="220" x2="220" y1="524" y2="536"/><line class="g-tick" x1="240" x2="240" y1="524" y2="530"/><line class="g-tick" x1="260" x2="260" y1="524" y2="530"/><line class="g-tick" x1="280" x2="280" y1="524" y2="530"/><line class="g-tick" x1="300" x2="300" y1="524" y2="530"/><line class="g-tick" x1="320" x2="320" y1="524" y2="536"/><line class="g-tick" x1="340" x2="340" y1="524" y2="530"/><line class="g-tick" x1="360" x2="360" y1="524" y2="530"/><line class="g-tick" x1="380" x2="380" y1="524" y2="530"/><line class="g-tick" x1="400" x2="400" y1="524" y2="530"/><line class="g-tick" x1="420" x2="420" y1="524" y2="536"/><line class="g-tick" x1="440" x2="440" y1="524" y2="530"/><line class="g-tick" x1="460" x2="460" y1="524" y2="530"/><line class="g-tick" x1="480" x2="480" y1="524" y2="530"/><line class="g-tick" x1="500" x2="500" y1="524" y2="530"/><line class="g-tick" x1="520" x2="520" y1="524" y2="536"/><line class="g-tick" x1="540" x2="540" y1="524" y2="530"/><line class="g-tick" x1="560" x2="560" y1="524" y2="530"/><line class="g-tick" x1="580" x2="580" y1="524" y2="530"/><line class="g-tick" x1="600" x2="600" y1="524" y2="530"/><line class="g-tick" x1="620" x2="620" y1="524" y2="536"/><line class="g-tick" x1="640" x2="640" y1="524" y2="530"/><line class="g-tick" x1="660" x2="660" y1="524" y2="530"/><line class="g-tick" x1="680" x2="680" y1="524" y2="530"/><line class="g-tick" x1="700" x2="700" y1="524" y2="530"/><line class="g-tick" x1="720" x2="720" y1="524" y2="536"/><line class="g-tick" x1="740" x2="740" y1="524" y2="530"/><line class="g-tick" x1="760" x2="760" y1="524" y2="530"/><line class="g-tick" x1="780" x2="780" y1="524" y2="530"/><line class="g-tick" x1="800" x2="800" y1="524" y2="530"/><line class="g-tick" x1="820" x2="820" y1="524" y2="536"/><line class="g-tick" x1="840" x2="840" y1="524" y2="530"/><line class="g-tick" x1="860" x2="860" y1="524" y2="530"/><line class="g-tick" x1="880" x2="880" y1="524" y2="530"/><line class="g-tick" x1="900" x2="900" y1="524" y2="530"/><text class="g-lb" x="922" y="516" text-anchor="start">자</text></g>
  <g class="g-meas"><rect class="g-shadow" x="220" y="524" width="446" height="16"/>
    <path class="g-dim" d="M220 600v24M666 600v24M220 612H666"/><text class="g-lb" x="443" y="652" text-anchor="middle">그림자 길이</text></g>
  <g class="g-part" data-s="2"><rect class="g-stick" x="196" y="150" width="24" height="374"/><path class="g-mark" d="M220 504h20v20"/>
    <path class="g-lead" d="M182 330H196"/><text class="g-lb" x="174" y="342" text-anchor="end">수수깡</text></g>
  <g class="g-part" data-s="4"><path class="g-prot" d="M546 524A120 120 0 0 1 786 524Z"/><path class="g-prot2" d="M588 524A78 78 0 0 1 744 524"/><line class="g-tick" x1="570" y1="524" x2="546" y2="524"/><line class="g-tick" x1="561.6" y1="505.6" x2="547.8" y2="503.2"/><line class="g-tick" x1="566.4" y1="487.7" x2="553.2" y2="483"/><line class="g-tick" x1="582.9" y1="476" x2="562.1" y2="464"/><line class="g-tick" x1="584.8" y1="455.9" x2="574.1" y2="446.9"/><line class="g-tick" x1="597.9" y1="442.8" x2="588.9" y2="432.1"/><line class="g-tick" x1="618" y1="440.9" x2="606" y2="420.1"/><line class="g-tick" x1="629.7" y1="424.4" x2="625" y2="411.2"/><line class="g-tick" x1="647.6" y1="419.6" x2="645.2" y2="405.8"/><line class="g-tick" x1="666" y1="428" x2="666" y2="404"/><line class="g-tick" x1="684.4" y1="419.6" x2="686.8" y2="405.8"/><line class="g-tick" x1="702.3" y1="424.4" x2="707" y2="411.2"/><line class="g-tick" x1="714" y1="440.9" x2="726" y2="420.1"/><line class="g-tick" x1="734.1" y1="442.8" x2="743.1" y2="432.1"/><line class="g-tick" x1="747.2" y1="455.9" x2="757.9" y2="446.9"/><line class="g-tick" x1="749.1" y1="476" x2="769.9" y2="464"/><line class="g-tick" x1="765.6" y1="487.7" x2="778.8" y2="483"/><line class="g-tick" x1="770.4" y1="505.6" x2="784.2" y2="503.2"/><line class="g-tick" x1="762" y1="524" x2="786" y2="524"/><circle class="g-hole" cx="666" cy="524" r="5"/><text class="g-lb" x="800" y="456" text-anchor="start">각도기</text></g>
  <g class="g-part" data-s="3"><line class="g-string" x1="220" y1="150" x2="666" y2="524"/><text class="g-lb" x="478" y="344" text-anchor="start">실</text></g>
  <g class="g-meas"><path class="g-angle" d="M616 524A50 50 0 0 1 627.7 491.9"/><path class="g-lead" d="M542 498L615 506.9"/><text class="g-lb" x="536" y="508" text-anchor="end">태양 고도</text>
    <line class="g-ray" x1="74.5" y1="27.9" x2="187.8" y2="123"/><polygon class="g-rayh" points="209.3,141 179.5,133 196.2,113"/><text class="g-lb" x="150" y="60" text-anchor="start">태양 빛</text></g>
</svg></figure>
  <p class="lead ld2" data-anim="fade-in" data-delay="4"><em>태양 고도</em> — 태양이 지표면과 이루는 각. 막대기의 그림자와 실이 이루는 각 = 태양 고도</p>
  <div class="vt" data-anim="fade-up" data-delay="3"><i class="spine"></i><div class="ve" data-s="1"><i class="vd"></i><span class="mono">01</span><div><b>자 붙이기</b><p>우드록 한쪽에 양면테이프로 자를 붙여요</p></div></div><div class="ve" data-s="2"><i class="vd"></i><span class="mono">02</span><div><b>수수깡 꽂기</b><p>수수깡을 10cm 정도 잘라 자의 '0' 위치에 수직으로 꽂아요</p></div></div><div class="ve" data-s="3"><i class="vd"></i><span class="mono">03</span><div><b>실 묶기</b><p>수수깡 끝에 실을 묶어요</p></div></div><div class="ve" data-s="4"><i class="vd"></i><span class="mono">04</span><div><b>각도기 끼우기</b><p>실의 다른 끝을 각도기 가운데 구멍에 끼워요</p></div></div></div>
  <div class="btns" data-anim="fade-in" data-delay="5"><button class="tag bt" data-act="step">다음 단계 →</button><button class="tag bt ghost" data-act="reset">처음부터</button><p class="cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quot;03 — 실 묶기&quot;,&quot;04 — 각도기 끼우기&quot;]">버튼을 눌러 순서대로 만들어 보세요</p></div>
  <div class="foot"><span>버튼 규칙 없음 → 골드 테두리 태그으로 표현</span><span>02 / 06</span></div>
</section>
<section class="slide dark">
  <div class="chrome"><span>계절의 변화 · 1단원 · 3~4차시</span><span>측정 결과</span></div>
  <div class="kick" data-anim="fade-in" data-delay="0">측정 결과</div><i class="rule" data-anim="reveal-right" data-delay="1"></i><h2 class="hd" data-anim="fade-up" data-delay="2">하루 동안 무엇이 <em>어떻게</em> 변할까요?</h2>
  <div class="stats"><div class="stat" data-anim="fade-up" data-delay="2"><span class="sv">12:30</span><span class="sl">남중 시각</span><span class="mono sn">태양 고도가 가장 높아요 무렵 · 남중</span></div><div class="stat" data-anim="fade-up" data-delay="3"><span class="sv">정남</span><span class="sl">남중 방향</span><span class="mono sn">남중할 때 태양의 위치 쪽</span></div><div class="stat" data-anim="fade-up" data-delay="4"><span class="sv">14:30</span><span class="sl">최고 기온</span><span class="mono sn">기온이 가장 높아요 무렵</span></div><div class="stat" data-anim="fade-up" data-delay="5"><span class="sv">9:30</span><span class="sl">가장 긴 그림자</span><span class="mono sn">그림자가 가장 길어요 · 15:30</span></div></div>
  <div class="chart" data-anim="fade-in" data-delay="5">
    <span class="mono rl rb">태양 고도(°)</span>
    <div class="plot"><div class="col"><span class="cv">38°</span><i class="bar" style="height:63%"></i></div><div class="col"><span class="cv">48°</span><i class="bar" style="height:80%"></i></div><div class="col"><span class="cv">55°</span><i class="bar" style="height:92%"></i></div><div class="col mx"><span class="cv">57°</span><i class="bar" style="height:95%"></i></div><div class="col"><span class="cv">54°</span><i class="bar" style="height:90%"></i></div><div class="col"><span class="cv">47°</span><i class="bar" style="height:78%"></i></div><div class="col"><span class="cv">37°</span><i class="bar" style="height:62%"></i></div></div>
    <span class="mono rl">시각</span><div class="vr tm"><span>9:30</span><span>10:30</span><span>11:30</span><span>12:30</span><span>13:30</span><span>14:30</span><span>15:30</span></div>
    <span class="mono rl">그림자 길이(cm)</span><div class="vr"><span>12.9</span><span>9.1</span><span>7</span><span>6.4</span><span>7.2</span><span>9.4</span><span>13.4</span></div>
    <span class="mono rl">기온(℃)</span><div class="vr"><span>22</span><span>23.8</span><span>25.2</span><span>26.3</span><span>27</span><span>27.4</span><span>26.9</span></div>
  </div>
  <div class="foot"><span>예시 값 — 태양 고도·그림자(10cm 막대)는 9월 중순 북위 36° 기준 계산, 기온은 교과서 그래프 모양을 따른 값</span><span>03 / 06</span></div>
</section>
<section class="slide light">
  <div class="chrome"><span>계절의 변화 · 1단원 · 3~4차시</span><span>관계 정리</span></div>
  <div class="kick" data-anim="fade-in" data-delay="0">관계 정리</div><i class="rule" data-anim="reveal-right" data-delay="1"></i><h2 class="hd" data-anim="fade-up" data-delay="2">태양 고도가 바뀌면 무엇이 <em>달라질까요</em>?</h2>
  <div class="cmp" data-anim="fade-up" data-delay="3"><div class="cp"><h3>태양 고도가 높을 때</h3><p class="bl"><span class="dash">—</span><span>그림자 길이는 짧아져요</span></p><p class="bl"><span class="dash">—</span><span>기온은 높아져요</span></p></div><div class="cp"><h3>태양 고도가 낮을 때</h3><p class="bl"><span class="dash">—</span><span>그림자 길이는 길어져요</span></p><p class="bl"><span class="dash">—</span><span>기온은 낮아져요</span></p></div></div>
  <div class="tbl" data-anim="fade-in" data-delay="4"><div class="tr th"><span>시각</span><span>태양 고도</span><span>그림자 길이</span><span>기온</span></div><div class="tr"><span>오전 9:30</span><span>낮아요</span><span>길어요</span><span>낮아요</span></div><div class="tr"><span>낮 12:30</span><span>가장 높아요</span><span>가장 짧아요</span><span>높아지는 중</span></div><div class="tr"><span>오후 14:30</span><span>낮아지는 중</span><span>길어지는 중</span><span>가장 높아요</span></div></div>
  <div class="lst" data-anim="fade-up" data-delay="4"><span class="mono kk">남중</span><p class="bl"><span class="dash">—</span><span>태양이 정남쪽에 있을 때 '남중했다'고 해요</span></p><p class="bl"><span class="dash">—</span><span>이때의 태양 고도를 남중 고도라고 해요</span></p></div>
  <blockquote class="qt" data-anim="fade-up" data-delay="5"><b class="qm">“</b><p>태양 고도가 가장 높은 시각과 기온이 가장 높은 시각에는 <em>차이</em>가 있어요.</p><span class="mono kk">— 오늘의 정리</span></blockquote>
  <div class="foot"><span>표 규칙 없음 → 1px 헤어라인 줄으로 표현</span><span>04 / 06</span></div>
</section>
<section class="slide dark">
  <div class="chrome"><span>계절의 변화 · 1단원 · 3~4차시</span><span>확인하기</span></div>
  <div class="kick" data-anim="fade-in" data-delay="0">확인하기</div><i class="rule" data-anim="reveal-right" data-delay="1"></i><h2 class="hd" data-anim="fade-up" data-delay="2">배운 내용을 <em>확인해</em> 볼까요?</h2>
  <div class="quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다시 생각해 볼까요? 태양 고도와 그림자 길이의 관계를 떠올려 보세요" data-anim="fade-up" data-delay="3">
    <span class="mono kk">QUESTION</span>
    <h3 class="q">하루 중 그림자 길이가 가장 짧을 때는?</h3>
    <div class="opts"><button class="opt" data-opt="0"><span class="dash">—</span><span class="ot">오전 9시 30분</span></button><button class="opt" data-opt="1"><span class="dash">—</span><span class="ot">낮 12시 30분 무렵</span></button><button class="opt" data-opt="2"><span class="dash">—</span><span class="ot">오후 3시 30분</span></button></div>
    <p class="fb" data-fb></p>
    <button class="tag bt ghost rty" data-act="retry">다시 풀기 ↺</button>
  </div>
  <div class="blk" data-anim="fade-up" data-delay="4">
    <span class="mono kk">빈칸을 눌러 확인해요</span>
    <p class="bl"><span class="dash">—</span><span><button class="blank" data-blank aria-pressed="false"><span>태양 고도</span></button>는 점점 높아졌다가 다시 낮아진다</span></p><p class="bl"><span class="dash">—</span><span><button class="blank" data-blank aria-pressed="false"><span>그림자 길이</span></button>는 점점 짧아졌다가 다시 길어진다</span></p><p class="bl"><span class="dash">—</span><span><button class="blank" data-blank aria-pressed="false"><span>기온</span></button>은 점점 높아졌다가 다시 낮아진다</span></p>
    <span class="mono kk wl">오늘의 낱말</span>
    <p class="words"><em>태양 고도</em> · <em>남중 고도</em> · <em>그림자 길이</em> · <em>기온</em></p>
  </div>
  <div class="foot"><span>빈칸 규칙 없음 → 골드 밑줄 칸으로 표현</span><span>05 / 06</span></div>
</section>
<section class="slide light">
  <div class="chrome"><span>계절의 변화 · 1단원 · 3~4차시</span><span>디자인 안내</span></div>
  <div class="kick" data-anim="fade-in" data-delay="0">디자인 안내</div><i class="rule" data-anim="reveal-right" data-delay="1"></i><h2 class="hd" data-anim="fade-up" data-delay="2">이 디자인 사용 <em>설명서</em></h2>
  <div class="g6" data-anim="fade-in" data-delay="3">
    <span class="kk">한눈에</span><p class="bl"><span class="dash">—</span><span>문예지 장기 기획 + 정보 브리핑. <b>짙은 남색과 따뜻한 크림</b>을 장마다 번갈아 쓰고, 앤티크 골드는 선·이탤릭 강조·숫자에만.</span></p>
    <span class="kk">색</span><p class="bl"><span class="dash">—</span><span><span class="sw6"><span><i style="background:#1C2644"></i>남색</span><span><i style="background:#F0ECE3"></i>크림</span><span><i style="background:#C8A870"></i>앤티크 골드</span><span><i style="background:#1A2030"></i>잉크</span><span><i style="background:#8A96A8"></i>슬레이트</span></span></span></p>
    <span class="kk">글꼴</span><p class="bl"><span class="dash">—</span><span>제목 Source Serif 4 → NanumMyeongjo Bold</span></p><p class="bl"><span class="dash">—</span><span>본문 DM Sans → 프리텐다드 Pretendard-Regular · 킥커 IBM Plex Mono</span></p>
    <span class="kk">이렇게 쓰면 좋아요</span><p class="bl"><span class="dash">—</span><span>개념을 차분히 정리하는 설명·브리핑 수업. 골드는 장마다 한 문장, 막대도 하나만.</span></p>
  </div>
  <span class="kk sl6">대표 장치 — 눌러 보세요</span>
  <div class="d6 a"><div class="dh"><h3>킥커 → 선 → 제목</h3><button class="tag bt sm" data-demo="#sg-in">다시 보기</button></div><p>나타남 → 선이 오른쪽으로 → 제목이 올라옴(스프링 곡선, 계단).</p><div class="in6" id="sg-in"><span class="kk">BRIEFING</span><i></i><b>태양 고도와 그림자</b></div></div>
  <div class="d6 b"><div class="dh"><h3>Signal moment</h3><button class="tag bt sm" data-demo="#sg-em" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>문장 한가운데 한 낱말만 이탤릭 골드 세리프로.</p><p class="em6" id="sg-em">그림자는 <span>한낮에</span> 가장 짧아요</p></div>
  <div class="d6 c"><div class="dh"><h3>골드 막대는 하나</h3><button class="tag bt sm" data-demo="#sg-bar" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>나머지는 흐린 슬레이트 — 1px 점선 격자 위.</p><div class="br6" id="sg-bar"><i class="" style="height:19.2px"></i><i class="" style="height:43.199999999999996px"></i><i class="" style="height:60px"></i><i class="mx" style="height:64.8px"></i><i class="" style="height:57.599999999999994px"></i><i class="" style="height:40.8px"></i><i class="" style="height:16.8px"></i></div></div>
  <div class="foot"><span>계절의 변화</span><span>06 / 06</span></div>
</section>
<nav class="dk-nav"><button class="dk-prev" aria-label="이전">←</button><span class="dk-dots"><button class="dk-dot" aria-label="1장"></button><button class="dk-dot" aria-label="2장"></button><button class="dk-dot" aria-label="3장"></button><button class="dk-dot" aria-label="4장"></button><button class="dk-dot" aria-label="5장"></button><button class="dk-dot" aria-label="6장"></button></span><button class="dk-next" aria-label="다음">→</button></nav>
  </main>
</div>

<!-- 슬라이드 넘김·단계 버튼·퀴즈 엔진. 이 줄은 지우거나 바꾸지 마세요 -->
<script src="https://k-slide.web.app/kit/v1/signal.js"></script>
</body>
</html>
```

---

## 5. 참고: 공통 CSS와 엔진 사용법 (뼈대가 이미 불러옴 — HTML에 옮겨 쓰지 마세요)

아래는 `https://k-slide.web.app/kit/v1/signal.css`의 내용과 엔진(`https://k-slide.web.app/kit/v1/signal.js`)의 사용법 주석입니다. 클래스의 모양·크기·배치를 이해하는 데에만 쓰세요. 이 내용을 `<style>`이나 `<script>`에 넣으면 안 됩니다.

```css
/* signal — k-slide 공통 CSS v1 (채팅 AI용 받기 .md가 불러옴, 고치지 말 것) */
/* === KOREAN FONTS === */
@font-face{font-family:'kp-40';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/nanummyeongjo/NanumMyeongjoBold.woff2") format("woff2");font-weight:700}
@font-face{font-family:'kp-5';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/pretendard/Pretendard-Regular.woff2") format("woff2");font-weight:400}
/* === THEME === */
:root{--stage-bg:#1C2644;--slide-bg:#1C2644;
  --kt:'kp-40';--kb:'kp-5';--ka:'kp-5';
  --wt:700;--wb:400}
*{margin:0;padding:0;box-sizing:border-box}
body{font-synthesis:none;word-break:keep-all;letter-spacing:0}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
button:disabled{cursor:default}
/* === VIEWPORT BASE (frontend-slides, mandatory) === */
/* ===========================================
   FIXED 16:9 STAGE: MANDATORY BASE STYLES
   Include this ENTIRE file in every presentation.
   Slides are authored at 1920×1080 and scaled as a whole.
   =========================================== */

/* 1. Lock the browser viewport */
html,
body {
    width: 100%;
    height: 100%;
    margin: 0;
    overflow: hidden;
    background: var(--stage-bg, #000);
}

/* 2. Full-window deck viewport */
.deck-viewport {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: var(--stage-bg, #000);
}

/* 3. Fixed 16:9 design canvas.
   JavaScript sets transform: translate(...) scale(...). */
.deck-stage {
    position: absolute;
    left: 0;
    top: 0;
    width: 1920px;
    height: 1080px;
    overflow: hidden;
    transform-origin: 0 0;
    background: var(--slide-bg, #fff);
}

/* 4. Slides stack inside the fixed stage.
   Content must be laid out at 1920×1080, not reflowed per device. */
.slide {
    position: absolute;
    inset: 0;
    width: 1920px;
    height: 1080px;
    overflow: hidden;
    display: block;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    background: var(--slide-bg, #fff);
}

.slide.active,
.slide.visible {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
    z-index: 1;
}

/* 5. Keep media inside authored slide bounds */
img,
video,
canvas,
svg {
    max-width: 100%;
    max-height: 100%;
}

/* 6. Presentation chrome stays outside the slide design system */
.deck-controls {
    position: fixed;
    left: 50%;
    bottom: 22px;
    transform: translateX(-50%);
    z-index: 1000;
}

/* 7. Print one fixed-size slide per page */
@media print {
    html,
    body {
        width: 1920px;
        height: auto;
        overflow: visible;
        background: #fff;
    }

    .deck-viewport {
        position: static;
        overflow: visible;
        background: #fff;
    }

    .deck-stage {
        position: static;
        width: auto;
        height: auto;
        transform: none !important;
        background: none;
    }

    .slide {
        position: relative;
        display: block !important;
        visibility: visible !important;
        opacity: 1 !important;
        pointer-events: auto !important;
        width: 1920px;
        height: 1080px;
        break-after: page;
        page-break-after: always;
    }

    .slide:last-child {
        break-after: auto;
        page-break-after: auto;
    }

    .deck-controls {
        display: none !important;
    }
}

/* 8. Reduced motion */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        transition-duration: 0.2s !important;
    }
}

/* 동작 줄이기(Windows '애니메이션 효과' 끔 등): 위 규칙이 길이를 0.01ms로 줄이면 반복 애니메이션이 깜빡이듯 빨라짐 → 반복은 한 번만 */
@media (prefers-reduced-motion: reduce){*,*::before,*::after{animation-iteration-count:1 !important}}
.dk-nav{position:absolute;z-index:50}


/* === 측정기 그림(figure-gauge.js) 기본 === */
.gauge{display:block;width:100%;height:auto;overflow:visible;--g-sw:2.5}
.gauge .g-lb{font-family:var(--g-font,var(--kb));font-size:40px;font-weight:700;fill:var(--g-ink,currentColor)}
.gauge .g-ground{stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw);opacity:.35}
.gauge .g-board{fill:var(--g-board,none);stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw)}
.gauge .g-ruler{fill:var(--g-ruler,none);stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw)}
.gauge .g-tick{stroke:var(--g-ink,currentColor);stroke-width:1.5}
.gauge .g-stick{fill:var(--g-stick,var(--g-ink,currentColor));stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw)}
.gauge .g-mark,.gauge .g-lead,.gauge .g-dim,.gauge .g-angle{fill:none;stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw)}
.gauge .g-angle{stroke-width:4}
.gauge .g-shadow{fill:var(--g-shadow,var(--g-ink,currentColor));opacity:.6}
.gauge .g-string{stroke:var(--g-acc,var(--g-ink,currentColor));stroke-width:4}
.gauge .g-prot{fill:var(--g-prot,none);stroke:var(--g-ink,currentColor);stroke-width:var(--g-sw)}
.gauge .g-prot2{fill:none;stroke:var(--g-ink,currentColor);stroke-width:1.5}
.gauge .g-hole{fill:var(--g-ink,currentColor)}
.gauge .g-ray{stroke:var(--g-acc,var(--g-ink,currentColor));stroke-width:7}
.gauge .g-rayh{fill:var(--g-acc,var(--g-ink,currentColor))}
/* 만드는 중(1~3단계): 아직 안 만든 부품과 측정 표시는 흐리게 / 0·4단계는 모두 또렷 */
.slide[data-step="1"] .gauge .g-part:not(.on),.slide[data-step="2"] .gauge .g-part:not(.on),.slide[data-step="3"] .gauge .g-part:not(.on),
.slide[data-step="1"] .gauge .g-meas,.slide[data-step="2"] .gauge .g-meas,.slide[data-step="3"] .gauge .g-meas{opacity:var(--g-dim,.2)}

/* === TEMPLATE STYLES === */

/* --- 두 바탕 · 골드 하나 (7.5vw = 144px, 5.5vh = 60px) --- */
:root{--navy:#1C2644;--cream:#F0ECE3;--warm:#E2DCD0;--mut:#8A96A8;--hint:#6A768A;--ink:#1A2030;--mutl:#5A6270;--hintl:#9AA0A8;--gold:#C8A870;--bdd:#2E3D5C;--bdl:#CAC4B4;--px:144px;--sp:cubic-bezier(.16,1,.3,1)}
.slide{font-family:'DM Sans',var(--kb),sans-serif;font-weight:var(--wb)}
.dark{background:var(--navy);color:var(--warm);--m:var(--mut);--h:var(--hint);--b:var(--bdd);--bg:var(--navy)}
.dark::before{content:'';position:absolute;inset:0;pointer-events:none;background:linear-gradient(rgba(255,255,255,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(255,255,255,.03) 1px,transparent 1px);background-size:80px 80px}
.light{background:var(--cream);color:var(--ink);--m:var(--mutl);--h:var(--hintl);--b:var(--bdl);--bg:var(--cream)}
.slide>*{position:absolute}
.slide em,.t1 .gk{font-family:'Source Serif 4',var(--kt),serif;font-style:italic;color:var(--gold)}
.t1 .gk{font-style:normal}
h1,h2,h3,.unit,.q,.qt p,.sv,.ve b,.words,.tr:not(.th) span:first-child{font-family:'Source Serif 4',var(--kt),serif;font-weight:var(--wt)}
.kick,.chrome,.foot,.mono,.tag,.dash{font-family:'IBM Plex Mono',var(--kb),monospace;font-weight:500;text-transform:uppercase}
.kick{left:var(--px);top:150px;font-size:24px;letter-spacing:.16em;color:var(--gold)}
.rule{left:var(--px);top:194px;width:36px;height:1px;background:var(--gold)}
.hd{left:var(--px);right:var(--px);top:214px;font-size:68px;line-height:1.18;white-space:nowrap}
.dash{color:var(--gold)}
.kk{display:block;font-size:22px;letter-spacing:.16em;color:var(--gold)}
.bl{display:grid;grid-template-columns:1.2em 1fr;gap:.4em;align-items:baseline;font-size:29px;line-height:1.55}
.tag{display:inline-block;border:1px solid var(--gold);color:var(--gold);padding:.35em .9em;font-size:22px;letter-spacing:.14em;background:transparent}
.bt{font-size:24px}
.bt:not(.ghost){background:var(--gold);color:var(--navy)}
.bt:disabled{opacity:.3}
.chrome,.foot{left:var(--px);right:var(--px);display:flex;justify-content:space-between;gap:40px;font-size:22px;letter-spacing:.14em;color:var(--m)}
.chrome span,.foot span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chrome{top:56px;padding-bottom:14px;border-bottom:1px solid var(--b)}
.foot{bottom:56px;padding-top:14px;border-top:1px solid var(--b)}

/* --- 1. 표지(남색, 크롬 없음): 골드 킥커 + 36px 골드 선 → 단원(영문 이탤릭 골드 em) → 모노 라벨 → 학습 목표 h1(가장 큰 세리프, 핵심 낱말 = 골드) → 골드 태그 --- */
.k1{top:220px}.r1{top:266px}
.unit{left:var(--px);top:300px;display:flex;align-items:baseline;gap:30px;font-size:72px;line-height:1.1;white-space:nowrap}
.unit span{font:600 48px/1 'Source Serif 4',serif;color:var(--mut)}
.gl{left:var(--px);top:446px;font-size:24px;letter-spacing:.16em;color:var(--mut)}
.t1{left:138px;top:490px;font-size:118px;line-height:1.16;letter-spacing:-.01em;white-space:nowrap}
.tags{left:var(--px);bottom:110px;display:flex;align-items:center;gap:20px}
.tags .mono{font-size:22px;letter-spacing:.14em;color:var(--hint);margin-left:16px}

/* --- 2. 만들기(크림): 헤어라인 틀 속 측정기 그림 + 리드(em = 골드 세리프) | 세로 타임라인(척추 + 골드 점, 켜지면 또렷) + 골드 태그 버튼 --- */
.fig{left:var(--px);top:330px;width:820px;border:1px solid var(--bdl);padding:14px 30px 6px;
  --g-ink:var(--ink);--g-acc:var(--gold);--g-stick:var(--navy);--g-board:#E6E0D4;--g-ruler:var(--cream);--g-prot:rgba(200,168,112,.12);--g-shadow:rgba(26,32,48,.3);--g-font:'DM Sans',var(--kb),sans-serif;--g-sw:1.5}
.fig figcaption{font-size:20px;letter-spacing:.14em;color:var(--mutl)}
.fig .gauge{width:690px;display:block;margin:4px auto 0}
.ld2{left:var(--px);width:820px;top:868px;font-size:26px;line-height:1.5;color:var(--mutl)}
.ld2 em{font-weight:600}
.vt{left:1060px;right:var(--px);top:336px;height:470px}
.spine{position:absolute;left:8px;top:12px;bottom:12px;width:1px;background:var(--bdl)}
.ve{position:relative;height:25%;padding-left:48px;display:grid;grid-template-columns:70px 1fr;column-gap:16px;align-content:start;transition:color .5s}
.vd{position:absolute;left:4px;top:12px;width:9px;height:9px;border-radius:50%;background:var(--bdl);transition:background .4s,transform .4s var(--sp)}
.ve .mono{font-size:22px;letter-spacing:.14em;padding-top:8px;color:var(--gold)}
.ve b{font-size:40px;line-height:1.15}
.ve p{margin-top:4px;font-size:24px;line-height:1.45;color:var(--mutl)}
.slide[data-step]:not([data-step="0"]) .ve:not(.on){color:var(--hintl)}
.slide[data-step]:not([data-step="0"]) .ve:not(.on) p{color:var(--hintl)}
.ve.on .vd{background:var(--gold)}
.ve.now .vd{transform:scale(1.8)}
.btns{left:1060px;right:var(--px);top:840px;display:flex;align-items:center;gap:16px}
.cap{flex:1;font-size:24px;line-height:1.4;color:var(--mutl)}

/* --- 3. 숫자와 그래프(남색): 통계 카드 4개(골드 세리프 숫자) + 막대(슬레이트, 가장 높은 값 = 골드, 점선 격자) + 모노 값 줄 --- */
.stats{left:var(--px);right:var(--px);top:320px;display:grid;grid-template-columns:repeat(4,1fr);gap:48px}
.stat{border-top:1px solid var(--bdd);padding-top:18px;display:flex;flex-direction:column;gap:8px}
.sv{font-size:84px;line-height:1;letter-spacing:-.02em;color:var(--gold)}
.sl{font-size:26px;color:var(--warm)}
.sn{font-size:19px;letter-spacing:.1em;color:var(--hint)}
.chart{left:var(--px);right:var(--px);top:574px;display:grid;grid-template-columns:230px 1fr;column-gap:24px}
.plot{height:220px;display:grid;grid-template-columns:repeat(7,1fr);border-bottom:1px solid var(--bdd);background:repeating-linear-gradient(to top,transparent 0 54px,rgba(138,150,168,.18) 54px 55px)}
.col{display:flex;flex-direction:column;justify-content:flex-end;align-items:center}
.bar{display:block;width:46%;background:#4E5A6E}
.col.mx .bar{background:var(--gold)}
.cv{margin-bottom:8px;font:500 21px/1 'IBM Plex Mono',monospace;color:var(--mut)}
.col.mx .cv{color:var(--gold)}
.rl{align-self:center;font-size:19px;letter-spacing:.12em;color:var(--mut);padding:6px 0}
.rb{align-self:end;padding-bottom:10px}
.vr{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;border-bottom:1px solid var(--bdd);padding:7px 0;font-size:26px}
.vr.tm{font:500 22px/1.3 'IBM Plex Mono',monospace;letter-spacing:.06em;color:var(--warm)}

/* --- 4. 비교와 표(크림): 비교 두 칸(1px 세로선, em-dash) + 헤어라인 표 | em-dash 남중 + 골드 따옴표 인용 --- */
.cmp{left:var(--px);width:1000px;top:330px;display:grid;grid-template-columns:1fr 1fr}
.cp{padding-right:40px}
.cp+.cp{padding:0 0 0 40px;border-left:1px solid var(--bdl)}
.cp h3{font-size:42px;line-height:1.2;margin-bottom:10px}
.tbl{left:var(--px);width:1000px;top:610px}
.tr{display:grid;grid-template-columns:1.2fr 1fr 1fr 1fr;gap:20px;padding:14px 0;border-bottom:1px solid var(--bdl);font-size:28px}
.tr.th{font:500 20px/1.2 'IBM Plex Mono',var(--kb),monospace;letter-spacing:.14em;color:var(--mutl);padding:10px 0}
.lst{left:1240px;right:var(--px);top:330px;display:flex;flex-direction:column;gap:10px}
.qt{left:1240px;right:var(--px);top:600px}
.qm{display:block;font:300 150px/.6 'Source Serif 4',serif;color:var(--gold)}
.qt p{margin-top:14px;font-size:42px;line-height:1.28;font-weight:400}
.qt .kk{margin-top:16px}

/* --- 5. 확인하기(남색): 헤어라인 퀴즈(em-dash 보기, 정답 = 이탤릭 골드 세리프) | em-dash 빈칸(골드 밑줄 칸) + 낱말(골드 em) --- */
.quiz{left:var(--px);width:900px;top:330px;bottom:150px;display:flex;flex-direction:column}
.q{margin-top:14px;font-size:54px;line-height:1.22}
.opts{margin-top:24px;border-top:1px solid var(--bdd)}
.opt{width:100%;display:grid;grid-template-columns:1.2em 1fr;gap:.4em;align-items:baseline;text-align:left;padding:14px 0;border-bottom:1px solid var(--bdd);font-size:36px;color:var(--warm)}
.opt.right .ot{font-family:'Source Serif 4',var(--kt),serif;font-style:italic;color:var(--gold)}
.opt.wrong .ot{color:var(--hint);text-decoration:line-through;text-decoration-thickness:1px}
.opt:disabled:not(.right){opacity:.6}
.fb{margin-top:16px;min-height:80px;font-size:28px;line-height:1.55;color:var(--mut)}
.rty{align-self:flex-start;margin-top:auto}
.blk{left:1140px;right:var(--px);top:330px;bottom:150px;padding-left:56px;border-left:1px solid var(--bdd);display:flex;flex-direction:column;gap:16px}
.blk .bl{font-size:30px;line-height:1.7}
.blank{position:relative;min-width:170px;margin-right:10px;padding:0 10px;border-bottom:1px solid var(--gold);font:500 30px/1.3 'Source Serif 4',var(--kt),serif;color:var(--gold);text-align:center}
.blank span{visibility:hidden}
.blank::after{content:'?';position:absolute;left:0;right:0}
.blank.open span{visibility:visible}
.blank.open::after{content:none}
.wl{margin-top:auto}
.words{font-size:40px;line-height:1.35}
.words em{font-style:normal}

/* --- 요소 등장(명세): [data-anim] + [data-delay] --- */
[data-anim]{opacity:0;transition:opacity .7s var(--sp),transform .7s var(--sp)}
[data-anim="fade-up"]{transform:translateY(30px)}
[data-anim="reveal-right"]{opacity:1;transform:scaleX(0);transform-origin:left}
.visible [data-anim]{opacity:1;transform:none}
[data-delay="1"]{transition-delay:.08s}[data-delay="2"]{transition-delay:.18s}[data-delay="3"]{transition-delay:.3s}[data-delay="4"]{transition-delay:.44s}[data-delay="5"]{transition-delay:.6s}[data-delay="6"]{transition-delay:.78s}

/* --- 내비: 아래 가운데 점 + 모노 화살표(발 바 아래) --- */
.dk-nav{position:absolute;left:50%;bottom:10px;transform:translateX(-50%);display:flex;align-items:center;gap:18px;z-index:40}
.dk-dots{display:flex;gap:12px}
.dk-dot{width:9px;height:9px;border-radius:50%;background:var(--hint);opacity:.6}
.dk-dot.on{background:var(--gold);opacity:1}
.dk-prev,.dk-next{font:500 24px/1 'IBM Plex Mono',monospace;color:var(--hint);padding:4px 8px}
.dk-prev:disabled,.dk-next:disabled{opacity:.3}
/* --- 6. 디자인 안내(크림): em-dash 설명 | 1px 윗선 칸 시연 3개 --- */
.g6{left:var(--px);width:880px;top:340px;display:flex;flex-direction:column;gap:4px}
.g6 .kk{margin-top:14px}
.g6 .bl{font-size:27px}
.g6 b{font-weight:600}
.sw6{display:flex;flex-wrap:wrap;gap:6px 20px}
.sw6 i{display:inline-block;width:24px;height:24px;margin-right:8px;vertical-align:-5px;border:1px solid var(--bdl)}
.sl6{left:1110px;top:340px}
.d6{left:1110px;right:var(--px);border-top:1px solid var(--bdl);padding-top:14px}
.d6.a{top:388px}.d6.b{top:590px}.d6.c{top:768px}
.d6 .dh{display:flex;justify-content:space-between;align-items:center;gap:16px}
.d6 h3{font-size:36px;line-height:1.15}
.d6>p{margin-top:4px;font-size:21px;line-height:1.4;color:var(--mutl)}
.bt.sm{font-size:18px;padding:.35em .8em}
.bt.sm[aria-pressed="true"]{background:var(--navy);color:var(--gold)}
.in6{margin-top:10px;display:flex;flex-direction:column;gap:8px}
.in6 .kk{font-size:18px}
.in6 i{display:block;width:36px;height:1px;background:var(--gold);transform-origin:left}
.in6 b{font:600 34px/1.2 'Source Serif 4',var(--kt),serif}
.in6.play .kk{animation:sg-fi .6s var(--sp) both}
.in6.play i{animation:sg-rv .8s var(--sp) .12s both}
.in6.play b{animation:sg-up .9s var(--sp) .24s both}
@keyframes sg-fi{from{opacity:0}}
@keyframes sg-rv{from{transform:scaleX(0)}}
@keyframes sg-up{from{opacity:0;transform:translateY(28px)}}
.d6 .em6{margin-top:12px;font-size:34px;line-height:1.3;color:var(--ink)}
.em6.play span{font-family:'Source Serif 4',var(--kt),serif;font-style:italic;color:var(--gold)}
.br6{margin-top:12px;height:76px;display:flex;align-items:flex-end;gap:14px;padding:0 10px;border-bottom:1px solid var(--bdl);background:repeating-linear-gradient(0deg,transparent 0 24px,rgba(26,32,48,.12) 24px 25px)}
.br6 i{flex:1;background:#4E5A6E;opacity:.35}
.br6.play i.mx{background:var(--gold);opacity:1}

/* === DECK ENGINE (slide-refs 공용, 덱 HTML에 그대로 인라인됨) ===
   window.DECK_CFG = { type: 'x' | 'y' | 'fade' | 'shift' | 'rise', dur: ms, ease: css, dist: px, wheel: bool }
   window.DECK_FX  = { enter(slide, i), step(slide, k), answer(quiz, ok, btn) }  // 템플릿별 효과 훅(선택)
   - 넘김: → ↓ Space PageDown Enter = 다음(단계가 남았으면 단계 먼저), ← ↑ PageUp = 이전, Home/End
   - 내비: .dk-dot(점) .dk-count(번호, data-pad면 01 형식) .dk-prev .dk-next
   - 단계: <section data-steps="4"> 안의 [data-s="k"] 요소가 k단계부터 .on, 현재 단계는 .now
           [data-caps='["...",...]'] 요소의 글이 단계마다 바뀜, 버튼 [data-act="step"] [data-act="reset"]
   - 퀴즈: [data-quiz data-answer data-right data-wrong] 안의 버튼 [data-opt="i"], 결과 글 [data-fb], 다시 풀기 [data-act="retry"]
   - 빈칸: [data-blank] 를 누르면 .open (답 보이기/숨기기)
   - 시연(6장 디자인 안내): 버튼 [data-demo="선택자"] 를 누르면 같은 장 안의 그 요소에 .play
       data-mode="toggle" 이면 .play 켜기/끄기(aria-pressed), 아니면 .play를 뺐다 다시 붙여 애니메이션을 처음부터 다시 재생 */
```

(끝. 사용자의 수업 내용을 받아 위 지시대로 HTML을 만드세요.)
