designpaca/apps/site/public/work/overtone-sound/index.html
Yun Chan 8e3cdb0d3b
Some checks are pending
ci / build (push) Waiting to run
feat(site): rework 19 marketing showcases for composition diversity
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.
2026-10-06 16:55:50 +09:00

254 lines
10 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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="전시장과 소극장의 반사와 잔향 시간을 먼저 재고 스피커 자리를 정하는 가상 공간 음향 연구소. 2023년부터 2026년까지 작업 네 건의 기록."
/>
<meta property="og:title" content="오버톤 사운드랩 — 공간 음향 설계" />
<meta
property="og:description"
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://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Gothic+A1:wght@400;700&display=swap"
/>
<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='%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>
<main id="main">
<section class="hero" aria-labelledby="hero-h">
<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="section-h">2023년부터 2026년까지 작업 네 건을 했습니다</h2>
<p class="section-lead">작업마다 채널 수와 측정 조건을 적었습니다. 최근 작업이 먼저 옵니다.</p>
<ol class="archive">
<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">
<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">
<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">
<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="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="작업한 공간 유형" 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>
</main>
<footer class="site-foot">
<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() {
dpr = Math.min(devicePixelRatio || 1, 1.5);
w = canvas.clientWidth;
h = canvas.clientHeight;
canvas.width = Math.round(w * dpr);
canvas.height = Math.round(h * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
function draw(t) {
ctx.clearRect(0, 0, w, h);
for (let layer = 0; layer < 3; layer++) {
ctx.beginPath();
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;
const env = Math.exp(-Math.pow((p - 0.5) * 2.4, 2));
const y =
yMid +
Math.sin(p * 21 + t * speed + layer * 2.1) * amp * env * Math.sin(p * Math.PI) +
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(0.9) : rgba(0.34 - layer * 0.1);
ctx.lineWidth = layer === 0 ? 1.6 : 1;
ctx.stroke();
}
}
function loop(t) {
if (!running) return;
draw(t);
requestAnimationFrame(loop);
}
fit();
addEventListener("resize", () => { fit(); if (!running) draw(0); }, { passive: true });
draw(0);
if (!reduced) {
const io = new IntersectionObserver((entries) => {
const on = entries[0].isIntersecting;
if (on && !running) {
running = true;
requestAnimationFrame(loop);
} else if (!on) {
running = false;
}
});
io.observe(canvas);
}
</script>
</body>
</html>