/* ==========================================================================
 * sidenav.css — 옆에 따라다니는 목차
 * ==========================================================================
 * 화면 오른쪽에 막대가 세로로 쌓이고, 지금 보고 있는 구간만
 * 막대가 길어지며 그 옆에 이름이 나타난다.
 *
 * ── 원본 계측값 (toss.im/tossfeed 에디션 페이지) ────────────────────────
 *   막대   비활성 37×6px · 활성 47×7px · 전환 0.2s
 *          (원본은 모서리 99px 알약이지만 여기서는 각진 직사각으로 바꿨다)
 *   간격   항목 사이 15px
 *   이름   18px / 700 — 활성 항목에만 보인다
 *   원본은 왼쪽에 붙고 세로 가운데쯤(sticky top 500px)에 선다.
 * 여기서는 **오른쪽**에 두므로 막대와 이름의 좌우가 뒤집힌다.
 *
 * ⚠ 이 페이지는 흰 지면과 검은 지면이 번갈아 나온다. 그래서 색을 고정하지 않고
 *   구간의 data-tone 을 읽어 바꾼다(js/mod-sidenav.js 가 .is-on-light 를 붙인다).
 *   한때 mix-blend-mode: difference 로 배경을 반전시켰다. 색을 안 정해도 되니 편했지만,
 *   하늘색(#00AAFF) 사각형 위에서 주황으로 뒤집혀 못 쓴다.
 *   반전은 배경이 한 가지일 때만 쓸 만하다.
 * ========================================================================== */

.sidenav {
  position: fixed;
  right: 32px;
  top: 50%;
  translate: 0 -50%;
  z-index: 30; /* 헤더(50)·메뉴(60)보다 아래, 본문보다는 위 */

  display: flex;
  flex-direction: column;
  align-items: flex-end; /* 오른쪽 정렬 — 막대 끝이 한 줄로 맞는다 */

  /* ★ 막대 사이 간격 바꾸는 곳 ★ 아래 gap 이 곧 **막대와 막대 사이의 빈틈**이다.
     --sidenav-row 를 막대 높이(5px)와 똑같이 맞춰 뒀기 때문에, 줄 높이에 군더더기가 없어
     gap 에 적은 값이 화면에서 그대로 막대 사이 거리가 된다.
     (예전에는 이름칸 18px 이 줄 높이를 정해서, gap 을 0 으로 둬도 18px 씩 벌어졌다)
     ⚠ 아래 .sidenav__item::after 의 호버 영역과 한 세트다 —
       gap 을 줄이면 ::after 의 inset 도 같이 줄여야 이웃 항목과 안 겹친다(한계는 gap 의 절반). */
  --sidenav-row: 3px;
  gap: 12px;

  /* ★ 기본색 ★ 어두운 지면(검정·파랑 구간) 위에 서 있을 때는 흰색.
     밝은 지면에서는 아래 .is-on-light 가 검정으로 바꾼다. */
  color: #ffffff;
  transition: color 0.3s ease;

  /* 목차 자체는 클릭만 받고 스크롤을 막지 않는다 */
  pointer-events: none;

  /* 처음에는 숨어 있다가 정해진 구간에서만 나타난다.
     나타나는 지점은 마크업의 data-sidenav-from / -at,
     사라지는 지점은 data-sidenav-until / -until-at 이 정한다(js/mod-sidenav.js).
     JS 가 죽으면 계속 숨어 있는데, 목차는 없어도 글을 읽는 데 지장이 없으므로
     그게 안전한 실패다.
     ⚠ 여기에 transition 을 걸지 않는다 — 스르륵 나타나지 않고 그 자리에서 바로 뜨는 게 의도다. */
  opacity: 0;
  visibility: hidden;
}

.sidenav.is-visible {
  opacity: 1;
  visibility: visible;
}

/* ★ 밝은 지면(흰 아티클) 위 ★ 검정으로 쓴다. */
.sidenav.is-on-light {
  color: #000000;
}

/* 항목 하나. 막대만 있으면 마우스로 집기가 너무 작아서 이름이 들어갈 자리만큼 폭을 미리 잡아 둔다 —
   그 넓은 가로 영역 전체가 호버 대상이다.
   row-reverse 라 flex-start 가 '오른쪽부터'가 되어 막대 끝이 한 줄로 맞는다.

   height 를 따로 주는 건 간격을 좁히기 위해서다 — 이름칸(18px)이 줄 높이를 정하게 두면
   막대 사이가 18px 밑으로 못 내려간다. 이름은 세로 가운데 정렬이라 넘쳐도 제자리에 보인다. */
.sidenav__item {
  position: relative;
  pointer-events: auto;
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  min-width: 130px;
  height: var(--sidenav-row);
  text-decoration: none;
  color: inherit;
}

/* 세로 호버 여유. 막대가 5px 뿐이라 그대로면 마우스로 집기 어렵다.
   레이아웃을 건드리지 않으려고 가짜 요소로만 넓힌다.
   ⚠ 위아래로 넓힐 수 있는 한계는 gap 의 절반이다 — 더 넓히면 이웃 항목과 겹쳐
     어느 항목에 올린 건지 모호해진다. 지금 gap 이 12px 이므로 6px 까지. */
.sidenav__item::after {
  content: "";
  position: absolute;
  inset: -6px 0;
}

/* 막대. 기본은 짧고 가늘다.
   원본(토스)은 모서리가 둥근 알약이었지만 여기서는 각진 직사각으로 쓴다. */
.sidenav__bar {
  display: block;
  width: 37px;

  /* ★ 막대 높이 ★ 활성·호버까지 **전부 같은 높이**다.
     길이(width)와 진하기(opacity)만 바뀌고 두께는 안 바뀐다.
     ⚠ 위 --sidenav-row 를 이 값과 같게 맞춰 둬야 gap 이 곧 막대 사이 거리가 된다. */
  height: 3px;

  border-radius: 0;
  background-color: currentColor;

  /* ★ 지금 보고 있는 구간이 아닌 항목의 불투명도 ★ */
  opacity: 0.5;

  transition:
    width 0.2s ease,
    opacity 0.2s ease;
}

/* 이름. 평소엔 감춰 두고 **활성이거나 마우스가 올라간 그 항목만** 보인다.
   visibility 까지 끄는 건 감춰진 이름이 마우스·스크린리더에 잡히지 않게 하려는 것. */
.sidenav__label {
  font-family: var(--font-display);
  /* ★ 이름 글자 크기 ★ */
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
  opacity: 0;
  visibility: hidden;
  translate: 8px 0;
  transition:
    opacity 0.2s ease,
    translate 0.2s ease,
    visibility 0.2s;
}

/* 지금 보고 있는 구간 */
.sidenav__item.is-active .sidenav__bar {
  width: 47px;
  opacity: 1;
}

.sidenav__item.is-active .sidenav__label {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
}

/* ── 마우스를 올린 항목 ──────────────────────────────────────────────────
   ⚠ 예전에는 :has() 로 목차 어디에 올리든 **모든** 이름이 한꺼번에 떴다.
     원본(토스)을 계측해 보니 그렇지 않다 — 마우스가 올라간 **그 항목 하나만**
     이름이 뜬다. 그래서 :has() 를 걷어내고 항목 단위 :hover 로 바꿨다. */
.sidenav__item:hover .sidenav__label {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
}

/* 마우스를 올린 항목의 막대는 **활성과 똑같아진다** — 같은 길이, 같은 진하기.
   "여기를 누르면 이 구간으로 간다"를 미리 보여 주는 셈이다. */
.sidenav__item:hover .sidenav__bar {
  width: 47px;
  opacity: 1;
}

/* 아직 그 구간이 페이지에 없는 항목(지금은 Part II·III·Outro).
   js/mod-sidenav.js 가 대상 id 를 못 찾으면 이 클래스를 붙인다.

   ⚠ 색을 따로 주지 않는다 — **비활성 항목은 전부 같은 색이어야 한다.**
     한때 여기에 opacity 0.18 을 걸어 더 흐리게 뒀는데, 그러면 비활성 4개 중
     3개(없는 구간)만 흐리고 1개(있는 구간)만 진해서 하나가 튄다.
     "아직 안 만든 구간"이라는 사정은 화면에 드러내지 않는다.

   ⚠ pointer-events 를 끄지 않는다. 끄면 그 위에 마우스를 올려도 호버가 안 잡혀
     이름이 안 뜬다. 클릭은 js 쪽에서 막는다. */
.sidenav__item.is-missing {
  cursor: default;
}

/* 키보드 초점은 보여야 한다 */
.sidenav__item:focus-visible .sidenav__bar {
  opacity: 1;
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* ── 좁은 화면 ───────────────────────────────────────────────────────────
   숨긴다. 원본(토스)도 모바일에서는 이 목차를 DOM 에서 아예 뺀다
   (2026-08-13 에 390×844 로 확인). 좁은 화면에서 세로 목차는 본문을 가리기만 한다.
   마크업은 그대로 두고 CSS 로만 숨기므로, 화면을 넓히면 바로 다시 나온다. */
@media only screen and (width < 768px) {
  .sidenav {
    display: none;
  }
}

/* 손가락으로 쓰는 기기에서는 :hover 가 한 번 눌리면 그대로 붙박이가 된다.
   그런 기기에서는 호버 효과를 끄고 활성 표시만 남긴다.
   (768px 이상이면서 터치인 태블릿·터치 노트북이 여기 해당한다) */
@media (hover: none) {
  .sidenav__item:hover .sidenav__bar {
    width: 37px;
    opacity: 0.5;
  }

  .sidenav__item:hover .sidenav__label {
    opacity: 0;
    visibility: hidden;
    translate: 8px 0;
  }

  /* 활성 표시는 위 규칙에 지지 않도록 다시 세워 준다.
     (구체성이 같으므로 **뒤에 오는 이 규칙이 이긴다** — 순서를 바꾸면 안 된다) */
  .sidenav__item.is-active .sidenav__bar {
    width: 47px;
    opacity: 1;
  }

  .sidenav__item.is-active .sidenav__label {
    opacity: 1;
    visibility: visible;
    translate: 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sidenav__bar,
  .sidenav__label {
    transition: none;
  }
}
