/*
 * Layout — 사이드바 셸과 본문 컬럼
 *
 * 데스크톱(48em 이상): 사이드바가 좌측 고정, 본문이 그만큼 밀린다.
 * 모바일: 사이드바가 화면 밖에서 슬라이드로 덮는다(오버레이).
 *
 * 접힘 상태는 <html>의 `.sidebar-hidden` 클래스로 표현하고,
 * head의 인라인 스크립트가 페인트 전에 복원한다.
 */

/* ── 사이드바 ──────────────────────────────────────────────── */

.sidebar {
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  width: var(--sidebar-width);
  padding: var(--sidebar-pad);
  overflow: hidden;
  background-color: var(--color-surface-sidebar);
  border-right: 1px solid var(--color-border-subtle);
  transition: transform var(--transition-slow), background-color var(--transition-slow);
}

/* 사이드바 상단 — 워드마크와 아이콘 버튼 행 */
.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs);
  padding: var(--space-xxs) var(--nav-item-pad-x) var(--space-sm);
}

.sidebar-brand {
  min-width: 0;
  margin: 0;
  font-size: var(--font-size-body);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
  line-height: 1.2;
}

.sidebar-brand a {
  color: var(--color-text-strong);
  white-space: nowrap;
}

.sidebar-brand a:hover {
  text-decoration: none;
}

.sidebar-tagline {
  display: block;
  margin-top: 1px;
  color: var(--color-text-faint);
  font-family: var(--font-mono);
  font-size: var(--font-size-meta);
  font-weight: var(--weight-body);
  letter-spacing: var(--tracking-meta);
}

.sidebar-actions {
  display: flex;
  flex-shrink: 0;
  gap: 2px;
}

/* 사이드바 본체 — 넘칠 때만 스크롤 */
.sidebar-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* 스크롤바는 hover에서만 드러낸다 */
.sidebar-body {
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}

.sidebar-body:hover {
  scrollbar-color: var(--color-border-strong) transparent;
}

.sidebar-body::-webkit-scrollbar {
  width: 6px;
}

.sidebar-body::-webkit-scrollbar-thumb {
  background-color: transparent;
  border-radius: var(--radius-pill);
}

.sidebar-body:hover::-webkit-scrollbar-thumb {
  background-color: var(--color-border-strong);
}

/* ── 네비게이션 — 알약형 항목 ───────────────────────────────── */

.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sidebar-nav li + li {
  margin-top: 0;
}

.nav-item {
  display: block;
  padding: var(--nav-item-pad-y) var(--nav-item-pad-x);
  overflow: hidden;
  color: var(--color-text);
  font-size: var(--font-size-sm);
  line-height: 1.45;
  white-space: nowrap;
  text-overflow: ellipsis;
  border-radius: var(--radius-md);
  transition: background-color var(--transition), color var(--transition);
}

.nav-item:hover,
.nav-item:focus-visible {
  color: var(--color-text-strong);
  background-color: var(--color-surface-hover);
  text-decoration: none;
}

.nav-item[aria-current] {
  color: var(--color-text-strong);
  background-color: var(--color-surface-active);
  font-weight: var(--weight-medium);
}

/* 섹션 라벨 — 모노 대문자 */
.sidebar-label {
  margin: var(--space-lg) 0 var(--space-xxs);
  padding: 0 var(--nav-item-pad-x);
  color: var(--color-text-faint);
  font-family: var(--font-mono);
  font-size: var(--font-size-meta);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
}

/* 최근 글 목록 — 제목을 두 줄까지 보여준다.
 *
 * `.nav-item`은 한 줄 전제(nowrap + ellipsis)라서 여기서 되돌린다. */
.nav-item-post {
  white-space: normal;
  text-overflow: clip;
}

/* 클램프는 <a>가 아니라 패딩 없는 안쪽 span에 건다.
 *
 * 클램프된 상자는 **패딩 박스**에서 잘린다. 패딩을 가진 <a>에 직접 걸면 세 번째
 * 줄이 아래 패딩 영역에 얇게 비쳐서, 다음 항목과 겹쳐 보인다. 안쪽 span은
 * 패딩이 없어 잘리는 경계가 텍스트 끝과 같다.
 *
 * `-webkit-box`를 `flow-root`로 블록화하는 엔진에서도 `max-height`가 같은
 * 두 줄 높이를 보장하므로, 클램프가 무시되더라도 결과가 같다. */
.nav-item-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* .nav-item의 line-height와 같은 값이어야 두 줄이 정확히 맞는다 */
  max-height: calc(2 * 1.45em);
}

/* ── 아이콘 버튼 ───────────────────────────────────────────── */

.icon-btn {
  display: grid;
  place-items: center;
  width: var(--icon-btn-size);
  height: var(--icon-btn-size);
  padding: 0;
  color: var(--color-text-muted);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background-color var(--transition), color var(--transition);
}

.icon-btn:hover,
.icon-btn:focus-visible {
  color: var(--color-text-strong);
  background-color: var(--color-surface-hover);
}

.icon-btn svg {
  width: var(--icon-size);
  height: var(--icon-size);
  margin: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* 테마 토글 — 현재 테마의 아이콘만 보인다 */
.icon-sun {
  display: none;
}

:root[data-theme="dark"] .icon-sun {
  display: block;
}

:root[data-theme="dark"] .icon-moon {
  display: none;
}

/* 사이드바가 접혔을 때 다시 열기 위한 버튼. 열려 있으면 사이드바 안쪽
 * 버튼이 그 역할을 하므로 숨긴다. */
.sidebar-reveal {
  position: fixed;
  top: var(--space-sm);
  left: var(--space-sm);
  z-index: 50;
  display: none;
  background-color: var(--color-surface);
}

/* ── 글 목차 ───────────────────────────────────────────────── */

/*
 * 사이드바를 접으면 같은 레일에 이 글의 절 목록이 들어온다. 그래서 왼쪽 열은
 * 항상 무언가를 안내한다 — 사이트 아니면 지금 읽는 글. 폭이 사이드바와 같아
 * 두 상태를 오가도 본문이 다시 흐르지 않는다.
 *
 * 기본값은 숨김이다. 데스크톱에서 사이드바가 접혔을 때, 그리고 모바일에서
 * 글 흐름 안에 얹힐 때만 드러난다.
 */
.outline {
  display: none;
}

.outline-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-xs);
  padding: var(--space-xxs) var(--nav-item-pad-x) var(--space-sm);
}

.outline-label {
  margin: 0;
  color: var(--color-text-faint);
  font-family: var(--font-mono);
  font-size: var(--font-size-meta);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
}

/* 접기 버튼은 모바일 전용이다 — 데스크톱 레일에서는 목차가 늘 펼쳐져 있다 */
.outline-toggle {
  display: none;
}

.outline-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}

.outline-body:hover {
  scrollbar-color: var(--color-border-strong) transparent;
}

.outline-body::-webkit-scrollbar {
  width: 6px;
}

.outline-body::-webkit-scrollbar-thumb {
  background-color: transparent;
  border-radius: var(--radius-pill);
}

.outline-body:hover::-webkit-scrollbar-thumb {
  background-color: var(--color-border-strong);
}

.outline-list,
.outline-sub {
  margin: 0;
  padding: 0;
  list-style: none;
}

.outline-list > li + li {
  margin-top: 0;
}

/* 항목 — 번호는 고정 폭 거터에, 제목은 그 오른쪽에.
 * 번호 없는 절(TL;DR·시작하며·마치며)은 거터를 비워두므로 제목의 왼쪽 끝이
 * 번호 유무와 무관하게 한 줄로 맞는다. */
.outline-link {
  display: grid;
  grid-template-columns: var(--toc-num-width) 1fr;
  padding: var(--nav-item-pad-y) var(--nav-item-pad-x);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: 1.45;
  border-radius: var(--radius-md);
  transition: color var(--transition), background-color var(--transition);
}

.outline-link:hover,
.outline-link:focus-visible {
  color: var(--color-text-strong);
  background-color: var(--color-surface-hover);
  text-decoration: none;
}

.outline-num {
  color: var(--color-text-faint);
  font-family: var(--font-mono);
  font-size: var(--font-size-meta);
  font-variant-numeric: tabular-nums;
  /* 모노 숫자는 본문보다 작아서 baseline이 어긋난다 — 한 줄 안에서 맞춘다 */
  line-height: 1.7;
}

.outline-text {
  min-width: 0;
}

/* 현재 읽는 절 */
.outline-link[aria-current] {
  color: var(--color-text-strong);
  font-weight: var(--weight-medium);
}

/* 소절을 읽는 동안에도 그 소절이 속한 절의 번호는 켜둔다. 번호가 이 글의
 * 논증 순서라서, 지금 몇 번째 절에 있는지가 목차의 핵심 정보다. */
.outline-item[data-open] > .outline-link .outline-num {
  color: var(--color-accent);
}

.outline-item[data-open] > .outline-link {
  color: var(--color-text-strong);
  font-weight: var(--weight-medium);
}

/* h3는 읽고 있는 절 아래에서만 펼친다. 19줄짜리 목차를 레일에 밀어넣는 대신,
 * 지금 있는 자리의 주변만 보여준다. */
.outline-sub {
  display: none;
  /* 소절은 부모 절의 제목 열에 맞춰 들여쓴다 */
  margin-left: calc(var(--toc-num-width) + var(--nav-item-pad-x));
  border-left: 1px solid var(--color-border-subtle);
}

.outline-item[data-open] > .outline-sub {
  display: block;
}

.outline-item-sub .outline-link {
  grid-template-columns: 1fr;
  padding-top: var(--space-xxs);
  padding-bottom: var(--space-xxs);
  color: var(--color-text-faint);
  font-size: var(--font-size-meta);
}

.outline-item-sub .outline-link:hover,
.outline-item-sub .outline-link:focus-visible,
.outline-item-sub .outline-link[aria-current] {
  color: var(--color-text-strong);
}

/* ── 본문 ──────────────────────────────────────────────────── */

/* 본문 컬럼은 margin-left로 사이드바를 피하고, 안쪽에서 읽기 폭을 잡는다.
 * padding으로 밀면 미디어 쿼리마다 offset을 다시 더해야 해서 어긋나기 쉽다. */
.content {
  padding: var(--space-2xl) var(--space-lg) var(--space-3xl);
  transition: margin var(--transition-slow);
}

/*
 * 읽기 컬럼은 **화면 기준으로** 가운데 온다.
 *
 * `margin: 0 auto`만 두면 사이드바를 뺀 나머지 공간의 가운데에 놓이므로,
 * 화면 전체로 보면 사이드바 폭의 절반만큼 오른쪽으로 밀린다. 1440px에서
 * 왼쪽 499px / 오른쪽 227px, 1920px에서는 739px / 467px까지 벌어졌다.
 *
 * 그래서 왼쪽 여백에서 사이드바 폭의 절반을 덜어낸다 (`auto`가 나머지를 채운다).
 * 넓은 화면에서만 유효한 보정이라, 남는 공간이 없으면 `max()`가 0을 골라
 * 평소처럼 동작한다.
 */
.content-inner {
  max-width: var(--content-max-width);
  margin: 0 auto;
}

@media (min-width: 48em) {
  .content {
    margin-left: var(--content-offset);
    padding-left: var(--space-xl);
    padding-right: var(--space-xl);
  }

  .content-inner {
    /* 화면 가운데에 놓기 위한 왼쪽 여백.
     *
     * 컬럼의 왼쪽 끝이 화면 기준 `(100vw - 읽기폭) / 2`에 오면 가운데다.
     * `.content-inner`의 여백은 사이드바와 좌우 패딩을 이미 지난 자리에서
     * 시작하므로, 그만큼을 뺀 값이 필요한 여백이다.
     *
     * 음수가 되는 좁은 화면에서는 0으로 떨어져 `margin-right: auto`가
     * 남은 공간을 흡수한다 — 기존 동작과 같다. */
    margin-left: max(0px, calc(
      (100vw - var(--content-max-width)) / 2
      - var(--content-offset) - var(--space-xl)
    ));
    margin-right: auto;
  }

  /* 사이드바가 없으면 보정할 것도 없다 */
  .sidebar-hidden .content-inner {
    margin-left: auto;
  }
}

/* ── 접힘 상태 ─────────────────────────────────────────────── */

.sidebar-hidden .sidebar {
  transform: translateX(-100%);
}

.sidebar-hidden .sidebar-reveal {
  display: grid;
}

@media (min-width: 48em) {
  .sidebar-hidden .content {
    margin-left: 0;
  }
}

/*
 * 떠 있는 목차 메뉴 — 사이드바를 접었을 때만, 그리고 옆에 자리가 있을 때만.
 *
 * 경계(`94em`)는 계산에서 나왔다. 메뉴는 본문 왼쪽 여백의 가운데에 놓이므로,
 * 여백이 `메뉴 폭 + 2 × 최소 간격`(238 + 52 = 290px)보다 넓어야 본문에 닿지 않는다.
 * 그 여백이 양쪽에 필요해서 필요한 화면 폭은 `918 + 2 × 290 = 1496px`이다.
 * 이보다 좁으면 흐름 안 배치(아래 `max-width: 93.99em`)로 떨어진다.
 *
 * **주의: 미디어 쿼리의 `em`은 루트 폰트 크기(16px)로 평가된다.** 48em 이상에서
 * 루트가 17px이지만 그건 쿼리 조건에 반영되지 않는다. 그래서 1496px을 17로 나눈
 * `88em`을 쓰면 실제로는 1408px에서 켜져 간격이 3.5px밖에 남지 않는다.
 * 16으로 나눈 `93.5em`을 올림해 `94em`(= 1504px)으로 둔다.
 *
 * 이 값은 미디어 쿼리 조건이라 토큰으로 뺄 수 없다 — `--content-max-width`나
 * `--outline-panel-width`를 바꾸면 이 리터럴도 **16px 기준으로** 다시 계산한다.
 */
@media (min-width: 94em) {
  .sidebar-hidden.has-outline .outline {
    position: fixed;
    top: 50%;
    /* 본문 왼쪽 여백의 가운데. 화면 끝에 붙이면 본문 쪽으로 쏠려 보인다. */
    left: calc(
      ((100vw - var(--content-max-width)) / 2 - var(--outline-panel-width)) / 2
    );
    transform: translateY(-50%);
    z-index: 30;
    display: flex;
    flex-direction: column;
    width: var(--outline-panel-width);
    /* 긴 글에서도 화면을 넘지 않게 — 넘치면 안쪽이 스크롤된다 */
    max-height: calc(100vh - 2 * var(--space-xl));
    padding: var(--space-xs);
    background-color: var(--color-surface-raised);
    border: 1px solid var(--color-border-subtle);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-panel);
  }

  /* 떠 있는 메뉴에서는 머리 라벨을 두지 않는다. 카드 자체가 이미 "본문과
   * 다른 것"으로 읽히고, 항목이 9개뿐이라 무엇인지 바로 보인다.
   * 사이드바로 돌아가는 버튼은 화면 좌상단의 햄버거가 담당한다. */
  .sidebar-hidden.has-outline .outline-head {
    display: none;
  }
}

/* ── 모바일 — 사이드바는 오버레이 ──────────────────────────── */

@media (max-width: 47.99em) {
  .sidebar {
    box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0.32);
    clip-path: inset(0 -100vmax 0 0);
  }

  /* 모바일 기본값은 닫힘. sidebar-open이 붙을 때만 열린다. */
  .sidebar {
    transform: translateX(-100%);
  }

  .sidebar-open .sidebar {
    transform: translateX(0);
  }

  .sidebar-reveal {
    display: grid;
  }

  .sidebar-open .sidebar-reveal {
    display: none;
  }

  .content {
    padding-top: var(--space-3xl);
  }
}

/*
 * 흐름 안 목차 — 떠 있을 자리가 없는 모든 폭.
 *
 * 모바일(레일이 아예 없다)과 중간 폭(1504px 미만, 옆에 자리가 없다)이 같은
 * 문제를 갖는다. 목차를 글 맨 위에 얹되 기본은 접어 한 줄로 둔다 — 19줄짜리
 * 목차를 펼쳐두면 글이 화면 밖으로 밀려난다.
 */
@media (max-width: 93.99em) {
  .outline {
    margin: 0 0 var(--space-xl);
    border-top: 1px solid var(--color-border-subtle);
    border-bottom: 1px solid var(--color-border-subtle);
  }

  /* 머리 부분의 데스크톱 노드 — 라벨은 접기 버튼 안에 자기 것이 있고,
   * 되돌리기 버튼은 모바일에서 할 일이 없다. */
  .outline-head > .outline-label,
  .outline-restore {
    display: none;
  }

  .outline-head {
    padding: 0;
  }

  /* 접힌 상태의 한 줄 — 라벨, 절 개수, 열림 표시 */
  .outline-toggle {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    width: 100%;
    padding: var(--space-sm) var(--nav-item-pad-x);
    color: var(--color-text-muted);
    background: none;
    border: 0;
    border-radius: var(--radius-md);
    cursor: pointer;
    text-align: left;
  }

  .outline-count {
    flex: 1;
    color: var(--color-text-faint);
    font-family: var(--font-mono);
    font-size: var(--font-size-meta);
    font-variant-numeric: tabular-nums;
  }

  .outline-chevron {
    width: var(--icon-size);
    height: var(--icon-size);
    flex-shrink: 0;
    margin: 0;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform var(--transition);
  }

  .outline[data-open] .outline-chevron {
    transform: rotate(180deg);
  }

  .outline-body {
    display: none;
    padding-bottom: var(--space-sm);
  }

  .outline[data-open] .outline-body {
    display: block;
  }

  /* 펼쳤을 때는 절 전체를 보여준다 — 스크롤 위치에 따라 접히면
   * 목록을 훑는 중에 항목이 움직인다. */
  .outline-sub {
    display: block;
  }
}

/* 중간 폭(48~94em) — 사이드바가 화면에 붙어 있으므로, 데스크톱과 같은 규칙으로
 * 사이드바를 접었을 때만 목차가 나온다. 둘 다 보이면 같은 열에 이동 수단이
 * 두 벌 생긴다. */
@media (min-width: 48em) and (max-width: 93.99em) {
  .sidebar-hidden.has-outline .outline {
    display: block;
  }
}

/* 모바일 — 사이드바가 닫힌 오버레이라 항상 목차를 보여준다 */
@media (max-width: 47.99em) {
  .has-outline .outline {
    display: block;
  }
}

/* ── 모션 축소 ─────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
