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

> 이 파일은 **ChatGPT·Claude·Gemini 같은 채팅 AI**에게 통째로 주면, 이 디자인(`peoples-platform`)으로 수업 슬라이드를 만들어 주도록 쓴 지시서입니다.
> 파일을 읽고 쓸 수 있는 에이전트 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`)에서 불러오는데, 일부 서비스의 미리보기 창은 바깥 파일을 막기 때문입니다. **내려받아 브라우저(크롬·엣지 등)로 열면 정상**으로 보입니다.

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

## 라이선스

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

- Hahmlet Black: Hahmlet — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright 2020 The Hahmlet Project Authors (https://github.com/hyper-type/hahmlet)
  파일: Hahmlet-Black.ttf
- Cafe24 PRO Slim Air: Cafe24 PRO Slim — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright ⓒ Cafe24 Corp. All Rights Reserved. Cafe24 PRO Slim is a trademark of Cafe24.
  파일: Cafe24PROSlim-Air.ttf
- 갈맷글: 갈맷글 — 갈맷글 (Galmat) — 네이버 / 눈누: https://noonnu.cc/font_page/604
  파일: Galmetgol.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/peoples-platform.css">`(head 안)와 `<script src="https://k-slide.web.app/kit/v1/peoples-platform.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. **글씨체는 바꾸지 마세요.** 한글 글씨체(제목 Hahmlet Black(900) · 본문 Cafe24 PRO Slim Air(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. 디자인 규칙 (`peoples-platform` design.md)

````markdown
---
version: alpha
name: People's Platform
description: "A WPA-poster-meets-political-campaign presentation system built on three typefaces and a five-color palette that reduces to three functional roles. Alfa Slab One — a compressed slab serif — does all the heavy lifting at extreme sizes in pure uppercase. Caveat Brush drops in as a handwritten human interrupt: lowercase, slightly rotated, emotionally warm. DM Mono carries all metadata at tight uppercase tracking. The palette is electric cobalt blue, amber orange, and hot red — with red functioning exclusively as a shadow/depth color, never as a surface fill. Every slide gets a paper grain overlay that makes the whole deck feel screen-printed. The aesthetic is loud, confident, and populist — the kind of visual language that belongs on a protest placard, a union newsletter, or a campaign bus."

colors:
  blue: "#2C2CDC"
  blue-deep: "#1B1BB0"
  orange: "#F2A03A"
  orange-deep: "#E89321"
  red: "#E83A2A"
  red-deep: "#B7281C"
  cream: "#F4E9D6"
  paper: "#F5F2EA"
  ink: "#0E0E14"

typography:
  display-jumbo:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 540px
    fontWeight: 400
    lineHeight: 0.82
    letterSpacing: -0.02em
    textTransform: uppercase
  display-hero:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 260px
    fontWeight: 400
    lineHeight: 0.86
    letterSpacing: 0.005em
    textTransform: uppercase
  display-title:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 240px
    fontWeight: 400
    lineHeight: 0.86
    letterSpacing: 0.005em
    textTransform: uppercase
  display-xl:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 180px
    fontWeight: 400
    lineHeight: 0.88
    letterSpacing: 0.005em
    textTransform: uppercase
  display-lg:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 140px
    fontWeight: 400
    lineHeight: 0.88
    letterSpacing: 0.005em
    textTransform: uppercase
  display-md:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 120px
    fontWeight: 400
    lineHeight: 0.88
    letterSpacing: 0.005em
    textTransform: uppercase
  display-sm:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 108px
    fontWeight: 400
    lineHeight: 1.04
    letterSpacing: 0.005em
    textTransform: uppercase
  stat-unit:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 130px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: 0
    textTransform: uppercase
  section-num:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 54px
    fontWeight: 400
    lineHeight: 1.0
    textTransform: uppercase
  card-title:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 54px
    fontWeight: 400
    lineHeight: 1.0
    textTransform: uppercase
  kpi-value:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 88px
    fontWeight: 400
    lineHeight: 0.9
    textTransform: uppercase
  quote-mark:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 300px
    fontWeight: 400
    lineHeight: 0.7
    textTransform: uppercase
  quote-body:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 78px
    fontWeight: 400
    lineHeight: 1.08
    textTransform: uppercase
  item-title:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 38px
    fontWeight: 400
    lineHeight: 1.0
    textTransform: uppercase
  item-title-sm:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 30px
    fontWeight: 400
    lineHeight: 1.0
    textTransform: uppercase
  toc-entry:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 36px
    fontWeight: 400
    lineHeight: 1.0
    textTransform: uppercase
  subtitle:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 72px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: 0.01em
    textTransform: uppercase
  cta:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 48px
    fontWeight: 400
    letterSpacing: 0.02em
    textTransform: uppercase
  stamp:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 28px
    fontWeight: 400
    letterSpacing: 0.04em
    textTransform: uppercase
  url:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 46px
    fontWeight: 400
    letterSpacing: 0.02em
    textTransform: uppercase
  script-lg:
    fontFamily: "Caveat Brush, cursive"
    fontSize: 96px
    fontWeight: 400
    textTransform: lowercase
  script-md:
    fontFamily: "Caveat Brush, cursive"
    fontSize: 64px
    fontWeight: 400
    textTransform: lowercase
  body-lg:
    fontFamily: "Archivo Narrow, sans-serif"
    fontSize: 30px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0
  body-md:
    fontFamily: "Archivo Narrow, sans-serif"
    fontSize: 28px
    fontWeight: 500
    lineHeight: 1.35
    letterSpacing: 0
  body-sm:
    fontFamily: "Archivo Narrow, sans-serif"
    fontSize: 26px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0
  body-xs:
    fontFamily: "Archivo Narrow, sans-serif"
    fontSize: 24px
    fontWeight: 400
    lineHeight: 1.4
    letterSpacing: 0
  label:
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: 0.18em
    textTransform: uppercase
  label-wide:
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    fontWeight: 400
    lineHeight: 1.0
    letterSpacing: 0.22em
    textTransform: uppercase
  label-accent:
    fontFamily: "DM Mono, monospace"
    fontSize: 32px
    fontWeight: 600
    lineHeight: 1.0
    letterSpacing: 0.16em
    textTransform: uppercase
  signoff:
    fontFamily: "DM Mono, monospace"
    fontSize: 26px
    fontWeight: 400
    lineHeight: 1.4
    letterSpacing: 0.20em
    textTransform: uppercase

spacing:
  slide-gutter: 90px
  content-gutter: 120px
  topbar-height: 90px
  section-border: 6px
  inner-border: 3px
  grid-gap-lg: 90px
  grid-gap-md: 30px
  frame-inset: 48px

canvas:
  width: 1920px
  height: 1080px

components:
  inset-frame:
    border: "6px solid {colors.cream}"
    position: absolute
    inset: 48px
  topbar:
    position: absolute
    top: 0
    left: 0
    right: 0
    height: 90px
    background: "{colors.blue}"
    color: "{colors.cream}"
    padding: 0 90px
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    letterSpacing: 0.18em
    borderBottom: "6px solid {colors.cream}"
  section-divider:
    borderBottom: "6px solid {colors.ink}"
    height: 6px
  toc-row:
    display: grid
    gridTemplateColumns: "90px 1fr 100px"
    gap: 24px
    padding: "20px 0"
    borderBottom: "3px solid {colors.ink}"
  toc-num:
    fontFamily: "Alfa Slab One, serif"
    fontSize: 54px
    color: "{colors.orange}"
    textShadow: "3px 3px 0 {colors.red}"
  pillar-col:
    padding: "60px 50px"
    borderRight: "6px solid {colors.ink}"
    background: "{colors.paper}"
  pillar-col-alt:
    background: "{colors.blue}"
    color: "{colors.cream}"
  pillar-tag:
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    letterSpacing: 0.18em
    borderTop: "3px solid {colors.ink}"
    paddingTop: 18px
    marginTop: 14px
    alignSelf: flex-start
  kpi-card:
    border: "5px solid {colors.ink}"
    padding: "28px 30px"
    background: "{colors.paper}"
  kpi-card-alt:
    background: "{colors.blue}"
    color: "{colors.cream}"
  timeline-dot:
    width: 60px
    height: 60px
    borderRadius: 50%
    background: "{colors.orange}"
    border: "6px solid {colors.ink}"
    boxShadow: "6px 6px 0 {colors.red}"
  timeline-dot-alt:
    background: "{colors.blue}"
  timeline-track:
    height: 14px
    background: "{colors.ink}"
  compare-side-left:
    background: "{colors.paper}"
    borderRight: "6px solid {colors.ink}"
    padding: "60px 70px"
  compare-side-right:
    background: "{colors.blue}"
    color: "{colors.cream}"
    padding: "60px 70px"
  compare-label:
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    letterSpacing: 0.22em
    paddingBottom: 14px
    borderBottom: "4px solid {colors.ink}"
    alignSelf: flex-start
  diamond-bullet:
    width: 24px
    height: 24px
    background: "{colors.red}"
    borderRadius: 4px
    transform: rotate(45deg)
  diamond-bullet-alt:
    background: "{colors.orange}"
  avatar:
    width: 120px
    height: 120px
    borderRadius: 50%
    background: "{colors.blue}"
    border: "6px solid {colors.blue}"
    boxShadow: "6px 6px 0 {colors.red}"
  quote-stamp:
    background: "{colors.blue}"
    color: "{colors.orange}"
    padding: "18px 32px"
    transform: rotate(-3deg)
    border: "5px solid {colors.cream}"
    fontFamily: "Alfa Slab One, serif"
    fontSize: 28px
    letterSpacing: 0.04em
    boxShadow: "6px 6px 0 {colors.red}"
    textTransform: uppercase
  circular-stamp:
    width: 200px
    height: 200px
    borderRadius: 50%
    background: "{colors.cream}"
    color: "{colors.blue}"
    border: "6px solid {colors.orange}"
    transform: rotate(-9deg)
    boxShadow: "8px 8px 0 {colors.red}"
  meta-pill:
    border: "3px solid {colors.cream}"
    padding: "8px 20px"
    borderRadius: 999px
  ribbon:
    position: absolute
    bottom: 0
    left: 0
    right: 0
    height: 60px
    background: "{colors.orange}"
    color: "{colors.blue}"
    borderTop: "6px solid {colors.ink}"
    fontFamily: "DM Mono, monospace"
    fontSize: 24px
    letterSpacing: 0.22em
    fontWeight: 600
  lede-block:
    fontFamily: "Archivo Narrow, sans-serif"
    fontWeight: 500
    fontSize: 28px
    lineHeight: 1.35
    borderLeft: "4px solid {colors.ink}"
    paddingLeft: 50px
  lede-block-top:
    borderTop: "6px solid {colors.ink}"
    paddingTop: 24px
  underline-rule:
    height: 14px
    background: "{colors.ink}"
    width: "30%"
    marginTop: 60px
  kicker:
    fontFamily: "DM Mono, monospace"
    letterSpacing: 0.22em
    fontSize: 26px
    color: "{colors.red}"
    marginBottom: 48px
  grain-overlay:
    position: absolute
    inset: 0
    pointerEvents: none
    backgroundImage: "radial-gradient(rgba(0,0,0,.06) 1px, transparent 1px), radial-gradient(rgba(255,255,255,.05) 1px, transparent 1px)"
    backgroundSize: "3px 3px, 5px 5px"
    backgroundPosition: "0 0, 1px 2px"
    mixBlendMode: multiply
    opacity: 0.5
  orange-dot:
    width: 10px
    height: 10px
    borderRadius: 50%
    background: "{colors.orange}"
---

## 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

People's Platform is a **WPA-poster-meets-political-campaign slide system** — the visual language of conviction, the graphic register of public address. The canvas is warm paper (`{colors.paper}` — #F5F2EA), a hair warmer than white, and every slide gets a grain texture applied via a CSS pseudo-element that makes the whole deck feel screen-printed rather than rendered.

The typeface stack is a three-way class system. **Alfa Slab One** owns the stage at extreme sizes — compressed, slab-heavy, all caps, intrinsically authoritative. It is the voice that shouts. **Caveat Brush** is the human interrupt — handwritten, lowercase, slightly rotated, emotionally present. It is the voice that whispers. **DM Mono** is the bureaucratic record-keeper — monospace, wide-tracked uppercase, 24px, always — the voice that accounts for things. Archivo Narrow is the workhorse body face: never used at display sizes, always condensed, weight 500 for readability.

The palette has five named colors but three functional roles. **Blue** (`{colors.blue}` — #2C2CDC) is the primary structural color: backgrounds for high-emphasis surfaces, borders for content dividers, text color on non-blue backgrounds. **Orange** (`{colors.orange}` — #F2A03A) is the energy color: stat figures, column numerals, accent text within blue surfaces. **Red** (`{colors.red}` — #E83A2A) is the depth color — it never appears as a surface fill, only as the first layer of a stacked text-shadow or box-shadow. Blue-deep and red-deep are the outer shadow layers in the double-stacked shadow system.

The signature depth technique is the **stacked offset text-shadow**: orange text casts a red shadow at 6–12px, which casts a red-deep shadow at 12–24px. This creates a three-layer quasi-3D letterpress effect that is the system's most recognisable trait. Box-shadows on interactive elements mirror the same treatment: `6px 6px 0 {colors.red}`.

**Key Characteristics:**
- Paper canvas (`{colors.paper}` — #F5F2EA) with grain overlay via CSS pseudo-element on every slide.
- Stacked double text-shadow: `Npx Npx 0 {colors.red}, 2Npx 2Npx 0 {colors.red-deep}`. Shadow size scales with font size.
- Alfa Slab One for all display and structural type — uppercase, line-height 0.82–1.04, letter-spacing 0.005em.
- Red (`{colors.red}`) functions exclusively as a shadow color — never a surface background.
- Heavy 6px ink borders for all major structural divisions (topbars, section headers, column separators, inset frames).
- DM Mono labels at exactly 24px with 0.18–0.22em tracking across all slides.
- Caveat Brush appears at 64–96px, always lowercase, always rotated 2–5 degrees — a deliberate roughness signal.
- Orange bottom ribbon: a horizontal marquee strip anchored to the bottom of data-heavy slides.
- Inset decorative frame (6px solid cream at `inset: 48px`) used on blue-background slides.

## Colors

### Primary Palette
- **Blue** (`{colors.blue}` — #2C2CDC): Electric cobalt. The dominant surface color for high-emphasis slides and structural elements. Used as full-slide background, column fills, topbar backgrounds, text on cream/paper surfaces, avatar fills, and compare-panel dark side.
- **Blue Deep** (`{colors.blue-deep}` — #1B1BB0): A darker blue. Used exclusively as the outermost layer of stacked text-shadows. Never a surface fill.
- **Orange** (`{colors.orange}` — #F2A03A): Warm amber. The energy accent. Used for oversized stat numerals, column ordinals, CTA button fill, ribbon background, accent text within blue surfaces, and text-shadow inner layer on stamp elements.
- **Orange Deep** (`{colors.orange-deep}` — #E89321): Darker amber. Reserved for the deepest shadow layer on orange elements. Not used as a surface fill.
- **Red** (`{colors.red}` — #E83A2A): Hot red. The depth color. Used exclusively in text-shadows and box-shadows — the first offset layer on most display text and buttons. Never appears as a background or primary text color.
- **Red Deep** (`{colors.red-deep}` — #B7281C): Dark red. The outermost layer of the double text-shadow on the largest display elements. Never a surface fill.

### Surface Palette
- **Cream** (`{colors.cream}` — #F4E9D6): Warm cream. Used as text/border color on blue surfaces (inverted mode), as the inset frame border, and as the full background on cream-tone slides.
- **Paper** (`{colors.paper}` — #F5F2EA): Off-white with a warm cast. The default slide background — slightly warmer and less stark than #fff. Most content slides use this.
- **Ink** (`{colors.ink}` — #0E0E14): Near-black with a barely-perceptible blue undertone. Used for all structural borders, body text, column dividers, timeline tracks, and KPI card borders.

### Color Roles Summary
- **Blue surfaces** = high-emphasis, conclusive, authoritative moments
- **Paper/cream surfaces** = content-first, readable, subordinate moments
- **Orange** = the number, the energy, the thing that matters most on a given slide
- **Red** = never a color you see directly — only a shadow you feel

## Typography

### Font Families
Three typefaces; each occupies a completely non-overlapping register:

**Alfa Slab One** is the primary voice. A compressed, heavy slab serif with strong verticals and blocky serifs. Used at weight 400 (the only weight available, which is intrinsically bold) in strict uppercase for every display moment from 28px stamps to 540px stat figures. Its compressed letterform means even massive sizes don't feel wide — they feel tall and column-like. The slight positive letter-spacing (0.005em) keeps glyphs from touching at large sizes.

**Caveat Brush** is the human voice. A rough handwritten script face used only at large sizes (64–96px), always lowercase, always with a small rotation (-2 to -5 degrees). It appears at moments of warmth, transition, or informality — a script annotation in an otherwise rigidly structured deck. It is never used for body copy or labels.

**DM Mono** is the accounting voice. Monospace, 24px, wide letter-spacing (0.18–0.22em), uppercase. It appears on topbars, footers, kicker labels, metadata rows, source citations, and ribbon text. It is always a supporting element — the technical spec printed at the bottom of a poster, not the headline.

**Archivo Narrow** is the body voice. A condensed sans used for all running body copy: pillar descriptions, list item paragraphs, compare list items, stat annotations. Weight 500 for most body text; 400 for smaller captions. Never used at display sizes.

### Display Scale

| Token | Size | Family | Weight | Use |
|---|---|---|---|---|
| `{typography.display-jumbo}` | 540px | Alfa Slab One | 400 | Full-bleed oversized stat numeral |
| `{typography.display-hero}` | 260px | Alfa Slab One | 400 | Dominant closing or opening headline |
| `{typography.display-title}` | 240px | Alfa Slab One | 400 | Primary deck title |
| `{typography.display-xl}` | 180px | Alfa Slab One | 400 | Large column ordinal numeral |
| `{typography.display-lg}` | 140px | Alfa Slab One | 400 | Section headline, primary |
| `{typography.display-md}` | 120px | Alfa Slab One | 400 | Section headline, secondary |
| `{typography.display-sm}` | 108px | Alfa Slab One | 400 | Body-adjacent manifesto headline |
| `{typography.stat-unit}` | 130px | Alfa Slab One | 400 | Superscript unit symbol alongside stat |
| `{typography.quote-mark}` | 300px | Alfa Slab One | 400 | Decorative oversized quotation mark |
| `{typography.quote-body}` | 78px | Alfa Slab One | 400 | Pull quote body text |
| `{typography.kpi-value}` | 88px | Alfa Slab One | 400 | KPI or metric card value |
| `{typography.subtitle}` | 72px | Alfa Slab One | 400 | Subtitle or secondary title alongside a primary headline |
| `{typography.card-title}` | 54px | Alfa Slab One | 400 | Card or column heading |
| `{typography.section-num}` | 54px | Alfa Slab One | 400 | Section or item ordinal numeral |
| `{typography.cta}` | 48px | Alfa Slab One | 400 | CTA button label |
| `{typography.url}` | 46px | Alfa Slab One | 400 | URL or contact address |
| `{typography.item-title}` | 38px | Alfa Slab One | 400 | List item or node heading |
| `{typography.toc-entry}` | 36px | Alfa Slab One | 400 | Table of contents entry title |
| `{typography.item-title-sm}` | 30px | Alfa Slab One | 400 | Dense list item heading |
| `{typography.stamp}` | 28px | Alfa Slab One | 400 | Stamp or badge label |

### Script Scale

| Token | Size | Use |
|---|---|---|
| `{typography.script-lg}` | 96px | Prominent handwritten accent — transition word, emotional opener |
| `{typography.script-md}` | 64px | Smaller handwritten annotation — subtitle callout, sub-label |

Both script tokens are always lowercase and always applied with a rotation between -2deg and -5deg. Never use Caveat Brush without rotation.

### Body and Label Scale

| Token | Size | Family | Weight | Use |
|---|---|---|---|---|
| `{typography.body-lg}` | 30px | Archivo Narrow | 500 | Stat annotation, primary body paragraph |
| `{typography.body-md}` | 28px | Archivo Narrow | 500 | Column body, lede paragraph, compare list |
| `{typography.body-sm}` | 26px | Archivo Narrow | 500 | Supporting body paragraphs |
| `{typography.body-xs}` | 24px | Archivo Narrow | 400 | Dense list items, captions |
| `{typography.label}` | 24px | DM Mono | 400 | Standard metadata label (0.18em tracking) |
| `{typography.label-wide}` | 24px | DM Mono | 400 | Footline and ribbon text (0.22em tracking) |
| `{typography.label-accent}` | 32px | DM Mono | 600 | Highlighted metadata (e.g. section count) |
| `{typography.signoff}` | 26px | DM Mono | 400 | Footer sign-off block (0.20em tracking) |

### Typography Principles
Alfa Slab One is always uppercase — never use it in sentence case or lowercase. Line-height at display sizes is tight: 0.82–0.88 for large headlines, 1.04 only for multi-line body-adjacent text where line collision would occur. The 0.005em letter-spacing is nearly invisible but prevents glyph collision at 100px+ sizes.

The stacked text-shadow is the inline styling rule for display text: orange display type always casts `{colors.red}` as its first shadow. At sizes above 200px, add a second `{colors.red-deep}` layer at double the offset. At sizes below 100px, a single 3px–6px offset in `{colors.red}` is sufficient.

DM Mono labels are always 24px regardless of context. The tracking varies by placement: 0.18em for topbar/footer, 0.22em for ribbon and footline, 0.16em for side labels in split panels. Never reduce tracking on DM Mono — at 24px without tracking, it reads as utilitarian rather than editorial.

Archivo Narrow is always weight 400 or 500. Never use it at display sizes. It is a supporting voice, not a headline voice.

## Layout

### Canvas System
Every slide is 1920×1080px. The `deck-stage` custom element handles scaling. All content is absolutely positioned or uses CSS grid — no scrolling.

### Gutter System
- **Slide gutter** (90px left/right): The standard edge padding for most content sections.
- **Content gutter** (120px left/right): Used for body content within slides that already have a structural header — provides extra breathing room for reading text.
- **Topbar height** (90px): The fixed-height blue topbar band that sits at the absolute top of a slide.
- **Frame inset** (48px): The distance from the slide edge to the decorative inset frame border used on blue-background slides.

### Universal Chrome
The system does not enforce a universal topbar on every slide. Two chrome patterns exist:

**Topbar pattern** — A full-width 90px blue bar anchored to the top (`position:absolute; top:0; left:0; right:0`). Contains DM Mono 24px label text at 0.18em tracking. Carries a 6px solid cream bottom border. Used on high-emphasis blue-background slides.

**Section-divider pattern** — A 6px solid ink horizontal rule between a header block and the content area below. The header block uses 90px left/right padding; the content below uses 90px padding. No topbar — the rule is the dividing element.

Both patterns can coexist on a single slide or be used independently.

## Depth and Elevation

### Stacked Text-Shadow (Primary Technique)
The system's signature. Display text casts layered offset shadows in the same direction (bottom-right), creating a quasi-3D letterpress effect. Three tiers by element size:

| Tier | Offset layer 1 | Offset layer 2 | Use |
|---|---|---|---|
| Small | `3px 3px 0 {colors.red}` | — | Items below 72px |
| Medium | `5px–6px 5px–6px 0 {colors.red}` | — | 72px–140px display |
| Large | `10px 10px 0 {colors.red}, 20px 20px 0 {colors.red-deep}` | | 140px–260px display |
| Jumbo | `12px 12px 0 {colors.red}, 24px 24px 0 {colors.red-deep}` | | 260px+ stat figures |

The orange display text is the "face" layer; red is the "body"; red-deep is the "foot." The illusion is of a letterform with physical thickness.

### Box-Shadow (Secondary Technique)
Interactive and decorative elements (stamps, avatars, CTA buttons, KPI cards) use the same offset logic in box-shadow form: `6px 6px 0 {colors.red}` or `8px 8px 0 {colors.red}`. This unifies the depth system: all elements in the deck cast shadows in the same direction at the same apparent light angle.

### Grain Texture (Atmospheric Depth)
Every slide carries a `.grain::before` pseudo-element: two overlapping radial-gradient dot grids at 3px and 5px pitch, with `mix-blend-mode: multiply` and 50% opacity. This simulates screen-print halftone texture, giving the flat digital surfaces a physical, printed quality. It is not elevation but atmosphere — the entire deck reads as produced rather than rendered.

### Flat Elements
DM Mono labels, ink section rules, body text, and grid lines are completely flat. No shadows on structural dividers.

## Shapes and Treatment

### Border Radius Scale
| Value | Use |
|---|---|
| 999px (pill) | Meta label pills in topbar/header areas |
| 50% (circle) | Avatar elements, timeline milestone dots, circular stamp |
| 4px | Diamond bullet pseudo-elements (rotated 45deg to form a diamond) |
| 0px | All structural elements: columns, cards, topbars, frames, ribbons, KPI cards, stamps |

The system is almost entirely square. The only soft shapes are the pill (for metadata chips), the circle (for avatars, dots, the closing stamp), and the diamond bullet. The squareness of structural elements reinforces the printed/constructed aesthetic.

### Border Weights
- **6px solid `{colors.ink}`** — Primary structural borders: section dividers, column separators, topbar bottom edges, inset frames, KPI card borders, CTA button border.
- **6px solid `{colors.cream}`** — Inverted structural borders on blue surfaces: inset frame, topbar divider in cream-on-blue mode.
- **5px solid** — Secondary structural borders: quote stamp, compare list item treatment.
- **4px solid** — Tertiary dividers: side labels in compare panels, lede left-border.
- **3px solid `{colors.ink}`** — Fine structural lines: TOC row separators, column tags, stat source dividers, inner timeline lines.

### Decorative Elements

**Inset frame** — A 6px solid cream border at `inset: 48px` creates a second inner rectangle on blue-background slides. It reinforces the poster/placard aesthetic — the design within a design.

**Orange ribbon** — A 60px bottom-anchored strip in `{colors.orange}` with 6px ink top border and repeating DM Mono text at 0.22em tracking. Functions as a marquee footer on data slides.

**Diamond bullet** — List item marker using a `::before` pseudo-element: 24px × 24px, `background: {colors.red}`, `border-radius: 4px`, `transform: rotate(45deg)`. On blue-background lists, uses `{colors.orange}` instead. The shape sits 48px left of the text (positioned absolutely).

**Circular stamp** — A 200px circle (`{components.circular-stamp}`) rotated -9deg with 6px orange border and an 8px red box-shadow. Functions as a seal — the physical-world approval mark on a bureaucratic document.

**Rotated rectangular stamp** — A rectangular block rotated -3deg with 5px cream border and 6px red box-shadow. Contains Alfa Slab One 28px text at 0.04em tracking. Lighter rotation than the circular stamp — feels like an address label placed at a slight angle.

**Script annotation** — Caveat Brush 64–96px, lowercase, rotated 2–5 degrees. Always appears adjacent to an Alfa Slab One headline it qualifies or interrupts — never alone.

**Column ordinal** — 180px Alfa Slab One orange numeral with a 5px red text-shadow, followed by a 3px ink top-border DM Mono tag label below it. This pairing (large orange numeral + small mono tag) is the system's standard way of labelling columns or sections.

**Underline rule** — A 14px tall solid ink rectangle, width 30% of its container, used as a full-stop after a manifesto headline. It is heavier than a hairline rule — closer to a redaction bar.

**Grain overlay** — The `.grain` class adds `::before` pseudo-element texture to every slide. It cannot be removed from a slide in this system — it is structural to the aesthetic.

## Do's and Don'ts

### Do
- Apply the grain overlay (`.grain::before`) to every slide. It is not decorative — it is the surface that everything else is printed on.
- Use the stacked text-shadow on all orange and cream display text. Shadowless Alfa Slab One reads flat and loses the letterpress character.
- Scale shadow offset proportionally to font size: small offset for small type, jumbo offset for jumbo type.
- Keep red exclusively as a shadow color. The moment red appears as a text color or background fill, the depth system collapses.
- Use Caveat Brush only at large sizes (64px+), always lowercase, always slightly rotated. Never for body text.
- Keep DM Mono labels at exactly 24px with at least 0.16em letter-spacing. The monospace face at body size with normal tracking reads as code, not editorial.
- Use the 6px border weight for major structural divisions. Thinner reads as SaaS; thicker looks like a design mistake.
- When a slide uses a blue background, use the inset frame — it distinguishes blue-background slides as "framed" rather than merely filled.
- Apply `{colors.orange}` as the numerals, values, and accent text on blue surfaces. Blue-on-orange or cream-on-blue are the only other permitted text combinations on dark surfaces.

### Don't
- Don't use red as a background or primary text color. It is a shadow material, not a surface material.
- Don't use Caveat Brush at body sizes or without rotation. Flat, small handwriting reads as untidy, not intentional.
- Don't apply Alfa Slab One in mixed case. The uppercase lock is essential to the slab's authority.
- Don't soften the border weights. 1px or 2px borders on structural elements break the printed-matter aesthetic.
- Don't round card or container corners. The inset frame and KPI cards are strictly square.
- Don't use Archivo Narrow for headlines. It is a body and lede face only — it lacks the visual weight for display use.
- Don't use blue-deep or red-deep as surface colors. They are shadow-only values — their role is depth, not fill.
- Don't omit the diamond bullet rotation on list items. A 45deg-rotated square is a diamond; an upright square is a box — the shape signals hand-crafted, not generic.
- Don't vary the DM Mono font size. 24px is the single fixed size for all monospace label text — increasing it for emphasis breaks the system; use `{typography.label-accent}` (32px, weight 600) as the sole exception.

## Responsive Behavior

This template is designed exclusively for 1920×1080 presentation display. The `deck-stage` custom element handles viewport scaling via CSS transforms — the 1920×1080 canvas scales proportionally to any screen size without layout changes.

Slides advance via keyboard or presentation clicker through `deck-stage.js`. No hover states, no interactive form elements, no responsive breakpoints.

For print and PDF export: at 96dpi, the 1920×1080 canvas maps to a 20×11.25 inch frame. The grain overlay uses `mix-blend-mode: multiply` — in PDF export, blend modes may flatten; test print output and consider disabling the grain for printed formats.

## CJK & International Content

### Recommended Chinese Pairing

| Role | Latin face | Chinese face | Weight |
|---|---|---|---|
| Display / title / quote (Alfa Slab One UPPERCASE) | Alfa Slab One | Noto Serif SC (思源宋体) | 900 |
| Script interrupt (Caveat Brush lowercase rotated) | Caveat Brush | — (no good equivalent; see Aesthetic Notes) | — |
| Body (Archivo Narrow 500) | Archivo Narrow | Noto Sans SC (思源黑体) | 500 |
| Label / mono (DM Mono UPPERCASE tracked) | DM Mono | Noto Sans SC | 400 (do not force monospace on CJK) |

### Mixed-Content Strategy

Strategy A — extend each token's `fontFamily` to include the Chinese face after the Latin face. Alfa Slab tokens become `"Alfa Slab One, Noto Serif SC, serif"`; Archivo Narrow tokens become `"Archivo Narrow, Noto Sans SC, sans-serif"`; DM Mono tokens become `"DM Mono, Noto Sans SC, monospace"`. Latin glyphs render in their original face; CJK falls through to the SC fallback automatically.

### Loading

```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=Alfa+Slab+One&family=Caveat+Brush&family=Archivo+Narrow:wght@400;500;600;700&family=DM+Mono:wght@300;400;500&family=Noto+Serif+SC:wght@400;500;700;900&family=Noto+Sans+SC:wght@400;500;700;900&display=swap" rel="stylesheet">
```

### 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 (Chinese typography convention)
- Pangu spacing 盘古之白 (space between CJK and Latin: `使用 Claude` not `使用Claude`)
- One font per sentence

### Aesthetic Notes for This System

People's Platform is a WPA-poster system built on three load-bearing typefaces, and **none of the three has a clean Chinese transfer**.

**Alfa Slab One** is a compressed slab serif at extreme sizes (up to 540px) in uppercase. There is no Chinese slab serif of equivalent weight and authority available on CDN. **Noto Serif SC at weight 900** is the closest match — it carries the slab-like heaviness and the structural authority — but it reads as more "literary monument" than "protest placard." Accept this register shift: Chinese versions of this system feel closer to a heritage-era public-notice board (think 大字报 or museum signage) than to a 1930s WPA poster. The stacked red text-shadow still applies and still carries the system's letterpress depth signature.

**Caveat Brush** is the "human interrupt" voice — lowercase, rotated, emotionally warm. **This does not transfer to Chinese.** Chinese brush calligraphy (Ma Shan Zheng / 马善政) carries cultural and traditional weight — it reads as ceremonial, formal, even bureaucratic, NOT the casual personal voice of Latin Caveat. **Recommended approach: leave the brush moment out entirely on pure-CJK slides.** A second option: use a short Latin word in Caveat Brush as the interrupt even within Chinese content (e.g., a script `yes!` annotation beside a Chinese headline) — this preserves the casual interrupt energy and signals "voice break" without invoking Chinese calligraphic tradition.

**DM Mono** uppercase tracked labels do not transfer to CJK. Set Chinese metadata in **Noto Sans SC 400** with letter-spacing reset to 0 and no uppercase. Pure-Latin tags (URLs, dates, edition numbers) keep DM Mono.

**Archivo Narrow** is condensed at weight 500. **Noto Sans SC has no condensed variant.** Use Noto Sans SC 500 at the original Archivo size and accept that Chinese body type sits slightly wider than Latin body type. The single-color paper canvas and the grain overlay absorb the width difference.

The stacked text-shadow (orange → red → red-deep) is the system's most recognizable trait. **It transfers perfectly to Chinese.** Apply it to every Chinese display headline in orange and the letterpress depth survives the script switch. The blue-and-orange-and-red palette is also fully script-agnostic.

The diamond bullet marker, the rotated rubber stamp, the inset cream frame, the 6px ink borders — all work unchanged in Chinese.

### Known CJK Gap

**Caveat Brush has no acceptable Chinese equivalent.** The "human interrupt" voice is structurally absent in a pure-CJK People's Platform deck. The two workarounds (drop the interrupt entirely; use Latin-in-Chinese for the script moments) are both visible aesthetic compromises — the populist-poster system loses one of its three voices when forced into pure Chinese. Mixed-content decks (English-led with Chinese accents, or vice versa) are the strongest fit for this template.

## Iteration Guide

1. The stacked shadow is a hard invariant — any new display element in orange or cream must carry it. Determine the offset by dividing the font size by approximately 20 to get the first shadow distance, double it for the second.
2. Any new slide with a blue background gets an inset frame (6px cream, `inset: 48px`) and, if it has a header bar, that bar uses the topbar pattern with a 6px cream bottom border.
3. New columns or side-by-side panels follow the 6px ink separator convention. Asymmetric layouts (e.g. 60/40 split) are fine as long as the separator border remains 6px.
4. New KPI or data cards use the `{components.kpi-card}` pattern: 5px ink border, paper background, optional alt variant in blue. The number inside uses Alfa Slab One with the standard text-shadow.
5. New list items always use the diamond bullet (24px × 24px, 4px radius, rotate 45deg). Use red for ink-background items, orange for blue-background items.
6. If a new decorative stamp or badge is needed, use Alfa Slab One with `letter-spacing: 0.04em`, a box-shadow of `6px 6px 0 {colors.red}`, and a slight rotation (–3 to –9deg). Circular stamps get 50% border-radius; rectangular ones stay square.
7. The grain overlay is a CSS pseudo-element on the `section` element — it must be present on every new slide via the `.grain` class.
8. Script (Caveat Brush) text is an interrupt, not a default. Use it once per slide maximum, and only at 64px+.

## Known Gaps

- `deck-stage.js` is an external script dependency not documented here. Slide navigation and scaling are handled by it entirely.
- The orange ribbon on data slides is implemented with static repeated text — there is no JavaScript marquee animation. At 1920px width, the text wraps naturally; for longer strings, manually duplicate the text.
- The grain overlay uses `mix-blend-mode: multiply`. This requires a semi-transparent background or a parent with a visible fill to produce the texture effect — on pure white or pure black surfaces the effect may be invisible.
- Speaker notes are embedded as a `<script type="application/json">` block in the template — this data is presentational, not part of the design system, and is not captured in these tokens.
- Archivo Narrow is loaded as a web font. It has broad system fallback (`system-ui, sans-serif`) but the condensed width of the system font stack fallback will differ significantly from Archivo Narrow and may break layouts at tight grid configurations.
- The `text-wrap: pretty` property on quote text is a modern CSS feature with limited browser support — it may not apply in older export environments.
````

---

## 2. 글씨체

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

---

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

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

**1장(표지)에서 처음 나오는 부품**
- `.blue` — 1·6장 — 예: `<section class="slide blue grain">`
- `.cstamp` — 1·6장 — 예: `<div class="cstamp">`
- `.frame` — 1·6장 — 예: `<i class="frame">`
- `.gk` — 1장 — 예: `<em class="gk">`
- `.gl` — 1장 — 예: `<div class="mono gl">`
- `.grain` — 1·2·3·4·5·6장 — 예: `<section class="slide blue grain">`
- `.k1` — 1장 — 예: `<div class="mono k1">`
- `.mono` — 1·2·3·4·5·6장 — 예: `<div class="mono k1">`
- `.pills` — 1장 — 예: `<div class="pills">`
- `.s1` — 1장 — 예: `<p class="script s1">`
- `.script` — 1·2·5·6장 — 예: `<p class="script s1">`
- `.slide` — 1·2·3·4·5·6장 — 예: `<section class="slide blue grain">`
- `.t1` — 1장 — 예: `<h1 class="t1">`
- `.unit` — 1장 — 예: `<p class="unit">`

**2장(흐름·단계)에서 처음 나오는 부품**
- `.btns` — 2장 — 예: `<div class="btns">`
- `.cap` — 2장 — 예: `<p class="lede cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;…`
- `.cta` — 2·5·6장 — 예: `<button class="cta" data-act="step">`
- `.fig` — 2장 — 예: `<div class="kpi fig">`
- `.ft` — 2장 — 예: `<span class="mono ft">`
- `.ghost` — 2장 — 예: `<button class="cta ghost" data-act="reset">`
- `.hd` — 2·3·4·5장 — 예: `<h2 class="hd">`
- `.kick` — 2·4장 — 예: `<div class="mono kick">`
- `.kpi` — 2·3·5·6장 — 예: `<div class="kpi fig">`
- `.ldf` — 2장 — 예: `<p class="lede ldf">`
- `.lede` — 2장 — 예: `<p class="lede ldf">`
- `.num` — 2장 — 예: `<b class="num">`
- `.paper` — 2·3·4·5장 — 예: `<section class="slide paper grain" data-steps="4">`
- `.ribbon` — 2·3·5장 — 예: `<div class="ribbon mono">`
- `.row` — 2장 — 예: `<div class="row" data-s="1">`
- `.s2` — 2장 — 예: `<p class="script s2">`
- `.tg` — 2장 — 예: `<span class="mono tg">`
- `.toc` — 2장 — 예: `<div class="toc">`
- `.under` — 2·4장 — 예: `<i class="under">`

**3장(숫자와 그래프)에서 처음 나오는 부품**
- `.alt` — 3·4·5·6장 — 예: `<div class="kpi kc alt">`
- `.chart` — 3장 — 예: `<div class="chart">`
- `.col` — 3장 — 예: `<div class="col">`
- `.cv` — 3장 — 예: `<span class="cv">`
- `.dot` — 3장 — 예: `<i class="dot">`
- `.h3t` — 3·5장 — 예: `<h2 class="hd h3t">`
- `.kc` — 3장 — 예: `<div class="kpi kc">`
- `.kpis` — 3장 — 예: `<div class="kpis">`
- `.kv` — 3장 — 예: `<b class="kv">`
- `.mx` — 3장 — 예: `<div class="col mx">`
- `.plot` — 3장 — 예: `<div class="plot">`
- `.rb` — 3장 — 예: `<span class="mono rl rb">`
- `.rl` — 3장 — 예: `<span class="mono rl rb">`
- `.stem` — 3장 — 예: `<i class="stem" style="height:63%">`
- `.tm` — 3장 — 예: `<div class="vr tm">`
- `.topbar` — 3·5장 — 예: `<div class="topbar mono">`
- `.vr` — 3장 — 예: `<div class="vr tm">`

**4장(비교와 표)에서 처음 나오는 부품**
- `.cl` — 4·5장 — 예: `<span class="mono cl">`
- `.cmp` — 4장 — 예: `<div class="cmp">`
- `.dl` — 4·5·6장 — 예: `<p class="dl">`
- `.lst` — 4장 — 예: `<div class="lst">`
- `.qm` — 4장 — 예: `<b class="qm">`
- `.qt` — 4장 — 예: `<div class="qt">`
- `.rstamp` — 4·5·6장 — 예: `<span class="rstamp">`
- `.side` — 4장 — 예: `<div class="side">`
- `.tbl` — 4장 — 예: `<div class="tbl">`
- `.th` — 4장 — 예: `<div class="tr th mono">`
- `.tr` — 4장 — 예: `<div class="tr th mono">`

**5장(확인(퀴즈·빈칸))에서 처음 나오는 부품**
- `.blank` — 5장 — 예: `<button class="blank" data-blank aria-pressed="false">`
- `.blk` — 5장 — 예: `<div class="blk">`
- `.dia` — 5장 — 예: `<i class="dia">`
- `.fb` — 5장 — 예: `<p class="fb" data-fb>`
- `.nr` — 5장 — 예: `<span class="mono nr">`
- `.ok` — 5장 — 예: `<div class="rstamp ok">`
- `.opt` — 5장 — 예: `<button class="opt" data-opt="0">`
- `.opts` — 5장 — 예: `<div class="opts">`
- `.q` — 5장 — 예: `<h3 class="q">`
- `.ql` — 5장 — 예: `<span class="mono ql">`
- `.quiz` — 5장 — 예: `<div class="kpi alt quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong…`
- `.rty` — 5장 — 예: `<button class="cta sm rty" data-act="retry">`
- `.s5` — 5장 — 예: `<p class="script s5">`
- `.sm` — 5·6장 — 예: `<button class="cta sm rty" data-act="retry">`

**6장(디자인 안내(시연))에서 처음 나오는 부품**
- `.a` — 6장 — 예: `<div class="kpi d6 a">`
- `.b` — 6장 — 예: `<div class="kpi d6 b">`
- `.c` — 6장 — 예: `<div class="kpi d6 c">`
- `.cs6` — 6장 — 예: `<div class="cstamp cs6">`
- `.d6` — 6장 — 예: `<div class="kpi d6 a">`
- `.dh` — 6장 — 예: `<div class="dh">`
- `.g6` — 6장 — 예: `<div class="g6 alt">`
- `.gr6` — 6장 — 예: `<div class="gr6" id="pp-gr">`
- `.h6` — 6장 — 예: `<h2 class="h6">`
- `.k6` — 6장 — 예: `<div class="mono k6">`
- `.s6s` — 6장 — 예: `<p class="script s6s">`
- `.sh6` — 6장 — 예: `<b class="sh6" id="pp-sh">`
- `.st6` — 6장 — 예: `<div class="st6" id="pp-st">`
- `.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="peoples-platform">
<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=Alfa+Slab+One&family=Caveat+Brush&family=DM+Mono:wght@400;500&family=Archivo+Narrow:wght@400;500;600&display=swap">
<!-- 이 디자인의 공통 CSS(글씨체·색·부품 모양). 이 줄은 지우거나 바꾸지 마세요 -->
<link rel="stylesheet" href="https://k-slide.web.app/kit/v1/peoples-platform.css">
<style>
/* === 추가 부품: 새 클래스가 꼭 필요할 때만 이 줄 아래에 정의하세요(공통 CSS는 위 <link>가 이미 불러옴 — 여기에 옮겨 쓰지 않음) === */
</style>
</head>
<body>
<div class="deck-viewport">
  <main class="deck-stage" id="deckStage">
<section class="slide blue grain">
  <i class="frame"></i>
  <div class="mono k1">초등 과학 · 6학년 2학기 · 1단원 · 3~4차시</div>
  <p class="unit">계절의 변화<span>Sun, Shadow & Temperature</span></p>
  <p class="script s1">오늘의 탐구!</p>
  <div class="mono gl">학습 목표</div>
  <h1 class="t1">하루 동안 <em class="gk">태양 고도</em>,<br><em class="gk">그림자 길이</em>, <em class="gk">기온</em>의 관계</h1>
  <div class="pills"><span>00초등학교</span><span>2026</span></div>
  <div class="cstamp"><b>03</b><span>3~4차시</span></div>
</section>
<section class="slide paper grain" data-steps="4">
  <div class="mono kick">측정 준비</div><h2 class="hd">태양 고도 측정기 만들기</h2><i class="under"></i>
  <p class="script s2">직접 만들어요</p>
  <div class="kpi fig"><span class="mono ft">FIG. 01 · 태양 고도 측정기</span><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></div>
  <p class="lede ldf"><b>태양 고도</b> — 태양이 지표면과 이루는 각</p>
  <p class="lede cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quot;03 — 실 묶기&quot;,&quot;04 — 각도기 끼우기&quot;]">버튼을 눌러 순서대로 만들어 보세요</p>
  <div class="toc"><div class="row" data-s="1"><b class="num">01</b><div><h3>자 붙이기</h3><p>우드록 한쪽에 양면테이프로 자를 붙여요</p></div><span class="mono tg">준비</span></div><div class="row" data-s="2"><b class="num">02</b><div><h3>수수깡 꽂기</h3><p>수수깡을 10cm 정도 잘라 자의 '0' 위치에 수직으로 꽂아요</p></div><span class="mono tg">수직</span></div><div class="row" data-s="3"><b class="num">03</b><div><h3>실 묶기</h3><p>수수깡 끝에 실을 묶어요</p></div><span class="mono tg">실</span></div><div class="row" data-s="4"><b class="num">04</b><div><h3>각도기 끼우기</h3><p>실의 다른 끝을 각도기 가운데 구멍에 끼워요</p></div><span class="mono tg">각도</span></div></div>
  <div class="btns"><button class="cta" data-act="step">다음 단계 →</button><button class="cta ghost" data-act="reset">처음부터</button></div>
  <div class="ribbon mono"><span>막대기의 그림자와 실이 이루는 각 = 태양 고도 <b>◆</b> 태양 고도 측정기 <b>◆</b> 막대기의 그림자와 실이 이루는 각 = 태양 고도 <b>◆</b> 태양 고도 측정기 <b>◆</b> 막대기의 그림자와 실이 이루는 각 = 태양 고도 <b>◆</b> 태양 고도 측정기 <b>◆</b> 막대기의 그림자와 실이 이루는 각 = 태양 고도 <b>◆</b> 태양 고도 측정기</span></div>
</section>
<section class="slide paper grain">
  <div class="topbar mono"><span>측정 결과</span><span>계절의 변화 · 1단원 · 3~4차시</span></div>
  <h2 class="hd h3t">하루 동안 무엇이 어떻게 변할까요?</h2>
  <div class="kpis"><div class="kpi kc"><span class="mono">남중 시각</span><b class="kv">12:30</b><p>태양 고도가 가장 높아요</p></div><div class="kpi kc alt"><span class="mono">남중 방향</span><b class="kv">정남</b><p>남중할 때 태양의 위치</p></div><div class="kpi kc"><span class="mono">최고 기온</span><b class="kv">14:30</b><p>기온이 가장 높아요</p></div><div class="kpi kc alt"><span class="mono">가장 긴 그림자</span><b class="kv">9:30</b><p>그림자가 가장 길어요</p></div></div>
  <div class="chart">
    <span class="mono rl rb">태양 고도 (°)</span>
    <div class="plot"><div class="col"><span class="cv">38°</span><i class="dot"></i><i class="stem" style="height:63%"></i></div><div class="col"><span class="cv">48°</span><i class="dot"></i><i class="stem" style="height:80%"></i></div><div class="col"><span class="cv">55°</span><i class="dot"></i><i class="stem" style="height:92%"></i></div><div class="col mx"><span class="cv">57°</span><i class="dot"></i><i class="stem" style="height:95%"></i></div><div class="col"><span class="cv">54°</span><i class="dot"></i><i class="stem" style="height:90%"></i></div><div class="col"><span class="cv">47°</span><i class="dot"></i><i class="stem" style="height:78%"></i></div><div class="col"><span class="cv">37°</span><i class="dot"></i><i class="stem" 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="ribbon mono"><span>예시 값 — 태양 고도·그림자(10cm 막대)는 9월 중순 북위 36° 기준 계산, 기온은 교과서 그래프 모양을 따른 값 <b>◆</b> 예시 값 — 태양 고도·그림자(10cm 막대)는 9월 중순 북위 36° 기준 계산, 기온은 교과서 그래프 모양을 따른 값</span></div>
</section>
<section class="slide paper grain">
  <div class="mono kick">관계 정리</div><h2 class="hd">태양 고도가 바뀌면 무엇이 달라질까요?</h2><i class="under"></i>
  <div class="cmp"><div class="side"><span class="mono cl">HIGH · 높을 때</span><h3>태양 고도가 높을 때</h3><p class="dl">그림자 길이는 짧아져요</p><p class="dl">기온은 높아져요</p></div><div class="side alt"><span class="mono cl">LOW · 낮을 때</span><h3>태양 고도가 낮을 때</h3><p class="dl">그림자 길이는 길어져요</p><p class="dl">기온은 낮아져요</p></div></div>
  <div class="tbl"><div class="tr th mono"><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="qt"><b class="qm">“</b><p>태양 고도가 가장 높은 시각과 기온이 가장 높은 시각에는 차이가 있어요.</p><span class="rstamp">오늘의 정리</span></div>
  <div class="lst"><span class="mono cl">남중</span><p class="dl">태양이 정남쪽에 있을 때 '남중했다'고 해요</p><p class="dl">이때의 태양 고도를 남중 고도라고 해요</p></div>
</section>
<section class="slide paper grain">
  <div class="topbar mono"><span>확인하기</span><span>계절의 변화 · 1단원 · 3~4차시</span></div>
  <h2 class="hd h3t">배운 내용을 확인해 볼까요?</h2>
  <div class="kpi alt quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다시 생각해 볼까요? 태양 고도와 그림자 길이의 관계를 떠올려 보세요">
    <span class="mono ql">QUESTION</span>
    <h3 class="q">하루 중 그림자 길이가 가장 짧을 때는?</h3>
    <div class="opts"><button class="opt" data-opt="0"><i class="dia"></i><span>오전 9시 30분</span></button><button class="opt" data-opt="1"><i class="dia"></i><span>낮 12시 30분 무렵</span></button><button class="opt" data-opt="2"><i class="dia"></i><span>오후 3시 30분</span></button></div>
    <p class="fb" data-fb></p>
    <button class="cta sm rty" data-act="retry">다시 풀기 ↺</button>
    <div class="rstamp ok">정답!</div>
    <p class="script s5">참 잘했어요</p>
  </div>
  <div class="blk">
    <span class="mono cl">빈칸을 눌러 확인해요</span>
    <p class="dl"><span><button class="blank" data-blank aria-pressed="false"><span>태양 고도</span></button>는 점점 높아졌다가 다시 낮아진다</span></p><p class="dl"><span><button class="blank" data-blank aria-pressed="false"><span>그림자 길이</span></button>는 점점 짧아졌다가 다시 길어진다</span></p><p class="dl"><span><button class="blank" data-blank aria-pressed="false"><span>기온</span></button>은 점점 높아졌다가 다시 낮아진다</span></p>
    <span class="mono nr">빈칸 규칙 없음 → 작은 CTA 단추으로 표현</span>
  </div>
  <div class="ribbon mono"><span>오늘의 낱말 <b>◆</b> 태양 고도 <b>◆</b> 남중 고도 <b>◆</b> 그림자 길이 <b>◆</b> 기온 <b>◆</b> 오늘의 낱말 <b>◆</b> 태양 고도 <b>◆</b> 남중 고도 <b>◆</b> 그림자 길이 <b>◆</b> 기온</span></div>
</section>
<section class="slide blue grain">
  <i class="frame"></i>
  <div class="mono k6">디자인 안내 · 1단원 · 3~4차시</div>
  <h2 class="h6">이 디자인 사용 설명서</h2>
  <p class="script s6s">이렇게 써요!</p>
  <div class="g6 alt">
    <p class="dl"><b>한눈에</b> — WPA 포스터 + 선거 캠페인. <b>코발트 파랑과 종이</b> 면에 주황은 숫자·에너지, 빨강은 그림자로만 써요.</p>
    <p class="dl"><b>색</b> — <span class="sw6"><span><i style="background:#2C2CDC"></i>코발트 파랑</span><span><i style="background:#F2A03A"></i>주황</span><span><i style="background:#E83A2A"></i>빨강(그림자만)</span><span><i style="background:#F4E9D6"></i>크림</span><span><i style="background:#0E0E14"></i>잉크</span></span></p>
    <p class="dl"><b>글꼴</b> — 제목 Alfa Slab One → Hahmlet Black · 본문 Archivo Narrow → Cafe24 PRO Slim Air · 손글씨 Caveat Brush → 갈맷글</p>
    <p class="dl"><b>이렇게 쓰면 좋아요</b> — 캠페인·선언·모둠 구호처럼 크게 외치는 수업. 손글씨는 한 장에 한 번, 기울여서.</p>
  </div>
  <div class="kpi d6 a"><div class="dh"><h3>겹친 글자 그림자</h3><button class="cta sm" data-demo="#pp-sh" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>주황 글자 → 빨강 → 짙은 빨강을 같은 방향으로 겹쳐 찍어요.</p><b class="sh6" id="pp-sh">57°</b></div>
  <div class="kpi d6 b"><div class="dh"><h3>도장 두 가지</h3><button class="cta sm" data-demo="#pp-st" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>원형 도장 -9°(주황 테두리) · 사각 도장 -3°(크림 테두리) — 빨강 그림자.</p><div class="st6" id="pp-st"><div class="cstamp cs6"><b>03</b><span>차시</span></div><span class="rstamp">정답!</span></div></div>
  <div class="kpi d6 c"><div class="dh"><h3>망점 질감</h3><button class="cta sm" data-demo="#pp-gr" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>모든 장 위에 3px·5px 점을 곱하기로 깔아 인쇄물처럼 — 시연은 진하게.</p><div class="gr6" id="pp-gr"><b>PRINT</b></div></div>
</section>
<nav class="dk-nav"><span class="dk-count" data-pad></span><button class="dk-prev" aria-label="이전">←</button><button class="dk-next" aria-label="다음">→</button></nav>
  </main>
</div>

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

---

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

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

```css
/* peoples-platform — k-slide 공통 CSS v1 (채팅 AI용 받기 .md가 불러옴, 고치지 말 것) */
/* === KOREAN FONTS === */
@font-face{font-family:'kp-30';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/hahmlet/Hahmlet-Black.woff2") format("woff2");font-weight:900}
@font-face{font-family:'kp-31';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/cafe24-pro-slim/Cafe24PROSlim-Air.woff2") format("woff2");font-weight:400}
@font-face{font-family:'kp-32';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/galmat/Galmetgol.woff2") format("woff2");font-weight:400}
/* === THEME === */
:root{--stage-bg:#F5F2EA;--slide-bg:#F5F2EA;
  --kt:'kp-30';--kb:'kp-31';--ka:'kp-32';
  --wt:900;--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 === */

/* --- 토큰 --- */
:root{--blue:#2C2CDC;--bdeep:#1B1BB0;--orange:#F2A03A;--red:#E83A2A;--rdeep:#B7281C;--cream:#F4E9D6;--paper:#F5F2EA;--ink:#0E0E14}
.slide{color:var(--ink);font-family:'Archivo Narrow',var(--kb),sans-serif;font-weight:500}
.paper{background:var(--paper)}.blue{background:var(--blue);color:var(--cream)}
.slide>*{position:absolute}
.grain::before{content:'';position:absolute;inset:0;pointer-events:none;z-index:40;background-image:radial-gradient(rgba(0,0,0,.06) 1px,transparent 1px),radial-gradient(rgba(255,255,255,.05) 1px,transparent 1px);background-size:3px 3px,5px 5px;background-position:0 0,1px 2px;mix-blend-mode:multiply;opacity:.5}
.mono{font-family:'DM Mono',var(--kb),monospace;font-weight:400;font-size:24px;letter-spacing:.18em;text-transform:uppercase}
.script{font-family:'Caveat Brush',var(--ka),cursive;font-weight:400;text-transform:lowercase}
h1,h2,h3,.unit,.kv,.qt p,.cta,.rstamp,.cstamp span{font-family:'Alfa Slab One',var(--kt),serif;font-weight:var(--wt);letter-spacing:.005em}
.lede{font-size:30px;line-height:1.4;padding-left:46px;border-left:4px solid var(--ink)}
.cta{background:var(--orange);color:var(--ink);border:6px solid var(--ink);box-shadow:6px 6px 0 var(--red);padding:12px 30px;font-size:36px;letter-spacing:.02em}
.cta.ghost{background:var(--paper)}
.cta:disabled{opacity:.35;box-shadow:none}
.kpi{border:5px solid var(--ink);background:var(--paper);padding:28px 30px}
.kpi.alt{background:var(--blue);color:var(--cream)}
.dl{position:relative;padding-left:52px;font-size:30px;line-height:1.45}
.dl::before{content:'';position:absolute;left:4px;top:.5em;width:24px;height:24px;background:var(--red);border-radius:4px;transform:rotate(45deg)}
.alt .dl::before{background:var(--orange)}
.cl{display:inline-block;align-self:flex-start;padding-bottom:14px;border-bottom:4px solid currentColor;letter-spacing:.22em}
.rstamp{background:var(--blue);color:var(--orange);border:5px solid var(--cream);box-shadow:6px 6px 0 var(--red);padding:14px 30px;font-size:30px;letter-spacing:.04em;transform:rotate(-3deg);display:inline-block}

/* --- 상단 머리(종이 장): 모노 킥커 + 파랑 제목(빨강 그림자) + 14px 먹선 / 상단 바(파랑) --- */
.kick{left:90px;top:64px;font-size:26px;letter-spacing:.22em;color:var(--blue)}
.hd{left:90px;top:104px;font-size:84px;line-height:1.1;color:var(--blue);text-shadow:5px 5px 0 var(--red);white-space:nowrap}
.under{left:90px;top:214px;width:30%;height:14px;background:var(--ink)}
.topbar{left:0;right:0;top:0;height:90px;background:var(--blue);color:var(--cream);border-bottom:6px solid var(--cream);box-shadow:0 6px 0 var(--ink);display:flex;justify-content:space-between;align-items:center;padding:0 90px}
.h3t{top:126px}

/* --- 리본(주황, 6px 잉크 윗선) --- */
.ribbon{left:0;right:0;bottom:0;height:60px;background:var(--orange);color:var(--blue);border-top:6px solid var(--ink);font-weight:500;letter-spacing:.22em;white-space:nowrap;overflow:hidden;display:flex;align-items:center}
.ribbon span{padding-left:90px;font-size:24px}
.ribbon b{font-weight:400;color:var(--ink);margin:0 14px}

/* --- 1. 표지(파랑): 크림 안쪽 틀 + 단원 + 손글씨 + 학습 목표 h1(크림, 핵심 낱말 = 주황, 겹 그림자) + 알약 + 원형 도장 --- */
.frame{inset:48px;border:6px solid var(--cream);pointer-events:none}
.k1{left:120px;top:110px;color:var(--orange)}
.unit{left:116px;top:166px;display:flex;align-items:baseline;gap:30px;font-size:84px;line-height:1.1;color:var(--cream);text-shadow:5px 5px 0 var(--red);white-space:nowrap}
.unit span{font:400 50px/1 'Alfa Slab One',serif;text-transform:uppercase;color:var(--cream);opacity:.8;text-shadow:none}
.s1{left:1290px;top:282px;font-size:96px;color:var(--orange);transform:rotate(-5deg)}
.gl{left:120px;top:340px;color:var(--orange);padding-bottom:12px;border-bottom:3px solid var(--orange)}
.t1{left:112px;top:404px;font-size:124px;line-height:1.22;color:var(--cream);text-shadow:6px 6px 0 var(--red);white-space:nowrap}
.t1 .gk{font-style:normal;color:var(--orange);text-shadow:8px 8px 0 var(--red),16px 16px 0 var(--rdeep)}
.pills{left:120px;top:840px;display:flex;gap:16px}
.pills span{border:3px solid var(--cream);border-radius:999px;padding:8px 24px;font:400 26px/1.2 'DM Mono',var(--kb),monospace;letter-spacing:.16em}
.cstamp{right:150px;top:700px;width:230px;height:230px;border-radius:50%;background:var(--cream);color:var(--blue);border:6px solid var(--orange);box-shadow:8px 8px 0 var(--red);transform:rotate(-9deg);display:grid;place-items:center;align-content:center;text-align:center}
.cstamp b{font:400 104px/.9 'Alfa Slab One',serif}
.cstamp span{margin-top:6px;font-size:30px;letter-spacing:.04em}

/* --- 2. 만들기(종이): 머리 + 손글씨 | KPI 카드 속 측정기 그림 + 리드 정의 | 목차 줄 4개(주황 번호, 켜지면 또렷 · 지금 = 다이아몬드) + CTA | 리본(메모) --- */
.s2{left:1260px;top:100px;font-size:72px;color:var(--orange);transform:rotate(-4deg)}
.fig{left:90px;top:262px;width:860px;padding:18px 30px 6px;
  --g-ink:var(--ink);--g-acc:var(--blue);--g-stick:var(--orange);--g-board:var(--cream);--g-ruler:var(--paper);--g-prot:rgba(44,44,220,.06);--g-shadow:rgba(14,14,20,.35);--g-font:'Archivo Narrow',var(--kb),sans-serif;--g-sw:3}
.ft{display:block;font-size:22px;color:var(--blue)}
.fig .gauge{width:740px;display:block;margin:0 auto}
.ldf{left:90px;width:860px;top:880px;font-size:28px}
.ldf b{color:var(--blue)}
.cap{left:1020px;right:90px;top:262px;font-size:28px;padding-left:30px}
.toc{left:1020px;right:90px;top:320px;border-top:6px solid var(--ink)}
.row{display:grid;grid-template-columns:90px 1fr 100px;gap:20px;align-items:center;padding:14px 0;border-bottom:3px solid var(--ink)}
.num{font:400 52px/1 'Alfa Slab One',serif;color:var(--orange);text-shadow:3px 3px 0 var(--red)}
.row h3{font-size:38px;line-height:1.1;color:var(--blue)}
.row p{margin-top:6px;font-size:25px;line-height:1.35}
.tg{justify-self:end;font-size:22px;letter-spacing:.16em}
.slide[data-step]:not([data-step="0"]) .row:not(.on){opacity:.3}
.row.now .tg{position:relative;padding-left:40px}
.row.now .tg::before{content:'';position:absolute;left:0;top:50%;width:22px;height:22px;margin-top:-11px;background:var(--red);border-radius:4px;transform:rotate(45deg)}
.btns{left:1020px;top:900px;display:flex;gap:26px}

/* --- 3. 숫자와 그래프(종이 + 상단 바): KPI 카드 4개(주황 숫자 + 빨강 그림자) + 14px 잉크 기둥·타임라인 점(가장 높은 값 = 파랑 점) | 리본(출처) --- */
.kpis{left:90px;right:90px;top:252px;display:grid;grid-template-columns:repeat(4,1fr);gap:30px}
.kc{display:flex;flex-direction:column;padding:20px 26px}
.kv{margin-top:8px;font-size:72px;line-height:1;color:var(--orange);text-shadow:4px 4px 0 var(--red)}
.kc p{margin-top:8px;font-size:25px;line-height:1.3}
.chart{left:90px;right:90px;top:470px;display:grid;grid-template-columns:250px 1fr;column-gap:20px}
.plot{height:290px;display:grid;grid-template-columns:repeat(7,1fr);border-bottom:6px solid var(--ink)}
.col{position:relative;display:flex;flex-direction:column;justify-content:flex-end;align-items:center}
.stem{display:block;width:14px;background:var(--ink)}
.dot{display:block;width:44px;height:44px;margin-bottom:-14px;position:relative;z-index:1;border-radius:50%;background:var(--orange);border:6px solid var(--ink);box-shadow:5px 5px 0 var(--red)}
.col.mx .dot{background:var(--blue)}
.cv{margin-bottom:8px;font:400 30px/1 'Alfa Slab One',serif;color:var(--blue)}
.col.mx .cv{color:var(--orange);text-shadow:3px 3px 0 var(--red)}
.rl{align-self:center;font-size:20px;letter-spacing:.14em;padding:6px 0}
.rb{align-self:end;padding-bottom:12px}
.vr{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;border-bottom:3px solid var(--ink);padding:8px 0;font-size:28px}
.vr.tm{font:400 28px/1.2 'Alfa Slab One',serif;color:var(--blue)}

/* --- 4. 비교와 표(종이): 머리 | 비교 두 면(종이 | 파랑, 6px 잉크 구분, 다이아몬드) + 목차 줄 표 | 따옴표 인용 + 사각 도장 + 남중 다이아몬드 --- */
.cmp{left:0;width:1240px;top:262px;height:360px;display:grid;grid-template-columns:1fr 1fr;border-top:6px solid var(--ink);border-bottom:6px solid var(--ink);border-right:6px solid var(--ink)}
.side{padding:30px 50px 26px 90px;display:flex;flex-direction:column;gap:12px;border-right:6px solid var(--ink)}
.side.alt{background:var(--blue);color:var(--cream);border-right:0;padding-left:50px}
.side h3{margin:6px 0 4px;font-size:46px;line-height:1.1}
.side:not(.alt) h3{color:var(--blue)}
.tbl{left:90px;width:1100px;top:660px}
.tr{display:grid;grid-template-columns:1.2fr 1fr 1fr 1fr;gap:20px;align-items:center;padding:14px 0;border-bottom:3px solid var(--ink);font-size:29px}
.tr.th{font-size:22px;letter-spacing:.16em;padding:10px 0;border-bottom:6px solid var(--ink)}
.tr:not(.th) span:first-child{font-family:'Alfa Slab One',var(--kt),serif;font-weight:var(--wt);color:var(--blue)}
.qt{left:1310px;right:90px;top:250px}
.qm{display:block;height:120px;font:400 220px/.9 'Alfa Slab One',serif;color:var(--orange);text-shadow:8px 8px 0 var(--red)}
.qt p{font-size:46px;line-height:1.25;color:var(--blue)}
.qt .rstamp{margin-top:26px;font-size:26px}
.lst{left:1310px;right:90px;top:690px;display:flex;flex-direction:column;gap:14px}
.lst .dl{font-size:28px}

/* --- 5. 확인하기(종이 + 상단 바): 파랑 KPI 카드 퀴즈(주황 다이아몬드, 정답 = 주황 + 사각 도장 + 손글씨) | 다이아몬드 빈칸(작은 CTA 단추) | 리본(낱말) --- */
.quiz{left:90px;width:1000px;top:250px;bottom:110px;display:flex;flex-direction:column;padding:30px 44px}
.ql{color:var(--orange)}
.q{margin-top:14px;font-size:56px;line-height:1.15;color:var(--cream);text-shadow:4px 4px 0 var(--red)}
.opts{margin-top:24px;border-top:3px solid var(--cream)}
.opt{width:100%;display:flex;align-items:center;gap:30px;text-align:left;padding:14px 8px;border-bottom:3px solid rgba(244,233,214,.35);font-size:36px;font-weight:600;color:var(--cream)}
.dia{flex:none;width:24px;height:24px;background:var(--orange);border-radius:4px;transform:rotate(45deg);margin-left:8px}
.opt.right{color:var(--orange)}
.opt.wrong span{text-decoration:line-through;text-decoration-thickness:3px;opacity:.6}
.opt:disabled:not(.right){opacity:.45}
.fb{margin-top:14px;min-height:80px;font-size:28px;line-height:1.4}
.cta.sm{font-size:26px;padding:8px 22px;border-width:4px;box-shadow:4px 4px 0 var(--red)}
.rty{align-self:flex-start;margin-top:auto}
.ok{position:absolute;right:-26px;top:-30px;font-size:38px;visibility:hidden}
.s5{position:absolute;right:40px;bottom:30px;font-size:76px;color:var(--orange);transform:rotate(-4deg);visibility:hidden}
.quiz.solved .ok,.quiz.solved .s5{visibility:visible}
.blk{left:1160px;right:90px;top:262px;bottom:110px;display:flex;flex-direction:column;gap:24px}
.blk .cl{color:var(--blue)}
.blk .dl{font-size:31px;line-height:1.7}
.blank{position:relative;min-width:180px;margin-right:12px;padding:2px 14px;background:var(--orange);border:4px solid var(--ink);box-shadow:4px 4px 0 var(--red);font:400 28px/1.3 'Alfa Slab One',var(--kt),serif;color:var(--ink);text-align:center}
.blank span{visibility:hidden}
.blank::after{content:'?';position:absolute;left:0;right:0;top:2px}
.blank.open{background:var(--paper)}
.blank.open span{visibility:visible}
.blank.open::after{content:none}
.nr{margin-top:auto;font-size:19px;letter-spacing:.12em;opacity:.7;text-transform:none}

/* --- 내비: 오른쪽 아래 DM Mono 번호 + 사각 화살표(4px 잉크) — 리본 위에 얹음 --- */
.dk-nav{position:absolute;right:24px;bottom:5px;display:flex;align-items:center;gap:10px;z-index:50}
.dk-count{font:400 24px/1 'DM Mono',monospace;letter-spacing:.18em;margin-right:8px;color:var(--ink)}
[data-slide="1"] .dk-count{color:var(--cream)}
[data-slide="2"] .dk-nav,[data-slide="3"] .dk-nav,[data-slide="5"] .dk-nav{bottom:0;height:54px;padding:0 24px;right:0;background:var(--orange);border-left:6px solid var(--ink)}
.dk-prev,.dk-next{width:46px;height:46px;background:var(--paper);border:4px solid var(--ink);font:400 22px/1 'Alfa Slab One',serif;color:var(--ink)}
.dk-prev:disabled,.dk-next:disabled{opacity:.35}
/* --- 6. 디자인 안내(파랑): 다이아몬드 글머리 설명 | KPI 카드 시연 3개 --- */
.k6{left:120px;top:100px;color:var(--orange)}
.h6{left:116px;top:146px;font-size:84px;line-height:1.1;color:var(--cream);text-shadow:5px 5px 0 var(--red);white-space:nowrap}
.s6s{left:1000px;top:120px;font-size:64px;color:var(--orange);transform:rotate(-4deg)}
.g6{left:120px;width:860px;top:310px;display:flex;flex-direction:column;gap:34px}
.g6 .dl{font-size:31px;line-height:1.55;color:var(--cream)}
.g6 b{color:var(--orange);font-weight:600}
.sw6{display:inline-flex;flex-wrap:wrap;gap:4px 18px}
.sw6 i{display:inline-block;width:24px;height:24px;margin-right:8px;vertical-align:-5px;border:2px solid var(--ink)}
.d6{left:1040px;right:110px;height:224px;padding:16px 26px;color:var(--ink)}
.d6.a{top:250px}.d6.b{top:494px}.d6.c{top:738px;height:190px}
.d6 .dh{display:flex;justify-content:space-between;align-items:center;gap:16px}
.d6 h3{font-size:32px;color:var(--blue)}
.d6 p{margin-top:2px;font-size:21px;line-height:1.4}
.cta.sm{font-size:18px;padding:4px 14px;border-width:3px;box-shadow:3px 3px 0 var(--red)}
.cta.sm[aria-pressed="true"]{background:var(--paper)}
.sh6{display:block;margin-top:4px;font:400 84px/1 'Alfa Slab One',serif;color:var(--orange)}
.sh6.play{text-shadow:8px 8px 0 var(--red),16px 16px 0 var(--rdeep)}
.st6{position:relative;margin-top:8px;height:100px;display:flex;align-items:center;gap:40px;padding-left:10px}
.st6>*{visibility:hidden}
.st6.play>*{visibility:visible}
.cs6{position:static;width:96px;height:96px;border-width:4px;box-shadow:5px 5px 0 var(--red)}
.cs6 b{font-size:40px}.cs6 span{font-size:16px}
.st6 .rstamp{font-size:28px}
.gr6{position:relative;margin-top:8px;height:64px;display:flex;align-items:center;padding:0 20px;background:var(--orange);border:3px solid var(--ink)}
.gr6 b{font:400 40px 'Alfa Slab One',serif;color:var(--ink)}
.gr6.play::after{content:'';position:absolute;inset:0;background-image:radial-gradient(rgba(0,0,0,.35) 1px,transparent 1px),radial-gradient(rgba(255,255,255,.25) 1px,transparent 1px);background-size:3px 3px,5px 5px;background-position:0 0,1px 2px;mix-blend-mode:multiply}
[data-slide="6"] .dk-count{color:var(--cream)}

/* === 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을 만드세요.)
