/* microlab 디자인 시스템 전역 스타일 — website 레포에서 이식.
   FOUC 방지를 위해 index.html <head> 에서 <link> 로 로드한다. JS 에서 import 금지. */

@import url('/fonts/pretendard/pretendard-variable.css');
@import url('/fonts/d2coding/d2coding.css');

@font-face {
  font-family: 'Press Start 2P';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url('/fonts/press-start-2p/press-start-2p-latin-400-normal.woff2') format('woff2');
  /* U+0020 만 빼고 전부. 이 한 줄이 픽셀 폰트 한글 제목의 낱말 사이가 한 글자만큼
     벌어지던 원인을 없앤다 — 한글 글리프는 Galmuri11 로 떨어지는데 공백은 목록
     첫 폰트인 여기서 그려졌고, 그 공백이 1em 이라 한글 한 글자와 폭이 거의 같았다.
     unicode-range 는 "이 폰트를 쓸 수 있는 코드포인트" 지 "이 폰트가 가진 글리프"가
     아니라서, 범위를 넓게 두어도 없는 글리프는 다음 폰트로 넘어간다. */
  unicode-range: U+0-1F, U+21-10FFFF;
}

/* 한글 픽셀 폰트 — 픽셀 컨텍스트의 한글 폴백 */
@font-face {
  font-family: 'Galmuri11';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/galmuri/Galmuri11.woff2') format('woff2');
  /* U+0020 포함 — 위 Press Start 2P 가 공백을 내려놓았으므로 여기서 받는다. */
  unicode-range: U+0020, U+1100-11FF, U+3000-303F, U+3130-318F, U+A960-A97F, U+AC00-D7A3, U+D7B0-D7FF;
}

:root {
  color-scheme: dark;

  /* surface */
  --color-bg: #0a0e17;
  --color-bg-alt: #111827;
  --color-bg-card: #1a1f2e;
  --color-border: #2a3142;

  /* brand */
  --color-primary: #7dffb3;
  --color-primary-dim: #5ce396;
  --color-accent: #7dd3fc;

  /* text */
  --color-text: #e2e8f0;
  --color-text-dim: #94a3b8;
  --color-text-muted: #64748b;

  /* status */
  --color-danger: #f87171;

  /* type */
  --font-pixel: 'Press Start 2P', 'Galmuri11', monospace;
  --font-body: 'Pretendard Variable', Pretendard, system-ui, sans-serif;
  /* 한글 폴백(Pretendard)이 마지막에 있어야 한다 — 앞의 세 폰트는 전부 한글
     글리프가 없어서, 한국어 시스템 폰트가 없는 환경(리눅스 서버, 일부
     외국 사용자 기기)에서 mono 컨텍스트의 한글이 통째로 사라진다. 폭 0 도
     tofu 도 아니고 그냥 안 보여서, 색만 남고 글자가 없는 화면이 된다.
     자체호스팅이라 시스템에 무엇이 깔려 있든 항상 그려진다.

     generic monospace **뒤에** 둔다. 앞에 두면 ui-monospace·SFMono·Menlo 가
     하나도 없는 환경(리눅스·윈도우)에서 숫자까지 Pretendard 비례폭으로
     떨어져 자릿수 정렬이 깨진다. CSS 폰트 매칭은 글자 단위라, generic
     monospace 가 못 그리는 한글만 뒤의 Pretendard 로 넘어간다. */
  /* D2Coding 이 맨 앞이어야 한다 — 한글 advance 가 라틴의 정확히 2배로 설계된
     폰트라, 라틴만 다른 고정폭에서 오면 그 2배 관계가 깨져 정렬이 안 맞는다.
     뒤의 Pretendard 는 D2Coding 에 없는 글자(이모지 등)를 위한 폴백으로 남긴다. */
  --font-mono: 'D2Coding', ui-monospace, SFMono-Regular, Menlo, monospace, 'Pretendard Variable', Pretendard;

  /* effects */
  --grid-line: color-mix(in srgb, var(--color-primary) 4%, transparent);
  --t-color: 0.2s;
  --t-transform: 0.15s ease;

  /* angled-cut */
  --ac-cut: 20px;
  --ac-border: 1px;
  --ac-border-color: var(--color-border);
  --ac-bg: var(--color-bg-card);
  --ac-diagonal-adjust: -0.7;
}

/* ── 라이트 테마 ──
   헤더 토글로 옵트인한다(html[data-theme="light"]). 다크가 기본이다.
   단순 반전이 아니라 브랜드 색을 어둡게 옮긴다 — 민트 #7dffb3 는 흰 배경에서
   대비가 안 나온다. 값은 website 레포의 라이트 팔레트와 동일하다. */
:root[data-theme='light'] {
  color-scheme: light;

  /* surface */
  --color-bg: #f6f9f7;
  --color-bg-alt: #eaf0ec;
  --color-bg-card: #ffffff;
  --color-border: #d3ddd5;

  /* brand */
  --color-primary: #087a4b;
  --color-primary-dim: #06603b;
  --color-accent: #0270a8;

  /* text */
  --color-text: #1d2733;
  --color-text-dim: #4a5a6e;
  --color-text-muted: #6d7b8c;

  /* status — website 에 없는 토큰이라 여기서 정한다.
     다크의 #f87171 은 밝은 배경에서 AA 대비를 못 맞춘다. */
  --color-danger: #b91c1c;

  /* effects */
  --grid-line: color-mix(in srgb, var(--color-primary) 6%, transparent);
}

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

html {
  word-spacing: 0.02em;
  letter-spacing: 0.02em;
  /* 스크롤바 자리를 항상 비워둔다. 내용이 길어져 스크롤바가 생기는 순간
     뷰포트가 좁아지면서 화면 전체가 좌우로 밀리는 레이아웃 시프트(CLS)가
     발생하는데, 이걸로 막는다. website 레포와 동일한 처리. */
  scrollbar-gutter: stable;
}

body {
  font-family: var(--font-body);
  background-color: var(--color-bg);
  /* signature: 아주 옅은 민트 그래프 배경 */
  background-image:
    linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
  background-size: 32px 32px;
  color: var(--color-text);
  line-height: 1.6;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}

/* scrollbar-gutter 미지원 브라우저(구형 Safari) 폴백.
   overflow-y: scroll 은 스크롤바 자리를 항상 차지하게 만든다. 단점처럼 보이지만
   이 블록이 켜지는 환경과 단점이 나타나는 환경이 겹치지 않는다 — 클래식 스크롤바를
   쓰는 Chrome·Firefox·Edge 는 scrollbar-gutter 를 지원하므로 여기 들어오지 않고,
   여기 들어오는 구형 Safari 는 macOS·iOS 기본이 오버레이 스크롤바라 자리를 안 먹는다.
   즉 CLS 가 실제로 일어나는 환경(스크롤바 항상 표시 설정)에서만 효과가 있다. */
@supports not (scrollbar-gutter: stable) {
  html {
    overflow-y: scroll;
  }
}

::selection { background: var(--color-primary); color: var(--color-bg); }

a { color: var(--color-primary); text-decoration: none; transition: color var(--t-color); }
a:hover { color: var(--color-accent); }
img { max-width: 100%; height: auto; }

footer { padding: 2.5rem 0; margin-top: auto; }

/* ── label: 픽셀 대문자 캡션 ── */
.label {
  font-family: var(--font-pixel);
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-dim);
  display: inline-block;
}

/* ── angled-cut 시스템 (website 이식) ──
   .angled-cut / -sm / -xs / -lg 를 요소에 추가. --ac-bg 로 채움색,
   --ac-border-color 로 테두리색 조정. .angled-cut-interactive 는 hover 강조. */
.angled-cut,
.angled-cut-sm,
.angled-cut-xs,
.angled-cut-lg,
.angled-cut-interactive {
  --ac-cut: 20px;
  --ac-border: 1px;
  --ac-border-color: var(--color-border);
  --ac-bg: var(--color-bg-card);
  position: relative;
  background: transparent !important;
  border: none !important;
  border-radius: 0 !important;
  isolation: isolate;
}

.angled-cut-sm { --ac-cut: 10px; }
.angled-cut-xs { --ac-cut: 5px; }
.angled-cut-lg { --ac-cut: 32px; }

/* 폼 컨트롤(input·select·textarea)은 대체요소라 브라우저가 ::before/::after 를
   **생성하지 않는다.** 위 규칙이 background 와 border 를 !important 로 지우는데
   상자를 그릴 의사요소가 없으니, angled-cut 을 붙인 입력칸은 배경도 테두리도 없이
   글자만 떠 있게 된다 — 실제로 그렇게 배포돼 있었다(격리 확인: input·select·
   textarea 의 ::before width 가 auto, button 만 67.78px).

   그래서 이들에게는 진짜 background·border 를 돌려주고 모서리는 clip-path 로
   직접 자른다. 잘린 대각선에는 테두리선이 없지만 --ac-cut 이 5~10px 이라
   눈에 띄지 않는다. <button> 은 의사요소가 정상이므로 여기서 제외한다. */
input.angled-cut,
input.angled-cut-sm,
input.angled-cut-xs,
input.angled-cut-lg,
select.angled-cut,
select.angled-cut-sm,
select.angled-cut-xs,
select.angled-cut-lg,
textarea.angled-cut,
textarea.angled-cut-sm,
textarea.angled-cut-xs,
textarea.angled-cut-lg {
  background: var(--ac-bg) !important;
  border: var(--ac-border) solid var(--ac-border-color) !important;
  clip-path: polygon(
    0 0,
    calc(100% - var(--ac-cut)) 0,
    100% var(--ac-cut),
    100% 100%,
    var(--ac-cut) 100%,
    0 calc(100% - var(--ac-cut))
  );
}


.angled-cut::before, .angled-cut::after,
.angled-cut-sm::before, .angled-cut-sm::after,
.angled-cut-xs::before, .angled-cut-xs::after,
.angled-cut-lg::before, .angled-cut-lg::after,
.angled-cut-interactive::before, .angled-cut-interactive::after {
  content: '';
  position: absolute;
  pointer-events: none;
  transition: background 0.25s ease, inset 0.25s ease;
}

.angled-cut::before,
.angled-cut-sm::before,
.angled-cut-xs::before,
.angled-cut-lg::before,
.angled-cut-interactive::before {
  inset: 0;
  background: var(--ac-border-color);
  clip-path: polygon(
    0 0,
    calc(100% - var(--ac-cut)) 0,
    100% var(--ac-cut),
    100% 100%,
    var(--ac-cut) 100%,
    0 calc(100% - var(--ac-cut))
  );
  z-index: -2;
}

.angled-cut::after,
.angled-cut-sm::after,
.angled-cut-xs::after,
.angled-cut-lg::after,
.angled-cut-interactive::after {
  top: var(--ac-border);
  left: var(--ac-border);
  right: var(--ac-border);
  bottom: var(--ac-border);
  background: var(--ac-bg);
  clip-path: polygon(
    0 0,
    calc(100% - var(--ac-cut) - var(--ac-border) * var(--ac-diagonal-adjust)) 0,
    100% calc(var(--ac-cut) + var(--ac-border) * var(--ac-diagonal-adjust)),
    100% 100%,
    calc(var(--ac-cut) + var(--ac-border) * var(--ac-diagonal-adjust)) 100%,
    0 calc(100% - var(--ac-cut) - var(--ac-border) * var(--ac-diagonal-adjust))
  );
  z-index: -1;
}

.angled-cut-interactive {
  cursor: pointer;
  transition: transform 0.15s ease;
}
.angled-cut-interactive:hover {
  --ac-border: 2px;
  --ac-border-color: var(--color-primary);
}
.angled-cut-interactive:active { transform: translateY(1px); }

/* ── buttons ── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.7rem 1.4rem;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.5px;
  color: var(--color-text-dim);
  cursor: pointer;
  transition: transform var(--t-transform), color var(--t-color);
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-primary {
  --ac-bg: var(--color-primary);
  --ac-border-color: var(--color-primary);
  color: var(--color-bg);
}
.btn-primary:hover {
  --ac-bg: var(--color-primary-dim);
  --ac-border-color: var(--color-primary-dim);
}

.btn-ghost:hover {
  --ac-border-color: var(--color-primary);
  color: var(--color-primary);
}

/* ── tools 레이아웃 ── */
.wrap {
  width: 100%;
  max-width: 56rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

/* 스크린리더 전용 텍스트. 화면에서는 안 보이지만 접근성 이름에는 들어간다.
   display:none 이나 visibility:hidden 은 접근성 트리에서도 빠지므로 쓸 수 없다. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.site-header {
  /* 도구 패널(position:absolute)의 기준 박스. 패널이 <details> 안에 있어도
     <details> 자체는 static 이라 여기에 붙는다 → 패널 폭이 헤더 폭과 같아진다. */
  position: relative;
  border-bottom: 1px solid var(--color-border);
  padding: 1rem 0;
}
/* 자식 결합자여야 한다 — 패널 안쪽에서도 .wrap 을 쓰므로 후손 선택자면 패널까지 flex 가 된다. */
.site-header > .wrap {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
.site-header .home {
  font-family: var(--font-pixel);
  /* 사이트 이름이 한글이라 Press Start 2P 에 글리프가 없고 Galmuri11 로 떨어진다.
     예전 값(0.7rem / letter-spacing 0.18em / uppercase)은 라틴 로고 'microlab image'
     에 맞춘 것이었다: uppercase 는 한글에 아무 일도 하지 않고, 0.18em 자간은 한글
     8자를 낱글자처럼 흩어놓는다. 0.75rem 은 12px 정수라 Galmuri11(11px 설계)이
     덜 뭉개지고, 자간은 픽셀 폰트의 답답함만 풀 만큼만 남긴다. */
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  line-height: 1.4;
  white-space: nowrap;
}

/* ── 도구 전체 패널 ── */
.site-nav {
  /* 트리거와 테마 토글을 오른쪽에 붙여 둔다. margin-left:auto 가 둘 다에 있으면
     남는 공간이 나뉘어 사이가 벌어지므로 여기에만 둔다. */
  margin-left: auto;
}

.site-nav-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  height: 34px;
  padding: 0 0.65rem;
  border: 1px solid var(--color-border);
  color: var(--color-text-dim);
  font-size: 0.78rem;
  cursor: pointer;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--t-color), border-color var(--t-color);
  /* 기본 삼각형 마커 제거 — 아이콘을 직접 그린다. */
  list-style: none;
}
.site-nav-trigger::-webkit-details-marker { display: none; }
.site-nav-trigger::marker { content: ''; }
.site-nav-trigger:hover,
.site-nav-trigger:focus-visible,
.site-nav[open] > .site-nav-trigger {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.site-nav-trigger svg { flex: none; }
.site-nav .icon-close { display: none; }
.site-nav[open] .icon-menu { display: none; }
.site-nav[open] .icon-close { display: block; }

.site-nav-panel {
  position: absolute;
  top: calc(100% + 1px); /* 헤더 아래 테두리 바로 밑 */
  left: 0;
  right: 0;
  /* 본문 위에 뜬다. .site-header 는 z-index 가 auto 라 쌓임 맥락을 만들지 않으므로
     이 값은 루트에서 비교되고, 위치 지정되지 않은 <main> 보다 항상 위에 그려진다. */
  z-index: 50;
}
.site-nav-sheet {
  --ac-bg: var(--color-bg-alt);
  /* 시트가 높이를 받고 목록이 남은 만큼 늘어난다. 예전에는 안쪽 목록에만 상한을 두고
     시트 패딩을 3rem 상수로 빼 뒀는데, 목록 위에 검색칸과 건너뛰기 줄이 얹히면서
     그 상수가 더는 맞지 않는다. 시트 쪽에 두면 위에 무엇을 더 얹어도 아래끝이
     뷰포트를 넘지 않는다.
     헤더 높이는 사이트 이름 길이와 화면 폭에 따라 한 줄이 되기도 두 줄이 되기도 해서
     (360px 에서 67px → 113px) 상수로 못 맞춘다 — SiteHeader 의 스크립트가 재서
     --site-header-h 로 넘긴다. JS 가 없으면 7rem 이 쓰인다 — 한 줄 헤더는 4.25rem 이지만,
     이름이 길어 두 줄로 감기면 113px(=7.06rem)까지 커진다. 폴백은 넉넉한
     쪽이 맞다: 패널이 조금 짧아지는 건 괜찮지만 화면 밖으로 나가면 안 된다.
     1.25rem 은 시트 아래 여백. 48rem 상한은 아주 큰 화면에서 한 덩어리가 지나치게
     길어지지 않게 하는 것이고, 목록 몫으로 치면 예전의 44rem 과 비슷하다. */
  display: flex;
  flex-direction: column;
  max-height: min(calc(100svh - var(--site-header-h, 7rem) - 1.25rem), 48rem);
  padding: 1.25rem;
}

/* ── 패널 검색칸 ──
   JS 가 없으면 마크업에 hidden 이 붙은 채로 남아 아예 나오지 않는다. */
.site-nav-find {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex: none;
  margin-bottom: 0.7rem;
}
.site-nav-q {
  flex: 1 1 auto;
  min-width: 0;
  height: 2.4rem;
  padding: 0 0.6rem;
  appearance: none;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 0;
  color: var(--color-text);
  font-family: inherit;
  font-size: 0.85rem;
  transition: border-color var(--t-color);
}
.site-nav-q::placeholder { color: var(--color-text-muted); }
.site-nav-q:focus { border-color: var(--color-primary); }
/* WebKit 이 type=search 에 붙이는 기본 지우기 버튼. 테마 색을 따르지 않아 라이트에서
   튀고, Escape 와 역할이 겹친다. */
.site-nav-q::-webkit-search-cancel-button { appearance: none; }
.site-nav-result {
  flex: none;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* ── 그룹 건너뛰기 칩 ──
   검색어가 떠오르지 않을 때 60개를 훑어 내리는 대신 한 번에 그 사이트로 간다.
   조각 링크라 JS 없이도 동작한다. 검색 중에는 감춘다 — 남은 결과가 몇 개뿐인데
   "여기로 건너뛰기" 를 권할 이유가 없고, 비어서 접힌 그룹을 가리킬 수도 있다. */
.site-nav-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  flex: none;
  margin-bottom: 0.8rem;
}
.site-nav-jump a {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 1.9rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--color-border);
  color: var(--color-text-dim);
  font-size: 0.75rem;
  line-height: 1.4;
  transition: color var(--t-color), border-color var(--t-color);
}
.site-nav-jump a:hover,
.site-nav-jump a:focus-visible {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.site-nav-jump-count {
  font-family: var(--font-mono);
  /* 고정폭에서는 자간을 되돌린다 — html 의 0.02em 이 글자마다 같은 값으로
     더해져 한글 1칸(2배 폭)과 라틴 2칸의 관계를 깨뜨린다. */
  letter-spacing: normal;
  word-spacing: normal;
  color: var(--color-text-muted);
}
/* 손가락으로 누르는 환경에서만 44px 목표까지 키운다. */
@media (pointer: coarse) {
  .site-nav-jump a {
    min-height: 2.75rem;
    padding-inline: 0.8rem;
  }
}
.site-nav-sheet[data-filtering='true'] .site-nav-jump { display: none; }

/* 스크롤은 반드시 안쪽 요소가 맡는다. angled-cut 은 ::before/::after 를 inset:0 으로
   깔기 때문에, 스크롤 컨테이너가 되면 그 배경이 내용과 함께 밀려 올라간다. */
.site-nav-scroll {
  /* flex 항목의 기본 min-height 는 auto 라, 이걸 0 으로 두지 않으면 내용만큼 늘어나
     시트의 max-height 를 뚫고 나간다. */
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* 더 있다는 걸 알려야 한다 — 오버레이 스크롤바만 있는 환경에서는 잘린 것처럼 보인다. */
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

/* 검색이 그룹과 항목에 hidden 을 단다. UA 기본값에 기대지 않고 못박아 둔다 —
   여기 display 를 주는 규칙이 하나라도 생기면 hidden 이 조용히 무력해진다. */
/* 저자 스타일시트의 display 가 UA 의 [hidden]{display:none} 를 이긴다. 검색칸은
   JS 가 없으면 hidden 으로 나가는데, .site-nav-find 의 display:flex 때문에
   그대로 그려져 아무 반응 없는 입력칸이 남아 있었다 — 네 레포 전부. */
.site-nav-find[hidden],
.nav-group[hidden],
.nav-group-list > li[hidden] { display: none; }

/* 인접 결합자(+)가 아니라 일반 형제 결합자(~)여야 한다. 검색으로 앞 그룹이 접히면
   + 는 "바로 앞 형제" 를 못 찾아 구분선이 사라지고, 반대로 접힌 그룹 뒤에도 선이
   남는 조합이 생긴다. ~ 는 "앞에 보이는 그룹이 하나라도 있는가" 를 묻는다. */
.nav-group:not([hidden]) ~ .nav-group:not([hidden]) {
  margin-top: 1.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--color-border);
}
.nav-group-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  /* 건너뛰기 칩으로 왔을 때 머리말이 목록 맨 위에 딱 붙지 않게 — 초점 테두리가 잘린다. */
  scroll-margin-top: 0.4rem;
}
/* 건너뛰기 칩이 초점을 여기로 옮긴다(tabindex=-1). 어디로 갔는지 보여야 한다. */
.nav-group-head:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
.nav-group-name {
  font-family: var(--font-pixel);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  line-height: 1.5;
  color: var(--color-primary);
}
.nav-group-badge {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 0.15rem 0.4rem;
  background: var(--color-primary);
  color: var(--color-bg);
}
.nav-group-host {
  font-family: var(--font-mono);
  /* 고정폭에서는 자간을 되돌린다 — html 의 0.02em 이 글자마다 같은 값으로
     더해져 한글 1칸(2배 폭)과 라틴 2칸의 관계를 깨뜨린다. */
  letter-spacing: normal;
  word-spacing: normal;
  font-size: 0.72rem;
  color: var(--color-text-muted);
}
.nav-group-host:hover,
.nav-group-host:focus-visible { color: var(--color-primary); }
.nav-group-blurb {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  margin-top: 0.2rem;
}

.nav-group-list {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
  gap: 0 0.5rem;
  margin-top: 0.5rem;
}
.nav-group-list > li { min-width: 0; }
.nav-group-list a {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 2.75rem; /* 손가락 목표 44px */
  padding: 0.35rem 0.5rem;
  color: var(--color-text-dim);
  font-size: 0.85rem;
  line-height: 1.35;
}
.nav-group-list a:hover,
.nav-group-list a:focus-visible {
  color: var(--color-primary);
  background: var(--color-bg-card);
}
.nav-group-list a[aria-current='page'] {
  color: var(--color-primary);
  font-weight: 600;
}
.nav-item-title { min-width: 0; }

/* 데스크톱에서는 줄 간격을 조인다. 44px 은 손가락 목표라 포인터가 정밀한 환경에는
   필요 없고, 그대로 두면 도구가 39개인 지금 세 번째 그룹이 제목만 남는다(실제로
   비디오 그룹의 도구가 한 개도 안 보였다). 열도 하나 더 들어가게 최소폭을 줄인다.
   모바일은 손대지 않는다 — 한 줄 배치라 스크롤이 자연스럽고, 목표 크기가 중요하다. */
@media (min-width: 40rem) and (pointer: fine) {
  .nav-group-list { grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); }
  .nav-group-list a {
    min-height: 2.1rem;
    padding: 0.25rem 0.5rem;
  }
}

/* 내용이 넘칠 때만 아래쪽에 페이드를 깔아 "더 있다"를 보이게 한다. 오버레이
   스크롤바만 있는 환경에서는 스크롤바가 안 보여서 잘린 게 아니라 끝난 것처럼
   읽힌다 — 실제로 그렇게 보였다. 넘치는지 여부는 SiteHeader 의 스크립트가
   재서 data-scrollable 로 알려준다(CSS 만으로는 알 수 없다). */
.site-nav-scroll[data-scrollable='true'] {
  mask-image: linear-gradient(to bottom, #000 calc(100% - 2.5rem), transparent 100%);
}
.nav-item-ext {
  /* 제목 바로 뒤에 붙인다. 오른쪽 끝으로 밀면(margin-left:auto) 넓은 칸에서
     화살표가 제목과 멀어져 무엇에 붙은 표시인지 읽히지 않는다. */
  flex: none;
  font-size: 0.7rem;
  color: var(--color-text-muted);
}
.nav-group-list a:hover .nav-item-ext,
.nav-group-list a:focus-visible .nav-item-ext { color: var(--color-primary); }

/* ── 테마 토글 ── */
.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex: none;
  background: none;
  border: 1px solid var(--color-border);
  color: var(--color-text-dim);
  cursor: pointer;
  transition: color var(--t-color), border-color var(--t-color);
  -webkit-tap-highlight-color: transparent;
}
.theme-toggle:hover,
.theme-toggle:focus-visible {
  color: var(--color-primary);
  border-color: var(--color-primary);
}
/* 다크에서는 해(누르면 라이트), 라이트에서는 달(누르면 다크) */
.theme-toggle .icon-moon { display: none; }
:root[data-theme='light'] .theme-toggle .icon-sun { display: none; }
:root[data-theme='light'] .theme-toggle .icon-moon { display: block; }

.tool-main { flex: 1; padding: 2.5rem 0 4rem; }

.tool-title {
  font-family: var(--font-pixel);
  font-size: clamp(1rem, 3.4vw, 1.55rem);
  font-weight: 400;
  line-height: 1.5;
  color: var(--color-primary);
  margin-bottom: 1.25rem;
}

/* 브라우저 내 처리 고지 — microlab 도구의 상시 노출 요소 */
.privacy-notice {
  --ac-bg: var(--color-bg-alt);
  --ac-border-color: var(--color-border);
  padding: 0.7rem 1rem;
  font-size: 0.82rem;
  color: var(--color-text-dim);
  margin-bottom: 1.75rem;
}
.privacy-notice strong { color: var(--color-primary); font-weight: 600; }

/* 도구 아일랜드 영역과 본문 영역을 분리해 둔다. 나중에 광고 슬롯이 들어오면
   본문 영역 위/아래에만 붙이고 도구 영역은 건드리지 않는다. */
.tool-stage { margin-bottom: 3rem; }
.tool-doc { margin-bottom: 3rem; }

.tool-doc h2 {
  font-family: var(--font-pixel);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  color: var(--color-text-dim);
  text-transform: uppercase;
  margin: 2rem 0 0.9rem;
  font-weight: 400;
}
.tool-doc ol, .tool-doc ul { padding-left: 1.2rem; color: var(--color-text-dim); }
.tool-doc li { margin-bottom: 0.4rem; }
.tool-doc details {
  border-top: 1px solid var(--color-border);
  padding: 0.75rem 0;
}
.tool-doc summary { cursor: pointer; color: var(--color-text); }
.tool-doc details p { color: var(--color-text-dim); padding-top: 0.5rem; }

.tool-related { border-top: 1px solid var(--color-border); padding-top: 1.5rem; }
.tool-related h2 {
  font-family: var(--font-pixel);
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-text-dim);
  font-weight: 400;
  margin-bottom: 0.9rem;
}

/* 허브 */
.hub-intro { padding: 3rem 0 2rem; }
.hub-intro h1 {
  font-family: var(--font-pixel);
  font-size: clamp(1.1rem, 4vw, 1.8rem);
  font-weight: 400;
  line-height: 1.4;
  color: var(--color-primary);
  margin-bottom: 0.9rem;
}
.hub-intro p { color: var(--color-text-dim); max-width: 34rem; }

.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1rem;
  padding-bottom: 4rem;
}
.tool-card { display: block; padding: 1.25rem; color: inherit; }
.tool-card h2 {
  font-size: 1rem;
  color: var(--color-primary);
  margin-bottom: 0.45rem;
  font-weight: 600;
}
.tool-card p { font-size: 0.85rem; color: var(--color-text-dim); }

.site-footer { padding: 2.5rem 0; margin-top: auto; text-align: center; }
