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

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

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

## 라이선스

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

- Hakgyoansim Moheomga B: Hakgyoansim Moheomga — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright © KERIS. All rights reserved.
  파일: HakgyoansimMoheomgaB.ttf
- Cafe24 Simplehae: Cafe24 Simplehae — KERIS 학교 안심폰트(https://copyright.keris.or.kr/wft/fntDwnld, 전체 OFL 안내)에서 받은 TTF (2026-10-07) / 파일 안 저작권: Copyright (c) Cafe24 Corp. All Rights Reserved.
  파일: Cafe24Simplehae-v2.0.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/long-table.css">`(head 안)와 `<script src="https://k-slide.web.app/kit/v1/long-table.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. **글씨체는 바꾸지 마세요.** 한글 글씨체(제목 Hakgyoansim Moheomga B(700) · 본문 Cafe24 Simplehae(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. 디자인 규칙 (`long-table` design.md)

````markdown
---
version: alpha
name: Long Table
description: A warm, single-ink editorial system in the register of a supper-club poster, a small-batch zine, or a Risograph-printed program. The entire system runs in one ink color — a warm rust terracotta (#B53D2A) — on a buttery cream paper ground (#FAF1E2), with a subtle 4px radial-dot texture overlay giving the surface its "printed paper" quality. Display type runs in Bricolage Grotesque at weight 700–800 in uppercase; body and metadata run in Fraunces serif at weight 400–600 with optical-size axis engaged. Pill buttons, outlined edition badges, italic-edition numerals, and dashed/solid 1.5px borders complete the printed-program vocabulary.

colors:
  paper: "#FAF1E2"
  paper-d: "#F2E5CF"
  paper-vd: "#E8D7B6"
  ink: "#B53D2A"
  ink-dp: "#8E2D1F"
  rule: "#B53D2A"
  ink-32: "rgba(181, 61, 42, 0.32)"
  ink-78: "rgba(181, 61, 42, 0.78)"
  ink-50: "rgba(181, 61, 42, 0.5)"

color-aliases:
  rule: ink
  ink-32-canonical: "Same ink #B53D2A at 32% opacity, used for dashed dividers and subtle internal rules"
  ink-78-canonical: "Same ink #B53D2A at 78% opacity, used for de-emphasized metadata"

typography:
  display-jumbo-numeral:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(180px, min(22vw, 38vh), 480px)"
    fontWeight: 400
    lineHeight: 0.86
    letterSpacing: -0.02em
    fontStyle: italic
  display-cover:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(82px, min(8.8vw, 15vh), 180px)"
    fontWeight: 800
    lineHeight: 0.92
    letterSpacing: -0.012em
    textTransform: uppercase
  display:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(72px, min(7.6vw, 13vh), 160px)"
    fontWeight: 800
    lineHeight: 0.9
    letterSpacing: -0.012em
    textTransform: uppercase
  headline-xl:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(60px, min(6.4vw, 10.5vh), 140px)"
    fontWeight: 800
    lineHeight: 0.9
    letterSpacing: -0.012em
    textTransform: uppercase
  headline:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(56px, min(6vw, 10vh), 120px)"
    fontWeight: 800
    lineHeight: 0.9
    letterSpacing: -0.012em
    textTransform: uppercase
  headline-md:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(48px, min(5vw, 8.4vh), 100px)"
    fontWeight: 800
    lineHeight: 0.92
    letterSpacing: -0.012em
    textTransform: uppercase
  quote:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(40px, min(4.4vw, 7.4vh), 96px)"
    fontWeight: 700
    lineHeight: 0.95
    letterSpacing: -0.012em
    textTransform: uppercase
  card-title:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(28px, 2.4vw, 44px)"
    fontWeight: 800
    lineHeight: 0.95
    letterSpacing: -0.008em
    textTransform: uppercase
  course-name:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(20px, 1.5vw, 28px)"
    fontWeight: 700
    lineHeight: 1.05
    letterSpacing: -0.005em
    textTransform: uppercase
  info-value:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(20px, 1.6vw, 28px)"
    fontWeight: 700
    lineHeight: 1.1
    letterSpacing: -0.005em
    textTransform: uppercase
  edition-label-tracked:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(15px, 1.1vw, 18px)"
    fontWeight: 700
    letterSpacing: 0.18em
    textTransform: uppercase
  who-tag:
    fontFamily: "'Bricolage Grotesque', sans-serif"
    fontSize: "clamp(15px, 1.05vw, 18px)"
    fontWeight: 700
    letterSpacing: -0.005em
    textTransform: uppercase
  body-serif-italic-lg:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(20px, 1.5vw, 28px)"
    fontWeight: 400
    lineHeight: 1.45
    fontStyle: italic
  body-serif-italic:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(17px, 1.2vw, 22px)"
    fontWeight: 400
    lineHeight: 1.5
    fontStyle: italic
  body-roman:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(15px, 1vw, 17px)"
    fontWeight: 400
    lineHeight: 1.45
  edition-label:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(20px, 1.6vw, 30px)"
    fontWeight: 400
    lineHeight: 1
    fontStyle: italic
  tagline:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(18px, 1.4vw, 26px)"
    fontWeight: 400
    lineHeight: 1.35
    fontStyle: italic
  stats:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(17px, 1.2vw, 22px)"
    fontWeight: 400
    lineHeight: 1.4
    fontStyle: italic
  pill-text:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(15px, 1.1vw, 20px)"
    fontWeight: 400
    lineHeight: 1
    fontStyle: italic
  meta-tag:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(14px, 0.95vw, 16px)"
    fontWeight: 400
    lineHeight: 1.4
    fontStyle: italic
  info-key:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(14px, 0.95vw, 16px)"
    fontWeight: 400
    letterSpacing: 0.16em
    textTransform: uppercase
    fontStyle: italic
  pagenum:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(14px, 0.95vw, 16px)"
    fontWeight: 400
    letterSpacing: 0.02em
    fontStyle: italic
  nav-hint:
    fontFamily: "'Fraunces', Georgia, serif"
    fontSize: "clamp(11px, 0.78vw, 13px)"
    fontWeight: 400
    letterSpacing: 0.02em
    fontStyle: italic

spacing:
  slide-pad-h-default: "clamp(60px, 5vw, 110px)"
  slide-pad-h-wide: "clamp(80px, 7vw, 160px)"
  slide-pad-h-narrow: "clamp(120px, 12vw, 280px)"
  slide-pad-top-default: "clamp(96px, 10vh, 160px)"
  slide-pad-top-cover: "clamp(60px, 6vh, 100px)"
  slide-pad-bottom-default: "clamp(110px, 11vh, 170px)"
  slide-pad-bottom-wide: "clamp(150px, 14vh, 220px)"
  gap-section: "clamp(28px, 3vh, 50px)"
  gap-content: "clamp(18px, 2vh, 32px)"
  gap-row: "clamp(14px, 1.6vh, 24px)"
  gap-tight: "clamp(10px, 1.2vh, 18px)"
  border-weight: "1.5px"
  rule-dashed-color: "{colors.ink-32}"

canvas:
  width: 100vw
  height: 100vh

components:
  pill:
    description: "Outlined rounded-rectangle (border-radius 999px → fully pill) holding short italic Fraunces text. The system's CTA / action button. Border is 1.5px solid {colors.ink}; padding is generous (~12px / 28px); text-color is {colors.ink}."
    border: "1.5px solid {colors.ink}"
    borderRadius: "999px"
    padding: "clamp(8px, 1vh, 14px) clamp(20px, 2vw, 32px)"
    typography: "{typography.pill-text}"
  pill-divider:
    typography: "{typography.pill-text}"
    opacity: 0.7
    description: "A small italic Fraunces divider character (typically · or /) used inline between adjacent pills."
  ed-badge:
    description: "A small circular outlined badge (~38px) holding a single italic Fraunces digit. The edition / chapter ordinal marker. Border is 1.5px solid {colors.ink}; background is transparent."
    width: "clamp(34px, 2.6vw, 44px)"
    height: "clamp(34px, 2.6vw, 44px)"
    border: "1.5px solid {colors.ink}"
    borderRadius: "50%"
  rect-tag:
    description: "Outlined rectangular tag — like the pill but with sharp corners. Holds short italic Fraunces text. Used as a category / status / metadata chip when the pill's roundness isn't appropriate."
    border: "1.5px solid {colors.ink}"
    padding: "clamp(7px, 0.9vh, 12px) clamp(14px, 1.4vw, 22px)"
    typography: "{typography.pill-text}"
  card-outlined:
    description: "A 1.5px ink-outlined rectangular content card. Holds a card-top metadata row (separated below by a 1px @ 32%-opacity rule), a Bricolage card-name, a Fraunces body description, and a meta-row at the bottom (separated above by a 1px dashed @ 32%-opacity rule). The system's primary content card pattern."
    border: "1.5px solid {colors.ink}"
    padding: "clamp(20px, 2vh, 32px) clamp(20px, 1.8vw, 30px)"
    internalDivider-solid: "1px solid {colors.ink-32}"
    internalDivider-dashed: "1px dashed {colors.ink-32}"
  paper-texture:
    description: "Subtle radial-dot texture overlay on the stage. A 4px-tile background-image of 0.5px radial-gradient dots in {colors.ink-50} at 10% opacity. Sits absolutely on the stage with pointer-events disabled, giving the paper its Risograph / printed-stock quality. This is on every slide."
    backgroundImage: "radial-gradient(circle at 1px 1px, {colors.ink-50} 0.5px, transparent 1px)"
    backgroundSize: "4px 4px"
    opacity: 0.1
  topbar-divider:
    description: "A 1.5px ink solid border-bottom under a slide topbar (where a Bricolage headline sits beside a small Fraunces label). The horizontal rule beneath the topbar is the system's universal page-divider device."
    borderBottom: "1.5px solid {colors.ink}"
  pagenum:
    position: "absolute"
    placement: "right: clamp(36px, 3.6vw, 80px); bottom: clamp(40px, 4vh, 64px)"
    typography: "{typography.pagenum}"
    color: "{colors.ink}"
    description: "Italic Fraunces page number at the bottom-right of every slide."
  nav-hint:
    position: "fixed"
    placement: "left: clamp(36px, 3.6vw, 80px); bottom: clamp(40px, 4vh, 64px)"
    typography: "{typography.nav-hint}"
    color: "{colors.ink}"
    opacity: 0.45
    description: "A faint italic Fraunces hint string at the bottom-left of the viewport (e.g. '← → to navigate'). Bonus interactivity affordance."
  ledger-row:
    description: "A horizontal ledger-style row in a calendar/schedule context. Multi-column grid (typical: 80px / 130px / 1.6fr / 0.9fr / auto) with a 1px @ 32%-opacity ink border-bottom. Each cell is a tag, label, or pill. Reads as a guestbook / restaurant-reservation log."
    rowPad: "clamp(11px, 1.3vh, 18px) 0"
    borderBottom: "1px solid {colors.ink-32}"
---

## 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

Long Table is a **single-ink editorial system** in the register of a supper-club poster, a Risograph zine, or a small-press dinner program. The foundational premise is monochromatic: every visible mark in the system — every headline, every paragraph, every border, every rule, every pill, every page number — is rendered in a single warm rust terracotta ink (`{colors.ink}` — #B53D2A) on a buttery cream paper ground (`{colors.paper}` — #FAF1E2). The only chromatic variation is opacity: the same ink at 100% for primary marks, at 78% for de-emphasized metadata, at 32% for dashed internal dividers, at 10% for the paper-texture dots.

The single-ink constraint is the system's identity. The aesthetic borrows from one-color screen printing, letterpress posters, and Risograph stationery — formats where each additional color is a separate printing pass and therefore a deliberate decision. By committing to one ink, the system achieves the calm authority of a printed object rather than the polish of a digital surface.

A signature **paper-texture overlay** sits on every slide: a 4px-tile radial-dot pattern in 50%-opacity ink at 10% opacity, applied via the `.stage::before` pseudo-element. The dots are invisible at conversational viewing distance but visible up close — they give the cream surface its "printed paper" feel and are an essential part of the design system, not optional decoration.

The typographic stack is a two-face pairing:

- **Bricolage Grotesque** at weights 700 and 800 in **strict uppercase** carries every display moment — covers, headlines, card titles, course names, quote bodies, info values, who-tags. Bricolage is a wide, slightly-condensed grotesque with strong personality; its uppercase set has the impact of a hand-lettered poster. The optical-size axis (`opsz` 12..96) is engaged.
- **Fraunces** at weight 400–600 carries every body paragraph, every metadata field, every pill, every page number, every edition label. **Italic Fraunces is the default body style** — the slanted serif is the system's body voice, lending warmth and editorial personality. Roman Fraunces appears only for specific tight cases (info keys, the description body inside index cards). The optical-size axis (`opsz` 9..144) is engaged for both styles.

A massive **italic Fraunces edition numeral** at up to 480px is the system's signature display anchor — it replaces the hand-drawn illustration that would traditionally fill the cover/featured slide right-half, giving the slide a typographic centerpiece in the same ink as the rest of the page.

Depth is **flat and printed**. There are no shadows, no gradients, no blur, no glow. Elevation is communicated entirely through 1.5px solid ink borders on cards, badges, pills, and tags; 1px solid or 1px-dashed internal dividers at 32% opacity; and the texture overlay's atmospheric quality. The whole system reads as ink soaked into paper.

**Density philosophy: rich-but-curated.** Long Table reads as authoritative when slides carry substantive content — a cover with a hero title plus a tagline plus action pills plus stats plus a big edition numeral; an index slide with a topbar headline plus three rich cards; a menu slide with five course rows with name + description + pairing. The slides are full but never crowded — each region carries one focused element with breathing room around it. A slide that holds only a headline reads as missing-its-program; a slide that holds 8 competing content blocks reads as broken. Reach for one major typographic moment (Bricolage display) anchored by 2–4 supporting groups (cards, pills, ledger rows, info-value pairs) per slide.

**Key Characteristics:**
- One ink color (`{colors.ink}` — warm rust terracotta) on cream paper (`{colors.paper}`). Opacity variants are the only color variation.
- Bricolage Grotesque weight 700–800 uppercase for every display moment; Fraunces 400–600 italic-default for every body and metadata moment.
- Subtle 4px radial-dot paper texture on every slide via `.stage::before` — invisible at distance, present up close.
- Pill buttons (border-radius 999px), edition badges (circular), rect-tags (sharp-cornered), and outlined cards (1.5px solid) — all single-weight ink outlines, no fills.
- A massive italic Fraunces edition numeral (up to 480px) is the system's hero typographic anchor on cover-class slides.
- 1.5px structural borders, 1px @ 32%-opacity solid or dashed internal dividers. No thicker borders, no shadows.
- Page number (italic Fraunces) at every slide's bottom-right; nav-hint (italic Fraunces at 45% opacity) at the bottom-left.
- The system is single-ink by design — adding any second color (a navy, a green, a yellow) shatters the printed-program register.

## Colors

### Palette
- **Paper / Cream** (`{colors.paper}` — #FAF1E2): The dominant warm buttery cream surface. Reads as good-quality paper stock — not white, not beige, somewhere between. The default slide background, and the only background fill the system uses.
- **Paper Dark** (`{colors.paper-d}` — #F2E5CF): A slightly darker cream for secondary surfaces or tonal separation. Available in the token system but used sparingly.
- **Paper Very Dark** (`{colors.paper-vd}` — #E8D7B6): A deeper cream for accent surfaces. Reserved.
- **Ink / Warm Rust Terracotta** (`{colors.ink}` — #B53D2A): The single ink color. Every text run, every border, every rule, every pill outline, every page number — all in this one color. The system's structural and expressive color.
- **Ink Deep** (`{colors.ink-dp}` — #8E2D1F): A deeper rust reserved for emphasis. Available in the token system but used sparingly in the published slides.
- **Rule** (`{colors.rule}` — #B53D2A): An alias for `{colors.ink}` — same hex, used semantically when referring to a rule line.
- **Ink @ 78%** (`{colors.ink-78}` — rgba(181,61,42,0.78)): The ink at 78% opacity. Used for de-emphasized metadata text where slightly lower contrast is desired (e.g., pairing notes in menu rows, meta-tags under quotes).
- **Ink @ 50%** (`{colors.ink-50}` — rgba(181,61,42,0.5)): The ink at 50% opacity. Used inside the paper-texture radial-dot gradient.
- **Ink @ 32%** (`{colors.ink-32}` — rgba(181,61,42,0.32)): The ink at 32% opacity. Used for internal dividers — solid 1px lines and 1px dashed lines inside cards, between ledger rows, between course rows.

### Defaults
- **Default slide background**: `{colors.paper}`. Every slide. There is no alternate surface in this system.
- **Default text color**: `{colors.ink}`. Every text run.
- **Default border color**: `{colors.ink}` at 1.5px solid for structural borders; `{colors.ink-32}` at 1px solid or dashed for internal dividers.
- **Default headline color**: `{colors.ink}`.
- **Default body color**: `{colors.ink}`.
- **Default page-number / nav-hint color**: `{colors.ink}` (full opacity for pagenum; 45% opacity for nav-hint).
- **Default de-emphasized metadata color**: `{colors.ink-78}` — when a small piece of supporting text needs to recede from a primary line.

The palette is intentionally single-ink. There is no "accent color" to reach for — the design language depends on the one-ink constraint. If a moment needs to stand out, scale up the type (Bricolage 800 at 180px) or reach for the italic Fraunces edition numeral; do not introduce a second color.

## Typography

### Font Family
The system loads exactly two web fonts from Google Fonts, both with optical-size axes:

- **Bricolage Grotesque** with `opsz` 12..96 and weights 400, 600, 700, 800. **In the published slides, only 700 and 800 are used.**
- **Fraunces** with `opsz` 9..144, both roman and italic styles, weights 400, 500, 600. **In the published slides, all three weights of italic and weight 400/600 of roman are used.**

The two-face role split is strict: **Bricolage uppercase carries every display moment** (covers, headlines, card titles, course names, quote bodies, info values, who-tags, edition labels with tracking). **Fraunces italic carries every body moment** (paragraphs, leads, metadata, taglines, pills, page numbers, info keys, edition labels without tracking). **Fraunces roman** is reserved for specific tight roles (info keys in info-rows where italic tracking would feel out of place, and the description body inside index cards where roman is more readable).

The optical-size axis is critical: the same Fraunces face renders with subtly different letterforms at 14px metadata sizes versus 480px hero-numeral sizes — small sizes pick up sturdier strokes; large sizes pick up finer detail. Self-hosted fallbacks without `opsz` will lose this quality.

### Display, Body, and Chrome Scale

| Token | Size | Family | Weight / Style | Use |
|---|---|---|---|---|
| `{typography.display-jumbo-numeral}` | up to 480px | Fraunces | 400 italic | Hero edition numeral (cover-class typographic anchor) |
| `{typography.display-cover}` | up to 180px | Bricolage | 800 uppercase | Cover-scale Bricolage title |
| `{typography.display}` | up to 160px | Bricolage | 800 uppercase | Section-opener / manifesto headline |
| `{typography.headline-xl}` | up to 140px | Bricolage | 800 uppercase | Featured-edition title |
| `{typography.headline}` | up to 120px | Bricolage | 800 uppercase | Topbar headline on index / calendar slides |
| `{typography.headline-md}` | up to 100px | Bricolage | 800 uppercase | Menu / programme title |
| `{typography.quote}` | up to 96px | Bricolage | 700 uppercase | Pull-quote / testimonial body |
| `{typography.card-title}` | up to 44px | Bricolage | 800 uppercase | Title inside an outlined card |
| `{typography.course-name}` | up to 28px | Bricolage | 700 uppercase | Course / item name in a ledger row |
| `{typography.info-value}` | up to 28px | Bricolage | 700 uppercase | Value in a key/value info row |
| `{typography.edition-label-tracked}` | up to 18px | Bricolage | 700 uppercase / 0.18em | Big-edition label beneath a hero numeral |
| `{typography.who-tag}` | up to 18px | Bricolage | 700 uppercase | Attribution name in a quote row |
| `{typography.body-serif-italic-lg}` | up to 28px | Fraunces | 400 italic | Lead paragraph in a manifesto / letter |
| `{typography.body-serif-italic}` | up to 22px | Fraunces | 400 italic | Standard body paragraph / lede |
| `{typography.body-roman}` | up to 17px | Fraunces | 400 roman | Card description body (tighter setting for legibility at small size) |
| `{typography.edition-label}` | up to 30px | Fraunces | 400 italic | "EDITION N." italic label beside an edition badge |
| `{typography.tagline}` | up to 26px | Fraunces | 400 italic | Tagline / subtitle beneath a cover title |
| `{typography.stats}` | up to 22px | Fraunces | 400 italic | Stats line ("N seats · M cities · L hours") |
| `{typography.pill-text}` | up to 20px | Fraunces | 400 italic | Text inside a pill button or rect-tag |
| `{typography.meta-tag}` | up to 16px | Fraunces | 400 italic | Card metadata (city tag, num tag, seats tag, date tag) |
| `{typography.info-key}` | up to 16px | Fraunces | 400 italic / 0.16em / UPPER | Key in a key/value info row |
| `{typography.pagenum}` | up to 16px | Fraunces | 400 italic | Page number at the bottom-right of every slide |
| `{typography.nav-hint}` | up to 13px | Fraunces | 400 italic / 45% opacity | Navigation hint at the bottom-left of the viewport |

### Defaults
- **Default size for a primary slide headline**: `{typography.headline}` (up to 120px) in Bricolage 800 uppercase.
- **Default size for a cover-scale title**: `{typography.display-cover}` (up to 180px).
- **Default size for the hero typographic anchor on cover-class slides**: `{typography.display-jumbo-numeral}` (italic Fraunces up to 480px) — the system's signature hero element.
- **Default size for a body paragraph**: `{typography.body-serif-italic}` (up to 22px) in italic Fraunces.
- **Default size for a lede paragraph**: `{typography.body-serif-italic-lg}` (up to 28px).
- **Default size for body text inside a card**: `{typography.body-roman}` (up to 17px) in **roman** Fraunces — the roman is more readable at small sizes than italic.
- **Default size for an "EDITION N." label**: `{typography.edition-label}` (up to 30px) in italic Fraunces, paired with an `{components.ed-badge}` circular ordinal.
- **Default weight for any Bricolage display moment**: 800. (Weight 700 is reserved for the quote body and course/who-tag elements; weight 800 is the primary display weight.)
- **Default weight for any Fraunces body moment**: 400.

When unsure, reach for `{typography.headline}` (up to 120px) for a routine slide headline. The 140–180px tier is for featured-edition titles and covers; the 160px tier is for section openers. Use the jumbo edition numeral when the slide is a cover-class moment and needs a hero anchor.

### Signature Treatments
These treatments are **non-optional whenever the corresponding element type is used**:

- **Every Bricolage display element is UPPERCASE with negative letter-spacing (-0.005em to -0.012em).** A sentence-case Bricolage headline does not exist in this system. The uppercase + negative-tracking + weight 800 combination is the system's display voice.
- **Every Fraunces body element is italic by default.** Roman Fraunces appears only for specific tight cases (info-key in info-rows, body inside index cards). When in doubt, italic.
- **The edition badge (`{components.ed-badge}`) is always paired with an italic edition label** — the circle ordinal and the "EDITION N." text are one unit. Using one without the other reads as broken.
- **Every card / pill / rect-tag / badge carries a 1.5px solid ink border with no fill.** The single-weight outlined-shape vocabulary is the system's structural language. Filled shapes do not exist.
- **The paper-texture overlay (`{components.paper-texture}`) is on every slide.** Removing it (or running the system on a pure flat cream without texture) loses the printed-paper quality.
- **Every slide carries the page-number marker** at bottom-right in italic Fraunces. The page-number is the system's spine — without it, slides feel unanchored.
- **Internal dividers inside cards alternate between 1px solid @ 32% opacity (above content) and 1px dashed @ 32% opacity (below content).** The solid/dashed pairing is the system's card-rhythm device.

### Typography Principles
The weight 800 + uppercase + negative letter-spacing combination is the system's Bricolage voice. Switching any of those three properties (e.g., weight 700 uppercase, or weight 800 sentence case, or default tracking) reads as a different design system. The Fraunces italic-default + opsz-axis combination is the system's body voice — using a non-opsz fallback face flattens the quality at small sizes.

Underline is not used. Bold within body paragraphs uses Fraunces weight 600 (not 700/800). Color emphasis does not exist because there is only one color. The system's only emphasis mechanisms are: scale (bigger Bricolage), weight shift inside body (Fraunces 400 → 600), italic ↔ roman switch, and opacity (full → 78%).

## Layout

### Canvas System
The system targets a fluid viewport — each `.slide` is `100vw × 100vh` with absolute positioning. Slides stack inside a `.stage` container with the paper-texture overlay sitting absolutely on the stage. Only one `.slide.active` is visible at a time; opacity transitions between slides take 280ms.

### Padding Scale (uses `clamp()` ranges)
| Token | Range | Use |
|---|---|---|
| `{spacing.slide-pad-h-default}` | clamp(60px, 5vw, 110px) | Default horizontal slide padding |
| `{spacing.slide-pad-h-wide}` | clamp(80px, 7vw, 160px) | Wider horizontal padding for featured / calendar slides |
| `{spacing.slide-pad-h-narrow}` | clamp(120px, 12vw, 280px) | Narrow horizontal padding for menu / quote slides (forces content into a column) |
| `{spacing.slide-pad-top-default}` | clamp(96px, 10vh, 160px) | Default top padding |
| `{spacing.slide-pad-top-cover}` | clamp(60px, 6vh, 100px) | Cover top padding (less, to give the title room) |
| `{spacing.slide-pad-bottom-default}` | clamp(110px, 11vh, 170px) | Default bottom padding (leaves room for page-num chrome) |
| `{spacing.slide-pad-bottom-wide}` | clamp(150px, 14vh, 220px) | Wider bottom padding for featured / quote slides |
| `{spacing.gap-section}` | clamp(28px, 3vh, 50px) | Between major content sections |
| `{spacing.gap-content}` | clamp(18px, 2vh, 32px) | Between related content blocks |
| `{spacing.gap-row}` | clamp(14px, 1.6vh, 24px) | Between row-level elements (course rows, ledger rows) |
| `{spacing.gap-tight}` | clamp(10px, 1.2vh, 18px) | Between tightly coupled elements |

### Chrome Anatomy
Every slide carries a **page-number marker** at the bottom-right (italic Fraunces, ~16px max). The viewport also carries a **nav-hint** at the bottom-left (italic Fraunces, 45% opacity), suggesting keyboard navigation. These two chrome elements are the system's universal slide anchors.

Slides with a topbar (index, calendar) carry a Bricolage headline on the left + a small italic Fraunces label-tag on the right, separated below by a 1.5px solid ink horizontal rule. The topbar-divider is the system's universal page-divider device.

### Border-Radius
- **999px** — pill buttons (fully pill-shaped)
- **50%** — circular edition badges
- **0** — every other shape (cards, rect-tags, info-cards, ledger rows, internal dividers)

The system uses sharp corners for content containers and pill/circle for action and ordinal markers. No medium border-radius values (4px, 8px, 12px) exist.

## Depth and Elevation

### Flat, No Shadows
The system uses **zero shadows**. No box-shadow, no text-shadow, no filter, no gradient. Elevation is communicated entirely through:

1. **1.5px solid ink borders** on cards, pills, badges, rect-tags — the outlined-shape vocabulary is the system's structural depth.
2. **1px solid or dashed internal dividers at 32% opacity** inside cards and between rows — the subtle horizontal lines give cards their internal rhythm.
3. **The paper-texture overlay** at 10% opacity on every slide — the dotted texture sits atmospherically beneath all content, giving the page its print-stock quality.
4. **Opacity layering on text** — primary at 100%, de-emphasized metadata at 78%, near-invisible dividers at 32%.

The absence of shadow is itself the depth language. Adding `box-shadow: 0 4px 12px rgba(0,0,0,0.1)` shatters the printed-paper feel.

### Paper Texture as Atmospheric Depth
The radial-dot texture on `.stage::before` is part of the depth system — it is not optional decoration. The texture gives the cream surface a quality that flat #FAF1E2 lacks: a sense that the surface is paper stock with grain, not a CSS background fill. The 4px tile size with 0.5px radial dots in 50%-opacity ink at 10% overall opacity is calibrated to be invisible at conversational viewing distance and just-visible at close inspection.

## Shapes and Treatment

### Border Weight and Style
- **1.5px solid `{colors.ink}`** — the universal structural border. Cards, pills, edition badges, rect-tags, topbar dividers, who-row top borders, info-card outlines.
- **1px solid `{colors.ink-32}`** — internal solid dividers inside cards (between card-top metadata and the card title), between ledger rows, between course rows.
- **1px dashed `{colors.ink-32}`** — internal dashed dividers inside cards (between the card body and the meta-row at the bottom), between info-rows in info-cards.

Borders are never thicker than 1.5px. Never colored beyond ink (full or 32%). Never dotted (dotted is reserved for the paper-texture pattern). The solid/dashed pairing inside cards is the system's signature rhythm device.

### Decorative Element Types

**Paper Texture Overlay** (`{components.paper-texture}`) — A 4px-tile radial-dot pattern in 50%-opacity ink at 10% overall opacity on `.stage::before`. The system's atmospheric base; on every slide.

**Pill Button** (`{components.pill}`) — An outlined fully-rounded-rectangle (border-radius 999px) holding short italic Fraunces text. The system's CTA / action button. Pills cluster in action rows (e.g., cover action row).

**Pill Divider** (`{components.pill-divider}`) — A small italic Fraunces character (typically `·` or `/`) at 70% opacity placed between pills in a row.

**Edition Badge** (`{components.ed-badge}`) — A ~38px circular outlined badge holding a single italic Fraunces digit. The system's edition / chapter ordinal marker; always paired with an italic "EDITION N." label.

**Rect Tag** (`{components.rect-tag}`) — An outlined sharp-cornered rectangular tag holding short italic Fraunces text. The sharp-cornered cousin of the pill; used where roundness isn't appropriate.

**Outlined Card** (`{components.card-outlined}`) — A 1.5px ink-outlined rectangular card. Holds a card-top metadata row (separated below by a 1px @ 32% solid divider), a Bricolage card title, a Fraunces body description, and a meta-row at the bottom (separated above by a 1px @ 32% dashed divider). The system's primary content card.

**Topbar with Divider** — A Bricolage headline on the left + a small italic Fraunces label-tag on the right, separated below by a 1.5px solid ink horizontal rule. The system's universal section opener.

**Info-Card** — A wider outlined card with internal info-rows (key / value pairs separated by 1px @ 32% dashed dividers). Used as a featured-edition supporting panel.

**Ledger Row** (`{components.ledger-row}`) — A multi-column grid row with a 1px @ 32% solid border-bottom. Holds tags, labels, and pills aligned in columns. The system's calendar / schedule / index pattern.

**Course Row** — A 64px / 1fr / auto grid row with a 1px @ 32% solid border-bottom. Holds a Fraunces num-tag, an item (Bricolage name + Fraunces description), and a Fraunces pairing tag. The menu / programme pattern.

**Italic Jumbo Edition Numeral** — A massive italic Fraunces digit at up to 480px. The system's signature hero typographic anchor on cover-class slides, paired with a small tracked Bricolage label beneath and an italic Fraunces meta line.

**Page Number** (`{components.pagenum}`) — Italic Fraunces at the bottom-right of every slide.

**Nav Hint** (`{components.nav-hint}`) — Italic Fraunces at 45% opacity at the bottom-left of the viewport, suggesting keyboard navigation.

## Do's and Don'ts

### Do
- Commit to single-ink rendering. Every text, border, rule, badge, and pill is `{colors.ink}` — the warm rust terracotta. Use opacity (78%, 32%, 10%) for variation, never a different hue.
- Apply the paper-texture overlay to every slide. The 4px radial-dot pattern at 10% opacity is part of the design system, not optional polish.
- Run every Bricolage display element at weight 800 (or 700 for quote / course-name / who-tag) in strict uppercase with negative letter-spacing.
- Run every Fraunces body element in italic by default. Use roman only for info-keys (where italic tracking would feel out of place) and card body descriptions (where italic at small size is less readable).
- Reach for the italic Fraunces jumbo numeral (up to 480px) as the hero typographic anchor on cover-class slides. It's the system's signature.
- Pair every edition badge with an italic "EDITION N." Fraunces label — the circle ordinal and the text label are one unit.
- Use the outlined-card pattern (1.5px ink border + internal 1px @ 32% solid divider above content + 1px @ 32% dashed divider below content) for primary content cards. The solid/dashed pairing is the system's rhythm.
- Use the pill (border-radius 999px) and the rect-tag (sharp corners) intentionally — pill for actions, rect for metadata / status. Don't conflate them.
- Place the page-number marker (italic Fraunces, bottom-right) on every slide. The marker is the system's spine.
- Keep slides rich-but-curated: one major Bricolage display moment + 2–4 supporting groups (cards, pills, ledger rows, info pairs). Single-element slides feel underweight; 8-element slides feel broken.

### Don't
- Don't introduce a second ink color. The system is single-ink — adding a navy, green, yellow, or any second hue shatters the printed-program register.
- Don't fill any shape. Cards, pills, badges, rect-tags are outline-only. Filled rectangles in the ink color do not exist.
- Don't use box-shadow, gradient, blur, or filter on any element. The system is flat printed paper.
- Don't omit the paper-texture overlay. A flat #FAF1E2 background without the dot pattern reads as digital, not paper.
- Don't run Bricolage in sentence case. Bricolage is always uppercase with negative tracking and weight 700 or 800.
- Don't render Fraunces in roman by default. Italic is the body voice; roman is the exception for specific tight cases.
- Don't use thicker borders (2px+). The 1.5px structural border weight is the system's commitment.
- Don't use a medium border-radius (4px, 8px, 12px). The system uses 999px (pill), 50% (badge), or 0 (everything else).
- Don't pair the edition badge with a non-Fraunces label or skip the label entirely. The badge-and-label unit is the system's edition marker.
- Don't crowd a slide with 8 small elements. Reach for fewer, larger groups with breathing room.

## Responsive Behavior

The system uses **`clamp()` units throughout** — every size, padding, gap, and rule scales fluidly between minimum and maximum based on viewport width and height. The same composition renders correctly on a 1280×720 laptop, a 1920×1080 monitor, and a 2560×1440 display without media queries.

### Scaling Behavior
- Bricolage display sizes clamp between a min (e.g. 60px), a vw/vh-based middle value, and a max (e.g. 140px). The `min()` inner function combines width-based and height-based caps so headlines never overflow on short viewports.
- Fraunces body sizes follow the same pattern but with smaller ranges.
- Padding and gaps scale linearly with vw/vh.
- The 1.5px structural border and 1px @ 32% internal dividers are fixed-pixel and do not scale, which means at larger viewports the borders appear proportionally finer. This is by design.

### Presenter Behavior
- Slides advance via keyboard navigation (handled by deck JavaScript).
- Only one `.slide.active` is visible at a time; non-active slides are `opacity: 0; pointer-events: none`.
- Slide-to-slide transition is a 280ms opacity fade.
- The nav-hint at the bottom-left ("← → to navigate") tells the viewer how to advance.

### Print / Export
There is no `@media print` rule in the system. Print export will render only the active slide; multi-slide print requires per-slide rendering or a dedicated print stylesheet.

## CJK & International Content

### Recommended Chinese Pairing

| Role | Chinese Face | Weight | Why |
|---|---|---|---|
| Display / cover / headline (Bricolage roles, 96–180px) | 思源宋体 Noto Serif SC | 700 | Mincho heavy weight carries the printed-program mass that Bricolage 800 provides in Latin |
| Card title / course-name / info-value (28–44px) | 思源宋体 Noto Serif SC | 700 | Same Mincho voice at smaller sizes for consistency |
| Hero edition numeral (480px italic Fraunces) | 思源宋体 Noto Serif SC | 400 | Use a Chinese ordinal character (一二三 / 春夏秋) for the hero anchor instead of a Western digit |
| Body / lede / tagline (Fraunces italic roles) | 思源宋体 Noto Serif SC | 400 | Mincho body voice — warmth without italic, since Chinese has no italic |
| Pill text / meta-tag / pagenum | 思源宋体 Noto Serif SC | 400 | Keep all chrome in Mincho 400; the system's single-ink discipline carries through |
| Info-key / edition-label-tracked (uppercase tracked roles) | 思源宋体 Noto Serif SC | 400 with 0.16em letter-spacing | Maintains the tracked-chrome feel |

### Mixed-Content Strategy

Use **Strategy A** — switch the entire face stack to Noto Serif SC across all roles, replacing both Bricolage Grotesque (display) and Fraunces (body). Long Table is a minimal single-ink data / program system where the typographic personality is carried more by the **single-ink rust terracotta**, the **outlined-shape vocabulary**, and the **paper-texture overlay** than by the specific Latin faces. Going all-Mincho in Chinese preserves the printed-program register cleanly without the per-glyph baseline wobble that Strategy C would introduce on a system this typographically dense. Stack:

```css
/* Bricolage roles (display, headline, card-title, course-name, info-value) */
font-family: 'Bricolage Grotesque', 'Noto Serif SC', sans-serif;
/* Fraunces roles (body, lede, tagline, pill, pagenum, edition-label) */
font-family: 'Fraunces', 'Noto Serif SC', Georgia, serif;
```

When the deck content is pure Chinese, override both font stacks to lead with Noto Serif SC. Bricolage roles get weight 700 (matches 800 mass in Mincho), Fraunces roles get weight 400.

### Loading

Add to the existing Google Fonts `<link>`:

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;700&display=swap" rel="stylesheet">
```

### Universal CJK Adjustments

These adjustments apply to **every CJK block** in this system, regardless of size or role:

- **Loosen line-height by 0.05–0.08.** CJK glyphs are full-width squares with more visual weight than Latin letterforms; line-heights tuned for Latin (0.86–0.95 on display, 1.45–1.5 on body) read as cramped in Chinese. Bump display to 1.0–1.1 and body to 1.55–1.65.
- **Remove negative letter-spacing on CJK headlines.** Bricolage display uses -0.005em to -0.012em tracking, which collides Chinese glyphs into each other. For CJK runs, set `letter-spacing: 0` — or a tiny positive `0.02em` if the headline feels visually packed.
- **Never `text-transform: uppercase` on CJK text.** Chinese has no case; the CSS property does nothing on Han glyphs but will silently break any mixed-script line where the Bricolage portion was meant to be capitalized. (This matters here — every Bricolage display element in the source is `text-transform: uppercase`.)
- **Use Chinese full-width punctuation** (`，。：；！？「」『』（）`) inside Chinese sentences, not the Latin equivalents (`,.:;!?""''()`). Mixing punctuation systems within one sentence reads as a typesetting error.
- **No period (。) at the end of CJK headlines.** Chinese headlines follow the same rule as Latin — title-style lines drop terminal punctuation. Body paragraphs keep their 。
- **Apply Pangu spacing (盘古之白) at the boundary between CJK and Latin runs.** A space (or 0.25em margin) belongs between a Chinese character and an adjacent Latin word or digit, e.g. `2026 年 5 月` not `2026年5月`. Either type the spaces manually or use a `pangu.js`-style auto-spacer.
- **One font per sentence.** Don't switch between Noto Serif SC weight 400 and 700 inside the same sentence — pick the weight that matches the role (headline = 700, body = 400) and commit to it for the whole run.

### Aesthetic Notes for This System

Long Table's whole voice is "supper-club poster / Risograph zine / small-press dinner program" — single-ink rust terracotta on cream, outlined shapes, paper-texture overlay. In Chinese, the system's identity does not depend on the specific Latin faces (Bricolage and Fraunces); it depends on the **single-ink commitment**, the **1.5px outlined-shape vocabulary**, the **4px radial-dot paper texture**, and the **rich-but-curated density**. Going all-Noto-Serif-SC preserves every one of those identity markers cleanly.

The default-italic body rule does not translate to Chinese (Chinese has no italic concept; slanted Han glyphs read as broken, not as a body voice). In Chinese, every Fraunces-italic role simply becomes **Noto Serif SC weight 400 upright** — the warmth comes from the Mincho character itself, not from the slant. This is the right trade-off for this system.

The hero italic Fraunces jumbo numeral (up to 480px) is the system's signature anchor in Latin — a single italic digit acting as a typographic centerpiece. In Chinese, **use a Chinese ordinal or season character instead of a Western digit**: 「三」、「五」、「春」、「秋」, rendered in Noto Serif SC at weight 400. The Han glyph's denser visual weight at 480px balances the cover slide better than a Western digit would; the cream paper background and warm rust ink carry the printed-program feel through unchanged.

The system's outlined-shape vocabulary (pills, edition badges, rect-tags, outlined cards) works identically in Chinese — no adjustments needed. The "EDITION N." label paired with the circular badge becomes 「第三期」or 「第 03 期」inside the circle, with the meta-label below in Noto Serif SC 400. The 32%-opacity solid / dashed internal divider rhythm is purely structural and unaffected by language.

### Known CJK Gap

The Fraunces italic-default body voice is one of Long Table's most distinctive typographic moves in Latin — italic Mincho-style serif body that gives the system its lyrical, hand-written warmth. Chinese has no equivalent: there is no commonly-available "italic Mincho" face on the Google Fonts CDN, and slanted Han glyphs read as broken regardless. The Chinese rendering loses the italic-default character — every body line becomes upright Noto Serif SC weight 400. This is a real loss of personality, partially compensated by Noto Serif SC's own warmth at body sizes, but Chinese-content Long Table decks read measurably more "neutral magazine" than "supper-club poster." For decks where this matters, lean harder on the **single-ink color** and the **paper-texture overlay** to carry the warmth that the italic body would have carried in Latin.

## Iteration Guide

1. Any new mark on a slide is in `{colors.ink}` — full opacity for primary, 78% for de-emphasized metadata, 32% for internal dividers. No second color.
2. Any new headline is Bricolage Grotesque weight 800 uppercase with negative letter-spacing. Pick the size from the headline ladder (96 / 100 / 120 / 140 / 160 / 180px max) — do not invent a new size.
3. Any new body paragraph is Fraunces italic at weight 400. Use roman only for info-keys (tracked uppercase) and card-body descriptions.
4. Any new edition / ordinal marker uses the `{components.ed-badge}` (circular outline) paired with an italic "EDITION N." Fraunces label.
5. Any new action button is the `{components.pill}` (border-radius 999px); any new metadata tag is the `{components.rect-tag}` (sharp corners). Don't conflate the two.
6. Any new card is the `{components.card-outlined}` pattern: 1.5px ink border, internal 1px @ 32% solid divider above content, internal 1px @ 32% dashed divider below content.
7. Any new ledger / schedule / calendar row uses the multi-column grid + 1px @ 32% solid border-bottom pattern (`{components.ledger-row}`).
8. Any new section opener uses the topbar pattern: Bricolage headline + small italic Fraunces label on the right + 1.5px solid ink horizontal rule beneath.
9. Any new cover-class moment reaches for the italic Fraunces jumbo edition numeral as the hero typographic anchor — paired with a small tracked Bricolage label beneath and a italic Fraunces meta line.
10. Every slide carries the page-number marker. If you skip it, the slide will feel unanchored.

## Known Gaps

- The two Google Fonts (Bricolage Grotesque with `opsz` 12..96, Fraunces with `opsz` 9..144) are loaded via `<link>`. Offline rendering will fall back to system sans (for Bricolage) and Georgia (for Fraunces) — which loses the optical-size axis and the personality of both faces. Self-hosting recommended for offline / print reliability.
- The `opsz` optical-size axis is critical to quality at large display sizes (480px jumbo numeral) and small metadata sizes (14px page-number). Fallback faces without `opsz` will look noticeably flat at the extremes.
- The system is single-ink by design. If a deck needs a second emphasis color (a "callout" or "warning" hue), the system cannot accommodate it without breaking the printed-program register. Use Bricolage scale + opacity + italic/roman switch as the only emphasis mechanisms.
- The paper-texture overlay uses a `background-image` radial-gradient that may render with subtle compression artifacts on some browsers at high zoom. The texture is essential to the system identity; do not remove it as a "performance optimization."
- Body paragraphs are italic by default. For deck content where italic at body scale is hard to read (long technical paragraphs, code samples), the system has no clean fallback — italic is the body voice. Keep paragraphs short and lyrical.
- The CSS has several empty rule blocks (`.body-it { ... }`, `.s-cover .stats .num { font-weight: 600; }` etc.) where the original commented-out italic / weight properties have been stripped. The intended treatment in many places is "italic Fraunces at weight 400" — the default style — but the empty blocks make this implicit rather than explicit. Treat italic as the default everywhere the comments hint at it.
- The system loads Bricolage weights 400 and 600 and Fraunces weights 500 — these are not actively used in the published CSS. Using them would introduce intermediate weights that break the single-weight commitment per face.
- The fallback `.body-it` and `.body-ro` utility classes are defined but use the explicit class names sparingly in the markup. Most slides set typography per-element rather than via the utility classes — copy the per-element styles when authoring new slides, not the utilities.
- The hero italic Fraunces jumbo numeral at 480px is a literal numeral character — there is no glyph alternation or kerning fix for specific characters. The "0" and "8" glyphs may need optical adjustment at extreme sizes; check rendering at the target viewport.
- The system has no `@media print` rule. Print export will not paginate; treat Long Table as screen-first.
````

---

## 2. 글씨체

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

---

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

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

**1장(표지)에서 처음 나오는 부품**
- `.badge` — 1·6장 — 예: `<i class="badge">`
- `.ed` — 1장 — 예: `<div class="ed">`
- `.el` — 1·6장 — 예: `<span class="el">`
- `.gk` — 1장 — 예: `<em class="gk">`
- `.gl` — 1장 — 예: `<span class="rt gl">`
- `.hero` — 1장 — 예: `<div class="hero">`
- `.jl` — 1장 — 예: `<span class="jl">`
- `.jm` — 1장 — 예: `<span class="jm">`
- `.jn` — 1장 — 예: `<span class="jn">`
- `.pdiv` — 1·2·5장 — 예: `<span class="pdiv">`
- `.pill` — 1·2·5·6장 — 예: `<span class="pill">`
- `.pills` — 1장 — 예: `<div class="pills">`
- `.rt` — 1·2·3·4·5·6장 — 예: `<span class="rt">`
- `.slide` — 1·2·3·4·5·6장 — 예: `<section class="slide">`
- `.stats` — 1장 — 예: `<p class="stats">`
- `.t1` — 1장 — 예: `<h1 class="t1">`
- `.tag` — 1장 — 예: `<p class="tag">`
- `.unit` — 1장 — 예: `<p class="unit">`

**2장(흐름·단계)에서 처음 나오는 부품**
- `.acts` — 2장 — 예: `<div class="acts">`
- `.btn` — 2·5장 — 예: `<button class="pill btn" data-act="step">`
- `.cap` — 2장 — 예: `<p class="cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quo…`
- `.card` — 2·3·4·5·6장 — 예: `<div class="card fig">`
- `.cd` — 2장 — 예: `<span class="cd">`
- `.cm` — 2·4·5·6장 — 예: `<div class="cm">`
- `.course` — 2장 — 예: `<div class="course" data-s="1">`
- `.ct` — 2·3·4·5·6장 — 예: `<div class="ct">`
- `.fig` — 2장 — 예: `<div class="card fig">`
- `.menu` — 2장 — 예: `<div class="menu">`
- `.mt` — 2·3·4·5·6장 — 예: `<span class="mt">`
- `.nt` — 2장 — 예: `<span class="nt">`
- `.num` — 2장 — 예: `<span class="num">`
- `.topbar` — 2·3·4·5·6장 — 예: `<div class="topbar">`

**3장(숫자와 그래프)에서 처음 나오는 부품**
- `.av` — 3장 — 예: `<span class="av">`
- `.ledger` — 3·4장 — 예: `<div class="ledger">`
- `.lh` — 3·4장 — 예: `<div class="lr lh">`
- `.lr` — 3·4장 — 예: `<div class="lr lh">`
- `.mx` — 3장 — 예: `<div class="lr mx">`
- `.nr` — 3·5장 — 예: `<p class="nr">`
- `.sm` — 3·5·6장 — 예: `<em class="rt sm">`
- `.src` — 3장 — 예: `<p class="src">`
- `.st` — 3장 — 예: `<div class="card st">`
- `.stats3` — 3장 — 예: `<div class="stats3">`
- `.sv` — 3장 — 예: `<span class="sv">`
- `.tm` — 3장 — 예: `<span class="tm">`
- `.track` — 3장 — 예: `<span class="track">`

**4장(비교와 표)에서 처음 나오는 부품**
- `.cmp` — 4장 — 예: `<div class="cmp">`
- `.info` — 4장 — 예: `<div class="card info">`
- `.ir` — 4장 — 예: `<p class="ir">`
- `.it4` — 4장 — 예: `<p class="it4">`
- `.qt` — 4장 — 예: `<blockquote class="qt">`
- `.t4` — 4장 — 예: `<div class="ledger t4">`
- `.who` — 4장 — 예: `<span class="who">`

**5장(확인(퀴즈·빈칸))에서 처음 나오는 부품**
- `.blank` — 5장 — 예: `<button class="blank" data-blank aria-pressed="false">`
- `.blk` — 5장 — 예: `<div class="card blk">`
- `.br` — 5장 — 예: `<p class="br">`
- `.fb` — 5장 — 예: `<p class="fb" data-fb>`
- `.opt` — 5장 — 예: `<button class="pill opt" data-opt="0">`
- `.opts` — 5장 — 예: `<div class="opts">`
- `.q` — 5장 — 예: `<h3 class="q">`
- `.quiz` — 5장 — 예: `<div class="card quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다…`
- `.rty` — 5장 — 예: `<button class="pill btn rty" data-act="retry">`
- `.words` — 5장 — 예: `<div class="words">`

**6장(디자인 안내(시연))에서 처음 나오는 부품**
- `.a` — 6장 — 예: `<div class="card d6 a">`
- `.ab6` — 6장 — 예: `<p class="ab6">`
- `.b` — 6장 — 예: `<div class="card d6 b">`
- `.c` — 6장 — 예: `<div class="card d6 c">`
- `.d6` — 6장 — 예: `<div class="card d6 a">`
- `.dh` — 6장 — 예: `<div class="dh">`
- `.ed6` — 6장 — 예: `<span class="ed6">`
- `.g6` — 6장 — 예: `<div class="card g6">`
- `.rg6` — 6장 — 예: `<div class="rg6">`
- `.rh6` — 6장 — 예: `<div class="rh6" id="lt-rh">`
- `.rw6` — 6장 — 예: `<div class="rw6">`
- `.sl6` — 6장 — 예: `<span class="rt sl6">`
- `.sw6` — 6장 — 예: `<span class="sw6">`
- `.tx6` — 6장 — 예: `<div class="tx6" id="lt-tex">`

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

**직접 쓰지 말 것**: 엔진이 상태를 나타내려고 붙이는 클래스(`.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="long-table">
<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=Bricolage+Grotesque:opsz,wght@12..96,700;12..96,800&family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,600;1,9..144,400;1,9..144,600&display=swap">
<!-- 이 디자인의 공통 CSS(글씨체·색·부품 모양). 이 줄은 지우거나 바꾸지 마세요 -->
<link rel="stylesheet" href="https://k-slide.web.app/kit/v1/long-table.css">
<style>
/* === 추가 부품: 새 클래스가 꼭 필요할 때만 이 줄 아래에 정의하세요(공통 CSS는 위 <link>가 이미 불러옴 — 여기에 옮겨 쓰지 않음) === */
</style>
</head>
<body>
<div class="deck-viewport">
  <main class="deck-stage" id="deckStage">
<section class="slide">
  <div class="ed"><i class="badge">3</i><span class="el">Edition 3.</span><span class="rt">1단원 · 3~4차시</span></div>
  <p class="unit">계절의 변화<span>Sun, Shadow & Temperature</span></p>
  <span class="rt gl">학습 목표</span>
  <h1 class="t1">하루 동안 <em class="gk">태양 고도</em>,<br><em class="gk">그림자 길이</em>, <em class="gk">기온</em>의 관계</h1>
  <p class="tag">초등 과학 · 6학년 2학기</p>
  <div class="pills"><span class="pill">자 붙이기</span><span class="pdiv">·</span><span class="pill">수수깡 꽂기</span><span class="pdiv">·</span><span class="pill">실 묶기</span><span class="pdiv">·</span><span class="pill">각도기 끼우기</span></div>
  <p class="stats"><b>4</b> 단계 · <b>7</b> 번 측정 · <b>3</b> 가지 변화</p>
  <div class="hero"><span class="jn">03</span><span class="jl">00초등학교</span><span class="jm">2026, a small science programme</span></div>
</section>
<section class="slide" data-steps="4">
  <div class="topbar"><h2>태양 고도 측정기 만들기</h2><span class="rt">측정 준비</span></div>
  <div class="card fig"><div class="ct"><span class="rt">FIG. 01</span><span class="mt">태양 고도 측정기</span></div><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 class="cm"><p><b>태양 고도</b> — 태양이 지표면과 이루는 각</p><p class="mt">막대기의 그림자와 실이 이루는 각 = 태양 고도</p></div></div>
  <div class="acts"><button class="pill btn" data-act="step">다음 단계 →</button><span class="pdiv">/</span><button class="pill btn" data-act="reset">처음부터</button></div>
  <p class="cap" data-caps="[&quot;버튼을 눌러 순서대로 만들어 보세요&quot;,&quot;01 — 자 붙이기&quot;,&quot;02 — 수수깡 꽂기&quot;,&quot;03 — 실 묶기&quot;,&quot;04 — 각도기 끼우기&quot;]">버튼을 눌러 순서대로 만들어 보세요</p>
  <div class="menu"><div class="course" data-s="1"><span class="num">01</span><div><b>자 붙이기</b><span class="cd">우드록 한쪽에 양면테이프로 자를 붙여요</span></div><span class="nt">준비</span></div><div class="course" data-s="2"><span class="num">02</span><div><b>수수깡 꽂기</b><span class="cd">수수깡을 10cm 정도 잘라 자의 '0' 위치에 수직으로 꽂아요</span></div><span class="nt">수직</span></div><div class="course" data-s="3"><span class="num">03</span><div><b>실 묶기</b><span class="cd">수수깡 끝에 실을 묶어요</span></div><span class="nt">실</span></div><div class="course" data-s="4"><span class="num">04</span><div><b>각도기 끼우기</b><span class="cd">실의 다른 끝을 각도기 가운데 구멍에 끼워요</span></div><span class="nt">각도</span></div></div>
</section>
<section class="slide">
  <div class="topbar"><h2>하루 동안 무엇이 어떻게 변할까요?</h2><span class="rt">측정 결과</span></div>
  <div class="stats3"><div class="card st"><div class="ct"><span class="mt">남중 시각</span></div><span class="sv">12:30</span><p>태양 고도가 가장 높아요 <span class="mt">무렵 · 남중</span></p></div><div class="card st"><div class="ct"><span class="mt">남중 방향</span></div><span class="sv">정남</span><p>남중할 때 태양의 위치 <span class="mt">쪽</span></p></div><div class="card st"><div class="ct"><span class="mt">최고 기온</span></div><span class="sv">14:30</span><p>기온이 가장 높아요 <span class="mt">무렵</span></p></div><div class="card st"><div class="ct"><span class="mt">가장 긴 그림자</span></div><span class="sv">9:30</span><p>그림자가 가장 길어요 <span class="mt">· 15:30</span></p></div></div>
  <div class="ledger">
    <div class="lr lh"><span>시각</span><span>태양 고도(°)</span><span></span><span>그림자 길이(cm)</span><span>기온(℃)</span></div>
    <div class="lr"><span class="tm">9:30</span><span class="av">38°</span><span class="track"><i style="width:63%"></i></span><span>12.9</span><span>22</span></div><div class="lr"><span class="tm">10:30</span><span class="av">48°</span><span class="track"><i style="width:80%"></i></span><span>9.1</span><span>23.8</span></div><div class="lr"><span class="tm">11:30</span><span class="av">55°</span><span class="track"><i style="width:92%"></i></span><span>7</span><span>25.2</span></div><div class="lr mx"><span class="tm">12:30</span><span class="av">57°</span><span class="track"><i style="width:95%"></i><em class="rt sm">남중</em></span><span>6.4</span><span>26.3</span></div><div class="lr"><span class="tm">13:30</span><span class="av">54°</span><span class="track"><i style="width:90%"></i></span><span>7.2</span><span>27</span></div><div class="lr"><span class="tm">14:30</span><span class="av">47°</span><span class="track"><i style="width:78%"></i></span><span>9.4</span><span>27.4</span></div><div class="lr"><span class="tm">15:30</span><span class="av">37°</span><span class="track"><i style="width:62%"></i></span><span>13.4</span><span>26.9</span></div>
  </div>
  <p class="src">예시 값 — 태양 고도·그림자(10cm 막대)는 9월 중순 북위 36° 기준 계산, 기온은 교과서 그래프 모양을 따른 값</p>
  <p class="nr">그래프 규칙 없음 → 원장 행 + 테두리 막대으로 표현</p>
</section>
<section class="slide">
  <div class="topbar"><h2>태양 고도가 바뀌면 무엇이 달라질까요?</h2><span class="rt">관계 정리</span></div>
  <div class="cmp"><div class="card"><div class="ct"><span class="rt">A</span><span class="mt">높을 때</span></div><h3>태양 고도가 높을 때</h3><p class="it4">그림자 길이는 짧아져요</p><p class="it4">기온은 높아져요</p><div class="cm"><span class="mt">그림자 길이 · 기온</span></div></div><div class="card"><div class="ct"><span class="rt">B</span><span class="mt">낮을 때</span></div><h3>태양 고도가 낮을 때</h3><p class="it4">그림자 길이는 길어져요</p><p class="it4">기온은 낮아져요</p><div class="cm"><span class="mt">그림자 길이 · 기온</span></div></div></div>
  <div class="ledger t4"><div class="lr lh"><span>시각</span><span>태양 고도</span><span>그림자 길이</span><span>기온</span></div><div class="lr"><span>오전 9:30</span><span>낮아요</span><span>길어요</span><span>낮아요</span></div><div class="lr"><span>낮 12:30</span><span>가장 높아요</span><span>가장 짧아요</span><span>높아지는 중</span></div><div class="lr"><span>오후 14:30</span><span>낮아지는 중</span><span>길어지는 중</span><span>가장 높아요</span></div></div>
  <div class="card info"><div class="ct"><span class="rt">남중</span><span class="mt">시각별 변화</span></div><p class="ir">태양이 정남쪽에 있을 때 '남중했다'고 해요</p><p class="ir">이때의 태양 고도를 남중 고도라고 해요</p></div>
  <blockquote class="qt"><p>태양 고도가 가장 높은 시각과 기온이 가장 높은 시각에는 차이가 있어요.</p><span class="who">오늘의 정리</span></blockquote>
</section>
<section class="slide">
  <div class="topbar"><h2>배운 내용을 확인해 볼까요?</h2><span class="rt">확인하기</span></div>
  <div class="card quiz" data-quiz data-answer="1" data-right="정답! 태양 고도가 가장 높을 때(남중) 그림자가 가장 짧아요" data-wrong="다시 생각해 볼까요? 태양 고도와 그림자 길이의 관계를 떠올려 보세요">
    <div class="ct"><span class="rt">QUESTION</span><span class="mt">one answer</span></div>
    <h3 class="q">하루 중 그림자 길이가 가장 짧을 때는?</h3>
    <div class="opts"><button class="pill opt" data-opt="0"><i>a.</i>오전 9시 30분</button><button class="pill opt" data-opt="1"><i>b.</i>낮 12시 30분 무렵</button><button class="pill opt" data-opt="2"><i>c.</i>오후 3시 30분</button></div>
    <p class="fb" data-fb></p>
    <button class="pill btn rty" data-act="retry">다시 풀기 ↺</button>
  </div>
  <div class="card blk">
    <div class="ct"><span class="rt">BLANKS</span><span class="mt">빈칸을 눌러 확인해요</span></div>
    <p class="br"><button class="blank" data-blank aria-pressed="false"><span>태양 고도</span></button>는 점점 높아졌다가 다시 낮아진다</p><p class="br"><button class="blank" data-blank aria-pressed="false"><span>그림자 길이</span></button>는 점점 짧아졌다가 다시 길어진다</p><p class="br"><button class="blank" data-blank aria-pressed="false"><span>기온</span></button>은 점점 높아졌다가 다시 낮아진다</p>
    <div class="cm"><span class="mt">오늘의 낱말</span><div class="words"><span class="pill sm">태양 고도</span><span class="pdiv">·</span><span class="pill sm">남중 고도</span><span class="pdiv">·</span><span class="pill sm">그림자 길이</span><span class="pdiv">·</span><span class="pill sm">기온</span></div></div>
  </div>
  <p class="nr">빈칸 규칙 없음 → 사각 태그으로 표현</p>
</section>
<section class="slide">
  <div class="topbar"><h2>이 디자인 사용 설명서</h2><span class="rt">디자인 안내</span></div>
  <div class="card g6"><div class="ct"><span class="ed6"><i class="badge">6</i><span class="el">Edition 6.</span></span><span class="mt">한눈에</span></div>
    <p class="ab6">만찬 클럽 포스터·리소 인쇄 프로그램. <b>녹슨 테라코타 잉크 한 가지</b>를 버터 크림 종이에 찍은 듯 — 변화는 투명도뿐, 도형은 채우지 않아요.</p>
    <div class="rw6"><span class="rt">색</span><span class="sw6"><span><i style="background:#B53D2A"></i>잉크 100%</span><span><i style="background:rgba(181,61,42,.78)"></i>78%</span><span><i style="background:rgba(181,61,42,.32)"></i>32%</span><span><i style="background:#FAF1E2"></i>크림 종이</span></span></div>
    <div class="rw6"><span class="rt">글꼴</span><span>제목 Bricolage Grotesque 800 → Hakgyoansim Moheomga B<br>본문 Fraunces 이탤릭 → Cafe24 Simplehae</span></div>
    <div class="cm"><span class="mt">이렇게 쓰면 좋아요 — 행사 안내·프로그램처럼 순서가 있는 수업. 알약은 행동(버튼), 사각 태그는 정보(메타)에만.</span></div>
  </div>
  <span class="rt sl6">대표 장치 — 눌러 보세요</span>
  <div class="card d6 a"><div class="dh"><h3>종이 점 질감</h3><button class="pill sm" data-demo="#lt-tex" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>4px 칸마다 작은 잉크 점을 10%로 깔아 인쇄 종이처럼 — 시연은 진하게.</p><div class="tx6" id="lt-tex"><b>PAPER</b></div></div>
  <div class="card d6 b"><div class="dh"><h3>카드 안쪽 리듬</h3><button class="pill sm" data-demo="#lt-rh" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>머리 아래 1px 실선(32%), 바닥 위 1px 점선(32%)으로 짝을 맞춰요.</p><div class="rh6" id="lt-rh"><span class="mt">STEP 01</span><b>자 붙이기</b><span class="mt">next — 수수깡</span></div></div>
  <div class="card d6 c"><div class="dh"><h3>정답 바깥 고리</h3><button class="pill sm" data-demo="#lt-ring" data-mode="toggle" aria-pressed="false">켜기 / 끄기</button></div><p>채우지 않는 규칙 — 정답은 1.5px 고리를 하나 더 둘러 표시해요.</p><div class="rg6"><span class="pill" id="lt-ring"><i>b.</i>낮 12시 30분 무렵</span></div></div>
</section>
<nav class="dk-nav"><span class="hint"><button class="dk-prev" aria-label="이전">←</button><button class="dk-next" aria-label="다음">→</button> to navigate</span><span class="dk-count"></span></nav>
  </main>
</div>

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

---

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

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

```css
/* long-table — k-slide 공통 CSS v1 (채팅 AI용 받기 .md가 불러옴, 고치지 말 것) */
/* === KOREAN FONTS === */
@font-face{font-family:'kp-26';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/hakgyoansim-moheomga/HakgyoansimMoheomgaB.woff2") format("woff2");font-weight:700}
@font-face{font-family:'kp-27';font-display:swap;src:url("https://maker-ssam.github.io/korean-ofl-fonts/fonts/cafe24-simplehae/Cafe24Simplehae-v2.0.woff2") format("woff2");font-weight:400}
/* === THEME === */
:root{--stage-bg:#FAF1E2;--slide-bg:#FAF1E2;
  --kt:'kp-26';--kb:'kp-27';--ka:'kp-27';
  --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{--paper:#FAF1E2;--pd:#F2E5CF;--pvd:#E8D7B6;--ink:#B53D2A;--idp:#8E2D1F;--i78:rgba(181,61,42,.78);--i32:rgba(181,61,42,.32);--i50:rgba(181,61,42,.5);--bd:1.5px solid #B53D2A}
.slide{background:var(--paper);color:var(--ink);font-family:'Fraunces',var(--kb),serif;font-weight:var(--wb);font-variation-settings:'opsz' 36}
.slide::before{content:'';position:absolute;inset:0;background-image:radial-gradient(circle at 1px 1px,var(--i50) .5px,transparent 1px);background-size:4px 4px;opacity:.1;pointer-events:none;z-index:0}
.slide>*{position:absolute;z-index:1}
.tag,.stats,.pill,.mt,.jm,.cap,.fb,.hint,.dk-count,.src,.nr,.el{font-style:italic}
.rt{border:var(--bd);padding:8px 18px;font:italic 400 26px/1 'Fraunces',var(--kb),serif;white-space:nowrap}
.pill{display:inline-block;border:var(--bd);border-radius:999px;padding:12px 30px;font:italic 400 32px/1.1 'Fraunces',var(--kb),serif;color:var(--ink);background:none}
.pill.sm{font-size:26px;padding:8px 22px}
.pdiv{font:italic 400 32px/1 'Fraunces',serif;opacity:.7}
.mt{font-size:26px;color:var(--i78)}
h1,h2,h3,.sv,.unit,.course b,.qt p{font-family:'Bricolage Grotesque',var(--kt),sans-serif;font-weight:var(--wt);text-transform:uppercase;letter-spacing:0}
.btn:disabled{opacity:.35}
.nr{left:50%;transform:translateX(-50%);bottom:54px;font-size:22px;color:var(--i78);white-space:nowrap}

/* --- 카드: 1.5px 테두리 + 안쪽 위 실선 32% / 아래 점선 32% --- */
.card{border:var(--bd);padding:24px 28px;display:flex;flex-direction:column}
.ct{display:flex;justify-content:space-between;align-items:center;gap:20px;padding-bottom:16px;border-bottom:1px solid var(--i32)}
.cm{margin-top:auto;padding-top:14px;border-top:1px dashed var(--i32)}

/* --- 상단 바: 제목 + 이탤릭 라벨 + 1.5px 아랫선 --- */
.topbar{left:110px;right:110px;top:80px;display:flex;justify-content:space-between;align-items:flex-end;gap:40px;border-bottom:var(--bd);padding-bottom:22px}
.topbar h2{font-size:76px;line-height:1.1;white-space:nowrap}
.topbar .rt{flex:none;margin-bottom:10px}

/* --- 1. 표지: 판 배지 + 'Edition N.' / 단원 / 학습 목표(가장 큰 글자) / 라벨 / 알약 줄 / 통계 | 오른쪽 아래 이탤릭 숫자 --- */
.ed{left:110px;top:90px;display:flex;align-items:center;gap:18px}
.badge{display:grid;place-items:center;width:52px;height:52px;border:var(--bd);border-radius:50%;font:italic 400 30px/1 'Fraunces',serif}
.el{font:italic 400 34px/1 'Fraunces',serif}
.ed .rt{margin-left:10px}
.unit{left:110px;top:180px;display:flex;align-items:baseline;gap:30px;font-size:68px;line-height:1.1;white-space:nowrap}
.unit span{font:800 44px/1 'Bricolage Grotesque',sans-serif;letter-spacing:-.012em;color:var(--i78)}
.gl{left:110px;top:306px}
.t1{left:104px;top:370px;font-size:112px;line-height:1.2;white-space:nowrap;color:var(--i78)}
.t1 .gk{font-style:normal;color:var(--ink)}
.tag{left:110px;top:680px;font-size:36px}
.pills{left:110px;top:760px;display:flex;align-items:center;gap:14px}
.stats{left:110px;top:870px;font-size:32px;color:var(--i78)}
.stats b{font-weight:600;color:var(--ink)}
.hero{left:1330px;right:110px;top:650px;bottom:110px;border-left:1px solid var(--i32);display:flex;flex-direction:column;align-items:center;justify-content:flex-end}
.jn{font:italic 400 240px/.86 'Fraunces',serif;font-variation-settings:'opsz' 144;letter-spacing:-.02em}
.jl{margin-top:22px;font:700 24px/1 'Bricolage Grotesque',var(--kb),sans-serif;letter-spacing:.18em;text-transform:uppercase}
.jm{margin-top:12px;font-size:24px;color:var(--i78)}

/* --- 2. 만들기: 테두리 카드 속 측정기 그림 | 알약 버튼 + 코스 행 4개(켜지면 또렷, 지금 단계 = 알약 태그) --- */
.fig{left:110px;width:780px;top:236px;bottom:110px;padding:20px 28px;
  --g-ink:var(--ink);--g-acc:var(--idp);--g-stick:var(--i78);--g-board:var(--pd);--g-ruler:var(--paper);--g-prot:rgba(181,61,42,.05);--g-shadow:var(--i50);--g-font:'Fraunces',var(--kb),serif;--g-sw:1.5}
.fig .gauge{margin:10px 0 4px}
.fig .cm p{font-size:28px;line-height:1.45}
.fig .cm b{font-weight:600}
.fig .cm .mt{font-size:26px}
.acts{left:970px;top:250px;display:flex;align-items:center;gap:14px}
.cap{left:970px;right:110px;top:336px;font-size:28px;color:var(--i78)}
.menu{left:970px;right:110px;top:390px;border-top:1px solid var(--i32)}
.course{display:grid;grid-template-columns:76px 1fr auto;align-items:center;gap:18px;padding:14px 0;border-bottom:1px solid var(--i32);transition:opacity .28s}
.slide[data-step]:not([data-step="0"]) .course:not(.on){opacity:.3}
.course .num{font:italic 400 40px/1 'Fraunces',serif}
.course b{display:block;font-size:42px;line-height:1.15}
.course .cd{display:block;margin-top:4px;font-size:26px;line-height:1.4;color:var(--i78)}
.nt{border:var(--bd);border-radius:999px;padding:6px 18px;font:italic 400 24px/1 'Fraunces',var(--kb),serif;opacity:0;transition:opacity .28s}
.course.now .nt{opacity:1}

/* --- 3. 숫자와 그래프: 테두리 카드 4개(통계) + 원장 행(태양 고도 = 테두리 막대, 남중 = 사각 태그) --- */
.stats3{left:110px;right:110px;top:236px;display:grid;grid-template-columns:repeat(4,1fr);gap:28px}
.st{padding:18px 26px}
.sv{margin-top:14px;font-size:68px;line-height:1}
.st p{margin-top:12px;font-size:26px;line-height:1.4}
.st p .mt{font-size:24px}
.ledger{left:110px;right:110px;top:520px}
.lr{display:grid;grid-template-columns:170px 150px 1fr 240px 190px;gap:24px;align-items:center;padding:7px 0;border-bottom:1px solid var(--i32);font-size:28px}
.lr.lh{font:italic 400 22px/1.2 'Fraunces',var(--kb),serif;letter-spacing:.08em;color:var(--i78);padding:10px 0;border-bottom:var(--bd)}
.tm{font:italic 400 30px/1 'Fraunces',serif}
.av{font:800 30px/1 'Bricolage Grotesque',sans-serif}
.lr.mx .av,.lr.mx .tm{font-weight:600}
.track{display:flex;align-items:center;gap:16px}
.track i{display:block;height:20px;border:var(--bd)}
.lr.mx .track i{border-color:var(--idp)}
.rt.sm{font-size:22px;padding:4px 12px;font-style:italic}
.src{left:110px;right:110px;top:928px;font-size:22px;color:var(--i78)}

/* --- 4. 비교와 표: 테두리 카드 둘 + 원장 표 | 정보 카드(남중) + 인용(이름 줄 1.5px 윗선) --- */
.cmp{left:110px;width:1020px;top:236px;display:grid;grid-template-columns:1fr 1fr;gap:28px}
.cmp h3{margin:18px 0 8px;font-size:44px;line-height:1.15}
.it4{font-size:30px;line-height:1.55}
.cmp .cm{margin-top:14px}
.t4{left:110px;width:1020px;top:620px;right:auto}
.t4 .lr{grid-template-columns:1.25fr 1fr 1fr 1fr;padding:14px 0}
.t4 .lr:not(.lh) span:first-child{font-family:'Bricolage Grotesque',var(--kt),sans-serif;font-weight:var(--wt)}
.info{left:1210px;right:110px;top:236px}
.ir{padding:14px 0;border-bottom:1px dashed var(--i32);font-size:29px;line-height:1.5}
.ir:last-child{border-bottom:0}
.qt{left:1210px;right:110px;top:620px}
.qt p{font-size:46px;line-height:1.3;font-weight:var(--wt)}
.who{display:block;margin-top:22px;padding-top:14px;border-top:var(--bd);font:700 24px/1 'Bricolage Grotesque',var(--kb),sans-serif;letter-spacing:.06em}

/* --- 5. 확인하기: 정보 카드 퀴즈(알약 보기, 정답 = 바깥 고리) | 빈칸 카드(사각 태그) + 낱말 알약 --- */
.quiz{left:110px;width:1020px;top:236px;bottom:110px}
.q{margin-top:22px;font-size:52px;line-height:1.25}
.opts{margin-top:24px;display:flex;flex-direction:column;align-items:flex-start;gap:16px}
.opt{font-size:34px;padding:12px 30px}
.opt i{margin-right:12px;opacity:.7}
.opt.right{outline:1.5px solid var(--ink);outline-offset:5px;font-weight:600}
.opt.wrong{text-decoration:line-through;text-decoration-thickness:1.5px;color:var(--i78)}
.opt:disabled:not(.right){opacity:.4}
.fb{margin-top:auto;padding-top:14px;border-top:1px dashed var(--i32);min-height:92px;font-size:28px;line-height:1.5}
.rty{align-self:flex-start;margin-top:12px;font-size:28px;padding:8px 26px}
.blk{left:1210px;right:110px;top:236px;bottom:110px}
.br{padding:20px 0;border-bottom:1px solid var(--i32);font-size:30px;line-height:1.6}
.blank{position:relative;min-width:180px;margin-right:10px;padding:4px 14px;border:var(--bd);font:italic 400 30px/1.2 'Fraunces',var(--kb),serif;color:var(--ink);text-align:center;background:none}
.blank span{visibility:hidden}
.blank::after{content:'?';position:absolute;left:0;right:0;top:4px}
.blank.open span{visibility:visible}
.blank.open::after{content:none}
.words{margin-top:12px;display:flex;flex-wrap:wrap;align-items:center;gap:10px}

/* --- 크롬: 왼쪽 아래 45% 안내 / 오른쪽 아래 이탤릭 쪽번호 --- */
.dk-nav{position:absolute;inset:0;pointer-events:none;color:var(--ink);font-family:'Fraunces',serif}
.hint{position:absolute;left:80px;bottom:46px;font-size:26px;opacity:.45;pointer-events:auto;display:flex;align-items:center;gap:6px}
.hint button{font:italic 400 30px/1 'Fraunces',serif;padding:4px 8px;color:inherit}
.hint button:disabled{opacity:.4}
.dk-count{position:absolute;right:80px;bottom:50px;font-size:30px}
/* --- 6. 디자인 안내: 테두리 카드(판 배지) | 테두리 카드 시연 3개 --- */
.g6{left:110px;width:960px;top:236px;bottom:110px;gap:14px}
.ed6{display:flex;align-items:center;gap:14px}
.ed6 .badge{width:44px;height:44px;font-size:26px}
.ed6 .el{font-size:28px}
.ab6{margin-top:6px;font-size:28px;line-height:1.55;font-style:italic}
.ab6 b{font-weight:600}
.rw6{display:grid;grid-template-columns:120px 1fr;gap:18px;align-items:start;font-size:25px;line-height:1.5}
.rw6 .rt{justify-self:start;font-size:22px;padding:6px 12px}
.sw6{display:flex;flex-wrap:wrap;gap:6px 20px}
.sw6 i{display:inline-block;width:24px;height:24px;margin-right:8px;vertical-align:-5px;border:1.5px solid var(--ink)}
.g6 .cm .mt{font-size:24px;line-height:1.5}
.rt.sl6{left:1130px;top:236px;font-size:22px}
.d6{left:1130px;right:110px;height:212px;padding:16px 26px}
.d6.a{top:296px}.d6.b{top:522px;height:226px}.d6.c{top:762px;height:176px}
.d6 .dh{display:flex;justify-content:space-between;align-items:center;gap:16px}
.d6 h3{font-family:'Bricolage Grotesque',var(--kt),sans-serif;font-weight:var(--wt);font-size:36px}
.d6 p{margin-top:4px;font-size:22px;line-height:1.4;font-style:italic;color:var(--i78)}
.pill.sm{font-size:20px;padding:6px 16px}
.pill.sm[aria-pressed="true"]{outline:1.5px solid var(--ink);outline-offset:4px}
.tx6{position:relative;margin-top:10px;height:76px;border:var(--bd);display:grid;place-items:center;font:800 40px 'Bricolage Grotesque',sans-serif}
.tx6.play::before{content:'';position:absolute;inset:0;background-image:radial-gradient(circle at 1px 1px,var(--ink) .8px,transparent 1.2px);background-size:4px 4px;opacity:.5}
.rh6{margin-top:8px;display:flex;flex-direction:column;gap:2px;border:var(--bd);padding:4px 16px}
.rh6 .mt{font-size:16px;line-height:1.3}
.rh6 b{font:800 22px 'Bricolage Grotesque',var(--kt),sans-serif}
.rh6.play .mt:first-child{padding-bottom:2px;border-bottom:1px solid var(--i32)}
.rh6.play .mt:last-child{padding-top:2px;border-top:1px dashed var(--i32)}
.rg6{margin-top:14px}
.rg6 .pill{font-size:28px}
.rg6 .pill i{margin-right:10px;opacity:.7}
.rg6 .pill.play{outline:1.5px solid var(--ink);outline-offset:5px;font-weight:600}

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