토큰 기반 CSS 체계 구축 + slide-base 스타일 분리
- tokens: typography(35변수), spacing(28변수), colors(41변수) 정의 - slide-base.html: 인라인 style 제거, Jinja include로 토큰/CSS 조립 - slide-base.css: 모든 직접값을 토큰 변수 참조로 전환 (직접값 0) - block_assembler.py: Template → Environment.from_string (include 지원) - TOKENS-v1.md: 위계 기준표 초안 + component token 후보 - BLOCK-RULES.md: 블록 작성 규칙 (spacing 문구 실제 토큰과 일치) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
162
docs/architecture/BLOCK-RULES.md
Normal file
162
docs/architecture/BLOCK-RULES.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# 블록 작성 규칙
|
||||
|
||||
Figma 1:1 HTML을 재사용 가능한 블록으로 전환할 때, 이 규칙을 따른다.
|
||||
figma_to_html_agent와 design_agent 간의 **계약서**.
|
||||
|
||||
---
|
||||
|
||||
## 1. HTML 규칙
|
||||
|
||||
### 구조 스타일은 OK
|
||||
블록의 배치/정렬을 위한 CSS는 블록 안에 있어야 한다.
|
||||
```css
|
||||
/* OK */
|
||||
display: flex;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
```
|
||||
|
||||
### 직접값은 금지
|
||||
하드코딩된 폰트/색/여백은 블록 안에 넣지 않는다.
|
||||
```css
|
||||
/* NG */
|
||||
font-size: 11px;
|
||||
color: #475569;
|
||||
padding: 16px;
|
||||
|
||||
/* OK — 토큰 참조 */
|
||||
font-size: var(--font-body);
|
||||
color: var(--color-body);
|
||||
padding: var(--card-padding);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 클래스명 규칙
|
||||
|
||||
### 공통 클래스 (모든 블록에서 사용)
|
||||
| 클래스 | 용도 | 토큰 참조 |
|
||||
|--------|------|-----------|
|
||||
| `.zone-title` | 중목차 제목 | `--font-zone-title`, `--color-zone-title` |
|
||||
| `.sub-title` | 소목차 제목 | `--font-sub-title` |
|
||||
| `.bul` | 본문 블릿 (hanging indent) | `--font-body`, `--bullet-indent` |
|
||||
| `.body-text` | 본문 텍스트 | `--font-body`, `--color-body` |
|
||||
| `.caption` | 캡션/보조 | `--font-caption`, `--color-caption` |
|
||||
|
||||
### 블록 고유 클래스
|
||||
블록별 고유 요소는 블록 prefix를 붙인다.
|
||||
```
|
||||
.p3c-bar (prerequisites-3col의 gradient 바)
|
||||
.pp2-col (process-product-2col의 컬럼)
|
||||
.cid-card (card-icon-desc의 카드)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 슬롯 규칙
|
||||
|
||||
블록이 받아들이는 콘텐츠 슬롯. catalog에 명시.
|
||||
|
||||
| 슬롯 | 용도 | 예시 |
|
||||
|------|------|------|
|
||||
| `zone_title` | 중목차 제목 | "DX의 궁극적 목표" |
|
||||
| `sub_title` | 소목차 제목 | "안전과 품질" |
|
||||
| `body` | 본문 텍스트 | 설명 문장 |
|
||||
| `bullets` | 블릿 리스트 | D2: 항목들 |
|
||||
| `image` | 이미지 | 시각 앵커 |
|
||||
| `preview` | 상세 preview | 표 헤더+행 |
|
||||
| `detail_link` | 자세히보기 링크 | 첨부 파일 연결 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 토큰 참조 방법
|
||||
|
||||
### 토큰 파일 위치
|
||||
```
|
||||
templates/styles/tokens/
|
||||
├── typography.css ← 글자 위계
|
||||
├── spacing.css ← 여백/간격
|
||||
└── colors.css ← 색상
|
||||
```
|
||||
|
||||
### 사용법
|
||||
```css
|
||||
/* 블록 CSS에서 */
|
||||
.my-block-title {
|
||||
font-size: var(--font-sub-title);
|
||||
font-weight: var(--weight-sub-title);
|
||||
line-height: var(--lh-sub-title);
|
||||
color: var(--color-zone-title);
|
||||
margin-bottom: var(--heading-gap);
|
||||
}
|
||||
|
||||
.my-block-body {
|
||||
font-size: var(--font-body);
|
||||
color: var(--color-body);
|
||||
padding-left: var(--bullet-indent);
|
||||
text-indent: calc(var(--bullet-indent) * -1);
|
||||
}
|
||||
```
|
||||
|
||||
### 블록 의미색이 필요할 때
|
||||
공통 테마색으로 안 되는 역할색은 colors.css의 2층 의미색을 참조.
|
||||
```css
|
||||
/* 3열 비교의 열별 색상 */
|
||||
.col-1 .bar { background: linear-gradient(180deg, var(--color-col-1-from), var(--color-col-1-to)); }
|
||||
.col-2 .bar { background: linear-gradient(180deg, var(--color-col-2-from), var(--color-col-2-to)); }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 블록 HTML 예시
|
||||
|
||||
### 좋은 예
|
||||
```html
|
||||
<section class="block block-3col">
|
||||
<div class="col">
|
||||
<div class="sub-title">{{ col.title }}</div>
|
||||
<div class="bul">• {{ col.desc }}</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.block-3col {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: var(--card-gap);
|
||||
}
|
||||
.block-3col .col {
|
||||
padding: var(--card-padding);
|
||||
background: var(--color-bg-subtle);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--card-radius);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### 나쁜 예
|
||||
```html
|
||||
<!-- NG: 직접값 하드코딩 -->
|
||||
<div style="font-size:12px; color:#1e293b; padding:16px; background:#f8fafc; border-radius:6px;">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 전환 체크리스트
|
||||
|
||||
Figma 1:1 HTML → 재사용 블록으로 전환할 때:
|
||||
|
||||
- [ ] font-size 직접값 → `var(--font-*)` 교체
|
||||
- [ ] color 직접값 → `var(--color-*)` 교체
|
||||
- [ ] padding/margin 직접값 → semantic spacing 또는 `var(--space-*)` 교체
|
||||
- 카드 내부: `var(--card-padding)`
|
||||
- 블릿 들여쓰기: `var(--bullet-indent)`
|
||||
- 소제목 아래: `var(--heading-gap)`
|
||||
- 일반 여백: `var(--space-sm)`, `var(--space-md)` 등
|
||||
- [ ] gap → `var(--card-gap)`, `var(--flex-gap)` 등
|
||||
- [ ] border-radius → `var(--card-radius)` 교체
|
||||
- [ ] 공통 클래스 사용 (`.bul`, `.sub-title` 등)
|
||||
- [ ] 블록 고유 요소에 prefix 클래스
|
||||
- [ ] catalog에 슬롯/구조/호환 정보 등록
|
||||
69
docs/architecture/TOKENS-v1.md
Normal file
69
docs/architecture/TOKENS-v1.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Typography Tokens — 초안 v1
|
||||
|
||||
## Global Hierarchy Tokens
|
||||
|
||||
슬라이드 전체의 공통 글자 위계. 모든 블록이 이 기준을 따른다.
|
||||
|
||||
| 위계 | 토큰명 | font-size | font-weight | line-height | 용도 |
|
||||
|------|--------|-----------|-------------|-------------|------|
|
||||
| 대목차 | `--font-slide-title` | 22px | 700 | 1.4 | 슬라이드 상단 제목 |
|
||||
| 중목차 | `--font-zone-title` | 13px | 700 | 1.4 | zone 제목 (## 대목차 하위) |
|
||||
| 소목차 | `--font-sub-title` | 12px | 700 | 1.45 | 블록 내 소제목, 카드 제목 |
|
||||
| 본문 | `--font-body` | 11px | 400~500 | 1.55 | 블릿, 설명 텍스트 |
|
||||
| 캡션 | `--font-caption` | 10px | 400 | 1.4 | 각주, 출처, 보조 텍스트 |
|
||||
| footer | `--font-footer` | 20px | 700 | 1.2 | 핵심 인사이트 pill |
|
||||
|
||||
---
|
||||
|
||||
## Component Semantic Token 후보
|
||||
|
||||
위계 6종으로 안 덮이는 역할. 가까운 위계에서 기본값을 가져오되, 필요시 override.
|
||||
|
||||
| 역할 | 기반 위계 | 예상 override | 비고 |
|
||||
|------|-----------|---------------|------|
|
||||
| body-strong (본문 강조) | 본문 (11px) | weight: 600~700 | 본문 heading, 인라인 강조 |
|
||||
| detail-link (자세히보기) | 캡션 (10px) | weight: 500, color: muted | 링크 텍스트 |
|
||||
| pill-label | 소목차 (12px) | weight: 700, color: white | pill/badge 안 라벨 |
|
||||
| table-header | 소목차 (12px) | weight: 700, color: white, bg: dark | 표 헤더 셀 |
|
||||
| table-cell | 본문 (11px) | - | 표 데이터 셀 |
|
||||
| compare-badge | 소목차 (12px) | weight: 700 | 비교 블록 VS 뱃지 |
|
||||
| callout | 소목차 (12px) | weight: 700, color: accent | 강조 인용 |
|
||||
| overline | 캡션 (10px) | weight: 600, letter-spacing | 상단 라벨 |
|
||||
|
||||
---
|
||||
|
||||
## Source
|
||||
|
||||
현재 코드에서 추출한 실제 사용값 기준.
|
||||
|
||||
| 출처 | 대목차 | 중목차 | 소목차 | 본문 | 캡션 | footer |
|
||||
|------|--------|--------|--------|------|------|--------|
|
||||
| slide-base.html | 22px | - | - | - | - | 20px |
|
||||
| block_assembler.py zone title | - | 13px | - | - | - | - |
|
||||
| block_assembler.py direct render | - | - | 12px | 11px | - | - |
|
||||
| block_assembler.py .bul | - | - | - | 11px | - | - |
|
||||
| FontHierarchy (legacy) | - | - | key_msg 14 | core 12 | sidebar 10 | - |
|
||||
|
||||
---
|
||||
|
||||
## FontHierarchy 매핑 (보조 체계)
|
||||
|
||||
기존 FontHierarchy는 역할 기반이므로, 위계 기반으로 매핑하여 보조로 유지.
|
||||
|
||||
| FontHierarchy | 위계 매핑 | 비고 |
|
||||
|---------------|-----------|------|
|
||||
| key_msg (14px) | 소목차~중목차 사이 | 강조 메시지용, component token 후보 |
|
||||
| core (12px) | 소목차 | 기본 블록 제목급 |
|
||||
| bg (11px) | 본문 | 배경/보조 텍스트 |
|
||||
| sidebar (10px) | 캡션 | 사이드바/첨부 |
|
||||
|
||||
---
|
||||
|
||||
## 상태
|
||||
|
||||
- [x] inventory 수집 완료
|
||||
- [x] global hierarchy v1 초안
|
||||
- [x] component token 후보 분리
|
||||
- [ ] typography.css 파일 작성
|
||||
- [ ] spacing tokens 정의
|
||||
- [ ] color tokens 정의 (공통 + 의미색)
|
||||
@@ -1688,9 +1688,16 @@ def assemble_slide_html_final(ctx: "PipelineContext", title_text: str = "", meas
|
||||
"{% block body %}{% endblock %}",
|
||||
body_html,
|
||||
)
|
||||
# Jinja2로 title, footer_text 등 변수만 렌더링
|
||||
from jinja2 import Template
|
||||
template = Template(slide_base_raw)
|
||||
# Jinja2 Environment로 렌더 ({% include %} 지원을 위해)
|
||||
from jinja2 import Environment, FileSystemLoader, BaseLoader
|
||||
include_env = Environment(loader=FileSystemLoader(str(templates_dir)))
|
||||
# slide_base_raw를 문자열 템플릿으로 렌더하되, include는 templates_dir 기준
|
||||
from jinja2 import DictLoader
|
||||
combined_loader = FileSystemLoader(str(templates_dir))
|
||||
include_env = Environment(loader=combined_loader)
|
||||
# slide-base 내용을 임시 템플릿으로 등록
|
||||
include_env.loader = FileSystemLoader(str(templates_dir))
|
||||
template = include_env.from_string(slide_base_raw)
|
||||
slide_html = template.render(
|
||||
title=title,
|
||||
footer_text=conclusion,
|
||||
|
||||
@@ -5,13 +5,7 @@
|
||||
용도: 16:9 슬라이드의 고정 배경. 상단 제목 + 구분선 + 본문 영역 + 하단 결론 pill.
|
||||
각 블록(new/, cards/, emphasis/ 등)은 본문 영역(.slide-body) 안에 들어간다.
|
||||
Figma 원본: Frame 1171281207 (node 107:22, 3848×2165, Page 2)
|
||||
수학적 계산:
|
||||
원본 3848×2165 → 16:9 (1280×720)
|
||||
scale = 1280 / 3848 = 0.33264
|
||||
상단 제목: top 125px × S ≈ 42px, left 155px × S ≈ 52px, font 65.8px × S ≈ 22px
|
||||
구분선: top 218px × S ≈ 72px
|
||||
하단 pill: top 1980px × S ≈ 659px, height 123px × S ≈ 41px
|
||||
본문 영역: top ~72px ~ bottom ~659px = 약 587px 가용
|
||||
CSS: styles/tokens/ + styles/base/slide-base.css 로 분리됨.
|
||||
슬롯:
|
||||
title — 슬라이드 제목 (gradient text)
|
||||
body — {% block body %}{% endblock %} 또는 include 대상
|
||||
@@ -20,10 +14,6 @@
|
||||
svg/bg_slide_texture.png — 배경 텍스처 (opacity 2%)
|
||||
svg/line_divider.svg — 구분선
|
||||
svg/pill_scroll.png — 하단 pill 배경 (두루마리, 이미지 유지)
|
||||
CSS 요소:
|
||||
배경 gradient: linear-gradient(180deg, #f0f0f0, #fff)
|
||||
제목 gradient text: linear-gradient(180deg, #296b55, #123328)
|
||||
하단 pill: 캡슐 border-radius 50px
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
@@ -33,136 +23,18 @@
|
||||
<title>{{ title|default("슬라이드") }}</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@500;700;900&display=swap" rel="stylesheet">
|
||||
<!--
|
||||
CSS 로딩 순서:
|
||||
1. tokens (typography, spacing, colors) — 변수 정의
|
||||
2. base (slide-base.css) — 프레임 스타일
|
||||
3. blocks (블록별 CSS) — 블록 스타일
|
||||
4. themes (선택) — 톤 변형
|
||||
-->
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
background: #e8ecf0;
|
||||
display: flex; justify-content: center; align-items: center;
|
||||
min-height: 100vh;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
/* ── 16:9 슬라이드 컨테이너 ── */
|
||||
.slide {
|
||||
width: 1280px; height: 720px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
/*
|
||||
배경: Figma gradient(#f0f0f0→#fff) + 텍스처(opacity 2%)
|
||||
MCP 확인: bg-gradient-to-b from-[#f0f0f0] to-white, opacity-2
|
||||
*/
|
||||
.slide-bg {
|
||||
position: absolute; inset: 0;
|
||||
background: linear-gradient(180deg, #f0f0f0 0%, #ffffff 100%);
|
||||
z-index: 0;
|
||||
}
|
||||
.slide-bg-texture {
|
||||
position: absolute; inset: 0;
|
||||
width: 100%; height: 100%;
|
||||
object-fit: cover;
|
||||
opacity: 0.02;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*
|
||||
상단 제목: Figma 65.8px Bold, gradient(#296b55→#123328)
|
||||
top: 125/2165 × 720 ≈ 42px, left: 155/3848 × 1280 ≈ 52px
|
||||
text-shadow: 0 0 5px #322c1e (Figma 5.263px × S)
|
||||
*/
|
||||
.slide-title {
|
||||
position: absolute;
|
||||
left: 52px; top: 22px;
|
||||
width: calc(100% - 104px);
|
||||
font-weight: 700;
|
||||
font-size: 22px;
|
||||
line-height: 1.4;
|
||||
background-image: linear-gradient(180deg, #296b55 0%, #123328 100%);
|
||||
-webkit-background-clip: text; background-clip: text;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 2px #322c1e;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/*
|
||||
구분선: Figma top 218px → 72px, width 3553/3848 × 1280 ≈ 1181px
|
||||
SVG 이미지 또는 CSS border
|
||||
*/
|
||||
.slide-divider {
|
||||
position: absolute;
|
||||
left: 50px; top: 58px;
|
||||
width: calc(100% - 100px);
|
||||
height: 2px;
|
||||
z-index: 2;
|
||||
}
|
||||
.slide-divider img {
|
||||
width: 100%; height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
본문 영역: 구분선 아래 ~ 하단 pill 위
|
||||
top: ~65px, bottom: ~60px (pill 영역)
|
||||
→ 가용 높이 약 595px
|
||||
*/
|
||||
.slide-body {
|
||||
position: absolute;
|
||||
left: 40px; top: 65px;
|
||||
width: calc(100% - 80px);
|
||||
height: 590px;
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*
|
||||
하단 pill: Figma top 1980/2165 × 720 ≈ 659px, height 123 × S ≈ 41px
|
||||
캡슐 border-radius: 50px × S ≈ 17px → 999px (캡슐)
|
||||
pill 배경: 이미지 (두루마리, R16 crop) 또는 CSS gradient
|
||||
*/
|
||||
.slide-footer {
|
||||
position: absolute;
|
||||
left: 50px; bottom: 8px;
|
||||
width: calc(100% - 100px);
|
||||
height: 41px;
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
z-index: 2;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.slide-footer-bg {
|
||||
position: absolute; inset: 0;
|
||||
width: 100%; height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 999px;
|
||||
z-index: 0;
|
||||
}
|
||||
/* pill 배경이 이미지 없을 때 CSS gradient fallback */
|
||||
.slide-footer--css {
|
||||
background: linear-gradient(90deg, #3b3523 5%, #263a2a 50%, #113f31 95%);
|
||||
}
|
||||
|
||||
/*
|
||||
footer 텍스트: Figma 60px × S ≈ 20px, Bold white
|
||||
<em> = 노란색 #fe3
|
||||
*/
|
||||
.slide-footer-text {
|
||||
position: relative; z-index: 1;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.5);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.slide-footer-text em {
|
||||
color: #ffee33;
|
||||
font-style: normal;
|
||||
}
|
||||
{% include "styles/tokens/typography.css" %}
|
||||
{% include "styles/tokens/spacing.css" %}
|
||||
{% include "styles/tokens/colors.css" %}
|
||||
{% include "styles/base/slide-base.css" %}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
133
templates/styles/base/slide-base.css
Normal file
133
templates/styles/base/slide-base.css
Normal file
@@ -0,0 +1,133 @@
|
||||
/* ══════════════════════════════════════
|
||||
slide-base.css
|
||||
══════════════════════════════════════
|
||||
슬라이드 공통 프레임 스타일.
|
||||
slide-base.html에서 분리.
|
||||
직접값 대신 토큰 변수 참조.
|
||||
══════════════════════════════════════ */
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Noto Sans KR', sans-serif;
|
||||
background: var(--color-bg-page);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
/* ── 16:9 슬라이드 컨테이너 ── */
|
||||
.slide {
|
||||
width: 1280px;
|
||||
height: 720px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: var(--color-bg);
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
/* ── 배경 ── */
|
||||
.slide-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(180deg, #f0f0f0 0%, #ffffff 100%);
|
||||
z-index: 0;
|
||||
}
|
||||
.slide-bg-texture {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
opacity: 0.02;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ── 대목차 제목 ── */
|
||||
.slide-title {
|
||||
position: absolute;
|
||||
left: var(--slide-title-left);
|
||||
top: var(--slide-title-top);
|
||||
width: calc(100% - 104px);
|
||||
font-weight: var(--weight-slide-title);
|
||||
font-size: var(--font-slide-title);
|
||||
line-height: var(--lh-slide-title);
|
||||
background-image: linear-gradient(180deg, var(--color-slide-title-from) 0%, var(--color-slide-title-to) 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
text-shadow: 0 0 2px #322c1e;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* ── 구분선 ── */
|
||||
.slide-divider {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
top: var(--slide-divider-top);
|
||||
width: calc(100% - 100px);
|
||||
height: 2px;
|
||||
z-index: 2;
|
||||
}
|
||||
.slide-divider img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ── 본문 영역 ── */
|
||||
.slide-body {
|
||||
position: absolute;
|
||||
left: var(--slide-padding-x);
|
||||
top: var(--slide-body-top);
|
||||
width: calc(100% - var(--slide-padding-x) * 2);
|
||||
height: var(--slide-body-height);
|
||||
z-index: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── 하단 footer pill ── */
|
||||
.slide-footer {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
bottom: var(--slide-footer-bottom);
|
||||
width: calc(100% - 100px);
|
||||
height: var(--slide-footer-height);
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.slide-footer-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 999px;
|
||||
z-index: 0;
|
||||
}
|
||||
.slide-footer--css {
|
||||
background: linear-gradient(90deg, var(--color-footer-bg-from) 5%, var(--color-footer-bg-mid) 50%, var(--color-footer-bg-to) 95%);
|
||||
}
|
||||
|
||||
/* ── footer 텍스트 ── */
|
||||
.slide-footer-text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-size: var(--font-footer);
|
||||
font-weight: var(--weight-footer);
|
||||
line-height: var(--lh-footer);
|
||||
color: var(--color-footer-text);
|
||||
text-align: center;
|
||||
text-shadow: 0 0 4px rgba(0,0,0,0.5);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
.slide-footer-text em {
|
||||
color: var(--color-footer-accent);
|
||||
font-style: normal;
|
||||
}
|
||||
76
templates/styles/tokens/colors.css
Normal file
76
templates/styles/tokens/colors.css
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ══════════════════════════════════════
|
||||
Color Tokens v1
|
||||
══════════════════════════════════════
|
||||
2층 구조: 공통 테마색 + 블록 의미색.
|
||||
══════════════════════════════════════ */
|
||||
|
||||
:root {
|
||||
/* ══ 1층: 공통 테마색 ══ */
|
||||
/* 모든 블록이 공유하는 기본 팔레트 */
|
||||
|
||||
/* 텍스트 */
|
||||
--color-title: #1e293b; /* 제목 (진한 남색) */
|
||||
--color-zone-title: #1a365d; /* zone 중목차 제목 */
|
||||
--color-body: #475569; /* 본문 */
|
||||
--color-body-strong: #1e293b; /* 본문 강조 */
|
||||
--color-caption: #94a3b8; /* 캡션, 보조 */
|
||||
--color-muted: #64748b; /* 약한 텍스트 */
|
||||
|
||||
/* 배경 */
|
||||
--color-bg: #ffffff; /* 슬라이드 배경 */
|
||||
--color-bg-subtle: #f8fafc; /* 카드/영역 배경 */
|
||||
--color-bg-page: #e8ecf0; /* 페이지 배경 (슬라이드 바깥) */
|
||||
|
||||
/* 보더 */
|
||||
--color-border: #e2e8f0; /* 기본 보더 */
|
||||
--color-border-strong: #cbd5e1; /* 강한 보더 */
|
||||
|
||||
/* 강조 */
|
||||
--color-accent: #2563eb; /* 링크, 강조 (파랑) */
|
||||
--color-accent-hover: #eff6ff; /* 링크 hover 배경 */
|
||||
--color-danger: #dc2626; /* 경고, 에러 */
|
||||
|
||||
/* slide-base 전용 */
|
||||
--color-slide-title-from: #296b55; /* 대목차 gradient 시작 */
|
||||
--color-slide-title-to: #123328; /* 대목차 gradient 끝 */
|
||||
--color-footer-bg-from: #3b3523; /* footer gradient 시작 */
|
||||
--color-footer-bg-mid: #263a2a; /* footer gradient 중간 */
|
||||
--color-footer-bg-to: #113f31; /* footer gradient 끝 */
|
||||
--color-footer-text: #ffffff; /* footer 텍스트 */
|
||||
--color-footer-accent: #ffee33; /* footer 강조 (em) */
|
||||
|
||||
/* ══ 2층: 블록 의미색 ══ */
|
||||
/* 특정 블록 유형에서 의미를 가지는 색 */
|
||||
|
||||
/* 3열 비교 (prerequisites-3col) */
|
||||
--color-col-1-from: #0D78D0; /* 1열 gradient 시작 */
|
||||
--color-col-1-to: #023056; /* 1열 gradient 끝 */
|
||||
--color-col-2-from: #FF9A23; /* 2열 gradient 시작 */
|
||||
--color-col-2-to: #CC5200; /* 2열 gradient 끝 */
|
||||
--color-col-3-from: #39BE49; /* 3열 gradient 시작 */
|
||||
--color-col-3-to: #23742C; /* 3열 gradient 끝 */
|
||||
|
||||
/* 비교 블록 (compare) */
|
||||
--color-compare-left: #5c3714; /* 좌측 (AS-IS 계열) */
|
||||
--color-compare-right: #285b4a; /* 우측 (TO-BE 계열) */
|
||||
--color-compare-badge: #ae3607; /* VS 뱃지 */
|
||||
|
||||
/* 다크 카드 (direct render) */
|
||||
--color-dark-card-1: #1a365d; /* 카드 1 배경 */
|
||||
--color-dark-card-2: #1e3a2f; /* 카드 2 배경 */
|
||||
--color-dark-card-3: #3b1f2b; /* 카드 3 배경 */
|
||||
--color-dark-card-title: #fbbf24; /* 다크카드 제목 (금색) */
|
||||
--color-dark-card-body: #e2e8f0; /* 다크카드 본문 */
|
||||
|
||||
/* 표 */
|
||||
--color-table-header-bg: #64748b; /* 표 헤더 배경 */
|
||||
--color-table-header-text: #ffffff; /* 표 헤더 텍스트 */
|
||||
|
||||
/* 블록 제목 gradient (Figma 원본) */
|
||||
--color-block-title-from: #CC5200; /* 주황 gradient 시작 */
|
||||
--color-block-title-to: #883700; /* 주황 gradient 끝 */
|
||||
|
||||
/* pill */
|
||||
--color-pill-bg: #1e293b; /* pill 배경 */
|
||||
--color-pill-text: #ffffff; /* pill 텍스트 */
|
||||
}
|
||||
47
templates/styles/tokens/spacing.css
Normal file
47
templates/styles/tokens/spacing.css
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ══════════════════════════════════════
|
||||
Spacing Tokens v1
|
||||
══════════════════════════════════════
|
||||
여백/간격/들여쓰기 공통 기준.
|
||||
══════════════════════════════════════ */
|
||||
|
||||
:root {
|
||||
/* ── 기본 스케일 ── */
|
||||
--space-xs: 4px;
|
||||
--space-sm: 8px;
|
||||
--space-md: 12px;
|
||||
--space-lg: 16px;
|
||||
--space-xl: 24px;
|
||||
|
||||
/* ── slide-base 레이아웃 ── */
|
||||
--slide-padding-x: 40px; /* 본문 좌우 여백 */
|
||||
--slide-title-left: 52px; /* 대목차 시작 */
|
||||
--slide-title-top: 22px; /* 대목차 위치 */
|
||||
--slide-divider-top: 58px; /* 구분선 위치 */
|
||||
--slide-body-top: 65px; /* 본문 시작 */
|
||||
--slide-body-height: 575px; /* 본문 높이 */
|
||||
--slide-footer-bottom: 18px; /* footer 하단 여백 */
|
||||
--slide-footer-height: 41px; /* footer 높이 */
|
||||
|
||||
/* ── zone ── */
|
||||
--zone-gap: 8px; /* zone 간 간격 */
|
||||
--zone-padding-left: 12px; /* zone 안쪽 좌측 여백 */
|
||||
--zone-padding-right: 8px; /* zone 안쪽 우측 여백 */
|
||||
--zone-title-mb: 8px; /* zone 제목 아래 여백 */
|
||||
|
||||
/* ── 블록 공통 ── */
|
||||
--card-padding: 16px; /* 카드 내부 여백 */
|
||||
--card-padding-sm: 8px; /* 작은 카드 내부 여백 */
|
||||
--card-gap: 12px; /* 카드 간 간격 */
|
||||
--card-radius: 6px; /* 카드 모서리 */
|
||||
|
||||
/* ── 블릿/텍스트 ── */
|
||||
--bullet-indent: 14px; /* 불릿 hanging indent */
|
||||
--bullet-gap: 2px; /* 불릿 항목 간 간격 */
|
||||
--heading-gap: 4px; /* 소제목 아래 간격 */
|
||||
--section-gap: 10px; /* 섹션 간 간격 */
|
||||
|
||||
/* ── flex/grid 기본 ── */
|
||||
--flex-gap: 12px; /* 기본 flex gap */
|
||||
--flex-gap-sm: 6px; /* 좁은 flex gap */
|
||||
--grid-gap: 16px; /* 기본 grid gap */
|
||||
}
|
||||
77
templates/styles/tokens/typography.css
Normal file
77
templates/styles/tokens/typography.css
Normal file
@@ -0,0 +1,77 @@
|
||||
/* ══════════════════════════════════════
|
||||
Typography Tokens v1
|
||||
══════════════════════════════════════
|
||||
슬라이드 전체의 공통 글자 위계.
|
||||
모든 블록은 이 토큰을 참조한다.
|
||||
직접값(font-size: 11px) 금지 → var(--font-body) 사용.
|
||||
══════════════════════════════════════ */
|
||||
|
||||
:root {
|
||||
/* ── 1층: Global Hierarchy ── */
|
||||
|
||||
/* 대목차: 슬라이드 상단 제목 */
|
||||
--font-slide-title: 22px;
|
||||
--weight-slide-title: 700;
|
||||
--lh-slide-title: 1.4;
|
||||
|
||||
/* 중목차: zone 제목 */
|
||||
--font-zone-title: 13px;
|
||||
--weight-zone-title: 700;
|
||||
--lh-zone-title: 1.4;
|
||||
|
||||
/* 소목차: 블록 내 소제목, 카드 제목 */
|
||||
--font-sub-title: 12px;
|
||||
--weight-sub-title: 700;
|
||||
--lh-sub-title: 1.45;
|
||||
|
||||
/* 본문: 블릿, 설명 텍스트 */
|
||||
--font-body: 11px;
|
||||
--weight-body: 500;
|
||||
--lh-body: 1.55;
|
||||
|
||||
/* 캡션: 각주, 출처, 보조 텍스트 */
|
||||
--font-caption: 10px;
|
||||
--weight-caption: 400;
|
||||
--lh-caption: 1.4;
|
||||
|
||||
/* footer: 핵심 인사이트 pill */
|
||||
--font-footer: 20px;
|
||||
--weight-footer: 700;
|
||||
--lh-footer: 1.2;
|
||||
|
||||
/* ── 2층: Component Semantic Tokens ── */
|
||||
/* 가까운 위계에서 기본값, 필요시 override */
|
||||
|
||||
/* 본문 강조 (인라인 heading) */
|
||||
--font-body-strong: var(--font-body);
|
||||
--weight-body-strong: 600;
|
||||
|
||||
/* 자세히보기 링크 */
|
||||
--font-detail-link: var(--font-caption);
|
||||
--weight-detail-link: 500;
|
||||
|
||||
/* pill/badge 라벨 */
|
||||
--font-pill-label: var(--font-sub-title);
|
||||
--weight-pill-label: 700;
|
||||
|
||||
/* 표 헤더 */
|
||||
--font-table-header: var(--font-sub-title);
|
||||
--weight-table-header: 700;
|
||||
|
||||
/* 표 셀 */
|
||||
--font-table-cell: var(--font-body);
|
||||
--weight-table-cell: 400;
|
||||
|
||||
/* 비교 뱃지 */
|
||||
--font-compare-badge: var(--font-sub-title);
|
||||
--weight-compare-badge: 700;
|
||||
|
||||
/* 강조 인용 */
|
||||
--font-callout: var(--font-sub-title);
|
||||
--weight-callout: 700;
|
||||
|
||||
/* 상단 라벨 (overline) */
|
||||
--font-overline: var(--font-caption);
|
||||
--weight-overline: 600;
|
||||
--ls-overline: 0.05em;
|
||||
}
|
||||
Reference in New Issue
Block a user