/* Suisse Intl — 사용자 보유 웹 라이선스 파일. 패키지에 woff2가 없어 woff로 간다.
   세 컷만 쓴다: 본문(400), 볼드 위계(600), 코드명 디스플레이(200).
   원본 패키지(otf/ttf 포함)는 .gitignore·.vercelignore로 막아뒀다 — 배포되면 안 된다. */
@font-face {
  font-family: "Suisse Intl";
  src: url("/font/SuisseIntl-Ultralight-WebS.woff") format("woff");
  font-weight: 200; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Suisse Intl";
  src: url("/font/SuisseIntl-Light-WebS.woff") format("woff");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Suisse Intl";
  src: url("/font/SuisseIntl-Regular-WebS.woff") format("woff");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Suisse Intl";
  src: url("/font/SuisseIntl-SemiBold-WebS.woff") format("woff");
  font-weight: 600; font-style: normal; font-display: swap;
}

/* ved.kr — 모든 수치는 --base(본문)와 뷰포트 비율 둘에서만 나온다.
   임의의 px을 흩뿌리지 말 것: 새 값이 필요하면 여기 :root에 관계로 정의한다. */

:root {
  /* 텍스트 — rem 기반이라 사용자 확대를 존중한다 */
  --base: 17px;
  --rhythm: 1.5rem;
  --gap-1: var(--rhythm);
  --gap-2: calc(var(--rhythm) * 3);
  --half: calc(var(--rhythm) / 2);
  --measure: 34em;              /* 본문 한 줄 길이 */
  /* 주석 층 — 도면 캡션·조작 힌트처럼 그림에 딸린 글.
     인쇄 시트도 도면 콜아웃을 본문보다 작게 앉힌다. 임의값이 아니라 5:6 비율. */
  --caption: calc(1rem * 5 / 6);
  --thumb-min: calc(var(--rhythm) * 8);

  /* 지면 — 뷰포트 비율이라 창이 변해도 구도가 유지된다 */
  --edge: 4vw;
  --mark-w: min(84vw, 74svh);   /* 락업 950:581 → 높이는 화면의 45%로 묶인다 */
  --poster-logo: clamp(15rem, 68vw, 24rem);
  --display: min(22vw, 16svh);  /* 작업 코드명 (TR-2 …) */

  /* 색 — 인쇄물 기준. 청회색 종이에 냉색 잉크, 형광 노랑은 별색 시트.
     회색·괘선은 그 둘을 섞어 파생하므로 배경을 바꾸면 함께 따라온다. */
  --fg: #20242a;      /* 냉색 잉크 검정 */
  --bg: #e9eced;      /* 청회색 종이 */
  --poster-green: #094; /* 홈 선화 SVG의 실제 stroke */
  --poster-green-muted: color-mix(in srgb, var(--poster-green) 76%, var(--bg));
  /* 위계에 회색을 쓰지 않는다. 2차 정보는 색이 아니라 섞어짜기 —
     락업의 'engineering' 행이 이미 하는 그 방식(세리프 이탤릭)으로 갈린다.
     회색은 상태(비활성) 표현에만 남기고, 그것도 opacity로 처리한다. */
  --line: var(--fg);                        /* 인쇄물처럼 잉크 헤어라인 */
  /* 섞어짜기는 기본으로 쓰지 않는다 — 이탤릭을 지면 전체에 깔면 남발이 된다.
     락업처럼 정말 필요한 극소수 지점을 위해 토큰만 남겨둔다.
     쓸 때는 --serif-optical을 곱할 것: Times 이탤릭 x-height가 같은 px에서
     그로테스크의 0.843배라 그냥 쓰면 혼자 작게 앉는다(실측). */
  --serif: "Times New Roman", Times, serif;
  --serif-optical: 1.186;

  /* 띠지 — 실물 포장을 두르는 색 띠. 웹에서는 제품 타이틀 영역이 그 띠가 된다.
     ★ 글자색으로 쓰지 않는다. 회색지 위 노랑 글자는 대비 1.14:1로 읽히지 않는다(실측).
     인쇄물이 하는 대로 "색 면 위에 검정 잉크"로만 쓴다 — 노랑 12.14:1, 하늘 9.12:1.
     --accent는 이 노랑과 같은 값이다. 노랑이 둘이면(ΔE 24.6) 어긋난 것으로 보인다. */
  --band: #e7ea66;
  --sel-bg: var(--band);   /* 선택 배경 — 색 면 위에서는 뒤집는다 */
  --sel-fg: var(--fg);
  --accent: var(--band);

  --sans: "Suisse Intl", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
}

@media (min-width: 768px) {
  :root {
    --edge: 2vw;
    --mark-w: min(52vw, 74svh);
    --poster-logo: clamp(24rem, 34vw, 42rem);
    --display: min(13vw, 20svh);
  }
}

* { box-sizing: border-box; margin: 0; }
/* 캔버스 = 문서 바깥. 브라우저에서 아래로 "띠용" 튕길 때 드러나는 면이 여기다.
   지면색으로 두면 흰 면이 보이므로 띠 색으로 칠한다. 문서 끝에 남던 28px도
   같이 덮인다. ★ --band를 읽으려면 밴드 클래스가 body가 아니라 html에 있어야
   한다 — 그래서 tr-2 계열의 band-sky는 <html>에 붙였다.
   위로 튕길 때도 같은 색이 보인다. 캔버스 색은 하나뿐이라 양끝을 다르게는 못 한다. */
html {
  font-size: var(--base);
  background: var(--band);
}

/* h1 기본 굵기(bold)를 끈다. 이 사이트의 h1은 화면에서 감춘 제목이거나 .code인데,
   둘 다 자기 굵기를 따로 정한다. 그대로 두면 브라우저가 '보이지도 않는 제목'을 그리려고
   SemiBold 컷을 매번 받아온다 — 실측 21.2KB. */
h1 { font-weight: inherit; }

body {
  /* 지면이 화면 왼쪽에 붙지 않도록 중앙에 놓인 한 장의 시트로 만든다.
     행 문법은 그대로 — 폭만 묶인다. */
  /* ★ max-width로 묶지 않는다. 묶으면 좌우에 body 배경이 없어 캔버스의 띠 색이
     세로 띠로 새어 보인다. 중앙 열은 패딩으로 만들고 배경은 화면을 다 덮는다.
     열 너비는 전과 같다: 100% - 2*((100%-68em)/2 + edge) = 68em - 2*edge. */
  padding-inline: max(var(--edge), calc((100% - 68em) / 2 + var(--edge)));
  /* 아래는 0이다. 발치의 띠가 화면 끝까지 닿아야 하는데, 패딩을 주고 푸터의
     음수 마진으로 상쇄하면 문서의 스크롤 영역이 13.2px 늘어난다(실측) —
     띠 아래에 그만큼 여백이 더 있는 것처럼 보인다. 안 주는 게 맞다. */
  padding-block: var(--edge) 0;
  /* 띠지(.sheet)가 50vw로 화면 끝까지 나가는데, 50vw는 세로 스크롤바 폭을
     포함한다. 그 차이만큼 삐져나온 것을 가로 스크롤로 만들지 않는다.
     clip은 hidden과 달리 스크롤 컨테이너를 만들지 않아 sticky를 깨지 않는다. */
  overflow-x: clip;
  font: 1rem/1.5 var(--sans);
  letter-spacing: -0.01em;
  color: var(--fg);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 0.2em;
          /* 큰 글자에서 기본 밑줄이 슬래브가 된다 — 헤어라인 비율로 고정 */
          text-decoration-thickness: max(1px, 0.045em); }

/* ── 선택 ─────────────────────────────────────────────────────────
   글을 끌어 선택하면 그 페이지의 띠 색이 깔린다 — 홈 초록, PD·BS 노랑,
   TR 파랑. 브라우저 기본 파랑은 어느 페이지와도 무관한 색이다.

   ★ 띠 위에서는 반전한다. 안 그러면 띠 색 면에 띠 색 배경이라 선택한 자리가
     보이지 않는다. 색 면을 가진 요소가 --sel-* 두 개만 뒤집으면 되게 해뒀다.
   대비는 어느 조합이든 잉크 기준 통과다 — 초록 5.47:1, 파랑 8.62:1, 노랑 12.14:1. */
::selection { background: var(--sel-bg); color: var(--sel-fg); }
.sheet, .fw-notice { --sel-bg: var(--fg); --sel-fg: var(--band); }
/* 코드명은 워드마크다. 200px 가까운 글자에 밑줄이 그이면 선 하나가 지면을
   가로지른다. 링크로만 두고 hover 표시는 없앤다.
   블록으로 둬서 워드마크 전체가 클릭 영역이 되게 한다. */
.code a { display: block; }
.code a:hover { text-decoration: none; }

/* ── 대문자 사이의 대시 ────────────────────────────────────────────
   인쇄물의 코드명 대시는 기본 엔대시가 아니라 대문자 조판용 상승형이다.
   데스크톱 OTF에는 `endash.case` 글리프가 있고 폭은 기본과 같은 401,
   높이만 다르다 — 중심이 캡 상단에서 49.4%(기본 엔대시는 62.6%).
   인쇄 실측 49.7%와 맞는다.

   ★ 웹 라이선스 컷(WebS)에는 GSUB 테이블이 통째로 없어 `font-feature-settings:
     "case"`로는 못 부른다. 그래서 같은 글자를 그 차이만큼 올린다:
     (62.6 − 49.4)% × 캡하이트 0.725em = 0.0957em.
   relative로 올려서 자리·폭·줄바꿈은 그대로 두고 그림만 옮긴다. */
.endash { position: relative; top: -0.0957em; }

/* ── 손끝 ─────────────────────────────────────────────────────────
   글자 높이만 한 링크는 22~26px이라 손가락으로 짚기 얕다(WCAG 2.5.8은 24px).
   ★ 인라인 링크의 세로 패딩은 줄상자를 늘리지 않는다 — 맞닿는 면만 넓어지고
     레이아웃은 그대로다. 그래서 문장 속 링크가 아니라 '혼자 서 있는' 링크,
     즉 문단의 유일한 자식인 링크와 이동 링크에만 건다. 문장 속 링크에 걸면
     여러 줄에서 히트 영역이 서로 겹쳐 엉뚱한 줄이 눌린다. */
.row .body p > a:only-child,
.pager a { padding-block: 0.6em; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ── 접근성 층 — 시각 결과는 동일 (감사 2026-08-22) ─────────────────
   라벨을 h2로 올려 제목 항해를 살리되, 크기·웨이트는 본문과 같게 묶는다.
   포커스 링은 currentColor — 지면·노랑·파랑·초록 어느 면에서든 잉크색. */
h2.label, h3.tgroup, h3.dhead { font-size: 1rem; font-weight: inherit; margin: 0; }
h2.label { font-weight: 400; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.skip { position: fixed; left: var(--edge); top: 0; z-index: 20;
        transform: translateY(-150%); transition: none;
        background: var(--fg); color: var(--bg); padding: var(--half) var(--gap-1); }
.skip:focus { transform: none; }

/* ── 행 ────────────────────────────────────────────────────────────
   전 페이지가 이 한 가지 행으로 조판된다. 좁은 라벨 열 + 내용 열,
   구분은 가로선. 세로 괘선은 쓰지 않는다. */
.row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--half);
  padding: var(--gap-1) 0;
  border-top: 1px solid var(--line);
}
.row > .body > * + * { margin-top: var(--gap-1); }
.row p { max-width: var(--measure); }

@media (min-width: 768px) {
  .row { grid-template-columns: 12em 1fr; gap: var(--gap-2); }
  /* 라벨 없는 행: 본문이 라벨 칸(12em)으로 밀리지 않게 제 칸에 앉힌다.
     칸 이름일 뿐인 라벨(images·about)을 지우면서 필요해졌다. */
  .row > .body:first-child { grid-column: 2; }
}

/* ── 작업 목록 ────────────────────────────────────────────────── */
.works { display: grid; }
.works .work-entry {
  display: grid;
  grid-template-columns: 4.5em 1fr auto;
  gap: var(--gap-1);
  padding: calc(var(--half) / 2) 0;
  text-decoration: none;
}
.works .work-entry + .work-entry {
  margin-top: 0;
  border-top: 1px solid var(--line);
}
.works .work-entry:first-child { padding-top: 0; }
.works a.work-entry:hover { opacity: 0.55; }        /* hover는 속삭임 */
.works .work-unlinked { cursor: default; }

/* 작품 표 아래를 화면 전체 너비로 가로지르는 작은 이미지 띠. */
.works-section { row-gap: 0; }
.works-carousel {
  grid-column: 1 / -1;
  width: 100vw;
  margin-top: var(--gap-1);
  margin-left: calc(50% - 50vw);
  padding-inline: var(--edge);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(var(--thumb-min), 1fr);
  gap: var(--half);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--edge);
  scrollbar-width: none;
}
.works-carousel::-webkit-scrollbar { display: none; }
.works-carousel a {
  display: block;
  scroll-snap-align: start;
}
.works-carousel img {
  display: block;
  width: 100%;
  height: auto;
  height: auto;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  background: color-mix(in srgb, var(--fg) 6%, var(--bg));
}

/* ── 작업 페이지 ──────────────────────────────────────────────── */
/* 로고는 어느 페이지에서든 같은 자리에 있어야 한다. flex + space-between이면
   곁의 링크 유무에 따라 로고가 좌우로 튀었다 — 도구 페이지에만 '제품으로' 링크가
   하나 더 있어서, 제품 페이지에서 넘어오면 로고가 가운데에서 왼쪽으로 옮겨갔다.
   가운데 칸을 따로 두면 곁의 링크가 로고를 밀지 못한다. */
.topbar {
  display: grid;
  justify-items: center;
  gap: var(--half);
  padding-bottom: var(--edge);
}
.topbar .wordmark { width: 7em; }
.topbar .wordmark span {
  display: block;
  aspect-ratio: 950.35 / 580.9;      /* 락업 원본 비율 */
  background: currentColor;
  -webkit-mask: url(/logo.svg) center / contain no-repeat;
  mask: url(/logo.svg) center / contain no-repeat;
}

.code {
  font-size: var(--display);   /* 시트 안에서는 sheet-fit.js가 실측해 덮어쓴다 */
  /* 인쇄물이 Light를 썼다(사용자 확인). 실측이 그걸 뒷받침한다 — 인쇄 코드명의
     획/캡하이트 = 0.0890이고, 획 굵기로 역산한 웨이트가 ≈310이었다.
     Ultralight 0.0267은 70% 얇고 Regular 0.136은 53% 두껍다. */
  font-weight: 300;
  line-height: 0.9;
  letter-spacing: -0.03em;
  padding-bottom: var(--half);
  /* ★ line-height 0.9는 글꼴의 콘텐츠 영역(약 1.22em)보다 작다. 그래서 글자
     상자가 아래로 13.8px 흘러나가고(실측), 그게 문서의 스크롤 영역을 늘려
     띠 밑에 그만큼 여백이 더 있는 것처럼 보인다. 잘라낸다 — 상자는 캡 윗선
     위 0.095em에서 베이스라인 아래 0.08em까지라 획은 하나도 안 걸린다. */
  overflow: clip;
}

/* 코드명 아래 한 줄 — 이름과 분류. 크기는 본문과 같고, 분류만 회색으로 물러난다 */

/* 행별 헤어라인 처리는 2026-08-22 커밋 30d81e8에 주인 미상으로 동승해
   배포된 편집이다(코덱스 세션 추정). 라이브에서 .row·.works 문법과 결이
   맞아 유지하기로 했다 — 주인이 나타나면 이 주석을 제 이름으로 바꿀 것. */
.specs { display: grid; gap: 0; }
.specs > div {
  display: grid;
  grid-template-columns: 7em 1fr;
  gap: var(--gap-1);
  padding: calc(var(--half) / 2) 0;
}
.specs > div + div {
  margin-top: 0;
  border-top: 1px solid var(--line);
}
.row > .body.specs > div + div { margin-top: 0; }
.specs > div:first-child { padding-top: 0; }
.specs dd { margin: 0; }

.tbd { opacity: 0.45; }   /* 빈 값은 색이 아니라 상태 — 유일한 예외 */

.pager {
  display: flex; justify-content: space-between; gap: var(--gap-1);
  padding-top: var(--gap-1);
  border-top: 1px solid var(--line);
}

/* ── 바닥 ─────────────────────────────────────────────────────── */
.meta {
  display: flex; justify-content: space-between; gap: var(--gap-1);
  padding-top: var(--gap-1);
  margin-top: var(--gap-2);
  border-top: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}

/* ── 동적 포스터 홈 ────────────────────────────────────────────────
   원본 포스터를 한 장으로 cover하지 않는다. 선화, 락업, 분류문을 각각의
   반응형 레이어로 조립해 화면 비율이 달라도 중심축과 정보 위계를 지킨다. */
.plate {
  position: relative;
  isolation: isolate;
  /* body가 폭이 묶여도 판은 화면 전체를 덮어야 한다 */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  margin-top: calc(var(--edge) * -1);
  margin-bottom: var(--gap-2);
  padding: var(--edge);
  min-height: 100svh;
  display: grid;
  align-content: center;
  overflow: hidden;
}
.poster-stage { position: absolute; inset: 0; background: #fff; }
.poster-network {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  object-fit: cover;
  object-position: 50% 50%;
}

.poster-logo {
  position: absolute;
  left: 50%; top: 50%;
  width: var(--poster-logo); height: auto;
  display: block;
  transform: translate(-50%, -50%);
  z-index: 2;
  mix-blend-mode: multiply;
  opacity: 0.84;
}

/* 원본 포스터의 분류표. 세 열의 시작점과 세 행의 높이만 고정하고,
   각 묶음은 같은 크기와 같은 굵기로 놓는다. */
.poster-taxonomy {
  position: absolute;
  top: var(--edge);
  left: var(--edge);
  right: var(--edge);
  z-index: 3;
  display: grid;
  grid-template-columns: 14vw 66vw 1fr;
  grid-template-rows: repeat(3, auto);
  align-content: start;
  row-gap: 1em;
  /* 하단 메뉴와 같은 폰트·크기·웨이트. 반응형은 열 간격만 바꾼다. */
  font: inherit;
  line-height: 1.05;
  letter-spacing: inherit;
}
.poster-taxonomy > :nth-child(1) { grid-area: 1 / 1; }
.poster-taxonomy > :nth-child(2) { grid-area: 1 / 2; }
.poster-taxonomy > :nth-child(3) { grid-area: 1 / 3; }
.poster-taxonomy > :nth-child(4) { grid-area: 2 / 1; }
.poster-taxonomy > :nth-child(5) { grid-area: 2 / 2; }
.poster-taxonomy > :nth-child(6) { grid-area: 2 / 3; }
.poster-taxonomy > :nth-child(7) { grid-area: 3 / 1; }

@media (max-width: 767px) {
  .poster-taxonomy {
    grid-template-columns: 20vw 54vw 1fr;
  }
}

@media (max-width: 420px) {
  .poster-taxonomy {
    grid-template-columns: 23vw 47vw 1fr;
  }
}

/* 메뉴도 포스터의 검은 인쇄층에 들어온 것처럼 겹친다. */
.plate-nav {
  position: absolute;
  left: var(--edge); right: var(--edge); bottom: var(--edge);
  z-index: 3;
  display: flex; flex-wrap: wrap; gap: var(--gap-1);
  mix-blend-mode: multiply;
}
.plate-nav a:last-child { margin-left: auto; }
.plate-nav { color: #20242a; }

/* 설치 절차용 — 새 수치를 만들지 않고 기존 리듬만 쓴다 */
.body ol { padding-left: var(--gap-1); max-width: var(--measure); }
.body li + li { margin-top: var(--half); }
.body code { font-family: ui-monospace, Menlo, monospace; }

/* ── 띠지 ─────────────────────────────────────────────────────────
   실물 포장을 한 바퀴 두르는 색 띠. 웹에서는 지면의 머리(.sheet)와
   발(footer)을 같은 색으로 묶어 그 한 바퀴를 대신한다.
   머리는 인쇄 시트의 구성 그대로 — 왼쪽 대형 코드명 + 오른쪽 사양 블록.

   폭은 음수 마진만으로 화면 끝까지 늘린다 — `width: 100vw`를 함께 주면
   세로 스크롤바가 자리를 차지하는 환경에서 그 폭만큼 가로로 넘친다.
   패딩은 그 마진을 정확히 되돌린 값이라 띠 안의 글이 본문 열과 같은 선에 선다
   (`68em`을 다시 적으면 --edge를 빠뜨려 26px 어긋난다 — 실제로 어긋났다).
   50vw는 스크롤바를 폭에 포함하므로 body에 overflow-x: clip이 짝으로 필요하다. */
.sheet {
  display: grid;
  gap: var(--gap-1);
  background: var(--band);
  margin-inline: calc(50% - 50vw);
  /* 위아래 같은 값. 아래만 --gap-2였는데 그게 --gap-1의 3배라 띠 밑이 휑했다.
     글자 기준으로도 균형이 맞는다 — 띠 위끝에서 첫 줄 캡까지가 0.375em,
     마지막 베이스라인에서 띠 아래끝까지가 0.40em으로 차이가 0.4px 남짓이다. */
  padding: var(--gap-1) calc(50vw - 50%);
}

/* 도구 페이지의 시트는 <div>라 `header.sheet`로는 안 잡혔고, 그래서 아래 여백이
   0이었다. 다음 행의 위 괘선이 띠의 아래 모서리에 그대로 얹혀 선이 겹쳐 보였다. */
.sheet:not(footer) { margin-bottom: var(--gap-1); }

/* 띠 바로 다음 행은 괘선을 빼운다. 띠의 아래 모서리가 이미 구분선이라
   그 밑에 한 줄 더 그으면 같은 일을 두 번 하는 것이다(푸터와 같은 규칙). */
.sheet + .row { border-top: 0; }

/* 발치의 띠 = 판권. 머리띠와 같은 조판을 쓴다 — 실물 포장을 한 바퀴 두른
   띠의 뒷면에 해당한다. 색이 곧 구분선이라 괘선은 없고, body 아래 여백만큼
   끌어내려 화면 바닥에 닿는다(띠 밑에 지면색이 한 줄 남으면 잘려 보인다). */
footer.sheet {
  margin-top: var(--gap-2);

  /* 지면 열(68em)에 모으지 않고 화면 폭으로 펼친다. 머리띠는 본문과 열을
     맞춰야 하지만 발치는 그럴 상대가 없다. 펼치면 코드명과 사양 사이가
     벌어지고, 오른쪽 두 열도 넓어져 "Seoul, Republic of Korea"와 판권 줄이
     두 줄로 접히지 않는다. */
  padding-inline: var(--edge);

  /* 스크롤은 글자에서 끝난다. ★ 패딩으로 색을 아래로 빼면 안 된다 —
     음수 마진은 레이아웃만 되돌리고 스크롤 오버플로는 마진을 무시해서
     문서가 통째로 100vh 늘어난다(실측: 4931 → 13944). 문서 밖에 드러나는
     면은 캔버스(html 배경)로 칠한다. 아래 html 규칙 참고. */
  padding-bottom: var(--gap-1);
}

/* 인쇄물 행간(300dpi 실측: 줄 간격 50px, 어센더 38px → 1.29). 본문 1.5로는
   네 덩이가 흩어져 보인다. 좁혀야 각 덩이가 하나로 읽힌다. */
footer.sheet .sheet-meta { line-height: 1.3; }

/* 열 폭은 글의 실측에서 나온다. 본문 17px에서 "Seoul, Republic of Korea"가
   188px(11.1em), 판권 줄이 316px(18.6em)이고 두 열 사이가 1.5em이니
   사양 블록은 최소 31.2em을 요구한다. 34em을 준다 — 어느 폭에서도 안 접힌다.
   ★ 왼쪽 열을 auto로 두면 안 된다. 두 행이 서로 다른 격자라 max-content가
     달라지고(93px vs 188px) 위아래 열이 어긋난다. 그래서 고정 12em이다. */
/* 왼쪽 열은 두 열이 되는 폭(768)부터 넓혀야 한다. 기본 11em(187px)으로는
   "Seoul, Republic of Korea"(188px)가 1px 모자라 접힌다. */
@media (min-width: 768px) {
  footer.sheet .sheet-meta > div { grid-template-columns: 12em 1fr; }
}

/* 바깥 두 열은 시트가 두 열이 되는 폭에서만. 밖에 두면 375에서도 2열이 강제돼
   34em(578px)이 화면을 넘어 가로로 354px 삐져나온다(실측). */
@media (min-width: 1120px) {
  footer.sheet { grid-template-columns: 1fr minmax(0, 34em); }
}

.band-home { --band: var(--poster-green-muted); }

/* 제품마다 띠 색이 다르다. TR-2는 제품 사진의 블리스터 헤더에서 #a5cdd4를
   뽑았었는데, 광택 카드를 흰 조명에서 찍으면 채도가 죽는다(인쇄 원본에는
   파랑 잉크가 없다 — 파일명의 blue는 실물 카드 재질을 가리킨다). 사용자 판단으로
   채도를 올리고 색상을 청록에서 파랑 쪽으로 옮겼다: L*78 C*28 H235.
   노랑 띠는 C*64.9지만 파랑은 이 밝기에서 색역상 C*30 근처가 한계다 — 같은
   채도로는 못 맞추니 '밝기를 맞춘다'로 갔다. 검정 잉크 8.62:1, 지면과 ΔE 31. */
.band-sky { --band: #7dcbeb; }
@media (min-width: 768px) {
}
.sheet .code { padding-bottom: 0; }

.sheet-meta { display: grid; gap: var(--gap-1); align-content: start; }
/* 라벨 | 값의 두 열은 폭과 무관하게 유지한다. 한 열로 무너지면 인쇄 시트의
   구조가 사라지고 그냥 목록이 된다. 좁은 화면에서는 라벨 열을 9em으로 줄여
   값 쪽에 폭을 남긴다 — 가장 긴 라벨 "Portable Display 3"이 138px이라 들어간다.
   값은 접히지만 그건 정상이고, 열이 무너지는 것과는 다르다. */
/* 좁은 화면은 1:3 — 9em 라벨 열이 지면의 44%를 먹어 반반처럼 보였다
   (사용자 지적). 긴 라벨("Portable Display 3")은 접힌다 — 그게 의도다. */
.sheet-meta > div { display: grid; grid-template-columns: minmax(0, 1fr) 3fr; gap: var(--half); }
@media (min-width: 768px) {
  .sheet-meta > div { grid-template-columns: 11em 1fr; gap: var(--gap-1); }
}

/* 시트를 두 열로 세우는 폭. 768이 아니라 1120인 데는 실측 근거가 있다 —
   좁을수록 사양 블록은 접혀서 높아지는데 코드명 열은 반대로 좁아진다. 그러면
   블록 높이에 걸칠 만큼 큰 글자가 제 열에 안 들어간다. 폭을 훑어 보니
   베이스라인이 모자란 양이 768px에서 -227px, 950px에서 -66px이었고
   세 페이지가 전부 0이 되는 지점이 1120px이었다. 그 아래는 세로로 쌓아
   사양에 지면 전체 폭을 준다 — 접힘이 줄어 오히려 잘 읽힌다. */
@media (min-width: 1120px) {
  /* 인쇄 시트의 열 비례(실측): 코드명 열 57.3%, 사양 블록 42.7%.
     `auto`로 두면 글자를 키울수록 열이 넓어져 사양이 더 접히고, 그게 다시 제목을
     키운다 — 발산한다. 비율을 고정해 고리를 끊는다. 워드마크 잉크는 인쇄물에서도
     제 열의 31.9%만 채우므로 남는 여백은 의도된 것이다. */
  .sheet { grid-template-columns: 57.3% 1fr; gap: 0; align-items: start; }
}
.sheet-meta ul { list-style: none; padding: 0; }
/* 레이블과 값이 두 열로 서는 짝. 레이블 폭은 가장 긴 것에 맞춘다.
   ★ align-content: start — 이게 없으면 옆 열(ul)이 더 높을 때 부모 셀에
   맞춰 stretch되면서 행들이 늘어나, DM 줄이 engineering 줄에서 이탈한다. */
.sheet-meta .pairs { display: grid; grid-template-columns: auto 1fr; gap: 0 var(--gap-1);
                     align-content: start; }
.sheet-meta .edition { font-variant-numeric: tabular-nums; }

/* ── 도면 ─────────────────────────────────────────────────────────
   인쇄 PDF에서 뽑은 선화. 잉크가 currentColor로 바뀌어 있어 팔레트를 따라온다. */
figure { margin: 0; display: grid; gap: var(--half); }
figure img { display: block; width: 100%; height: auto; }
figcaption { max-width: var(--measure); font-size: var(--caption); }

/* ── 사진 ─────────────────────────────────────────────────────────
   세 장 고정, 나란히: 제품 사진은 페이지당 세 장이다 (사용자 결정,
   2026-08-22). 캐러셀·가로 스크롤 아님 — 지면 폭을 셋으로 나눠
   원본 비율대로 선다.
   ★ 라벨 칸까지 쓴다: 라벨 없는 행이라 본문을 2열에 앉히는 기본
     규칙(.row > .body:first-child)을 여기서만 되돌려 전폭을 준다.
     사진은 설명이 붙는 대상이 아니라 지면 그 자체다. */
/* 다른 행과 같은 위아래 여백. 한때 사진이 페이지 마지막이라 아래를 0으로 뒀는데,
   앞뒤 화살표가 그 뒤로 오면서 사진이 화살표의 괘선에 붙어버렸다. */
.images { padding: var(--gap-1) 0; }
.images .body {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap-1);
}
.images .body > * + * { margin-top: 0; }
@media (min-width: 768px) {
  .images > .body:first-child { grid-column: 1 / -1; }
}

/* 점프 내비는 가로로 늘어선 링크다. .row의 세로 쌓기 마진(--gap-1)이 여기까지
   걸려서 두 번째 링크부터 25.5px씩 내려앉고, 그 바람에 첫 링크가 그 줄 높이
   (26+25.5=51.5px)만큼 늘어나 혼자 두 배로 보였다. 사진 격자와 같은 이유로 뺀다. */
.jump .body > * + * { margin-top: 0; }

.images img {
  width: 100%;
  /* 비율을 고정하고 채운다. 원본 크롭이 한 화소라도 다르면(pd-3은 912×1400과
     933×1400이었다) 나란한 두 장의 아래끝이 14px 어긋나 행의 밑선이 깨졌다.
     사진마다 크롭을 맞추라고 하는 대신 격자가 흔들리지 않게 한다.
     2:3은 이 사진들의 실제 비율이라(933/1400 = 0.6664) 잘리는 양이 거의 없다. */
  height: auto;    /* ★ 빼면 HTML의 height="1400" 속성이 그대로 쓰인다 */
  aspect-ratio: 2 / 3;
  object-fit: cover;
  background: color-mix(in srgb, var(--fg) 6%, var(--bg));   /* 로딩 중 자리 유지 */
}
/* TR-2 대기화면 — 실기와 같은 128×32 1-bit.
   픽셀 격자가 곧 재료라 보간하지 않는다. 데스크톱에서 정확히 4배(512px)로 걸어
   픽셀이 고르게 떨어지게 한다. */
.oled {
  display: block;
  width: 100%;
  max-width: 512px;
  image-rendering: pixelated;
  background: #000;
}

/* BS-2 실물 3D — 조절되는 것이 이 물건의 요점이라 움직임이 설명이다.
   높이를 화면 비율로 잡아 어느 창에서도 물건이 한눈에 들어온다. */
.hero-live { display: grid; gap: var(--gap-1); padding-bottom: var(--gap-1);
             justify-items: center; }   /* 무대가 지면보다 좁을 때 중앙에 */
#bs3d {
  width: min(100%, 62svh);
  aspect-ratio: 4 / 3;
  touch-action: none;      /* 세로 드래그를 페이지 스크롤에 뺏기지 않게 */
  cursor: grab;
}
#bs3d:active { cursor: grabbing; }
.hint { max-width: var(--measure); font-size: var(--caption); }
