feat(skill): 자율 검증 폐쇄 루프 내재화 — 0.6.0
Some checks failed
ci / build (push) Failing after 5s

- 핵심 규칙 6: 완료의 정의는 게이트 통과. 사용자를 QA로 쓰지 않는다
- 5단계 기계 검사 4번째: design-gate 실행 의무화
- references/audit-gate.md: 사고-검사 매핑, SEO/meta 체크리스트, OS/브라우저 특성, 하니스 규칙
- tools/design-gate.mjs: 범용 게이트(메타/SEO·대비·수축·리듬·트랙·스케일×폭 + 옵션 L0/L3/L4, checks 깊은 병합)
- 리듬·트랙 불변식: 숫자 라벨 등폭·빈 셀 트랙 균일·등간격 — 시간표 자동배치 결함 재현 픽스처 검출, 앱 15뷰 통과(오탐 0)

feat(site): 관리 앱 2종 프로덕션 콘솔(v6→v18)

- 가온 학적부 9뷰·두레 수강신청 6뷰: shadcn 문법, Pretendard/Noto Serif/IBM Plex 폰트 전략, 볼드 금지(400/500/600), WCAG AA 대비 전면 교정, 한글 keep-all 조판
- LMS 필수 요소(알림 센터·공지·진도·평가 유형·출결 사유·학점 경고), 12명 기준 데이터 정합, SEO 구조(h1 유일·OG/twitter·og.png)
- 시간표 자동배치 결함 수리(명시적 격자 좌표)
- QA 게이트: L0 stylelint/html-validate · L1 단위 30 · L2 감사 61+불변식 · L3 시각회귀 30화면 · L4 WebKit · L5 키보드 탐색 — npm run verify 실패 시 배포 금지 체인
This commit is contained in:
Yun Chan 2026-08-22 21:22:05 +09:00
parent 78ddc8b61a
commit 72337b7ee0
226 changed files with 18212 additions and 380 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

View file

@ -0,0 +1,303 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>스튜디오 폼 · 공간건축연구소</title>
<meta
name="description"
content="형태는 침묵하고 치수가 태도를 증명한다. 비례와 구조의 명료성으로 설계하는 건축연구소의 프로젝트 인덱스와 도면."
/>
<meta property="og:title" content="스튜디오 폼 · 공간건축연구소" />
<meta
property="og:description"
content="비례와 구조의 명료성으로 설계하는 건축연구소."
/>
<meta property="og:type" content="website" />
<meta name="theme-color" content="#FDFDFB" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
/>
<link rel="stylesheet" href="./styles/main.css?v=2" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect x='6' y='6' width='20' height='20' fill='none' stroke='%23111' stroke-width='2'/%3E%3Crect x='11' y='11' width='10' height='10' fill='%23111'/%3E%3C/svg%3E"
/>
</head>
<body>
<a class="skip" href="#main">본문으로 건너뛰기</a>
<!-- 4모서리 등록 표시(인쇄 판맞춤) — 이 페이지의 리스크. 넓은 화면에서만. -->
<div class="corner corner-tl" aria-hidden="true"></div>
<div class="corner corner-tr" aria-hidden="true"></div>
<div class="corner corner-bl" aria-hidden="true"></div>
<div class="corner corner-br" aria-hidden="true"></div>
<header class="site-head">
<div class="wrap head-inner">
<a class="wordmark" href="#main">스튜디오 폼 <span class="wordmark-en">FORM</span></a>
<nav class="nav" aria-label="섹션">
<a href="#index">인덱스</a>
<a href="#drawing">도면</a>
<a href="#photo">사진</a>
<a href="#contact">연락</a>
</nav>
</div>
</header>
<main id="main">
<!--
서문 — Pawson의 교훈: 크기가 아니라 여백과 무게로 위계를 만든다.
큰 글자는 이 페이지에 하나만 있다.
-->
<section class="hero" aria-labelledby="hero-h">
<div class="wrap">
<p class="hero-meta reveal">
공간건축연구소 · 서울 · 2014년 설립
</p>
<h1 id="hero-h" class="reveal" style="--delay: 60ms">
형태는 침묵하고<br />치수가 태도를 증명한다
</h1>
<p class="hero-statement reveal" style="--delay: 120ms">
폼은 공간을 꾸미지 않습니다. 벽이 서는 이유, 창이 열리는 방향, 보가
건너뛰는 길이를 설계합니다. 아름다움은 그 결정들이 모였을 때의
부산물입니다 — 그래서 우리의 홍보는 도면과 치수로 합니다.
</p>
<dl class="hero-facts reveal" style="--delay: 180ms">
<div>
<dt>설립</dt>
<dd>2014년</dd>
</div>
<div>
<dt>구성</dt>
<dd>건축사 4 · 연구원 3</dd>
</div>
<div>
<dt>영역</dt>
<dd>주거 · 미술관 · 재생</dd>
</div>
</dl>
</div>
</section>
<!--
인덱스 — 이 페이지의 주인공. 사진 없는 역연도 목록.
R1(johnpawson.com): 프로젝트는 제목/위치/연도의 세 줄 텍스트다.
-->
<section id="index" class="section" aria-labelledby="index-h">
<div class="wrap">
<h2 id="index-h" class="index-h reveal">프로젝트 인덱스</h2>
<ol class="index">
<li class="index-row reveal">
<a href="#drawing">
<span class="idx-name">폼 하우스</span>
<span class="idx-loc">경기 가평</span>
<span class="idx-year">2025</span>
</a>
</li>
<li class="index-row reveal" style="--delay: 40ms">
<a href="#drawing">
<span class="idx-name">백령도 해녀기념관</span>
<span class="idx-loc">인천 백령도</span>
<span class="idx-year">2024</span>
</a>
</li>
<li class="index-row reveal" style="--delay: 80ms">
<a href="#drawing">
<span class="idx-name">은평 재생주거</span>
<span class="idx-loc">서울 은평</span>
<span class="idx-year">2024</span>
</a>
</li>
<li class="index-row reveal" style="--delay: 120ms">
<a href="#drawing">
<span class="idx-name">제주 돌담 스튜디오</span>
<span class="idx-loc">제주 애월</span>
<span class="idx-year">2023</span>
</a>
</li>
<li class="index-row reveal" style="--delay: 160ms">
<a href="#drawing">
<span class="idx-name">성수 인쇄공장 재생</span>
<span class="idx-loc">서울 성수</span>
<span class="idx-year">2022</span>
</a>
</li>
<li class="index-row reveal" style="--delay: 200ms">
<a href="#drawing">
<span class="idx-name">폼 오피스</span>
<span class="idx-loc">서울 종로</span>
<span class="idx-year">2019</span>
</a>
</li>
</ol>
</div>
</section>
<!--
도면 — 스티키 평면도가 섹션을 지나는 동안 그어진다.
R3: CSS scroll-driven + stroke-dashoffset. 폴백은 완성된 도면.
도면은 장식이 아니라 이 연구소의 언어 그 자체다.
-->
<section id="drawing" class="section drawing" aria-labelledby="drawing-h">
<div class="wrap drawing-grid">
<div class="drawing-stage reveal">
<svg
viewBox="0 0 520 640"
role="img"
aria-label="폼 하우스 1층 평면도. 남쪽으로 긴 거실과 북쪽 서비스 블록, 동쪽 마당으로 이루어져 있다."
>
<!-- 외곽 벽 (이중선) -->
<path
class="wall"
d="M 80 60 H 440 V 580 H 80 Z M 88 68 H 432 V 572 H 88 Z"
/>
<!-- 내부 벽 -->
<path
class="wall inner"
d="M 260 68 V 300 M 260 380 V 572 M 88 300 H 432 M 88 380 H 260"
/>
<!-- 문 개구부 표시 -->
<path class="door" d="M 260 340 h -36 M 260 340 a 36 36 0 0 1 36 -36" />
<!-- 기둥 -->
<path class="column" d="M 176 130 h 10 v 10 h -10 z M 356 130 h 10 v 10 h -10 z M 176 250 h 10 v 10 h -10 z M 356 250 h 10 v 10 h -10 z" />
<!-- 치수선 -->
<g class="dim">
<path d="M 80 610 H 440 M 80 602 v 16 M 440 602 v 16" />
<path d="M 50 60 V 580 M 42 60 h 16 M 42 580 h 16" />
<text x="260" y="632" text-anchor="middle">14,400</text>
<text x="30" y="325" text-anchor="middle" transform="rotate(-90 30 325)">9,600</text>
</g>
<!-- 방 이름 -->
<g class="room-label">
<text x="174" y="190">거실</text>
<text x="350" y="190" text-anchor="middle"></text>
<text x="174" y="460">주방·식당</text>
<text x="350" y="455">서비스</text>
<text x="350" y="490">현관</text>
</g>
<!-- 방위 -->
<g class="north">
<path d="M 470 90 v -40 M 470 50 l -8 14 M 470 50 l 8 14" />
<text x="470" y="110" text-anchor="middle">N</text>
</g>
</svg>
<p class="drawing-caption">폼 하우스 · 1층 평면도 · mm</p>
</div>
<div class="drawing-notes">
<h2 id="drawing-h">폼 하우스, 가평</h2>
<p>
대지 남쪽의 소나무군을 지우지 않기 위해 집은 길게 눕고, 마당은 집
안쪽으로 들어왔습니다. 구조는 9.6m 축 한 번으로 건너뛰어 거실에 기둥이
없습니다.
</p>
<p>
벽체는 단열 성능의 요구치에서 두께가 정해졌습니다 — 마감 재료를 먼저
고르고 두께를 맞추지 않았습니다. 창은 남향 긴면 하나, 동쪽 마당 면
하나. 그 두 개로 이 집의 하루가 결정됩니다.
</p>
<dl class="drawing-spec">
<div>
<dt>구조</dt>
<dd>RC 라멘 · 9.6m 스팬</dd>
</div>
<div>
<dt>면적</dt>
<dd>132.4 ㎡ (40.0평)</dd>
</div>
<div>
<dt>창개구</dt>
<dd>남측 14.4m · 동측 4.2m</dd>
</div>
<div>
<dt>줄공사</dt>
<dd>2025-04 2026-01</dd>
</div>
</dl>
</div>
</div>
</section>
<!--
사진 — 흑백 3점. 그리드는 엄격하게, 크기는 사진이 요구하는 대로.
-->
<section id="photo" class="section photo" aria-labelledby="photo-h">
<div class="wrap">
<h2 id="photo-h" class="reveal">사진</h2>
<div class="photo-grid">
<figure class="ph ph-a reveal">
<img
src="./assets/pavilion-bw.webp"
alt="긴 수평창이 낸 콘크리트 파빌리온에 벽 그림자가 지는 모습"
width="1440"
height="810"
loading="lazy"
/>
<figcaption>폼 하우스 · 남측 · 준공 후 첫 여름</figcaption>
</figure>
<figure class="ph ph-b reveal" style="--delay: 60ms">
<img
src="./assets/interior-bw.webp"
alt="천창으로 한 줄기 빛이 사선으로 들어오는 미장 마감 전시실"
width="900"
height="1200"
loading="lazy"
/>
<figcaption>백령도 해녀기념관 · 제1전시실</figcaption>
</figure>
<figure class="ph ph-c reveal" style="--delay: 120ms">
<img
src="./assets/model-bw.webp"
alt="스터디 모델 — 직육면체를 쌓은 백색 석고 모형에 측광이 지는 모습"
width="1100"
height="825"
loading="lazy"
/>
<figcaption>스터디 모델 07 · 석고</figcaption>
</figure>
</div>
</div>
</section>
<!-- 연락 — 서류 같은 마무리 -->
<section id="contact" class="section contact" aria-labelledby="contact-h">
<div class="wrap contact-grid">
<h2 id="contact-h">연락</h2>
<address>
서울 종로구 자하문로 00길 00, 3층<br />
<a class="link" href="mailto:studio@form.kr">studio@form.kr</a>
</address>
<p class="contact-note">
신규 프로젝트는 분기에 두 건만 받습니다. 대지와 예산의 조건을 적어
보내주시면, 가능 여부를 2주 안에 답합니다.
</p>
</div>
</section>
</main>
<footer class="site-foot">
<div class="wrap foot-inner">
<p>스튜디오 폼 · 공간건축연구소</p>
<p class="foot-meta">© 20142026</p>
</div>
</footer>
<script>
const io = new IntersectionObserver(
(entries) => {
for (const e of entries) {
if (!e.isIntersecting) continue;
e.target.classList.add("is-in");
io.unobserve(e.target);
}
},
{ rootMargin: "0px 0px -8% 0px", threshold: 0.05 },
);
for (const el of document.querySelectorAll(".reveal")) io.observe(el);
</script>
</body>
</html>

View file

@ -0,0 +1,497 @@
@import url("./tokens.css");
/* ==========================================================================
스튜디오 swiss-minimal. 판맞춤 도면 묶음.
========================================================================== */
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin: 0;
}
html {
-webkit-text-size-adjust: 100%;
scroll-behavior: smooth;
background: var(--surface);
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
body {
background: var(--surface);
color: var(--ink);
font-family: var(--font-body);
font-size: var(--step-0);
line-height: var(--leading-normal);
-webkit-font-smoothing: antialiased;
}
:where(h1, h2, h3) {
font-weight: 600;
line-height: var(--leading-tight);
letter-spacing: -0.01em;
word-break: keep-all;
overflow-wrap: break-word;
text-wrap: balance;
}
h1 {
font-size: var(--step-3);
}
h2 {
font-size: var(--step-2);
}
:where(p, li, dd, dt, th, td, address, figcaption) {
word-break: keep-all;
overflow-wrap: break-word;
line-height: var(--leading-normal);
text-wrap: pretty;
}
a {
color: inherit;
}
.link {
text-decoration: none;
border-bottom: 1px solid var(--line-strong);
transition: border-color var(--dur-quick) var(--ease-soft);
}
.link:hover {
border-color: var(--ink);
}
:focus-visible {
outline: 2px solid var(--ink);
outline-offset: 3px;
}
.skip {
position: absolute;
left: -9999px;
top: 0;
background: var(--ink);
color: var(--surface);
padding: var(--space-3) var(--space-4);
z-index: 100;
}
.skip:focus {
left: 0;
}
.wrap {
width: min(100% - 2 * var(--pad-inline), var(--container));
margin-inline: auto;
}
/* ── 판맞춤 표시 — 넓은 화면에서만, 내용과 겹치지 않는 곳에 ──────────── */
.corner {
position: fixed;
width: 18px;
height: 18px;
z-index: 40;
pointer-events: none;
}
.corner-tl {
top: 10px;
left: 10px;
border-top: 1px solid var(--line-strong);
border-left: 1px solid var(--line-strong);
}
.corner-tr {
top: 10px;
right: 10px;
border-top: 1px solid var(--line-strong);
border-right: 1px solid var(--line-strong);
}
.corner-bl {
bottom: 10px;
left: 10px;
border-bottom: 1px solid var(--line-strong);
border-left: 1px solid var(--line-strong);
}
.corner-br {
bottom: 10px;
right: 10px;
border-bottom: 1px solid var(--line-strong);
border-right: 1px solid var(--line-strong);
}
@media (max-width: 900px) {
.corner {
display: none;
}
}
/* ── 헤더 ─────────────────────────────────────────────────────────────── */
.site-head {
position: sticky;
top: 0;
z-index: 50;
background: color-mix(in srgb, var(--surface) 90%, transparent);
backdrop-filter: blur(6px);
border-bottom: 1px solid var(--line);
}
.head-inner {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: var(--space-4);
padding-block: var(--space-3);
}
.wordmark {
font-size: var(--step-1);
font-weight: 600;
text-decoration: none;
}
.wordmark-en {
color: var(--ink-faint);
font-weight: 400;
margin-left: var(--space-1);
}
.nav {
display: flex;
gap: clamp(var(--space-3), 2vw, var(--space-5));
font-size: var(--step--1);
}
.nav a {
text-decoration: none;
color: var(--ink-muted);
border-bottom: 1px solid transparent;
padding-block: 2px;
transition: color var(--dur-quick) var(--ease-soft),
border-color var(--dur-quick) var(--ease-soft);
}
.nav a:hover {
color: var(--ink);
border-color: var(--ink);
}
/* ── 서문 ─────────────────────────────────────────────────────────────── */
.hero {
padding-block: var(--space-8) var(--space-7);
border-bottom: 1px solid var(--line);
}
.hero-meta {
font-size: var(--step--1);
color: var(--ink-muted);
margin-bottom: var(--space-5);
}
.hero-statement {
margin-top: var(--space-5);
max-width: 30em;
}
.hero-facts {
margin-top: var(--space-6);
display: flex;
flex-wrap: wrap;
gap: var(--space-4) var(--space-7);
border-top: 1px solid var(--line);
padding-top: var(--space-4);
}
.hero-facts dt {
font-size: var(--step--1);
color: var(--ink-faint);
}
.hero-facts dd {
font-weight: 500;
}
/* ── 인덱스 ───────────────────────────────────────────────────────────── */
.section {
padding-block: var(--space-8);
}
.index-h {
font-size: var(--step--1);
font-weight: 500;
color: var(--ink-muted);
letter-spacing: 0.2em;
}
.index {
list-style: none;
margin-top: var(--space-3);
padding: 0;
border-top: 1px solid var(--line-strong);
}
.index-row a {
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
gap: var(--space-4) var(--space-6);
align-items: baseline;
padding-block: var(--space-3);
border-bottom: 1px solid var(--line);
text-decoration: none;
transition: background var(--dur-quick) var(--ease-soft);
}
.index-row a:hover {
background: var(--ink);
color: var(--surface);
}
.idx-name {
font-size: var(--step-1);
font-weight: 500;
}
.idx-loc {
color: var(--ink-muted);
font-size: var(--step--1);
}
.index-row a:hover .idx-loc {
color: inherit;
}
.idx-year {
font-variant-numeric: tabular-nums;
color: var(--ink-faint);
}
.index-row a:hover .idx-year {
color: inherit;
}
/* ── 도면(스티키) ─────────────────────────────────────────────────────── */
.drawing {
background: var(--surface);
}
.drawing-grid {
display: grid;
grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
gap: var(--space-6) var(--space-7);
}
.drawing-stage {
position: sticky;
top: calc(var(--space-5) + 56px);
align-self: start;
}
.drawing-stage svg {
display: block;
width: 100%;
height: auto;
border: 1px solid var(--line);
background: var(--surface-bright);
}
.wall {
fill: none;
stroke: var(--ink);
stroke-width: 2;
}
.wall.inner {
stroke-width: 1.25;
}
.door {
fill: none;
stroke: var(--ink-muted);
stroke-width: 1;
stroke-dasharray: none;
}
.column {
fill: var(--ink);
}
.dim path {
fill: none;
stroke: var(--line-strong);
stroke-width: 1;
}
.dim text {
font-size: 12px;
fill: var(--ink-faint);
font-variant-numeric: tabular-nums;
}
.room-label text {
font-size: 13px;
fill: var(--ink-muted);
}
.north path {
fill: none;
stroke: var(--ink);
stroke-width: 1.25;
}
.north text {
font-size: 12px;
fill: var(--ink-muted);
}
.drawing-caption {
margin-top: var(--space-2);
font-size: var(--step--1);
color: var(--ink-faint);
}
@media (prefers-reduced-motion: no-preference) {
@supports (animation-timeline: view()) {
.wall,
.wall.inner {
stroke-dasharray: 3400;
stroke-dashoffset: 3400;
animation: draw 1.4s linear both;
animation-timeline: --drawing;
animation-range: entry 10% contain 55%;
}
@keyframes draw {
to {
stroke-dashoffset: 0;
}
}
}
}
.drawing-notes h2 {
font-size: var(--step-2);
}
.drawing-notes p + p {
margin-top: var(--space-4);
}
.drawing-spec {
margin-top: var(--space-5);
display: grid;
grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
gap: var(--space-3) var(--space-5);
border-top: 1px solid var(--line);
padding-top: var(--space-4);
}
.drawing-spec dt {
font-size: var(--step--1);
color: var(--ink-faint);
}
.drawing-spec dd {
margin-top: 2px;
font-weight: 500;
font-variant-numeric: tabular-nums;
}
/* ── 사진 ─────────────────────────────────────────────────────────────── */
.photo {
border-top: 1px solid var(--line);
}
.photo h2 {
font-size: var(--step--1);
font-weight: 500;
color: var(--ink-muted);
letter-spacing: 0.2em;
}
.photo-grid {
margin-top: var(--space-4);
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-4);
}
.ph {
display: block;
}
.ph img {
display: block;
width: 100%;
height: auto;
filter: grayscale(1); /* 사진 파일이 흑백이 아니어도 페이지는 흑백이다 */
}
.ph-a {
grid-column: 1 / -1;
}
.ph figcaption {
margin-top: var(--space-2);
font-size: var(--step--1);
color: var(--ink-faint);
}
/* ── 연락 ─────────────────────────────────────────────────────────────── */
.contact {
border-top: 1px solid var(--line);
}
.contact-grid {
display: grid;
grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
gap: var(--space-5) var(--space-7);
align-items: start;
}
.contact address {
font-style: normal;
color: var(--ink-muted);
}
.contact-note {
color: var(--ink-muted);
max-width: 26em;
}
/* ── 푸터 ─────────────────────────────────────────────────────────────── */
.site-foot {
border-top: 1px solid var(--line-strong);
padding-block: var(--space-4);
font-size: var(--step--1);
}
.foot-inner {
display: flex;
justify-content: space-between;
gap: var(--space-3) var(--space-5);
flex-wrap: wrap;
}
.foot-meta {
color: var(--ink-faint);
}
/* ── 등장 모션 ────────────────────────────────────────────────────────── */
.reveal {
opacity: 0;
translate: 0 10px;
transition: opacity var(--dur-normal) var(--ease-soft),
translate var(--dur-normal) var(--ease-soft);
transition-delay: var(--delay, 0ms);
}
.reveal.is-in {
opacity: 1;
translate: 0 0;
}
@media (prefers-reduced-motion: reduce) {
.reveal {
opacity: 1;
translate: 0 0;
transition: none;
}
}
/* ── 반응형 ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.drawing-grid {
grid-template-columns: 1fr;
}
.drawing-stage {
position: static;
}
.contact-grid {
grid-template-columns: 1fr;
}
.hero,
.section {
padding-block: var(--space-6);
}
}
@media (max-width: 560px) {
.head-inner {
flex-direction: column;
align-items: flex-start;
gap: var(--space-1);
}
.nav {
width: 100%;
justify-content: space-between;
}
.index-row a {
grid-template-columns: 1fr auto;
}
.idx-loc {
grid-column: 1;
}
.idx-year {
grid-row: 1;
grid-column: 2;
}
}

View file

@ -0,0 +1,52 @@
/* ==========================================================================
스튜디오 디자인 토큰
프리셋: swiss-minimal
컨셉 문장: 판맞춤 도면 묶음 색이 아니라 선과 치수가 말한다.
레퍼런스: R1 johnpawson.com(실측: 724px 고정폭, 태그 동일 크기+색으로만
위계, 유일한 구분선 1px, 프로젝트는 제목/위치/연도 텍스트 )
R2 cereal( 크림 3단 모노크롬 우리는 중성 회색으로 번안)
R3 CSS scroll-driven view()+dashoffset(이중 게이트, 폴백=완성 도면)
하지 않은 : (무채색 100% 강조색 없음, 링크만 밑줄), radius 전면 0,
사진 캐러셀, 서비스 아이콘. 이유: 도면의 권위는 하나에 있다.
========================================================================== */
:root {
/* 타입 — Pawson 교훈: 크기를 다양하게 쓰지 않는다. 위계는 무게와 색으로. */
--step--1: 0.8125rem; /* 13px — 캡션·치수 */
--step-0: 1rem; /* 16px — 본문 */
--step-1: 1.125rem; /* 18px — 소제목(본문과 1단계 차이만) */
--step-2: 1.375rem; /* 22px — 섹션 표제 */
--step-3: clamp(1.75rem, 1.3rem + 2.4vw, 2.75rem); /* 44px — 서문 하나만 */
--leading-tight: 1.35;
--leading-normal: 1.8;
--font-body: "Pretendard Variable", Pretendard, -apple-system, sans-serif;
/* 무채색 3단계 + 선 2단계. 강조색 없음. */
--surface: #fdfdfb;
--ink: #111111;
--ink-muted: #555555;
--ink-faint: #8a8a8a;
--line: #d9d9d5;
--line-strong: #999999; /* Pawson의 유일한 구분선 색 */
--surface-bright: #ffffff; /* index 행 hover 반전의 가장 밝은 단계 */ /* Pawson의 유일한 구분선 색 */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 1rem;
--space-4: 1.5rem;
--space-5: 2.5rem;
--space-6: 4rem;
--space-7: 6rem;
--space-8: clamp(4.5rem, 3rem + 6vw, 8.5rem);
--radius: 0; /* 이 페이지에는 모서리 둥금이 없다 */
--container: 1080px;
--pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem);
--dur-quick: 140ms;
--dur-normal: 380ms;
--ease-soft: cubic-bezier(0.25, 1, 0.35, 1);
}