/* ══════════════════════════════════════════════════════════════════════════
   shell2026.css — 자체 셸: WebGL 배경 레이어 · 나브바 · 좌측 사이드바
   ══════════════════════════════════════════════════════════════════════════

   Spectral 의 `#header` / `#menu` 를 쓰지 않는다. 새 이름(`#topbar`, `#sidenav`,
   `body.is-sidenav-open`)을 쓰므로 생성물 CSS(h5u.css)의 규칙이 **하나도 발동하지
   않는다** — 특이도 싸움이 없다는 것이 이 파일의 전제다.

   로드 순서: h5u-tokens → h5u → h5u-project → **shell2026** → link_list

   ── 층(z-index)을 한 곳에서 정한다 ────────────────────────────────────────
   배경 캔버스 < 페이지 < 나브바 < 사이드바 백드롭 < 사이드바 < 모달.
   나브바가 백드롭보다 위면, 딤 처리된 화면 위로 나브바 클릭이 관통한다.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
	--z-canvas: 0;
	--z-page: 1;
	--z-topbar: 900;
	--z-scrim: 1000;
	--z-sidenav: 1010;
	/* 모달은 link_list.css 가 10002 를 쓴다 — 위 값들보다 크다 */

	--topbar-h: 3.5rem;
	--topbar-gap: 0.75rem;

	/* 배너 하단 기하 — 원본 값에서 유도한다(눈대중 금지).
	     `.more`        height: 8.5em · font-size: 0.8em  → 배너 기준 6.8em
	     `.more:after`  bottom: 4em   (화살표 아래 여백)   → 배너 기준 3.2em
	   화살표 아래 여백(3.2em)이 «프레임» 이다 — 위쪽도 같은 값을 쓰면 대칭이 된다. */
	--banner-more-h: 6.8em;
	--banner-frame: 3.2em;

	/* 유리판 표면 — 배경 씬이 비쳐야 하므로 알파를 낮게 유지한다 */
	--glass: 210 22% 11%;
	--hairline: 255 255 255;
}

/* ══════════════════════ 배경 캔버스 레이어 ══════════════════════

   호스트에 transform·filter·will-change·opacity<1·contain 을 **주지 않는다.**
   그 중 하나만 있어도 새 컨테이닝 블록·스택 컨텍스트가 되어 position:fixed 인
   나브바·사이드바가 이 안에 갇힌다 (docs/issues/1 · docs/issues/3 과 같은 부류).
   ──────────────────────────────────────────────────────────────── */

/* 폴백에서는 호스트 자체를 치운다. `:after` 비네트가 남으면 «정적 이미지를 그대로 쓴다» 는
   약속이 깨진다 — 실측에서 폴백 화면이 최대 28/255 만큼 어두워졌고, 상태 밴드 좌표의
   최상위 요소가 호스트로 잡혔다. */
body.webgl-off #bg-scene-host {
	display: none;
}

#bg-scene-host {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: var(--z-canvas);
	pointer-events: none;
	overflow: hidden;
}

#bg-scene-host canvas,
#bg-scene {
	display: block;
	width: 100% !important;
	height: 100% !important;
	/* 화면 전체를 덮으므로 이것이 없으면 모든 클릭을 삼킨다 */
	pointer-events: none;
}

/* 씬 위에 아주 옅은 비네트 — 배너 문구 대비 확보 */
#bg-scene-host:after {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
	/* 두 겹이다.
	   ① 배너 문구가 앉는 자리를 눌러 대비를 만든다 — 씬이 촘촘해지면 글자가 묻힌다.
	   ② 가장자리 비네트로 화면 밖으로 자연스럽게 잠긴다. */
	background:
		radial-gradient(44% 30% at 50% 27%, rgba(5, 8, 12, 0.74) 0%,
			rgba(5, 8, 12, 0.36) 58%, rgba(5, 8, 12, 0) 100%),
		radial-gradient(125% 90% at 50% 14%, rgba(0, 0, 0, 0) 42%, rgba(6, 9, 13, 0.66) 100%);
}

/* ── 캔버스 세계 / 정적 이미지 세계 ─────────────────────────────────────────
 * body.webgl-on  — 캔버스가 산다. 페이지 배경을 비우고 어두운 밴드를 반투명으로.
 * body.webgl-off — 폴백. h5u.css 원본대로 banner.jpg 정적 배경을 그대로 쓴다.
 *                  (이 클래스가 붙지 않으면 배경이 «단색» 이 된다)
 * ──────────────────────────────────────────────────────────────────────── */

html {
	/* 오버스크롤·최초 페인트에서 흰 화면이 튀지 않게 */
	background-color: #070a0e;
}

body.webgl-on {
	background: transparent;
}

/* 원본은 배너 이미지를 `body.landing #page-wrapper` 에 깔고, **모바일용 대체 경로**로
   `body.is-mobile.landing` 에도 같은 이미지를 여러 요소에 깐다(#page-wrapper · #banner ·
   .wrapper.style4 · #footer). 캔버스 세계에서는 그 전부를 치워야 한다.

   특이도를 맞춰 둔다 — 원본 `body.is-mobile.landing #banner` 는 (1,2,1) 이라
   `body.webgl-on #banner` (1,1,1) 로는 진다. 실측에서 ≤980px 과 모든 터치 기기에서
   배너에 정적 이미지가 다시 깔려 씬을 가렸다. 아래 선택자는 (1,2,1)~(1,3,1) 이고
   shell2026.css 가 h5u.css 뒤에 로드되므로 이긴다. */
body.webgl-on.landing #page-wrapper,
body.webgl-on.landing.is-mobile #page-wrapper {
	position: relative;
	z-index: var(--z-page);
	background: none;
}

body.webgl-on.landing #banner,
body.webgl-on.landing.is-mobile #banner {
	background: transparent;
}

body.webgl-on.landing.is-mobile .wrapper.style4 {
	background-image: none;
}

/* 어두운 밴드는 씬이 비치게. 강한 색 밴드(틸 style1 · 남보라 style3)와 타일은
   불투명을 유지한다 — 목록 가독성이 배경보다 우선이다. */
body.webgl-on .wrapper.style2,
body.webgl-on .result-note,
body.webgl-on.landing #footer,
body.webgl-on.landing.is-mobile #footer {
	background-color: hsl(var(--slate) / 0.66);
	background-image: none;
}

/* 프리로드 페이드(원본 #banner:after)는 캔버스 세계에서 불필요하다 —
   캔버스가 이미 검은 화면에서 시작하므로 3초 페이드가 겹치면 첫 인상만 늦어진다. */
body.webgl-on #banner:after {
	display: none;
}

/* ══════════════════════ 배너 — 높이만 줄인다 ══════════════════════

   원본은 `height: 100vh; min-height: 35em` 이고 폭별 미디어 쿼리가 따로 있다.
   높이만 덮고 구조·내용은 원본을 따른다. 내용이 잘리지 않게 min-height 는
   내용 기준으로 넉넉히 둔다.
   ────────────────────────────────────────────────────────────── */

/* 높이를 «내용 + 프레임» 으로 확정한다. 뷰포트 비율(58vh)로 두고 내용을 세로 중앙에
   정렬하면, 뷰포트가 짧아질 때 중앙 정렬된 내용이 `.more` 영역까지 내려와 **버튼과
   «LEARN MORE» 가 겹친다**(실측: 1440×760 47px · 1280×700 48px · 980×900 29px).
   원본은 100vh 라 이 문제가 없었다 — 높이를 줄인 쪽이 자리를 만들어야 한다.

   그래서 세로 중앙 정렬을 쓰지 않고 위·아래 여백을 직접 준다. 그러면
     · 겹침이 **구조적으로** 불가능해지고(내용 아래에 `.more` 높이만큼 자리가 항상 있다)
     · 「HUB 위 구분선 위 여백」과 「화살표 아래 여백」이 같은 변수라 대칭이 보장된다.
   두 값을 눈대중으로 맞추면 폭·글꼴이 바뀔 때마다 다시 어긋난다. */
#banner {
	height: auto;
	min-height: 0;
	justify-content: flex-start;
	/* 나브바(떠 있는 판) 아래에서 프레임만큼 띄운다 */
	padding-top: calc(var(--topbar-gap) + var(--topbar-h) + var(--banner-frame));
	/* `.more` 는 absolute + bottom:0 이라 패딩 박스 하단에 앉는다 — 그 높이를 예약하면
	   화살표 아래에 정확히 --banner-frame 만큼 남는다 */
	padding-bottom: var(--banner-more-h);
}

/* 마지막 요소의 하단 마진을 없애 «아래 여백» 을 패딩이 온전히 결정하게 한다.
   원본 `ul.actions` 는 `margin-bottom: 2em` 을 갖는데, `.more` 가 숨는 좁은 화면에서
   그 마진이 패딩에 더해져 아래 여백이 위보다 정확히 2em(실측 29px) 커졌다. */
#banner .inner > *:last-child {
	margin-bottom: 0;
}

@media screen and (max-width: 736px) {

	/* 원본이 `.more` 를 감추는 구간 — 예약할 대상이 없으니 프레임만 남긴다 */
	#banner {
		padding-bottom: var(--banner-frame);
	}

}

/* ══════════════════════ 자체 컴포넌트의 버튼 리셋 ══════════════════════

   Spectral 은 **맨 `button` 선택자**에 `height: 2.75em` / `line-height: 2.75em` /
   `padding` / `text-transform` 을 걸어 둔다. 그래서 새로 만든 컴포넌트의 `<button>` 이
   그 치수를 물려받아, 내가 준 padding 이 무시되고 상속된 절대 line-height 가 고정 높이를
   넘쳐 **글자가 잘렸다**(실측: 내용 54px 가 33px 박스에 갇힘).

   `font: inherit` 는 line-height 까지 상속해 오므로 함께 끊어 준다 — 작은 글자에 본문의
   큰 절대 line-height 가 들어오면 같은 문제가 재발한다.
   ──────────────────────────────────────────────────────────────────────── */

#topbar button,
#sidenav button {
	/* height 는 **여기서 정하지 않는다.** ID 로 스코프한 리셋이 각 컴포넌트의 명시 높이를
	   이겨 버려서 햄버거가 15px 로 찌그러진 적이 있다. 원본의 `button{height:3.125em}` 은
	   특이도 (0,0,1) 이라 `.nav-burger`(0,1,0) 만으로 이미 이긴다 — 크기는 컴포넌트가 갖고,
	   여기서는 «크기와 무관한 물려받은 군더더기» 만 끊는다. */
	line-height: 1.4;
	text-transform: none;
	box-shadow: none;
	max-width: none;
	padding: 0;
}

/* ── 배너 인트로 연출 속도 ─────────────────────────────────────────────────
 * 원본은 `#banner .more` 에 `transition-delay: 3.5s` 를 걸고 `body.is-preload` 에서
 * `translateY(8.5em) / opacity: 0` 으로 숨긴다. is-preload 는 load 후 0.1초에 떨어지므로
 * «LEARN MORE»+화살표가 완전히 보이는 시점이 약 4.4초다 — 100vh 배너를 천천히 훑는
 * 원본 데모에는 맞지만, 배너를 줄이고 목록이 본론인 이 화면에서는 그냥 느리게 느껴진다.
 * 제목·문구 다음에 오는 순서(스태거)는 유지하고 대기 시간만 줄인다.
 * ──────────────────────────────────────────────────────────────────────── */

#banner .more {
	transition-delay: 0.55s;
}

/* ══════════════════════ 나브바 (2026) ══════════════════════

   떠 있는 유리판. 직각 유지. 좌측이 햄버거다.
   항목이 늘어날 자리이므로 wrap 을 허용하고, 줄어들 요소에 min-width:0 을 준다
   (flex-shrink:0 + 고정폭 조합은 안쪽 wrap 을 막는다).
   ────────────────────────────────────────────────────── */

#topbar {
	position: fixed;
	top: var(--topbar-gap);
	left: var(--topbar-gap);
	right: var(--topbar-gap);
	z-index: var(--z-topbar);
	display: flex;
	/* 항목이 늘어나는 영역이다 — wrap 은 «처음부터» 켜 둔다. 좁은 폭에서만 켜면 그때까지는
	   줄이 늘지 않고 기존 요소가 눌린다(늘려 본 뒤에야 드러나는 부류의 결함). */
	flex-wrap: wrap;
	align-items: center;
	gap: 0.85rem 0.85rem;
	min-height: var(--topbar-h);
	padding: 0 0.6rem 0 0.5rem;
	background-color: hsl(var(--glass) / 0.42);
	border: solid 1px rgba(var(--hairline) / 0.09);
	backdrop-filter: blur(18px) saturate(150%);
	-webkit-backdrop-filter: blur(18px) saturate(150%);
	transition: background-color 0.28s ease, border-color 0.28s ease;
}

/* 내려가면 또렷해진다 — Spectral 의 `.alt` 를 대체하는 자체 동작 */
#topbar.is-scrolled {
	background-color: hsl(var(--glass) / 0.86);
	border-color: rgba(var(--hairline) / 0.16);
}

/* 상단 헤어라인 — 액센트가 아주 옅게 흐른다 */
#topbar:before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 1px;
	background: linear-gradient(90deg,
		transparent,
		hsl(var(--accent) / 0.55) 22%,
		hsl(var(--band-1) / 0.45) 58%,
		transparent);
	opacity: 0.7;
}

/* ── 햄버거 (좌측) ──────────────────────────────────────────────────────── */

.nav-burger {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: 0.55rem;
	height: 2.4rem;
	padding: 0 0.7rem !important;
	background: transparent;
	border: solid 1px rgba(var(--hairline) / 0.12);
	color: #fff;
	cursor: pointer;
	font: inherit;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.nav-burger:hover {
	background-color: rgba(var(--hairline) / 0.07);
	border-color: rgba(var(--hairline) / 0.24);
}

.nav-burger .bars {
	position: relative;
	display: block;
	width: 1.05rem;
	height: 0.7rem;
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
}

.nav-burger .bars i {
	position: absolute;
	left: 0;
	width: 100%;
	height: 1.5px;
	background: #fff;
	transition: transform 0.26s ease, opacity 0.18s ease;
}

.nav-burger .bars i:nth-child(1) { top: 0; }
.nav-burger .bars i:nth-child(2) { top: 50%; margin-top: -0.75px; }
.nav-burger .bars i:nth-child(3) { bottom: 0; }

/* 열리면 X 로 — 여는 버튼이 그대로 닫는 버튼이 된다 */
body.is-sidenav-open .nav-burger .bars i:nth-child(1) {
	transform: translateY(0.335rem) rotate(45deg);
}

body.is-sidenav-open .nav-burger .bars i:nth-child(2) {
	opacity: 0;
}

body.is-sidenav-open .nav-burger .bars i:nth-child(3) {
	transform: translateY(-0.335rem) rotate(-45deg);
}

.nav-burger .burger-label {
	font-size: 0.6rem;
	font-weight: 600;
}

/* ── 워드마크 ───────────────────────────────────────────────────────────── */

.nav-brand {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	display: flex;
	align-items: baseline;
	gap: 0.45rem;
	border-bottom: 0;
	color: #fff;
}

.nav-brand .mark {
	font-size: 0.95rem;
	font-weight: 800;
	letter-spacing: 0.3em;
	text-transform: uppercase;
}

.nav-brand .tag {
	font-size: 0.55rem;
	font-weight: 600;
	letter-spacing: 0.24em;
	opacity: 0.5;
	text-transform: uppercase;
}

/* ── 라이브 상태 — 정상 응답 수를 앞세운다 ──────────────────────────────── */

.nav-live {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	min-width: 0;          /* 이게 없으면 줄어들지 않아 wrap 이 걸리지 않는다 */
	margin-left: auto;
	padding: 0.3rem 0.7rem;
	background-color: rgba(var(--hairline) / 0.05);
	border: solid 1px rgba(var(--hairline) / 0.1);
	font-size: 0.6rem;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	white-space: nowrap;
}

.nav-live .dot {
	position: relative;
	display: block;
	width: 0.42rem;
	height: 0.42rem;
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	background-color: #35b07a;
}

/* 살아 있다는 신호 — 느리게 숨쉰다 */
.nav-live .dot:after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	width: 1.4rem;
	height: 1.4rem;
	margin: -0.7rem 0 0 -0.7rem;
	background-color: inherit;
	opacity: 0.28;
	animation: navPulse 2.6s ease-out infinite;
}

@keyframes navPulse {
	0%   { transform: scale(0.28); opacity: 0.34; }
	70%  { transform: scale(1);    opacity: 0; }
	100% { transform: scale(1);    opacity: 0; }
}

.nav-live.is-degraded .dot { background-color: #d99b1f; }
.nav-live.is-down .dot     { background-color: #d63b2a; }

.nav-live .num {
	font-size: 0.78rem;
	font-weight: 800;
	letter-spacing: 0.08em;
}

.nav-live .sep { opacity: 0.4; }
.nav-live .total { opacity: 0.62; }
.nav-live .word { opacity: 0.5; }

/* ── 액센트 스위치 ──────────────────────────────────────────────────────── */

#topbar .accents {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: 0.35rem;
}

#topbar .accents .label {
	font-size: 0.55rem;
	font-weight: 600;
	letter-spacing: 0.24em;
	opacity: 0.45;
	text-transform: uppercase;
}

#topbar .swatch {
	display: block;
	width: 0.95rem;
	height: 0.95rem;
	padding: 0;
	border: solid 1px rgba(var(--hairline) / 0.3);
	cursor: pointer;
	transition: transform 0.16s ease, border-color 0.16s ease;
}

#topbar .swatch:hover {
	border-color: #fff;
	transform: translateY(-1px);
}

#topbar .swatch[aria-checked='true'] {
	border-color: #fff;
	box-shadow: inset 0 0 0 2px hsl(var(--glass));
}

#topbar .swatch[data-accent='vermilion'] { background-color: hsl(8 84% 57%); }
#topbar .swatch[data-accent='teal']      { background-color: hsl(175 68% 40%); }
#topbar .swatch[data-accent='indigo']    { background-color: hsl(250 62% 58%); }

/* ── 나브바 반응형 — 라벨부터 접고 햄버거·워드마크·상태는 남긴다 ────────── */

@media screen and (max-width: 860px) {

	#topbar { gap: 0.6rem; }
	.nav-burger .burger-label { display: none; }
	.nav-burger { padding: 0 0.6rem; }
	#topbar .accents .label { display: none; }

}

@media screen and (max-width: 560px) {

	#topbar {
		padding: 0.4rem 0.5rem;
		row-gap: 0.4rem;
	}

	.nav-live .word { display: none; }

}

/* ══════════════════════ 좌측 사이드바 (2026) ══════════════════════

   좌측에서 열리고, 페이지를 밀지 않고 덮는다. `#page-wrapper` 에 transform 을
   걸지 않으므로 position:fixed 가 깨지는 함정 자체가 없다.
   ─────────────────────────────────────────────────────────────── */

#sidenav-scrim {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: var(--z-scrim);
	background-color: rgba(4, 7, 11, 0.62);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.32s ease;
}

body.is-sidenav-open #sidenav-scrim {
	opacity: 1;
	pointer-events: auto;
}

#sidenav {
	position: fixed;
	top: 0;
	left: 0;
	z-index: var(--z-sidenav);
	display: flex;
	flex-direction: column;
	width: 22rem;
	max-width: 86vw;
	height: 100%;
	background-color: hsl(212 26% 8% / 0.94);
	border-right: solid 1px rgba(var(--hairline) / 0.1);
	backdrop-filter: blur(22px) saturate(140%);
	-webkit-backdrop-filter: blur(22px) saturate(140%);
	overflow-y: auto;
	transform: translateX(-100%);
	transition: transform 0.42s cubic-bezier(0.22, 1, 0.36, 1);
	visibility: hidden;
}

body.is-sidenav-open #sidenav {
	transform: translateX(0);
	visibility: visible;
}

/* 패널 섹션은 «줄어들지» 않는다.
   flex 아이템의 기본값은 `flex-shrink: 1` 이라, 내용이 패널 높이를 조금 넘으면 스크롤이
   아니라 **각 섹션이 눌린다** — 실측에서 동작 버튼이 54px 내용을 33px 로 압축해 글자가
   잘렸다. 넘칠 때 해야 하는 일은 압축이 아니라 스크롤(`overflow-y: auto`)이다. */
#sidenav > * {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
}

/* 좌측 가장자리에 액센트 광선 — 패널이 «켜져 있다» 는 인상 */
#sidenav:before {
	content: '';
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	width: 2px;
	background: linear-gradient(180deg,
		hsl(var(--accent) / 0.9),
		hsl(var(--band-1) / 0.55) 46%,
		transparent);
}

/* ── 사이드바 머리 ──────────────────────────────────────────────────────── */

.sidenav-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.5rem 1.5rem 1.15rem 1.5rem;
	border-bottom: solid 1px rgba(var(--hairline) / 0.08);
}

.sidenav-head .eyebrow {
	display: block;
	font-size: 0.55rem;
	font-weight: 600;
	letter-spacing: 0.28em;
	opacity: 0.45;
	text-transform: uppercase;
}

.sidenav-head .title {
	display: block;
	margin-top: 0.3rem;
	font-size: 1.05rem;
	font-weight: 800;
	letter-spacing: 0.26em;
	text-transform: uppercase;
}

.sidenav-close {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.2rem;
	height: 2.2rem;
	background: transparent;
	border: solid 1px rgba(var(--hairline) / 0.14);
	color: #fff;
	cursor: pointer;
	font-size: 1.1rem;
	line-height: 1;
}

.sidenav-close:hover {
	background-color: rgba(var(--hairline) / 0.08);
	border-color: rgba(var(--hairline) / 0.3);
}

/* ── 이동 목록 — 인덱스 번호 + 자라는 액센트 바 ─────────────────────────── */

.sidenav-nav {
	list-style: none;
	margin: 0;
	padding: 0.5rem 0;
}

.sidenav-nav li {
	margin: 0;
	padding: 0;
}

.sidenav-nav a {
	position: relative;
	display: flex;
	align-items: center;
	gap: 0.9rem;
	padding: 0.85rem 1.5rem;
	border-bottom: 0;
	color: #fff;
	text-decoration: none;
	transition: background-color 0.2s ease, padding-left 0.24s ease;
}

.sidenav-nav a:before {
	content: '';
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	width: 0;
	background-color: hsl(var(--accent));
	transition: width 0.24s ease;
}

.sidenav-nav a:hover,
.sidenav-nav a:focus-visible {
	background-color: rgba(var(--hairline) / 0.05);
	padding-left: 1.85rem;
}

.sidenav-nav a:hover:before,
.sidenav-nav a:focus-visible:before {
	width: 3px;
}

.sidenav-nav .idx {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	font-size: 0.6rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	opacity: 0.38;
}

.sidenav-nav .label {
	-webkit-flex: 1 1 auto;
	flex: 1 1 auto;
	min-width: 0;
	font-size: 0.82rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.sidenav-nav .arrow {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	opacity: 0;
	transform: translateX(-0.3rem);
	transition: opacity 0.2s ease, transform 0.2s ease;
}

.sidenav-nav a:hover .arrow,
.sidenav-nav a:focus-visible .arrow {
	opacity: 0.7;
	transform: translateX(0);
}

/* 열릴 때 항목이 순서대로 들어온다 */
body.is-sidenav-open .sidenav-stagger > * {
	animation: sidenavIn 0.44s cubic-bezier(0.22, 1, 0.36, 1) both;
	animation-delay: calc(var(--i, 0) * 42ms + 90ms);
}

@keyframes sidenavIn {
	from { opacity: 0; transform: translateX(-0.9rem); }
	to   { opacity: 1; transform: translateX(0); }
}

/* ── 상태 요약 블록 ─────────────────────────────────────────────────────── */

.sidenav-status {
	margin: 0.35rem 1.5rem 0 1.5rem;
	padding: 1.15rem 0 0 0;
	border-top: solid 1px rgba(var(--hairline) / 0.08);
}

.sidenav-status .eyebrow {
	display: block;
	margin-bottom: 0.8rem;
	font-size: 0.55rem;
	font-weight: 600;
	letter-spacing: 0.28em;
	opacity: 0.45;
	text-transform: uppercase;
}

.sidenav-status .grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0.6rem;
}

.sidenav-status .cell {
	padding: 0.6rem 0.65rem;
	background-color: rgba(var(--hairline) / 0.04);
	border-left: solid 2px rgba(var(--hairline) / 0.2);
}

.sidenav-status .cell.is-ok   { border-left-color: #35b07a; }
.sidenav-status .cell.is-auth { border-left-color: #d99b1f; }
.sidenav-status .cell.is-down { border-left-color: #d63b2a; }

.sidenav-status .cell .n {
	display: block;
	font-size: 1.05rem;
	font-weight: 800;
	letter-spacing: 0.04em;
	line-height: 1.1;
}

.sidenav-status .cell .k {
	display: block;
	margin-top: 0.25rem;
	font-size: 0.52rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	opacity: 0.6;
	text-transform: uppercase;
}

.sidenav-status .checked {
	margin: 0.85rem 0 0 0;
	font-size: 0.58rem;
	letter-spacing: 0.2em;
	opacity: 0.55;
	text-transform: uppercase;
}

/* ── 동작 · 발 ──────────────────────────────────────────────────────────── */

.sidenav-actions {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	margin: 1.35rem 1.5rem 0 1.5rem;
}

.sidenav-actions button {
	-webkit-flex-shrink: 0;
	flex-shrink: 0;
	height: auto;
	width: 100%;
	padding: 0.8rem 1rem !important;
	background: transparent;
	border: solid 1px rgba(var(--hairline) / 0.18);
	color: #fff;
	cursor: pointer;
	font: inherit;
	font-size: 0.65rem;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.sidenav-actions button:hover {
	background-color: rgba(var(--hairline) / 0.08);
	border-color: rgba(var(--hairline) / 0.34);
}

.sidenav-actions button.primary {
	background-color: hsl(var(--accent));
	border-color: hsl(var(--accent));
}

.sidenav-actions button.primary:hover {
	background-color: hsl(var(--accent-lo));
	border-color: hsl(var(--accent-lo));
}

.sidenav-actions button[disabled] {
	cursor: default;
	opacity: 0.5;
}

.sidenav-foot {
	margin-top: auto;
	padding: 1.5rem;
}

.sidenav-foot .accents {
	display: flex;
	align-items: center;
	gap: 0.4rem;
}

.sidenav-foot .accents .label {
	margin-right: 0.25rem;
	font-size: 0.55rem;
	font-weight: 600;
	letter-spacing: 0.24em;
	opacity: 0.45;
	text-transform: uppercase;
}

.sidenav-foot .swatch {
	display: block;
	width: 1.05rem;
	height: 1.05rem;
	padding: 0;
	border: solid 1px rgba(var(--hairline) / 0.3);
	cursor: pointer;
}

.sidenav-foot .swatch:hover { border-color: #fff; }

.sidenav-foot .swatch[aria-checked='true'] {
	border-color: #fff;
	box-shadow: inset 0 0 0 2px hsl(212 26% 8%);
}

.sidenav-foot .swatch[data-accent='vermilion'] { background-color: hsl(8 84% 57%); }
.sidenav-foot .swatch[data-accent='teal']      { background-color: hsl(175 68% 40%); }
.sidenav-foot .swatch[data-accent='indigo']    { background-color: hsl(250 62% 58%); }

.sidenav-foot .meta {
	margin: 1rem 0 0 0;
	font-size: 0.52rem;
	letter-spacing: 0.18em;
	opacity: 0.35;
	text-transform: uppercase;
}

/* 사이드바가 열려 있으면 배경 스크롤을 잠근다 */
body.is-sidenav-open {
	overflow: hidden;
}

/* 움직임을 줄이라는 설정이면 전환·스윕을 끈다 (배경 씬은 애초에 뜨지 않는다) */
@media (prefers-reduced-motion: reduce) {

	#sidenav,
	#sidenav-scrim,
	.nav-burger .bars i,
	.sidenav-nav a,
	.sidenav-nav a:before {
		transition: none !important;
	}

	body.is-sidenav-open .sidenav-stagger > * {
		animation: none !important;
	}

	.nav-live .dot:after {
		animation: none !important;
	}

}

/* ── `.wrapper.alt` 밴드의 좁은 화면 여백 ─────────────────────────────────
 * 원본 `.wrapper.alt { padding: 0 }` 은 전폭 콘텐츠(spotlight 의 edge-to-edge 이미지)를
 * 위한 변형이다. 그런데 «찾기»(`#find`)가 그 변형을 쓰면서 폼을 담고 있어, `.inner` 가
 * 100% 가 되는 ≤980px 부터 **제목·설명·입력이 화면 좌우 끝에 붙는다**(실측 x=0 —
 * 430px 에서 «찾기» 의 첫 글자가 잘려 보였다). 다른 밴드(`#groups`·`#cta`)와 footer 는
 * `.wrapper` padding 으로 48px/29px 여백을 갖는데 이 밴드만 0 이었다.
 * 원본 값과 같은 여백을 넣어 좌우를 맞춘다.
 * ──────────────────────────────────────────────────────────────────────── */

@media screen and (max-width: 980px) {

	.wrapper.alt {
		padding-left: 3em;
		padding-right: 3em;
	}

}

@media screen and (max-width: 736px) {

	.wrapper.alt {
		padding-left: 2em;
		padding-right: 2em;
	}

}

/* ══════════════════════ Footer (2026) ══════════════════════

   구성 — 상단 한 줄(라이브 + 내비) · 큰 워드마크 · 얇은 유틸리티 줄.
   정보를 늘리지 않는 것이 요점이다: 상태 수치는 나브바·상태 카드·사이드바에 이미 있어
   Footer 가 네 번째로 반복할 이유가 없다.

   ── 지켜야 하는 수치 (전부 회귀 검사로 못박혀 있다) ────────────────────────
   · **대비 4.5:1** — WCAG 2.2 SC 1.4.3. 이전 Footer 는 `rgba(255,255,255,0.5)` 로
     4.31:1 이라 미달이었다(실측). 표면을 **불투명**하게 해야 이 값이 보장된다 — 반투명
     표면 뒤로 WebGL 씬이 비치면 대비가 «움직이는 값» 이 된다.
     예외: 큰 워드마크는 **로고타입**이라 명세가 대비 요구에서 제외한다.
   · **터치 타깃 24×24 CSS px** — SC 2.5.8. 문장 안 인라인 링크는 예외지만 여기 목록
     링크는 독립 타깃이라 예외가 아니다. 이전 Footer 의 링크는 높이 17px 였다.
   · **포커스가 가려지지 않게** — SC 2.4.11. 앵커 대상에 `scroll-margin-top`.
   ──────────────────────────────────────────────────────────────────────── */

/* 표면을 불투명하게. **두 세계(webgl-on / webgl-off) 모두** 덮어야 한다. 원본이 Footer
   배경에 걸어 둔 규칙은
     `#footer`                        (1,0,0)  #1d242a
     `body.landing #footer`           (1,1,1)  rgba(29,36,42,0.9)  ← 반투명
     `body.is-mobile.landing #footer` (1,2,1)  banner.jpg
   이고, 처음에 `webgl-on` 쪽만 덮었더니 **폴백 세계에서 (1,1,1) 이 살아나** 반투명이
   됐다(회귀 검사가 잡았다). 아래는 (1,2,1)~(1,3,1) 이고 shell2026.css 가 뒤에 로드되므로
   동률도 이긴다. */
#footer,
body.landing #footer,
body.landing.is-mobile #footer,
body.webgl-on.landing #footer,
body.webgl-on.landing.is-mobile #footer {
	background-color: #0d1317;
	background-image: none;
}

#footer {
	padding: 0;
	text-align: left;
}

/* 원본은 폭을 `.wrapper > .inner` 에만 준다(60em / ≤1280px 90% / ≤980px 100%). Footer 는
   `.wrapper` 가 아니어서 그 규칙이 닿지 않는다 — 같은 폭 체계를 명시적으로 준다. */
#footer .inner {
	width: 60em;
	max-width: none;
	margin: 0 auto;
	padding: 3em 0 1.5em 0;
}

/* 앵커 이동 시 고정 나브바에 가리지 않게 (SC 2.4.11) */
#top,
#footer [id] {
	scroll-margin-top: calc(var(--topbar-h) + var(--topbar-gap) * 2);
}

/* ── 상단 한 줄: 라이브 상태 + 내비 ──────────────────────────────────────── */

#footer .foot-lead {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1em 2em;
}

#footer .foot-live {
	display: flex;
	align-items: center;
	gap: 0.55em;
	margin: 0;
	font-size: 0.62em;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.82);   /* #0d1317 위 대비 ≈ 11:1 */
	white-space: nowrap;
}

#footer .foot-live .dot {
	display: block;
	width: 0.5em;
	height: 0.5em;
	flex-shrink: 0;
	background-color: #8894a0;
}

#footer .foot-live.is-ok       .dot { background-color: #0ca30c; }
#footer .foot-live.is-degraded .dot { background-color: #fab219; }
#footer .foot-live.is-down     .dot { background-color: #d03b3b; }

#footer .foot-nav ul {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0 1.6em;
	list-style: none;
	margin: 0;
	padding: 0;
}

#footer .foot-nav li {
	margin: 0;
	padding: 0;
}

#footer .foot-nav a {
	display: inline-flex;
	align-items: center;
	/* 24px 하한 — SC 2.5.8. px 로 못박는다(글꼴 크기에 흔들리지 않게) */
	min-height: 24px;
	border-bottom: 0;
	color: rgba(255, 255, 255, 0.88);   /* 대비 ≈ 13:1 */
	font-size: 0.66em;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-decoration: none;
	text-transform: uppercase;
	transition: color 0.16s ease;
}

#footer .foot-nav a:hover,
#footer .foot-nav a:focus-visible {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 0.4em;
}

/* ── 워드마크 ─────────────────────────────────────────────────────────────
   로고타입이라 대비 요구 대상이 아니다(SC 1.4.3 예외). 시각적 마무리 역할이므로
   화면 폭에 따라 함께 커지되(clamp) 넘치지 않게 한다. */

/* 워드마크와 소개를 한 줄에 나란히 — 워드마크만 두면 오른쪽이 비고, 글자를 벌려 폭을
   채우면 워드마크로 읽히지 않는다(둘 다 실측으로 확인). */
#footer .foot-identity {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: end;
	gap: 0 3em;
	margin: 1.6em 0 0 0;
}

#footer .foot-about {
	margin: 0 0 0.7em 0;
	max-width: 30em;
	font-size: 0.72em;
	letter-spacing: 0.03em;
	line-height: 1.75;
	color: rgba(255, 255, 255, 0.72);   /* 대비 ≈ 9.5:1 */
}

#footer .foot-about strong {
	color: #fff;
	font-weight: 600;
}

#footer .foot-mark {
	margin: 0;
	font-size: clamp(3rem, 8vw, 6.5rem);
	font-weight: 800;
	letter-spacing: 0.01em;
	line-height: 0.8;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.07);
	/* 액센트가 아주 옅게 스민다 — 배경 씬과 같은 계열로 묶는다 */
	background-image: linear-gradient(100deg,
		hsl(var(--accent) / 0.42) 0%,
		hsl(var(--band-1) / 0.3) 55%,
		rgba(255, 255, 255, 0.07) 100%);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
	user-select: none;
}



/* ── 유틸리티 줄 ──────────────────────────────────────────────────────────── */

#footer .foot-base {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75em 1.75em;
	margin: 0.6em 0 0 0;
	padding: 1.2em 0 0 0;
	border-top: solid 1px rgba(255, 255, 255, 0.1);
}

#footer .foot-legal {
	margin: 0;
}

#footer .foot-legal small {
	font-size: 0.62em;
	letter-spacing: 0.14em;
	color: rgba(255, 255, 255, 0.7);   /* 대비 ≈ 8.5:1 */
}

#footer .foot-credits {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0 1.1em;
	list-style: none;
	margin: 0;
	padding: 0;
}

#footer .foot-credits li {
	margin: 0;
	padding: 0;
}

#footer .foot-credits a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	border-bottom: 0;
	color: rgba(255, 255, 255, 0.66);   /* 대비 ≈ 7.5:1 */
	font-size: 0.6em;
	letter-spacing: 0.12em;
	text-decoration: none;
	text-transform: uppercase;
}

#footer .foot-credits a:hover,
#footer .foot-credits a:focus-visible {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 0.35em;
}

#footer .foot-top {
	display: inline-flex;
	align-items: center;
	gap: 0.3em;
	min-height: 24px;
	margin-left: auto;
	padding: 0.4em 0.9em;
	border: solid 1px rgba(255, 255, 255, 0.22);
	color: rgba(255, 255, 255, 0.88);
	font-size: 0.6em;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-decoration: none;
	text-transform: uppercase;
	transition: background-color 0.16s ease, border-color 0.16s ease;
}

#footer .foot-top:hover,
#footer .foot-top:focus-visible {
	background-color: rgba(255, 255, 255, 0.08);
	border-color: rgba(255, 255, 255, 0.5);
	color: #fff;
}

/* ── 반응형 ─────────────────────────────────────────────────────────────── */

@media screen and (max-width: 1280px) {

	#footer .inner {
		width: 90%;
	}

}

/* ≤980px 부터 원본은 `.inner` 를 100% 로 두고 **`.wrapper` 자체의 padding** 으로 여백을
   만든다(`4em 3em 2em 3em` → ≤736px `3em 2em 1em 2em`). Footer 도 같은 값을 써야 본문
   밴드와 좌우가 맞는다. */
@media screen and (max-width: 980px) {

	#footer {
		padding-left: 3em;
		padding-right: 3em;
	}

	#footer .inner {
		width: 100%;
	}

	#footer .foot-lead {
		flex-direction: column;
		align-items: flex-start;
	}

	#footer .foot-identity {
		grid-template-columns: minmax(0, 1fr);
		align-items: start;
		gap: 1em 0;
	}

	#footer .foot-about {
		margin-bottom: 0;
	}

}

@media screen and (max-width: 736px) {

	#footer {
		padding-left: 2em;
		padding-right: 2em;
	}

	#footer .foot-nav ul {
		gap: 0 1.1em;
	}

	#footer .foot-top {
		margin-left: 0;
	}

}
