release: v0.11.0

This commit is contained in:
Yun Chan 2026-09-12 15:28:46 +09:00
parent 3c39a1731d
commit 45ba92ea82
45 changed files with 1459 additions and 1887 deletions

View file

@ -0,0 +1,43 @@
# 스튜디오 폼 — 디자인 결정 기록
## 0. 브리프와 범위
- 무엇을: 빛·비례·구조를 사진과 도면으로 함께 읽는 가상 공간건축 포트폴리오 예시.
- 누구에게: 건축 작업의 기록 방식을 살피고 프로젝트 인덱스로 이동하려는 방문자.
- 제약: 기존 흑백 사진·도면과 Pretendard를 보존한다. 실제 수행 이력·연락처로 오인될 수 없게 가상 사례와 생성 이미지라는 사실을 가까이에 표기한다. 기본 언어는 ko-KR 한국어이며, 영문은 고유 표기 FORM만 사용한다.
경로: **연장**. 정적 HTML의 토큰·콘텐츠 구조를 재구성했으며 이 문서가 이후 작업의 국소 기준이 된다.
## 1. 조사와 관찰
| 출처 | 관찰 | 적용 범위 |
| --- | --- | --- |
| [David Chipperfield Architects — Projects](https://davidchipperfield.com/projects) | 프로젝트 사진·모형과 그 아래 정렬된 메타데이터가 탐색의 위계를 소유하고, Grid/List/Filter는 보조 탐색으로 물러난다. | 사진을 첫 화면의 주 장면으로 두고, 인덱스는 번호·이름·위치·연도를 정렬한다. |
| [Klim Type Foundry](https://klim.co.nz/) | 글자와 작업물이 표면을 주도하고 인터페이스는 뒤로 물러난다. | 큰 헤드라인, 얇은 선, 흑백 사진의 우선순위. |
| [Carbon 2x Grid](https://carbondesignsystem.com/elements/2x-grid/usage/) | 넓은 표면과 읽기 표면은 분리된 레일을 가져야 한다. | 최대 1800px stage와 1280px 정보 레일, 720px 본문 measure. |
표현을 복제하지 않았다. 이 페이지의 고유한 결합은 `제목 → 실제로 보이는 사진 → 도면의 이유`라는 건축 기록 순서다.
## 2. 수정 전 문제와 결정
- 1440px 첫 화면에서 소개 문단이 약 80px 열에 갇혀 단어마다 줄바꿈됐고, 사진과 인덱스 행동이 첫 화면에 없었다.
- `설립 연도 예시`, `팀 구성 예시`처럼 작업 판독에 기여하지 않는 가상 수치를 제거했다.
- 기존 인덱스의 여섯 항목은 모두 같은 도면으로 연결됐지만 그 관계가 설명되지 않았다. 이제 목록 직전에 같은 가상 도면을 다른 관점에서 참조한다는 사실을 고지한다.
- 기존 생성 이미지는 유지하고 각 사진 캡션에 `생성 이미지 · 실제 프로젝트 사진 아님`을 남긴다.
## 3. 토큰과 레이아웃 계약
- 표면 `#fdfdfb`, 전경 `#171b19`, 중립 선 `#d8dbd7`, 보조 글자 `#5b615d`.
- 본문 16px 이상, 캡션 12px 이상, 본문 줄간 1.75, 읽기 폭 720px.
- `h1: clamp(2.5rem, 5.5vw, 5.5rem)`; Pretendard 단일 패밀리.
- 1440px 정보 레일 최대 1280px, stage 최대 1800px; 2560px에서는 사진만 stage에 머물고 산문은 720px 내에서 읽힌다.
- 모바일 gutter는 20px, 320px에서 16px. 이미지의 원본 비율을 유지하며 `object-fit: cover`는 슬롯에서 정한 비율 안의 편집에만 사용한다.
성능 예산: 첫 화면 JS 0KB / 첫 인터랙션은 정적 링크 / 폰트 패밀리 1개. 이미지 생성·추가는 하지 않는다.
## 4. 검증 추적
- 320, 390, 768, 1440, 1920, 2560px에서 문서 및 요소 가로 오버플로, h1/본문 가시성, 레일 상한, 이미지 로드, 탭 순서를 점검한다.
- `prefers-reduced-motion`과 효과 제거 상태에서도 콘텐츠가 같은 순서로 읽히는지 점검한다.
- 200% 텍스트 확대에서 본문·CTA가 사라지지 않는지 점검한다.
- 실행 결과와 화면 캡처는 `outputs/design-expertise-20260912/form/`에 남긴다.

View file

@ -4,300 +4,91 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>스튜디오 폼 · 공간건축연구소</title>
<meta
name="description"
content="형태는 침묵하고 치수가 태도를 증명한다. 비례와 구조의 명료성으로 설계하는 건축연구소의 프로젝트 인덱스와 도면."
/>
<meta name="description" content="빛, 비례, 구조를 도면과 사진으로 읽는 가상 공간건축 포트폴리오의 기록 형식." />
<meta property="og:title" content="스튜디오 폼 · 공간건축연구소" />
<meta
property="og:description"
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"
/>
<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=3" />
<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='%23171b19' stroke-width='2'/%3E%3Crect x='11' y='11' width='10' height='10' fill='%23171b19'/%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>
<div class="rail head-inner">
<a class="wordmark" href="#main">스튜디오 폼 <span>FORM</span></a>
<nav class="nav" aria-label="섹션">
<a href="#index">인덱스</a>
<a href="#drawing">도면</a>
<a href="#photo">사진</a>
<a href="#contact">연락</a>
<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 class="stage hero-top">
<div class="hero-title">
<p class="eyebrow">가상 공간건축 포트폴리오 · 설계 기록 형식</p>
<h1 id="hero-h">공간을 짓는<br />명료한 질서.</h1>
</div>
<div class="hero-intro">
<p>빛이 머무는 방향과 구조가 건너는 거리를 함께 읽습니다. 사진은 결과를, 도면은 그 결과가 만들어진 이유를 남깁니다.</p>
<a class="index-link" href="#index">프로젝트 인덱스 보기 <span aria-hidden="true">↓</span></a>
</div>
</div>
<figure class="hero-image stage">
<img src="./assets/pavilion-bw.webp" alt="긴 수평창이 난 콘크리트 파빌리온에 벽 그림자가 지는 모습" width="1440" height="810" />
<figcaption><span>폼 하우스 · 가평 · 2025</span><span>생성 이미지 · 실제 프로젝트 사진 아님</span></figcaption>
</figure>
<div class="hero-caption rail"><p>이 페이지의 프로젝트명·연도·도면·이미지는 공간 설계 기록의 형식을 설명하기 위한 가상 사례입니다.</p></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>
<section id="index" class="section index-section" aria-labelledby="index-h">
<div class="wide-rail">
<div class="section-head"><h2 id="index-h">프로젝트 인덱스</h2><p>여섯 항목은 한 장의 가상 설계 도면을 서로 다른 기록의 관점에서 참조합니다.</p></div>
<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>
<li><a href="#drawing"><span class="idx-no">01</span><span class="idx-name">폼 하우스</span><span class="idx-loc">경기 가평</span><span class="idx-year">2025</span></a></li>
<li><a href="#drawing"><span class="idx-no">02</span><span class="idx-name">백령도 해녀기념관</span><span class="idx-loc">인천 백령도</span><span class="idx-year">2024</span></a></li>
<li><a href="#drawing"><span class="idx-no">03</span><span class="idx-name">은평 재생주거</span><span class="idx-loc">서울 은평</span><span class="idx-year">2024</span></a></li>
<li><a href="#drawing"><span class="idx-no">04</span><span class="idx-name">제주 돌담 스튜디오</span><span class="idx-loc">제주 애월</span><span class="idx-year">2023</span></a></li>
<li><a href="#drawing"><span class="idx-no">05</span><span class="idx-name">성수 인쇄공장 재생</span><span class="idx-loc">서울 성수</span><span class="idx-year">2022</span></a></li>
<li><a href="#drawing"><span class="idx-no">06</span><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="wide-rail drawing-grid">
<div class="drawing-notes">
<p class="eyebrow">도면으로 읽는 장면</p>
<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>
<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 class="drawing-stage">
<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="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>
</section>
<!--
사진 — 흑백 3점. 그리드는 엄격하게, 크기는 사진이 요구하는 대로.
-->
<section id="photo" class="section photo" aria-labelledby="photo-h">
<div class="wrap">
<h2 id="photo-h" class="reveal">사진</h2>
<div class="wide-rail"><div class="section-head photo-head"><h2 id="photo-h">사진 시퀀스</h2><p>빛의 방향, 재료의 밀도, 비례의 검토를 순서대로 기록합니다.</p></div>
<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>
<figure class="ph ph-wide"><img src="./assets/pavilion-bw.webp" alt="긴 수평창이 낸 콘크리트 파빌리온에 벽 그림자가 지는 모습" width="1440" height="810" loading="lazy" /><figcaption><span>폼 하우스 · 남측 · 준공 후 첫 여름</span><span>생성 이미지 · 실제 프로젝트 사진 아님</span></figcaption></figure>
<figure class="ph ph-narrow"><img src="./assets/interior-bw.webp" alt="천창으로 한 줄기 빛이 사선으로 들어오는 미장 마감 전시실" width="900" height="1200" loading="lazy" /><figcaption><span>백령도 해녀기념관 · 제1전시실</span><span>생성 이미지 · 실제 프로젝트 사진 아님</span></figcaption></figure>
<figure class="ph ph-note"><p class="eyebrow">비례의 검토</p><p>빛과 재료의 표정은 사진으로, 공간의 관계는 도면으로 살펴봅니다.</p></figure>
<figure class="ph ph-model"><img src="./assets/model-bw.webp" alt="직육면체를 쌓은 백색 석고 모형에 측광이 지는 모습" width="1100" height="825" loading="lazy" /><figcaption><span>스터디 모델 07 · 석고</span><span>생성 이미지 · 실제 프로젝트 사진 아님</span></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>
<section id="contact" class="section contact" aria-labelledby="contact-h"><div class="rail contact-grid"><h2 id="contact-h">구성 안내</h2><address>가상 공간건축 포트폴리오<br />실제 연락처를 제공하지 않습니다.</address><p>이 페이지는 도면·사진·사양을 한 흐름으로 읽는 포트폴리오 형식의 예시입니다. 신규 프로젝트 상담이나 견적을 접수하지 않습니다.</p></div></section>
</main>
<footer class="site-foot">
<div class="wrap foot-inner">
<p>스튜디오 폼 · 공간건축연구소</p>
<p class="foot-meta">© 2014–2026</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>
<footer class="site-foot"><div class="rail foot-inner"><p>스튜디오 폼 · 가상 공간건축 포트폴리오</p><p>설계 기록 형식 예시</p></div></footer>
</body>
</html>

View file

@ -1,497 +1,91 @@
@import url("./tokens.css");
@import url("./tokens.css?v=3");
/* ==========================================================================
스튜디오 폼 — swiss-minimal. 판맞춤 도면 묶음.
========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { background: var(--surface); scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { min-width: 0; 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; }
img { display: block; max-width: 100%; height: auto; }
h1, h2 { font-weight: 600; line-height: var(--leading-tight); letter-spacing: -.025em; word-break: keep-all; overflow-wrap: break-word; text-wrap: balance; }
p, dd, dt, address, figcaption { word-break: keep-all; overflow-wrap: break-word; text-wrap: pretty; }
a { color: inherit; }
a:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.rail, .wide-rail, .stage { width: min(100% - 2 * var(--pad), var(--rail)); margin-inline: auto; }
.wide-rail, .stage { width: min(100% - 2 * var(--pad), var(--stage)); }
.skip { position: absolute; left: -999px; top: 0; z-index: 100; background: var(--ink); color: var(--surface); padding: var(--space-3); }
.skip:focus { left: 0; }
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin: 0;
}
.site-head { position: sticky; top: 0; z-index: 20; min-height: var(--header-h); background: color-mix(in srgb, var(--surface) 96%, transparent); border-bottom: 1px solid var(--line); backdrop-filter: blur(8px); }
.head-inner { min-height: var(--header-h); display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); }
.wordmark { font-weight: 600; text-decoration: none; letter-spacing: -.02em; }
.wordmark span { margin-left: var(--space-1); color: var(--ink-faint); font-weight: 400; }
.nav { display: flex; gap: clamp(1rem, 2vw, 2.5rem); font-size: var(--step--1); }
.nav a { display: inline-flex; align-items: center; min-height: 2.75rem; text-decoration: none; color: var(--ink-muted); border-bottom: 1px solid transparent; transition: color var(--dur-quick) var(--ease), border-color var(--dur-quick) var(--ease); }
.nav a:hover { color: var(--ink); border-color: var(--ink); }
html {
-webkit-text-size-adjust: 100%;
scroll-behavior: smooth;
background: var(--surface);
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
.hero { padding: var(--space-6) 0 var(--space-5); border-bottom: 1px solid var(--line); }
.hero-top { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(18rem, .7fr); gap: var(--space-6); align-items: end; margin-bottom: var(--space-5); }
.eyebrow { font-size: var(--step--1); line-height: 1.5; color: var(--ink-muted); letter-spacing: .08em; }
.hero-title .eyebrow { margin-bottom: var(--space-3); }
h1 { font-size: var(--step-display); max-width: 10em; }
.hero-intro { max-width: 28rem; padding-bottom: var(--space-1); }
.hero-intro p { color: var(--ink-muted); }
.index-link { display: inline-flex; align-items: center; gap: var(--space-2); min-height: 2.75rem; margin-top: var(--space-3); font-weight: 500; text-underline-offset: .35em; text-decoration-thickness: 1px; }
.index-link span { font-size: 1.25em; }
.hero-image img { width: 100%; aspect-ratio: 2.35 / 1; object-fit: cover; object-position: center 58%; filter: grayscale(1); }
figcaption { display: flex; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-2); color: var(--ink-faint); font-size: var(--step--1); line-height: 1.55; }
.hero-caption { margin-top: var(--space-3); color: var(--ink-muted); font-size: var(--step--1); }
.hero-caption p { max-width: var(--measure); }
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;
}
.section { padding-block: var(--space-7); }
.section-head { display: grid; grid-template-columns: minmax(14rem, .7fr) minmax(0, 1fr); gap: var(--space-5); align-items: baseline; margin-bottom: var(--space-5); border-top: 1px solid var(--line-strong); padding-top: var(--space-3); }
.section-head h2 { font-size: var(--step-1); letter-spacing: .03em; }
.section-head p { max-width: 40rem; color: var(--ink-muted); font-size: var(--step--1); }
.index { list-style: none; padding: 0; border-top: 1px solid var(--line-strong); }
.index li { border-bottom: 1px solid var(--line); }
.index a { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr) minmax(8rem, .35fr) 4rem; gap: var(--space-3); align-items: baseline; padding: 1.15rem var(--space-2); text-decoration: none; transition: background var(--dur-quick) var(--ease), color var(--dur-quick) var(--ease); }
.index a:hover { background: var(--ink); color: var(--surface); }
.idx-no, .idx-loc, .idx-year { font-size: var(--step--1); color: var(--ink-faint); }
.idx-name { font-size: var(--step-1); font-weight: 500; }
.idx-year { font-variant-numeric: tabular-nums; text-align: right; }
.index a:hover .idx-no, .index a:hover .idx-loc, .index a:hover .idx-year { color: inherit; }
: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;
}
.drawing { border-top: 1px solid var(--line); background: var(--surface-raised); }
.drawing-grid { display: grid; grid-template-columns: minmax(17rem, .82fr) minmax(20rem, 1fr); gap: clamp(2.5rem, 6vw, 8rem); align-items: start; }
.drawing-notes { max-width: var(--measure); }
.drawing-notes .eyebrow { margin-bottom: var(--space-3); }
.drawing-notes h2 { font-size: var(--step-2); margin-bottom: var(--space-4); }
.drawing-notes p + p { margin-top: var(--space-3); }
.drawing-spec { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); margin-top: var(--space-5); padding-top: var(--space-4); border-top: 1px solid var(--line); }
.drawing-spec dt { font-size: var(--step--1); color: var(--ink-faint); }
.drawing-spec dd { margin-top: var(--space-1); font-size: var(--step--1); font-weight: 500; font-variant-numeric: tabular-nums; }
.drawing-stage { position: sticky; top: calc(var(--header-h) + var(--space-3)); }
.drawing-stage svg { display: block; width: 100%; height: auto; border: 1px solid var(--line); background: var(--surface); }
.wall { fill: none; stroke: var(--ink); stroke-width: 2; }
.wall.inner { stroke-width: 1.25; }
.door, .dim path, .north path { fill: none; stroke: var(--ink-muted); stroke-width: 1; }
.column { fill: var(--ink); }
.dim text, .north text { fill: var(--ink-faint); font-size: 12px; }
.room-label text { fill: var(--ink-muted); font-size: 13px; }
.drawing-caption { display: block; }
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);
}
.photo { border-top: 1px solid var(--line); }
.photo-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(15rem, .55fr); gap: var(--space-5); }
.ph-wide { grid-column: 1 / -1; }
.ph-wide img { width: 100%; aspect-ratio: 2.35 / 1; object-fit: cover; filter: grayscale(1); }
.ph-narrow { align-self: start; }
.ph-narrow img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; filter: grayscale(1); }
.ph-model { align-self: end; }
.ph-model img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; filter: grayscale(1); }
.ph-note { align-self: end; border-top: 1px solid var(--line-strong); padding-top: var(--space-3); max-width: 30rem; }
.ph-note p:last-child { margin-top: var(--space-3); font-size: var(--step-1); line-height: 1.55; }
:focus-visible {
outline: 2px solid var(--ink);
outline-offset: 3px;
}
.contact { border-top: 1px solid var(--line); }
.contact-grid { display: grid; grid-template-columns: .7fr 1fr 1.2fr; gap: var(--space-5); align-items: start; }
.contact h2 { font-size: var(--step-1); letter-spacing: .03em; }
.contact address, .contact p { color: var(--ink-muted); font-style: normal; }
.site-foot { border-top: 1px solid var(--line-strong); padding-block: var(--space-4); font-size: var(--step--1); color: var(--ink-muted); }
.foot-inner { display: flex; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.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;
}
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } .nav a, .index a { transition: none; } }
@media (max-width: 48rem) { .hero-top, .drawing-grid { grid-template-columns: 1fr; } .hero-top { gap: var(--space-4); } .hero-intro { max-width: var(--measure); } .drawing-stage { position: static; grid-row: 1; } .drawing-notes { grid-row: 2; } .photo-grid { grid-template-columns: minmax(0, 1fr) minmax(11rem, .72fr); } .contact-grid { grid-template-columns: 1fr; gap: var(--space-3); } }
@media (max-width: 35rem) { .head-inner { padding-block: var(--space-2); align-items: flex-start; flex-direction: column; gap: 0; } .site-head { min-height: auto; } .nav { width: 100%; justify-content: space-between; gap: var(--space-2); } .nav a { min-height: 2.25rem; } .hero { padding-top: var(--space-5); } .hero-image img, .ph-wide img { aspect-ratio: 1.45 / 1; } .section-head { grid-template-columns: 1fr; gap: var(--space-2); } .index a { grid-template-columns: 2.25rem minmax(0, 1fr) auto; gap: var(--space-2); padding-inline: 0; } .idx-loc { grid-column: 2; } .idx-year { grid-column: 3; grid-row: 1; text-align: right; } .photo-grid { grid-template-columns: 1fr; } .ph-note { grid-row: 2; } .ph-narrow { grid-row: 3; max-width: 70%; } .ph-model { grid-row: 4; } .contact { padding-block: var(--space-6); } figcaption { flex-direction: column; gap: 0; } .drawing-spec { grid-template-columns: 1fr; } }

View file

@ -1,52 +1,34 @@
/* ==========================================================================
스튜디오 폼 — 디자인 토큰
프리셋: 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단계. 강조색 없음. */
--font-body: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont, sans-serif;
--surface: #fdfdfb;
--ink: #111111;
--ink-muted: #555555;
--ink-faint: #8a8a8a;
--line: #d9d9d5;
--line-strong: #999999; /* Pawson의 유일한 구분선 색 */
--surface-bright: #ffffff; /* index 행 hover 반전의 가장 밝은 단계 */ /* Pawson의 유일한 구분선 색 */
--surface-raised: #ffffff;
--ink: #171b19;
--ink-muted: #5b615d;
--ink-faint: #686e6a;
--line: #d8dbd7;
--line-strong: #a7aca7;
--step--1: 0.75rem;
--step-0: 1rem;
--step-1: 1.25rem;
--step-2: clamp(1.75rem, 1.3rem + 1.7vw, 2.5rem);
--step-display: clamp(2.5rem, 5.5vw, 5.5rem);
--leading-tight: 1.12;
--leading-normal: 1.75;
--measure: 45rem;
--rail: 78rem;
--stage: 112.5rem;
--pad: clamp(1.25rem, 1rem + 2vw, 3rem);
--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);
--space-6: clamp(3.5rem, 2.2rem + 4vw, 6rem);
--space-7: clamp(5rem, 3rem + 6vw, 9rem);
--header-h: 4rem;
--dur-quick: 140ms;
--dur-normal: 380ms;
--ease-soft: cubic-bezier(0.25, 1, 0.35, 1);
--ease: cubic-bezier(.25, 1, .35, 1);
}
@media (min-width: 120rem) { :root { --rail: 80rem; --stage: 112.5rem; } }
@media (max-width: 20rem) { :root { --pad: 1rem; } }