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

@ -3,170 +3,197 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>오버톤 사운드랩 · 공간 음향 연구소</title>
<title>오버톤 사운드랩 — 공간 음향 설계</title>
<meta
name="description"
content="공간 음향 작업을 기록하는 방식을 보여 주는 가상 아카이브입니다. 작업·장소·수치는 예시입니다."
content="전시장과 소극장의 반사와 잔향 시간을 먼저 재고 스피커 자리를 정하는 가상 공간 음향 연구소. 2023년부터 2026년까지 작업 네 건의 기록."
/>
<meta property="og:title" content="오버톤 사운드랩" />
<meta property="og:title" content="오버톤 사운드랩 — 공간 음향 설계" />
<meta
property="og:description"
content="공간 음향 작업을 읽는 가상 아카이브 구성."
content="잔향 시간을 먼저 재고 스피커 자리를 정합니다. 작업 네 건의 채널 수와 측정 조건을 적었습니다."
/>
<meta property="og:type" content="website" />
<meta property="og:image" content="./og.png" />
<meta property="og:image:alt" content="어두운 바탕 위에 로즈색 파형 조각, 듀오톤 설치 사진, 수치 조각이 겹친 오버톤 사운드랩 첫 화면" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="theme-color" content="#12100e" />
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css"
href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Gothic+A1:wght@400;700&display=swap"
/>
<link rel="stylesheet" href="./styles/main.css?v=20260912all" />
<link rel="stylesheet" href="./styles/tokens.css" />
<link rel="stylesheet" href="./styles/main.css" />
<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='%230E0D0B'/%3E%3Cpath d='M4 16h4l2-7 3 14 3-10 2 5h10' fill='none' stroke='%23E8A33D' stroke-width='1.8'/%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='%2312100E'/%3E%3Cpath d='M4 16h4l2-7 3 14 3-10 2 5h10' fill='none' stroke='%23EF587E' stroke-width='1.8'/%3E%3C/svg%3E"
/>
</head>
<body>
<a class="skip" href="#main">본문으로 건너뛰기</a>
<header class="site-head">
<div class="wrap head-inner">
<a class="wordmark" href="#main">오버톤 사운드랩</a>
<nav class="nav" aria-label="섹션">
<a href="#works">작업</a>
<a href="#manifesto">선언</a>
<a href="#contact">연락</a>
</nav>
</div>
</header>
<main id="main">
<section class="hero" aria-labelledby="hero-h">
<div class="wrap hero-inner">
<div class="hero-copy">
<p class="hero-kicker reveal">
<span>가상 공간 음향 아카이브</span>
<span class="mono">작업 기록 형식 예시</span>
</p>
<h1 id="hero-h" class="reveal" style="--delay: 80ms">
침묵과 폭발의<br /><em>주파수</em>
</h1>
<p class="hero-statement reveal" style="--delay: 160ms">
오버톤은 소리가 공간에서 어떻게 달라지는지를 기록하는 방식을 보여 줍니다.
곡선과 아래 작업·장소·수치는 화면 구성을 위한 예시이며 실제 작업이나
협업 이력을 뜻하지 않습니다.
</p>
</div>
<div class="wave-surface">
<canvas id="wave" class="wave" aria-hidden="true"></canvas>
<div class="wrap hero-head">
<p class="brand">오버톤 사운드랩</p>
<a class="hero-link" href="#works">작업 네 건 보기</a>
</div>
<div class="wrap collage">
<h1 id="hero-h" class="hero-h">
잔향 시간을 먼저 재고<br />
스피커 자리를 정합니다
</h1>
<div class="piece piece-wave" aria-hidden="true">
<canvas id="wave" class="wave"></canvas>
<p class="piece-tag">잔향 파형 그래픽</p>
</div>
<figure class="piece piece-photo">
<div class="duotone">
<img
src="./assets/installation.webp"
alt="종이 콘 스피커가 줄지어 놓인 어두운 전시실, 그 위를 가로지르는 조명 한 줄"
width="1440"
height="810"
fetchpriority="high"
decoding="async"
/>
</div>
<figcaption class="piece-tag">공명하는 방, 전시장 설치 연출</figcaption>
</figure>
<dl class="piece piece-figures">
<div class="figure">
<dt>작업</dt>
<dd><span class="num">4</span>건, 2023–2026</dd>
</div>
<div class="figure">
<dt>최대 채널</dt>
<dd><span class="num">48</span>ch</dd>
</div>
<div class="figure">
<dt>바닥 소음</dt>
<dd><span class="num">−62</span>dB</dd>
</div>
<div class="figure">
<dt>조율 범위</dt>
<dd><span class="num">220–940</span>Hz</dd>
</div>
</dl>
</div>
</section>
<section id="works" class="section works" aria-labelledby="works-h">
<div class="wrap">
<h2 id="works-h" class="works-h reveal">작업</h2>
<p class="muted reveal" style="--delay: 30ms">
아래 제목, 연도, 공간, 기술 조건은 음향 작업 아카이브의 표현 방식을 설명하는 예시입니다.
</p>
<h2 id="works-h" class="section-h">2023년부터 2026년까지 작업 네 건을 했습니다</h2>
<p class="section-lead">작업마다 채널 수와 측정 조건을 적었습니다. 최근 작업이 먼저 옵니다.</p>
<ol class="archive">
<li class="work reveal">
<p class="work-year mono">2026</p>
<h3>공명하는 방 — 전시장 설치 예시</h3>
<p>
종이 콘 스피커가 공간의 반사를 되돌려주는 설치 구성 예시입니다.
소리의 지연과 관람객 동선을 함께 기록하는 방식을 보여 줍니다.
</p>
<p class="work-meta mono">48ch · 공간지연 · 상설</p>
<li class="work">
<p class="work-year">2026</p>
<div class="work-body">
<h3>공명하는 방 — 전시장 설치</h3>
<p>
전시실에 종이 콘 스피커 48개를 설치했습니다. 관람객이 걷는 속도에 맞춰 채널마다 지연
시간을 다르게 설정했습니다.
</p>
</div>
<ul class="work-meta">
<li>48채널</li>
<li>공간 지연</li>
<li>상설 설치</li>
</ul>
</li>
<li class="work work-b reveal" style="--delay: 60ms">
<p class="work-year mono">2025</p>
<h3>무의 스펙트럼 — 공연 구성 예시</h3>
<p>
조용한 공간의 바닥 소음을 다루는 공연 구성 예시입니다. 표기된 수치는
실제 측정값이나 공연 기록이 아닙니다.
</p>
<p class="work-meta mono">live · −62dB floor</p>
<li class="work">
<p class="work-year">2025</p>
<div class="work-body">
<h3>빈 객석 — 공연</h3>
<p>
빈 객석의 바닥 소음을 소리 재료로 쓴 공연입니다. 공조기를 끈 뒤 남은 −62dB 소음을
증폭해 첫 악장에 썼습니다.
</p>
</div>
<ul class="work-meta">
<li>공연</li>
<li>바닥 소음 −62dB</li>
</ul>
</li>
<li class="work reveal" style="--delay: 40ms">
<p class="work-year mono">2024</p>
<h3>파도의 인버전 — 해안 설치 예시</h3>
<p>
바람과 파도라는 소재를 반대 위상으로 해석하는 해안 설치 구성 예시입니다.
</p>
<p class="work-meta mono">field data · 6h loop</p>
<li class="work">
<p class="work-year">2024</p>
<div class="work-body">
<h3>역위상 파도 — 해안 설치</h3>
<p>
6시간 녹음한 파도 소리를 역위상으로 재생해, 해안 데크 위에서만 파도 소리가 줄어들게
했습니다.
</p>
</div>
<ul class="work-meta">
<li>현장 녹음</li>
<li>6시간 반복</li>
</ul>
</li>
<li class="work work-b reveal" style="--delay: 100ms">
<p class="work-year mono">2023</p>
<h3>유리 진동자 — 연주 설비 예시</h3>
<p>
유리잔의 높이와 공진을 조율하는 연주 설비 구성 예시입니다.
</p>
<p class="work-meta mono">glass · 220–940Hz</p>
<li class="work">
<p class="work-year">2023</p>
<div class="work-body">
<h3>유리잔 12개 — 연주 설비</h3>
<p>물 높이를 달리한 유리잔 12개를 220Hz부터 940Hz까지 조율한 연주 설비입니다.</p>
</div>
<ul class="work-meta">
<li>유리잔 12개</li>
<li>220–940Hz</li>
</ul>
</li>
</ol>
</div>
</section>
<section id="manifesto" class="section manifesto" aria-labelledby="manifesto-h">
<div class="wrap">
<h2 id="manifesto-h" class="sr-only">선언</h2>
<p class="manifesto-line reveal">
좋은 음향은 들리지 않는다.<br />
방이 좋아지는 것뿐이다.
</p>
<p class="manifesto-note reveal" style="--delay: 100ms">
이 구성은 음파의 크기보다 공간의 반사와 잔향을 먼저 읽게 합니다.
시각화가 소리의 모든 경험을 대신할 수 없다는 점을, 작업 기록의 순서로
보여 줍니다.
<section id="method" class="section method" aria-labelledby="method-h">
<div class="wrap method-grid">
<h2 id="method-h" class="method-h">음량보다 잔향&nbsp;시간을 먼저&nbsp;잽니다.</h2>
<p class="method-note">
잔향이 길면 같은 음량에서도 말소리가 뭉개집니다. 그래서 모든 설계는 공간의 잔향 시간(RT60)
측정에서 시작하고, 그다음에 스피커 배치와 흡음재를 정합니다. 첫 화면의 파형은 분위기를
보여 주는 그래픽이며 측정값이 아닙니다.
</p>
</div>
</section>
<div class="marquee" role="group" aria-label="협업 장소 유형 예시">
<div class="marquee-track">
<span>공공 전시장</span><span>도심 복합문화공간</span><span>콘서트홀</span><span>소극장</span><span>해안 야외 공연장</span><span>공공 전시장</span><span>도심 복합문화공간</span><span>콘서트홀</span><span>소극장</span><span>해안 야외 공연장</span>
</div>
<div class="marquee" role="group" aria-label="작업한 공간 유형" tabindex="0">
<ul class="marquee-track">
<li>공공 전시장</li>
<li>도심 복합문화공간</li>
<li>콘서트홀</li>
<li>소극장</li>
<li>해안 야외 공연장</li>
<li aria-hidden="true">공공 전시장</li>
<li aria-hidden="true">도심 복합문화공간</li>
<li aria-hidden="true">콘서트홀</li>
<li aria-hidden="true">소극장</li>
<li aria-hidden="true">해안 야외 공연장</li>
</ul>
</div>
<section class="section photo" aria-label="설치 현장">
<figure class="wrap photo-fig reveal">
<img
src="./assets/installation.webp"
alt="어두운 전시실에 종이콘 스피커들이 늘어서 있고 앰버색 빛줄기가 한 줄 지나간다"
width="1440"
height="810"
loading="lazy"
/>
<figcaption class="mono">공명하는 방 · 설치 연출 이미지</figcaption>
</figure>
</section>
<section id="contact" class="section contact" aria-labelledby="contact-h">
<div class="wrap contact-grid">
<h2 id="contact-h">구성 안내</h2>
<p>
이 페이지는 공간 음향 작업을 설명하는 구성 예시입니다. 실제 설치·공연·연구
협업이나 연락을 접수하지 않습니다.
</p>
<a class="contact-mail" href="#main">작업 구성 다시 보기</a>
</div>
</section>
</main>
<footer class="site-foot">
<div class="wrap foot-inner">
<p>오버톤 사운드랩 · 가상 공간 음향 아카이브</p>
<p class="mono foot-meta">실제 협업 단체·장소·연락처를 제공하지 않습니다.</p>
<div class="wrap foot-row">
<p class="foot-note">가상 브랜드 쇼케이스입니다. 작업, 장소, 수치는 모두 예시이고 의뢰를 받지 않습니다.</p>
<a class="foot-top" href="#main">맨 위로</a>
</div>
<p class="foot-mark" aria-hidden="true">오버톤 사운드랩</p>
</footer>
<script>
// 파형 캔버스 — 화면에 보일 때만 그리고, 화면 밖과 감소 모션에서는 정지 프레임 하나만 남긴다.
const canvas = document.getElementById("wave");
const reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
const ctx = canvas.getContext("2d");
const accent = getComputedStyle(document.documentElement).getPropertyValue("--accent-rgb").trim() || "239 88 126";
const rgba = (a) => `rgb(${accent} / ${a})`;
let w, h, dpr, running = false;
function fit() {
@ -182,8 +209,8 @@
ctx.clearRect(0, 0, w, h);
for (let layer = 0; layer < 3; layer++) {
ctx.beginPath();
const amp = (h * 0.16) * (1 - layer * 0.28);
const yMid = h * (0.52 + layer * 0.12);
const amp = h * 0.2 * (1 - layer * 0.28);
const yMid = h * (0.48 + layer * 0.1);
const speed = 0.00042 * (1 + layer * 0.7);
for (let x = 0; x <= w; x += 3) {
const p = x / w;
@ -194,8 +221,8 @@
Math.sin(p * 53 - t * speed * 1.7) * amp * 0.25 * env;
x === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
}
ctx.strokeStyle = layer === 0 ? "rgba(232,163,61,0.85)" : `rgba(232,163,61,${0.32 - layer * 0.1})`;
ctx.lineWidth = layer === 0 ? 1.4 : 1;
ctx.strokeStyle = layer === 0 ? rgba(0.9) : rgba(0.34 - layer * 0.1);
ctx.lineWidth = layer === 0 ? 1.6 : 1;
ctx.stroke();
}
}
@ -207,7 +234,7 @@
}
fit();
addEventListener("resize", fit, { passive: true });
addEventListener("resize", () => { fit(); if (!running) draw(0); }, { passive: true });
draw(0);
if (!reduced) {
@ -222,18 +249,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>