/*!
 * site.css — EOMPAGE
 *
 * s-air 의 편집 디자인 문법을 잇습니다.
 *   · 위 행(나와 만든 것)은 검정, 아래 행(일 맡기기)은 종이
 *   · 무지개도 네온도 글래스모피즘도 없음. 강조색은 짙은 청록 하나
 *   · 셀 크기 = 뷰포트 크기이므로 셀 안에서 vw/vh 를 그대로 씁니다
 *
 * 색은 아래 :root 가 단일 출처입니다. 여기 없는 색을 쓰지 마세요.
 */

/* ------------------------------------------------------------------ *
 * 0. 토큰
 * ------------------------------------------------------------------ */
:root {
  /* 종이 */
  --paper:      #f1eee7;
  --paper-2:    #e7e3d9;
  --ink:        #16171a;
  --ink-2:      #3e4148;
  --ink-3:      #5d616a;   /* 종이 위 5.37:1. 더 밝히면 본문 보조색으로 못 씁니다 */
  --rule:       #cdc8ba;

  /* 잉크. 위 행(01·02·03) */
  --deep:       #121316;
  --deep-2:     #1b1d21;
  --deep-rule:  #32353c;
  --deep-ink-2: #a8adb6;   /* 검정 위 8.2:1 */

  /* 강조 */
  --accent:     #1f6f63;   /* 종이 위 5.16:1 */
  --accent-dim: #17564d;
  --accent-lit: #5fbfae;   /* 검정 위 8.5:1. 어두운 셀에서만 씁니다 */

  --font-kr: "Pretendard Variable", Pretendard, -apple-system, "Apple SD Gothic Neo",
             "Malgun Gothic", "맑은 고딕", system-ui, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "JetBrains Mono", Consolas, monospace;

  --ease: cubic-bezier(.22,.61,.36,1);

  /* 판면의 최대 폭. 셀은 뷰포트 크기라 제한이 없으면 2000px 화면에서
     한 줄이 1840px 까지 늘어납니다. 넘는 만큼은 좌우 여백으로 돌립니다. */
  --measure: 1320px;
}

/* ------------------------------------------------------------------ *
 * 1. 리셋
 * ------------------------------------------------------------------ */
* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%;
  overflow: hidden;                      /* 페이지 스크롤 없음. 이동은 카메라가 합니다 */
  background: var(--deep);
  overscroll-behavior: none;
}
body {
  font-family: var(--font-kr);
  letter-spacing: -.011em;
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}
img, video, iframe { display: block; max-width: 100%; }
button { font: inherit; letter-spacing: inherit; color: inherit; }

/* hidden 은 무조건 이깁니다.
   브라우저 기본 규칙은 `[hidden] { display: none }` 인데, 클래스에 display 를 주는
   순간(.gate 의 grid, .reader 의 grid) 그쪽이 더 세서 hidden 이 조용히 무시됩니다.
   숨겼다고 생각한 덮개가 화면을 그대로 가립니다. 실제로 두 번 당했습니다. */
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.cell--deep :focus-visible { outline-color: var(--accent-lit); }
.rig-viewport:focus { outline: none; }

.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;
}

/* ------------------------------------------------------------------ *
 * 2. 리그
 * ------------------------------------------------------------------ */
.rig-viewport {
  position: fixed; inset: 0;
  /* clip 은 스크롤 상자를 아예 만들지 않습니다. hidden 은 상자를 만들어 두고
     막대만 감추는 것이라, 안 보이는 칸의 iframe 이 포커스를 가져가면 브라우저가
     그걸 보여주려고 이 상자를 굴립니다. 그러면 보드뿐 아니라 HUD 와 미니맵까지
     같이 밀려 화면이 통째로 어긋납니다. hidden 은 clip 을 모르는 브라우저용 대비입니다. */
  overflow: hidden;
  overflow: clip;
  background: var(--deep);
  cursor: grab;
  touch-action: none;
}
body.is-dragging .rig-viewport { cursor: grabbing; }
body.is-overview .rig-viewport { cursor: default; }

.rig-zoom  { position: absolute; inset: 0; transform-origin: 50% 50%; will-change: transform; }
.rig-board { position: absolute; top: 0; left: 0; display: grid;
             transform-origin: 0 0; will-change: transform; }

/* ------------------------------------------------------------------ *
 * 3. 셀 공통
 * ------------------------------------------------------------------ */
.cell {
  position: relative;
  /* 창과 같은 이유로 clip 입니다. 굴러가야 하는 것은 .cell-body 하나뿐입니다. */
  overflow: hidden;
  overflow: clip;
  background: var(--paper);
  color: var(--ink);
  display: flex; flex-direction: column;
  padding: clamp(26px, 4.2vh, 54px) clamp(22px, 4.4vw, 80px);
  padding-top: clamp(58px, 7.5vh, 88px);   /* 위쪽은 HUD 막대가 지나가는 자리 */
  /* 한 셀의 레이아웃·그리기를 자기 안에 가둡니다. 이게 없으면 한 셀의 변화가
     여섯 장 전체의 재계산으로 번집니다. */
  contain: layout paint;
}

/* 지금 화면에 안 걸리는 셀. display:none 이 아니라 visibility 라서
   격자 크기는 그대로 유지되고 그리기만 건너뜁니다. */
.cell.is-far { visibility: hidden; }

/* 종이 셀의 4단 판면. 인쇄물의 단 나누기 선입니다 */
.cell--paper::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: repeating-linear-gradient(to right,
              var(--rule) 0 1px, transparent 1px 25%);
  opacity: .3;
}
/* 04 만 선을 하나로 줄입니다. 25% 마다 그은 4단 선은 내용 폭과 상관없이 칸 너비를
   기준으로 그어져서, 사례 목록이 선을 뚫고 지나가는 것처럼 보입니다.
   여기는 카드와 사례 두 단이므로 그 사이에 선 하나면 됩니다. 판이 가운데 정렬이고
   두 단이 1fr 씩이라 그 경계가 곧 칸의 한가운데입니다. */
.cell--paper[data-cell="4"]::before {
  inset: 0 auto 0 50%; width: 1px; background: var(--rule); opacity: .55;
}

.cell--deep { background: var(--deep); color: var(--paper); }

/* 셀 머리말 */
.cell-head {
  width: 100%; max-width: var(--measure); margin-inline: auto;
  display: flex; align-items: baseline; gap: 14px;
  padding-bottom: 11px; margin-bottom: clamp(14px, 2.8vh, 32px);
  border-bottom: 1px solid var(--rule);
  position: relative; z-index: 3; flex: none;
}
.cell--deep .cell-head { border-color: var(--deep-rule); }

.cell-num {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .1em;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.cell--deep .cell-num { color: var(--accent-lit); }
.cell-name {
  font-size: 12px; font-weight: 600; letter-spacing: .24em;
  text-transform: uppercase; color: var(--ink-3);
}
.cell--deep .cell-name { color: #878c94; }
.cell-kr { margin-left: auto; font-size: 12px; color: var(--ink-3); }
.cell--deep .cell-kr { color: #878c94; }

/* 본문은 넘칠 때만 스스로 스크롤합니다.
   안쪽에 또 overflow:auto 를 두지 마세요. 그 영역에서 카메라가 휠을 뺏깁니다. */
.cell-body {
  flex: 1 1 auto; min-height: 0; position: relative; z-index: 3;
  display: flex;
  align-items: flex-start;
  align-items: safe center;              /* 짧으면 가운데, 길면 위에 붙습니다 */
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: var(--rule) transparent;
}
/* 내용 개수가 바뀌는 지면(03 작품, 06 노트)은 위로 붙입니다.
   가운데 두면 필터를 누를 때마다 블록이 다시 가운데로 모여서,
   방금 누른 버튼이 커서 밑에서 도망갑니다. 21개에서 2개로 줄면 178px 움직였습니다. */
.cell-body--top { align-items: flex-start; }
/* 04 는 판이 칸 높이를 꽉 채워야 세 줄이 높이를 나눠 갖습니다. 가운데 정렬로는 안 됩니다. */
.cell-body--fill { align-items: stretch; }

/* --measure 는 머리말과 본문 양쪽에 겁니다. 한쪽만 걸면 어긋납니다. */
.cell-body > * { width: 100%; max-width: var(--measure); margin-inline: auto; }
.cell-body::-webkit-scrollbar { width: 6px; }
.cell-body::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }
.cell--deep .cell-body { scrollbar-color: var(--deep-rule) transparent; }
.cell--deep .cell-body::-webkit-scrollbar-thumb { background: var(--deep-rule); }

/* 타이포 */
.kicker {
  /* 한글이 섞이는 라벨이라 자간을 벌리지 않습니다. 벌리면 글자가 흩어져 읽힙니다. */
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .02em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 14px;
  display: flex; align-items: center; gap: 10px;
}
.kicker::before { content: ""; width: 34px; height: 2px; background: currentColor; }
.cell--deep .kicker { color: var(--accent-lit); }

.display {
  font-size: clamp(30px, 4.6vw, 66px);
  line-height: 1.06; letter-spacing: -.04em; font-weight: 800;
  margin: 0 0 clamp(12px, 2.2vh, 26px); text-wrap: balance;
}
.display--sm { font-size: clamp(24px, 2.6vw, 40px); }
.lede { font-size: clamp(13.5px, 1.1vw, 17.5px); line-height: 1.78; color: var(--ink-2);
        max-width: 46ch; margin: 0 0 18px; }
.cell--deep .lede { color: var(--deep-ink-2); }
.fine { font-size: 13px; line-height: 1.7; color: var(--ink-3); margin: 0; }
.cell--deep .fine { color: #878c94; }

/* 등장 연출. 도착했을 때만 */
.cell [data-reveal] {
  opacity: 0; transform: translateY(16px);
  transition: opacity .62s var(--ease), transform .62s var(--ease);
}
.cell.is-live [data-reveal] { opacity: 1; transform: none; }
.cell.is-live [data-reveal="2"] { transition-delay: .09s; }
.cell.is-live [data-reveal="3"] { transition-delay: .18s; }
.cell.is-live [data-reveal="4"] { transition-delay: .27s; }
.cell.is-live [data-reveal="5"] { transition-delay: .36s; }

/* 시차. site.js 가 셀마다 --px/--py 를 채웁니다.
   data-depth 는 HTML 속성이라 calc() 가 못 읽습니다. JS 가 --depth 로 옮깁니다. */
[data-depth] {
  transform: translate3d(calc(var(--px, 0) * var(--depth) * 1px),
                         calc(var(--py, 0) * var(--depth) * .6px), 0);
  will-change: transform;
}

/* 공용 버튼 */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 12px 22px; cursor: pointer;
  border: 1px solid var(--accent); border-radius: 3px;
  background: var(--accent); color: #fff;
  font-size: 14px; font-weight: 600;
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.btn:hover { background: var(--accent-dim); border-color: var(--accent-dim); }
.btn--ghost { background: transparent; color: var(--accent); }
.btn--ghost:hover { background: var(--accent); color: #fff; }
.cell--deep .btn { background: var(--accent-lit); border-color: var(--accent-lit); color: #0d1113; }
.cell--deep .btn:hover { background: #7ed0c0; border-color: #7ed0c0; }
.btn[disabled] { opacity: .5; cursor: default; }

/* 바깥으로 나가는 링크 */
.ext { color: var(--accent); text-decoration: none; border-bottom: 1px solid currentColor; }
.ext:hover { color: var(--accent-dim); }
.ext::after { content: "↗"; font-size: .85em; margin-left: 3px; }
.cell--deep .ext { color: var(--accent-lit); }

/* 태그 */
.tags { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.tags span, .tags li {
  font-size: 11.5px; letter-spacing: .02em; color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 2px; padding: 3px 8px;
}
.cell--deep .tags span, .cell--deep .tags li { color: #878c94; border-color: var(--deep-rule); }

/* ------------------------------------------------------------------ *
 * 4. HUD. 배율 레이어 바깥이라 줌에 끌려가지 않습니다
 * ------------------------------------------------------------------ */
.hud { position: absolute; z-index: 40; pointer-events: none; color: var(--paper); }
.hud-top {
  top: 0; left: 0; right: 0;
  display: flex; align-items: center; gap: 16px;
  padding: 18px clamp(16px, 3vw, 30px);
}
/* 워드마크. 글자가 아니라 그림입니다.
   img 로 넣으면 지면에 따라 색을 뒤집을 수 없습니다. mask 로 넣고 바탕을
   currentColor 로 칠하면, 검은 칸에서는 종이색으로 종이 칸에서는 잉크색으로
   저절로 바뀝니다. 글자였을 때 하던 일을 그대로 합니다.
   가로세로비는 SVG 의 viewBox 와 같아야 합니다. 어긋나면 글자가 눈에 띄게 눌립니다. */
.hud-mark {
  display: block; height: 14px; aspect-ratio: 6494 / 1824; flex: none;
  background: currentColor;
  -webkit-mask: url(brand/eompage-mark.svg?v=3589edf6) no-repeat left center / contain;
          mask: url(brand/eompage-mark.svg?v=3589edf6) no-repeat left center / contain;
}
.hud-where {
  margin-left: auto; font-family: var(--font-mono); font-size: 11.5px;
  letter-spacing: .1em; font-variant-numeric: tabular-nums; opacity: .82;
}
body.on-light .hud { color: var(--ink); }

.hud-hint {
  left: clamp(16px, 3vw, 30px); bottom: 20px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .01em;
  opacity: .62; line-height: 1.95;
}
.hud-hint kbd {
  font: inherit; border: 1px solid currentColor; border-radius: 3px;
  padding: 1px 5px; opacity: .85;
}

/* ------------------------------------------------------------------ *
 * 5. 조작 묶음. 좁은 화면에서도 항상 보입니다
 * ------------------------------------------------------------------ */
.controls {
  position: absolute; z-index: 45;
  right: clamp(16px, 3vw, 30px); bottom: clamp(16px, 3vw, 26px);
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
}

.motion-toggle {
  padding: 5px 10px; min-height: 28px; cursor: pointer; border-radius: 3px;
  background: rgba(18,19,22,.34); border: 1px solid rgba(255,255,255,.14);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .01em;
  color: rgba(255,255,255,.8);
  transition: color .2s var(--ease), border-color .2s var(--ease),
              background .2s var(--ease), opacity .3s var(--ease);
}
body.on-light .motion-toggle {
  background: rgba(241,238,231,.56); border-color: rgba(22,23,26,.18); color: rgba(22,23,26,.68);
}
.motion-toggle:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
body.on-light .motion-toggle:hover { border-color: var(--accent); color: var(--accent); }
.motion-toggle b { font-weight: 700; }
body.is-idle .motion-toggle { opacity: .36; }

.minimap {
  position: relative;
  display: grid; grid-template-columns: repeat(3, 34px); grid-auto-rows: 34px; gap: 4px;
  padding: 7px; border-radius: 4px;
  background: rgba(18,19,22,.34);
  border: 1px solid rgba(255,255,255,.14);
  transition: opacity .3s var(--ease);
}
body.on-light .minimap { background: rgba(241,238,231,.56); border-color: rgba(22,23,26,.18); }
body.is-idle .minimap { opacity: .36; }

.mm-cell {
  position: relative; padding: 0; cursor: pointer;
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 2px;
  display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 10px; color: rgba(255,255,255,.8);
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
body.on-light .mm-cell {
  background: rgba(22,23,26,.06); border-color: rgba(22,23,26,.18); color: rgba(22,23,26,.68);
}
.mm-cell:hover { background: rgba(255,255,255,.26); color: #fff; }
body.on-light .mm-cell:hover { background: rgba(22,23,26,.14); color: var(--ink); }
/* 현재 칸. body.on-light .mm-cell 이 (0,2,1)로 더 세기 때문에
   같은 무게로 두 번 적지 않으면 종이 지면에서 조용히 덮입니다. */
.mm-cell[aria-current="true"],
body.on-light .mm-cell[aria-current="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.mm-cell[aria-current="true"]:hover,
body.on-light .mm-cell[aria-current="true"]:hover {
  background: var(--accent-dim); border-color: var(--accent-dim); color: #fff;
}
/* 작품 두 칸을 점으로 표시 */
.mm-cell[data-works="1"]::after {
  content: ""; position: absolute; right: 4px; bottom: 4px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--accent-lit);
}
.mm-cell[aria-current="true"][data-works="1"]::after { background: #fff; }

.mm-tip {
  position: absolute; right: 0; bottom: calc(100% + 9px);
  white-space: nowrap; padding: 5px 9px; border-radius: 3px;
  background: var(--ink); color: var(--paper); font-size: 11.5px;
  opacity: 0; transform: translateY(4px); pointer-events: none;
  transition: opacity .18s var(--ease), transform .18s var(--ease);
}
.minimap.has-tip .mm-tip { opacity: 1; transform: none; }

/* ------------------------------------------------------------------ *
 * 6. 전체 조망. 셀 위에 반투명 이름표
 * ------------------------------------------------------------------ */
.cell-veil {
  position: absolute; inset: 0; z-index: 30;
  display: grid; place-content: center; gap: 10px; text-align: center;
  background: rgba(18,19,22,.52);
  opacity: 0; pointer-events: none;
  transition: opacity .38s var(--ease), background .38s var(--ease);
}
body.is-overview .cell-veil { opacity: 1; pointer-events: auto; cursor: pointer; }
body.is-overview .cell-veil:hover { background: rgba(31,111,99,.68); }
.cell-veil .v-num {
  font-family: var(--font-mono); font-size: 34px; color: rgba(255,255,255,.6); letter-spacing: .08em;
}
.cell-veil .v-name { font-size: 58px; font-weight: 800; letter-spacing: -.03em; color: #fff; }
.cell-veil .v-sub  { font-size: 26px; color: rgba(255,255,255,.66); }

body.is-overview .cell-body,
body.is-overview .cell-head { opacity: .45; transition: opacity .38s var(--ease); }

/* ------------------------------------------------------------------ *
 * 7. 인트로
 * ------------------------------------------------------------------ */
.intro {
  position: absolute; inset: 0; z-index: 90;
  display: grid; place-content: center; justify-items: center; gap: 18px; text-align: center;
  padding: 24px;
  background: var(--deep); color: var(--paper);
  transition: opacity .7s var(--ease), visibility .7s;
}
.intro.is-gone { opacity: 0; visibility: hidden; }
.intro-sub { font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .16em;
             text-transform: uppercase; color: #878c94; margin: 0; }
.intro-keys { font-family: var(--font-mono); font-size: 11.5px; color: #878c94; line-height: 2.1; margin: 0; }
.intro-keys kbd { border: 1px solid #494d55; border-radius: 3px; padding: 1px 6px; }
.intro-go {
  margin-top: 6px; padding: 13px 26px; min-height: 44px; cursor: pointer;
  background: var(--accent-lit); color: #0d1113; border: 0; border-radius: 3px;
  font-size: 14px; font-weight: 700;
  transition: background .2s var(--ease);
}
.intro-go:hover { background: #7ed0c0; }

/* ------------------------------------------------------------------ *
 * 8. 셀 01 · 소개 (표지를 겸합니다)
 * ------------------------------------------------------------------ */
.about {
  display: grid; grid-template-columns: auto 1fr; gap: clamp(30px, 4.4vw, 72px);
  align-items: center;
}
.portrait {
  width: clamp(150px, 17vw, 260px); aspect-ratio: 1; border-radius: 50%;
  overflow: hidden; position: relative; flex: none;
  background: var(--paper-2); border: 1px solid var(--rule);
  display: grid; place-items: center;
}
/* 01 은 검은 지면이라 동그라미도 같이 어두워야 합니다 */
.cell--deep .portrait { background: var(--deep-2); border-color: var(--deep-rule); }
.cell--deep .portrait .initial { color: var(--accent-lit); }
.portrait img { width: 100%; height: 100%; object-fit: cover; }
/* 사진이 없으면 이름 첫 글자를 큼직하게 둡니다. 깨진 이미지 아이콘보다 낫습니다. */
.portrait .initial {
  font-size: clamp(56px, 7vw, 104px); font-weight: 800; color: var(--accent);
  letter-spacing: -.04em; line-height: 1;
}
.about-who { display: flex; flex-direction: column; gap: 4px; }

/* 표지를 겸하므로 이름이 화면에서 제일 큽니다 */
.about-name { font-size: clamp(40px, 5.6vw, 92px); font-weight: 800; letter-spacing: -.05em;
              line-height: 1; margin: 2px 0 0; }
.about-role { font-size: 12.5px; letter-spacing: .02em; color: var(--accent-lit); margin: 0; }
.about-line { font-size: clamp(15px, 1.5vw, 21px); line-height: 1.5; color: var(--paper);
              margin: 12px 0 0; max-width: 30ch; }
.about-links { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 20px;
               list-style: none; padding: 0; font-size: 14px; }
.about-way { display: flex; align-items: center; gap: 10px; margin: 22px 0 0;
             font-size: 12.5px; letter-spacing: .01em; color: #8a8f98; }
.about-way b { color: var(--paper); font-weight: 500; }

/* 01 의 숫자 띠.
   소개 블록이 칸 가운데 있어서 위아래로 180px 씩 비어 있었습니다. 그 아래를 씁니다.
   세로로 쌓지 않고 한 줄 괘선 아래에 눕혀서, 표지의 이름과 싸우지 않게 합니다.
   숫자를 누르면 03 작품 전체로 갑니다. 세어 보여 준 것을 바로 볼 수 있어야 합니다. */
.about-wrap { display: flex; flex-direction: column; }
.tally {
  margin-top: clamp(24px, 4.2vh, 54px);
  padding-top: clamp(16px, 2.2vh, 26px);
  border-top: 1px solid var(--deep-rule);
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: clamp(18px, 3vw, 52px);
}
.t-kicker {
  /* 라틴 라벨이라 자간을 벌립니다. 한글 라벨에는 이렇게 하지 않습니다. */
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--accent-lit);
  align-self: center; flex: none;
}
.t-main { display: flex; align-items: baseline; gap: 13px; flex: none; }
.t-num {
  font-size: clamp(52px, 7.4vw, 120px); font-weight: 800; letter-spacing: -.055em;
  line-height: .82; color: var(--paper); font-variant-numeric: tabular-nums;
  transition: color .2s var(--ease);
}

.t-cap { font-size: clamp(13px, 1.15vw, 16px); color: var(--deep-ink-2); }
.t-side {
  display: flex; flex-wrap: wrap; gap: clamp(16px, 2.4vw, 40px);
  list-style: none; margin: 0; padding: 0; align-self: center;
}
.t-side li { display: flex; align-items: baseline; gap: 8px; }
.t-side b {
  font-size: clamp(19px, 2.1vw, 30px); font-weight: 700; color: var(--accent-lit);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.t-side span { font-size: 12.5px; color: #8a8f98; }

/* ------------------------------------------------------------------ *
 * 9. 셀 02 · 대표작
 * ------------------------------------------------------------------ */
/* 대표작은 셋입니다. 2열로 떨어뜨리면 셋째가 혼자 남아 허전해지므로,
   좁아지면 2열을 건너뛰고 바로 1열로 갑니다(아래 좁은 화면 규칙). */
/* 열 수는 대표작으로 켠 개수를 따릅니다. site.js 가 --picks-n 을 채웁니다.
   한 줄을 지키려는 것입니다. 칸이 화면 한 장이라 두 줄이 되면 굴려야 하는데,
   02번은 한 눈에 들어오는 것이 일입니다. */
.picks { display: grid; grid-template-columns: repeat(var(--picks-n, 3), minmax(0, 1fr));
         gap: clamp(14px, 1.6vw, 26px); }
/* 넷을 넘으면 두 줄이 됩니다. 칸이 화면 한 장이라 카드를 그대로 두면 아래 줄이 잘립니다.
   미리보기 비율을 눕히고 글자와 여백을 같이 줄여서 두 줄이 칸 안에 들어오게 합니다.
   설명은 두 줄에서 끊습니다. 길이가 제각각이라 안 끊으면 카드 하나 때문에 줄 전체가 커집니다. */
.picks--many { gap: clamp(12px, 1.2vw, 20px); }
.picks--many .shot { aspect-ratio: 16 / 9; }
.picks--many .pick-t { padding: 11px 13px 12px; gap: 4px; }
.picks--many .pick-t h3 { font-size: 15px; }
.picks--many .pick-t p {
  font-size: 12.5px; line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* 1366×768 처럼 낮은 화면. 여백부터 깎고 그래도 모자라면 비율을 더 눕힙니다. */
@media (max-height: 860px) {
  .picks--many { gap: 10px; }
  .picks--many .shot { aspect-ratio: 2.1 / 1; }
  .picks--many .pick-t { padding: 8px 11px 9px; gap: 3px; }
  .picks--many .pick-t h3 { font-size: 14px; }
  .picks--many .pick-t p { font-size: 12px; line-height: 1.5; }
}
.pick {
  display: flex; flex-direction: column; text-align: left; padding: 0; cursor: pointer;
  background: var(--deep-2); border: 1px solid var(--deep-rule); border-radius: 3px;
  overflow: hidden; color: inherit;
  transition: border-color .22s var(--ease), transform .22s var(--ease);
}
.pick:hover { border-color: var(--accent-lit); transform: translateY(-3px); }

/* 미리보기 창.
   iframe 은 데스크톱 폭으로 띄운 뒤 축소해서 넣습니다. 그냥 넣으면 좁은 칸에서
   모바일 레이아웃이 나와 무슨 화면인지 알아볼 수 없습니다. */
.shot { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: #0c0d0f; flex: none; }
.shot iframe {
  position: absolute; top: 0; left: 0;
  /* max-width:100% 인 공통 규칙에 걸리면 1280px 이 칸 폭으로 줄어들어
     축소가 무의미해집니다. 여기서만 풀어 줍니다. */
  width: 1280px; height: 800px; max-width: none; border: 0;
  transform-origin: 0 0;
  /* site.js 의 fitShots() 가 칸 폭을 재서 --shot-scale 을 채웁니다.
     기본값은 값이 아직 없을 때 화면을 덜 놀라게 하려고 둔 것입니다. */
  transform: scale(var(--shot-scale, .28));
  pointer-events: none;                  /* 카드 클릭을 iframe 이 먹지 않게 */
}
.shot img { width: 100%; height: 100%; object-fit: cover; }
.shot video { width: 100%; height: 100%; object-fit: cover; }
.shot--empty { display: grid; place-items: center; background: var(--deep-2); }
.shot--empty span { font-size: 13px; letter-spacing: .01em; color: #7b8089; }
.shot::after {                            /* 미리보기 위에 얇은 막. 글자가 읽히게 */
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 55%, rgba(18,19,22,.5));
  pointer-events: none;
}

.pick-t { padding: 15px 16px 17px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.pick-t h3 { font-size: clamp(16px, 1.3vw, 21px); font-weight: 700; margin: 0; letter-spacing: -.022em; }
.pick-t p { font-size: 13.5px; line-height: 1.65; color: var(--deep-ink-2); margin: 0; }
.pick-go { margin-top: auto; padding-top: 8px; font-size: 12.5px; font-weight: 600;
           letter-spacing: .01em; color: var(--accent-lit); }

/* ------------------------------------------------------------------ *
 * 10. 셀 03 · 작품 전체
 * ------------------------------------------------------------------ */
/* 태그 줄은 목록 위에 붙여 둡니다. 21개를 훑어 내려가는 동안에도 보여야 합니다.
   굴러가는 상자는 .cell-body 하나뿐이라 sticky 의 기준도 그것입니다. */
.filters {
  position: sticky; top: 0; z-index: 4;
  display: flex; flex-wrap: wrap; gap: 7px;
  margin-bottom: 18px; padding: 2px 0 12px;
  background: var(--deep);
}
.filter {
  padding: 6px 13px; min-height: 32px; cursor: pointer; border-radius: 2px;
  background: transparent; border: 1px solid var(--deep-rule); color: var(--deep-ink-2);
  font-size: 12.5px;
  transition: border-color .2s var(--ease), color .2s var(--ease), background .2s var(--ease);
}
.filter:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
.filter[aria-pressed="true"] { background: var(--accent-lit); border-color: var(--accent-lit); color: #0d1113; }

.works { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
         background: var(--deep-rule); border: 1px solid var(--deep-rule); }
.work {
  background: var(--deep); padding: 17px 19px 19px; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 8px; color: inherit; border: 0;
  transition: background .2s var(--ease);
}
.work:hover { background: var(--deep-2); }
.work-top { display: flex; align-items: baseline; gap: 10px; }
.work h3 { font-size: 17px; font-weight: 700; margin: 0; letter-spacing: -.022em; }
.work .w-live { font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em;
                color: var(--accent-lit); text-transform: uppercase; margin-left: auto; }
.work p { font-size: 13.5px; line-height: 1.65; color: var(--deep-ink-2); margin: 0; }
.works-empty { padding: 30px 0; color: var(--deep-ink-2); font-size: 14px; }

/* ------------------------------------------------------------------ *
 * 11. 셀 04 · 연수 메뉴판
 * ------------------------------------------------------------------ */
/* 판이 칸 높이를 정확히 나눠 갖게 해서 굴리지 않아도 되게 합니다.
   칸 하나가 화면 한 장이므로 세 줄이 1fr 씩 가져가면 딱 들어맞습니다. */
.menu-wrap { display: flex; flex-direction: column; min-height: 0; height: 100%; }
.menu-wrap .kicker { margin-bottom: 10px; }
.menu-wrap .menu { flex: 1 1 auto; min-height: 0; }

.menu { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(12px, 1.4vw, 22px); }

/* 줄마다 왼쪽이 카드, 오른쪽이 그 연수에서 다루는 사례입니다.
   대각선으로 내려 놓아 봤는데 가운데 줄만 한쪽이 비어서 통일감이 깨졌습니다.
   순서는 난이도 표시가 이미 말해 주므로 배치까지 계단으로 만들 이유가 없습니다.

   문서 순서가 카드·사례·카드·사례이므로 자리를 지정할 필요가 없습니다.
   이름 붙인 영역을 쓰면 좁은 화면에서 그걸 다시 푸는 규칙이 또 필요해집니다. */
.menu--rows {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  /* 1fr 만 주면 내용이 줄 높이를 넘어 옆 칸을 덮습니다. 낮은 창에서 그렇습니다.
     min-content 를 바닥으로 깔아 두면, 자리가 있을 때는 셋이 높이를 똑같이 나눠 갖고
     모자랄 때만 줄이 내용만큼 늘어나 칸이 스스로 굴러갑니다. 겹치지는 않습니다. */
  grid-template-rows: repeat(3, minmax(min-content, 1fr));
  height: 100%;
}

.course {
  display: flex; flex-direction: column; gap: 7px; min-width: 0; min-height: 0;
  border: 1px solid var(--rule); border-radius: 3px; padding: 14px 18px 15px;
  background: var(--paper);
}
.course h3 { font-size: clamp(17px, 2vh, 20px); font-weight: 700; margin: 0;
             letter-spacing: -.024em; line-height: 1.3; }
.course > p { font-size: clamp(13.5px, 1.6vh, 15px); line-height: 1.66; color: var(--ink-2); margin: 0; }
.course dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 0;
             font-size: clamp(13px, 1.5vh, 14px); }
.course dt { color: var(--ink-3); }
.course dd { margin: 0; color: var(--ink); }
/* 한글에 자간을 벌리면 글자가 흩어져 읽힙니다. 라벨이라도 그냥 둡니다. */
.course .c-level { font-family: var(--font-mono); font-size: 12px; font-weight: 600;
                   letter-spacing: 0; color: var(--accent); margin: 0; }
.course .c-meta { font-size: clamp(12.5px, 1.45vh, 13.5px); color: var(--ink-3); margin: -4px 0 0; }
.course .c-hands { font-size: 11.5px; font-weight: 600; letter-spacing: 0;
                   color: var(--accent); margin: -4px 0 0; }
.course .btn { margin-top: auto; align-self: flex-start; }

/* 카드 바깥의 사례 목록. 테두리를 두지 않습니다.
   상자를 또 두면 여섯 칸이 다 카드처럼 보여서 계단이 안 보입니다. */
.menu-side { display: flex; flex-direction: column; gap: 9px; min-width: 0; min-height: 0;
             padding: 16px 4px 0 2px; }
.menu-side h4 { font-size: clamp(12.5px, 1.45vh, 13.5px); font-weight: 600; margin: 0;
                color: var(--ink-3); }
.menu-side ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.menu-side li { position: relative; padding-left: 15px;
                font-size: clamp(13.5px, 1.6vh, 15px); line-height: 1.58; color: var(--ink-2); }
.menu-side li::before { content: ""; position: absolute; left: 0; top: .62em;
                        width: 7px; height: 1px; background: var(--accent); }
.menu-side .s-prep { margin: 3px 0 0; font-size: clamp(12.5px, 1.45vh, 13.5px);
                     color: var(--ink-3); line-height: 1.5; }

/* 1366×768 같은 낮은 화면에서는 기본 여백만으로 세 줄이 안 들어갑니다.
   글자를 줄이면 읽기가 나빠지므로 여백부터 깎습니다. 그래도 모자라면 칸이 굴러갑니다. */
@media (max-height: 860px) {
  .menu { gap: 11px; }
  .menu-wrap .kicker { margin-bottom: 7px; }
  .course { padding: 10px 14px 11px; gap: 5px; }
  .course dl { gap: 2px 10px; }
  .menu-side { padding: 10px 4px 0 2px; gap: 6px; }
  .menu-side ul { gap: 4px; }
}

/* ------------------------------------------------------------------ *
 * 12. 셀 05 · 연수 요청
 * ------------------------------------------------------------------ */
.ask { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
       gap: clamp(24px, 3.4vw, 56px); align-items: start; }
.ask-form { display: grid; gap: 12px; }
.field { display: grid; gap: 5px; min-width: 0; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
/* 격자 칸 안의 input 은 기본 폭(약 170px) 때문에 1fr 이 그 아래로 안 줄어듭니다.
   좁은 화면에서 통째로 넘칩니다. */
.field input, .field select, .field textarea { min-width: 0; }
.field label { font-size: 12.5px; color: var(--ink-3); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 14px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--rule); border-radius: 2px;
  padding: 11px 12px; min-height: 44px; width: 100%;
}
.field textarea { min-height: 104px; resize: vertical; line-height: 1.6; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent);
}
.ask-note { font-size: 13px; line-height: 1.75; color: var(--ink-3); }
.ask-say { margin: 0 0 10px; }
.form-msg { font-size: 13.5px; line-height: 1.6; margin: 0; min-height: 1.6em; }
.form-msg[data-kind="ok"]   { color: var(--accent); }
.form-msg[data-kind="bad"]  { color: #a8321f; }

/* ------------------------------------------------------------------ *
 * 13. 셀 06 · 노트
 * ------------------------------------------------------------------ */
.notes { list-style: none; margin: 0; padding: 0; }
.notes li { border-top: 1px solid var(--rule); }
.notes li:last-child { border-bottom: 1px solid var(--rule); }
.note {
  width: 100%; display: grid; grid-template-columns: 104px 1fr; gap: 18px;
  padding: 16px 4px; background: none; border: 0; cursor: pointer; text-align: left;
  align-items: baseline;
  transition: background .18s var(--ease);
}
.note:hover { background: var(--paper-2); }
.note .n-d { font-family: var(--font-mono); font-size: 12.5px; color: var(--accent);
             letter-spacing: .04em; font-variant-numeric: tabular-nums; }
.note h3 { font-size: clamp(17px, 1.5vw, 22px); font-weight: 700; margin: 0 0 5px; letter-spacing: -.026em; }
.note p { font-size: 13.5px; line-height: 1.7; color: var(--ink-3); margin: 0 0 8px; max-width: 62ch; }

/* 네이버에서 가져온 글. 본문은 저쪽에 있으므로 새 창으로 보냅니다.
   그렇게 간다는 것을 누르기 전에 알 수 있어야 해서 날짜 아래 표시를 답니다. */
.note--out { text-decoration: none; color: inherit; }
.note .n-out {
  display: block; margin-top: 5px; font-family: var(--font-mono); font-size: 10.5px;
  font-weight: 600; letter-spacing: .02em; color: var(--ink-3);
}
.note--out:hover .n-out { color: var(--accent); }
.notes-foot { margin: 18px 0 0; font-size: 14px; }

/* ------------------------------------------------------------------ *
 * 13-1. 관리 모드
 *
 * 로그인한 주인에게만 보입니다. 방문자는 Firebase SDK 자체를 안 받습니다.
 * 한 번 누르면 끝나는 것만 여기서 합니다. 제목이나 본문을 고치는 것은
 * 폼이 필요하므로 관리 화면을 그 작품이 열린 채로 띄웁니다.
 * 폼을 두 벌로 만들면 고칠 때마다 두 군데를 맞춰야 합니다.
 * ------------------------------------------------------------------ */
.admin-toggle {
  padding: 5px 10px; min-height: 28px; cursor: pointer; border-radius: 3px;
  background: rgba(18,19,22,.34); border: 1px solid rgba(255,255,255,.14);
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .01em;
  color: rgba(255,255,255,.8);
  transition: color .2s var(--ease), border-color .2s var(--ease),
              background .2s var(--ease), opacity .3s var(--ease);
}
body.on-light .admin-toggle {
  background: rgba(241,238,231,.56); border-color: rgba(22,23,26,.18); color: rgba(22,23,26,.68);
}
.admin-toggle:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
body.on-light .admin-toggle:hover { border-color: var(--accent); color: var(--accent); }
body.is-idle .admin-toggle { opacity: .36; }
body.is-admin .admin-toggle,
body.on-light.is-admin .admin-toggle {
  border-color: var(--accent-lit); color: var(--accent-lit);
}
body.on-light.is-admin .admin-toggle { border-color: var(--accent); color: var(--accent); }

/* 카드 묶음. 버튼 안에 버튼을 넣을 수 없어서 도구 줄을 밖으로 뺍니다. */
.work-cell, .pick-cell { display: flex; flex-direction: column; min-width: 0; }

.tools {
  display: none;                        /* 관리 모드에서만 나타납니다 */
  flex-wrap: wrap; gap: 6px;
  padding: 8px 10px;
  background: var(--deep-2);
  border-top: 1px solid var(--deep-rule);
}
body.is-admin .tools { display: flex; }

.tool {
  padding: 5px 9px; min-height: 30px; cursor: pointer; border-radius: 2px;
  background: transparent; border: 1px solid var(--deep-rule);
  font-size: 12px; color: var(--deep-ink-2);
  transition: border-color .18s var(--ease), color .18s var(--ease),
              background .18s var(--ease);
}
.tool:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
.tool[aria-pressed="true"] { background: var(--accent-lit); border-color: var(--accent-lit); color: #0d1113; }
.tool--danger:hover { border-color: #e0736a; color: #e0736a; }
.tool[disabled] { opacity: .4; cursor: default; }

/* 숨긴 작품은 관리자 눈에만 보이고, 숨김이라는 것이 드러나야 합니다. */
body.is-admin .work-cell.is-hidden .work,
body.is-admin .pick-cell.is-hidden .pick { opacity: .45; }

/* ------------------------------------------------------------------ *
 * 14. 리더 레이어
 *
 * 작품 상세와 글 읽기가 같은 레이어를 씁니다.
 * 셀 안에서 펼치지 않는 이유는 .cell-body 말고 다른 스크롤 상자를 만들면
 * 그 영역에서 카메라가 휠을 뺏기기 때문입니다.
 * ------------------------------------------------------------------ */
.reader {
  position: fixed; inset: 0; z-index: 120;
  display: grid; justify-items: end;
  background: rgba(18,19,22,.62);
  opacity: 0; visibility: hidden;
  transition: opacity .34s var(--ease), visibility .34s;
}
body.reading .reader { opacity: 1; visibility: visible; }
/* 닫았을 때 자리를 비우는 것은 리셋의 [hidden] 규칙이 맡습니다. */

.reader-panel {
  position: relative;
  width: min(780px, 100%); height: 100%;
  background: var(--paper); color: var(--ink);
  overflow-y: auto; overscroll-behavior: contain;
  padding: clamp(28px, 4vw, 56px) clamp(20px, 3.4vw, 60px) 80px;
  transform: translateX(28px);
  transition: transform .34s var(--ease);
  scrollbar-width: thin; scrollbar-color: var(--rule) transparent;
}
body.reading .reader-panel { transform: none; }
.reader-panel::-webkit-scrollbar { width: 7px; }
.reader-panel::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }

.reader-close {
  position: sticky; top: 0; float: right; z-index: 2;
  width: 44px; height: 44px; cursor: pointer; margin: -8px -8px 0 0;
  background: var(--paper); border: 1px solid var(--rule); border-radius: 50%;
  font-size: 18px; line-height: 1; color: var(--ink-2);
  transition: border-color .2s var(--ease), color .2s var(--ease);
}
.reader-close:hover { border-color: var(--accent); color: var(--accent); }

.reader-kicker { font-family: var(--font-mono); font-size: 11px; letter-spacing: .02em;
                 color: var(--accent); margin: 0 0 12px; }
.reader h2 { font-size: clamp(26px, 3.2vw, 40px); font-weight: 800; letter-spacing: -.04em;
             line-height: 1.16; margin: 0 0 12px; }
.reader-meta { display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
               font-size: 13px; color: var(--ink-3); margin: 0 0 22px;
               padding-bottom: 18px; border-bottom: 1px solid var(--rule); }
.reader-shot { margin: 0 0 22px; border: 1px solid var(--rule); border-radius: 3px; overflow: hidden;
               position: relative; aspect-ratio: 16 / 9; background: var(--paper-2); }
.reader-shot iframe { position: absolute; top: 0; left: 0; width: 1280px; height: 800px;
                      max-width: none; border: 0; transform-origin: 0 0;
                      transform: scale(var(--shot-scale, .55)); }
.reader-shot img { width: 100%; height: 100%; object-fit: cover; }

/* 글 본문. 에디터가 만든 HTML 이 여기 들어옵니다. */
.prose { font-size: 16px; line-height: 1.85; color: var(--ink-2); }
.prose > :first-child { margin-top: 0; }
.prose p { margin: 0 0 1.15em; }
.prose h1, .prose h2, .prose h3, .prose h4 {
  color: var(--ink); font-weight: 700; letter-spacing: -.028em; line-height: 1.34;
  margin: 1.9em 0 .6em;
}
.prose h1 { font-size: 1.62em; }
.prose h2 { font-size: 1.34em; }
.prose h3 { font-size: 1.14em; }
.prose a { color: var(--accent); text-decoration: none; border-bottom: 1px solid currentColor; }
.prose a:hover { color: var(--accent-dim); }
.prose ul, .prose ol { margin: 0 0 1.15em; padding-left: 1.3em; }
.prose li { margin-bottom: .4em; }
.prose img { max-width: 100%; height: auto; border-radius: 3px; margin: 1.2em 0; }
.prose blockquote {
  margin: 1.4em 0; padding: 2px 0 2px 18px;
  border-left: 2px solid var(--accent); color: var(--ink-3);
}
.prose code {
  font-family: var(--font-mono); font-size: .88em;
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: 2px; padding: 1px 5px;
}
.prose pre {
  background: var(--deep); color: var(--paper); padding: 16px 18px; border-radius: 3px;
  overflow-x: auto; font-size: 13.5px; line-height: 1.7; margin: 1.4em 0;
}
.prose pre code { background: none; border: 0; padding: 0; color: inherit; font-size: inherit; }
.prose table { width: 100%; border-collapse: collapse; margin: 1.4em 0; font-size: .94em; }
.prose th, .prose td { border: 1px solid var(--rule); padding: 8px 11px; text-align: left; }
.prose th { background: var(--paper-2); font-weight: 600; color: var(--ink); }
.prose hr { border: 0; border-top: 1px solid var(--rule); margin: 2em 0; }

.reader-foot { margin-top: 30px; padding-top: 20px; border-top: 1px solid var(--rule);
               display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* 주소를 복사할 때 잠깐 쓰는 상자. clipboard API 가 거절당했을 때의 옛날 방법입니다.
   화면에서 보이면 안 되지만 select() 가 먹어야 해서 .sr-only 처럼 잘라내지 않습니다. */
.copy-sink { position: fixed; top: 0; left: 0; width: 1px; height: 1px;
             opacity: 0; pointer-events: none; border: 0; padding: 0; }

/* ------------------------------------------------------------------ *
 * 14-1. 글 읽기 모드
 *
 * 작품 상세는 미리보기 한 장에 서너 줄이라 옆에서 열리는 편이 자연스럽습니다.
 * 글은 오래 스크롤하며 읽는 것이라 다릅니다. 왼쪽에 검은 화면이 남아 있으면
 * 시선이 갈라지고, 뒤의 카메라 화면이 보일 이유도 없습니다.
 * 그래서 글일 때만 종이로 화면을 덮고 가운데에 세웁니다.
 * notes/<slug>/ 정적 페이지와 같은 모양이라, 검색으로 들어온 사람과
 * 사이트 안에서 읽는 사람이 같은 화면을 봅니다.
 * ------------------------------------------------------------------ */
.reader.is-note { justify-items: center; background: var(--paper); }
.reader.is-note .reader-panel {
  width: min(820px, 100%);
  padding: 0 clamp(20px, 4vw, 60px) 100px;
  transform: translateY(20px);
}
body.reading .reader.is-note .reader-panel { transform: none; }

.reader.is-note .reader-close { display: none; }
.reader.is-note h2 { font-size: clamp(28px, 3.6vw, 44px); }
.reader.is-note .prose { font-size: 17px; }
.reader.is-note .reader-kicker { margin-top: 4px; }

/* 상단 막대. 패널과 같이 굴러가지 않고 위에 붙어 있습니다. */
.reader-bar { display: none; }
.reader.is-note .reader-bar {
  display: flex; align-items: center; gap: 14px;
  position: sticky; top: 0; z-index: 3;
  /* 패널의 좌우 여백만큼 도로 넓혀서 막대가 끝에서 끝까지 갑니다.
     clamp 는 최솟값이 최댓값보다 크면 안 되므로 음수는 calc 로 뒤집습니다. */
  margin: 0 calc(-1 * clamp(20px, 4vw, 60px)) clamp(22px, 3vw, 40px);
  padding: 14px clamp(20px, 4vw, 60px);
  background: var(--paper);
  border-bottom: 1px solid var(--rule);
}
.reader-back {
  background: none; border: 0; cursor: pointer; padding: 6px 2px;
  font-size: 13.5px; color: var(--accent);
}
.reader-back:hover { color: var(--accent-dim); }
.reader-bar-date { margin-left: auto; font-family: var(--font-mono);
                   font-size: 12px; color: var(--ink-3); }

/* ------------------------------------------------------------------ *
 * 14-7. 연수장 공통. 입장 막대
 *
 * 07 과 08 에 한 벌씩 있고 assets/room.js 가 같은 모양으로 그립니다.
 * 연수 중이 아니면 한 줄 안내, 연수 중이면 코드 입력칸, 들어오면 나가기 단추.
 * ------------------------------------------------------------------ */
.room-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 18px;
  padding: 14px 16px; margin-bottom: clamp(16px, 2.6vh, 28px);
  background: var(--deep-2); border: 1px solid var(--deep-rule); border-radius: 3px;
}
.room-bar[data-state="gate"] { border-color: var(--accent-lit); }
.rb-say { margin: 0; font-size: 14px; line-height: 1.6; color: var(--deep-ink-2); }
.rb-live {
  display: inline-block; margin-right: 6px; padding: 2px 8px; border-radius: 2px;
  background: var(--accent-lit); color: #0d1113; font-size: 12px; font-weight: 700;
}
.rb-out {
  margin-left: auto; min-height: 44px; padding: 8px 14px; cursor: pointer; border-radius: 3px;
  background: none; border: 1px solid var(--deep-rule); color: var(--deep-ink-2); font-size: 13px;
}
.rb-out:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
.rb-enter {
  margin-left: auto; display: grid; grid-template-columns: auto minmax(0, 150px) auto;
  align-items: center; gap: 6px 10px;
}
.rb-enter label { font-size: 13px; color: var(--deep-ink-2); }
.rb-msg { grid-column: 1 / -1; margin: 0; font-size: 13px; color: var(--accent-lit); min-height: 0; }
.rb-msg:empty { display: none; }

/* 검은 칸의 입력칸. 05 폼(종이)과 같은 크기, 색만 뒤집습니다. */
.rb-enter input, .card--form input[type="text"], .card--form input[type="url"],
.card--form textarea {
  font: inherit; font-size: 15px; color: var(--paper); min-width: 0; width: 100%;
  background: var(--deep); border: 1px solid var(--deep-rule); border-radius: 2px;
  padding: 10px 12px; min-height: 44px;
}
.rb-enter input { font-family: var(--font-mono); font-size: 17px; letter-spacing: .12em; text-align: center; }
.rb-enter input:focus, .card--form input:focus, .card--form textarea:focus {
  outline: none; border-color: var(--accent-lit); box-shadow: 0 0 0 1px var(--accent-lit);
}

/* 관리 모드에서만 막대 아래에 붙는 손잡이. 연수 시작·끝(assets/room.js 4-1) */
.rb-admin {
  flex-basis: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  padding-top: 12px; border-top: 1px dashed var(--deep-rule);
}
.rb-admin-k { font-size: 12px; font-weight: 700; color: var(--accent-lit); margin-right: 4px; }
.rb-admin label { font-size: 13px; color: var(--deep-ink-2); }
.rb-admin input {
  font: inherit; font-size: 15px; color: var(--paper); min-width: 0;
  background: var(--deep); border: 1px solid var(--deep-rule); border-radius: 2px;
  padding: 8px 10px; min-height: 40px;
}
.rb-admin input[name="label"] { width: 230px; }
.rb-admin input[name="code"] { width: 96px; font-family: var(--font-mono); letter-spacing: .12em; text-align: center; }
.rb-admin input:focus { outline: none; border-color: var(--accent-lit); box-shadow: 0 0 0 1px var(--accent-lit); }
.rb-admin-code { font-size: 13px; color: var(--deep-ink-2); }
.rb-admin-code b { margin-left: 8px; font-family: var(--font-mono); font-size: 18px; letter-spacing: .1em; color: var(--accent-lit); }
.rb-admin .btn, .rb-admin .tool { margin-left: auto; }
.b-flip { flex: none; margin-left: 8px; }

/* ------------------------------------------------------------------ *
 * 14-7a. 셀 07 · 자료실
 * ------------------------------------------------------------------ */
.bundles { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.bundle {
  padding: 16px 18px 14px; border: 1px solid var(--deep-rule); border-radius: 3px;
  background: transparent;
}
.bundle.is-open { background: var(--deep-2); border-color: #3f5d58; }
.b-head { display: flex; align-items: baseline; gap: 14px; }
.b-no { font-family: var(--font-mono); font-size: 12.5px; color: #878c94; font-variant-numeric: tabular-nums; }
.bundle.is-open .b-no { color: var(--accent-lit); }
.b-head h3 { margin: 0; font-size: clamp(16px, 1.4vw, 20px); font-weight: 700; letter-spacing: -.02em; }
.b-state {
  margin-left: auto; flex: none; font-size: 12px; padding: 2px 8px; border-radius: 2px;
  border: 1px solid var(--deep-rule); color: #878c94;
}
.bundle.is-open .b-state { border-color: var(--accent-lit); color: var(--accent-lit); }
.b-sum { margin: 6px 0 0 calc(12.5px * 2 + 14px); font-size: 14px; line-height: 1.65; color: var(--deep-ink-2); }
.b-meta { margin: 4px 0 0 calc(12.5px * 2 + 14px); font-size: 12.5px; color: #878c94; }
.b-lock { margin: 10px 0 0 calc(12.5px * 2 + 14px); font-size: 13px; color: #878c94; }
.b-files { list-style: none; margin: 12px 0 0; padding: 0; border-top: 1px solid var(--deep-rule); }
.b-files li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 14px;
  padding: 6px 0 6px calc(12.5px * 2 + 14px); border-bottom: 1px solid var(--deep-rule);
}
.b-files li:last-child { border-bottom: 0; }
.f-name { font-size: 14.5px; overflow-wrap: anywhere; }
.f-size { font-family: var(--font-mono); font-size: 12px; color: #878c94; }
.cell--deep .btn--ghost.f-get { background: transparent; color: var(--accent-lit); min-height: 40px; padding: 8px 16px; }
.cell--deep .btn--ghost.f-get:hover { background: var(--accent-lit); color: #0d1113; }
.b-empty { padding: 8px 0; }

/* ------------------------------------------------------------------ *
 * 14-8. 셀 08 · 과제 벽
 *
 * 과제가 가로 탭으로 놓이고, 그 아래가 카드 벽입니다. 카드 붙이기는 벽의 첫 칸이
 * 폼으로 펼쳐지는 방식입니다. 따로 창을 띄우면 리더처럼 스크롤 상자가 또 생깁니다.
 * ------------------------------------------------------------------ */
.wall-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; }
.wall-tabs:empty { display: none; }
.wall-tab {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 14px; cursor: pointer; border-radius: 3px;
  background: none; border: 1px solid var(--deep-rule); color: var(--deep-ink-2); font-size: 14px;
}
.wall-tab:hover { border-color: var(--accent-lit); color: var(--paper); }
.wall-tab[aria-pressed="true"] { background: var(--paper); border-color: var(--paper); color: var(--ink); font-weight: 600; }
.wt-on { font-size: 11px; font-weight: 700; color: var(--accent-lit); }
.wall-tab[aria-pressed="true"] .wt-on { color: var(--accent); }

.w-head { margin-bottom: 16px; }
.w-prompt {
  margin: 0 0 6px; font-size: clamp(20px, 2.1vw, 30px); font-weight: 800;
  line-height: 1.3; letter-spacing: -.03em; text-wrap: balance;
}
.w-state { margin: 0; font-size: 13px; color: #878c94; }
.w-lock { margin: 0; padding: 26px 0; font-size: 14px; color: #878c94; }

/* 관리 모드에서만. 과제 열기·고치기·받기 마감·공개(assets/room.js 6) */
.w-new { align-self: center; }
.w-admin { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; }
.w-form { max-width: 560px; }
.w-form .cf-check { margin-right: 14px; }

.cards {
  display: grid; gap: 12px; align-items: start;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.card {
  display: flex; flex-direction: column; min-width: 0;
  background: var(--deep-2); border: 1px solid var(--deep-rule); border-radius: 3px;
  overflow: hidden;
}
.card.is-pinned { border-color: var(--accent-lit); box-shadow: inset 0 3px 0 var(--accent-lit); }
.c-pic { aspect-ratio: 16 / 10; background: var(--deep); }
.c-pic img { width: 100%; height: 100%; object-fit: cover; }
.c-text { padding: 12px 14px 14px; display: grid; gap: 4px; }
.c-pin { margin: 0; font-size: 11.5px; font-weight: 700; color: var(--accent-lit); }
.c-name { margin: 0; font-size: 13px; color: #878c94; }
.c-line { margin: 0; font-size: 15px; line-height: 1.55; color: var(--paper); overflow-wrap: anywhere; }
.c-url { justify-self: start; margin-top: 4px; font-size: 13.5px; }
.c-mine { display: flex; gap: 6px; padding: 0 14px 12px; }
.c-act {
  min-height: 36px; padding: 6px 11px; cursor: pointer; border-radius: 2px;
  background: none; border: 1px solid var(--deep-rule); color: var(--deep-ink-2); font-size: 12.5px;
}
.c-act:hover { border-color: var(--accent-lit); color: var(--accent-lit); }
.c-tools { display: none; flex-wrap: wrap; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--deep-rule); }
body.is-admin .c-tools { display: flex; }

/* 붙이기 칸. 벽의 첫 칸입니다. */
.card--add {
  min-height: 150px; cursor: pointer; place-content: center; align-items: center; justify-content: center;
  background: transparent; border: 1px dashed #4c5a58; color: var(--accent-lit);
  font-size: 15px; font-weight: 600;
}
.card--add:hover { border-color: var(--accent-lit); background: var(--deep-2); }
.card--add::before { content: "+"; font-size: 28px; font-weight: 400; line-height: 1; margin-bottom: 6px; }

.card--form { padding: 14px; gap: 11px; border-color: var(--accent-lit); grid-row: span 2; }
.cf-field { display: grid; gap: 5px; min-width: 0; }
.cf-field label { font-size: 12.5px; color: var(--deep-ink-2); }
.card--form textarea { min-height: 64px; resize: vertical; line-height: 1.55; }
.card--form input[type="file"] { font-size: 13px; color: var(--deep-ink-2); min-width: 0; max-width: 100%; }
.cf-check { display: flex; align-items: center; gap: 8px; min-height: 36px; }
.cf-check input { width: 18px; height: 18px; accent-color: var(--accent-lit); }
.cf-msg { margin: 0; font-size: 13px; color: var(--accent-lit); }
.cf-msg:empty { display: none; }
.cf-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.cell--deep .card--form .btn--ghost { background: transparent; color: var(--accent-lit); }
.cell--deep .card--form .btn--ghost:hover { background: var(--accent-lit); color: #0d1113; }

/* ------------------------------------------------------------------ *
 * 14-9. 셀 09 · 마무리
 *
 * 아직 비워 두는 칸입니다. 판의 끝이라는 것만 알립니다.
 * 워드마크는 인트로와 같은 그림을 mask 로 씁니다. 가로세로비는 viewBox 그대로.
 * ------------------------------------------------------------------ */
.fin { display: grid; justify-items: center; gap: 22px; text-align: center; }
.fin-mark {
  width: min(560px, 70vw); aspect-ratio: 6494 / 1824;
  background: currentColor;
  -webkit-mask: url(brand/eompage-mark.svg?v=3589edf6) no-repeat center / contain;
          mask: url(brand/eompage-mark.svg?v=3589edf6) no-repeat center / contain;
}
.fin-line { margin: 0; font-size: clamp(14px, 1.2vw, 18px); color: var(--deep-ink-2); }
.cell--deep .fin .btn--ghost { background: transparent; color: var(--accent-lit); }
.cell--deep .fin .btn--ghost:hover { background: var(--accent-lit); color: #0d1113; }

/* ------------------------------------------------------------------ *
 * 15. 큰 화면
 *
 * 판면은 --measure 로 묶여 있는데 글자 크기는 그대로라, 2000px 화면에서
 * 가운데 작은 덩어리처럼 보입니다. 여기서 한 단 키웁니다.
 * ------------------------------------------------------------------ */
@media (min-width: 1600px) {
  :root { --measure: 1440px; }
  .lede { font-size: 19px; max-width: 42ch; }
  .fine { font-size: 15px; }
  .kicker { font-size: 13px; }
  .pick-t h3 { font-size: 22px; }
  .pick-t p { font-size: 15px; }
  .work h3 { font-size: 19px; }
  .work p { font-size: 15px; }
  .course h3 { font-size: 19px; }
  .course > p, .course dl { font-size: 15px; }
  .note p { font-size: 15px; }
  .prose { font-size: 17.5px; }
}

/* ------------------------------------------------------------------ *
 * 16. 좁은 화면
 * ------------------------------------------------------------------ */
@media (max-width: 880px) {
  .cell { padding: 54px 16px 18px; }
  .about { grid-template-columns: 1fr; gap: 20px; justify-items: start; }
  .picks, .menu { grid-template-columns: 1fr; }
  /* 좁은 화면에서 계단은 의미가 없습니다. 카드와 사례를 번갈아 한 줄로 놓습니다. */
  .menu--rows { grid-template-columns: 1fr; grid-template-rows: none; height: auto; }
  /* 한 줄로 떨어지면 높이를 나눠 가질 이유가 없습니다. 그대로 두면 판이 칸 높이로
     눌려서 카드가 제 높이보다 작아지고 글이 밖으로 삐져나옵니다. */
  .cell-body--fill { align-items: flex-start; }
  .menu-wrap { height: auto; }
  .menu-wrap .menu { flex: 0 0 auto; }
  .menu-side { padding: 0 2px; }
  .works { grid-template-columns: 1fr; }
  .ask { grid-template-columns: 1fr; gap: 20px; }
  .field-row { grid-template-columns: 1fr; }
  .note { grid-template-columns: 1fr; gap: 5px; }
  /* 연수장. 폰으로 들어오는 연수자가 제일 많습니다. 번호 들여쓰기를 걷고 입력칸을 넓힙니다. */
  .rb-enter { margin-left: 0; width: 100%; grid-template-columns: minmax(0, 1fr) auto; }
  .rb-enter label { grid-column: 1 / -1; }
  .b-sum, .b-meta, .b-lock { margin-left: 0; }
  .b-files li { padding-left: 0; grid-template-columns: minmax(0, 1fr) auto; }
  .f-size { display: none; }
  .cards { grid-template-columns: 1fr; }
  .cell-kr, .hud-hint { display: none; }
  .minimap { grid-template-columns: repeat(3, 28px); grid-auto-rows: 28px; }
  /* 미니맵과 모션 토글이 본문 끝을 가리지 않도록 스크롤 여백을 둡니다 */
  .cell-body { padding-bottom: 148px; }
  .cell-veil .v-name { font-size: 40px; }
  .cell-veil .v-sub { font-size: 18px; }
  .cell--paper::before { display: none; }
  .reader-panel { padding-bottom: 60px; }
}
@media (max-height: 640px) {
  .cell { padding-top: 52px; padding-bottom: 14px; }
}

/* ------------------------------------------------------------------ *
 * 17. 움직임 최소
 *
 * 미디어 쿼리 대신 :root[data-motion] 으로 거는 이유는, OS 가 "애니메이션 끔"
 * 이어도 이 사이트에서만 켤 수 있어야 하기 때문입니다. 판단은 <head> 의
 * 인라인 스크립트가 CSS 보다 먼저 합니다.
 *
 * 카메라 이동은 여기서 끄지 않습니다. 그건 장식이 아니라 길찾기라서,
 * 없애면 어디로 갔는지 알 수 없게 됩니다. site.js 가 시간과 후퇴 폭만 줄입니다.
 * ------------------------------------------------------------------ */
:root[data-motion="soft"] .cell [data-reveal] { opacity: 1; transform: none; transition: none; }
:root[data-motion="soft"] [data-depth] { transform: none; }
:root[data-motion="soft"] .pick:hover { transform: none; }
:root[data-motion="soft"] .reader-panel { transition: none; transform: none; }

/* ------------------------------------------------------------------ *
 * 18. 확인 창 (assets/dialog.js)
 *
 * 브라우저 기본 confirm·alert·prompt 대신 씁니다. 기본 창은 떠 있는 동안
 * 페이지를 멈춰서 원격 조작 도구가 누르지 못합니다. 리더(120)와 코드 화면(100)
 * 위에도 떠야 하므로 z-index 를 그보다 높게 둡니다.
 * ------------------------------------------------------------------ */
.dlg-back {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; padding: 20px;
  background: rgba(18,19,22,.62);
}
.dlg {
  width: min(440px, 100%); background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 4px;
  padding: 26px 26px 20px;
}
.dlg-text p { margin: 0; font-size: 15px; line-height: 1.7; overflow-wrap: anywhere; }
.dlg-text p + p { margin-top: 4px; color: var(--ink-3); font-size: 14px; }
.dlg-field { margin-top: 16px; }
.dlg-acts { display: flex; justify-content: flex-end; gap: 8px; margin-top: 22px; }
.btn--danger { background: #a8321f; border-color: #a8321f; }
.btn--danger:hover { background: #8d2a1a; border-color: #8d2a1a; }
