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

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

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

## 라이선스

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

- Elice DigitalBaeum Bold: Elice DigitalBaeum — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright (c) 2016-2021 elice. All rights reserved.
  파일: EliceDigitalBaeum_Bold.ttf
- Paperlogy 4Regular: Paperlogy — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright © 2024 PT&
  파일: Paperlogy-4Regular.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/playful.css">`(head 안)와 `<script src="https://k-slide.web.app/kit/v1/playful.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. **글씨체는 바꾸지 마세요.** 한글 글씨체(제목 Elice DigitalBaeum Bold(700) · 본문 Paperlogy 4Regular(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. 디자인 규칙 (`playful` design.md)

````markdown
---
version: alpha
name: Playful
description: "A warm, hand-crafted editorial system built on a peach-clay canvas with charcoal ink as the only \"color.\" Display type runs in Syne (weight 700–800, tight negative tracking); body type runs in Space Grotesk at weight 400–500. The aesthetic borrows from independent studio decks, risograph zines, and sketchbook spreads: organic blob frames, scribbled SVG doodles, slightly rotated cards, and double-stroke offset borders give every slide a hand-touched, unpolished warmth. The effect is creative-studio editorial, not corporate pitch — confident but human, structured but loose."

colors:
  bg: "#F0C8A0"
  bg-alt: "#E8B88E"
  light: "#F7DEC6"
  text: "#1A1A1A"

color-aliases:
  accent: text

typography:
  display-hero:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(4rem, 10vw, 9rem)"
    fontWeight: 800
    lineHeight: 0.9
    letterSpacing: -0.03em
  display:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(3rem, 8vw, 7rem)"
    fontWeight: 800
    lineHeight: 0.9
    letterSpacing: -0.02em
  headline:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(2.5rem, 6vw, 5rem)"
    fontWeight: 700
    lineHeight: 1.0
    letterSpacing: -0.01em
  statement:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(2.5rem, 5vw, 4.5rem)"
    fontWeight: 700
    lineHeight: 1.1
    letterSpacing: -0.01em
  title:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(2rem, 4vw, 3.5rem)"
    fontWeight: 700
    lineHeight: 1.1
    letterSpacing: -0.01em
  title-sm:
    fontFamily: "Syne, sans-serif"
    fontSize: "1.3rem"
    fontWeight: 700
    lineHeight: 1.2
  number-hero:
    fontFamily: "Syne, sans-serif"
    fontSize: "clamp(4rem, 8vw, 7rem)"
    fontWeight: 800
    lineHeight: 1.0
  number-md:
    fontFamily: "Syne, sans-serif"
    fontSize: "2.5rem"
    fontWeight: 800
    lineHeight: 1.0
  number-sm:
    fontFamily: "Syne, sans-serif"
    fontSize: "2rem"
    fontWeight: 800
    lineHeight: 1.0
  body:
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "clamp(1rem, 1.2vw, 1.1rem)"
    fontWeight: 400
    lineHeight: 1.7
  body-md:
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "1.2rem"
    fontWeight: 500
    lineHeight: 1.6
  label-eyebrow:
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "0.85rem"
    fontWeight: 600
    lineHeight: 1.2
    letterSpacing: 0.15em
    textTransform: uppercase
  caption:
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "0.85rem"
    fontWeight: 500
    lineHeight: 1.4
  tag:
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "0.75rem"
    fontWeight: 600
    lineHeight: 1.2

spacing:
  pad-slide-lg: "4rem 5rem"
  pad-slide-md: "3rem 4rem"
  pad-card-lg: "2rem 3rem"
  pad-card-md: "1.5rem"
  gap-lg: "3rem"
  gap-md: "2rem"
  gap-sm: "1.5rem"

canvas:
  width: 100vw
  height: 100vh

components:
  rough-box:
    border: "3px solid {colors.text}"
    background: "{colors.bg}"
    padding: "1.5rem"
    offsetShadowOffset: "6px 6px"
    offsetShadowBorder: "2–3px solid {colors.text}"
    description: "Generic content card with a double-stroke effect — the inner box has a 3px solid border, and an absolutely-positioned ::before pseudo-element offsets a second 2–3px border down-and-right by 6–8px to simulate a hand-drawn double outline. No fill on the offset; the canvas shows through."
  filled-block:
    background: "{colors.text}"
    color: "{colors.bg}"
    padding: "1.5rem"
    description: "Inverted card: dark charcoal background with peach text. Used as the visual counterpoint to outlined cards in a collage of mixed treatments."
  blob-frame-organic:
    border: "3px solid {colors.text}"
    borderRadius: "40% 60% 70% 30% / 40% 50% 60% 50%"
    description: "Organic outlined blob, asymmetric border-radius. Decorative wrapper that holds a smaller solid filled-blob inside it."
  blob-frame-pebble:
    border: "3px solid {colors.text}"
    borderRadius: "255px 15px 225px 15px / 15px 225px 15px 255px"
    description: "Pebble-shaped frame with extreme alternating border-radius — two opposing corners pulled long, the other two pinched short. Reads as a hand-drawn lozenge."
  blob-fill:
    background: "{colors.text}"
    borderRadius: "60% 40% 30% 70% / 60% 30% 70% 40%"
    description: "Solid dark blob with asymmetric organic radius. Used inside an outlined blob-frame or floating on its own as decorative mass."
  scribble-svg:
    stroke: "{colors.text}"
    strokeWidth: 2
    fill: none
    strokeLinecap: round
    description: "Inline SVG path drawn as a single hand-drawn line — wavy stub, scribbled circle, star outline, squiggle, arrow. Always 2px stroke, rounded caps. Placed absolutely in corners and edges as decorative breath."
  doodle-circle:
    border: "3px solid {colors.text}"
    borderRadius: "50%"
    description: "Plain round outlined circle used as a decorative anchor in slide corners."
  doodle-rect:
    border: "3px solid {colors.text}"
    rotation: "5–10deg"
    description: "Plain outlined rectangle, slightly rotated, used as a decorative anchor in slide corners."
  card-rotated:
    transform: "rotate(-3deg to 3deg)"
    description: "Any card or block can carry a small ±3deg rotation. Rotations stagger so adjacent cards rotate in opposite directions — never all in the same direction, never more than 3deg."
  step-node-circle:
    width: 64px
    height: 64px
    border: "3px solid {colors.text}"
    borderRadius: "50%"
    background: "{colors.bg}"
    fontFamily: "Syne, sans-serif"
    fontSize: 1.5rem
    fontWeight: 800
    description: "Round outlined node containing a single numeric digit at display weight. Used as a timeline or process marker; alternates between outlined (bg fill) and filled (charcoal fill, bg text)."
  avatar-placeholder:
    width: 60px
    height: 60px
    background: "{colors.text}"
    borderRadius: "50%"
    description: "Solid dark circle used as a portrait stand-in inside a team or people card."
  tag-pill:
    background: "{colors.text}"
    color: "{colors.bg}"
    padding: "0.4rem 0.8rem"
    fontFamily: "Space Grotesk, sans-serif"
    fontSize: "0.75rem"
    fontWeight: 600
    description: "Small charcoal pill with peach text, anchored to the bottom-left of an image frame as a category label."
  bar-chart:
    barFillSolid: "{colors.text}"
    barFillOutlined: "3px solid {colors.text} + transparent"
    axisStroke: "3px solid {colors.text}"
    description: "Custom HTML bar chart. Bars are either solid charcoal (primary series) or outlined transparent (secondary series). Axes are 3px solid charcoal lines, no grid."
  vertical-text:
    fontFamily: "Syne, sans-serif"
    fontWeight: 700
    letterSpacing: 0.1em
    transform: "rotate(90deg)"
    description: "Display-weight text rotated 90deg, anchored to a slide edge as a magazine-style spine label."
  ghost-blob:
    background: "{colors.text}"
    borderRadius: "40% 60% 70% 30% / 40% 50% 60% 50%"
    opacity: 0.08
    description: "Oversized organic blob at very low opacity placed behind content as atmospheric wallpaper. Functions like a watermark cloud."
---

## 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

Playful is a **hand-crafted editorial system** anchored by a single warm canvas — a peach-clay `{colors.bg}` (#F0C8A0) — with charcoal `{colors.text}` (#1A1A1A) as the only meaningful "color." Everything reads as ink-on-clay-paper. There are no secondary brand colors, no gradients, no chromatic accents. The system commits fully to a one-color discipline and finds its expressiveness in shape, weight, rotation, and hand-drawn marks rather than in palette variety.

The typeface stack is **Syne for display, Space Grotesk for body**. Syne is the personality — a high-contrast display sans with quirky humanist proportions that reads as a contemporary independent studio voice, not a corporate sans. It is used at weights 700 and 800 with tight negative letter-spacing (-0.01em to -0.03em) for every headline, statement, statistic, and number. Space Grotesk is the workhorse — a steady, neutral geometric sans at weight 400–500 for body and 500–600 for labels. The pairing reads as "expressive editorial built on a reliable grid."

The color philosophy is **monochrome warmth**: a single ink color on a single warm surface, plus two tonal siblings of the canvas (`{colors.bg-alt}` slightly darker for image placeholders, `{colors.light}` slightly lighter for gentle layering). The peach is saturated enough to read as a deliberate aesthetic choice, not a neutral. The ink is slightly softened from pure black (#1A1A1A) to sit comfortably on the warm paper. The system's emotional register is "studio sketchbook" — confident but warm, structured but unpolished.

Depth is **double-stroke offset borders** and **hand-drawn marks**, not blurred shadows. The signature treatment: a 3px charcoal border on a card, plus a `::before` pseudo-element offset down-and-right by 6–8px carrying a second 2–3px border — the visual effect is a hand-drawn double outline that suggests imperfect tracing. Combined with small rotations (±0.5deg to ±3deg on cards) and scribbled SVG paths placed in slide corners, the system reads as crafted-by-hand rather than rendered-by-software.

**Density philosophy: medium-low.** Each slide is anchored by a single dominant element — a statement, a chart, a roster — surrounded by deliberate breathing room and one or two decorative scribbles. Crowding the canvas with simultaneous cards, doodles, and copy collapses the hand-touched feeling into clutter. The correct density is one substantive moment per slide with one or two SVG scribbles or organic blobs serving as visual punctuation in the negative space.

**Key Characteristics:**
- Peach-clay canvas (`{colors.bg}`) with charcoal ink (`{colors.text}`) as the only color. No secondary brand palette.
- Syne at weight 700–800 with negative letter-spacing for every display and numeric moment; Space Grotesk at 400–500 for body.
- Double-stroke offset borders on cards — a 3px outline plus a 6–8px offset ghost border via `::before`.
- Small ±0.5deg to ±3deg rotations on cards, blocks, and statistics for a hand-placed feel.
- Organic blob shapes with asymmetric border-radius act as decorative frames and fills.
- Inline 2px-stroke SVG scribbles (squiggles, stars, circles, arrows) live in slide corners as hand-drawn punctuation.
- No web shadows. Depth comes from double borders, rotation, and ink-density contrast.
- One dominant element per slide with generous negative space — never wall-to-wall content.

## Colors

### Palette
- **Background** (`{colors.bg}` — #F0C8A0): The peach-clay canvas. The default surface for every slide. Saturated enough to be the system's signature; warm enough that charcoal ink reads softly rather than starkly.
- **Background Alt** (`{colors.bg-alt}` — #E8B88E): A slightly darker tonal sibling of the canvas. Used as a fill for image placeholder regions and for subtle surface differentiation when one card needs to read as "behind" another without committing to a new color.
- **Light** (`{colors.light}` — #F7DEC6): A slightly lighter tonal sibling of the canvas. Available for gentle layering when a region needs to lift off the background by a single tonal step without introducing white.
- **Text/Ink** (`{colors.text}` — #1A1A1A): Charcoal ink — the single non-canvas color in the system. Softened from pure black so it sits as warm ink on warm paper. Used for all body text, all display text, all borders, all SVG strokes, all filled blocks, all dark fills.

The `accent` alias resolves to `{colors.text}` — the system has no separate accent color. The "accent" in Playful is contrast against the canvas, not a third hue.

### Defaults
- **Default surface background**: `{colors.bg}` — every slide opens on peach-clay.
- **Default headline color**: `{colors.text}` — always. Headlines are never tinted or recolored.
- **Default body text color**: `{colors.text}` — sometimes at opacity 0.7–0.9 for de-emphasis, but the underlying color remains charcoal.
- **Default border color**: `{colors.text}` — every outlined card, blob, doodle, and chart axis is charcoal.
- **Default text color on filled charcoal blocks**: `{colors.bg}` — peach text on dark surfaces is the only color inversion.
- **Default image-placeholder fill**: `{colors.bg-alt}` — slightly darker than the canvas so the placeholder reads as a distinct region without using white.
- **Default decorative-blob fill**: `{colors.text}` at full opacity (foreground) or at 0.08 opacity (atmospheric ghost-blob behind content).

The system has no concept of "primary vs secondary color." Every visual decision is a binary between canvas (peach) and ink (charcoal), modulated by opacity, scale, and shape.

## Typography

### Font Family
The system pairs two carefully chosen Google Fonts:

- **Syne** (display): A contemporary humanist display sans with quirky letterforms, narrow apertures, and slightly compressed proportions. Used at weight 700 and 800 for every display moment — headlines, statements, titles, numerals, vertical labels. Its character is what distinguishes Playful from a generic warm-toned deck: Syne reads as an independent studio voice, not a corporate header.
- **Space Grotesk** (body): A clean, slightly geometric sans-serif with a friendly humanist warmth. Used at weight 400–500 for body paragraphs, 500–600 for labels and captions. Provides a steady, legible counterweight to Syne's expressiveness.

There is no third face. Italic and underline are not used. Emphasis comes from weight (700 → 800), size, and the Syne-vs-Space-Grotesk contrast itself.

### Type Scale

| Token | Size (clamp) | Family | Weight | Use |
|---|---|---|---|---|
| `{typography.display-hero}` | 4–9rem | Syne | 800 | Oversized cover or opening date/title |
| `{typography.display}` | 3–7rem | Syne | 800 | Closing or major declarative headline |
| `{typography.headline}` | 2.5–5rem | Syne | 700 | Primary section headline |
| `{typography.statement}` | 2.5–4.5rem | Syne | 700 | Long-form quoted statement or manifesto line |
| `{typography.title}` | 2–3.5rem | Syne | 700 | Region or section title |
| `{typography.number-hero}` | 4–7rem | Syne | 800 | Hero statistic numeral |
| `{typography.number-md}` | 2.5rem | Syne | 800 | Mid-scale ordinal or stat numeral |
| `{typography.number-sm}` | 2rem | Syne | 800 | Inline ordinal or step numeral |
| `{typography.title-sm}` | 1.3rem | Syne | 700 | Card title within a small block |
| `{typography.body-md}` | 1.2rem | Space Grotesk | 500 | Subtitle or emphasized body |
| `{typography.body}` | 1–1.1rem | Space Grotesk | 400 | Paragraph body |
| `{typography.label-eyebrow}` | 0.85rem | Space Grotesk | 600 | Section eyebrow above a headline, uppercase tracked |
| `{typography.caption}` | 0.85rem | Space Grotesk | 500 | Subtitle, fine print, footnote |
| `{typography.tag}` | 0.75rem | Space Grotesk | 600 | Pill tag text inside a charcoal label |

### Defaults
- **Default size for a primary section headline**: `{typography.headline}` (2.5–5rem clamp).
- **Default size for a cover or major opening moment**: `{typography.display-hero}` (4–9rem clamp).
- **Default size for paragraph body**: `{typography.body}` (1–1.1rem clamp).
- **Default size for a subtitle or emphasized lead body**: `{typography.body-md}` (1.2rem).
- **Default size for any inline caption, footnote, or fine print**: `{typography.caption}` (0.85rem).
- **Default size for a hero numerical figure**: `{typography.number-hero}` (4–7rem clamp).
- **Default size for a stat tile or ordinal numeral**: `{typography.number-md}` (2.5rem).
- **Default weight for any display element (headline, statement, title, numeral)**: 700 or 800 — never lower.
- **Default weight for any body element**: 400 or 500.

When unsure between `{typography.title}` and `{typography.headline}` for the primary text on a slide, reach for `{typography.headline}` — `{typography.title}` is for sub-regions within a slide.

### Signature Treatments
These treatments are **non-optional whenever the corresponding element type is used**:

- **Every display element is set in Syne.** Headlines, statements, titles, numerals, vertical labels, decorative single-character marks — all Syne. Using Space Grotesk at large sizes is the wrong system signal.
- **Every Syne element uses negative letter-spacing**: -0.01em to -0.03em depending on size. Syne at default tracking reads as untreated; the negative tracking is what gives display type its tight, compressed personality.
- **Every body and label element is set in Space Grotesk.** Syne for body paragraphs reads as overwrought.
- **Eyebrow labels are uppercase with 0.15em letter-spacing.** A label without uppercase + tracked spacing reads as a body fragment, not a label.
- **Statistics and numerals are always weight 800.** Even mid-scale numerals (2rem) follow the display-weight convention. A weight-500 numeral reads as inventory, not a brag.
- **Numerals and statistics may carry a small rotation (±0.5deg to ±1deg)** when they sit as standalone stat-items rather than inside a chart or table. The rotation reinforces the hand-placed feeling.

### Typography Principles
The system's typographic rhythm comes from the **Syne-vs-Space-Grotesk contrast**, not from mixing weights within a face. A slide that uses only Syne at varying weights reads as monotonous; a slide that uses only Space Grotesk reads as understated to the point of corporate. The correct rhythm is Syne headline + Space Grotesk body, repeated with discipline.

Line-height: tight on display (0.85–1.1), generous on body (1.5–1.7). Never use tight line-height on body or generous line-height on display — both inversions break the rhythm.

Italic does not exist in this system. Underline does not exist. Emphasis is achieved by switching face (body → display) or weight (400 → 700), never by italicizing.

## Layout

### Canvas System
The system targets `100vw × 100vh` — full viewport. Every `.slide` is absolutely positioned to fill the viewport, and only the `.active` slide is visible (opacity 1, others at opacity 0). Slide navigation is JS-driven via arrow keys, space, click on next/prev buttons, and touch swipe. A 4px-tall charcoal progress bar runs along the bottom of the viewport, growing to indicate slide position. All sizes use `clamp()` so the layout fluidly scales without breakpoints down to a mobile reflow at 768px.

### Padding Scale
| Token | Value | Use |
|---|---|---|
| `{spacing.pad-slide-lg}` | 4rem 5rem | Cover, statement, and closing slides — generous outer padding |
| `{spacing.pad-slide-md}` | 3rem 4rem | Standard content slides — outer padding |
| `{spacing.pad-card-lg}` | 2rem 3rem | Large card or contact block interior padding |
| `{spacing.pad-card-md}` | 1.5rem | Standard card interior padding |
| `{spacing.gap-lg}` | 3rem | Large grid/flex gaps between major regions |
| `{spacing.gap-md}` | 2rem | Standard grid/flex gaps between cells |
| `{spacing.gap-sm}` | 1.5rem | Tight inline gaps |

### Chrome
A fixed 48px×48px navigation cluster sits at bottom-right (prev arrow, slide counter, next arrow — all outlined in 2px charcoal). A 4px-tall charcoal progress bar runs flush along the bottom edge of the viewport. Neither is part of the slide composition; they exist as the deck's persistent presenter chrome and should not be styled against.

The progress bar and nav buttons are the only persistent UI elements. Slides themselves carry no top bar, no footer chrome, no slide numbers within the canvas.

## Depth and Elevation

### Double-Stroke Offset Border (Primary Technique)
The signature depth treatment is a **double-stroke offset border**. A card carries a 3px solid charcoal border, and a `::before` pseudo-element absolutely positioned over the card carries a second 2–3px border offset 6–8px down-and-right. The offset border has no fill — the canvas shows through. The visual effect is a hand-drawn double outline that suggests imperfect tracing, like a pen pulled twice along an edge. This is the system's elevation device; it replaces what most systems would do with a `box-shadow`.

### Rotation (Secondary Technique)
Small rotations (±0.5deg to ±3deg) on cards, blocks, statistics, and decorative shapes provide a hand-placed feeling. Rotation directions alternate across adjacent elements — never two cards rotated the same direction next to each other — to suggest someone laid each piece down by hand rather than via a snapped grid.

### Atmospheric Ghost-Blob
A signature treatment: an oversized organic blob (`{components.ghost-blob}`) filled with charcoal at 0.08 opacity, placed absolutely in a slide corner as atmospheric wallpaper. The blob reads as a soft watermark cloud behind the content. Use sparingly — at most one ghost-blob per slide, anchored to a corner the primary content does not occupy.

### No Web Shadows
The system uses **no `box-shadow` blur values, no `drop-shadow`, no rgba shadows**. All apparent depth comes from the double-stroke offset border, rotation, and ink-density contrast. A blurred shadow on any element breaks the hand-crafted aesthetic — the marks should look drawn, not rendered.

## Shapes and Treatment

### Border Radius Scale
| Value | Use |
|---|---|
| 0px | Cards, blocks, tags, image frames, table cells |
| 50% | Round avatar placeholders, step-node circles, doodle circles |
| Asymmetric organic (e.g. `40% 60% 70% 30% / 40% 50% 60% 50%`) | Blob frames and blob fills only |
| Pebble-asymmetric (e.g. `255px 15px 225px 15px / 15px 225px 15px 255px`) | Pebble-shaped frames only |

The system avoids smooth medium radii (4px, 8px, 12px) — corners are either sharp, perfectly round, or organically blob-shaped. The middle ground reads as a generic web app, which is the wrong signal.

### Border Weights
- **3px solid `{colors.text}`** — the standard outlined-card and blob-frame border weight.
- **2–3px solid `{colors.text}`** — the offset ghost-border weight on the `::before` pseudo-element (slightly thinner than the primary).
- **3px solid `{colors.text}`** — the chart axis weight (X and Y axes on bar charts).
- **2px solid `{colors.text}`** — the nav-button border weight and the timeline-track horizontal line.
- **2px stroke** — the standard SVG scribble stroke weight with rounded line-caps.

### Decorative Element Types

**Rough-box card** — A rectangular content card with the signature double-stroke offset border. Background can be canvas peach (default), or solid charcoal (inverted card). Padding from the `{spacing.pad-card-*}` scale. Optional small rotation (±0.5–3deg).

**Organic blob frame** — A decorative outlined wrapper with asymmetric border-radius. Used as a portrait frame or decorative anchor; often holds a smaller solid blob-fill inside. Two characteristic shapes: the wavy organic blob (`{components.blob-frame-organic}`) and the pebble shape (`{components.blob-frame-pebble}`).

**Solid blob fill** — A charcoal organic shape with asymmetric border-radius. Used either inside an outlined blob-frame (creating a frame-and-mass pairing) or floating alone as a decorative mass.

**Scribble SVG** — Inline SVG path drawn as a single 2px-stroke charcoal line with round caps. The vocabulary: wavy stub, star outline, scribbled circle, squiggle waveform, arrow, concentric circles. Placed absolutely in slide corners or edges as decorative breath. Every slide gets at least one scribble; the most populated slides carry two or three.

**Doodle circle / doodle rect** — Plain outlined circle or rectangle, slightly rotated, placed absolutely in slide corners as a minimal decorative anchor. The simpler counterpart to the blob shapes — when a slide needs visual punctuation but a blob would feel too organic.

**Step-node circle** — A 64px round outlined node containing a single digit in Syne 800. Alternates between outlined (canvas fill, charcoal digit) and filled (charcoal fill, canvas digit) in sequence — odd steps filled, even steps outlined, or any consistent pattern.

**Tag pill** — A small charcoal rectangle with peach text at 0.75rem weight 600. Anchored to the bottom-left of an image frame as a category label. The only inverted text-on-charcoal element that is not a full card.

**Vertical spine label** — Syne 700 text at 1.5rem rotated 90deg, anchored to a slide's right edge with 0.1em letter-spacing. Reads as a magazine-spine wayfinder.

**Ghost-blob wallpaper** — Oversized organic blob at 0.08 opacity, placed absolutely in a slide corner as atmospheric wallpaper.

**Connector arrow doodle** — A small SVG sketched arrow (single 2px line with chevron head) used to suggest "next" or "see also" in the negative space of a slide.

## Do's and Don'ts

### Do
- Use Syne for every display moment (headline, statement, title, number, vertical label) and Space Grotesk for every body and label. The two-face contrast is the system's typographic rhythm.
- Apply negative letter-spacing (-0.01em to -0.03em) to every Syne element. Default tracking on Syne reads as untreated.
- Apply the double-stroke offset border to every primary content card — 3px main outline plus a 6–8px offset ghost border via `::before`. This is the system's signature elevation device.
- Place a scribbled SVG mark (squiggle, star, circle, arrow) in at least one corner of every slide as hand-drawn breath. The marks are punctuation, not content.
- Give cards, blocks, and statistics a small ±0.5–3deg rotation. Alternate rotation direction across adjacent elements so nothing reads as snapped to a grid.
- Use `{colors.text}` (charcoal) as the only ink color. Headlines, body, borders, scribbles, fills — all the same color.
- Reach for `{colors.bg-alt}` when a region needs to read as a distinct surface without introducing white or a new color.
- Let negative space breathe. One dominant element per slide plus one or two scribbles is the correct density.
- Pair an outlined blob frame with a smaller solid blob fill inside it when you need a portrait-like decorative anchor.
- Place an oversized ghost-blob (charcoal at 0.08 opacity) in a slide corner when the negative space feels empty but a scribble would be too small.

### Don't
- Don't introduce a third color. The system is peach-canvas + charcoal-ink only. No blues, no reds, no chart-segment palettes — chart bars are solid charcoal or outlined charcoal, never colored.
- Don't use blurred `box-shadow`. All depth comes from double borders and rotation. A blurred shadow breaks the hand-drawn aesthetic immediately.
- Don't apply medium border-radius values (4px, 8px, 12px). Corners are sharp, fully round, or organically blob-shaped — nothing between.
- Don't use Space Grotesk for headlines or display moments. Syne is the personality face; substituting Space Grotesk loses the studio voice.
- Don't use Syne for body paragraphs. It reads as overwrought at small sizes and at low weights.
- Don't rotate elements more than 3deg. Beyond ±3deg the hand-placed feeling tips into wonky and amateur.
- Don't rotate every element in the same direction. Alternate ±directions across adjacent elements; uniformity reads as a tilted canvas, not as hand-placement.
- Don't crowd a slide with simultaneous cards, statistics, and doodles. The system reads as expensive when sparse and broken when dense.
- Don't use italic or underline for emphasis. Switch face or weight instead.
- Don't put display-weight text at default tracking. Always tighten Syne with negative letter-spacing.

## Responsive Behavior

The system targets `100vw × 100vh` and uses `clamp()` throughout, so type and padding scale fluidly between viewport sizes without media queries. A single media query at `max-width: 768px` reflows multi-column grids to single-column, collapses the horizontal timeline track to vertical, and reduces slide padding to 2rem.

### Presenter Behavior
- Slides advance via `ArrowRight`, `Space`, or `Enter`.
- Slides reverse via `ArrowLeft`.
- The active slide carries the `.active` class; inactive slides are visibility-hidden at opacity 0.
- Slide transitions use a 0.6s opacity fade.
- A 4px-tall charcoal progress bar runs along the bottom of the viewport, growing as the deck advances.
- A bottom-right nav cluster shows prev/next buttons (48px outlined squares) and the current/total slide counter.
- Touch swipe horizontal on mobile advances/reverses.

### Print Behavior
No `@media print` rule is defined. The deck is web/viewport-first; printing will not render correctly without custom print styles.

## CJK & International Content

### Recommended Chinese Pairing

| Role | Latin face | Chinese face | Weight |
|---|---|---|---|
| Display / headline / numeral (Syne 700–800) | Syne | 站酷快乐体 ZCOOL KuaiLe | 400 (only weight available) |
| Body / label (Space Grotesk 400–600) | Space Grotesk | 悠哉字体 Yozai | 400 |

### Mixed-Content Strategy

Strategy A — extend each token's `fontFamily` to include the Chinese face after the Latin face. Syne tokens become `"Syne, ZCOOL KuaiLe, sans-serif"`; Space Grotesk tokens become `"Space Grotesk, Yozai, sans-serif"`. Latin glyphs render in the original face; CJK characters fall through 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=Syne:wght@700;800&family=Space+Grotesk:wght@400;500;600;700&family=ZCOOL+KuaiLe&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/cn-fontsource-yozai-regular/font.css" 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

Playful is a hand-crafted editorial system built on Syne (quirky humanist display) plus Space Grotesk (warm geometric body) on a peach-clay canvas. The Chinese transfer is exceptionally strong because both Chinese faces selected here carry the same "warm, hand-touched, independent studio" register as the Latin pairing.

**站酷快乐体 ZCOOL KuaiLe** is a rounded, friendly Chinese display face with quirky humanist proportions — the closest CDN-available equivalent to Syne's expressive studio voice. At display weights (4–9rem), KuaiLe reads as a contemporary independent Chinese studio voice, not a corporate or formal one. It pairs naturally with the peach canvas and charcoal ink. **Drop the negative letter-spacing (-0.01em to -0.03em) for Chinese display** — KuaiLe is designed on a square em-box and tightening causes glyph collision. The face's intrinsic warmth replaces what negative tracking does for Syne.

**悠哉字体 Yozai** is a Chinese sans-serif designed for relaxed body reading — slightly rounded terminals, friendly humanist proportions, designed to match the warmth that Space Grotesk brings to Latin. Set every Chinese body paragraph and label in Yozai 400. The eyebrow label treatment (0.15em letter-spacing + uppercase in Latin) does not transfer to CJK; for Chinese eyebrows, use Yozai at the same 0.85rem size with letter-spacing 0 and no uppercase — small size alone reads as label.

The double-stroke offset border, the small ±3deg rotations, the organic blob shapes, the SVG scribbles, the ghost-blob wallpaper — all script-agnostic. The single-color discipline (peach + charcoal) and the hand-crafted aesthetic survive the script switch fully.

The system's typographic rhythm (Syne-vs-Space-Grotesk contrast) becomes (KuaiLe-vs-Yozai contrast) in pure Chinese — both pairs carry the same "expressive editorial built on a reliable grid" rhythm. Statistics and numerals are pure digits and transfer unchanged in Syne 800; only when a stat carries a Chinese unit suffix (`亿`, `万`) does the suffix glyph fall through to KuaiLe.

### Known CJK Gap

ZCOOL KuaiLe and Yozai are both single-weight faces (400). The system's reliance on weight contrast (Syne 700 vs 800 for sub-display hierarchy; Space Grotesk 400 vs 500 vs 600 for label hierarchy) collapses to size-only hierarchy in pure Chinese. This is not a meaningful loss — Playful's hierarchy is primarily size-driven anyway, and the missing weight steps don't change the visual rhythm enough to matter. The rotation, scribble, and double-border treatments carry the system's character regardless of weight availability.

## Iteration Guide

1. Any new card uses the rough-box pattern: 3px charcoal border, peach background (or charcoal if inverted), padding from `{spacing.pad-card-*}`, and a `::before` ghost-border offset 6–8px down-and-right at 2–3px weight.
2. Any new card carries a small rotation (±0.5–3deg). Alternate rotation direction with neighboring cards; never align all cards to the same angle.
3. Any new headline uses Syne at weight 700–800 with negative letter-spacing. If the headline is the primary slide moment, reach for `{typography.headline}` or `{typography.display}` — not `{typography.title}` (which is sub-region scale).
4. Any new body or label uses Space Grotesk at weight 400–600. Use `{typography.label-eyebrow}` (0.85rem, weight 600, uppercase, 0.15em tracking) for the small label above a headline.
5. Any new statistic or numeral uses Syne at weight 800 with negative letter-spacing. Even small numerals (2rem) follow the display-weight convention.
6. Any new slide gets at least one scribbled SVG mark in a corner — squiggle, star, circle, arrow. Stroke 2px with rounded line-caps in `{colors.text}`.
7. Any decorative shape uses asymmetric organic border-radius (blob) or sharp 0px (rectangle) or 50% (round). Avoid medium radii.
8. If the slide negative space feels heavy, add a ghost-blob (charcoal at 0.08 opacity, oversized organic shape) anchored to a corner the content does not occupy.
9. Charts (bar, donut, line) use only `{colors.text}` and `{colors.bg-alt}` as fills. Do not introduce chromatic chart palettes.
10. Cards may be either outlined (default — canvas fill, charcoal border, charcoal text) or inverted (charcoal fill, peach text). Inverted cards are the system's emphasis device; reserve them for the cell you want to anchor the slide's attention.

## Known Gaps

- The system loads two Google Fonts (Syne, Space Grotesk) over the network. If fonts fail to load, the fallback sans-serif will render but the system's voice will be lost. Self-hosting is recommended for production.
- The double-stroke offset border (`::before` with 6–8px offset) requires the parent card to have `position: relative` and the pseudo-element to be visually inside the card's bounding box plus the offset. Cards near a slide edge may have their offset border clipped.
- The mobile responsive breakpoint at 768px reflows grids but does not adjust the absolutely-positioned decorative SVGs and blobs — they remain at desktop coordinates and may overlap or fall off-screen on small viewports. Treat the responsive behavior as basic, not polished.
- The peach canvas (#F0C8A0) has a strong cultural register (earthy, warm, slightly rustic). It does not pair well with cool-toned brand palettes and is not interchangeable with a neutral cream or white — the warmth is foundational.
- Image placeholders (`{colors.bg-alt}` fills with a centered "IMG 01" label) are stubs only. Production decks need real images that respect the warm palette; cool-toned photos will fight the canvas.
- There is no defined dark-mode variant. The system is single-mode (warm peach canvas only).
- The hover states on nav buttons (background fills to charcoal, text inverts to peach) are interactive presenter-chrome behaviors and are not part of the deck's slide composition.
````

---

## 2. 글씨체

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

---

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

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

**1장(표지)에서 처음 나오는 부품**
- `.ar1` — 1장 — 예: `<i class="scr ar1">`
- `.bfill` — 1장 — 예: `<div class="bfill">`
- `.bframe` — 1장 — 예: `<div class="bframe">`
- `.e1` — 1장 — 예: `<p class="eye e1">`
- `.eye` — 1·2·3·4·5·6장 — 예: `<p class="eye e1">`
- `.g1` — 1장 — 예: `<i class="ghost g1">`
- `.ghost` — 1·3·6장 — 예: `<i class="ghost g1">`
- `.gk` — 1장 — 예: `<em class="gk">`
- `.gl` — 1장 — 예: `<p class="eye gl">`
- `.scr` — 1·2·3·4·5·6장 — 예: `<i class="scr st1">`
- `.slide` — 1·2·3·4·5·6장 — 예: `<section class="slide">`
- `.spine` — 1장 — 예: `<p class="spine">`
- `.st1` — 1장 — 예: `<i class="scr st1">`
- `.t1` — 1장 — 예: `<h1 class="t1">`
- `.tag` — 1·2·4·5장 — 예: `<span class="tag tg1">`
- `.tg1` — 1장 — 예: `<span class="tag tg1">`
- `.unit` — 1장 — 예: `<p class="unit">`
- `.wv1` — 1장 — 예: `<i class="scr wv1">`

**2장(흐름·단계)에서 처음 나오는 부품**
- `.ar2` — 2장 — 예: `<i class="scr ar2">`
- `.box` — 2·3·4·5·6장 — 예: `<div class="box fig" style="--r:-1deg">`
- `.bt` — 2·5·6장 — 예: `<button class="bt fill" data-act="step">`
- `.btns` — 2장 — 예: `<div class="btns">`
- `.cap` — 2장 — 예: `<p class="cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quo…`
- `.ci2` — 2장 — 예: `<i class="scr ci2">`
- `.e2` — 2·3·4·5·6장 — 예: `<p class="eye e2">`
- `.fig` — 2장 — 예: `<div class="box fig" style="--r:-1deg">`
- `.fill` — 2장 — 예: `<button class="bt fill" data-act="step">`
- `.ft` — 2장 — 예: `<span class="tag ft">`
- `.hd` — 2·3·4·5·6장 — 예: `<h2 class="hd">`
- `.nd` — 2·5장 — 예: `<div class="nd" data-s="1">`
- `.nodes` — 2장 — 예: `<div class="nodes">`
- `.note` — 2장 — 예: `<p class="note">`
- `.nr` — 2·3·4·5장 — 예: `<p class="nr">`
- `.stmt` — 2장 — 예: `<p class="stmt">`

**3장(숫자와 그래프)에서 처음 나오는 부품**
- `.a` — 3·6장 — 예: `<i class="sw a">`
- `.b` — 3·6장 — 예: `<i class="sw b">`
- `.bar` — 3장 — 예: `<i class="bar a" style="height:63%">`
- `.chart` — 3장 — 예: `<div class="chart">`
- `.g3` — 3장 — 예: `<i class="ghost g3">`
- `.inv` — 3·4·5장 — 예: `<div class="box st inv" style="--r:1deg">`
- `.lg` — 3장 — 예: `<div class="lg">`
- `.nv` — 3장 — 예: `<b class="nv">`
- `.pair` — 3장 — 예: `<div class="pair">`
- `.src` — 3장 — 예: `<span class="src">`
- `.st` — 3장 — 예: `<div class="box st" style="--r:-1.2deg">`
- `.st3` — 3장 — 예: `<i class="scr st3">`
- `.stats` — 3장 — 예: `<div class="stats">`
- `.sw` — 3장 — 예: `<i class="sw a">`
- `.tr3` — 3장 — 예: `<div class="tr3">`
- `.xl` — 3장 — 예: `<div class="xl">`

**4장(비교와 표)에서 처음 나오는 부품**
- `.ci4` — 4장 — 예: `<i class="scr ci4">`
- `.cmp` — 4장 — 예: `<div class="cmp">`
- `.cp` — 4장 — 예: `<div class="box cp" style="--r:-1.4deg">`
- `.lst` — 4장 — 예: `<div class="box lst" style="--r:.8deg">`
- `.qb` — 4장 — 예: `<span class="tag qb">`
- `.qt` — 4장 — 예: `<p class="qt">`
- `.tbl` — 4장 — 예: `<div class="tbl">`
- `.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">`
- `.br` — 5장 — 예: `<div class="nd br">`
- `.fb` — 5장 — 예: `<p class="fb" data-fb>`
- `.lt` — 5장 — 예: `<button class="bt lt rty" data-act="retry">`
- `.od` — 5장 — 예: `<i class="od">`
- `.opt` — 5장 — 예: `<button class="opt" data-opt="0">`
- `.opts` — 5장 — 예: `<div class="opts">`
- `.q` — 5장 — 예: `<h3 class="q">`
- `.quiz` — 5장 — 예: `<div class="box inv quiz" style="--r:-1deg" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 …`
- `.ring` — 5장 — 예: `<svg class="ring" viewBox="0 0 400 90" preserveAspectRatio="none">`
- `.rty` — 5장 — 예: `<button class="bt lt rty" data-act="retry">`
- `.wl` — 5장 — 예: `<p class="eye wl">`
- `.words` — 5장 — 예: `<div class="words">`
- `.wv5` — 5장 — 예: `<i class="scr wv5">`

**6장(디자인 안내(시연))에서 처음 나오는 부품**
- `.bl6` — 6장 — 예: `<div class="bl6" id="pf-blob">`
- `.c` — 6장 — 예: `<div class="box d6 c" style="--r:1deg">`
- `.d6` — 6장 — 예: `<div class="box d6 a" style="--r:1.5deg">`
- `.dh` — 6장 — 예: `<div class="dh">`
- `.g6` — 6장 — 예: `<div class="box g6" style="--r:-1deg">`
- `.g6g` — 6장 — 예: `<i class="ghost g6g">`
- `.of6` — 6장 — 예: `<div class="of6" id="pf-off">`
- `.r6` — 6장 — 예: `<div class="r6">`
- `.sl6` — 6장 — 예: `<p class="eye sl6">`
- `.sm` — 6장 — 예: `<button class="bt sm" data-demo="#pf-off" data-mode="toggle" aria-pressed="false">`
- `.st6` — 6장 — 예: `<i class="scr st6">`
- `.sw6` — 6장 — 예: `<span class="sw6">`
- `.tl6` — 6장 — 예: `<div class="tl6" id="pf-tilt">`

**예시 장에는 없지만 CSS에 정의된 클래스**(디자인 규칙에 맞으면 써도 됨): `.prog`

**직접 쓰지 말 것**: 엔진이 상태를 나타내려고 붙이는 클래스(`.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="playful">
<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=Syne:wght@700;800&family=Space+Grotesk:wght@400;500;600&display=swap">
<!-- 이 디자인의 공통 CSS(글씨체·색·부품 모양). 이 줄은 지우거나 바꾸지 마세요 -->
<link rel="stylesheet" href="https://k-slide.web.app/kit/v1/playful.css">
<style>
/* === 추가 부품: 새 클래스가 꼭 필요할 때만 이 줄 아래에 정의하세요(공통 CSS는 위 <link>가 이미 불러옴 — 여기에 옮겨 쓰지 않음) === */
</style>
</head>
<body>
<div class="deck-viewport">
  <main class="deck-stage" id="deckStage">
<section class="slide">
  <i class="ghost g1"></i>
  <p class="eye e1">초등 과학 · 6학년 2학기 · 1단원 · 3~4차시</p>
  <p class="unit">계절의 변화<span>Sun, Shadow & Temperature</span></p>
  <p class="eye gl">학습 목표</p>
  <h1 class="t1">하루 동안 <em class="gk">태양 고도</em>,<br><em class="gk">그림자 길이</em>, <em class="gk">기온</em>의 관계</h1>
  <span class="tag tg1">00초등학교 · 2026</span>
  <div class="bframe"><div class="bfill"><b>03</b><span>3~4차시</span></div></div>
  <i class="scr st1"><svg viewBox="0 0 60 60"><path d="M30 4l7 18 19 1-15 12 6 19-17-11-17 11 6-19L4 23l19-1z"/></svg></i><i class="scr wv1"><svg viewBox="0 0 220 40"><path d="M4 22c18-22 34 22 52 0s34 22 52 0 34 22 52 0 34 22 52 0" /></svg></i><i class="scr ar1"><svg viewBox="0 0 160 60"><path d="M6 40c30-26 70-34 120-18M110 8l18 14-20 12"/></svg></i>
  <p class="spine">SUN · SHADOW · 2026</p>
</section>
<section class="slide" data-steps="4">
  <p class="eye e2">측정 준비</p><h2 class="hd">태양 고도 측정기 만들기</h2>
  <div class="box fig" style="--r:-1deg"><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><span class="tag ft">FIG. 01 · 태양 고도 측정기</span></div>
  <p class="stmt">태양 고도 — 태양이 지표면과 이루는 각</p>
  <p class="note">막대기의 그림자와 실이 이루는 각 = 태양 고도</p>
  <div class="nodes"><div class="nd" data-s="1"><b>1</b><div><h3>자 붙이기</h3><p>우드록 한쪽에 양면테이프로 자를 붙여요</p></div></div><div class="nd" data-s="2"><b>2</b><div><h3>수수깡 꽂기</h3><p>수수깡을 10cm 정도 잘라 자의 '0' 위치에 수직으로 꽂아요</p></div></div><div class="nd" data-s="3"><b>3</b><div><h3>실 묶기</h3><p>수수깡 끝에 실을 묶어요</p></div></div><div class="nd" data-s="4"><b>4</b><div><h3>각도기 끼우기</h3><p>실의 다른 끝을 각도기 가운데 구멍에 끼워요</p></div></div></div>
  <div class="btns"><button class="bt fill" data-act="step">다음 단계 →</button><button class="bt" 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>
  <p class="nr">버튼 규칙 없음 → 윤곽 사각으로 표현</p>
  <i class="scr ar2"><svg viewBox="0 0 160 60"><path d="M6 40c30-26 70-34 120-18M110 8l18 14-20 12"/></svg></i><i class="scr ci2"><svg viewBox="0 0 120 120"><path d="M64 10c-34-4-56 22-52 52s34 50 62 42 40-40 30-66C96 22 80 12 52 14"/></svg></i>
</section>
<section class="slide">
  <i class="ghost g3"></i>
  <p class="eye e2">측정 결과</p><h2 class="hd">하루 동안 무엇이 어떻게 변할까요?</h2>
  <div class="stats"><div class="box st" style="--r:-1.2deg"><span class="eye">남중 시각</span><b class="nv">12:30</b><p>태양 고도가 가장 높아요</p></div><div class="box st inv" style="--r:1deg"><span class="eye">남중 방향</span><b class="nv">정남</b><p>남중할 때 태양의 위치</p></div><div class="box st" style="--r:-0.8deg"><span class="eye">최고 기온</span><b class="nv">14:30</b><p>기온이 가장 높아요</p></div><div class="box st inv" style="--r:1.4deg"><span class="eye">가장 긴 그림자</span><b class="nv">9:30</b><p>그림자가 가장 길어요</p></div></div>
  <div class="lg"><span><i class="sw a"></i>태양 고도 (°)</span><span><i class="sw b"></i>그림자 길이 (cm)</span><span>아래 줄 = 기온 (℃)</span><span class="src">예시 값</span></div>
  <div class="chart"><div class="grp"><div class="pair"><i class="bar a" style="height:63%"><span>38</span></i><i class="bar b" style="height:86%"><span>12.9</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:80%"><span>48</span></i><i class="bar b" style="height:61%"><span>9.1</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:92%"><span>55</span></i><i class="bar b" style="height:47%"><span>7</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:95%"><span>57</span></i><i class="bar b" style="height:43%"><span>6.4</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:90%"><span>54</span></i><i class="bar b" style="height:48%"><span>7.2</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:78%"><span>47</span></i><i class="bar b" style="height:63%"><span>9.4</span></i></div></div><div class="grp"><div class="pair"><i class="bar a" style="height:62%"><span>37</span></i><i class="bar b" style="height:89%"><span>13.4</span></i></div></div></div>
  <div class="xl"><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>
  <div class="tr3"><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>
  <p class="nr">예시 값 — 태양 고도·그림자(10cm 막대)는 9월 중순 북위 36° 기준 계산, 기온은 교과서 그래프 모양을 따른 값</p>
  <i class="scr st3"><svg viewBox="0 0 60 60"><path d="M30 4l7 18 19 1-15 12 6 19-17-11-17 11 6-19L4 23l19-1z"/></svg></i>
</section>
<section class="slide">
  <p class="eye e2">관계 정리</p><h2 class="hd">태양 고도가 바뀌면 무엇이 달라질까요?</h2>
  <div class="cmp"><div class="box cp" style="--r:-1.4deg"><span class="eye">HIGH</span><h3>태양 고도가 높을 때</h3><p>— 그림자 길이는 짧아져요</p><p>— 기온은 높아져요</p></div><div class="box cp inv" style="--r:1.2deg"><span class="eye">LOW</span><h3>태양 고도가 낮을 때</h3><p>— 그림자 길이는 길어져요</p><p>— 기온은 낮아져요</p></div></div>
  <div class="tbl"><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="box lst" style="--r:.8deg"><span class="eye">남중</span><p>— 태양이 정남쪽에 있을 때 '남중했다'고 해요</p><p>— 이때의 태양 고도를 남중 고도라고 해요</p></div>
  <p class="qt">“태양 고도가 가장 높은 시각과 기온이 가장 높은 시각에는 차이가 있어요.”</p>
  <span class="tag qb">오늘의 정리</span>
  <p class="nr">표 규칙 없음 → 3px 축선 + 2px 줄으로 표현</p>
  <i class="scr ci4"><svg viewBox="0 0 120 120"><path d="M64 10c-34-4-56 22-52 52s34 50 62 42 40-40 30-66C96 22 80 12 52 14"/></svg></i>
</section>
<section class="slide">
  <p class="eye e2">확인하기</p><h2 class="hd">배운 내용을 확인해 볼까요?</h2>
  <div class="box inv quiz" style="--r:-1deg" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다시 생각해 볼까요? 태양 고도와 그림자 길이의 관계를 떠올려 보세요">
    <p class="eye">QUESTION</p>
    <h3 class="q">하루 중 그림자 길이가 가장 짧을 때는?</h3>
    <div class="opts"><button class="opt" data-opt="0"><i class="od">A</i><span>오전 9시 30분</span><svg class="ring" viewBox="0 0 400 90" preserveAspectRatio="none"><path d="M210 8C110 2 14 18 8 44s88 42 196 40 190-16 188-42S300 6 160 12"/></svg></button><button class="opt" data-opt="1"><i class="od">B</i><span>낮 12시 30분 무렵</span><svg class="ring" viewBox="0 0 400 90" preserveAspectRatio="none"><path d="M210 8C110 2 14 18 8 44s88 42 196 40 190-16 188-42S300 6 160 12"/></svg></button><button class="opt" data-opt="2"><i class="od">C</i><span>오후 3시 30분</span><svg class="ring" viewBox="0 0 400 90" preserveAspectRatio="none"><path d="M210 8C110 2 14 18 8 44s88 42 196 40 190-16 188-42S300 6 160 12"/></svg></button></div>
    <p class="fb" data-fb></p>
    <button class="bt lt rty" data-act="retry">다시 풀기 ↺</button>
  </div>
  <div class="blk">
    <p class="eye">빈칸을 눌러 확인해요</p>
    <div class="nd br"><b>1</b><p><button class="blank" data-blank aria-pressed="false"><span>태양 고도</span></button>는 점점 높아졌다가 다시 낮아진다</p></div><div class="nd br"><b>2</b><p><button class="blank" data-blank aria-pressed="false"><span>그림자 길이</span></button>는 점점 짧아졌다가 다시 길어진다</p></div><div class="nd br"><b>3</b><p><button class="blank" data-blank aria-pressed="false"><span>기온</span></button>은 점점 높아졌다가 다시 낮아진다</p></div>
    <p class="eye wl">오늘의 낱말</p>
    <div class="words"><span class="tag">태양 고도</span><span class="tag">남중 고도</span><span class="tag">그림자 길이</span><span class="tag">기온</span></div>
  </div>
  <p class="nr">빈칸 규칙 없음 → 윤곽 사각으로 표현</p>
  <i class="scr wv5"><svg viewBox="0 0 220 40"><path d="M4 22c18-22 34 22 52 0s34 22 52 0 34 22 52 0 34 22 52 0" /></svg></i>
</section>
<section class="slide">
  <i class="ghost g6g"></i>
  <p class="eye e2">디자인 안내</p><h2 class="hd">이 디자인 사용 설명서</h2>
  <div class="box g6" style="--r:-1deg"><div class="r6"><p class="eye">한눈에</p><p>손으로 만든 스튜디오 스케치북. <b>복숭아 점토 바탕 + 숯색 잉크 하나</b> — 포인트 색이 없어서 강조는 반전(숯 바탕 + 복숭아 글자)으로 해요.</p></div><div class="r6"><p class="eye">색</p><p><span class="sw6"><span><i style="background:#F0C8A0"></i>복숭아</span><span><i style="background:#E8B88E"></i>짙은 복숭아</span><span><i style="background:#F7DEC6"></i>옅은 복숭아</span><span><i style="background:#1A1A1A"></i>숯색 잉크</span></span></p></div><div class="r6"><p class="eye">글꼴</p><p>제목·숫자 Syne 800 → Elice DigitalBaeum Bold<br>본문 Space Grotesk → Paperlogy 4Regular</p></div><div class="r6"><p class="eye">이렇게 쓰면 좋아요</p><p>만들기·관찰처럼 손을 쓰는 수업. 장마다 주인공 하나 + 여백, 낙서는 두세 개면 충분해요.</p></div></div>
  <i class="scr st6"><svg viewBox="0 0 60 60"><path d="M30 4l7 18 19 1-15 12 6 19-17-11-17 11 6-19L4 23l19-1z"/></svg></i>
  <p class="eye sl6">대표 장치 — 눌러 보세요</p>
  <div class="box d6 a" style="--r:1.5deg"><div class="dh"><h3>어긋난 둘째 선</h3><button class="bt sm" data-demo="#pf-off" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>3px 테두리 뒤로 8px 어긋난 선을 한 번 더.</p><div class="of6" id="pf-off">러프 박스</div></div>
  <div class="box d6 b" style="--r:-1.5deg"><div class="dh"><h3>이웃은 반대로 기울기</h3><button class="bt sm" data-demo="#pf-tilt" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>±0.5~3° — 옆 카드끼리는 서로 반대 방향.</p><div class="tl6" id="pf-tilt"><span>관찰</span><span>기록</span><span>비교</span></div></div>
  <div class="box d6 c" style="--r:1deg"><div class="dh"><h3>블롭 틀 + 채움</h3><button class="bt sm" data-demo="#pf-blob" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>둥글둥글한 틀 안에 숯색 블롭을 채워 숫자를 담아요.</p><div class="bl6" id="pf-blob"><b>03</b></div></div>
</section>
<nav class="dk-nav"><button class="dk-prev" aria-label="이전">←</button><span class="dk-count" data-pad></span><button class="dk-next" aria-label="다음">→</button></nav><i class="prog"></i>
  </main>
</div>

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

---

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

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

```css
/* playful — k-slide 공통 CSS v1 (채팅 AI용 받기 .md가 불러옴, 고치지 말 것) */
/* === KOREAN FONTS === */
@font-face{font-family:'kp-22';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/elice-digitalbaeum/EliceDigitalBaeum_Bold.woff2") format("woff2");font-weight:700}
@font-face{font-family:'kp-16';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/paperlogy/Paperlogy-4Regular.woff2") format("woff2");font-weight:400}
/* === THEME === */
:root{--stage-bg:#F0C8A0;--slide-bg:#F0C8A0;
  --kt:'kp-22';--kb:'kp-16';--ka:'kp-16';
  --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 === */

/* --- 복숭아 + 숯 --- */
:root{--bg:#F0C8A0;--alt:#E8B88E;--light:#F7DEC6;--ink:#1A1A1A}
.slide{background:var(--bg);color:var(--ink);font-family:'Space Grotesk',var(--kb),sans-serif;font-weight:var(--wb)}
.slide>*{position:absolute}
.eye{font:600 24px/1.2 'Space Grotesk',var(--kb),sans-serif;letter-spacing:.15em;text-transform:uppercase}
h1,h2,h3,.unit,.nv,.stmt,.qt,.nd b,.q{font-family:'Syne',var(--kt),sans-serif;font-weight:var(--wt);letter-spacing:0}
.tag{background:var(--ink);color:var(--bg);padding:8px 18px;font-weight:600;font-size:24px}
.nr{left:120px;bottom:40px;font-size:20px;opacity:.7}

/* 낙서 SVG · 유령 블롭 · 두 겹 테두리 카드 */
.scr svg{display:block;width:100%;height:100%;fill:none;stroke:var(--ink);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.ghost{background:var(--ink);opacity:.08;border-radius:40% 60% 70% 30% / 40% 50% 60% 50%}
.box{position:absolute;background:var(--bg);border:3px solid var(--ink);padding:26px 30px;transform:rotate(var(--r,0deg))}
/* 어긋난 둘째 선: 회전 카드에서도 카드 밖으로만 보이도록 '흐림 없는 두 겹 고리'로 그림(바탕색 사각 위에 잉크 고리) */
.box{box-shadow:8px 8px 0 -2.5px var(--bg),8px 8px 0 0 var(--ink)}
.box.inv{background:var(--ink);color:var(--bg)}
.bt{border:2px solid var(--ink);padding:14px 26px;font:600 30px/1 var(--kb);color:var(--ink);background:transparent}
.bt.fill{background:var(--ink);color:var(--bg)}
.bt:disabled{opacity:.35}
.e2{left:120px;top:86px}
.hd{left:120px;right:120px;top:130px;font-size:80px;line-height:1.12;white-space:nowrap}

/* --- 1. 표지: 단원 → 라벨 → 학습 목표(가장 큰 Syne, 핵심 낱말 = 반전) + 태그 | 블롭 틀(차시) + 낙서 3개 + 세로 책등 + 유령 블롭 --- */
.g1{right:-160px;bottom:-200px;width:820px;height:700px}
.e1{left:120px;top:140px}
.unit{left:116px;top:190px;display:flex;align-items:baseline;gap:30px;font-size:80px;line-height:1.1;white-space:nowrap}
.unit span{font:800 46px/1 'Syne',sans-serif;letter-spacing:-.03em;opacity:.75}
.gl{left:120px;top:350px}
.t1{left:112px;top:400px;font-size:116px;line-height:1.3;white-space:nowrap}
.t1 .gk{font-style:normal;background:var(--ink);color:var(--bg);padding:0 .12em;-webkit-box-decoration-break:clone;box-decoration-break:clone}
.tg1{left:120px;top:770px;font-size:28px}
.bframe{right:180px;top:640px;width:380px;height:330px;border:3px solid var(--ink);border-radius:40% 60% 70% 30% / 40% 50% 60% 50%;display:grid;place-items:center;transform:rotate(-4deg)}
.bfill{width:250px;height:210px;background:var(--ink);color:var(--bg);border-radius:60% 40% 30% 70% / 60% 30% 70% 40%;display:grid;place-items:center;align-content:center;text-align:center}
.bfill b{font:800 104px/.9 'Syne',sans-serif;letter-spacing:-.03em}
.bfill span{font-family:'Syne',var(--kt),sans-serif;font-weight:var(--wt);font-size:28px}
.st1{right:300px;top:110px;width:80px;height:80px;transform:rotate(12deg)}
.wv1{left:120px;top:870px;width:300px;height:56px}
.ar1{left:620px;top:800px;width:200px;height:76px;transform:rotate(-6deg)}
.spine{right:-110px;top:380px;transform:rotate(90deg);font:700 28px/1 'Syne',sans-serif;letter-spacing:.1em;white-space:nowrap}

/* --- 2. 만들기: 러프 박스 속 측정기 그림(태그 알약) + 정의 문장 | 단계 노드 원 4개(켜지면 채움) + 윤곽 버튼 --- */
.fig{left:120px;top:270px;width:860px;padding:14px 30px 30px;
  --g-ink:var(--ink);--g-acc:var(--ink);--g-stick:var(--ink);--g-board:var(--alt);--g-ruler:var(--light);--g-prot:rgba(26,26,22,.05);--g-shadow:rgba(26,26,26,.45);--g-font:'Space Grotesk',var(--kb),sans-serif;--g-sw:2.5}
.fig .gauge{width:780px;display:block;margin:0 auto}
.ft{position:absolute;left:-3px;bottom:-3px}
.stmt{left:120px;width:880px;top:880px;font-size:38px;line-height:1.2}
.note{left:120px;width:880px;top:938px;font-size:26px;opacity:.8}
.nodes{left:1080px;right:130px;top:280px;display:flex;flex-direction:column;gap:22px}
.nd{display:grid;grid-template-columns:64px 1fr;gap:22px;align-items:start;transition:opacity .3s}
.nd b{display:grid;place-items:center;width:64px;height:64px;border-radius:50%;border:3px solid var(--ink);background:var(--bg);font:800 30px/1 'Syne',sans-serif}
.nd h3{font-size:42px;line-height:1.1}
.nd p{margin-top:6px;font-size:25px;line-height:1.5}
.slide[data-step]:not([data-step="0"]) .nd:not(.on){opacity:.35}
.nd.on b{background:var(--ink);color:var(--bg)}
.btns{left:1080px;right:130px;top:880px;display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px}
.cap{flex:1 1 100%;font-size:26px;font-weight:500}
.ar2{left:990px;top:180px;width:150px;height:60px;transform:rotate(10deg)}
.ci2{right:100px;top:60px;width:110px;height:110px}

/* --- 3. 숫자와 그래프: 기울어진 러프 박스 4개(숫자 Syne 800) + 막대 그래프(채움 = 태양 고도 · 윤곽 = 그림자, 3px 축) + 기온 줄 --- */
.g3{left:-220px;bottom:-240px;width:700px;height:560px}
.stats{left:120px;right:130px;top:270px;display:grid;grid-template-columns:repeat(4,1fr);gap:44px}
.st{position:relative;padding:18px 26px}
.nv{display:block;margin-top:6px;font-size:68px;line-height:1;transform:rotate(-1deg)}
.st p{margin-top:8px;font-size:24px;line-height:1.35}
.lg{left:120px;top:478px;display:flex;align-items:center;gap:34px;font-size:24px;font-weight:600}
.lg .src{opacity:.7;font-weight:500}
.sw{display:inline-block;width:22px;height:22px;margin-right:10px;vertical-align:-4px;border:3px solid var(--ink)}
.sw.a{background:var(--ink)}
.chart{left:120px;right:130px;top:530px;height:300px;display:grid;grid-template-columns:repeat(7,1fr);gap:30px;padding:30px 30px 0;border-left:3px solid var(--ink);border-bottom:3px solid var(--ink)}
.pair{height:100%;display:flex;align-items:flex-end;gap:8px}
.bar{position:relative;flex:1;display:block}
.bar.a{background:var(--ink)}
.bar.b{border:3px solid var(--ink);border-bottom:0}
.bar span{position:absolute;left:50%;bottom:100%;transform:translateX(-50%);margin-bottom:4px;font:800 22px/1 'Syne',sans-serif}
.xl{left:120px;right:130px;top:846px;display:grid;grid-template-columns:repeat(7,1fr);gap:30px;padding:0 30px 0 33px}
.xl span,.tr3>span:not(.eye){text-align:center;font:800 26px/1 'Syne',sans-serif}
.tr3{left:120px;right:130px;top:892px;display:grid;grid-template-columns:repeat(7,1fr);gap:30px;padding:12px 30px 0 33px;border-top:2px solid var(--ink)}
.tr3 .eye{position:absolute;left:-2px;top:-40px;font-size:20px}
.tr3>span:not(.eye){font:500 26px/1 'Space Grotesk',sans-serif}
.st3{right:130px;top:90px;width:76px;height:76px;transform:rotate(-12deg)}

/* --- 4. 비교와 표: 러프 박스 둘(바탕 | 반전, 반대 기울기) + 3px 축선 표 | 밝은 톤 박스 남중 + 문장 인용 + 태그 --- */
.cmp{left:120px;width:980px;top:276px;display:grid;grid-template-columns:1fr 1fr;gap:48px}
.cp{position:relative}
.cp h3{margin:10px 0 8px;font-size:40px;line-height:1.15}
.cp p,.lst p{font-size:27px;line-height:1.55}
.tbl{left:120px;width:980px;top:610px;border-top:3px solid var(--ink)}
.tr{display:grid;grid-template-columns:1.2fr 1fr 1fr 1fr;gap:20px;padding:14px 4px;border-bottom:2px solid var(--ink);font-size:28px}
.tr.th{font:600 22px/1.2 'Space Grotesk',var(--kb),sans-serif;letter-spacing:.12em;padding:10px 4px}
.tr:not(.th) span:first-child{font-family:'Syne',var(--kt),sans-serif;font-weight:var(--wt)}
.lst{left:1210px;right:140px;top:280px;background:var(--light)}
.qt{left:1210px;right:130px;top:610px;font-size:46px;line-height:1.25}
.qb{left:1210px;top:850px}
.ci4{right:110px;top:820px;width:110px;height:110px}

/* --- 5. 확인하기: 반전 카드 퀴즈(정답 = 손그림 동그라미) | 단계 노드 빈칸(윤곽 사각) + 태그 알약 낱말 --- */
.quiz{left:120px;width:960px;top:270px;bottom:120px;display:flex;flex-direction:column;padding:34px 44px}
.q{margin-top:14px;font-size:54px;line-height:1.15}
.opts{margin-top:28px;display:flex;flex-direction:column;gap:16px}
.opt{position:relative;display:flex;align-items:center;gap:22px;text-align:left;font-size:36px;font-weight:600;color:var(--bg);padding:6px 10px;align-self:flex-start}
.od{flex:none;display:grid;place-items:center;width:56px;height:56px;border-radius:50%;border:2.5px solid var(--bg);font:800 26px/1 'Syne',sans-serif;font-style:normal}
.ring{position:absolute;left:-14px;top:-10px;width:calc(100% + 28px);height:calc(100% + 20px);fill:none;stroke:var(--bg);stroke-width:3;stroke-linecap:round;pointer-events:none;visibility:hidden}
.opt.right .ring{visibility:visible}
.opt.right .od{background:var(--bg);color:var(--ink)}
.opt.wrong span{text-decoration:line-through;text-decoration-thickness:3px}
.opt:disabled:not(.right){opacity:.45}
.fb{margin-top:20px;font-size:28px;line-height:1.5}
.bt.lt{border-color:var(--bg);color:var(--bg)}
.rty{align-self:flex-start;margin-top:auto}
.blk{left:1180px;right:130px;top:280px;bottom:120px;display:flex;flex-direction:column;gap:22px}
.br{align-items:center}
.br p{font-size:30px;line-height:1.6}
.blank{position:relative;min-width:170px;margin-right:10px;padding:2px 14px;border:3px solid var(--ink);font:600 28px/1.35 'Space Grotesk',var(--kb),sans-serif;color:var(--ink);text-align:center}
.blank span{visibility:hidden}
.blank::after{content:'?';position:absolute;left:0;right:0;top:2px;font-family:'Syne',sans-serif;font-weight:800}
.blank.open{background:var(--ink);color:var(--bg)}
.blank.open span{visibility:visible}
.blank.open::after{content:none}
.wl{margin-top:auto}
.words{display:flex;flex-wrap:wrap;gap:12px}
.words .tag{font-size:28px}
.wv5{left:1180px;top:160px;width:260px;height:48px}

/* --- 내비: 오른쪽 아래 윤곽 사각 + 번호(누르면 숯 채움 — 명세의 내비 반응), 아래 진행 막대 --- */
.dk-nav{position:absolute;right:40px;bottom:30px;display:flex;align-items:center;gap:12px;z-index:40}
.dk-prev,.dk-next{width:56px;height:56px;border:2px solid var(--ink);font:700 26px/1 'Syne',sans-serif;color:var(--ink);transition:background .2s,color .2s}
.dk-prev:hover:not(:disabled),.dk-next:hover:not(:disabled){background:var(--ink);color:var(--bg)}
.dk-prev:disabled,.dk-next:disabled{opacity:.3}
.dk-count{font:600 26px/1 'Space Grotesk',sans-serif;min-width:90px;text-align:center}
.prog{position:absolute;left:0;bottom:0;height:6px;background:var(--ink);width:16.7%;transition:width .6s ease;z-index:40}
[data-slide="2"] .prog{width:33.3%}[data-slide="3"] .prog{width:50%}[data-slide="4"] .prog{width:66.7%}[data-slide="5"] .prog{width:83.3%}
/* --- 6. 디자인 안내: 큰 러프 박스 설명 | 반대로 기운 러프 박스 시연 3개 --- */
.g6g{left:-200px;bottom:-260px;width:760px;height:620px}
.g6{left:120px;width:820px;top:290px;display:flex;flex-direction:column;gap:22px;padding:34px 40px}
.r6 .eye{font-size:21px}
.r6 p+p{margin-top:6px;font-size:28px;line-height:1.5}
.r6 b{font-weight:600}
.sw6{display:flex;flex-wrap:wrap;gap:6px 24px}
.sw6 i{display:inline-block;width:26px;height:26px;margin-right:8px;vertical-align:-5px;border:2px solid var(--ink)}
.st6{left:900px;top:220px;width:76px;height:76px;transform:rotate(-14deg)}
.sl6{left:1060px;top:262px;font-size:21px}
.d6{left:1060px;right:130px;padding:16px 26px}
.d6.a{top:310px}.d6.b{top:530px}.d6.c{top:750px}
.d6 .dh{display:flex;justify-content:space-between;align-items:center;gap:16px}
.d6 h3{font-size:34px;line-height:1.1}
.d6 p{margin-top:4px;font-size:22px;line-height:1.4}
.bt.sm{font-size:20px;padding:8px 14px}
.bt.sm[aria-pressed="true"]{background:var(--ink);color:var(--bg)}
.of6{margin-top:12px;display:inline-block;padding:10px 26px;border:3px solid var(--ink);font:800 28px/1.2 'Syne',var(--kt),sans-serif;background:var(--bg)}
.of6.play{box-shadow:8px 8px 0 -2.5px var(--bg),8px 8px 0 0 var(--ink)}
.tl6{margin-top:12px;display:flex;gap:18px}
.tl6 span{padding:8px 20px;border:3px solid var(--ink);background:var(--light);font-weight:600;font-size:24px;transition:transform .3s}
.tl6.play span:nth-child(odd){transform:rotate(-3deg)}.tl6.play span:nth-child(even){transform:rotate(2.5deg)}
.bl6{margin-top:8px;width:150px;height:76px;border:3px solid var(--ink);border-radius:40% 60% 70% 30% / 40% 50% 60% 50%;display:grid;place-items:center}
.bl6 b{width:104px;height:54px;display:grid;place-items:center;border-radius:60% 40% 30% 70% / 60% 30% 70% 40%;font:800 34px/1 'Syne',sans-serif}
.bl6.play b{background:var(--ink);color:var(--bg)}
[data-slide="6"] .prog{width:100%}

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