feat(site): rework 19 marketing showcases for composition diversity
Some checks are pending
ci / build (push) Waiting to run

Measured convergence before: split hero 13/19, top-bar nav 19/19,
one-line notice footer 14/19, body Pretendard 17/21, 10 similarity
pairs above 0.78. Each showcase got a pre-assigned hero family, nav
form, footer form, type pair, background, accent hue, radius, motion
grammar and material from outputs/rework-2026-10-06/plan.md; direction
cards and the chosen reason are recorded in every design.md.

After: 0 similarity warnings, 19 distinct display faces, 7 hero
families, 5 nav forms, 5 footer forms, no scroll reveals, 5 showcases
with SVG filter materials. Example contact values replace bracket
placeholders under the existing fictional-brand notices. Thumbnails,
OG images, card copy and three e2e assertions updated; dead CSS in
dure-enrollment and hannam-jari removed; similarity.mjs learns the new
font families.
This commit is contained in:
Yun Chan 2026-10-06 16:55:50 +09:00
parent 88c11682b1
commit 8e3cdb0d3b
296 changed files with 19131 additions and 17538 deletions

View file

@ -2,26 +2,44 @@
## 브리프
- 무엇을: 시뮬레이션 신호와 연구 보고·윤리 경계를 설명하는 개념 페이지.
- 누구에게: 임상 결과로 오해하지 않고 신호·제한·보고 필드를 읽어야 하는 방문자.
- 제약: no clinical/participant data 표기, 조작 동작, 정적 reduced-motion 경로를 유지한다.
- 무엇을: 64채널 표면 전극 연구가 무엇을 기록하고 무엇을 기록하지 않을지, 데이터 권리와 보고 항목을 먼저 밝히는 신경 인터페이스 연구 개념서.
- 누구에게: 임상 결과로 오해하지 않고 연구의 경계를 읽어야 하는 일반 방문자·연구 윤리 검토자.
- 제약: 임상시험·참여자·실제 기기 없음 표기, 시뮬레이션 기록 캔버스(`#raster`)의 화면 밖 정지와 움직임 줄이기 정지 경로를 유지한다.
- 기본 언어: 한국어(`lang="ko"`).
## 2026-10 재작업 이유
2026-09판은 lumina-optics·pulsegate와 같은 니어블랙 계기판 템플릿이었다(유사도 0.83). 표제 "A signal interface, explained clearly"가 정직함을 변명했고, 히어로 본문·메타 3칸·푸터가 같은 면책을 반복했다.
## 결정표
| 축 | 관찰과 적용 범위 | 결정·역할 토큰 | 기각 조건 |
| 축 | 이 브리프의 재료 | 결정·역할 토큰 | 기각 조건 |
|---|---|---|---|
| 구도 | 기준 화면의 메타·래스터·장치·윤리 구분이 약했다. | 세 상태 메타, 장치 설명 레일, 윤리 항목 레일을 역할별로 나눈다. `--line`, `--accent-dim`, `--space-4`. | 레일이 제목이나 상태 문구를 분절해 읽기 순서를 해치면 제거한다. |
| 타입 | 연구 한계와 범례가 13px 아래로 약해지면 사실 범위가 묻힌다. | 메타·래스터 머리말·범례를 `--step--1` 이상으로 둔다. | 좁은 폭에서 메타가 지나치게 길어져 제목이나 행동을 밀면 행 분리한다. |
| 색 | 스파이크는 신호 표면의 주체이고 경계선은 보조다. | `--accent`, `--accent-dim`, `--line`으로 스파이크·시뮬레이션 범례·레일을 구분한다. | 밝은 스파이크가 임상 결과처럼 읽히거나 범례보다 과장되면 밝기를 낮춘다. |
| 은유 | 연구 참여의 첫 문서는 동의서다. 이 개념서의 고유한 주장은 "권리가 신호보다 먼저"다. | 표제 "신호 기록 전에 동의부터 받습니다"(2026-10-02 카피 정리 전 "동의는 신호보다 먼저 기록됩니다"). 장(章) 번호와 번호 조항으로 읽히는 문서 흐름, 가운데 한 단(`--measure: 40rem`). | 문서 흐름이 너무 길어 390 폭에서 기록지가 첫 화면 바로 아래로 밀리면 표제부 여백을 줄인다. |
| 바탕 | 뇌파 기록계(EEG chart recorder) 용지는 옅은 연두 바탕에 붉은 인쇄 눈금이다. | `--surface: #dbe5cb`, 눈금 `--grid: #d88f7f`(선 전용), 신호는 검은 잉크, 동기 발화만 붉은 잉크 `--accent: #a3271c`. | 붉은 동기 발화가 임상 이벤트처럼 과장되어 보이면 굵기를 1px로 낮춘다. |
| 신호 | 64채널 스파이크 래스터는 종이에 찍힌 기록이다. | 캔버스를 화면 양끝까지 뻗은 기록지 띠로 바꾸고, 종이처럼 왼쪽으로 흘린다. 첫 장은 이미 기록된 상태로 시작한다. 고밀도 화면에서 `drawImage`가 dpr 배로 늘어나던 결함을 장치 픽셀 이동으로 고쳤다. | 화면 밖에서 계속 그리면 e2e가 실패한다(IntersectionObserver 정지). |
| 타입 | 조항은 읽는 글이다. | 표제 함렛(Hahmlet) 600, 본문 고운바탕 18px·행간 1.85. 모노 없음 — 2026-09판의 모노 메타 칸이 템플릿 지문이었다. | 바탕체 본문이 14px 이하로 내려가는 곳(캡션)은 대비 4.5:1 이상인지 확인한다. |
| 보고 | 측정하지 않은 값은 비워 두는 것이 이 연구의 태도다. | 보고 표의 값 열은 전부 `—`, 셋째 열은 "비워 둔 이유"(참여자 기록 없음·측정 안 함 등). | 이유 칸이 다시 면책 문장 반복이 되면 짧은 사실로 줄인다. |
| 형태·모션 | 문서는 모서리를 굴리지 않는다. | `--radius: 0`, 구분은 괘선. 기록지 외에는 움직이는 것이 없다. | — |
## 근거와 경계
## 카피 방향 (2026-10-02)
[art-direction.md](../../../../../packages/skill/references/art-direction.md)의 Hofmann 관련 군집 관찰은 신호/메타/윤리 표면을 나누는 데만 적용했다. [typography.md](../../../../../packages/skill/references/typography.md)의 Ruder 관련 실제 상태·숫자 proof는 13px 이상 메타와 표에만 적용했다. [visual-design-lineage.md](../../../../../packages/skill/references/visual-design-lineage.md)의 Albers 관련 색 맥락은 금색 신호와 어두운 바탕의 구분에만 적용했다. 이는 학습·임상 성능 근거가 아니다.
잠언형 표제("동의는 신호보다 먼저 기록됩니다", "측정하지 않은 숫자를 채우는 순간 이 표는 광고가 됩니다")를 절차를 설명하는 정보 문장으로 바꿨다. 전극이 '읽는다', 판이 '답한다' 같은 무생물 주어 문장은 사람이 하는 일로 다시 쓴다. 조항 제목은 합니다체로 통일한다("연구 목적 외에는 쓰지 않습니다"). 장 번호·괘선 같은 문서 형식은 디자인이 맡고, 문장은 연구 윤리 문서에서 실제로 쓰는 말(동의 절차, 열람 권한, 보관 기간)을 쓴다.
[trustworthy-showcases.md](../../../../../packages/skill/references/trustworthy-showcases.md)에 따라 시뮬레이션 표기는 래스터와 인접하게, no clinical/participant data 표기는 기존 가까운 문맥에 유지한다.
## 진실 범위
## 2026-09-12 현재 검증 기록
헤더 아래 띠 한 곳이 소유한다("임상시험·참여자·실제 기기가 없으며, 아래 기록지의 신호는 시뮬레이션"). 기록지 캡션의 `시뮬레이션`은 그림 자체의 속성 표기다. 히어로 본문·표제·조항에는 면책 문구를 넣지 않는다. `thread-array.webp`는 페이지에서 뺐다(자산 파일은 남긴다).
- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다.
- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다.
- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다.
## 검증
- `node tools/instrument-showcases-e2e.mjs` — `#raster` 보이는 동안 변화, 화면 밖 정지, 움직임 줄이기 정지.
- `node tools/similarity.mjs` — 재작업 엄격 대상.
## 내비·푸터 결정 (2026-10-06 연장)
- 내비: 상단 바의 섹션 링크를 빼고 표제부에 녹인 차례(`nav.toc`)로 바꿨다. 리드 아래에 "차례" 표제와 `그림 1 · 제1장 · 제2장 · 제3장` 네 줄 — 연구 문서의 목차처럼 번호(붉은 잉크 `--accent`)·제목·괘선(`--grid`)만으로 짠다. 상단 바에는 워드마크만 남는다. 분배표의 "표제부 차례 3종" 중 하나다.
- 푸터: 고지 띠 유지(브랜드 한 줄 + "designpaca 쇼케이스"). 마지막 섹션 `.closing`이 "기록지로 돌아가기"로 행동을 끝낸다.
## 변경 기록
- 2026-10-06 연장: 상단 바 내비 → 표제부 차례. 토큰·서체·표제부 구도·기록지 캔버스·조항·푸터는 그대로.

View file

@ -1,244 +1,187 @@
<!doctype html>
<html lang="en">
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Synapse BCI Lab · Neural Interface Study</title>
<title>Synapse BCI Lab · 신경 인터페이스 연구 개념서</title>
<meta
name="description"
content="An illustrative neural-interface study showing how simulated signals, reporting fields, and research commitments can be communicated."
/>
<meta property="og:title" content="Synapse BCI Lab · Neural Interface Study" />
<meta
property="og:description"
content="An illustrative interface concept with simulated signals and no clinical results."
content="64채널 표면 전극 연구에서 기록할 신호와 기록하지 않을 신호, 데이터 권리, 보고 항목을 정리한 신경 인터페이스 연구 개념서."
/>
<meta property="og:title" content="Synapse BCI Lab · 신경 인터페이스 연구 개념서" />
<meta property="og:description" content="64채널 표면 전극 연구의 동의 절차, 데이터 권리, 보고 항목을 정리한 연구 개념서." />
<meta property="og:type" content="website" />
<meta name="theme-color" content="#08090B" />
<meta property="og:image" content="./og.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="theme-color" content="#dbe5cb" />
<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=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Sans+KR:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap"
href="https://fonts.googleapis.com/css2?family=Gowun+Batang:wght@400;700&family=Hahmlet:wght@400;600;700&display=swap"
/>
<link rel="stylesheet" href="./styles/main.css?v=20260912all" />
<link rel="stylesheet" href="./styles/main.css?v=20261006" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%2308090B'/%3E%3Cpath d='M6 24l6-6 4 4 9-14' fill='none' stroke='%23D9A441' stroke-width='2'/%3E%3Cpath d='M19 8h6v6' fill='none' stroke='%23D9A441' stroke-width='2'/%3E%3C/svg%3E"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23DBE5CB'/%3E%3Cpath d='M0 8h32M0 16h32M0 24h32M8 0v32M16 0v32M24 0v32' stroke='%23D88F7F' stroke-width='.6'/%3E%3Cpath d='M3 18h7l2-9 3 15 3-11 2 5h9' fill='none' stroke='%2317201A' stroke-width='2'/%3E%3C/svg%3E"
/>
</head>
<body>
<a class="skip" href="#main">Skip to main content</a>
<a class="skip" href="#main">본문으로 건너뛰기</a>
<header class="site-head">
<div class="wrap head-inner">
<a class="wordmark" href="#main">synapse<span class="wordmark-dot">·</span>bci</a>
<nav class="nav" aria-label="Sections">
<a href="#raster">Raster</a>
<a href="#device">Device</a>
<a href="#numbers">Numbers</a>
<a href="#ethics">Ethics</a>
</nav>
<a class="wordmark" href="#main">Synapse BCI Lab<span>연구 개념서</span></a>
</div>
</header>
<div class="scope-note">
<p class="wrap">개념 페이지입니다. 임상시험·참여자·실제 기기가 없으며, 아래 기록지의 신호는 시뮬레이션입니다.</p>
</div>
<main id="main">
<section class="hero" aria-labelledby="hero-h">
<div class="wrap hero-grid">
<div class="hero-text">
<p class="hero-kicker reveal">Illustrative μECoG concept · simulated signal display</p>
<h1 id="hero-h" class="reveal" style="--delay: 60ms">
A signal interface,<br />explained clearly
</h1>
<p class="lead reveal" style="--delay: 120ms">
This page illustrates how a neural-interface study could describe
signals, reporting, and safeguards. It is not a clinical device,
a trial, or evidence of performance. The raster is simulated and
contains no participant data.
</p>
<dl class="trial-register reveal" style="--delay: 150ms">
<div>
<dt>study status</dt>
<dd>illustrative concept · no trial</dd>
</div>
<div>
<dt>reporting</dt>
<dd>no clinical outcomes reported</dd>
</div>
<div>
<dt>raster source</dt>
<dd>simulated signal · no participant data</dd>
</div>
</dl>
<div class="hero-actions reveal" style="--delay: 180ms">
<a class="btn" href="#numbers">See the reporting format</a>
<a class="link-quiet" href="#ethics">Read the research principles</a>
</div>
</div>
<figure class="raster-frame reveal" style="--delay: 140ms">
<figcaption class="raster-head">
<span>SPIKE RASTER · 64 CH · SIMULATED</span>
<span>2.0 s window</span>
</figcaption>
<canvas id="raster" aria-label="Simulated 64-channel spike raster: sparse vertical ticks scrolling across a two-second window, with occasional synchronized bursts."></canvas>
<div class="raster-legend">
<span class="legend-tick" aria-hidden="true"></span>
<span>each tick — one detected spike · bursts are channel-sync events</span>
</div>
</figure>
<section class="title-block" aria-labelledby="hero-h">
<div class="doc">
<p class="doc-id">연구 개념서 SYN-64 · 2026년 10월판</p>
<h1 id="hero-h">신호 기록 전에<br />동의부터 받습니다</h1>
<p class="lead">
64채널 표면 전극으로 기록할 신호와 기록하지 않을 신호, 기록을 볼 수 있는 사람과
보관 기간을 먼저 정리했습니다. 신호 기록 예시는 그 아래에 있습니다.
</p>
<nav class="toc" aria-labelledby="toc-h">
<h2 id="toc-h" class="toc-title">차례</h2>
<ol class="toc-list">
<li><a href="#recorder"><span class="toc-no">그림 1</span><span class="toc-name">64채널 스파이크 기록지</span></a></li>
<li><a href="#device"><span class="toc-no">제1장</span><span class="toc-name">뇌를 뚫지 않는 표면 전극</span></a></li>
<li><a href="#numbers"><span class="toc-no">제2장</span><span class="toc-name">보고서 필수 항목</span></a></li>
<li><a href="#ethics"><span class="toc-no">제3장</span><span class="toc-name">기록하기 전에 정하는 세 가지</span></a></li>
</ol>
</nav>
</div>
</section>
<figure id="recorder" class="recorder">
<canvas id="raster" aria-label="시뮬레이션한 64채널 스파이크 기록지: 붉은 눈금 위에 검은 세로 눈금이 2초 창을 따라 흘러가고, 가끔 여러 채널이 함께 튀는 동기 발화가 지나갑니다."></canvas>
<figcaption class="wrap">
<span><b>그림 1</b> · 64채널 스파이크 기록 · 시뮬레이션</span>
<span>눈금 하나 = 검출된 스파이크 하나 · 세로로 겹친 줄 = 채널 동기 발화 · 2초 창</span>
</figcaption>
</figure>
<section id="device" class="section" aria-labelledby="device-h">
<div class="wrap two">
<figure class="two-photo reveal">
<div class="doc">
<div class="article-head">
<span class="article-no">제1장</span>
<h2 id="device-h">뇌를 뚫지 않는 표면 전극</h2>
</div>
<p>
SYN-64는 뇌를 뚫지 않고 표면에 얹는 얇은 전극판입니다. 신호 품질보다 먼저
전극이 닿는 조직, 접촉 기간, 제거한 뒤 남는 물질을 확인합니다.
</p>
<figure class="plate">
<img
src="./assets/chip-macro.webp"
alt="Illustrative neural-interface concept plate with dense gold traces and a micro-electrode grid at one edge"
alt="금색 배선이 촘촘한 신경 인터페이스 개념 판, 한쪽 끝에 미세 전극 격자가 보이는 참고 이미지"
width="900"
height="1200"
loading="lazy"
/>
<figcaption>SYN-64 concept plate · illustrative reference image</figcaption>
<figcaption>그림 2 · SYN-64 개념 판 — 오른쪽 아래 금색 격자가 전극 64개 자리</figcaption>
</figure>
<div class="two-text">
<h2 id="device-h">Surface interface,<br />explained</h2>
<p>
The SYN-64 is an illustrative surface-interface concept. It helps
explain the questions a real device page must answer about contact,
tissue interaction, and user safety; it does not describe an
implant available for study or care.
</p>
<p class="muted">
The image is a constructed reference for this concept, not a
clinical product photograph or a surgical instruction.
</p>
</div>
</div>
</section>
<section id="numbers" class="section band" aria-labelledby="numbers-h">
<div class="wrap">
<h2 id="numbers-h" class="reveal">Reporting fields, not results</h2>
<div class="table-wrap reveal" style="--delay: 80ms">
<table>
<caption class="sr-only">
Illustrative research reporting fields — metric, reported value, and condition
</caption>
<section id="numbers" class="section" aria-labelledby="numbers-h">
<div class="doc">
<div class="article-head">
<span class="article-no">제2장</span>
<h2 id="numbers-h">보고서 필수 항목</h2>
</div>
<p>
아직 측정하지 않은 값은 비워 두고, 비워 둔 이유를 함께 적습니다.
</p>
<div class="table-wrap plate">
<table class="report-table">
<caption class="sr-only">연구 보고 항목 — 지표, 보고 값, 비워 둔 이유</caption>
<thead>
<tr>
<th scope="col">Metric</th>
<th scope="col" class="num">Value</th>
<th scope="col">Condition</th>
<th scope="col">지표</th>
<th scope="col" class="num">값</th>
<th scope="col">비워 둔 이유</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Decode latency</th>
<td class="num">—</td>
<td>No clinical result reported</td>
</tr>
<tr>
<th scope="row">Raw sampling</th>
<td class="num">—</td>
<td>No device specification reported</td>
</tr>
<tr>
<th scope="row">SNR</th>
<td class="num">—</td>
<td>No clinical measurement reported</td>
</tr>
<tr>
<th scope="row">Gesture classes</th>
<td class="num">—</td>
<td>No accuracy or participant result reported</td>
</tr>
<tr>
<th scope="row">Wireless link</th>
<td class="num">—</td>
<td>No system detail reported</td>
</tr>
<tr><th scope="row">해독 지연</th><td class="num">—</td><td>참여자 기록 없음</td></tr>
<tr><th scope="row">원신호 표본 주기</th><td class="num">—</td><td>기기 사양 미확정</td></tr>
<tr><th scope="row">신호 대 잡음비</th><td class="num">—</td><td>측정 안 함</td></tr>
<tr><th scope="row">동작 분류 수와 정확도</th><td class="num">—</td><td>참여자 기록 없음</td></tr>
<tr><th scope="row">무선 전송 방식</th><td class="num">—</td><td>시스템 설계 전</td></tr>
</tbody>
</table>
</div>
<p class="measure-note reveal" style="--delay: 140ms">
This table shows the fields a responsible report should identify.
It deliberately reports no clinical values, participant outcomes,
regulatory status, or device availability.
</p>
</div>
</section>
<section class="section plate" aria-label="Illustrative microelectrode layout reference image">
<figure class="plate-fig reveal">
<img
src="./assets/thread-array.webp"
alt="Illustrative gold-tipped microelectrode layout spreading across a dark reference stage"
width="1440"
height="810"
loading="lazy"
/>
<figcaption class="wrap">Illustrative electrode layout · reference image</figcaption>
</figure>
</section>
<section id="ethics" class="section" aria-labelledby="ethics-h">
<div class="wrap ethics-grid">
<h2 id="ethics-h">Research principles for a real study</h2>
<ul class="ethics-list">
<li class="reveal">
<h3>Signals are not advertising data</h3>
<p>
A real study should define purpose limits before data collection
and should not repurpose neural signals for advertising or profiling.
</p>
<div class="doc">
<div class="article-head">
<span class="article-no">제3장</span>
<h2 id="ethics-h">기록하기 전에 정하는 세 가지</h2>
</div>
<ol class="clauses">
<li>
<h3>연구 목적 외에는 쓰지 않습니다</h3>
<p>신경 신호는 광고·프로파일링에 쓰지 않습니다. 사용 범위는 수집 전에 문서로 정합니다.</p>
</li>
<li class="reveal" style="--delay: 80ms">
<h3>Withdrawal must be possible</h3>
<p>
A real protocol must explain withdrawal, support, and follow-up
before enrollment. This concept reports no participants or outcomes.
</p>
<li>
<h3>언제든 참여를 중단할 수 있습니다</h3>
<p>중단 방법, 중단 뒤 지원과 추적 관찰을 등록 전에 설명합니다. 그만둔 사람의 기록이 어떻게 처리되는지도 함께 적습니다.</p>
</li>
<li class="reveal" style="--delay: 160ms">
<h3>Data access needs a stated boundary</h3>
<p>
A real study must state how raw data is retained, who can access
it, and how publication separates aggregate findings from identity.
</p>
<li>
<h3>원자료 열람 권한을 밝힙니다</h3>
<p>원신호의 보관 기간, 열람 권한, 그리고 발표할 때 집계 결과와 신원을 어떻게 떼어 놓는지를 밝힙니다.</p>
</li>
</ul>
</ol>
</div>
</section>
<section class="section band contact" aria-labelledby="contact-h">
<div class="wrap contact-grid">
<h2 id="contact-h">About this concept</h2>
<p>
This is a design concept for explaining an emerging research area.
It does not recruit participants, accept data-access requests, or
provide medical or research services.
</p>
<a class="btn" href="#main">Return to the concept</a>
<section class="closing" aria-labelledby="closing-h">
<div class="doc">
<h2 id="closing-h">기록하지 않을 신호도<br />미리 정해 둡니다</h2>
<a class="back-link" href="#recorder">기록지로 돌아가기</a>
</div>
</section>
</main>
<footer class="site-foot">
<div class="wrap foot-inner">
<p>synapse bci · illustrative research concept</p>
<p class="foot-meta">no trial, clinical result, regulatory approval, or participant data</p>
<p>Synapse BCI Lab · 연구 개념서 SYN-64</p>
<p>designpaca 쇼케이스</p>
</div>
</footer>
<script>
// 기록지: 붉은 인쇄 눈금 위에 검은 잉크로 스파이크를 찍고 종이처럼 왼쪽으로 흘린다.
// 화면 밖이면 멈추고, 움직임 줄이기면 한 장만 그린다.
const canvas = document.getElementById("raster");
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
const CH = 64;
let ctx, w, h, dpr, running = false;
const PAPER = "#dbe5cb";
const GRID = "rgba(216, 143, 127, 0.55)";
const GRID_MAJOR = "rgba(196, 98, 80, 0.7)";
const INK = "rgba(23, 32, 26, 0.82)";
const INK_BURST = "rgba(163, 39, 28, 1)";
let ctx, w, h, dpr, running = false, feed = 0;
function paperColumn(x, width) {
ctx.fillStyle = PAPER;
ctx.fillRect(x, 0, width, h);
ctx.fillStyle = GRID;
for (let row = 0; row <= 8; row++) {
ctx.fillRect(x, Math.round((row * h) / 8), width, 1);
}
}
function fit() {
dpr = Math.min(devicePixelRatio || 1, 1.5);
@ -248,13 +191,14 @@
canvas.height = Math.round(h * dpr);
ctx = canvas.getContext("2d");
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.fillStyle = "#0b0d10";
ctx.fillRect(0, 0, w, h);
paperColumn(0, w);
for (let x = 0; x < w; x += 24) {
ctx.fillStyle = x % 120 === 0 ? GRID_MAJOR : GRID;
ctx.fillRect(x, 0, 1, h);
}
}
const rate = () => 0.02 + Math.random() * 0.05;
const GOLD = "rgba(235, 184, 78, 1)";
const GOLD_DIM = "rgba(217, 164, 65, 0.72)";
const rate = () => 0.015 + Math.random() * 0.04;
function column(x) {
const burst = Math.random() < 0.006;
@ -262,12 +206,12 @@
for (let ch = 0; ch < CH; ch++) {
const fire = burst ? Math.random() < 0.55 : Math.random() < rate();
if (!fire) continue;
ctx.strokeStyle = burst ? GOLD : GOLD_DIM;
ctx.lineWidth = burst ? 1.35 : 1;
ctx.strokeStyle = burst ? INK_BURST : INK;
ctx.lineWidth = burst ? 1.4 : 1;
ctx.beginPath();
const y = ch * rowH + rowH / 2;
ctx.moveTo(x, y - rowH * 0.36);
ctx.lineTo(x, y + rowH * 0.36);
ctx.moveTo(x, y - rowH * 0.38);
ctx.lineTo(x, y + rowH * 0.38);
ctx.stroke();
}
}
@ -275,9 +219,18 @@
function step() {
if (!running) return;
const dx = 2;
ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, -dx * dpr, 0, canvas.width, canvas.height);
ctx.fillStyle = "#0b0d10";
ctx.fillRect(w - dx - 1, 0, dx + 2, h);
// 장치 픽셀 단위로 옮긴다. 변환 행렬(dpr)을 그대로 두면 매 프레임 그림이
// dpr 배로 늘어나 고밀도 화면에서 기록지가 눈금색으로 번진다(390@2x 실측).
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.drawImage(canvas, -Math.round(dx * dpr), 0);
ctx.restore();
paperColumn(w - dx - 1, dx + 2);
feed += dx;
if (feed % 24 < dx) {
ctx.fillStyle = feed % 120 < dx ? GRID_MAJOR : GRID;
ctx.fillRect(w - 1, 0, 1, h);
}
column(w - 1);
requestAnimationFrame(step);
}
@ -286,11 +239,14 @@
for (let x = 0; x < w; x += 3) column(x);
}
// 첫 장은 이미 기록된 종이로 시작한다. 빈 눈금만 보이는 구간을 두지 않는다.
fit();
addEventListener("resize", fit, { passive: true });
if (reduced) {
staticFrame();
addEventListener("resize", () => {
fit();
staticFrame();
} else {
}, { passive: true });
if (!reduced) {
const io = new IntersectionObserver((entries) => {
const on = entries[0].isIntersecting;
if (on && !running) {
@ -302,18 +258,6 @@
});
io.observe(canvas);
}
const io2 = new IntersectionObserver(
(entries) => {
for (const e of entries) {
if (!e.isIntersecting) continue;
e.target.classList.add("is-in");
io2.unobserve(e.target);
}
},
{ rootMargin: "0px 0px -8% 0px", threshold: 0.05 },
);
for (const el of document.querySelectorAll(".reveal")) io2.observe(el);
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View file

@ -1,7 +1,9 @@
@import url("./tokens.css?v=20260912all");
@import url("./tokens.css?v=20261002");
/* ==========================================================================
Synapse BCI Lab — dark-instrument. 측정 조건이 붙은 계기.
Synapse BCI Lab — 동의서처럼 읽는 개념서.
구도: 가운데 한 단(40rem)의 문서 흐름. 조 번호는 왼쪽 여백에 걸어 두고,
기록지만 화면 양끝까지 뻗는다. 좌우 분할 히어로를 쓰지 않는다.
========================================================================== */
*,
@ -17,7 +19,7 @@ html {
-webkit-text-size-adjust: 100%;
scroll-behavior: smooth;
background: var(--surface);
color-scheme: dark;
color-scheme: light;
}
@media (prefers-reduced-motion: reduce) {
html {
@ -28,58 +30,37 @@ html {
body {
word-break: keep-all;
overflow-wrap: break-word;
font-synthesis: none;
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: 500;
font-family: var(--font-display);
line-height: var(--leading-tight);
letter-spacing: -0.015em;
overflow-wrap: break-word;
letter-spacing: 0;
text-wrap: balance;
}
h1 {
font-size: var(--step-3);
font-weight: 600;
}
h2 {
font-size: var(--step-2);
}
h3 {
font-size: var(--step-0);
font-weight: 600;
}
:where(p, th, td, figcaption, li) {
overflow-wrap: break-word;
line-height: var(--leading-normal);
h3 {
font-size: var(--step-1);
font-weight: 600;
}
:where(p, th, td, li, figcaption) {
text-wrap: pretty;
}
.lead {
color: var(--ink-muted);
max-width: 36em;
}
.muted {
color: var(--ink-muted);
}
a {
color: inherit;
}
.link-quiet {
color: var(--ink-muted);
text-decoration: none;
border-bottom: 1px solid var(--line-strong);
padding-bottom: 1px;
transition: color var(--dur-quick) var(--ease-soft),
border-color var(--dur-quick) var(--ease-soft);
}
.link-quiet:hover {
color: var(--accent);
border-color: var(--accent);
text-underline-offset: 0.25em;
}
:focus-visible {
@ -96,414 +77,298 @@ a {
z-index: 100;
}
.skip:focus {
left: 0;
left: var(--space-3);
top: var(--space-3);
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0 0 0 0);
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.wrap {
width: min(100% - 2 * var(--pad-inline), var(--container));
margin-inline: auto;
}
.doc {
width: min(100% - 2 * var(--pad-inline), var(--measure));
margin-inline: auto;
}
/* ── 헤더 ─────────────────────────────────────────────────────────────── */
/* ── 머리 ── */
.site-head {
position: sticky;
top: 0;
z-index: 50;
background: color-mix(in srgb, var(--surface) 86%, transparent);
backdrop-filter: blur(8px);
border-bottom: 1px solid var(--line);
border-bottom: 1px solid var(--ink);
}
.head-inner {
display: flex;
align-items: baseline;
align-items: center;
justify-content: space-between;
gap: var(--space-4);
padding-block: var(--space-3);
}
.wordmark {
font-family: var(--font-mono);
font-size: var(--step-1);
font-weight: 500;
text-decoration: none;
letter-spacing: -0.02em;
}
.wordmark-dot {
color: var(--accent);
}
.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);
padding-block: 2px;
border-bottom: 1px solid transparent;
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(--accent);
}
/* ── 히어로 + 래스터 ──────────────────────────────────────────────────── */
.hero {
padding-block: var(--space-8) var(--space-7);
}
.hero-grid {
display: grid;
grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
gap: var(--space-6) var(--space-7);
align-items: center;
}
.hero-kicker {
font-family: var(--font-mono);
font-size: var(--step--1);
color: var(--accent);
letter-spacing: 0.08em;
margin-bottom: var(--space-4);
}
.hero .lead {
margin-top: var(--space-4);
}
.trial-register {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0;
margin-top: var(--space-4);
padding: var(--space-3) 0;
border-block: 1px solid var(--line);
}
.trial-register > div {
min-width: 0;
padding-inline: var(--space-3);
border-left: 1px solid var(--line);
}
.trial-register > div:first-child {
padding-left: 0;
border-left: 0;
}
.trial-register dt,
.trial-register dd {
font-family: var(--font-mono);
font-size: var(--step--1);
letter-spacing: 0.04em;
}
.trial-register dt {
color: var(--accent);
}
.trial-register dd {
margin-top: 0.2rem;
color: var(--ink-muted);
overflow-wrap: anywhere;
}
.hero-actions {
margin-top: var(--space-5);
display: flex;
align-items: center;
gap: var(--space-4);
gap: var(--space-3);
min-height: 4rem;
flex-wrap: wrap;
}
.btn {
.wordmark {
font-family: var(--font-display);
font-weight: 700;
font-size: 1.25rem;
text-decoration: none;
white-space: nowrap;
}
.wordmark span {
font-weight: 400;
color: var(--ink-muted);
margin-left: 0.4em;
font-size: 0.95rem;
}
/* 상단 바에는 워드마크만 둔다. 차례는 표제부(.toc)가 맡는다. */
.scope-note {
border-bottom: 1px solid var(--ink);
font-size: var(--step--1);
color: var(--ink-muted);
text-align: center;
}
.scope-note p {
padding-block: 0.55rem;
}
/* ── 표제부 ── */
.title-block {
padding-block: var(--space-6) var(--space-5);
text-align: center;
}
.doc-id {
display: inline-block;
padding-bottom: var(--space-2);
border-bottom: 2px solid var(--accent);
font-size: var(--step--1);
color: var(--ink-muted);
}
.title-block h1 {
margin-top: var(--space-4);
font-size: var(--step-3);
}
.title-block .lead {
margin: var(--space-4) auto 0;
max-width: 34rem;
color: var(--ink-muted);
}
/* 차례 — 표제부에 녹인 내비. 문서 앞머리의 목차처럼 번호·제목·괘선으로만 짠다. */
.toc {
max-width: 34rem;
margin: var(--space-5) auto 0;
text-align: left;
border-top: 2px solid var(--ink);
}
.toc-title {
padding-block: var(--space-2);
border-bottom: 1px solid var(--ink);
font-family: var(--font-body);
font-size: var(--step--1);
font-weight: 700;
letter-spacing: 0.08em;
color: var(--ink-muted);
}
.toc-list {
list-style: none;
padding: 0;
}
.toc-list a {
display: grid;
grid-template-columns: 4.5rem minmax(0, 1fr);
align-items: baseline;
gap: var(--space-3);
min-height: 44px;
padding-block: 0.55rem;
border-bottom: 1px solid var(--grid);
text-decoration: none;
}
.toc-list li:last-child a {
border-bottom: 0;
}
.toc-no {
font-family: var(--font-display);
font-weight: 600;
color: var(--accent);
}
.toc-list a:hover .toc-name,
.toc-list a:focus-visible .toc-name {
text-decoration: underline;
}
/* ── 기록지 ── */
.recorder {
border-block: 2px solid var(--ink);
}
.recorder canvas {
display: block;
width: 100%;
height: clamp(200px, 22vw, 300px);
}
.recorder figcaption {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: var(--space-2) var(--space-4);
padding-block: var(--space-2);
font-size: var(--step--1);
color: var(--ink-muted);
}
.recorder figcaption b {
color: var(--ink);
font-weight: 700;
}
/* ── 조항 ── */
.section {
padding-block: var(--space-7);
}
.section + .section {
border-top: 1px solid var(--ink);
}
.article-head {
margin-bottom: var(--space-4);
}
.article-no {
display: block;
font-family: var(--font-display);
font-size: var(--step--1);
font-weight: 600;
color: var(--accent);
margin-bottom: var(--space-2);
}
.doc p + p {
margin-top: var(--space-3);
}
.clauses {
list-style: none;
padding: 0;
counter-reset: clause;
}
.clauses li {
position: relative;
padding: var(--space-4) 0 var(--space-4) 3.25rem;
border-top: 1px solid var(--ink);
counter-increment: clause;
}
.clauses li:last-child {
border-bottom: 1px solid var(--ink);
}
.clauses li::before {
content: counter(clause) ".";
position: absolute;
left: 0;
top: var(--space-4);
font-family: var(--font-display);
font-size: var(--step-1);
font-weight: 600;
color: var(--accent);
line-height: 1.3;
}
.clauses h3 {
margin-bottom: var(--space-2);
}
.clauses p {
color: var(--ink-muted);
}
/* ── 도판 ── */
.plate {
margin-block: var(--space-5);
}
.plate img {
display: block;
width: 100%;
height: auto;
aspect-ratio: 4 / 3;
object-fit: cover;
border: 1px solid var(--plate);
background: var(--plate);
}
.plate figcaption {
margin-top: var(--space-2);
font-size: var(--step--1);
color: var(--ink-muted);
}
/* ── 보고 표 ── */
.table-wrap {
overflow-x: auto;
}
.report-table {
width: 100%;
border-collapse: collapse;
background: var(--surface-raised);
}
.report-table th,
.report-table td {
text-align: left;
padding: var(--space-3);
border: 1px solid var(--ink);
vertical-align: top;
font-size: 1rem;
}
.report-table thead th {
font-family: var(--font-display);
font-weight: 600;
}
.report-table .num {
text-align: center;
width: 4.5rem;
}
/* ── 맺음 ── */
.closing {
padding-block: var(--space-7);
border-top: 2px solid var(--ink);
text-align: center;
}
.closing h2 {
font-size: var(--step-2);
}
.back-link {
display: inline-flex;
align-items: center;
min-height: 44px;
border: 1px solid var(--accent);
color: var(--accent);
text-decoration: none;
font-weight: 500;
padding: 0.7rem 1.4rem;
border-radius: var(--radius);
transition: background var(--dur-quick) var(--ease-soft),
color var(--dur-quick) var(--ease-soft);
margin-top: var(--space-5);
font-weight: 700;
}
.btn:hover {
background: var(--accent);
color: var(--surface);
}
.raster-frame {
min-width: 0;
border: 1px solid var(--line);
border-radius: var(--radius-frame);
background: var(--surface-raised);
padding: var(--space-3);
}
.raster-head {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: var(--space-3);
font-family: var(--font-mono);
font-size: var(--step--1);
letter-spacing: 0.08em;
color: var(--ink-faint);
margin-bottom: var(--space-2);
}
.raster-head > span {
min-width: 0;
overflow-wrap: anywhere;
}
#raster {
display: block;
width: 100%;
height: 320px;
}
.raster-legend {
display: flex;
align-items: center;
gap: var(--space-2);
margin-top: var(--space-2);
font-size: var(--step--1);
color: var(--ink-muted);
}
.legend-tick {
display: inline-block;
width: 2px;
height: 12px;
background: var(--accent-dim);
}
/* ── 섹션 공통 ────────────────────────────────────────────────────────── */
.section {
padding-block: var(--space-8);
}
.band {
background: var(--surface-raised);
border-block: 1px solid var(--line);
}
/* ── 디바이스 2단 ─────────────────────────────────────────────────────── */
.two {
display: grid;
grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
gap: var(--space-6) var(--space-7);
align-items: center;
}
.two-photo img {
display: block;
width: 100%;
height: auto;
border-radius: var(--radius);
}
.two-photo figcaption {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ink-faint);
margin-top: var(--space-2);
}
.two-text p + p {
margin-top: var(--space-4);
}
.two-text {
min-width: 0;
padding-left: var(--space-4);
border-left: 1px solid var(--accent-dim);
}
/* ── 수치 표 ──────────────────────────────────────────────────────────── */
.table-wrap {
margin-top: var(--space-4);
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
}
thead th {
text-align: left;
font-weight: 500;
font-size: var(--step--1);
color: var(--ink-faint);
padding: var(--space-2) var(--space-3);
border-bottom: 1px solid var(--line-strong);
}
tbody th {
font-weight: 500;
text-align: left;
white-space: nowrap;
}
tbody td,
tbody th {
padding: var(--space-3);
border-bottom: 1px solid var(--line);
vertical-align: baseline;
}
tbody td:not(.num) {
color: var(--ink-muted);
font-size: var(--step--1);
}
.num {
font-family: var(--font-mono);
font-variant-numeric: tabular-nums;
text-align: right;
white-space: nowrap;
}
.measure-note {
margin-top: var(--space-3);
font-size: var(--step--1);
color: var(--ink-faint);
}
/* ── 어레이 판 ────────────────────────────────────────────────────────── */
.plate-fig img {
display: block;
width: 100%;
height: auto;
}
.plate-fig figcaption {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ink-faint);
margin-top: var(--space-2);
}
/* ── 윤리 ─────────────────────────────────────────────────────────────── */
.ethics-grid h2 {
margin-bottom: var(--space-5);
}
.ethics-list {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
gap: 0;
border-top: 1px solid var(--line);
padding-top: var(--space-5);
}
.ethics-list li {
min-width: 0;
padding-inline: var(--space-4);
border-left: 1px solid var(--line);
}
.ethics-list li:first-child {
padding-left: 0;
border-left: 0;
}
.ethics-list h3 {
color: var(--ink);
}
.ethics-list p {
margin-top: var(--space-2);
color: var(--ink-muted);
font-size: var(--step--1);
}
/* ── 연락 ─────────────────────────────────────────────────────────────── */
.contact-grid {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
gap: var(--space-4) var(--space-7);
align-items: center;
}
.contact-grid p {
color: var(--ink-muted);
max-width: 34em;
}
/* ── 푸터 ─────────────────────────────────────────────────────────────── */
.site-foot {
border-top: 1px solid var(--line);
border-top: 1px solid var(--ink);
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) var(--space-5);
flex-wrap: wrap;
}
.foot-meta {
font-family: var(--font-mono);
font-size: 0.75rem;
color: var(--ink-faint);
justify-content: space-between;
gap: var(--space-3);
}
/* ── 등장 모션 ────────────────────────────────────────────────────────── */
.reveal {
opacity: 0;
translate: 0 12px;
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: 600px) {
.title-block {
padding-top: var(--space-5);
}
.toc-list a {
grid-template-columns: 3.75rem minmax(0, 1fr);
}
.clauses li {
padding-left: 2.25rem;
}
}
/* ── 반응형 ───────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.hero-grid,
.two,
.contact-grid {
grid-template-columns: 1fr;
gap: var(--space-5);
}
.hero,
.section {
padding-block: var(--space-6);
}
}
@media (max-width: 640px) {
.trial-register {
grid-template-columns: 1fr;
gap: var(--space-2);
}
.trial-register > div,
.trial-register > div:first-child,
.ethics-list li,
.ethics-list li:first-child {
padding-left: 0;
border-left: 0;
}
.ethics-list li + li {
margin-top: var(--space-4);
padding-top: var(--space-4);
border-top: 1px solid var(--line);
}
}
@media (max-width: 560px) {
.head-inner {
flex-direction: column;
align-items: flex-start;
gap: var(--space-1);
}
.nav {
width: 100%;
flex-wrap: wrap;
justify-content: flex-start;
column-gap: var(--space-4);
row-gap: var(--space-2);
/* 좁은 화면·글자 확대에서는 부제를 접어 워드마크가 폭을 넘지 않게 한다. */
@media (max-width: 480px) {
.wordmark span {
display: none;
}
}

View file

@ -1,37 +1,42 @@
/* ==========================================================================
Synapse BCI Lab — 디자인 토큰
프리셋: dark-instrument (연구 계기판)
컨셉 한 문장: 측정 조건이 붙은 계기 — 신경 데이터는 장식이 아니라 증거다.
레퍼런스: 방향 앵커 dogfood-synapse(신경인터페이스 업종). 그 파일의 수치는
audit-references.md 날조 판명 — 토큰은 브리프 재정의. 골드 1색은
'전극의 금'에서, 배경은 측정 암실(거의 흑)에서.
하지 않은 것: 'superhuman' 카피, 두뇌 일러스트, 싸이버 글로우, 채널 수
자랑 배너. 이유: 의료 기기의 신뢰는 미측정값의 공백에서도 온다.
Synapse BCI Lab — 디자인 토큰 (2026-10 재작업)
컨셉 한 문장: 연구 동의서처럼 읽히는 신경 인터페이스 개념서 — 권리 조항이
먼저 오고, 신호는 기록지 한 장으로 그 뒤에 붙는다.
재작업 이유: 2026-09판은 lumina-optics·pulsegate와 같은 니어블랙 계기판
템플릿이었다(레드팀 06 P0-1, similarity 0.83). 헤드라인
"explained clearly"가 정직함을 변명했다(06 P0-2).
결정:
- 바탕: 뇌파 기록계(EEG chart recorder) 용지의 옅은 연두. 눈금은 기록계의
붉은 인쇄선, 신호는 검은 잉크. 니어블랙·웜 오프화이트 어느 쪽도 아니다.
- 서체: 표제 함렛(Hahmlet), 본문 고운바탕. 조항을 '읽는' 문서라 본문을
바탕체로 둔다. 모노는 쓰지 않는다.
- 형태: 문서는 모서리를 굴리지 않는다(radius 0). 구분은 괘선으로.
- 모션: 기록지만 종이처럼 흘러간다(화면 밖이면 멈춤, 움직임 줄이기면 정지).
다른 요소는 등장 애니메이션이 없다.
하지 않은 것: 두뇌 일러스트, 사이버 글로우, 'superhuman' 카피, 채널 수 자랑.
========================================================================== */
:root {
/* 타입 — 최대(58px) ÷ 본문(16px) ≈ 3.6배 */
--step--1: 0.8125rem;
--step-0: 1rem;
--step-1: 1.1875rem;
--step-2: clamp(1.375rem, 1.2rem + 0.9vw, 1.75rem);
--step-3: clamp(1.5rem, 0.8rem + 3vw, 3rem); /* 48px — 두 줄 계약 */
/* 타입 — 표제 최대 76px ÷ 본문 18px ≈ 4.2배 */
--step--1: 0.875rem;
--step-0: 1.125rem;
--step-1: 1.3125rem;
--step-2: clamp(1.625rem, 1.3rem + 1.4vw, 2.375rem);
--step-3: clamp(2.25rem, 1.3rem + 4vw, 4.75rem);
--leading-tight: 1.24;
--leading-normal: 1.72;
--leading-tight: 1.22;
--leading-normal: 1.85;
--font-body: "IBM Plex Sans", "IBM Plex Sans KR", Pretendard, -apple-system, sans-serif;
--font-mono: "JetBrains Mono", monospace;
--font-display: "Hahmlet", "Gowun Batang", serif;
--font-body: "Gowun Batang", "Hahmlet", serif;
--surface: #08090b;
--surface-raised: #0d0f13;
--ink: #e9ebee;
--ink-muted: #9aa1ab;
--ink-faint: #838d98;
--line: #1e2229;
--line-strong: #343a45;
--accent: #d9a441; /* 전극 금 — 텍스트·선 */
--accent-dim: rgba(217, 164, 65, 0.4);
--surface: #dbe5cb; /* 기록지 연두 */
--surface-raised: #e8eedd; /* 표·조항 면 */
--ink: #17201a;
--ink-muted: #3d4a3f; /* 바탕 대비 ≈7:1 */
--grid: #d88f7f; /* 기록지 인쇄 눈금 — 선 전용 */
--accent: #a3271c; /* 기록계 붉은 잉크 — 조 번호·강조 괘선 */
--plate: #0b0d0c; /* 도판 테두리 */
--space-1: 0.25rem;
--space-2: 0.5rem;
@ -40,15 +45,11 @@
--space-5: 2.5rem;
--space-6: 4rem;
--space-7: 6rem;
--space-8: clamp(4.5rem, 3rem + 6vw, 8.5rem);
--space-8: clamp(4.5rem, 3rem + 6vw, 8rem);
--radius: 2px;
--radius-frame: 6px;
--radius: 0;
--container: 1240px;
--pad-inline: clamp(1.25rem, 1rem + 2.5vw, 5rem);
--dur-quick: 160ms;
--dur-normal: 420ms;
--ease-soft: cubic-bezier(0.25, 1, 0.35, 1);
--measure: 40rem;
--container: 1200px;
--pad-inline: clamp(1rem, 0.6rem + 2.4vw, 4rem);
}