/* ══════════════════════════════════════════════════════════════════════════
   base.css — 바탕. 상자 모델·본문·초점·건너뛰기 링크.
   컴포넌트가 아니라 «모든 요소에 깔리는 규칙» 이다. 여기에 컴포넌트를 넣지 않는다.

   셸 CSS 는 책임별로 나뉘어 있다(`static/css/shell/`). 한 파일이 토큰·바탕·머리·Footer를
   모두 갖고 있으면 «머리 간격 하나» 를 고치러 700줄을 뒤져야 하고, 무엇이 시스템이고
   무엇이 한 컴포넌트인지 구분이 사라진다.

     tokens.css   색·서체·크기·간격         — **다른 모든 CSS 가 의존한다**
     base.css     리셋·바탕·초점·건너뛰기    — tokens 에만 의존
     nav.css      머리 한 컴포넌트          — tokens 에만 의존
     footer.css   Footer 한 컴포넌트          — tokens 에만 의존

   의존은 한 방향뿐이다(tokens ← 나머지). 컴포넌트끼리는 서로를 모른다.
   ══════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════ 2. 바탕 ═══════════════════════════ */

*, *::before, *::after {
	box-sizing: border-box;
}

/* **가로로는 넘치지 않는다.** 배너가 지면 밖으로 흘러 화면 끝까지 가는데(`50% - 50vw`),
   `vw` 는 **세로 스크롤바까지 포함한** 폭이다 — 스크롤바가 자리를 차지하는 환경(Windows 등)
   에서는 띠가 그 두께만큼 넓어져 가로 스크롤바가 하나 더 생긴다.
   `clip` 을 쓴다(`hidden` 이 아니다): `hidden` 은 스크롤 컨테이너를 만들어 `position: sticky`
   와 앵커 스크롤을 망가뜨리지만, `clip` 은 자르기만 한다. */
html {
	overflow-x: clip;
}

body {
	margin: 0;
	background: var(--bg);
	color: var(--fg);
	font-family: var(--font);
	font-size: var(--t-base);
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
	/* 고정된 머리 아래로 내용이 숨지 않게 */
	padding-top: var(--nav-h);

	/* ── 짧은 페이지에서도 꼬리는 **바닥에** ──
	   본문이 짧으면 꼬리가 화면 중간에서 끝나고 그 아래로 지면 색이 드러났다(실측: LAB 에서
	   꼬리 밑 457px). «페이지가 덜 그려졌나» 로 읽힌다.

	   본문(`#main`)이 남는 높이를 먹게 해서 꼬리를 밀어낸다. 내용이 길면 아무 일도 하지
	   않는다 — `flex: 1` 은 «남을 때만» 늘리는 규칙이다.

	   `100dvh` 를 쓰는 이유: 모바일 브라우저의 주소창이 접히면 `100vh` 는 실제 화면보다
	   커서 꼬리가 화면 밖으로 밀린다. 지원하지 않는 브라우저를 위해 `100vh` 를 먼저 둔다. */
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100dvh;
}

/* 남는 높이는 본문이 먹는다(위 주석). `#page` 가 본문과 꼬리를 감싸고 있으므로 **사슬을
   이어야** 한다 — `#main` 에만 `flex: 1` 을 주면 그 부모가 늘지 않아 아무 일도 일어나지
   않는다(실측: 꼬리 밑 457px 그대로).
   서랍·나브처럼 이 사슬 밖에 있는 것은 영향받지 않는다. */
#page {
	display: flex;
	flex-direction: column;
	flex: 1;
}

#main {
	flex: 1;
}

/* 앵커로 이동할 때 고정된 머리에 가려지지 않게 — 이걸 빼면 «맨 위로» 가 제목을 덮는다 */
:target {
	scroll-margin-top: calc(var(--nav-h) + 1rem);
}

.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ══ 두 가지 «기기 규칙» ══ 둘 다 **모든 화면에 같은 방식으로** 적용된다.

   ① hover 가드 — 화면 CSS 의 모든 `:hover` 규칙은 `@media (hover: hover)` 안에 있다(37곳,
      예외 없음). 터치 기기에는 커서가 없어 브라우저가 **탭한 요소에 hover 를 붙여 두고 다음
      탭까지 유지**한다 — 목록의 한 줄을 눌러 상세로 갔다 오면 그 줄만 밑줄이 남아 «선택된 줄»
      처럼 보인다. 가드는 그 잔상을 없앤다.
      **`:focus-visible` 은 가드 밖이다** — 키보드는 기기와 무관하다. 그래서 두 선택자가 한
      규칙에 섞여 있던 13곳은 갈랐다(감싸면 터치 기기에서 초점 표시가 함께 죽는다).
      회귀 검사: `test_site.py::test_hover_rules_are_all_guarded`

   ② safe-area — **쓰지 않는다.** 노치·홈 인디케이터를 피하는 `env(safe-area-inset-*)` 는
      뷰포트 메타에 `viewport-fit=cover` 가 있어야 0 이 아닌 값이 되는데, 우리는 그것을 켜지
      않았다(`_shell.html`). 켜지 않으면 브라우저가 **안전영역 안쪽에만** 그리므로 가려지는
      곳이 없다 — 즉 지금 구조에서 `env()` 는 항상 0 이고, 넣어도 아무 일도 하지 않는다.
      「값은 0 이지만 일단 넣어 둔다」 는 코드를 두지 않는다: 읽는 사람이 그것이 동작한다고
      믿게 된다. 화면 끝까지 쓰기로 결정하면 그때 `cover` 와 함께 **한 번에** 넣는다
      (고정 머리·꼬리·서랍 전부). 회귀 검사: 같은 파일의 `test_no_dead_safe_area_code`

   초점 — 시스템 전체에서 한 모양. 키보드로 올 때만 보인다(`:focus-visible`). */
:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
	border-radius: var(--radius-sm);
}

/* 건너뛰기 링크 — 키보드 사용자가 머리를 지나 본문으로 바로 간다. 초점을 받을 때만 나타난다. */
#skip {
	position: fixed;
	top: 0.5rem;
	left: 0.5rem;
	z-index: calc(var(--z-nav) + 10);
	padding: 0.5rem 0.85rem;
	border-radius: var(--radius);
	background: var(--accent);
	color: var(--on-accent);
	font-size: var(--t-sm);
	font-weight: 600;
	text-decoration: none;
	transform: translateY(-200%);
	transition: transform var(--dur) var(--ease);
}

#skip:focus {
	transform: none;
}

/* ── 폭 상한 ──
   래퍼 요소를 넣지 않고 **좌우 패딩**으로 콘텐츠를 가둔다:

       padding-inline: max(var(--gutter), (100% - var(--page-max)) / 2)

   좁은 화면에서는 `--gutter` 가 이기고, 넓어지면 뒤쪽 항이 이겨 콘텐츠가 지면 폭에서 멈춘다.
   배경·테두리는 여전히 화면 끝까지 간다 — 머리의 흐림과 Footer 의 지면이 «화면 폭» 이어야
   층으로 읽히기 때문이다. 래퍼를 넣으면 그 둘을 따로 처리해야 한다.

   (`.bleed-cap` 이라는 클래스로도 같은 값을 내주고 있었으나 **쓰는 곳이 없어 지웠다** —
   지금 이 계산을 쓰는 것은 아래 `#main` 하나다. 두 번째 사용처가 생기면 그때 다시 뽑는다.) */

/* 본문도 같은 폭에 갇힌다. **이건 셸이 계속 쥔다** — 세 화면이 같은 폭·같은 셸 간격을
   써야 오갈 때 지면이 흔들리지 않는다. 화면 CSS 로 내려보내면 화면마다 갈린다. */
#main {
	/* **이 화면들의 반응형 기준.** 화면 CSS 는 뷰포트가 아니라 이 «지면 폭» 으로 판단한다
	   (`@container`) — 지면 폭은 좌우 여백과 `--page-max` 를 이미 뺀 값이라, 「접을 때」와
	   「넘칠 때」가 어긋나지 않는다. 뷰포트로 재면 어긋난다: 사다리가 폭을 179~195px 계단으로
	   떨어뜨리는데 뷰포트는 그 계단을 모른다(상세·목록에서 실제 결함이었다).

	   `inline-size` 만 쓴다(`size` 가 아니다) — 세로는 담기지 않아야 내용만큼 자란다.

	   **이름을 준다(`page`).** 이름 없이 `@container` 를 쓰면 «가장 가까운 컨테이너» 가
	   대상이 되는데, 화면 CSS 는 구획·칸에도 컨테이너를 걸기 때문에 의도한 것과 다른 폭을
	   보게 된다 — 실제로 표지의 단추 규칙이 지면(1536px) 대신 왼쪽 칸(491px)을 보고 넓은
	   화면에서 단추를 세로로 쌓았다(지문 비교로 발견). 이름을 쓰면 그 사고가 구조적으로 없다. */
	container: page / inline-size;
	padding-inline: max(var(--gutter), calc((100% - var(--page-max)) / 2));
	/* 셸과 본문 사이 — 위아래 **양쪽 다 여기서** 낸다. 화면 CSS 가 첫·마지막 구획에
	   패딩을 주는 방식이면 화면마다 값이 갈리고, 페이지 CSS 가 없는 화면(상세)은
	   아예 0 이 된다. 지면이 내면 어느 화면이든 같다.

	   («상세만 위가 14px 넓다» 는 지난 기록은 해소됐다 — 그 화면에 페이지 CSS 가 없어
	   `<p>` 가 브라우저 기본 여백(1em)을 쓰고 있던 것이고, `detail.css` 가 그 여백을
	   지우면서 세 화면이 같아졌다.) */
	padding-block: var(--gap-shell);
}
