    /* 전역 폰트: Abordage (Regular 단일 — 모든 weight를 이 페이스로 매핑) */
    @font-face {
      font-family: "Abordage";
      src: url("../../public/font/Abordage-Regular.woff2") format("woff2"),
        url("../../public/font/Abordage-Regular.woff") format("woff");
      font-weight: 100 900;
      font-style: normal;
      font-display: swap;
    }

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

    :root {
      --bg: #F0F0F0;
      --ink: #111111;
      --c-interface: #2b4cff;
      --c-tools: #18a558;
      --c-visual: #ff5436;
      --c-interactive: #cf25c9;
      --edge: 24px;
      /* 공통 좌측 여백 (헤더 / contact / INDEX 행) */
    }

    html,
    body {
      height: 100%;
      background: var(--bg);
      color: var(--ink);
      font-family: "Abordage", "Helvetica Neue", Helvetica, Arial, sans-serif;
      overflow: hidden;
      cursor: none;
    }

    /* Hide scrollbar for Chrome, Safari and Opera */
    *::-webkit-scrollbar {
      display: none;
    }

    /* Hide scrollbar for IE, Edge and Firefox */
    * {
      -ms-overflow-style: none;
      /* IE and Edge */
      scrollbar-width: none;
      /* Firefox */
    }

    /* headbar 안에서 전체 폭을 채우는 flex 행 */
    .topbar {
      position: relative;
      /* tagline(absolute) 기준 */
      display: flex;
      align-items: center;
      width: 100%;
      height: 100%;
    }

    .tag {
      background: var(--bg);
      color: #000;
      font-weight: 500;
      font-size: 15px;
      padding: 0 var(--edge);
      white-space: nowrap;
      pointer-events: auto;
      cursor: none;
      position: relative;
      z-index: 1;
    }

    /* 텍스트(span)만큼만 반전 배경 (instagram 링크와 동일) */
    .tag:hover span {
      background: var(--ink);
      color: #fff;
    }

    /* 뷰포트 중앙(전체 폭 기준)에 가로·세로 중앙정렬 */
    .tagline {
      position: absolute;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 16px;
      color: var(--ink);
      white-space: nowrap;
      pointer-events: none;
    }

    .tagline .i {
      color: var(--c-interface);
    }

    .tagline .t {
      color: var(--c-tools);
    }

    .tagline .v {
      color: var(--c-visual);
    }

    .tagline .x {
      color: var(--c-interactive);
    }

    .tagline span {
      pointer-events: auto;
      cursor: none;
      padding: 1px 4px;
      border-radius: 3px;
    }

    .tagline span.on {
      color: #fff !important;
    }

    .index {
      margin-left: auto;
      /* 오른쪽 끝으로 */
      background: var(--bg);
      color: #000;
      font-weight: 500;
      font-size: 15px;
      letter-spacing: 2px;
      padding: 0 18px;
      pointer-events: auto;
      cursor: none;
      position: relative;
      z-index: 1;
    }

    .index:hover span {
      background: var(--ink);
      color: #fff;
    }

    #scene {
      position: fixed;
      inset: 0;
      width: 100%;
      height: 100%;
      display: block;
    }

    /* 헤더 바: 배경색(#f0f0f0) + 하단 border (Figma detail 헤더). flex로 내부 텍스트 세로 중앙정렬 */
    .headbar {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      height: 50px;
      background: var(--bg);
      border-bottom: 1px solid var(--ink);
      z-index: 78;
      display: flex;
      align-items: center;
    }

    /* 우측 하단 모드 셀렉트박스 (galaxy / garden / town) */
    .mode-select {
      position: fixed;
      right: 24px;
      bottom: 24px;
      display: flex;
      align-items: center;
      gap: 8px;
      z-index: 55;
      font-size: 16px;
      color: var(--ink);
      user-select: none;
    }

    .mode-select.hidden {
      display: none;
    }

    .mode-label {
      padding-top: 4px;
      pointer-events: none;
    }

    .mode-dropdown {
      position: relative;
    }

    /* 닫힌 상태: 현재 모드 (테두리 박스) */
    .mode-current {
      font: inherit;
      color: var(--ink);
      background: var(--bg);
      border: 1px solid var(--ink);
      padding: 4px 14px;
      min-width: 116px;
      /* 가장 긴 옵션('perspective')에 맞춘 고정 너비 → 모드 전환 시 너비 안 변함 */
      text-align: center;
      cursor: none;
    }

    /* 현재 선택된(닫힌) 버튼도 hover 시 반전 → 클릭 가능 표시 */
    .mode-current:hover {
      background: var(--ink);
      color: #fff;
    }

    /* 열린 상태: 위로 펼쳐지는 옵션 목록 (바닥 = 현재 박스 위치) */
    .mode-list {
      position: absolute;
      left: 0;
      bottom: 0;
      margin: 0;
      padding: 0;
      list-style: none;
      display: none;
    }

    .mode-select.open .mode-list {
      display: block;
    }

    .mode-select.open .mode-current {
      visibility: hidden;
    }

    .mode-list li {
      background: var(--bg);
      border: 1px solid var(--ink);
      margin-bottom: -1px;
      padding: 4px 14px;
      min-width: 116px;
      /* 가장 긴 옵션('perspective')에 맞춘 고정 너비 */
      text-align: center;
      white-space: nowrap;
      cursor: none;
    }

    .mode-list li:hover,
    .mode-list li.active {
      background: var(--ink);
      color: #fff;
    }

    /* hover 효과 모드 전환 (프로토타입 비교용) — 현재 숨김. 다시 보려면 display:flex */
    .hover-mode {
      display: none;
      position: fixed;
      left: 20px;
      bottom: 20px;
      align-items: center;
      gap: 6px;
      z-index: 55;
      font-size: 14px;
      color: var(--ink);
      user-select: none;
    }

    .hover-mode.hidden {
      display: none;
    }

    .hover-mode-label {
      opacity: .6;
      margin-right: 2px;
    }

    .hover-mode button {
      font: inherit;
      color: var(--ink);
      background: var(--bg);
      border: 1px solid var(--ink);
      width: 26px;
      height: 26px;
      cursor: none;
    }

    .hover-mode button.active {
      background: var(--ink);
      color: #fff;
    }

    /* 좌측 하단 연락처 */
    .contact {
      position: fixed;
      left: var(--edge);
      bottom: 24px;
      z-index: 55;
      font-size: 16px;
      color: var(--ink);
    }

    .contact.hidden {
      display: none;
    }

    .contact a {
      color: var(--ink);
      text-decoration: underline;
      text-underline-offset: 2px;
      cursor: none;
    }

    .contact a:hover {
      background: var(--ink);
      color: #fff;
    }

    /* INDEX 목록 테이블 (flex DOM) — 우변(spine)은 paper 척추선, 행/별/구분선은 DOM */
    .index-table {
      position: fixed;
      right: 50%;
      /* 우변 = 화면 중앙(= paper 척추선 위치) */
      top: 50%;
      transform: translateY(-50%);
      width: 50vw;
      /* 화면 너비 절반 (좌변=화면 왼쪽 끝, 우변=중앙 척추선) */
      border-bottom: 1px solid #000000;
      z-index: 56;
      opacity: 0;
      display: none;
      pointer-events: none;
      font-size: 16px;
      color: var(--ink);
    }

    .ix-row {
      display: flex;
      align-items: center;
      height: 64px;
      /* ROW_HEIGHT */
      padding-left: var(--edge);
      border-top: 1px solid #000000;
      border-left: 1px solid #000000;
      position: relative;
      overflow: visible;
      pointer-events: auto;
      cursor: none;
      transition: height .35s ease, opacity .35s ease, border-color .35s ease, color .2s ease;
    }

    /* 전역 커스텀 커서 닷 (DOM, z 최상위) — 헤더/링크/셀렉트 등 DOM 요소 위에서도 표시.
       캔버스의 paper 닷은 DOM 위로 못 올라오므로 이 DOM 닷이 전 화면의 커서 역할. */
    .dot-cursor {
      position: fixed;
      top: 0;
      left: 0;
      width: 9px;
      height: 9px;
      border-radius: 50%;
      background: var(--ink);
      transform: translate(-50%, -50%);
      pointer-events: none;
      z-index: 90;
      display: block;
    }

    /* hover 시 행 텍스트 = 해당 카테고리 색 */
    .ix-row[data-cat="interface"]:hover {
      color: var(--c-interface);
    }

    .ix-row[data-cat="tools"]:hover {
      color: var(--c-tools);
    }

    .ix-row[data-cat="visual"]:hover {
      color: var(--c-visual);
    }

    .ix-row[data-cat="interactive"]:hover {
      color: var(--c-interactive);
    }

    /* 컬럼은 원래 비율(269:146:291:136) 그대로 flex-grow로 분배 → 절반 폭에 맞춰 스케일 */
    .ix-name {
      flex: 269 1 0;
    }

    .ix-cat {
      flex: 146 1 0;
    }

    .ix-tags {
      flex: 291 1 0;
    }

    .ix-year {
      flex: 136 1 0;
    }

    .ix-star {
      position: absolute;
      right: 0;
      /* 우변(척추선) 위에 중앙 정렬 */
      top: 50%;
      width: 46px;
      height: 46px;
      transform: translate(50%, -50%);
    }

    .ix-star svg {
      width: 100%;
      height: 100%;
      display: block;
      overflow: visible;
    }

    /* 카테고리 필터: 매칭 안 되는 행 접힘 */
    .ix-row.filtered-out {
      height: 0;
      opacity: 0;
      overflow: hidden;
      border-top-color: transparent;
    }

    /* 호버 라벨: 오벌 상/하단 곡선을 따라 흐르는 제목·설명 (SVG textPath) */
    .oval-labels {
      position: fixed;
      inset: 0;
      width: 100%;
      height: 100%;
      overflow: visible;
      pointer-events: none;
      z-index: 50;
      opacity: 0;
      transition: opacity .28s ease;
    }

    .oval-labels.on {
      opacity: 1;
    }

    .oval-label {
      font-family: "Abordage", "Helvetica Neue", Helvetica, Arial, sans-serif;
      /* 테두리 없이 텍스트 자체를 흰색으로 */
      fill: #fff;
    }

    .oval-title {
      font-weight: 700;
      font-size: 18px;
      letter-spacing: .3px;
    }

    .oval-desc {
      font-weight: 400;
      font-size: 16px;
      transform: translateY(8px);
    }

    /* ===== 상세 (F: 확대된 orbit 호 위의 별 + 중앙 본문 + 좌우 주석/TOC) ===== */
    .detail {
      position: fixed;
      inset: 0;
      z-index: 60;
      cursor: none;
      opacity: 0;
      pointer-events: none;
      transition: opacity .4s ease;
      background: transparent;
      overflow-y: auto;
    }

    .detail.open {
      opacity: 1;
      pointer-events: auto;
    }

    .d-close {
      position: fixed;
      top: 13px;
      right: 18px;
      z-index: 70;
      border: none;
      background: none;
      color: var(--ink);
      font-size: 24px;
      cursor: none;
    }

    /* H: 줌인된 화면이 좌측으로 이동 → 3컬럼(좌:별/제목, 중:본문, 우:이미지, 우여백:메타) */
    .detail {
      overflow: hidden;
    }

    /* 가든(좌측 첫 컬럼)을 제외한 나머지 컬럼은 흰색 배경 — 좌측은 paper.js 가든이 비쳐 보이도록 투명 유지 */
    .dH-white {
      position: fixed;
      left: 24.7%;
      right: 0;
      top: 50px;
      bottom: 0;
      background: var(--bg);
      z-index: 60;
      opacity: 0;
      transition: opacity .5s ease 1.2s;
    }

    .detail.open .dH-white {
      opacity: 1;
    }

    /* 세로 가이드선 (좌|중 / 중|우 / 우|메타) — 슬라이드 끝난 뒤 등장 */
    .dH-line {
      position: fixed;
      top: 50px;
      bottom: 0;
      border-left: 1px solid var(--ink);
      z-index: 61;
      opacity: 0;
      transition: opacity .5s ease 1.3s;
    }

    .detail.open .dH-line {
      opacity: 1;
    }

    .dH-line.a {
      left: 24.7%;
    }

    .dH-line.b {
      left: 66.8%;
    }

    .dH-line.c {
      left: 92.1%;
    }

    /* 좌측 컬럼 상단: 제목 + 설명 한 문장 (맵 줌인 트랜지션 후 제자리에서 페이드인) */
    .dH-lefthead {
      position: fixed;
      left: 0;
      width: 24.7%;
      top: 90px;
      padding: 0 var(--edge);
      text-align: left;
      z-index: 62;
      opacity: 0;
      transition: opacity .4s ease .7s;
    }

    .detail.open .dH-lefthead {
      opacity: 1;
    }

    .dH-title {
      font-size: 24px;
      letter-spacing: .3px;
    }

    .dH-desc {
      font-size: 16px;
      margin-top: 10px;
    }

    /* 좌측 컬럼 하단: 카테고리(키워드) + 연도 (맵 줌인 후 제자리에서 페이드인) */
    .dH-leftmeta {
      position: fixed;
      left: 0;
      width: 24.7%;
      bottom: var(--edge);
      padding: 0 var(--edge);
      text-align: left;
      font-size: 16px;
      z-index: 62;
      opacity: 0;
      transition: opacity .4s ease .7s;
    }

    .detail.open .dH-leftmeta {
      opacity: 1;
    }

    .dH-year {
      margin-top: 6px;
    }

    /* 별은 별도 DOM이 아니라 '줌인된 맵'이 좌측 컬럼에 그대로 보인다.
       .dH-star = 좌측(맵) 영역 클릭 시 상세 닫기용 투명 영역. */
    .dH-star {
      position: fixed;
      left: 0;
      width: 24.7%;
      top: 50px;
      bottom: 0;
      z-index: 64;
      cursor: none;
    }

    /* 데스크톱: 별은 줌인된 맵으로 보이므로 주입된 인라인 SVG는 숨긴다(모바일에서만 표시). */
    .dH-star svg {
      display: none;
    }

    /* 중앙 컬럼: 본문(스크롤) — 슬라이드 뒤 등장 */
    .dH-body {
      position: fixed;
      left: 24.7%;
      width: 42.1%;
      top: 50px;
      bottom: 0;
      padding: 24px;
      overflow-y: auto;
      z-index: 62;
      opacity: 0;
      transition: opacity .55s ease 1.35s;
    }

    .detail.open .dH-body {
      opacity: 1;
    }

    .dH-body p {
      font-size: 16px;
      line-height: 1.85;
      margin-bottom: 18px;
      max-width: 60ch;
    }

    /* 우측 영역: 이미지 컬럼 + 캡션 컬럼을 하나의 스크롤 컨테이너로(세트로 함께 스크롤).
       66.8%~100% 전체를 차지하고, 각 미디어 행이 [미디어(→92.1%) | 캡션(92.1%~)]로 나뉜다.
       세로가 넘치면 이 컨테이너만 스크롤. (세로 가이드선 c=92.1%가 두 컬럼의 경계) */
    .dH-image {
      position: fixed;
      left: 66.8%;
      right: 0;
      width: auto;
      top: 80px;
      bottom: var(--edge);
      padding: 0;
      overflow-y: auto;
      z-index: 60;
      opacity: 0;
      transition: opacity .55s ease 1.45s;
    }

    .detail.open .dH-image {
      opacity: 1;
    }

    /* 미디어 한 행: 좌=미디어(이미지 컬럼), 우=캡션(캡션 컬럼). 캡션은 미디어 상단에 정렬. */
    .dH-media-fig {
      display: flex;
      align-items: flex-start;
      margin: 0 0 18px;
    }

    /* 미디어 박스: 66.8%~92.1% (전체 컨테이너의 76.2%) → 우변이 가이드선 c와 일치 */
    .dH-media-box {
      flex: 0 0 76.2%;
      min-width: 0;
    }

    .dH-media-el {
      width: 100%;
      height: auto;
      display: block;
      background: #d9d7d3;
    }

    /* 캡션 컬럼: 92.1%~100%, 가이드선 c 우측 14px(기존 dH-rightmeta 들여쓰기와 동일) */
    .dH-media-cap {
      flex: 1 1 0;
      min-width: 0;
      padding-left: 14px;
      font-size: 13px;
      line-height: 1.5;
      color: var(--ink);
    }

    /* 기존 단일 캡션 컬럼(연도/도판 라벨)은 캡션이 미디어 행으로 옮겨가 더이상 쓰지 않음(데스크톱 숨김). */
    .dH-rightmeta {
      display: none;
    }

    /* 모바일(≤700px) 대응은 별도 파일 playground.mobile.css 로 분리 */