/* =====================================================================
   InnoLink — 레이아웃 셸 (M7: feature-spec.md §9)

   구조
     .il-shell
       ├─ .il-sidebar   240px 잉크 배경. 운영 / 탐색 / 구성 / 관리 4 카테고리
       └─ .il-main
            ├─ .il-topbar    통합 검색 · 기간 필터 · 계정
            └─ .il-content   페이지 본문

   규칙 (코딩 가이드 §11)
     · 375px 까지 반응형. body 는 절대 가로 스크롤되지 않는다
     · 넓은 화면에만 필요한 규칙은 @media (min-width:…) 로 범위를 명시한다
       — 파일 뒤쪽의 평범한 규칙이 위쪽 @media 를 덮지 않게
   ===================================================================== */

/* overflow-x: hidden 은 스크롤 컨테이너를 만들어 자식의 position:sticky 를 죽인다
   (사이드바가 아래로 스크롤하면 중간에서 끊긴다). clip 은 컨테이너를 만들지 않는다 */
html, body { max-width: 100%; overflow-x: clip; }

/* ★ 세로 스크롤바 자리를 늘 비워 둔다 (2026-09-08).
   화면이 길어지는 순간 스크롤바가 생기면서 **본문 전체가 그 폭만큼 왼쪽으로
   밀린다.** 감사 로그에서 줄 하나를 펼쳤을 때 눈에 띄었다 — 누른 꺾쇠가
   제자리에 있지 않고 옆으로 뛰었다. 접었다 펴는 것 · 더 보기 · 토스트처럼
   높이가 오르내리는 자리는 다 같은 증상을 낸다.
   자리를 처음부터 비워 두면 생기고 없어져도 아무것도 안 움직인다 */
html { scrollbar-gutter: stable; }

/* ── 셸 ────────────────────────────────────────────────────────────── */
.il-shell { display: flex; min-height: 100vh; }

/* ── 사이드바 ──────────────────────────────────────────────────────── */
.il-sidebar {
  width: var(--sidebar-w); flex: none;
  background: var(--ink); color: var(--on-ink-2);
  display: flex; flex-direction: column;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}

.il-sidebar__brand {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-5) var(--sp-4) var(--sp-4);
}
.il-sidebar__logo { font-size: var(--fs-lead); font-weight: 800; letter-spacing: -.02em; color: var(--on-ink); }

/* 접기 단추 — 로고 줄 오른쪽 끝 (2026-09-15) */
.il-sidebar__rail {
  flex: none; margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0;
  background: none; border: 0; border-radius: var(--radius-sm);
  color: var(--on-ink-3); cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.il-sidebar__rail:hover { background: var(--on-ink-hover); color: var(--on-ink); }
/* 접히면 같은 아이콘을 돌려 쓴다 — 둘을 두면 어느 쪽이 지금인지
   CSS 와 JS 두 곳에서 정하게 된다.
   판때기 아이콘이라 180° 돌리면 왼쪽 기둥이 오른쪽으로 갈 뿐,
   네모는 그대로다 (2026-09-17) */
.il-rail .il-sidebar__rail svg { transform: rotate(180deg); }
.il-sidebar__role {
  padding: 1px var(--sp-2); border-radius: var(--radius-full);
  border: 1px solid var(--on-ink-disabled); color: var(--on-ink-3);
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .04em;
}

/* 주 액션 — 가장 잦은 동작이 항상 1클릭 거리에 (vo.la 패턴) */

.il-nav { padding: 0 var(--sp-2) var(--sp-4); }
.il-nav__section + .il-nav__section { margin-top: var(--sp-5); }
.il-nav__label {
  padding: 0 var(--sp-2) var(--sp-2);
  font-size: var(--fs-micro); font-weight: var(--fw-micro); letter-spacing: var(--ls-micro);
  text-transform: uppercase; color: var(--on-ink-label);
}
.il-nav__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-2);
  /* WCAG 2.2 타깃 크기 — 최소 24px 를 넘긴다 */
  min-height: 36px;
  border-radius: var(--radius-sm);
  color: var(--on-ink-2); font-weight: 500;
  transition: background var(--t-fast), color var(--t-fast);
}
.il-nav__item:hover { background: var(--on-ink-hover); color: var(--on-ink); text-decoration: none; }
/* 활성 표시는 CSS 클래스 하나로. 렌더 후 JS 로 배경색을 칠하지 않는다.
   왼쪽 띠(border-left)는 2026-08-21 에 뺐다 — 배경 · 글자색 · 굵기 셋이
   이미 활성을 말하고, 스크린리더에는 aria-current="page" 가 따로 있다 */
.il-nav__item.is-active { background: var(--on-ink-active); color: var(--on-ink); font-weight: 620; }
.il-nav__icon { flex: none; width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1.6; }
.il-nav__text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.il-nav__count { font-size: var(--fs-caption); color: var(--on-ink-label); font-variant-numeric: tabular-nums; }

/* 밖으로 나가는 항목의 작은 화살표 (2026-09-15 — `GA 확인`).
   말하지 않으면 누른 사람은 이 앱이 통째로 GA 로 넘어간 줄 안다.

   글자보다 한 단 흐리다 — 이름이 먼저 읽히고 화살표는 그 뒤에 붙는
   단서다. 얹으면 글자를 따라 같이 진해진다 */
.il-nav__ext { flex: none; color: var(--on-ink-label); }
.il-nav__item:hover .il-nav__ext,
.il-nav__item.is-active .il-nav__ext { color: inherit; }

/* 하단 사용자 — 지금 무슨 권한으로 보고 있는지 항상 보인다 */
.il-sidebar__foot {
  margin-top: auto; padding: var(--sp-4);
  border-top: 1px solid var(--on-ink-active);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.il-sidebar__user { display: flex; align-items: center; gap: var(--sp-2); color: var(--on-ink); font-weight: 620; }
/* 로그아웃은 **POST** 다 (2026-09-02). 링크(GET)로 두면 남의 사이트에 심어 둔
   <img> 하나로 남을 로그아웃시킬 수 있어, 폼 + CSRF 토큰으로 받는다.
   그래서 이 자리는 <a> 가 아니라 <form> 안의 <button> 이다.

   ★ 버튼의 브라우저 기본값을 걷어야 한다. 안 걷으면 어두운 사이드바 위에
     회색 상자가 하나 떠 있다 — 링크처럼 보이던 자리가 갑자기 버튼이 된다.
     background · border · padding · font 넷 다 물려받게 만든다.

   폼은 display:contents 로 없앤다. 폼 상자가 남으면 그것이 flex 항목이 되어
   위 사용자 이름과의 gap 이 한 겹 더 생긴다 */
.il-sidebar__foot form { display: contents; }
.il-sidebar__logout {
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--on-ink-3); font-size: var(--fs-caption);
  background: none; border: 0; padding: 0;
  font: inherit; font-size: var(--fs-caption);
  text-align: left; cursor: pointer;
}
.il-sidebar__logout:hover { color: var(--on-ink); text-decoration: none; }

/* ══ 접은 사이드바 — 아이콘만 남는 좁은 기둥 (2026-09-15 · 사용자 요청) ══

   ★ 폭을 **토큰째로 바꾼다.** `.il-sidebar { width }` 만 줄이면 그 값을
     보고 있는 다른 자리가 안 따라온다 — 모달은 사이드바를 피해 가운데에
     서려고 `padding-left: calc(var(--sidebar-w) + …)` 를 쓴다 (아래 §모달).
     여기서 --sidebar-w 를 갈아 끼우면 그 계산이 저절로 맞는다.
     <html> 에 걸어야 한다: 모달이 .il-shell 밖에 그려지는 화면이 있다.

   ★ 넓은 화면에만 건다. 1024px 아래에서 사이드바는 덮어 뜨는 서랍이라
     (아래 @media) 폭을 줄이면 **서랍이 64px 로 뜬다** — 접는 것이 아니라
     고장이다. 그 폭에서는 접기 단추도 없다.

   ★ 통째로 감추지 않고 기둥을 남기는 까닭 — 감추면 다른 화면으로 가려고
     매번 펴야 한다. 240px 가 아까운 화면은 표가 넓은 관리자 화면인데,
     거기서 하는 일이 바로 화면을 오가는 것이다. */
@media (min-width: 1025px) {
  .il-rail { --sidebar-w: 64px; }

  /* 로고 · 권한 배지 · 사용자 이름 · 메뉴 글자 · 묶음 이름표가 빠진다.
     남는 것은 아이콘과 접기 단추뿐이다 */
  .il-rail .il-sidebar__logo,
  .il-rail .il-sidebar__brand .il-sidebar__role,
  .il-rail .il-nav__label,
  .il-rail .il-nav__text,
  /* 나가는 화살표도 같이 뺀다 — 접힌 기둥에는 아이콘 하나만 서고,
     무엇인지는 title 이 말한다 (shell.js) */
  .il-rail .il-nav__ext,
  .il-rail .il-sidebar__user,
  .il-rail .il-sidebar__logout > span { display: none; }

  /* 글자가 빠지면 가운데로 모은다 — 왼쪽에 붙여 두면 아이콘 줄이
     기둥 한쪽으로 쏠려 접힌 것이 아니라 잘린 것처럼 보인다 */
  .il-rail .il-sidebar__brand { justify-content: center; padding-inline: var(--sp-2); }
  .il-rail .il-sidebar__rail { margin-left: 0; }
  .il-rail .il-nav__item,
  .il-rail .il-sidebar__logout { justify-content: center; }
  .il-rail .il-sidebar__foot { padding-inline: var(--sp-2); }

  /* 이름표가 사라져도 누르는 자리는 그대로 넓게 둔다 (WCAG 2.5.8) —
     아이콘 크기로 줄이면 겨냥이 어려워진다 */
  .il-rail .il-nav__item { padding-inline: 0; }
}

/* ── 본문 ──────────────────────────────────────────────────────────── */
.il-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.il-topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: var(--sp-3);
  /* 배경과 아래 선은 끝까지 가되, 안의 것들은 본문과 같은 자리에서
     시작한다 (2026-08-25). 넓은 화면에서 본문만 가운데로 물러나면
     띠의 검색칸이 저 혼자 왼쪽 끝에 남아 어긋나 보인다 */
  min-height: var(--topbar-h); padding: var(--sp-2) var(--gutter);
  background: var(--bg-elevated); border-bottom: 1px solid var(--border);
}
.il-topbar__toggle { display: none; }        /* 좁은 화면에서만 노출 */
/* 검색·기간이 모두 꺼진 화면의 상단바는 빈 띠만 남는다. 넓은 화면에서는 없앤다
   (좁은 화면에서는 햄버거 때문에 다시 보여준다 — 아래 1024px 블록) */
.il-topbar--empty { display: none; }
.il-topbar__search { flex: 1 1 320px; max-width: 420px; min-width: 0; }
.il-topbar__spacer { flex: 1 1 auto; }
.il-daterange { display: flex; align-items: center; gap: var(--sp-2); }
.il-daterange .il-input { width: 130px; }

/* 좌우로 가운데 세운다 (2026-08-25). 폭을 열어 두니 화면을 옮길 때마다
   본문이 모니터 폭을 그대로 따라가 덜컹거렸다 — 홈에서 통계로 넘어갈 때
   특히 그랬다. 상한과 여백이 같이 있어야 넓은 화면에서도 자리가 안 흔들린다 */
.il-content {
  flex: 1 1 auto; width: 100%;
  max-width: var(--content-max); margin-inline: auto;
  padding: var(--sp-6) var(--content-pad) var(--sp-12);
}
/* 글이 주인 화면 — 한 줄이 너무 길어지면 읽기 어렵다 */
.il-content--reading { max-width: var(--reading-max); margin-inline: auto; }

.il-page-head { margin-bottom: var(--sp-5); }
.il-page-head__eyebrow { margin-bottom: 4px; }

/* 그룹 링크 통계 머리의 주소 줄 (2026-08-26 35차).
   .il-code 의 회색 상자를 걷어냈다 — 그것은 글 속에 낀 짧은 조각에 쓰는 것이라
   <p> 에 걸면 띠가 본문 폭을 가로지른다. 목록 줄·꾸미기 화면과 같은 모양으로 둔다 */
.il-pgd__addr {
  display: flex; align-items: center; gap: var(--sp-2);
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-lead); color: var(--text-secondary);
}
.il-page-head__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.il-page-head__row .il-title { flex: 1 1 auto; }

/* 제목 밑 한 줄 설명 (2026-09-15 · 그룹 링크 만들기).
   처음 온 사람에게 **무엇이 만들어지는지** 한 줄로 말하는 자리다.
   본문 크기(14px)로 둔다 — 캡션(12.5px)은 표 아래 각주에 쓰는 것이라,
   읽으라고 놓은 문장을 그 크기로 두면 읽지 않고 넘긴다.
   il-lead(16px)는 제목(24px)에 너무 가까워 둘이 겨룬다. */
.il-page-head__note {
  margin: 4px 0 0;
  font-size: var(--fs-body); color: var(--text-secondary);
  /* 폰에서는 두 줄이 된다(390px 이하). 그냥 두면 `만듭니다.` 한 마디만
     둘째 줄에 남아 문장이 끊긴 것처럼 보인다 — 두 줄을 고르게 나눈다.
     못 받는 브라우저는 그냥 예전처럼 흘려 넘긴다(문장은 그대로 읽힌다) */
  text-wrap: balance;
}

/* 섹션 · 그리드 */
.il-stack { display: flex; flex-direction: column; gap: var(--sp-5); }
.il-grid { display: grid; gap: var(--sp-5); }
.il-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.il-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.il-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.il-grid-sidebar { grid-template-columns: minmax(0, 1fr) 320px; }   /* 본문 + 우측 패널 */

/* 링크 행 — 목록에서 단축 URL 복사가 항상 1클릭 (vo.la 패턴) */
.il-linkrow { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.il-linkrow__title { font-weight: 620; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.il-linkrow__short { display: flex; align-items: center; gap: var(--sp-2); color: var(--accent); font-weight: 620; }
.il-linkrow__dest { color: var(--text-muted); font-size: var(--fs-caption); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 아직 안 채운 칸 — 홈 카드의 빈 칩과 같은 말투다 ('+ 제목' · '+ 프로젝트').
   비어 있다는 것과 채울 수 있다는 것을 한 번에 말한다 */
.il-linkrow__empty { color: var(--text-placeholder); font-weight: 620; }
[data-edit]:hover .il-linkrow__empty { color: var(--ink); }
/* 표 안에서는 밑줄 대신 배경으로 짚어 준다 — 줄이 촘촘해 밑줄이 겹쳐 보인다 */
.tabulator [data-edit] { display: inline-block; max-width: 100%; border-radius: var(--radius-sm); }
.tabulator [data-edit]:hover { background: var(--bg-subtle); box-shadow: 0 0 0 3px var(--bg-subtle); }
.il-copy { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
  background: none; border: 0; border-radius: 6px; color: var(--text-muted); cursor: pointer; }
.il-copy:hover { background: var(--bg-subtle); color: var(--ink); }

/* 실시간 클릭 피드 */
.il-feed { display: flex; flex-direction: column; }
.il-feed__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) 0; border-bottom: 1px solid var(--border); font-size: var(--fs-caption); }
.il-feed__row:last-child { border-bottom: 0; }
.il-feed__time { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* 인쇄 — PDF 리포트 미리보기 */
@media print {
  .il-sidebar, .il-topbar, .il-btn, .il-bulkbar { display: none !important; }
  .il-content { max-width: none; padding: 0; }
  .il-card, .reb-chart-card, .reb-table-wrap { break-inside: avoid; border-color: var(--border-strong); }
}

/* =====================================================================
   반응형 — 아래 규칙은 이 파일 끝에 둔다.
   여기에 새 규칙을 더할 때는 위쪽 @media 를 덮지 않는지 먼저 확인한다.
   ===================================================================== */

/* 태블릿 — 2·3열 그리드를 접는다 */
@media (max-width: 1100px) {
  .il-grid-3, .il-grid-4, .il-kpi-row-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .il-kpi-row-2a { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .il-kpi-row-3a { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .il-kpi-row-5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .il-grid-sidebar { grid-template-columns: minmax(0, 1fr); }
  .il-chartrow.is-split { grid-template-columns: minmax(0, 1fr); }
  .il-grid-donut { grid-template-columns: minmax(0, 1fr); }
  /* 한 열로 접히면 세로 구분선은 뜻이 없다 */
  .il-split-col { border-left: 0; padding-left: 0; }
}

/* ── 모달은 본문 영역 기준으로 가운데 선다 (2026-09-01) ──────────────
   .il-modal 은 position:fixed 라 화면 전체가 기준이다. 그러면 사이드바
   240px 만큼 왼쪽으로 치우쳐 보인다 — 사람이 보고 있던 것은 본문이고,
   창은 그 본문 위에 떠야 하기 때문이다.

   덮개(.il-modal__scrim)는 그대로 화면 전체다. 절대 위치 자식의 기준은
   판의 padding box 라 이 여백 바깥까지 덮는다.

   사이드바가 자리를 차지하는 폭에서만이다. 1024px 아래에서는 사이드바가
   겹쳐 뜨는 서랍이라 본문이 화면 전체이고, 치우침도 없다 */
@media (min-width: 1025px) {
  .il-modal.is-open { padding-left: calc(var(--sidebar-w) + var(--sp-4)); }
}

/* 사이드바를 오버레이로 — 1024px 미만 */
@media (max-width: 1024px) {
  .il-sidebar {
    position: fixed; z-index: 40; left: 0; top: 0;
    transform: translateX(-100%); transition: transform var(--t-base);
    box-shadow: var(--shadow-xl);
    /* ★ 100vh 가 아니라 100dvh 다 (2026-09-11).

       ── 무슨 일이 있었나 ──────────────────────────────────────────
       폰에서 메뉴를 열면 **`로그아웃` 이 안 보였다.** 서랍 안을 굴리면 나왔다.

       `vh` 는 iOS 에서 **주소창과 아래 도구막대가 없는 셈 친 높이**다
       (큰 뷰포트). 그런데 그 막대들은 처음에 떠 있으므로, 실제로 보이는
       칸은 그보다 낮다. 서랍은 위 규칙대로 100vh 만큼 서고 맨 아래 칸
       (사용자 이름 · 로그아웃)은 `margin-top: auto` 로 그 끝에 붙으니 —
       정확히 **도구막대 아래**, 안 보이는 자리에 놓였다.

       `dvh` 는 **지금 실제로 보이는 만큼**이다. 막대가 접히면 따라 늘어난다.
       위의 `height: 100vh` 는 그대로 둔다 — dvh 를 모르는 브라우저가
       받을 값이다 (모르면 이 줄을 통째로 버린다).

       ★ 넓은 화면(sticky 사이드바)에는 걸지 않는다. 거기서는 100vh 가
         맞고, 굳이 바꿀 이유가 없다 */
    height: 100dvh;
  }
  .il-sidebar.is-open { transform: translateX(0); }

  /* ★ 접기 단추는 여기 없다 (2026-09-15). 이 폭에서 사이드바는 덮어 뜨는
     서랍이라 `접는다` 는 말이 성립하지 않는다 — 여닫는 것은 상단 햄버거가
     맡는다. 남겨 두면 서랍 안에 여닫는 단추가 둘이 되고, 둘이 하는 일이
     다르다 (하나는 닫고 하나는 좁힌다) */
  .il-sidebar__rail { display: none; }

  /* ★ 상단 띠도 본문과 같은 바탕이다 (2026-09-11).

     넓은 화면에서 이 띠는 **검색칸과 기간 고르개를 얹는 판**이라 흰 바탕에
     아래 선 한 줄로 서 있는 편이 맞다. 좁은 화면은 다르다 — 지금 어느 화면도
     그 둘을 켜지 않아서(layouts/app 의 머리말), 띠에 남는 것은 **햄버거
     하나**뿐이다. 그 빈 흰 띠가 회색 본문 위에 얹히면 아무 일도 하지 않으면서
     화면을 위아래로 가른다. 사진의 그 자리다.

     바탕을 본문과 맞추면 햄버거가 화면 위에 그냥 놓인 것처럼 보인다.

     ★ 아래 선도 뺀다. 처음에는 남겼다 — 이 띠가 sticky 라 본문이 그 밑으로
       밀려 들어갈 때 경계가 필요하다고 봤다. 그런데 바탕이 본문과 같아지면
       그 선만 혼자 남아, 아무것도 가르지 않으면서 **가르는 시늉**을 한다
       (띠가 비어 있어 선 위에는 햄버거뿐이다).
       경계는 선이 아니라 **글이 사라지는 것**으로 이미 보인다 — 같은 색
       띠 밑으로 미끄러져 들어가면 그 자리에서 잘린다. */
  .il-topbar { background: var(--bg); border-bottom: 0; }
  /* 아래 여백에 safe-area 를 더한다 — 막대가 접히면 그 자리를 홈 인디케이터가
     차지하고, 그때 `로그아웃` 이 그것에 물린다 */
  .il-sidebar__foot {
    padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
  }
  .il-topbar--empty { display: flex; }
  .il-topbar__toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px; flex: none;
    background: none; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
    color: var(--ink); cursor: pointer;
  }
  .il-scrim { position: fixed; inset: 0; z-index: 35; background: var(--overlay); display: none; }
  .il-scrim.is-open { display: block; }
}

/* 모바일 */
@media (max-width: 720px) {
  .il-grid-2, .il-grid-3, .il-kpi-row-3, .il-kpi-row-3a, .il-kpi-row-4, .il-kpi-row-5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .il-content { padding-top: var(--sp-4); padding-bottom: var(--sp-10); }
  .il-topbar { padding-block: var(--sp-2); }
  .il-daterange .il-input { width: 112px; }
  /* 필터 바 — 한 줄에 다 못 들어간다. 필드를 통째로 한 줄씩 내린다 */
  .il-filterbar__field { flex: 1 1 100%; flex-wrap: wrap; }
  .il-filterbar__field .il-select { flex: 1 1 160px; width: auto; min-width: 0; }
  .il-filterbar .il-input--date,
  .il-toolbar .il-input--date { flex: 1 1 110px; width: auto; min-width: 0; }
  .reb-kpi-value { font-size: var(--fs-heading); }
}

/* 375px — 최소 지원 폭. 한 열로 내린다 */
@media (max-width: 520px) {
  .il-grid-2, .il-grid-3, .il-kpi-row-2, .il-kpi-row-2a, .il-kpi-row-3, .il-kpi-row-3a, .il-kpi-row-4, .il-kpi-row-5 { grid-template-columns: minmax(0, 1fr); }
  .il-kpi-cols--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .il-topbar { flex-wrap: wrap; }
  .il-topbar__search { flex-basis: 100%; order: 3; max-width: none; }
  .il-segment { width: 100%; }
  .il-segment__btn { flex: 1 1 auto; }

  /* ★ 기간 프리셋만 **격자로 세운다** (2026-09-11).

     ── 무슨 일이 있었나 ──────────────────────────────────────────────
     프리셋이 폰에서 한 줄에 안 들어간다. flex 가 접으면 남은 자리를
     `flex:1` 이 글자 길이 비율대로 나눠 주므로 아랫줄의 한둘만 유난히
     커진다 — 접힌 것이 아니라 **망가진 것**처럼 읽힌다.

     ── 어떻게 세우나 ─────────────────────────────────────────────────
     열두 칸 격자에 **다섯을 한 줄로** 앉힌다 (2026-09-15 2차).
     균등하게 다섯으로 나누면 칸이 55px 인데 `최근 30일` 은 글자만 그만큼이라
     넘친다 — 그래서 **글자 길이에 맞춰 나눈다**:

         전체 | 오늘 | 어제 | 최근 7일 | 최근 30일
          2      2      2       3          3         (합 12)

     짧은 셋은 두 칸씩, 긴 둘은 세 칸씩이다. 좌우 안여백도 4px 로 줄인다 —
     격자에서는 단추가 칸을 꽉 채우므로 여백은 눈에 안 보이고 **넘칠 여지만**
     줄여 준다. 공짜로 얻는 자리다.

     ★ 두 줄(3 + 2)로 눕혔던 것을 한 줄로 되돌린 것이다. 접힌 모양이
       가지런하더라도, 기간은 **서로 견주어 고르는 것**이라 다섯이 한눈에
       들어오는 편이 낫다.

     ★ 개수가 바뀌면 이 규칙도 같이 본다 — 칸 수를 손으로 적는 격자의 값이자
       대가다 (일곱이던 때는 4 + 3 두 줄이었다).

     ── 왜 `.il-segment` 전체에 걸지 않나 ─────────────────────────────
     세그먼티드는 이 화면에만 있는 부품이 아니다 — 기기 고르개(셋) · 분석
     기준(둘) · 로그 종류(둘) · 관리자 로그의 기간(넷)이 같은 클래스를 쓴다.
     그것들이 도리어 깨지므로 **기간 프리셋에만** 이름을 하나 더 준다.

     ★ 480px 언저리부터 한 줄에 들어간다 (재어 봤다). 이 규칙이 도는 520px
       아래에서는 어차피 접히던 자리라, 접힌 모양만 가지런해진다. */
  .il-segment--period {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
  }
  /* 뒤 둘 — 최근 7일 · 최근 30일 (이름이 긴 쪽) */
  .il-segment--period .il-segment__btn { grid-column: span 3; }
  /* 앞 셋 — 전체 · 오늘 · 어제 */
  .il-segment--period .il-segment__btn:nth-child(-n+3) { grid-column: span 2; }
  .il-segment--period .il-segment__btn { padding: 0 4px; }

  /* ★ `직접선택` 라벨을 제 줄로 내린다 (2026-09-11).

     한 줄에 다섯(라벨 · 시작일 · — · 종료일 · 검색 · 초기화)이 안 들어가는데,
     flex 가 아무 데서나 접으니 **`—` 만 줄 끝에 홀로 남는** 모양이 나왔다.
     날짜 둘이 갈라지면 그 줄표는 아무것도 잇지 못한다.

     라벨을 미리 내려 주면 남은 폭을 날짜 둘이 나눠 갖고, 줄표는 그 사이에
     붙어 있는다. 검색 · 초기화는 자연히 다음 줄로 간다.

         직접선택
         [시작일] — [종료일]
         [검색] [초기화]

     ★ 손가락 기기의 칸 글자가 16px 로 커지면서(components.css) 날짜 칸이
       빠듯해진 것도 여기서 함께 풀린다 — 110px 에 묶여 `YYYY-MM-DD` 가
       잘리던 것이, 줄을 통째로 쓰면서 130px 남짓으로 늘어난다.

     ※ 마크업의 `라벨과 칸은 한 덩어리` 라는 주의와 어긋나지 않는다.
       그것은 라벨만 **앞줄 끝에 남는** 것을 막으려던 것이고, 여기서는
       제 칸 바로 위에 선다 — 무엇을 가리키는지가 그대로 읽힌다 */
  .il-filterbar__field > .il-filterbar__label { flex: 1 1 100%; }
  /* 날짜 둘이 그 줄의 대부분을 차지하게 한다. 110px 로 묶어 두면 폭이
     조금 남는 기기(414px 언저리)에서 `검색` 이 그 줄에 비집고 들어오고,
     그만큼 날짜 칸이 줄어 **글자가 잘린다.** 둘이 40%씩 깔고 앉으면
     남는 자리가 단추 하나만큼이 안 되어 자연히 다음 줄로 간다 */
  .il-filterbar .il-input--date { flex: 1 1 40%; min-width: 0; }

  /* ★ 분석 탭의 고르개는 **제 줄**을 갖는다 (2026-09-11).
     탭 다섯이 이미 가로로 넘치는 폭이라, 같은 줄에 두면 화면 밖으로 밀려
     있는 줄도 모르게 된다. 아래로 내리면 늘 보이고, 폭을 다 쓰므로
     세 단추가 한 줄에 가지런히 선다 (.il-segment 가 100% 다).
     탭 줄은 이제 높이가 고정된다 — 탭을 옮겨도 들썩이지 않는다.
     까닭은 components.css 의 `.reb-tabsbar` 에 적어 두었다 */
  .reb-tabsbar { flex-wrap: wrap; }
  .reb-tabsbar > .reb-tabs { flex: 1 1 100%; }
  .reb-tabsbar > .il-dimswitch {
    flex: 1 1 100%;
    margin-left: 0;
    padding: var(--sp-3) var(--sp-4);
    border-top: 1px solid var(--border);
  }
  .il-daterange { flex: 1 1 auto; }
  .il-daterange .il-input { flex: 1 1 auto; width: auto; min-width: 0; }
  /* 좁은 화면에서는 여백을 줄여 창이 넓게 선다.
     패널이 아니라 판의 padding 을 줄인다 (components.css §모달) —
     패널에 margin 을 다시 붙이면 가운데 정렬이 그만큼 어긋난다.
     사이드바가 이 폭에서는 겹쳐 뜨는 서랍이라 자리를 차지하지 않는다 */
  .il-modal.is-open { padding: var(--sp-4) var(--sp-2); }
  .reb-pin-cell { width: 38px; height: 46px; }
}

/* =====================================================================
   접근성 보완 (Phase 3 검수 반영)
   ===================================================================== */

/* 스킵 링크 — 평소 숨어 있다가 Tab 을 누르면 나타난다 (WCAG 2.4.1) */
.il-skip {
  position: absolute; left: var(--sp-3); top: -60px; z-index: 70;
  padding: var(--sp-2) var(--sp-4);
  background: var(--ink); color: var(--text-inverse);
  border-radius: var(--radius-sm); font-weight: 620;
  transition: top var(--t-fast);
}
.il-skip:focus { top: var(--sp-3); text-decoration: none; }

/* 포커스가 상단 고정바에 가리지 않게 (WCAG 2.4.11) */
.il-content :focus-visible,
.reb-table :focus-visible { scroll-margin-top: calc(var(--topbar-h) + var(--sp-4)); }
#ilMain:focus { outline: none; }

/* 타깃 크기 — 체크박스 실효 영역을 24px 로 확보 (WCAG 2.5.8) */
.reb-table input[type="checkbox"],
.il-check {
  min-width: 24px; min-height: 24px;
  width: 24px; height: 24px; margin: 0; padding: 0;
}

/* 모션 최소화 설정을 존중한다 (WCAG 2.3.3) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =====================================================================
   좁은 화면 방어 — flex 자식의 min-width

   flex 자식의 기본값은 min-width:auto 라서 "내용보다 작아지지 못한다".
   .il-content 안에 min-width:720px 인 표가 있을 때 이 값이 없으면 컬럼 전체가
   720px 아래로 줄지 않아 문서가 가로로 넘칠 수 있다.
   (375px 실측에서는 현재 마크업 기준 넘침이 없지만, 앞으로 더 넓은 표나
    긴 코드 블록이 들어와도 깨지지 않게 미리 걸어 둔다 — 가이드 §11)
   ===================================================================== */
.il-main > .il-topbar,
.il-main > .il-content { min-width: 0; }
.il-content > * { min-width: 0; }

/* 도넛이 컬럼 폭만큼 늘어나 화면을 잡아먹지 않게 */
.reb-chart[data-chart="donut"] svg { max-width: 240px; margin: 0 auto; }

/* =====================================================================
   로그인 — 좌우 2단 (login.html 전용)

   왼쪽은 잉크면, 오른쪽은 흰 면이다. 사이드바와 같은 --ink / --on-ink-*
   짝을 쓴다 — 로그인에서 처음 보는 검정이 로그인 뒤 사이드바의 검정과
   같아야 "같은 도구에 들어왔다" 로 읽힌다.

   960px 아래에서는 위아래로 쌓는다. 좁은 화면에서 왼쪽 잉크면을 반으로
   유지하면 정작 눌러야 할 버튼이 접힌 아래로 밀린다.
   ===================================================================== */
.il-login { display: flex; min-height: 100vh; }

.il-login__brand {
  flex: 1 1 50%;
  background: var(--ink); color: var(--on-ink);
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--sp-12) clamp(var(--sp-6), 6vw, var(--sp-18));
}
.il-login__brand-inner { width: 100%; max-width: 380px; margin-inline: auto; }

.il-login__mark {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-8);
}
.il-login__mark svg { flex: none; }

.il-login__pitch { font-weight: 620; line-height: var(--lh-body); margin-bottom: var(--sp-6); }

/* 목록 마커를 직접 그린다 — 기본 불릿은 잉크면에서 너무 밝게 뜬다 */
.il-login__points { list-style: none; margin: 0; padding: 0; }
.il-login__points li {
  display: flex; align-items: center; gap: var(--sp-3);
  color: var(--on-ink-2); font-size: var(--fs-caption);
  padding: var(--sp-2) 0;
}
.il-login__points li::before {
  content: ''; flex: none;
  width: 5px; height: 5px; border-radius: var(--radius-full);
  background: var(--on-ink-label);
}

.il-login__panel {
  flex: 1 1 50%;
  background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-12) clamp(var(--sp-6), 6vw, var(--sp-18));
}
.il-login__panel-inner { width: 100%; max-width: 420px; }

@media (max-width: 960px) {
  .il-login { flex-direction: column; min-height: 100vh; }
  .il-login__brand { flex: none; padding: var(--sp-10) var(--sp-6); }
  .il-login__panel { flex: 1 1 auto; padding: var(--sp-10) var(--sp-6); }
  .il-login__brand-inner, .il-login__panel-inner { max-width: none; }
}

/* =====================================================================
   링크 (links.html) — 붙여 넣고 끝나는 화면
   2026-08-25 2차 리뷰. linktr.ee 의 link shortener 를 참고했다.

   왜 컴포넌트를 새로 만드나
     나머지 화면은 "관리 도구" 라 정보 밀도가 우선이다. 홈은 반대다 —
     **한 가지 동작(링크 만들기)만** 하는 곳이라, 그 하나를 크게 놓고
     나머지를 비운다. 기존 .il-card · .il-input 을 그대로 쓰면
     목록 화면과 구분이 안 돼서 "여기서 뭘 하는 곳인지" 가 흐려진다.

   토큰은 그대로 쓴다. 크기와 여백만 이 화면 기준으로 다시 잡았다.
   ===================================================================== */

/* 폭은 --list-max 다. 그룹 링크 · 프로젝트 목록(.il-listbox)이 같은 값을 쓴다 */
.il-home { max-width: var(--list-max); margin-inline: auto; }

/* ── 히어로 — 입력 하나, 버튼 하나 ────────────────────────────────── */
.il-home__hero { padding: var(--sp-12) 0 var(--sp-10); text-align: center; }
.il-home__title {
  font-size: clamp(28px, 4vw, 40px); font-weight: 800;
  letter-spacing: -.03em; line-height: 1.2;
  /* ★ sp-3 → sp-8 (2026-09-14 3차). 부제를 지우면서 그 아래 여백(sp-8)이
     같이 사라져 제목이 입력 알약에 달라붙었다. 부제가 들고 있던 간격을
     제목이 이어받는다 — 히어로에 남는 것은 제목 · 알약 · 버튼 셋뿐이다 */
  margin-bottom: var(--sp-8);
}
/* .il-home__sub 는 걷어냈다 (2026-09-14 3차) — 쓰는 화면이 없다.
   부제가 하던 말(`나머지는 나중에 채워도 됩니다`)은 아래 카드의
   `선택 사항` 이름표가 이미 하고 있었다 */

/* 알약 한 덩어리. 입력과 버튼이 하나로 보여야 "여기에 붙여 넣는다" 가 읽힌다 */
.il-paste {
  display: flex; align-items: center; gap: var(--sp-2);
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong); border-radius: var(--radius-full);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-6);
  box-shadow: var(--shadow-lg);
  transition: border-color var(--t-fast);
}
.il-paste:focus-within { border-color: var(--ink); }
.il-paste.is-bad { border-color: var(--danger); }
.il-paste__input {
  flex: 1 1 auto; min-width: 0;
  height: 52px; border: 0; background: transparent; outline: none;
  font-size: var(--fs-lead); color: var(--ink);
}
/* 알약 테두리가 :focus-within 으로 이미 어두워진다 (바로 위 규칙).
   안쪽에 링을 또 두면 테두리 · 여백 · 링으로 세 줄이 겹친다 */
.il-paste__input:focus-visible { box-shadow: none; }
.il-paste__input::placeholder { color: var(--text-muted); }
.il-paste__btn {
  flex: none; height: 52px; padding: 0 var(--sp-6);
  border: 0; border-radius: var(--radius-full);
  background: var(--ink); color: var(--text-inverse);
  font-size: var(--fs-body); font-weight: 700; cursor: pointer;
  transition: background var(--t-fast);
}
.il-paste__btn:hover { background: var(--ink-hover); }
.il-home__err {
  margin-top: var(--sp-3); font-size: var(--fs-caption); color: var(--danger);
}

/* ── 선택 — 제목 · 프로젝트 (2026-09-01) ──────────────────────────
   알약 밑에 늘 펼쳐져 있다. 접었다 폈다 하지 않는다.

   1차에는 칩 두 개로 접어 뒀다가 같은 날 다시 폈다. 접어 두는 편이
   "묻는 것은 하나뿐" 이라는 약속에 맞아 보였는데, 실제로는 한 가지 동작을
   두 걸음으로 늘린 것이었다 — 열고, 적고, 접고.
   특히 프로젝트가 그랬다. 붙일 수 있다는 것을 몰라서 안 붙이는 쪽이,
   칸이 보여서 성가신 쪽보다 훨씬 잦다.

   그럼 "빈 칸은 채우라는 뜻으로 읽힌다" 는 걱정은 접힘이 아니라 **글자**가
   맡는다 — 머리의 '선택 사항', 그리고 칸마다 붙은 안내 한 줄.

   무게는 여전히 알약이 가져간다
     알약   52px · 잉크 버튼 · --shadow-lg · 폭 100%
     패널   42px · 글자 칸만 · --shadow-sm · 폭 100% - 48px */
.il-opt { margin-top: var(--sp-4); }

/* 알약보다 한 뼘(sp-6 씩) 안쪽으로 물러선다 */
.il-opt__panel {
  width: calc(100% - var(--sp-12)); margin: var(--sp-3) auto 0;
  text-align: left;
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  box-shadow: var(--shadow-sm);
}

/* 머리 — '선택 사항' 한 마디. 이 패널이 무엇인지를 말하는 유일한 자리다 */
.il-opt__head { margin-bottom: var(--sp-4); }
.il-opt__eyebrow {
  font-size: var(--fs-micro); font-weight: var(--fw-micro);
  letter-spacing: var(--ls-micro); color: var(--text-muted);
}

/* 제목이 넓다 — 문장이 들어가는 칸이고, 프로젝트는 고르는 칸이라
   가장 긴 이름만 들어가면 된다 */
.il-opt__grid {
  display: grid; grid-template-columns: 1.35fr 1fr; gap: var(--sp-5);
}
.il-opt__f { min-width: 0; }
.il-opt__lab {
  display: block; margin-bottom: var(--sp-2);
  font-size: var(--fs-caption); font-weight: 620; color: var(--text-secondary);
}
/* 이름표 줄 — 왼쪽에 이름표, 오른쪽 끝에 보조 동작(`프로젝트 생성`).
   components.css 의 .il-field__head 와 같은 규칙이다: **줄이 높이를 고정한다.**
   버튼이 있는 칸만 줄이 높아지면 나란히 선 두 입력칸이 어긋나므로,
   버튼이 없는 제목 칸도 같은 줄 상자를 쓴다 (min-height 28px = il-btn--sm) */
.il-opt__labrow {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); min-height: 28px; margin-bottom: var(--sp-2);
  /* 물음표 레이어가 이 줄에 매달린다 (.il-opt__tip 은 absolute 다).
     기준이 없으면 훨씬 위 조상에 붙어 칸과 상관없는 자리에 뜬다 */
  position: relative;
}
.il-opt__labrow .il-opt__lab { margin-bottom: 0; }
/* 이름표와 물음표는 한 덩어리다 (2026-09-03).
   줄 상자가 space-between 이라 따로 두면 물음표가 오른쪽 끝까지 밀린다 —
   이름표에서 한 뼘 떨어진 물음표는 무엇을 설명하는지 안 읽힌다 */
.il-opt__labgrp { display: inline-flex; align-items: center; gap: var(--sp-1); min-width: 0; }
/* 버튼은 이 저장소의 버튼(.il-btn--sm · 28px)을 그대로 쓴다.
   여기만 다르게 그리면 `누를 수 있는 것` 의 생김새가 화면마다 갈린다 */
.il-opt__labrow .il-btn { flex: none; }
/* 알약 안의 칸과 달리 여기는 테두리를 그린다 — 흰 패널 위라
   테두리가 없으면 어디까지가 칸인지 안 보인다 */
.il-opt__in {
  width: 100%; height: 42px; padding: 0 var(--sp-4);
  border: 1px solid var(--border-strong); border-radius: var(--radius-full);
  background: var(--bg-elevated); color: var(--ink);
  font-family: inherit; font-size: var(--fs-body); outline: none;
  transition: border-color var(--t-fast);
}
.il-opt__in::placeholder { color: var(--text-placeholder); }
/* 테두리 한 줄이 잉크로 바뀌는 것으로 말한다 — 링을 겹치지 않는다
   (tokens.css §--focus-ring 의 규칙) */
.il-opt__in:focus, .il-opt__in:focus-visible { border-color: var(--ink); box-shadow: none; }

/* ── 고르는 칸의 화살표를 직접 그린다 (2026-09-01) ────────────────
   알약 모양(radius-full) 칸이라 브라우저 기본 화살표가 어긋난다 —
   둥근 칸 안에 각진 회색 삼각형이 오른쪽 끝에 딱 붙어 모서리와 겹쳐 보인다.

   모양은 이 프로젝트의 아이콘 규칙을 따른다 — stroke 만, 채우기 없음.
   색은 --text-muted (#6F6F6B) 을 그대로 박아 넣었다. data URI 안에서는
   var() 가 안 풀리기 때문이다. 토큰이 바뀌면 여기도 같이.

   ★ 팝오버(inlineedit.js)의 프로젝트 칸도 이 클래스를 쓴다 (2026-09-03).
     앞서는 select.il-pop__input 이라는 제 클래스를 따로 들고 이 규칙에
     선택자로만 얹혀 있었다 — 그러다 보니 화살표만 같고 높이 · 글자
     크기 · 이름표는 위아래가 서로 달랐다 */
.il-opt__in--sel {
  cursor: pointer;
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  /* 화살표가 앉을 자리를 글자 쪽에서 비워 준다 */
  padding-right: var(--sp-10);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%236F6F6B' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
  background-size: 15px 15px;
}
/* 구형 Edge/IE 는 appearance 를 안 듣고 제 화살표를 하나 더 그린다 */
.il-opt__in--sel::-ms-expand { display: none; }
/* 포커스가 오면 화살표도 같이 또렷해진다 */
.il-opt__in--sel:focus, .il-opt__in--sel:focus-visible {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23111111' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6.5 8 10.5 12 6.5'/%3E%3C/svg%3E");
}
/* 고를 것이 하나도 없을 때 잠근다 (home.js). 옆의 안내가 까닭을 말한다 */
.il-opt__in:disabled {
  background-color: var(--bg-subtle); color: var(--text-muted); cursor: not-allowed;
}
.il-opt__hint {
  margin-top: var(--sp-2); font-size: var(--fs-micro); color: var(--text-muted);
}

/* ── UTM — 이 패널 안에서 여기만 접는다 (2026-09-01) ──────────────
   같은 '선택' 이라도 무게가 다르다.
     제목 · 프로젝트   거의 모든 링크가 갖는다 · 칸 둘
     UTM             캠페인 링크만 갖는다   · 칸 넷
   넷을 늘 펼쳐 두면 이 패널이 여섯 칸짜리 폼이 되고, 그러면
   "붙여 넣고 엔터" 는 화면 어디에도 안 남는다.

   여는 줄은 조용하다 — 테두리도 배경도 없는 글자 한 줄에 꺾쇠 하나.
   여기는 이 화면의 세 번째 층이라(알약 → 선택 칸 → UTM) 위 둘보다
   눈에 덜 띄어야 순서가 읽힌다 */
.il-opt__utm {
  margin-top: var(--sp-5); padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
}
.il-opt__more {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  border: 0; background: transparent; padding: 0;
  font-family: inherit; font-size: var(--fs-caption); font-weight: 620;
  color: var(--text-secondary); cursor: pointer; text-align: left;
}
.il-opt__more:hover { color: var(--ink); }

/* 여는 줄 — 버튼 둘(펴기 · 물음표)과 상태 한 마디가 한 줄에 선다.
   레이어가 여기에 매달리므로 기준을 여기 둔다 */
.il-opt__utmhead {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-2);
}

/* ── 물음표 (2026-09-01) ─────────────────────────────────────────
   앞서는 설명 두 줄이 늘 떠 있었다. 둘 다 **한 번 읽으면 다시 안 읽는 글**이다.
   UTM 을 쓰는 사람은 이미 알고, 모르는 사람은 그 두 줄로 배우지 못한다.
   그런데 자리는 늘 차지해 칸 넷보다 글이 더 길었다.
   아이콘은 stroke 만이다. 평소에는 흐리게 두고 hover · 열림에서만 잉크가 된다 */
.il-opt__info {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; padding: 0;
  border: 0; border-radius: var(--radius-full);
  background: transparent; color: var(--text-placeholder); cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast);
}
.il-opt__info:hover { color: var(--ink); background: var(--bg-subtle); }
.il-opt__info[aria-expanded="true"] { color: var(--ink); background: var(--bg-subtle); }

/* 아이콘 밑에 매달리는 레이어. 열리는 것이 이 한 장뿐이라 자리를 계산하지 않는다.
   왼쪽 끝을 아이콘이 아니라 줄머리에 맞춘다 — 아이콘에 맞추면 320px 짜리
   레이어가 패널 오른쪽으로 삐져나간다 */
.il-opt__tip {
  position: absolute; z-index: 20;
  top: calc(100% + var(--sp-2)); left: 0;
  width: 320px; max-width: calc(100vw - var(--sp-10));
  padding: var(--sp-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-micro); line-height: var(--lh-body); color: var(--text-secondary);
}
.il-opt__tip p { margin: 0 0 var(--sp-2); }
.il-opt__tip p:last-child { margin-bottom: 0; }
.il-opt__tip b { font-weight: 700; color: var(--ink); }
.il-opt__tip-h {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-caption); font-weight: 700; color: var(--ink);
}
/* 예시 한 줄. 주소 조각이라 고정폭이어야 utm_ 앞뒤가 눈으로 갈린다 */
.il-opt__tip-ex {
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 11px; color: var(--text-muted);
  word-break: break-all;
}
.il-opt__tip code { font-family: var(--font-mono); }

/* 꺾쇠가 돌아서 열림/닫힘을 말한다. 글자를 '펼치기/접기' 로 바꾸지 않는다 —
   글자가 바뀌면 무엇을 여는 줄인지(UTM)가 그 자리에서 사라진다 */
.il-opt__more-i { flex: none; transition: transform var(--t-fast); }
.il-opt__more[aria-expanded="true"] .il-opt__more-i { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .il-opt__more-i { transition: none; }
}
/* 접힌 채로 무엇이 들어 있는지 말하는 자리. 설명은 물음표 뒤로 갔고
   이 자리는 **상태**만 맡는다 — 접힌 것 안에 보이지 않는 설정이
   남지 않게 하는 유일한 장치다 */
.il-opt__more-note {
  font-size: var(--fs-micro); font-weight: 500; color: var(--text-muted);
}
.il-opt__more-note.is-set { color: var(--ink); font-weight: 620; }
/* 값이 없으면 자리도 안 차지한다 */
.il-opt__more-note:empty { display: none; }

.il-opt__utmbody { margin-top: var(--sp-4); }
/* 넷을 2×2 로 놓는다. 한 줄에 넷을 세우면 칸 하나가 90px 이 되어
   utm_campaign 값이 들어가지 않는다 */
.il-opt__utmgrid {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3) var(--sp-5);
}
/* 라벨은 코드 이름 그대로다 (utm_source). 우리말로 옮기지 않는다 —
   GA4 화면에서 보게 될 이름과 같아야 옮겨 적을 수 있다 */
.il-opt__lab--sm {
  font-size: var(--fs-micro); font-weight: 700; color: var(--text-muted);
}
/* 작고 넷이라 모서리를 각지게 한다. 알약 넷이 붙어 서면 눈이 바쁘다.
   팝오버(inlineedit.js)의 UTM 도 이 칸을 그대로 쓴다 — 위에서 넷을 채우는
   자리와 카드에서 넷을 고치는 자리가 다르게 생길 이유가 없다 */
.il-opt__in--sm {
  height: 36px; padding: 0 var(--sp-3);
  border-radius: var(--radius-sm); font-size: var(--fs-caption);
}
/* 손가락 기기의 16px 규칙은 components.css 에 **요소 선택자**로 한 번만
   적어 두었다 (input · textarea · select). 여기 있던 .il-opt__in 목록은
   그쪽이 통째로 덮으므로 걷어냈다 — 두 곳에 적으면 한쪽만 고쳐진다 */
.il-opt__err {
  margin-top: var(--sp-2); font-size: var(--fs-micro); color: var(--danger);
}

/* 좁으면 두 칸이 위아래로 선다. 나란히 두면 프로젝트 이름이 잘린다 */
@media (max-width: 720px) {
  .il-opt__panel { width: 100%; }
  .il-opt__grid { grid-template-columns: 1fr; gap: var(--sp-4); }
  .il-opt__utmgrid { grid-template-columns: 1fr; }
  /* 상태 한 마디가 아래로 내려간다 — 한 줄에 셋을 우겨넣으면 잘린다 */
  .il-opt__utmhead { flex-wrap: wrap; }
  .il-opt__tip { width: 100%; }
}

/* ── 링크 카드 ────────────────────────────────────────────────────
   카드 한 장이 통째로 통계로 가는 길이다 (2026-08-25).
   '통계' 버튼을 따로 두면 카드에 누를 것이 다섯 개가 된다 — 어디를
   눌러야 할지 고르는 일이 생긴다. 대신 제 할 일이 있는 것(복사·목적지·
   칩·UTM)만 덮개 위로 띄운다.

   왼쪽부터  무엇인가 → 얼마나(숫자) → QR.  읽는 순서가 그대로다.

   방금 만든 것만 잉크 카드다. linktr.ee 는 카드마다 색이 다른데
   그 색에 뜻이 없어 눈만 바쁘다. 여기서는 색이 "방금 만든 것" 하나를 말한다 */
.il-lc {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-6);
  padding: var(--sp-5) var(--sp-6);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  margin-bottom: var(--sp-3);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.il-lc--new { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }

/* 카드를 덮는 링크. 글자가 없으니 카드가 통째로 눌리는 판이 된다.

   방금 만든 카드(.il-lc--new)에는 이 덮개가 아예 안 붙는다 (2026-09-01, home.js).
   몇 초짜리 링크의 통계는 볼 것이 없는데, 이 카드는 지금 가장 많이
   만져지는 카드다 — 복사하고, 제목 고치고, 프로젝트 붙이고, 오타 잡는다.
   그 손놀림이 전부 빈 통계로 새는 문 위에 있었다 */
/* ★ 카드를 덮던 링크(.il-lc__go)를 걷어냈다 (2026-09-15).
   통계로 가는 길이 단추로 나왔다 — 까닭은 home.js 의 card() 주석에 있다.
   덮개가 없어지면서 딸려 있던 규칙 넷도 같이 걷었다:
     · 팝오버가 뜨면 덮개를 잠그던 것 (.il-popping)
     · 덮개에 마우스를 올리면 카드 테두리가 짙어지던 것
     · 덮개 위로 띄우려고 제 할 일 있는 것들에 주던 z-index

   카드에 마우스를 올렸을 때의 반응은 남긴다 — 다만 이제 **카드가 눌린다는
   신호가 아니라** 지금 보고 있는 줄이 어느 것인지 짚어 주는 표시다 */
.il-lc:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }

/* ── 무엇인가 ───────────────────────────────────────────────────── */
.il-lc__main { flex: 1 1 auto; min-width: 0; }
.il-lc__urlrow { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.il-lc__short {
  font-size: 22px; font-weight: 800; letter-spacing: -.02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* inline-block 이다 — block 이면 글자가 짧아도 줄 전체를 덮어
   카드를 누를 자리를 잡아먹는다 */
.il-lc__dest {
  display: inline-block; max-width: 100%; vertical-align: top; margin-top: 3px;
  /* caption(12.5) 에서 올렸다 (2026-08-25). 카드에서 두 번째로 많이 읽는 줄이고,
     여기를 눌러 고치기도 하므로 누를 만한 크기여야 한다 */
  font-size: var(--fs-body); color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.il-lc--new .il-lc__dest { color: var(--on-ink-3); }

/* 나중에 채우는 것들 — 칩으로 둔다. 비어 있으면 '+ 제목' 처럼 보인다 */
.il-lc__chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-3); }
.il-chip {
  display: inline-flex; align-items: center; gap: 4px;
  height: 26px; padding: 0 var(--sp-3);
  border: 1px dashed var(--border-strong); border-radius: var(--radius-full);
  background: transparent; color: var(--text-secondary);
  font-size: var(--fs-micro); font-weight: 620; cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.il-chip:hover { background: var(--bg-subtle); border-color: var(--ink); color: var(--ink); }
/* 값이 채워진 칩은 실선이다 — 비어 있는 것과 한눈에 갈린다 */
.il-chip.is-set {
  border-style: solid; border-color: var(--border-strong);
  background: var(--bg-subtle); color: var(--ink);
}
.il-lc--new .il-chip { border-color: var(--on-ink-disabled); color: var(--on-ink-2); }
.il-lc--new .il-chip:hover { background: rgba(255,255,255,.12); border-color: var(--on-ink); color: var(--on-ink); }
.il-lc--new .il-chip.is-set { background: rgba(255,255,255,.14); color: var(--on-ink); }

/* UTM 은 선택이다. 칩과 같은 줄에 서지만 모양이 다르다 —
   칩은 "채울 빈 칸", 이건 "켜짐/꺼짐" 이라 뜻이 다르기 때문이다.

   색을 한 칸 통째로 칠하지 않는다 (2026-08-25). tint 로 채우면 카드에서
   가장 안 중요한 것이 가장 눈에 띄었다 — 무게가 거꾸로다.
   켜짐은 점 하나로만 말하고, 나머지는 글자 밝기로 가른다.
     ON   또렷한 글자 + accent 점
     OFF  흐린 글자 + 흐린 점
   OFF 에 주의색을 쓰지 않는다. 빨갛게 칠하면 안 한 일처럼 읽힌다 */
.il-utm {
  display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 10px 0 8px;
  border: 1px solid var(--border); border-radius: var(--radius-full);
  background: transparent; color: var(--text-muted);
  font-size: var(--fs-micro); font-weight: 620; letter-spacing: .02em;
  text-decoration: none; white-space: nowrap;
  transition: border-color var(--t-fast), color var(--t-fast);
}
.il-utm::before {
  content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; opacity: .4;
}
.il-utm b { font-weight: 700; }
.il-utm:hover { border-color: var(--border-strong); color: var(--ink); }
.il-utm.is-on { border-color: var(--border-strong); color: var(--ink); }
.il-utm.is-on::before { background: var(--accent); opacity: 1; }
.il-lc--new .il-utm { border-color: var(--on-ink-disabled); color: var(--on-ink-3); }
.il-lc--new .il-utm:hover { border-color: var(--on-ink-3); color: var(--on-ink); }
.il-lc--new .il-utm.is-on { border-color: var(--on-ink-3); color: var(--on-ink); }
.il-lc--new .il-utm.is-on::before { background: var(--on-ink-success); }

/* ── 얼마나 ─────────────────────────────────────────────────────
   '클릭' 이라는 글자는 뺐다 — 카드에 숫자가 이것 하나뿐이라 안 헷갈린다.
   화면을 읽어 주는 쪽에만 il-sr-only 로 남긴다 */
/* ── 할 일 — 통계 (2026-09-15) ────────────────────────────────────
   맨 오른쪽, QR 뒤에 선다. 카드에 이미 있는 둥근 아이콘 단추(.il-iconbtn)를
   그대로 쓴다 — 같은 카드 안에서 누르는 것의 생김새가 갈리면 안 된다.

   ★ 지우기를 같이 세웠다가 뺐다 (3차). 둘이 나란히 서니 오른쪽에 덩어리가
     넷이 되어 무엇이 한 묶음인지 안 보였고, 기둥으로 묶어 셋으로 줄인 뒤에도
     **가장 드물게 하는 일이 가장 자주 보는 자리**에 서 있었다.
     하나가 되면서 기둥(세로 쌓기)도 함께 걷었다 — 하나는 기둥이 아니다. */
.il-lc__act { flex: none; }

/* 지우기 — 칩 줄 끝의 작은 단추 (2026-09-15 4차).
   클릭이 0인 카드에만 선다 (home.js 의 card).

   ★ 칩(26px)과 키를 맞춘다. 오른쪽의 둥근 단추(44px)를 쓰면 칩 줄 높이가
     그 하나 때문에 늘어나고, 어쩌다 한 번 누르는 것이 줄에서 가장 커진다.
   ★ 평소에는 잠잠하고 손을 올려야 붉어진다. 늘 붉게 칠해 두면 카드마다
     경고등이 하나씩 켜져 있는 꼴이라 정작 위험할 때 눈에 안 띈다.

   ★ **테두리를 둘렀다 (2026-09-15 5차).** 처음에는 테두리 없이 흐린 회색
     (--text-placeholder, 대비 3.24:1)으로 뒀다 — 옆의 칩 둘이 테두리를
     들고 있어 셋이 같은 무게의 알약으로 읽히는 것을 피하려던 것인데,
     **눌 수 있는 것으로 안 보였다.** 값(칩)과 동작(이것)을 가르려다
     동작을 아예 숨긴 셈이다.
     테두리는 `UTM` 칩과 같은 것(--border)을 쓴다 — 칩 둘이 쓰는
     --border-strong 보다 한 단 옅어서, 눌 수 있다는 것은 말하되 앞으로
     나서지는 않는다. 글자색도 본문에 쓰는 --text-secondary(6.79:1)로 올린다. */
.il-lc__del {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-full);
  background: transparent; color: var(--text-secondary); cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.il-lc__del:hover {
  background: var(--danger-tint); color: var(--danger); border-color: var(--danger);
}
.il-lc__del:disabled { opacity: .4; cursor: default; }
/* 방금 만든 카드는 잉크 바탕이라 흐린 회색이 묻힌다 */
.il-lc--new .il-lc__del { color: var(--on-ink-2); border-color: var(--on-ink-disabled); }
.il-lc--new .il-lc__del:hover { background: rgba(255,255,255,.12); color: var(--on-ink); }

.il-lc__stat { flex: none; text-align: right; }
.il-lc__num {
  font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums;
  letter-spacing: -.01em; line-height: 1.1;
}

/* ── QR ─────────────────────────────────────────────────────────
   맨 오른쪽. 누를 것이 아니라 "이 링크엔 QR 이 있다" 는 표시다 */
/* 크기를 직접 준다 (2026-08-25).
   한 번 align-self: stretch + aspect-ratio 로 카드 높이에 맞춰 봤다가
   되돌렸다 — QR 이 커지면 카드가 높아지고, 카드가 높아지면 QR 이 또
   커지는 되먹임이 생겨 칩이 두 줄로 밀리고 QR 만 200px 로 부풀었다.
   카드 높이는 왼쪽 내용이 정해야 하고 QR 은 거기 따라가는 쪽이다.
   70px — linktr.ee 레퍼런스(약 50px)보다 한 단계 크다 */
/* 누르면 이미지를 내려받는다 (2026-08-25) — 그림 자체가 곧 받는 버튼이다.
   행사장 배너나 리플렛에 넣으려고 QR 을 보는 것이지 화면에서 들여다보려는
   것이 아니다. 덮개 위로 띄운다 — 아니면 카드가 먼저 먹어 통계로 넘어간다 */
.il-lc__qr {
  position: relative; z-index: 1;
  flex: none; width: 70px; height: 70px; padding: 6px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-md);
  background: var(--bg-elevated); color: var(--ink); cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.il-lc__qr:hover { border-color: var(--ink); box-shadow: var(--shadow-sm); }

/* ── QR 위를 덮는 내려받기 겹 (2026-09-01) ────────────────────────
   그림 자체가 받는 버튼인데, QR 은 생김새가 "누르는 것" 처럼 안 생겼다 —
   보라고 붙여 놓은 그림으로 읽힌다. title 은 1초 얹고 기다려야 뜨고,
   aria-label 은 눈으로 쓰는 사람에게 안 보인다.

   덮개는 --overlay-strong 이다. 새 값을 만들지 않았고, .62 라 QR 무늬가
   뒤에 어렴풋이 남는다 — 무엇을 받는지가 겹 위에서도 읽힌다.
   흰 veil + 검은 아이콘은 안 썼다. QR 은 검은 모듈이 빽빽해서 밝게 덮으면
   무늬가 씻긴 것처럼 되고, 그 위 검은 화살표가 무늬와 뒤엉킨다.

   inset:0 은 이 버튼의 padding box 다. pointer-events:none 이라
   누르는 것은 여전히 버튼이다 */
.il-lc__qrdl {
  position: absolute; inset: 0; border-radius: inherit;
  display: flex; align-items: center; justify-content: center;
  background: var(--overlay-strong); color: var(--text-inverse);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast);
}
/* 키보드로 닿았을 때도 뜬다 — 마우스에만 보이면 키보드로 쓰는 사람은
   이 그림이 버튼이라는 것을 끝까지 모른다 */
.il-lc__qr:hover .il-lc__qrdl,
.il-lc__qr:focus-visible .il-lc__qrdl { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .il-lc__qrdl { transition: none; }
}

/* 링크 상세의 QR — 그림도 곧 받는 버튼이다. 옆의 '내려받기' 버튼과 같은 일을 한다 */
.il-qr-dl { cursor: pointer; border-radius: var(--radius-md); }
.il-qr-dl:hover { opacity: .82; }

/* ── 링크 상세 · 머리 카드 ────────────────────────────────────────
   요약(무엇인가)과 숫자(얼마나)를 한 카드에 나란히 둔다 (2026-08-25).
   따로 있을 때 둘 다 반쪽만 쓰고 있었다 — 요약은 왼쪽에 글자 다섯 줄,
   숫자 카드는 1300px 짜리 칸에 숫자 둘.

   숫자칸은 340px 로 묶는다. 늘리면 다시 숫자 둘이 넓은 자리에 떠 있게 된다 —
   이 카드에서 자리를 더 받아야 하는 쪽은 글자가 긴 요약이다 */
.il-linkhead {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 340px);
  /* center 였다 (2026-09-07 되돌림). 가운데로 맞추면 오른쪽 칸이 제 내용
     높이(고르개 + 숫자)로만 서고, 그 덩어리가 통째로 카드 한가운데에
     뜬다 — 고르개와 숫자가 서로 붙은 채 세로선 중간에 떠 있게 된다.
     늘려 두어야 아래에서 둘을 위 · 가운데로 갈라 놓을 수 있다 */
  align-items: stretch; gap: var(--sp-8);
}
.il-linkhead__facts { min-width: 0; }
/* 같은 카드지만 성격이 다르다 — 줄 하나로 나눠 준다 */
.il-linkhead__kpi {
  padding-left: var(--sp-6); border-left: 1px solid var(--border);
  display: flex; flex-direction: column;
}
/* 기기 고르개 (2026-09-07). 칸 맨 위에 오른쪽 맞춤으로 선다 —
   숫자가 오른쪽에 붙어 있어서 왼쪽에 두면 둘이 따로 노는 것처럼 보인다.
   아래 여백을 padding 과 margin 으로 나눠 준 이유는 바로 아래 참조 */
.il-linkhead__kpisw {
  display: flex; justify-content: flex-end; flex: none;
  padding-bottom: var(--sp-4); margin-bottom: auto;
}
/* 숫자를 남은 자리 가운데로 민다 (2026-09-07).
   ★ flex: 1 이 아니라 auto margin 이다. 늘리지 않고 **빈자리만** 가져간다 —
     위(고르개 밑)와 아래가 똑같이 나눠 가지므로 라벨·숫자가 가운데에 선다.
     늘려서 맞추려던 판이 한 번 있었는데, 그때 이 칸에 .il-kpi-cols 가
     라벨용·숫자용 둘이라 각자 남은 자리를 반씩 먹고 `클릭수` 와 `24` 가
     통째로 벌어졌다. 지금은 한 판이지만, 늘리는 방식 자체를 안 쓴다 */
.il-linkhead__kpi > .il-kpi-cols { margin-bottom: auto; }

@media (max-width: 960px) {
  /* 좁으면 숫자가 요약 아래로 내려온다. 세로선은 가로선이 된다 */
  .il-linkhead { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
  .il-linkhead__kpi {
    padding: var(--sp-5) 0 0; border-left: 0; border-top: 1px solid var(--border);
  }
}

/* ── 링크 상세 · QR 블록 ───────────────────────────────────────────
   il-grid-2 였다 (2026-08-25 되돌림). 그림은 132px 인데 칸은 화면 절반이라
   넓은 화면에서 그림과 숫자 사이가 500px 씩 벌어졌다. 둘은 같이 읽는 것이다.
   그림은 제 크기대로 두고, 숫자가 남은 자리를 나눠 쓴다 */
/* 1 : 2 로 나눈다 (2026-08-25).
   flex 로 두었더니 그림은 132px 로 붙박이고 숫자 셋이 남은 1150px 를
   갈라 가져 서로 380px 씩 떨어졌다 — 세 개가 한 덩어리로 안 읽혔다.
   칸을 먼저 나누고 그 안에서 가운데로 모은다. 그러면 넓은 자리가
   "남은 자리" 가 아니라 "칸의 여백" 으로 읽힌다 */
.il-qrblock {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  align-items: center; gap: var(--sp-6);
}
.il-qrblock__img { justify-self: center; }
/* 그림과 `내려받기` 를 세로로 세우던 칸(.il-qrblock__col)을 걷어냈다
   (2026-09-08) — 이름이 붙은 그 줄이 없어져 세울 짝이 사라졌다.
   그림 하나로 받는다 (아래 .il-qrblock__btn) */
/* 라벨 · 숫자를 칸 가운데에 두는 것은 il-kpi-label-cell / -value-cell 이 맡는다
   (components.css) — 링크 · 프로젝트 KPI 카드도 같은 모양이 된다 */

@media (max-width: 960px) {
  /* 좁으면 1 : 2 가 안 나온다 — 그림 아래로 숫자가 내려온다 */
  .il-qrblock { grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
}
.il-lc--new .il-lc__qr:hover { border-color: var(--on-ink); }
/* 직계만이다 (2026-09-01). 후손 전체에 걸면 내려받기 겹의 아이콘까지
   타일 크기로 늘어난다 — QR 그림은 이 버튼의 직계 자식 하나뿐이다 */
.il-lc__qr > svg { display: block; width: 100%; height: 100%; }
.il-lc__qrdl svg { display: block; }
.il-lc--new .il-lc__qr { border-color: var(--on-ink-disabled); }

.il-iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
  border: 1px solid var(--border-strong); border-radius: var(--radius-full);
  background: var(--bg-elevated); color: var(--ink); cursor: pointer;
  transition: background var(--t-fast);
}
.il-iconbtn:hover { background: var(--bg-subtle); }
.il-iconbtn--sm { flex: none; width: 30px; height: 30px; }
.il-iconbtn--sm svg { width: 15px; height: 15px; }

/* ★ 지우기 (2026-09-15 · 관리자 표 셋).
   평소에는 **옆의 것들과 같은 무게**로 선다 — 아이콘 줄에서 하나만
   빨갛게 서 있으면 눈이 거기부터 가고, 그 줄에서 제일 자주 누르는 것은
   통계다. 위험한 것은 누를 때 드러나면 된다: 얹으면 그때 붉어지고,
   그다음은 되묻는 창이 받는다.

   테두리와 자리는 그대로 둔다 — 크기가 다르면 아이콘 줄의 리듬이 깨진다 */
.il-iconbtn--danger:hover {
  background: var(--bg-subtle);
  border-color: var(--danger); color: var(--danger);
}
.il-iconbtn--danger:focus-visible { border-color: var(--danger); color: var(--danger); }
.il-lc--new .il-iconbtn {
  background: transparent; border-color: var(--on-ink-disabled); color: var(--on-ink);
}
.il-lc--new .il-iconbtn:hover { background: rgba(255,255,255,.12); }

/* ── 탭 — 내가 관리하는 링크 · 내 프로젝트 (2026-09-01) ────────────
   .il-home__listhead(제목 + 검색 한 줄)가 있던 자리다. projects.html 의
   화면이 여기로 들어오면서 제목 둘이 탭 둘이 되었다.

   왜 .il-segment 를 쓰지 않나
     .il-segment 는 **같은 목록을 다르게 거르는** 스위치다 (전체/활성/만료).
     여기는 아예 다른 것 둘을 갈아 보는 자리라 role="tablist" 가 맞다.

   밑줄 하나로만 말한다
     알약(만들기 칸)이 이 화면의 주인이라 탭이 상자나 배경을 가지면
     화면에 굵은 것이 둘이 된다. 고른 탭은 잉크 밑줄 하나와 글자 무게로만
     갈린다. 줄 전체를 가로지르는 옅은 선이 그 아래를 받친다 */
.il-tabs {
  display: flex; align-items: flex-end; gap: var(--sp-6);
  margin: var(--sp-10) 0 var(--sp-5);
  border-bottom: 1px solid var(--border);
}
/* 탭 묶음과, 그 오른쪽에 서는 것 하나 (2026-09-16).
   가른 까닭은 뷰 주석에 있다 — role="tablist" 가 탭 아닌 자식을 들면
   화면 낭독기가 그것도 탭으로 읽는다.
   .il-tabs 의 gap 은 이제 목록과 그 하나 사이에만 걸리고, 밑줄은
   .il-tabs__t 의 ::after 라 안 흔들린다 */
.il-tabs__list { display: flex; align-items: flex-end; gap: var(--sp-6); }
/* margin-bottom 은 탭 글자의 padding-bottom(--sp-3) 과 아랫변을 맞춘다 */
.il-tabs__aside { margin-left: auto; margin-bottom: var(--sp-3); }

/* 옛 이노링크 목록의 `제목 - 메모` 에서 메모 쪽 (2026-09-16).
   같은 무게로 두면 둘 중 무엇이 제목인지 안 읽힌다 — 메모는 그 링크가
   어디 쓰였는지를 적은 꼬리표라 제목을 거들 뿐이다 */
.il-linkrow__memo { color: var(--text-muted); font-weight: 400; }
.il-tabs__t {
  position: relative; display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 0 2px var(--sp-3);
  border: 0; background: transparent;
  font-family: inherit; font-size: 20px; font-weight: 800; letter-spacing: -.02em;
  color: var(--text-muted); cursor: pointer;
  transition: color var(--t-fast);
}
.il-tabs__t:hover { color: var(--ink); }
/* 밑줄은 ::after 다. border-bottom 으로 두면 고를 때마다 글자가 1px 씩
   위아래로 뛴다 — 줄 아래 상자의 테두리와 겹쳐 있기 때문이다 */
.il-tabs__t::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  background: var(--ink); border-radius: 2px;
  opacity: 0; transition: opacity var(--t-fast);
}
.il-tabs__t[aria-selected="true"] { color: var(--ink); }
.il-tabs__t[aria-selected="true"]::after { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .il-tabs__t, .il-tabs__t::after { transition: none; }
}

/* 개수를 달지 않는다 (2026-09-01 2차).
   한 번 달았다가 걷어냈다. 사이드바가 같은 수를 이미 말하고 있어
   한 화면에서 같은 숫자를 두 번 읽게 됐고, 탭 글자 옆에 붙은 작은 숫자가
   `내가 관리하는 링크 7` 처럼 제목의 일부로 읽혔다.
   탭이 답해야 하는 것은 `몇 개인가` 가 아니라 `무엇을 보고 있나` 다. */

/* 판. [hidden] 은 JS 가 세운다 — 여기서 display 를 건드리면 그 순간
   UA 의 [hidden]{display:none} 을 이겨 조용히 안 감춰진다 */
.il-tabp:focus { outline: none; }

/* 더 부르는 자리. 손으로 누를 일은 거의 없다 — 스크롤이 대신 눌러 준다.
   그래도 버튼인 까닭은 키보드 · 화면 낭독기로도 닿아야 하기 때문이고,
   IntersectionObserver 가 없는 환경에서는 이것이 유일한 길이 되기 때문이다 */
.il-more {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  width: 100%; height: 52px; margin-top: var(--sp-4);
  border: 1px dashed var(--border-strong); border-radius: var(--radius-lg);
  background: transparent; color: var(--text-muted);
  font-family: inherit; font-size: var(--fs-caption); font-weight: 620; cursor: pointer;
}
/* 여기 있던 .il-more[hidden] 을 걷었다 (2026-09-03).
   display 를 준 자리마다 [hidden] 을 한 줄씩 덧대고 있었는데(여섯 군데),
   components.css 가 [hidden]{display:none !important} 로 한 번에 막는다.
   왜 그래야 하는지는 거기 주석에 있다 */
.il-more:hover { border-color: var(--ink); color: var(--ink); }
.il-more.is-loading { cursor: default; border-style: solid; }
.il-more.is-loading:hover { border-color: var(--border-strong); color: var(--text-muted); }

.il-more__text { line-height: 1; }

/* 도는 동그라미는 부르는 동안에만 나온다 */
.il-more__spin { display: none; width: 14px; height: 14px; }
.il-more.is-loading .il-more__spin {
  display: block;
  border: 2px solid var(--border-strong); border-top-color: var(--ink); border-radius: 50%;
  animation: il-spin .6s linear infinite;
}
@keyframes il-spin { to { transform: rotate(360deg); } }
/* 움직임을 줄여 달라고 한 사람에게는 돌리지 않는다 — 글자가 이미 말하고 있다 */
@media (prefers-reduced-motion: reduce) {
  .il-more.is-loading .il-more__spin { animation: none; }
}

@media (max-width: 720px) {
  .il-paste { padding-left: var(--sp-4); }
  .il-paste__btn { padding: 0 var(--sp-4); }
  /* 좁으면 주소 줄이 한 줄을 다 쓰고, 숫자와 QR 이 그 아래로 내려온다 */
  .il-lc { flex-wrap: wrap; gap: var(--sp-4); }
  .il-lc__main { flex: 1 1 100%; }

  .il-lc__stat { flex: 1 1 auto; text-align: left; }
  .il-lc__qr { width: 64px; height: 64px; }
  .il-lc__qrdl svg { width: 19px; height: 19px; }
  /* 탭 글자를 한 단계 줄인다 — 둘이 한 줄에 서야 갈아 보는 것으로 읽힌다 */
  .il-tabs { gap: var(--sp-4); }
  .il-tabs__t { font-size: 17px; }
}

/* ── 그 자리에서 고치기 (inlineedit.js) ─────────────────────────────
   한 칸만 여는 팝오버. 편집 화면으로 보내지 않는다 —
   고칠 것이 한 칸인데 화면을 옮기면 왕복이 네 번이 된다.
   목적지 · 제목 · 프로젝트 · UTM 이 각각 제 팝오버를 연다 */
[data-edit] {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; border-radius: var(--radius-sm);
}
/* 밑줄은 읽는 줄(목적지)에만. 칩은 테두리가 이미 누를 것임을 말한다 */
.il-lc__dest[data-edit]:hover { text-decoration: underline; }
/* 전역 :focus-visible 규칙(components.css)이 이미 링을 준다. 따로 두지 않는다 */
/* 연필은 평소에 흐리게 둔다 — 읽는 것을 방해하지 않되 고칠 수 있다는 것은 보인다.
   inline-flex + svg display:block 으로 세로 가운데를 맞춘다 —
   기본값(inline)이면 svg 가 텍스트 베이스라인에 앉아 글자보다 아래로 내려간다 */
.il-pop__pen { flex: none; display: inline-flex; align-items: center; opacity: .55; }
.il-pop__pen svg { display: block; }
[data-edit]:hover .il-pop__pen { opacity: 1; }

/* ★ 폭을 고정한다 (2026-09-03).
     내용에 맡겨 두었더니 짧은 이름의 프로젝트를 고르는 순간 상자가
     쪼그라들었다. 같은 레이어가 열 때마다 다른 크기로 뜨면, 다음에 어디를
     누를지 눈이 매번 다시 찾는다 — 특히 `저장` 이 자리를 옮긴다.
     셋(제목 · 프로젝트 · UTM)이 다 이 폭이다. UTM 은 이 안에서 두 칸씩
     두 줄로 서므로 넷을 세로로 세울 때보다 훨씬 낮다 */
/* ★ fixed 다 (2026-09-03 3차). absolute 로 두었더니 레이어가 **문서를
     늘렸다.** body 에 붙는 데다, 아래쪽 카드에서 열면 찾기 목록이 문서 끝을
     넘어간다 — 그만큼 세로 스크롤이 생긴다.
     그런데 사이드바는 셸 안에서 sticky · height:100vh 다 (.il-shell 은
     min-height:100vh). 셸은 안 자랐는데 문서만 자라니, 늘어난 만큼
     사이드바 아래에 흰 바닥이 남았다 — 왼쪽 메뉴가 깨져 보이던 까닭이다.

     fixed 는 문서 높이에 손대지 않는다. 대신 화면이 구르면 기준 요소와
     어긋나므로 그때는 닫는다 (assets/js/inlineedit.js 의 onScroll) */
.il-pop {
  position: fixed; z-index: 60;
  /* 420px — 칸과 저장이 한 줄에 서므로 그만큼 넓다.
     좁히면 프로젝트 이름이 잘리고, 더 넓히면 카드보다 커진다 */
  width: 420px; max-width: calc(100vw - 24px);
  padding: var(--sp-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* ★ 좁은 화면에서는 바닥에서 올라오는 시트다 (2026-09-11).
     아이폰에서 칩을 누르면 화면만 확대되고 레이어가 안 뜬다는 신고에서
     나왔다. 사연은 assets/js/inlineedit.js 의 `손에 쥔 기기에서는…` 에 있다.

     여기서 좌표를 주지 않는다 — `bottom` 만 JS 가 넣는다(키보드가 가리는
     높이). top · left 는 위의 팝오버가 쓰던 인라인 값인데, 시트일 때는 JS 가
     아예 안 쓴다. 그래서 !important 가 필요 없다.

     ★ 테두리는 위쪽 한 줄만 남긴다. 화면 끝에 닿은 상자에 좌우 테두리를
       그리면 1px 만큼 안으로 들어간 것처럼 보인다.
     ★ 아래 여백에 safe-area 를 더한다 — 홈 인디케이터가 `저장` 을 문다. */
@media (max-width: 640px) {
  .il-pop--sheet {
    /* ★ `bottom: 0` 을 못 박는다 (2026-09-11 2차).
         top · bottom 이 둘 다 auto 인 fixed 상자는 **제가 흐름에 있었을
         자리**에 선다. 이 상자는 body 맨 끝에 붙으므로 그 자리가 곧
         문서의 끝이다 — JS 가 `bottom` 을 넣기 전에 칸에 포커스가 가면
         브라우저가 거기까지 굴러 내려갔다. 실제로 그렇게 났다.
         JS 는 이 값을 **키보드가 가리는 높이로 덮어쓸 뿐**이다 */
    left: 0; right: 0; top: auto; bottom: 0;
    width: auto; max-width: none;
    border-width: 1px 0 0;
    border-radius: var(--radius-xl) var(--radius-xl) 0 0;
    padding-bottom: calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
    box-shadow: var(--shadow-xl);
  }

  /* 키보드까지 올라오면 남는 자리가 얼마 안 된다. UTM 은 칸이 넷이라
     그때 넘칠 수 있어서, 넘치면 시트 안에서 구르게 둔다.

     ★ **찾기가 얹힌 칸이 든 시트에는 걸지 않는다** (`:not(:has(.il-pick))`).
       고르는 목록은 그 칸에 붙어 뜨는 absolute 라, 상자에 overflow 가 걸리면
       **잘려서 안 보인다** — 시트는 화면 바닥에 있으니 목록은 위로 뒤집혀
       뜨고(pickselect.js), 그 위쪽이 정확히 잘리는 자리다.
       프로젝트 시트는 칸이 하나라 어차피 구를 일이 없다.

     ★ :has() 를 모르는 브라우저에서는 이 규칙이 통째로 빠진다 — 높이 제한
       없이 내용만큼 선다. 잘려서 못 고치는 것보다 그편이 낫다 */
  .il-pop--sheet:not(:has(.il-pick)) {
    max-height: 78vh; overflow-y: auto;
  }

  /* 뒤를 덮는다. 시트가 화면 절반을 먹는데 뒤가 그대로면 목록을 누를 수
     있을 것처럼 보인다 — 실제로는 닫히기만 한다.
     z-index 는 시트(60) 바로 아래다 */
  .il-pop-scrim {
    position: fixed; inset: 0; z-index: 59;
    background: var(--overlay);
  }
}

/* ★ 레이어 안의 칸은 **선택사항 패널과 같은 부품**이다 (2026-09-03).
     .il-opt__f · .il-opt__lab · .il-opt__in · .il-opt__utmgrid 를 그대로 쓴다.

     앞서는 팝오버가 제 칸(.il-pop__input · __grid · __lab)을 따로 들었다.
     그러다 보니 같은 것을 고치는 자리가 위(만들 때)와 아래(카드에서)에서
     서로 달라졌고, 셋끼리도 제각각이 됐다 — 제목은 칸 옆에 저장,
     프로젝트는 그 아래 안내와 선, UTM 은 이름표가 왼쪽에 붙은 네 줄.

     여기서는 자리(뜨는 상자)와 마무리(저장 줄)만 정한다.
     칸의 생김새는 위와 한 곳에서 온다 */
/* 폼 바로 아래 칸이 둘 이상일 때만. 격자(UTM) 안에서는 간격을 격자가 준다 */
.il-pop__form > .il-opt__f + .il-opt__f { margin-top: var(--sp-4); }

/* ★ 한 칸짜리 레이어는 칸과 저장이 **한 줄**이다 (2026-09-03 2차).
     고칠 것이 하나인데 저장을 아래로 내리면 손이 한 칸을 지나 한 번 더
     내려간다 — 팝오버가 값을 하는 까닭이 그 왕복을 줄이는 것이다.
     칸이 남는 자리를 다 먹고(flex:1) 저장은 제 너비만 든다 */
.il-pop__row { display: flex; align-items: center; gap: var(--sp-3); }
.il-pop__row .il-opt__f { flex: 1 1 auto; min-width: 0; }

/* 프로젝트 레이어의 윗줄 — `프로젝트 생성` 하나가 오른쪽에 선다.
   이름표를 두지 않으므로 이 줄에 다른 것은 없다 */
.il-pop__head {
  display: flex; justify-content: flex-end; margin-bottom: var(--sp-3);
}

/* 고르는 칸에 찾기가 얹히면 그 자리에 .il-pick 이 들어선다 (pickselect.js).
   감싸는 자리에 폭을 주지 않으면 안의 버튼(width:100%)이 고른 이름의
   길이만큼 쪼그라든다 — 짧은 프로젝트를 고르면 상자가 작아지던 까닭이다 */
.il-pop .il-pick { width: 100%; }
.il-pop .il-pick__btn {
  height: 42px; padding-top: 0; padding-bottom: 0; line-height: 40px;
  border-radius: var(--radius-full); font-size: var(--fs-body);
}

/* 마무리 줄 — 셋 다 오른쪽 아래에 `저장` 하나다.
   자리가 고정이라 무엇을 고치든 손이 같은 곳으로 간다 */
.il-pop__foot {
  display: flex; align-items: center; justify-content: flex-end;
  margin-top: var(--sp-4);
}
.il-pop__save {
  flex: none; height: 38px; padding: 0 var(--sp-5);
  border: 0; border-radius: var(--radius-full);
  background: var(--ink); color: var(--text-inverse);
  font-family: inherit; font-size: var(--fs-caption); font-weight: 700; cursor: pointer;
}
.il-pop__save:hover { background: var(--ink-hover); }
.il-pop__save:disabled { opacity: .55; cursor: default; }
.il-pop__err { margin-top: var(--sp-2); font-size: var(--fs-micro); color: var(--danger); }



/* =====================================================================
   그룹 링크 (pages.html · page-edit.html · page-detail.html · page-public.html)
   2026-08-26 신설. feature-spec §18 · competitor-analysis-bio.md

   두 가지 성격이 한 절에 있다 —

     관리 화면 (목록 · 편집 · 분석)
       나머지 화면과 같은 도구다. tokens.css 만 쓴다.

     공개 화면 (.il-pg)
       바깥 사람이 보는 클라이언트 산출물이다. 색이 tokens 가 아니라
       그 그룹 링크의 테마에서 온다 — QR 색을 사람이 고르게 한 것과 같다
       (feature-spec §18-3). 그래서 여기만 --pg-* 지역 토큰을 쓴다.
       기본값을 .il-pg 에 두고 JS 가 인라인으로 덮어쓴다.
   ===================================================================== */

/* ── 그룹 링크 목록 ──────────────────────────────────────────────────
   links.html 과 같은 화면이다. 한 번에 묻는 것이 하나뿐이라는 것도 같다 —
   링크는 목적지 URL, 그룹 링크는 주소(handle) 하나다.

   그래서 .il-home · .il-paste · .il-lc 를 그대로 쓴다.
   여기서는 그룹 링크 카드가 링크 카드와 달라지는 지점만 더한다 */

/* 카드 오른쪽 끝의 작은 미리보기. 링크 카드에서 QR 이 있던 자리다.
   왜 두나 — 목록에서 그룹 링크를 가르는 것은 제목이 아니라 생김새다.
   제목 다섯 줄은 훑을 때 다 비슷해 보이지만 색은 한눈에 갈린다.
   블록을 실제로 그리지 않고 막대 몇 개만 둔다 — 이 크기에서는 못 읽는다 */
/* ── 그룹 링크 한 줄 (2026-08-26 17차) ─────────────────────────────────
   ★ 색 세 덩이로 흉내 내던 .il-pgmini 를 걷어냈다.
     테마 색만 말할 뿐 블록이 몇 개인지 · 커버가 있는지를 말하지 못했다.
     지금은 공개 화면와 같은 코드로 진짜로 그려 줄여서 넣는다. */
/* ★ 표가 아니라 **줄지어 선 그룹 링크**로 읽히게 한다 (2026-08-26 18차).
   한 사람이 만드는 그룹 링크가 서넛뿐이라 줄을 촘촘히 세울 이유가 없다.
   여백을 열고 그림을 키웠다 — 세로를 아끼는 대신 알아보는 쪽을 골랐다 */
/* ★ 안여백은 사방 24px 다 (2026-08-26 57차).
   56차에 좌우만 60px 로 벌렸는데, 그것이 **카드 오른쪽 끝까지** 벌렸다 —
   숫자 뒤로 60px 이 비어 카드가 오른쪽으로 새는 것처럼 보였다.
   넓히고 싶었던 것은 카드 테두리와 오른쪽 끝이 아니라 **폰 양옆**이었다.

   그래서 여백을 카드가 아니라 폰이 들고 있게 옮긴다 (.il-pgc__shot 의 margin).
   카드 네 변은 24px 로 고르게 서고, 흰 여백은 폰 둘레에만 붙는다.
   안쪽(--shot-pad)을 벌리는 길은 여전히 쓰지 않는다 — 안쪽을 벌리면 그림이
   들어갈 폭이 줄어 배율이 딸려 내려가고 글자가 작아진다 (54차에 그랬다가 되돌렸다) */
/* ★ 칸 사이 간격이 30px 다 (2026-08-28 5차 · --sp-8 32px 에서 내렸다).
   폰 바깥 여백을 0 으로 두었으므로 **폰과 글 사이는 이 값 하나**가 정한다.

   ★ 30 은 간격 눈금에 없는 값이다 (4·8·12·16·20·24·32·40 …).
     이 저장소는 눈금 밖 숫자를 피하는 쪽인데(57차에 60px 을 그래서 물렸다),
     여기서는 화면에서 정한 값이라 그대로 적는다. 눈금으로 되돌리려면 32(--sp-8)다 —
     2px 차이라 눈에는 안 잡히고, 그때는 제목 칸이 316px 이 된다.

   왼쪽 끝 → 폰 사이에는 이 값이 끼지 않는다. 거기는 카드 안여백 24px 하나다 */
.il-pgc {
  display: flex; align-items: stretch; gap: 30px;
  padding: var(--sp-6);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-xl);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.il-pgc + .il-pgc { margin-top: var(--sp-5); }
.il-pgc:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); }

/* 320×520 으로 그려 0.42배로 줄인다. 폭을 처음부터 134px 로 주면
   좁은 화면용 레이아웃이 잡혀 실제와 다른 그림이 나온다 */
/* ★ 꾸미기 화면의 미리보기(.il-phone)와 **같은 배율**이다 (2026-08-26 21차).
   ※ 껍데기는 갈렸다 (2026-09-08). 꾸미기 쪽은 테를 걷어내고 모서리만 굴린
     판이 됐는데, 여기는 5px 테를 그대로 둔다 — 목록에서는 줄마다 작은
     그림이 늘어서므로 테가 없으면 어디까지가 한 장인지 안 보인다.
     맞춰 두는 것은 **그리는 배율**이지 껍데기가 아니다 —
   숫자를 따로 정해 두었더니 목록의 그림과 꾸미기의 폰이 폭이 달라
   **같은 그룹 링크가 두 화면에서 다르게 보였다** (줄바꿈이 다른 자리에서 났다).

   ※ 그리는 폭만은 갈렸다. 아래 53차 주석대로 여기는 440 이고 꾸미기의 폰은
     375~430 이다 (2026-09-08에 380 고정에서 옮겼다) — 배율과 상자 크기를
     둘 다 지키려다 그렇게 됐고, 그 대가는 그 주석에 적어 두었다.

   ★ 다만 세로는 폰보다 짧게 자른다 (24차 · 636 → 540).
     폭을 그대로 두고 높이만 줄이려면 길이가 둘 중 하나다 —
       ⓐ 통째로 줄인다   → 폭이 함께 줄어든다. 가로를 지키라는 뜻과 어긋난다
       ⓑ 덜 보여 준다   → 그리는 것은 그대로 두고 상자만 짧게 자른다
     ⓑ 를 골랐다. **그리는 폭도 배율도 건드리지 않으므로** 21차에 맞춘 것
     (두 화면에서 같은 모양)이 그대로 지켜진다. 달라지는 것은 보이는 양뿐이다 —
     그룹 링크를 알아보는 데 필요한 것은 맨 위(사진 · 제목 · 첫 블록 몇 개)다.
     줄 높이가 625px 에서 538px 로 내려간다.

   396/540 은 테두리를 더한 바깥 크기다 (380+16 : 524+16).
   aspect-ratio 는 border-box 에 걸리므로 안쪽 비율을 그대로 쓰면
   테두리 두께만큼 어긋난다 */
.il-pgc__shot {
  /* 논리 크기는 pages.js 가 인라인으로 준다. 여기 기본값은 그것이
     못 들어왔을 때의 대비다 — 없으면 선언이 통째로 무효가 된다 */
  --shot-w: 380px; --shot-h: 620px; --shot-k: 1;

  /* ★ 250×400 (2026-08-26 52차 → 53차에 270, 2026-08-28 3차에 다시 250).

     51차에 꾸미기 폰의 비율(396:816)을 그대로 지켜 234×482 로 뒀는데,
     목록에서는 **줄이 너무 높았다.** 여기서 필요한 것은 폰을 그대로 옮기는 것이
     아니라 `어떤 그룹 링크인지`가 한눈에 들어오는 것이고, 그것은 맨 위 한 화면이면 된다.

     그래서 비율을 폰과 맞추지 않는다. 상자는 270×400, 배율은 0.59 다 (53차).

     ★ 상자를 넓히면서 배율을 되돌리면 **더 많이 보인다.**
       배율이 작을수록 같은 자리에 더 많은 것이 들어오기 때문이다 —
       가로 440 · 세로 661 논리 픽셀이 보인다 (52차에는 380 × 617 이었다).

     ★ 그 대가 하나 — 그리는 폭이 380 에서 440 으로 넓어졌다.
       꾸미기의 폰은 375~430 이라 (2026-09-08), 제목이 아슬아슬하게 두 줄이 되는 그룹 링크는
       여기서 한 줄로 보일 수 있다. 배율 0.59 와 상자 270 을 둘 다 지키려면
       그리는 폭이 (270-10)÷0.59 = 440 이어야 해서 피할 수 없다.
       (배율을 놓으면 380 으로 되돌릴 수 있다 — 그때 배율은 0.68 이 된다)

     ★ 3차에 상자를 250 으로 줄이면서 **배율만 따라 내려간다** (0.59 → 0.545).
       그리는 폭 440 은 건드리지 않는다 — 그것을 줄이면 줄바꿈 자리가 달라져
       21차에 맞춘 것(꾸미기와 목록이 같은 모양)이 깨진다. JS 가 clientWidth 를
       재서 --shot-k 를 다시 넣으므로 CSS 의 숫자 하나만 고치면 끝난다.
       배율이 작아지면 같은 상자에 더 많이 들어온다 — 세로로 보이는 양이 늘어난다

     ★ 상자 안쪽에는 여백을 두지 않는다 (2026-08-26 55차).
       54차에 좌우 16px 를 넣어 봤다. 상자를 그대로 두고 그림만 들이면
       배율이 0.59 → 0.52 로 내려가 **글자가 작아졌다** — 얻은 것(세로 660 → 753)
       보다 잃은 것이 컸다. 벌려야 할 곳은 상자 안쪽이 아니라
       **카드와 폰 사이**였다 (.il-pgc 의 padding 을 늘렸다).

     ★ 테두리는 5px 를 유지한다. 배율을 안 타는 고정값이라 8px 로 두면
       작은 폰에서 껍데기만 두꺼워 보인다.

     ★ `줄 폭의 35%` 를 쓰지 않는다 (51차). 가로세로를 둘 다 못 박아야
       줄 높이가 화면 폭에 따라 출렁이지 않는다.
       좁은 화면에서는 아래 @media 가 통째로 줄인다.

     배율은 JS 가 재서 --shot-k 에 넣는다 (CSS 의 calc() 로는 길이를 길이로
     나눌 수 없다). JS 는 clientWidth 를 재는데 그 값은 테두리를 뺀 안쪽 폭이다 */
  /* ★ 270 → 250 (2026-08-28 3차). 줄이 서는 상자가 1440 에서 880 으로
     좁아지면서(--list-max) 카드 안쪽이 1294 → 830 이 됐다. 그 안에서 270 은
     제목이 들어갈 폭을 남기지 못한다 — 232px 밖에 안 남아 22자 제목이 잘렸다.
     52차에 한 번 250 이었던 값으로 되돌아간다. 세로 400 은 그대로다 */
  flex: none;
  /* ★ 세로 400 → 300 → **250** (2026-09-15, 두 번에 걸쳐). 줄마다 폰 한 대가
     통째로 서 있어서 카드가 440px 을 넘었고, 오른쪽(제목 · 주소 · 단추 ·
     숫자)은 가운데가 텅 빈 채로 그 높이를 따라갔다 — 목록을 훑는데 한
     화면에 두 줄이 겨우 들어왔다.

     ★ 비율은 안 건드린다. 안의 그림은 440×800 을 --shot-k 로 줄여 그리고
       상자는 overflow:hidden 이라, 높이를 줄이면 **아래가 더 잘릴 뿐** 그림이
       찌그러지지 않는다. 잘리는 것은 폰 아랫부분인데 거기는 대개 비어 있다.
       이 줄에서 가릴 것은 `어떤 그룹 링크인가` 이고, 그것은 사진 · 이름 ·
       첫 블록 몇 줄이 말한다 — 250px 이면 그것이 든다.

     ★ 가로(250)와 세로가 같아져 정사각이 됐다. 폰 모양을 흉내 내는 상자가
       아니게 된 셈인데, 그래도 된다 — 안의 그림은 여전히 폰 비율로 그려지고
       상자는 그 **위쪽을 보여 주는 창**일 뿐이다. 세로를 더 줄이면 첫 블록이
       잘리기 시작하므로 여기가 바닥이다. */
  width: 250px; height: 250px;
  position: relative; overflow: hidden;
  /* ★ 테를 얇고 옅게 (2026-09-08). 5px 잉크 테는 줄마다 검은 액자가 늘어서
     목록에서 가장 진한 것이 **그림이 아니라 그 테**였다. 이 줄에서 눈이
     좇는 것은 어떤 그룹 링크인지이고, 그것은 안의 그림이 말한다.
     꾸미기의 미리보기도 같은 날 껍데기를 걷었다 (.il-phone).

     그래도 테를 아주 없애지는 않는다 — 여기는 줄마다 작은 그림이 늘어서고
     그 배경이 흴 때가 많아, 없으면 어디까지가 한 장인지 사라진다.
     1px 이면 경계는 서고 진하기는 그림자 몫으로 넘어간다 */
  border: 1px solid var(--border); border-radius: 19px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow-lg);

  /* ★ 폰 바깥 여백을 뗐다 (2026-08-28 5차). 57차 32px → 4차 16px → 0.

     이 여백은 **카드가 1294px 이던 때** 생긴 것이다. 그때는 폰과 카드 테두리
     사이가 허전해서 벌렸다. 줄이 서는 상자가 880 으로 좁아지면서(--list-max)
     카드 안쪽이 830 이 됐고, 같은 여백이 이제는 제목이 들어갈 폭을 먹는다.
     여백이 커진 게 아니라 카드가 작아져 비중이 뒤집혔다.

     0 으로 두면 폰 왼쪽에 서는 흰 여백은 **카드 안여백 24px 하나**다.
     오른쪽은 칸 사이 간격(.il-pgc 의 gap)이 통째로 맡는다 — 여백을 두 군데서
     더하지 않으므로 `왼쪽 몇 · 오른쪽 몇` 을 한 값씩만 보면 된다.

     안쪽(--shot-pad)을 벌리는 길은 여전히 쓰지 않는다. 안쪽을 벌리면 그림이
     들어갈 폭이 줄어 배율이 딸려 내려가고 글자가 작아진다 (54차에 그랬다).

     세로에도 주지 않는다. 폰이 이 줄에서 가장 높아 위아래를 벌리면 그만큼
     줄이 통째로 높아진다 — 55차에 482px 까지 갔던 그 길이다 */
}
.il-pgc__scale {
  width: var(--shot-w); height: var(--shot-h);
  transform: scale(var(--shot-k)); transform-origin: 0 0;
  /* 그림이다. 안의 링크가 눌리거나 Tab 에 걸리면 안 된다
     (renderPage 가 tabindex="-1" 을 이미 붙이지만 두 겹으로 막는다) */
  pointer-events: none;
}

/* 글은 그림의 **윗줄에 맞춰** 선다. 가운데로 두면 그림이 371px 이라
   제목이 허공에 떠 어디에 딸린 글인지가 흐려진다 */
.il-pgc__main {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: var(--sp-3);
  justify-content: flex-start;
}
/* ★ 제목을 아이콘 버튼과 같은 높이(44px) 상자에 담는다 (2026-08-26 22차).
   글자 줄 높이는 29px, 버튼은 44px 이라 둘 다 위에 붙여 두면 가운데가
   7px 씩 어긋난다 — 나란히 선 둘이 어긋나면 줄이 삐뚤어져 보인다.
   같은 높이 상자에 넣고 안에서 가운데로 두면 눈금 하나 없이 맞는다.

   ★ line-height 를 1 로 못 박는다 (25차).
     그 전에는 글꼴이 정하는 줄 높이(29px)를 그대로 썼는데, 그 줄 상자는
     **글자 위아래로 남는 여백이 서로 다르다** (프리텐다드는 위 1.0em · 아래 0.25em).
     그래서 상자 가운데(179.0)와 글자 줄 가운데(178.3)가 0.7px 어긋났고,
     글꼴이 바뀌면 그 값도 함께 바뀐다.
     1 로 고정하면 줄 상자가 글자 크기와 같아져 이 값이 글꼴 사정에 덜 흔들린다.
     제목은 한 줄로 잘리므로(white-space: nowrap) 줄 사이 간격이 좁아질 일은 없다.

   ★ 그래도 0.5px 이 남는다 — padding-top 으로 메운다 (26차).
     em 상자를 가운데에 두어도 **그 안에서 글자가 가운데가 아니다.**
     프리텐다드는 기준선 위로 23px · 아래로 6px 을 잡는데(24px 기준),
     실제로 칠해지는 잉크는 위 17px · 아래 -1px 이다 — 대문자도 한글도
     기준선 아래로 내려가는 획이 없어 잉크가 위쪽에 몰린다.
     그래서 상자 가운데(179.0)에 맞춰도 잉크 가운데는 178.5 가 된다.

     padding-top: 1px 을 주면 안쪽이 1px 줄면서 글자가 **0.5px 내려간다** —
     잉크 가운데가 179.0 이 되어 아이콘과 정확히 같은 선에 선다.
     세 줄(영문 대문자 · 한글 둘)을 다 재 보니 어긋난 값이 0.50px 로 같았다.
     글자에 따라 달라지는 값이 아니라 **글꼴이 정한 값**이라 상수로 둘 수 있다.
     (2배 화면에서는 이것이 실제 1픽셀이라 눈에 보인다) */
/* ★ 24px(--fs-title) → 22px (2026-08-28 3차).
   줄 상자가 880 으로 좁아지면서 제목 칸이 232px 까지 내려갔다. 그림을 250 으로
   줄여 되찾은 20px 로는 모자라 글자에서도 조금 가져왔다.

   22 를 고른 이유 — 20 으로 내리면 바로 아래 주소 줄(20px)과 같아져
   **읽는 순서가 사라진다.** 주소 줄이 24 를 못 쓰는 것과 같은 이유다.
   지금은 22/800 과 20/500 이라 크기와 무게가 함께 갈린다.

   ★ padding-top: 1px 은 그대로 둔다. 잉크 쏠림 보정값이라 글자 크기를 따라
     비례해서 줄지만(24px 에서 0.50 → 22px 에서 0.46), 그 차이가 0.04px 다.
     2배 화면에서도 안 보이는 값이라 상수 하나를 유지하는 편이 낫다 */
.il-pgc__title {
  margin: 0; min-height: 44px; padding-top: 1px;
  display: flex; align-items: center;
  font-size: 22px; font-weight: var(--fw-title);
  line-height: 1;
  letter-spacing: var(--ls-title); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ★ 주소는 제목보다 한 단 아래다 (17차 · 22차에 한 단 올림).
   .il-lc__short 는 22px/800 이다 — **링크 카드에서는 그것이 맞다.**
   단축 주소 한 줄이 곧 그 링크 자체라 목록에서 가장 크게 읽혀야 한다.
   그룹 링크는 다르다. `ilk.kr/p/change26` 을 봐도 안에 무엇이 들어 있는지 모른다 —
   여기서 앞서야 하는 것은 제목이고, 주소는 복사해 갈 값이다.
   그대로 두면 제목보다 주소가 커져 읽는 순서가 뒤집힌다.

   다만 14px 은 너무 내려갔다 (22차 → 23차에 한 번 더 올림).
   복사해서 남에게 보내는 값이라 **눈으로 한 번 확인하는 글자**인데
   캡션만 해서는 읽어 내기 어렵다.

   ★ 20px 은 토큰에 없는 값이다. 글자 크기 눈금이 18(heading) 다음
     24(title) 로 뛰어서 그 사이가 비어 있다. 바로 위 `.il-lc__short` 가
     같은 이유로 22px 을 직접 적고 있다 — 링크 카드에서 단축 주소가
     제목 노릇을 하기 때문이다. 여기 20px 은 **그 22px 바로 아래 한 칸**이라는
     뜻이고, 두 목록의 주소가 같은 성격이되 무게가 다르다는 것을 말한다.
     (24px 을 쓰면 제목과 같아져 읽는 순서가 사라진다) */
.il-pgc .il-lc__short {
  font-size: 20px; font-weight: var(--fw-lead);
  letter-spacing: 0; color: var(--text-secondary);
}
/* ── 오른쪽 기둥 — 위에 버튼 셋, 아래에 숫자 둘 (2026-08-26 20차) ──
   19차에는 숫자를 왼쪽 글 칸의 밑바닥에 두었는데, 오른쪽 끝의 아이콘과 축이
   어긋났다. 같은 기둥에 넣으면 **맨 아래 숫자의 오른쪽 끝이 마지막 아이콘의
   오른쪽 끝과 같은 선**에 선다.

   space-between 이라 위와 아래를 둘 다 잡는다 — 그 사이 빈칸이 여백으로 읽힌다 */
.il-pgc__side {
  flex: none; display: flex; flex-direction: column;
  justify-content: space-between; align-items: flex-end;
  gap: var(--sp-4);
}
.il-pgc__nums { display: flex; gap: var(--sp-8); }

.il-pgc__num { display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.il-pgc__num b {
  font-size: var(--fs-title); font-weight: var(--fw-title);
  letter-spacing: var(--ls-title); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.il-pgc__num span { font-size: var(--fs-caption); color: var(--text-secondary); }

/* 셋 다 눌리는 버튼이다. 하나만 덮개로 두면 나머지는
   "덮개를 피해 눌러야 하는 것" 이 된다.
   제목과 같은 줄에 가로로 세운다 — 세로로 쌓으면 오른쪽 끝에 기둥이 하나
   더 서서 표처럼 읽힌다 */
.il-pgc__acts { display: flex; gap: var(--sp-2); }

/* 좁은 화면 — 그림을 위로 올리고 한 단 줄인다 */
/* 좁은 화면 — 35% 로는 그림이 우표가 된다. 반으로 늘리고 줄바꿈을 허용한다 */
@media (max-width: 720px) {
  .il-pgc { flex-wrap: wrap; gap: var(--sp-4); padding: var(--sp-4); }
  /* 좁은 화면에서는 통째로 줄인다 — 비율은 그대로다 (51차 · 52차) */
  /* 테 두께는 좁은 화면에서도 1px 그대로다 (2026-09-08) — 배율을 안 타는
     값이라 여기서 굳이 줄일 것이 없다. 상자와 모서리만 줄인다 */
  .il-pgc__shot { width: 202px; height: 240px; border-radius: 14px; }

  /* ★ 좁은 화면에서 줄이 셋으로 갈린다 — 자리를 정해 준다 (2026-09-11).

     넓을 때는 `그림 | 글 | 오른쪽 기둥` 이 한 줄에 나란히 서고, 기둥의 것들은
     카드 오른쪽 끝에 줄을 맞춘다. 좁아지면 셋이 접혀 위아래로 서는데,
     그때까지 **전부 왼쪽에 붙어 있었다.** 접힌 것이 아니라 왼쪽으로 쏠린
     것처럼 보였다 — 특히 폰 그림이 그렇다. 카드 폭이 300px 남짓인데 그림은
     202px 이라, 오른쪽에 100px 짜리 빈 기둥이 줄마다 남았다.

       그림      → 가운데. 카드 한가운데 놓이면 그것이 주인공으로 읽힌다
       제목·주소 → 왼쪽 그대로. 읽는 글이라 왼쪽에서 시작해야 한다
       버튼·숫자 → 오른쪽. 넓은 화면에서 서던 자리를 그대로 지킨다.
                   화면이 좁아졌다고 같은 것이 반대편으로 옮겨 다니면,
                   손이 매번 어디를 눌러야 할지 다시 찾는다

     자리를 잡으려면 **줄을 차지해야** 한다 — 접힌 칸은 제 내용만큼만 넓어서
     안에서 아무리 오른쪽으로 밀어도 그 좁은 상자 안에서만 움직인다.
     그래서 글 칸과 기둥에 100% 를 준다: 그 줄의 주인이 되어야 끝에 닿는다.
     그림은 그러지 않는다 — 크기가 정해진 그림이라 좌우 여백을 auto 로
     나눠 갖는 것으로 충분하고, 100% 를 주면 껍데기까지 늘어난다 */
  .il-pgc__shot { margin-inline: auto; }
  .il-pgc__main { flex: 1 1 100%; }
  .il-pgc__side { flex: 1 1 100%; align-items: flex-end; }
}

/* 만들기 버튼 옆의 남은 수 (2026-08-26 70차 · §18-7 P3).
   버튼과 한 덩어리로 묶는다 — 떨어뜨려 두면 무엇에 대한 수인지 흐려진다.
   좁은 화면에서는 글이 버튼 위로 접힌다 */
.il-pgquota {
  display: flex; align-items: center; gap: var(--sp-3);
  flex-wrap: wrap; justify-content: flex-end;
}
.il-pgquota .il-caption { text-align: right; }

/* 상태 배지가 카드 안에 들어간다. 링크 카드에는 없다 —
   링크는 상태 4종이라 표(admin_links)에서 걸러야 하지만,
   그룹 링크는 둘뿐이라 카드에서 바로 말해도 시끄럽지 않다 */
.il-lc__badges {
  display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-1);
}

/* 그룹 링크 카드의 숫자는 둘이다 (방문 · 클릭). 링크는 하나였다 —
   클릭률의 분모가 보여야 클릭률이 뜻을 갖는다 (feature-spec §6-5) */
.il-lc__stat--two { display: flex; gap: var(--sp-6); text-align: right; }
.il-lc__statcell { display: flex; flex-direction: column; align-items: flex-end; }
/* ★ eyebrow 꼴(11px · 700 · 자간)을 걷어냈다 (2026-09-07).
   굵고 자간 벌어진 글자는 **머리말**의 모양이라, 숫자 밑에 놓으면 이름표가
   숫자만큼 목소리를 낸다 — 여기서 읽어야 할 것은 숫자다.
   그룹 링크 카드의 이름표(.il-pgc__num span)와 같은 꼴로 맞춘다:
   카드 두 종류가 같은 자리에서 다른 무게로 말하면 안 된다 */
.il-lc__statlab { font-size: var(--fs-caption); color: var(--text-secondary); }


/* ── 프로젝트 한 장 (projects.html · 2026-08-28 신설) ───────────────
   표를 걷어내고 카드로 세웠다. 왜 —

     프로젝트는 한 사람에게 대여섯이다. 칸 일곱 개짜리 표는 **수십 건을
     걸러 내는** 도구인데, 여섯 줄을 거를 일은 없다. 표가 답하는 질문
     ("정렬해서 위에서부터 훑자")과 사람이 실제로 묻는 질문
     ("빅세일 아직 하고 있나 · 얼마나 남았나")이 다르다.

     그래서 칸을 지우고 **문장**으로 바꿨다 — `2026-08-01 ~ 10-31` 대신
     `63일 남음`. 막대가 그 문장을 한 번 더 그린다.
     전사 수십 건을 훑는 자리는 admin_project.html 에 그대로 남아 있다
     (거기서는 표가 맞다 — 링크 · 그룹 링크와 같은 갈림이다).

   뼈대는 .il-lc(링크) · .il-pgc(그룹 링크)와 같다 —
   덮개 링크 하나 + 왼쪽 표식 + 가운데 글 + 오른쪽 기둥.
   세 목록이 같은 손놀림으로 읽히게 하려는 것이라 셋을 한 규칙으로 둔다 */
/* ★ 카드 목록을 가운데로 모으는 상자 — pages.html · projects.html 공용.
   links.html 의 .il-home 과 같은 자리, 같은 폭(--list-max)이다.

   .il-content 에 max-width 를 거는 대신 안쪽에 상자를 하나 더 두는 이유는
   box-sizing 이 border-box 라서다. .il-content 에 880 을 걸면 좌우 안여백
   (--content-pad, 넓은 화면에서 48px)이 그 안에서 빠져 실제 폭이 784 가 되고,
   links.html(안쪽 .il-home 이 880)보다 좁아진다. 같은 구조를 써야 같은 폭이 된다.

   ★ 화면마다 이름을 따로 두지 않는다 (2026-08-28 3차).
     프로젝트에 .il-prlist 를 만들었다가 그룹 링크에도 같은 규칙이 필요해졌다.
     같은 값을 가진 클래스가 셋이 되면 하나만 고쳐지는 날이 온다 —
     .il-home 은 히어로 스타일을 함께 들고 있어 이름을 남기되, 폭은 같은 토큰에서 온다 */
.il-listbox { max-width: var(--list-max); margin-inline: auto; }

.il-prc {
  position: relative;
  display: flex; align-items: stretch; gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  margin-bottom: var(--sp-3);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
/* ★ 카드를 통째로 덮던 링크(.il-prc__go)를 걷어냈다 (2026-09-03).
   링크 카드(.il-lc)에서 가져온 규칙이었는데 여기서는 값이 안 맞았다 —
   이 카드에는 [편집]과 [통계]가 이미 떠 있어서, 덮개가 글자 없는 셋째
   버튼이 됐다. 눌러 보기 전에는 어디를 눌렀는지 갈리지 않는다.
   아이콘을 위로 띄우던 z-index 도 같이 걷었다 — 이제 덮을 것이 없다 */

/* ★ 왼쪽 표식 타일을 걷어냈다 (2026-08-28 2차).
     이름 두 글자를 차트 색 타일에 담아 뒀는데, 그 색에 **뜻이 없었다.**
     이 저장소는 색을 그렇게 쓰지 않는다 — .il-lc--new 의 잉크 카드는
     `방금 만든 것` 하나를 말하고, 차트의 여섯 색은 계열을 말한다.
     아무것도 말하지 않는 색이 카드에서 가장 큰 덩어리로 앉아 있었다.
     (링크트리가 카드마다 색을 다르게 두는 것을 걷어낸 것과 같은 이유다)

     남는 색은 막대 하나뿐이고, 그것은 --accent 로 못 박는다 —
     프로젝트마다 달라지지 않으므로 "무슨 색이 무슨 뜻이냐" 가 생기지 않는다 */

.il-prc__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.il-prc__title {
  margin: 0;
  font-size: 20px; font-weight: 800; letter-spacing: -.02em; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* ★ 기간을 문장으로 적는다. `2026-08-01 ~ 2026-10-31` 은 두 번 읽어야
   `아직 두 달 남았다` 가 나온다 — 그 계산을 화면이 대신한다.
   날짜 자체는 편집 모달과 관리자 표에 그대로 있다 */
.il-prc__when { font-size: var(--fs-caption); color: var(--text-secondary); }
.il-prc__when b { font-weight: 700; color: var(--ink); }

/* 남은 기간 막대. 종료일이 없으면(상시 운영) 아예 그리지 않는다 —
   끝이 없는 것에 진행률을 그릴 수 없다 */
.il-prc__bar {
  height: 6px; margin-top: 2px;
  border-radius: var(--radius-full); background: var(--bg-subtle); overflow: hidden;
}
.il-prc__bar i { display: block; height: 100%; background: var(--accent); }
/* 끝난 것은 색을 뺀다. 지난 프로젝트가 목록에서 가장 눈에 띄면 안 된다 */
.il-prc--done .il-prc__bar i { background: var(--border-strong); }

/* 참여자 — 이름을 그대로 적는다 (2026-08-28 2차).
   앞서는 26px 동그라미에 성 한 글자만 넣었는데, 사내에 김 · 이 · 박이 몰려 있어
   `김` 하나로는 누구인지 가려지지 않았다. 동그라미는 그림처럼 보일 뿐
   정작 알고 싶은 것(누구랑 하고 있나)에 답하지 못했다.

   그렇다고 26px 안에 세 글자를 넣을 수는 없으므로 동그라미를 버리고
   알약으로 눕혔다. 넷까지 적고 나머지는 `+n명` 으로 접는다 —
   카드에서 가장 긴 줄이 되면 안 된다 */
.il-prc__who {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: var(--sp-2);
}
.il-prc__name {
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px;
  border: 1px solid var(--border); border-radius: var(--radius-full);
  background: var(--bg-subtle); color: var(--text-secondary);
  font-size: var(--fs-caption); font-weight: 600;
}
/* 접힌 나머지 — 테두리를 뗀다. 사람 이름이 아니라 세어 놓은 수다 */
.il-prc__name--rest { border-color: transparent; background: transparent; color: var(--text-muted); }

/* 오른쪽 기둥 — 위 아이콘, 아래 숫자. .il-pgc__side 와 같은 규칙이다.
   space-between 이라 맨 아래 숫자의 오른쪽 끝이 마지막 아이콘과 같은 선에 선다 */
.il-prc__side {
  flex: none; display: flex; flex-direction: column;
  justify-content: space-between; align-items: flex-end; gap: var(--sp-4);
}
.il-prc__acts { display: flex; gap: var(--sp-2); }
.il-prc__nums { display: flex; gap: var(--sp-6); }
.il-prc__num { display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.il-prc__num b {
  font-size: var(--fs-title); font-weight: var(--fw-title);
  letter-spacing: var(--ls-title); color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.il-prc__num span { font-size: var(--fs-caption); color: var(--text-secondary); }
.il-prc--done .il-prc__num b { color: var(--text-secondary); }

/* 좁은 화면 — 숫자를 글 아래로 내린다. 오른쪽 기둥을 그대로 두면
   이름이 들어갈 폭이 남지 않는다 */
@media (max-width: 720px) {
  .il-prc { flex-wrap: wrap; gap: var(--sp-4); padding: var(--sp-4); }
  .il-prc__side {
    flex: 1 1 100%; flex-direction: row-reverse; align-items: center;
    justify-content: space-between;
  }
}


/* ── 편집 화면 (page-edit.html) ────────────────────────────────────
   좌 편집 / 우 미리보기. 인포크와 링크트리가 완전히 같은 구조를 쓴다 —
   이 화면의 정답이 하나라는 뜻으로 읽었다.

   미리보기는 스크롤을 따라온다. 편집 항목이 길어지면 미리보기가 화면
   밖으로 나가는데, 그러면 "지금 고친 것이 어떻게 보이나" 를 못 본다 */
/* 반씩 나눈다 — 5 : 5 (2026-09-08. 400px 고정 → 6:4 → 여기).
   오른쪽이 400px 고정일 때는 넓은 화면에서 편집 칸만 계속 자라 미리보기가
   구석으로 밀렸다. 6:4 로 한 번 넓혔다가 반반으로 왔다 — 이 화면에서 하는
   일이 `고치기` 와 `보기` 둘이고, 둘 중 하나가 곁다리가 아니다.

   ★ 폰은 칸을 따라 375~430px 사이에서 늘고 준다 (.il-phone).
     양 끝이 둘 다 실제 폰의 폭이라, 어느 폭에서 보든 `어떤 폰에서 본 모습`
     이다. 남는 자리는 폰 양옆의 여백이 되고, 그 여백이 맨 위 사진을 누를
     때의 숨통이 된다 */
.il-pe {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 5fr);
  gap: var(--sp-10); align-items: start;
}
.il-pe__side { min-width: 0; }
.il-pe__preview { position: sticky; top: var(--sp-6); }

/* 미리보기 위의 주소 바. 링크트리가 여기에 둔다 —
   지금 만들고 있는 것이 어느 주소인지가 미리보기 바로 위에 있어야 한다.

   주소를 정가운데에 세운다 (2026-08-26 5차). 버튼은 오른쪽에만 있으므로
   좌우 여백을 같은 값(--sp-18 = 72px)으로 잡고 버튼을 그 위에 얹는다 —
   flex 로 밀면 주소가 버튼 폭만큼 왼쪽으로 치우쳐 아래 폰 껍데기와 축이 어긋난다.
   72px 는 버튼 둘(28px) + 사이 + 오른쪽 여백을 덮는 폭이라 긴 주소도 겹치지 않는다 */
.il-pe__addr {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  min-height: 44px;
  margin-bottom: var(--sp-3); padding: var(--sp-2) var(--sp-18);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-full);
}
.il-pe__addrurl {
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; text-align: center;
  font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--ink);
}
.il-pe__addracts {
  position: absolute; right: var(--sp-2); top: 50%; transform: translateY(-50%);
  display: flex; align-items: center; gap: 2px;
}

/* 편집 항목 묶음. .il-card 를 쓰지 않는다 —
   카드 안에 카드가 들어가면 테두리가 두 겹이 된다 */
/* ★ 칸 머리를 블록 하나만 남겼다 (2026-09-01 2차).
   나머지 셋(주소 · 맨 위 · 색)은 그 아래 줄들이 이미 제 이름표를 들고 있어
   같은 말이 두 번이었다.
   ★ 4차에 덩이마다 달랐던 여백 modifier(--line · --split)를 걷어냈다 —
     세로 리듬은 위 §편집 칸 리듬 한 곳에서만 정한다 */

/* 색 두 칸을 한 줄에. 색 상자가 64px 이라 줄마다 오른쪽이 통째로 비었고,
   무엇보다 이 둘은 같이 보아야 하는 값이다 — 배경 위에 버튼이 올라앉는다.
   이름표는 상자 오른쪽이다. 위에 얹으면 상자 둘이 아래로 내려가
   한 줄로 만든 값이 사라진다 */
.il-pe__colors { display: flex; align-items: center; gap: var(--sp-6); flex-wrap: wrap; }
.il-pe__color { display: inline-flex; align-items: center; gap: var(--sp-2); cursor: pointer; }
.il-pe__color .il-input { width: 56px; padding: 2px; flex: none; }
.il-pe__color span { font-size: var(--fs-caption); color: var(--text-secondary); }
/* 잠긴 테마(풍차 · 하늘)를 고르면 색 줄이 통째로 접힌다 (syncColorLock) —
   흐린 칸 + 안내문으로 두었더니 읽을 것만 늘었다. 고를 수 없는 것은
   화면에 없는 것이 맞다 (걷어낸 글꼴 칸과 같은 판단) */

/* ── 테마 카드 3장 (2026-09-09) ──────────────────────────────────────
   ★ 이름만 적지 않는다. `오로라` 가 무엇인지는 글자로 알 수 없어서,
     고르는 일이 눌러 보고 되돌리기의 반복이 된다. 작은 그림이 바탕색과
     버튼 두 줄을 그대로 보여 준다 — 미리보기의 축소판이다.

   ★ 그림에 실제 테마 클래스(.il-pg--aurora …)를 그대로 건다. 카드용 색을
     따로 적으면 언젠가 진짜와 갈라지고, 그때 카드는 없는 화면을 광고한다.
     바탕 · 움직임 · 유리 버튼이 전부 저기서 온다 */
.il-pe__themes { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.il-pe__theme {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2); border-radius: var(--radius-md);
  border: 1px solid transparent; background: none; cursor: pointer;
}
.il-pe__theme:hover { background: var(--bg-subtle); }
/* 고른 것은 테두리로 말한다 — 바탕으로 말하면 카드 안 그림의 바탕색과
   겹쳐서, 밝은 테마에서는 눌린 것이 안 보인다 */
.il-pe__theme[aria-pressed="true"] { border-color: var(--ink); }
/* 이름표를 걷어냈다 (2026-09-09 4차) — `풍차` 같은 이름이 그림보다 먼저
   읽혀서 그림을 설명문으로 만들었다. 카드는 그림 하나로 말하고, 이름은
   보조기기용으로만 남는다 (pageedit.js 의 aria-label) */

/* 폰 한 대의 축소판. 세로가 긴 것이 그룹 링크의 모양이다 */
.il-pe__themeshot {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 4px;
  width: 56px; height: 76px; padding: 6px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--pg-bg);
}
/* 버튼 두 줄. 테마마다 생김새가 다르므로 색만 주고 나머지는 .il-pg--* 가
   덮어쓰게 둔다 — 여기서 정하면 카드와 실제가 갈린다 */
.il-pe__themeshot i {
  display: block; height: 12px; border-radius: 4px;
  background: var(--pg-btn); position: relative; z-index: 1;
}
.il-pe__themeshot.il-pg--aurora i {
  background: color-mix(in srgb, var(--pg-btn) 22%, transparent);
  border: 1px solid color-mix(in srgb, var(--pg-btn) 35%, transparent);
}
/* ★ 장면 테마(풍차 · 별똥별)의 카드는 **작은 포스터**다. 실제 장면
   레이어(풍차 · 나무 · 별똥별)를 56px 에 그대로 욱여넣으면 형체를 알 수
   없어서, 하늘 · 달 · 노을만 남긴 요약본을 카드에만 따로 깐다.
   가짜 광고는 아니다 — 같은 하늘의 같은 색이다 */
.il-pe__themeshot.il-pg--mill::before, .il-pe__themeshot.il-pg--mill::after,
.il-pe__themeshot.il-pg--mill .il-pg__inner::before { content: none; }
.il-pe__themeshot.il-pg--mill {
  /* 달 점도 걷었다 — 장면에서 달을 걷은 날 (2026-09-09). 카드가 없는
     것을 광고하면 그때부터 거짓말이다 */
  background: linear-gradient(180deg, #131B33 0%, #2C4066 66%, #16223C 66%, #0C1426 100%);
}
.il-pe__themeshot.il-pg--mill i { background: rgba(12, 19, 36, .8); border: 1px solid rgba(255, 255, 255, .16); }
.il-pe__themeshot.il-pg--sky::before, .il-pe__themeshot.il-pg--sky::after { content: none; }
.il-pe__themeshot.il-pg--sky {
  background:
    radial-gradient(ellipse 26px 10px at 20% 18%, rgba(255, 255, 255, .9), transparent 70%),
    radial-gradient(ellipse 30px 12px at 85% 60%, rgba(255, 255, 255, .8), transparent 70%),
    linear-gradient(180deg, #9FCBEF 0%, #ABD6F2 45%, #C2E4EE 75%, #CFEEE6 100%);
}
.il-pe__themeshot.il-pg--sky i { background: rgba(255, 255, 255, .85); border: 1px solid rgba(46, 64, 83, .18); }

/* 블록 밑으로 내려온 SNS 는 제 선을 들지 않는다 —
   바로 위 블록 칸이 이미 선으로 닫혀 있다 */
/* .il-pe__fold--bare 를 걷어냈다 (4차) — .il-pe__fold 가 아예 선을 안 든다 */
.il-pe__grouphead {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); margin-bottom: var(--sp-4);
}
.il-pe__grouphead h2 {
  font-size: var(--fs-heading); font-weight: var(--fw-heading);
  letter-spacing: var(--ls-heading);
}

/* ── 순서·묶기 안내 (2026-09-15) ────────────────────────────────────
   ★ 넓은 화면과 폰이 **서로 다른 말**을 한다. 폰에는 끌기가 아예 없다 —
     touch 에서 drag 이벤트가 안 나서 손잡이를 순서 단추(↑↓)와 묶기
     단추로 바꿔 두었다 (아래 @media (pointer: coarse)).

   그래서 가르는 조건이 **그 규칙과 같아야** 한다. 여기만 폭(max-width)
   으로 가르면, 넓은 태블릿에서 단추는 서 있는데 설명은 `끌어서` 라고
   말하는 짝이 생긴다. 같은 pointer 질의를 쓴다.

   기본은 마우스 쪽이다 — 판정이 안 되는 브라우저에서는 손잡이도 그대로
   서 있으므로(아래 규칙이 안 걸린다) 둘이 어긋나지 않는다 */
.il-pe__tip--coarse { display: none; }
.il-pe__tip--fine { display: block; }

@media (pointer: coarse) {
  .il-pe__tip--fine { display: none; }
  .il-pe__tip--coarse { display: block; }
}

/* 패널 안의 <span> 이라 문단 여백이 안 먹는다 — 블록으로 세운다 */
.il-infotip__panel :is(.il-pe__tip--fine, .il-pe__tip--coarse) > p:last-child {
  margin-bottom: 0;
}

/* 물음표가 제목 뒤에 붙는다. 제목이 grouphead 의 왼쪽 몫이라, 아이콘이
   그 안으로 들어와야 오른쪽의 `링크 N개` 와 사이가 벌어지지 않는다 */
.il-pe__grouphead-h { display: inline-flex; align-items: center; }
/* ★ 머리를 든 묶음도 줄 하나와 같은 리듬 위에 선다 (2026-09-09).
   `블록` 은 .il-pe__band 라 위아래 sp-5 를 제가 들고 있는데, 줄들로 된
   묶음(`디자인`)은 그 여백이 첫 줄 안에 있었다 — 그래서 선과 제목 사이는
   붙고 제목과 첫 줄 사이는 sp-4 + sp-5 로 벌어졌다.
   제목이 그 sp-5 를 위로 가져가고, 바로 아래 줄은 제 윗여백을 내려놓는다 */
.il-pe__group:not(.il-pe__band) > .il-pe__grouphead { padding-top: var(--sp-5); }
.il-pe__grouphead + .il-pe__row { padding-top: 0; }
/* ── 편집 칸의 세로 리듬 (2026-09-01 4차) ──────────────────────────
   **칸 하나가 곧 한 줄이다.** 위아래 여백이 같고, 아래 선 하나로 다음 칸과
   갈린다. 그 규칙 하나만 있으면 화면 어디를 잘라 봐도 간격이 같다.

   앞서는 여백을 세 군데에서 들었다 — 줄(.il-pe__row)의 padding,
   덩이(.il-pe__group)의 margin, 그리고 덩이마다 다른 modifier.
   그래서 `주소 → 모양` 은 24+8+16, `제목 → 소개` 는 16+16,
   `소개 → 블록` 은 40+32 가 되어 같은 화면 안에서 셋이 다 달랐다.
   여백을 두 곳에서 들면 반드시 어디는 넓고 어디는 좁아진다.

   덩이는 이제 묶기만 한다 (data-pe-lock 을 걸 대상이라 남는다).
   줄이 아닌 덩이(블록 목록 · SNS)는 .il-pe__band 를 달아 같은 줄에 선다 */
.il-pe__row {
  display: grid; grid-template-columns: 120px minmax(0, 1fr);
  align-items: center; gap: var(--sp-3) var(--sp-5);
}
/* display:grid 가 UA 의 [hidden]{display:none} 을 이긴다 — 잠긴 테마가
   색 줄을 접을 때(pageedit.js syncColorLock) 이 한 줄이 없으면
   hidden 을 세웠는데 조용히 안 접힌다 */
.il-pe__row[hidden] { display: none; }
.il-pe__row, .il-pe__band { padding: var(--sp-5) 0; border-bottom: 1px solid var(--border); }
.il-pe__group { margin: 0; }
/* 맨 끝 줄만 선을 뗀다 — 아래에 아무것도 없는데 선이 남으면 잘린 것처럼 보인다 */
.il-pe__side > .il-pe__group:last-child > :last-child { border-bottom: 0; }
.il-pe__lab { font-size: var(--fs-body); font-weight: 700; color: var(--text-secondary); }
.il-pe__val { min-width: 0; }

/* 글자수(0/160)를 걷어냈다 (2026-09-08). 링크트리 · 인포크가 같은 자리에
   두는 것이지만, 이 화면에는 **미리보기가 있다** — 잘릴지 말지를 숫자로
   셈하는 대신 폰 안에서 바로 보인다. 한도는 칸이 지킨다 (maxlength).

   ★ 줄의 여백은 손대지 않았다. .il-pe__row 가 위아래 sp-5 를 들고
     align-items:center 라, 아래 한 줄이 빠지면 칸이 그 자리에서 가운데로
     선다 — 여백을 따로 더하면 이 줄만 다른 리듬이 된다 */


/* ── 블록 목록 (편집) ────────────────────────────────────────────
   인포크의 블록 리스트를 그대로 가져왔다 — 행이 접히는 카드다.
   평소에는 제목 한 줄, 펼치면 자식과 설정. 스무 줄이 되어도 훑을 수 있다 */
.il-be {
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  margin-bottom: var(--sp-3);
  transition: border-color var(--t-fast), opacity var(--t-fast);
}
.il-be.is-off { opacity: .55; }
.il-be.is-off:hover, .il-be.is-off:focus-within { opacity: 1; }
/* ★ 줄 전체가 세로 가운데다 (2026-08-26 14차).
   손잡이 · 배지 · 토글 · 휴지통만 가운데로 두고 글자 칸은 위에 붙여 뒀더니
   **소제목 행에서 배지가 글자보다 8px 아래**에 섰다 — 소제목은 칸이 한 줄뿐이라
   (27px) 오른쪽 토글·휴지통 줄(44px)보다 짧고, 그 차이가 그대로 어긋남이 됐다.
   칸까지 가운데로 두면 셋이 같은 높이에 선다.

   링크·모음 행은 달라지지 않는다 — 그쪽은 칸(제목+주소+아이콘 줄)이 가장 길어서
   이미 그것이 높이를 정하고 있었다 */
.il-be__head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}

/* 순서 손잡이. 맨 앞에 서고 세로로 가운데다 (링크트리와 같은 자리).
   위아래 버튼을 따로 세우지 않는다 — 대신 이 손잡이가 버튼이라
   커서를 두고 ↑↓ 를 누르면 순서가 바뀐다 (WCAG 2.1.1).
   마우스는 끌고 키보드는 화살표를 쓴다 */
.il-be__grip {
  flex: none; align-self: center;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 30px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent;
  /* 한 단 진하게 (2026-08-26 10차). --text-placeholder 는 UI 전용 색이라
     3.24:1 이다 — 끌어야 하는 것이 안 보이면 있으나 마나다 */
  color: var(--text-muted);
  cursor: grab;
}
.il-be__grip:hover { background: var(--bg-subtle); color: var(--ink); }
.il-be__grip:active { cursor: grabbing; }

/* 자식 줄의 손잡이 — 점 여섯 대신 `묶음에서 빼기` 하나가 선다
   (2026-09-08 2차). 둘을 나란히 두었더니 한 칸에 아이콘이 둘인데 하는 일이
   겹쳤다: 손잡이의 Shift+↓ 가 바로 그 단추가 하는 일이다.
   그래서 하나로 합쳤다 — 끌면 옮기고 · 누르면 빠지고 · ↑↓ 로 순서를 바꾼다.
   생김새는 맨 위 줄의 손잡이(.il-be__grip)와 같은 칸을 쓴다 */
.il-be__out {
  flex: none; align-self: center;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 30px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted); cursor: grab;
}
.il-be__out:hover { background: var(--bg-subtle); color: var(--ink); }
.il-be__out:active { cursor: grabbing; }
.il-be__out svg { width: 16px; height: 16px; }

/* 끄는 동안 — 집어 든 행은 옅게, 놓일 자리는 잉크 선으로 */
.il-be.is-dragging, .il-be__child.is-dragging { opacity: .4; }
/* 놓을 자리를 커서 아래에서 말한다.
     위 · 아래  선 하나 — 그 자리에 끼워 넣는다
     가운데      테두리 전체 — 이 블록과 **묶는다**
   선과 테두리로 갈라 둔 이유: 둘이 같은 모양이면 끌면서 지금 무엇이
   일어날지 모른다. 선은 사이(틈)를 가리키고 테두리는 대상을 가리킨다 */
.il-be.is-over-top,    .il-be__child.is-over-top    { box-shadow: inset 0 2px 0 var(--ink); }
.il-be.is-over-bottom, .il-be__child.is-over-bottom { box-shadow: inset 0 -2px 0 var(--ink); }
.il-be.is-over-mid {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
  background: var(--bg-subtle);
}
/* 끄는 동안 커서가 칸 위를 지나가도 글자가 잡히지 않게 —
   끌기 중에는 행 전체가 하나의 물건이다 */
.il-be.is-dragging, .il-be__child.is-dragging { opacity: .5; }

/* ── 내 링크에서 고르기 (2026-09-01) ──────────────────────────────
   주소를 손으로 붙여 넣는 길은 그대로 두고, 이미 만들어 둔 단축 링크를
   고르는 길을 하나 더 연다. 그룹 링크에 거는 것은 대개 우리가 이미
   줄여 둔 주소이고, 그것을 다시 찾아 복사해 오는 것이 실제 일이었다.

   일곱 줄까지 편다 — 그 뒤로는 상자 안에서 스크롤한다 (2026-09-15).
   다 펼치면 고르는 자리가 아니라 또 하나의 링크 목록이 된다 */
.il-be__pickq { height: 34px; font-size: var(--fs-caption); }

/* ★ 일곱 줄까지 펴지고 그 뒤로 스크롤한다 (2026-09-15 · 사용자 요청).
   앞서는 JS 가 여덟에서 잘랐다(pickRows). 그러면 **아홉 번째 링크가 아예
   없는 것처럼** 보인다 — 목록이 끝나 있으니 그것이 전부라고 읽히고,
   안 보이는 것을 찾을 생각을 하지 않는다. 다 담고 상자로 막는다:
   더 있다는 것을 스크롤바가 말한다.

   줄 높이를 여기서 못 박는 까닭 — 일곱 줄이라는 말이 맞으려면 한 줄이
   몇 px 인지 이 파일이 알아야 한다. 안쪽 여백으로 정해지게 두면 글꼴이
   바뀔 때 `일곱 줄`이 조용히 6.4줄이 된다.

   overscroll-behavior — 다 내리고 더 굴리면 서랍 뒤의 화면이 따라
   움직인다. 서랍은 제자리에 있는데 화면이 흐르면 어디를 보고 있었는지
   잃는다 (폰에서 특히 그렇다) */
.il-be__picks {
  --be-pick-h: 36px;
  margin-top: var(--sp-2);
  max-height: calc(7 * var(--be-pick-h));
  overflow-y: auto; overscroll-behavior: contain;
}
.il-be__pick {
  display: flex; align-items: baseline; gap: var(--sp-3);
  width: 100%; height: var(--be-pick-h); padding: 0 var(--sp-3);
  border: 0; border-radius: var(--radius-sm);
  background: transparent; cursor: pointer; text-align: left;
  font-family: inherit;
}
.il-be__pick:hover { background: var(--bg-subtle); }
/* 주소가 먼저다 — 고르는 기준이 제목이 아니라 `어느 단축 주소인가` 다 */
.il-be__pickurl {
  flex: none; font-family: var(--font-mono); font-size: var(--fs-caption);
  font-weight: 700; color: var(--ink);
}
.il-be__picktitle {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-micro); color: var(--text-muted);
}

/* ★ 블록 종류 배지(`링크` · `묶음`)를 걷어냈다 (2026-09-01).
   종류가 넷일 때는 아이콘만으로 구분이 안 돼서 글자를 붙였는데, 지금은
   더할 수 있는 것이 링크 하나다 — 행마다 `링크` 라고 적혀 있으면
   그것은 정보가 아니라 배경이다. 묶음도 상자와 자식으로 이미 구분된다 */
/* 칸이 내용 폭이라 그대로 두면 제목과 주소가 한 줄에 나란히 선다.
   세로로 쌓고 왼쪽에 맞춘다 */
.il-be__body {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: flex-start;
}
.il-be__title {
  display: block; font-size: var(--fs-body); font-weight: 700; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.il-be__dest {
  display: block; margin-top: 2px;
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── 행 안에서 바로 고치는 칸 (링크트리 방식) ────────────────────
   인풋이지만 평소에는 글자처럼 보인다. 행마다 테두리가 셋씩 서면
   목록이 시끄러워지고, 어디가 눌리는 곳인지가 오히려 흐려진다.
   손을 올리면 바탕이 서고, 커서가 들어가면 테두리가 잉크가 된다 —
   글자 칸에 포커스 링을 두지 않는 이 저장소의 규칙 그대로다 */
/* ★ 상자로 두르지 않는다 (2026-08-26 9차).
   네 면을 두르면 그 순간 인풋이 알약처럼 보이고, 글을 고치는 자리가 아니라
   무언가를 고르는 칸처럼 읽힌다. 밑줄 한 줄이면 "여기에 친다" 가 말해진다.

   포커스를 밑줄로 잡는다 — 이 저장소는 글자 칸에 링을 겹치지 않고
   테두리 한 줄로 말한다(csstest §글자 칸). 그 규칙을 한 면으로 줄인 것이다.
   쉬는 동안에도 2px 를 투명으로 잡아 둔다 — 포커스에서 두께가 생기면
   글자가 2px 들썩인다 */
.il-be__inp {
  width: 100%; min-width: 0;
  /* 오른쪽 안여백을 0 으로 둔다 (2026-08-26 13차) — 칸의 폭은 글자 폭에
     맞춰 재는데, 오른쪽에 안여백이 남아 있으면 그만큼 연필이 밀려난다.
     왼쪽 안여백은 남긴다: 음수 margin 과 짝을 이뤄 글자를 행 왼쪽에 맞추고,
     손을 올렸을 때 눌리는 자리가 글자에 딱 붙지 않게 한다 */
  padding: 3px 0 2px var(--sp-2); margin-left: calc(var(--sp-2) * -1);
  border: 0;
  background: transparent; color: var(--ink);
  font-family: inherit; font-size: var(--fs-body);
  text-overflow: ellipsis;
}
/* ★ 커서만 깜빡인다 (2026-08-26 13차). 바탕도 밑줄도 링도 없다.

   11차에 :focus 만 끄고 :focus-visible 은 남겨 두었다. 그때 적은
   "마우스로 누를 때는 아무것도 안 뜬다" 는 버튼 얘기였다 —
   **글자 칸은 무엇으로 누르든 항상 :focus-visible 에 걸린다.**
   키보드로 치는 곳이라 브라우저가 그렇게 정해 둔다. 그래서 누를 때마다
   전역 링(components.css:45)이 그대로 떴고, 화면에서는 그것이 상자로 보였다.

   둘 다 끈다. 여기서 포커스를 말하는 것은 **캐럿**이다 — 글자 칸은
   깜빡이는 막대가 있어 상자 없이도 지금 어디에 치고 있는지가 보인다.
   버튼·토글·손잡이의 링은 그대로 둔다 — 그쪽은 캐럿이 없어
   링을 끄면 정말로 어디에 있는지 사라진다 */
.il-be__inp:focus,
.il-be__inp:focus-visible { outline: none; box-shadow: none; }
.il-be__inp::placeholder { color: var(--text-placeholder); }

/* ★ 손가락 기기에서는 이 칸도 16px 이다 (2026-09-11).
     칸 자체는 components.css 의 요소 규칙이 이미 키운다. 그런데 여기만
     **클래스로도 적어야** 하는 까닭이 따로 있다 —

     이 칸은 글자 폭에 맞춰 제 너비를 잰다 (pageedit.js 의 fitInp). 재는 자는
     화면 밖에 세워 둔 `<span>` 하나인데, **칸과 같은 class 를 입혀** 글꼴과
     굵기를 맞춘다. 그 자는 input 이 아니므로 요소 규칙에 안 걸린다 —
     클래스로도 안 적으면 칸은 16px 로 그려지는데 자는 14px 로 재서,
     블록 제목과 주소가 제 글자보다 좁게 잘린다. */
@media (pointer: coarse) {
  .il-be__inp { font-size: 16px; }
}

/* 제목과 주소는 **같은 크기**다 (2026-08-26 9차).
   주소를 모노 11px 로 뒀더니 제목 옆에서 각주처럼 보였다 —
   둘 다 사람이 읽고 고치는 글이라 크기가 같아야 한다.
   무게와 색으로만 가른다: 제목은 굵고 잉크, 주소는 보통에 한 단 옅게 */
.il-be__inp--title { font-weight: 700; }
.il-be__inp--dest  { color: var(--text-secondary); }

/* 값이 들어찬 칸에만 연필이 뜬다 (링크트리와 같다).
   빈 칸에는 자리 표시 글자가 이미 "여기 치세요" 라고 말하고 있다 */
/* ★ 빈 칸은 넓게, 찬 칸은 글자만큼 (2026-08-26 11차).
     둘 다 겪고 나온 값이다 —
       늘 넓게 두면  연필이 행 끝에 떨어져 무엇에 딸린 것인지 안 읽힌다
       늘 좁게 두면  빈 칸이 여덟 자로 쪼그라들어 `연결할 주소` 가 잘린다
     그래서 값이 있을 때만 좁힌다. 폭은 **글자를 직접 재서** 넣는다 (pageedit.js fitInp — inline width).
     size 속성은 밑받침이다: size 는 `0` 글자 한 칸을 단위로 세는 값이라
     한글과 라틴이 섞인 줄에서는 실제 폭과 어긋난다 —
     `https://www.innored.co.kr/` 가 26자라 27칸을 잡았는데 그려진 글자는
     그보다 짧아 끝에 빈틈이 남고, 그만큼 연필이 밀려난다 */
.il-be__inpwrap {
  display: flex; align-items: center; gap: 2px;
  /* ★ `min(460px, 100%)` 이다 (2026-09-11). 460 만 적어 두면 **칸이 제 칸을
       넘어선다** — 이 칸은 글자 폭에 맞춰 JS 가 style.width 를 박는데
       (pageedit.js 의 fitInp, 상한 460), 담는 칸(.il-be__body)은 min-width:0
       이라 좁아지는 대로 좁아지고 넘친 것을 잘라 주지도 않는다.
       그래서 주소가 길면 오른쪽의 켜고 끄기 · 지우기 **밑으로 깔려서** 글자가
       단추 사이로 비어져 나왔다. 100% 를 같이 걸면 칸을 넘지 않고 … 로 끊는다 */
  width: 100%; max-width: min(460px, 100%);
}
.il-be__inpwrap > .il-be__inp { flex: 1 1 auto; width: 100%; }

.il-be__inpwrap:not(.is-empty) { display: inline-flex; width: auto; }
.il-be__inpwrap:not(.is-empty) > .il-be__inp { flex: 0 1 auto; width: auto; }
.il-be__pen {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted); cursor: pointer;
}
.il-be__pen:hover { background: var(--bg-subtle); color: var(--ink); }
.il-be__inpwrap.is-empty > .il-be__pen { visibility: hidden; }

/* ★ 고치는 동안에는 비켜 준다 (2026-09-08). 연필이 하는 일은 `이건 고칠 수
   있는 것` 이라고 말하는 것뿐인데(누르면 그 칸으로 커서를 옮긴다), 이미
   커서가 들어와 있으면 그 말은 끝난 말이다 — 남아 있으면 치는 글자 바로
   뒤에 아이콘이 따라붙는다.

   visibility 다. display:none 이나 폭을 0 으로 만들면 그 자리만큼 칸이
   넓어져 **치기 시작하는 순간 글자가 옆으로 튄다** — 칸 폭을 글자에 맞춰
   재고 있어서(fitInp) 그 흔들림이 그대로 보인다. 자리는 두고 그림만 감춘다.

   :focus-within 이라야 한다. 연필은 칸의 형제라 :focus 로는 안 걸린다 */
.il-be__inpwrap:focus-within > .il-be__pen { visibility: hidden; }

/* 아이콘 줄. 링크트리가 블록 행 아래에 두는 그것이다 */
.il-be__icons { display: flex; align-items: center; gap: var(--sp-1); margin-top: var(--sp-1); }
.il-be__ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted); cursor: pointer;
}
.il-be__ico:hover { background: var(--bg-subtle); color: var(--ink); }
/* 펼쳐 둔 것은 눌린 채로 보인다 — 어느 서랍이 열렸는지가 아이콘에 남아야 한다 */
.il-be__ico[aria-expanded="true"] { background: var(--ink); color: var(--on-ink); }

/* 서랍 — 그 행 안에서 아래로 펼쳐진다 */
.il-be__drawer {
  margin-top: var(--sp-3); padding: var(--sp-4);
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: var(--sp-2);
}
/* 자식 행 안에서는 여백을 한 단 줄인다 — 모음 안에 또 상자가 생기면 답답하다 */
.il-be__child .il-be__drawer { padding: var(--sp-3) 0 var(--sp-1); }
.il-be__drawer--center { align-items: center; text-align: center; }


/* ── 스타일 고르기 — 낱말이 아니라 모양으로 ──────────────────────
   인포크의 `스타일` 라디오를 가져왔다. `심플 / 썸네일 / 카드` 라는 낱말만
   놓으면 그 셋이 어떻게 다른지는 골라 봐야 안다 — 카드 안에 그 스타일의
   뼈대를 그려 두면 고르기 전에 보인다.

   고른 것에 주황 대신 잉크를 쓴다 (innored_basic 하드 룰 — 강조는 잉크다) */
/* 카드 사이는 sp-5 다 (2026-08-26 14차). sp-3 로 붙여 뒀더니 뼈대 그림끼리
   서로의 일부처럼 읽혔다 — 안에 든 것이 그림이라 글자보다 더 벌려야 갈린다 */
.il-be__styles { display: flex; justify-content: center; gap: var(--sp-5); flex-wrap: wrap; }

.il-be__style {
  width: 92px; padding: 0; border: 0; background: none;
  text-align: center; cursor: pointer;
}
.il-be__style:focus-visible { box-shadow: var(--focus-ring); outline: none; border-radius: var(--radius-md); }

.il-be__smbox {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  height: 54px; padding: var(--sp-2) var(--sp-3);
  border: 2px solid var(--border); border-radius: var(--radius-md);
  background: var(--bg-elevated);
  transition: border-color var(--t-fast);
}
.il-be__smbox--row { flex-direction: row; gap: 5px; }
.il-be__smbox--col { flex-direction: column; gap: 4px; }
.il-be__style:hover .il-be__smbox { border-color: var(--border-strong); }
.il-be__style[aria-pressed="true"] .il-be__smbox { border-color: var(--ink); }

/* 고른 것에 붙는 체크. 테두리만으로도 알 수 있지만, 테두리 색 하나에
   기대면 색을 못 가리는 사람에게는 아무 표시도 없는 것과 같다 */
.il-be__smcheck {
  position: absolute; right: -7px; bottom: -7px;
  display: none; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: var(--radius-full);
  background: var(--ink); color: var(--on-ink);
}
.il-be__style[aria-pressed="true"] .il-be__smcheck { display: flex; }

.il-be__smname {
  display: block; margin-top: var(--sp-2);
  font-size: var(--fs-micro); font-weight: 700; color: var(--text-muted);
}
.il-be__style[aria-pressed="true"] .il-be__smname { color: var(--ink); }

/* 뼈대 조각 — 네모와 막대뿐이다 */
.il-be__smsq {
  flex: none; width: 17px; height: 17px; border-radius: 3px;
  background: var(--border-strong);
}
.il-be__smbox--row > .il-be__smsq { height: 22px; }
.il-be__smlines { flex: 1 1 auto; display: flex; flex-direction: column; gap: 4px; }
.il-be__smbar { height: 4px; border-radius: 2px; background: var(--border-strong); }
.il-be__smbox--col > .il-be__smbar { width: 100%; }
.il-be__smbar--w70 { width: 70%; }
.il-be__smbar--w60 { width: 60%; }
.il-be__smbar--w45 { width: 45%; }
.il-be__smblock {
  width: 100%; height: 20px; border-radius: 3px;
  background: var(--border-strong);
}
/* 고르면 뼈대도 함께 진해진다 — 테두리만 바뀌면 안쪽이 죽어 보인다 */
.il-be__style[aria-pressed="true"] .il-be__smsq,
.il-be__style[aria-pressed="true"] .il-be__smbar,
.il-be__style[aria-pressed="true"] .il-be__smblock { background: var(--ink); }

/* 블록별 클릭수를 행에서 뺐다 (2026-08-26 8차).
   인포크는 행마다 붙여 두는데, 토글 옆에 숫자가 서면 그 숫자가
   토글의 값처럼 읽힌다. 성과는 그룹 링크 통계의 블록별 클릭 표에서 본다 */
.il-be__acts { flex: none; display: flex; align-items: center; gap: var(--sp-2); }

/* ── 순서 단추 — 폰에서만 (2026-09-11) ───────────────────────────────
   넓은 화면에서는 **없다.** 거기는 끌기가 더 빠르고, 손잡이에 키보드 길도
   이미 붙어 있다 — 줄마다 단추가 둘씩 늘면 누를 것만 많아진다.
   폰에서는 그 둘이 다 죽어서(끌기는 터치에서 이벤트가 안 나고, 자판이 없다)
   손잡이 자리를 이것이 이어받는다. 사연은 pageedit.js 의 moveBtns 에 있다 */
.il-be__move { display: none; flex: none; }
.il-be__mv {
  display: inline-flex; align-items: center; justify-content: center;
  /* 24px 는 WCAG 2.5.8 의 바닥이다. 손잡이 기둥이 좁아 더 키우기 어렵고,
     둘이 세로로 붙어 서므로 사이를 2px 띄워 누를 자리를 가른다 */
  width: 26px; height: 26px; padding: 0;
  border: 0; border-radius: var(--radius-sm);
  background: transparent; color: var(--text-muted); cursor: pointer;
}
.il-be__mv:hover:not(:disabled) { background: var(--bg-subtle); color: var(--ink); }
/* 끝에서는 잠근다. 눌러도 아무 일이 없는 단추를 살려 두면 그것이 고장으로
   읽힌다 — 이 화면이 손잡이로 겪던 바로 그 문제다 */
.il-be__mv:disabled { opacity: .25; cursor: default; }

/* 묶기도 폰에서만. 넓은 화면은 끌기(가운데 구역)와 Shift+↑ 가 이미 맡는다 —
   거기에 단추를 더하면 줄마다 누를 것이 하나 더 는다 (pageedit.js 의 icons) */
.il-be__ico--group { display: none; }
.il-be__ico:disabled { opacity: .25; cursor: default; }
.il-be__ico:disabled:hover { background: transparent; color: var(--text-muted); }

/* 펼침 영역 — 모음의 자식이 여기 들어간다 */
.il-be__fold { border-top: 1px solid var(--border); padding: var(--sp-3) var(--sp-4); }
.il-be__foldbtn {
  display: block; width: 100%; padding: var(--sp-2);
  border: 0; border-top: 1px solid var(--border); background: transparent;
  font-family: inherit; font-size: var(--fs-micro); font-weight: 700;
  color: var(--text-secondary); cursor: pointer;
}
.il-be__foldbtn:hover { color: var(--ink); background: var(--bg-subtle); }

/* 자식 행 — 부모보다 한 칸 안쪽. 테두리를 또 두르지 않는다 */
/* 자식 행. 서랍이 아래로 펼쳐지므로 격자로 짠다 —
   flex 한 줄로 두면 서랍이 오른쪽으로 밀려난다 */
.il-be__child {
  display: grid; gap: 0 var(--sp-3); padding: var(--sp-2) var(--sp-3);
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  border-radius: var(--radius-sm);
}
.il-be__child > .il-be__drawer { grid-column: 1 / -1; }
.il-be__child + .il-be__child { margin-top: var(--sp-1); }
.il-be__child:hover { background: var(--bg-subtle); }

/* ── 폰에서는 줄을 눕힌다 (2026-09-11) ────────────────────────────────
   행 하나에 손잡이 · 제목 · 주소 · 아이콘 셋 · 켜고 끄기 · 지우기가 선다.
   넓은 화면에서는 왼쪽 글 칸과 오른쪽 단추 칸이 나란히 서지만, 폰에서는
   글 칸이 줄어드는 만큼 **주소가 단추 밑으로 깔렸다** (위 inpwrap 의 max-width
   가 그것을 막는다). 잘리지만 않을 뿐 주소를 읽을 자리는 여전히 좁다.

   그래서 켜고 끄기 · 지우기를 **아이콘 줄의 오른쪽**으로 내린다.
   제목과 주소가 줄을 통째로 쓰고, 단추는 이미 단추가 서 있는 줄에 합류한다 —
   누르는 것끼리 한 줄에 모이므로 손이 갈 곳도 한 군데다.

        ⠿   제목                          ✎
            https://…                     ✎
            🔗 🖼 ▦            [켜고 끄기] [지우기]

   ★ `display: contents` 로 글 칸(.il-be__body)의 상자를 없앤다. 그래야 그
     속의 제목 · 주소 · 아이콘이 바깥 격자의 칸을 직접 차지한다 — 상자를 둔
     채로는 단추를 그 속의 아이콘 줄 옆에 세울 방법이 없다 (둘의 부모가 다르다).
     .il-be__body 는 배치만 하는 칸이라 상자를 없애도 잃는 모양이 없다.

   ★ 손잡이는 세 줄을 통째로 쓴다 (같은 이름을 세 줄에 적으면 그렇게 된다).
     끌고 옮기는 자리라 줄 옆에 길게 서 있는 편이 맞다.

   ★ 자식 줄(.il-be__child)은 칸이 넷이다 — 거기는 켜고 끄기와 지우기가
     `.il-be__acts` 로 묶이지 않고 각각 서 있어서, 칸을 따로 준다.

   ★ **아이콘 줄이 있는 행에만** 건다 (`:has(.il-be__icons)`).
     묶음(collection)에는 주소도 아이콘도 없어서 제목 한 줄뿐이다 —
     거기까지 눕히면 빈 줄 하나를 사이에 두고 단추가 저 아래 혼자 선다.
     한 줄짜리 행은 원래대로 나란히 두는 편이 맞다. */
@media (max-width: 520px) {
  :is(.il-be__head, .il-be__child):has(.il-be__icons) {
    display: grid;
    column-gap: var(--sp-2);
    row-gap: 2px;
    align-items: center;
  }
  .il-be__head:has(.il-be__icons) {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "grip title title"
      "grip dest  dest"
      "grip icons acts";
  }
  .il-be__child:has(.il-be__icons) {
    grid-template-areas:
      "out  title title title"
      "move dest  dest  dest"
      "move icons vis   del";
  }

  /* ★ 손잡이를 순서 단추가 대신한다. 폰에서 손잡이는 끌리지도(터치에서
       이벤트가 안 난다) 눌리지도 않는 장식이다 — 자리를 통째로 내준다.
     ★ 자식 줄의 `빼기`(.il-be__out)는 남긴다. 그것은 폰에서도 눌러서
       동작하는 **유일한 묶음 해제 길**이라 걷어내면 갈 곳이 없어진다.
       그래서 그 기둥을 둘로 나눈다 — 위 칸에 빼기, 아래 두 칸에 순서 단추 */
  .il-be__move { display: flex; flex-direction: column; gap: 2px; }
  .il-be__grip { display: none; }
  /* 묶기는 아이콘 줄 끝에 선다 — 그 줄에 자리가 남고, 서랍을 열지 않아도
     한 번에 닿는다 (오른쪽의 켜고 끄기 · 지우기와는 사이가 벌어져 있다) */
  .il-be__ico--group { display: inline-flex; }
  .il-be__head:has(.il-be__icons) > .il-be__move { grid-area: grip; }
  .il-be__child:has(.il-be__icons) > .il-be__move { grid-area: move; }

  /* 상자를 없애 속엣것이 바깥 격자에 직접 앉게 한다 */
  :is(.il-be__head, .il-be__child):has(.il-be__icons) > .il-be__body { display: contents; }

  :is(.il-be__head, .il-be__child):has(.il-be__icons) > .il-be__grip { grid-area: grip; }
  :is(.il-be__head, .il-be__child):has(.il-be__icons) > .il-be__out { grid-area: out; }
  /* 제목은 늘 첫 칸, 주소는 둘째 칸이다 */
  :is(.il-be__head, .il-be__child):has(.il-be__icons) .il-be__inpwrap:first-child { grid-area: title; }
  :is(.il-be__head, .il-be__child):has(.il-be__icons) .il-be__inpwrap:nth-child(2) { grid-area: dest; }
  :is(.il-be__head, .il-be__child):has(.il-be__icons) .il-be__icons { grid-area: icons; }
  /* 맨 위 줄 — 단추 둘이 .il-be__acts 로 묶여 있다 */
  .il-be__head:has(.il-be__icons) > .il-be__acts { grid-area: acts; justify-self: end; }
  /* 자식 줄 — 묶이지 않고 각각 선다 */
  .il-be__child:has(.il-be__icons) > .il-toggle { grid-area: vis; }
  .il-be__child:has(.il-be__icons) > [data-be="del"] { grid-area: del; }
  /* 서랍은 줄 전체를 쓴다. 이름 격자에서는 위의 `grid-column: 1 / -1` 만으로는
     자리가 안 잡혀 다시 적는다 */
  .il-be__child:has(.il-be__icons) > .il-be__drawer { grid-area: auto; grid-column: 1 / -1; }
}

/* 블록을 더하는 자리. 점선이라 "여기는 아직 빈 곳" 으로 읽힌다 */
.il-be__add {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  width: 100%; padding: var(--sp-4);
  border: 1px dashed var(--border-strong); border-radius: var(--radius-md);
  background: transparent; color: var(--text-secondary);
  font-family: inherit; font-size: var(--fs-body); font-weight: 700; cursor: pointer;
}
.il-be__add:hover { border-color: var(--ink); color: var(--ink); background: var(--bg-subtle); }


/* ── 블록 이미지 서랍 ────────────────────────────────────────────
   아이콘을 누르면 그 행 아래가 펼쳐진다 (링크트리 `Add Thumbnail`).
   레이어로 덮지 않는 이유는 pageedit.js 의 블록 목록 머리말에 있다 */
.il-be__imgbox { display: flex; align-items: flex-start; gap: var(--sp-4); }
.il-be__imgprev {
  flex: none; width: 72px; height: 72px; border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background-color: var(--bg-elevated);
  background-size: cover; background-position: center;
}
.il-be__imgprev.is-empty { border-style: dashed; }
.il-be__imgacts {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.il-be__imgrow { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
/* 파일 칸을 버튼처럼 감쌌다. label 이라 기본 커서가 글자 커서다 */
.il-be__imgrow label.il-btn { cursor: pointer; }


/* ── 테마 고르기 ─────────────────────────────────────────────────
   6개다. 링크트리는 21개인데 그것은 고르는 화면이 아니라 헤매는 화면이다 */
/* ★ 테마 카드 6종을 걷어냈다 (2026-09-01). 프리셋이 하는 일은 배경색 ·
   버튼색 두 값을 한 번에 넣는 것뿐이었는데, 그 두 칸이 바로 아래 열려 있어
   고르고 나면 카드 이름과 실제 색이 곧 어긋났다 (mock-data.js §PAGE_THEME).
   .il-themes 는 이제 쓰이지 않는다 — 규칙만 지운다 */
.il-theme {
  position: relative; padding: 0; cursor: pointer;
  border: 2px solid transparent; border-radius: var(--radius-md);
  background: transparent;
}
.il-theme__chip {
  /* 프리셋 색은 JS 가 인라인으로 넣는다. 기본값은 여기 */
  --th-bg:  var(--bg-subtle);
  --th-btn: var(--border-strong);

  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 5px; height: 62px; border-radius: 9px;
  border: 1px solid var(--border);
  background: var(--th-bg);
}
.il-theme__btn {
  width: 60%; height: 9px; border-radius: var(--radius-full);
  background: var(--th-btn);
}
.il-theme[aria-pressed="true"] { border-color: var(--ink); }
.il-theme:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* 대비비. 사람이 색을 직접 고쳤을 때 지금 값이 얼마인지 말해 준다 —
   프리셋 6종은 전부 9:1 을 넘으므로 평소에는 조용하다 */
/* ── 주소 칸 · 잠금 · 접기 (2026-09-01) ────────────────────────────
   page-new.html 이 여기로 들어오면서 생긴 것들이다.

   ★ 아직 안 만들어졌을 때 아래를 잠근다.
     빈 칸을 열어 두고 적게 한 뒤 "주소부터 정하세요" 라고 되묻는 것보다,
     못 적게 해 두고 위 칸으로 눈이 가게 하는 편이 짧다.
     흐리게만 두지 않는다 — pointer-events 로 마우스를 막고, JS 가
     disabled 까지 세운다 (흐린데 눌리면 고장으로 읽힌다) */
.il-pe__group.is-locked { opacity: .38; pointer-events: none; }

/* 주소 판정 한 줄. 자리를 늘 잡아 둔다 — 글자가 나타났다 사라지면
   아래 칸이 위아래로 흔들린다 (page-new.html 이 쓰던 규칙 그대로) */
.il-pe__note {
  display: block; margin: var(--sp-2) 0 0; min-height: 18px;
  font-size: var(--fs-micro); color: var(--text-muted);
}
.il-pe__note.is-bad { color: var(--danger); }

/* SNS 접기 — 필수가 아니고 칸이 여섯이다. 쓰는 사람만 편다.
   여는 줄은 조용하다 (links.html 의 UTM 여는 줄과 같은 규칙) */
/* 밴드(.il-pe__band) 안에 든다 — 선과 여백은 밴드가 이미 든다.
   여기서 또 들면 블록과 SNS 사이에 선이 둘이 된다 (2026-09-01 4차에 밟았다) */
.il-pe__fold { margin: 0; padding: 0; border: 0; }
/* ── 여는 줄 ──────────────────────────────────────────────────────
   줄 전체가 눌리는 판이고, 그 위에 이름표 · i · 개수 · 꺾쇠가 뜬다
   (2026-09-01 3차). 링크 카드의 덮개(.il-lc__go)와 같은 꼴이다.

   왜 덮개인가 — button 안에 button 을 넣을 수 없다. i 를 여는 버튼 안에
   두면 브라우저가 마크업을 임의로 풀어 버리고, 버튼 밖으로 빼면
   꺾쇠(오른쪽 끝)와 i(이름표 옆) 둘 중 하나는 제자리를 잃는다.

   꺾쇠는 오른쪽 끝이다 (2차) — 왼쪽에 두면 이름표가 위 줄들의 이름표보다
   꺾쇠 너비만큼 안으로 밀려 왼쪽 세로선이 이 줄에서만 끊긴다.
   개수(.il-pe__foldnote)가 그 사이를 채운다 — 없으면 자리도 안 잡는다 */
.il-pe__foldhead {
  position: relative;
  display: flex; align-items: center; gap: var(--sp-2);
}
.il-pe__foldbtn {
  position: absolute; inset: 0; width: 100%;
  border: 0; background: transparent; padding: 0;
  border-radius: var(--radius-sm); cursor: pointer;
}
.il-pe__foldbtn:focus-visible { box-shadow: var(--focus-ring); }
.il-pe__foldlab {
  font-size: var(--fs-caption); font-weight: 620; color: var(--text-secondary);
}
.il-pe__foldhead:hover .il-pe__foldlab { color: var(--ink); }
/* i 만 덮개 위로 띄운다 — 나머지는 글자라 눌릴 일이 없다 */
.il-pe__foldhead .il-infotip { position: relative; z-index: 1; }
.il-pe__foldhead .il-pe__foldi { margin-left: auto; }
.il-pe__foldi { flex: none; transition: transform var(--t-fast); }
.il-pe__foldhead:has(.il-pe__foldbtn[aria-expanded="true"]) .il-pe__foldi {
  transform: rotate(180deg);
}
@media (prefers-reduced-motion: reduce) { .il-pe__foldi { transition: none; } }
/* 접힌 줄이 몇 개를 넣었는지 말한다 — 접힌 것 안에 보이지 않는 설정이
   남지 않게 하는 유일한 장치다 */
.il-pe__foldnote { font-size: var(--fs-micro); font-weight: 500; color: var(--text-muted); }
.il-pe__foldnote.is-set { color: var(--ink); font-weight: 620; }
.il-pe__foldnote:empty { display: none; }
.il-pe__foldbody { margin-top: var(--sp-3); }

/* 묶음 행 — 편집 화면에서도 한 덩어리로 보여야 한다.
   공개 화면의 상자(.il-pg__box)와 같은 말을 여기서도 한다 */
.il-be--box { border-color: var(--border-strong); }

.il-pe__contrast {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-top: var(--sp-2); font-size: var(--fs-micro);
  color: var(--text-muted); font-variant-numeric: tabular-nums;
}
/* ★ 안내 두 줄을 i 레이어로 옮겼다 (2026-09-01 4차) — 한 번 읽으면 다시
   안 읽는 글인데 색 상자보다 넓게 자리를 차지했다.
   다만 **못 읽는 조합일 때는 접지 않는다.** 이 칸이 있는 이유가 그 경우를
   잡는 것이라(§18-3 · B7), 정작 걸렸을 때 숨어 있으면 안 된다 */
.il-pe__contrast.is-bad { color: var(--danger); font-weight: 700; }
/* ── 이름표 안의 i ────────────────────────────────────────────────
   ★ 글자와 아이콘의 세로 가운데를 맞춘다 (2026-09-01 5차).
     .il-infotip 은 inline-flex + vertical-align:middle 인데, middle 은
     **글꼴의 x-높이 절반**을 기준으로 잰다. 14px 글자 옆에 24px 짜리 버튼이
     서면 그 기준이 버튼의 가운데와 어긋나 한두 픽셀 내려앉는다 —
     화면에서는 `색` 보다 ⓘ 가 살짝 아래로 처져 보였다.

     이름표를 flex 로 만들어 두 아이를 가운데로 세운다. 글꼴 기준이 아니라
     상자 기준이 되므로 글자 크기가 바뀌어도 어긋나지 않는다.
     i 가 없는 이름표는 그대로 둔다 — 글자 하나뿐인 줄에 flex 를 걸 이유가 없다 */
.il-pe__lab:has(.il-infotip) { display: flex; align-items: center; }
.il-pe__lab .il-infotip__btn { color: var(--text-placeholder); }


/* ── 미리보기 폰 ─────────────────────────────────────────────────
   껍데기만 그린다. 안은 .il-pg 로 공개 화면와 같은 마크업이다 —
   미리보기와 실제가 다른 마크업이면 언젠가 갈라진다 */
/* ★ 안쪽 폭 375 ~ 430px (2026-09-08. 380 고정 → 390 고정 → 이 범위).
   흔한 폭은 이렇다 (CSS 픽셀, 세로) —
     360  갤럭시 S 계열 등 안드로이드에서 가장 흔하다
     375  아이폰 SE · 8 · X · 11 Pro · 12 mini   ← 아래 끝
     390  아이폰 12 · 13 · 14 · 15 기본
     393  픽셀 · 갤럭시 S24
     430  아이폰 Pro Max                          ← 위 끝
   380 은 어느 폰의 폭도 아닌 어림수였다.

   ★ 칸을 따라 늘어나되 **양 끝이 둘 다 실제 폰의 폭**이다. 브라우저를
     줄이면 줄바꿈 자리가 달라지지만, 어느 폭에서 보든 그것은 `어떤 폰에서
     본 모습` 이다 — 실제로 큰 폰과 작은 폰에서 다르게 보이는 것이 맞고,
     좁혀 보는 것이 그 확인이 된다.
     아래로는 375 에서 멈춘다. 더 줄면 어느 폰도 아닌 폭이 된다.

   ★ 375 를 min() 으로 감싼다. 담는 칸이 그보다 좁으면(작은 폰으로 이 화면을
     열었을 때) 못 박힌 375 가 칸 밖으로 삐져나가고, 그러면 **화면 전체가
     가로로 구른다** — 이 저장소가 막아 둔 것이다 (components.css 의
     `표는 자기 컨테이너 안에서만 구른다`). 그때는 칸을 따라 준다.

   ★ 목록 그림(.il-pgc__shot)은 440 으로 그린다 — 여기와 다르다.
     배율 0.545 와 상자 250px 을 둘 다 지키려다 그렇게 됐다 (아래 그 주석).
     그래서 아슬아슬한 제목은 두 화면에서 줄바꿈이 다를 수 있다 */
/* ★ 폰 껍데기를 걷어냈다 (2026-09-08 5차. 8px 액자 → 얇은 테 → 알약 → 여기).
   테를 얇게도 해 보고 알약도 달아 봤는데, 어느 쪽이든 **껍데기가 먼저 눈에
   들어왔다.** 이 상자가 하는 일은 그룹 링크를 보여 주는 것이고, 그것을
   폰 그림 안에 넣는 것은 그 일에 보태는 것이 없다.
   링크트리도 그렇게 한다 — 테도 알약도 없이 모서리만 굴린 판 하나다.

   `폰` 이라는 이름은 남는다. 폭이 375~430 — 폰에서 보는 폭이라는 뜻이고,
   목록 그림(.il-pgc__shot)이 그 짝이다. 껍데기 얘기가 아니다.

   그림자는 남긴다. 바깥(--bg)과 안(그룹 링크 배경)이 둘 다 옅어서,
   그것이 없으면 어디까지가 미리보기인지 경계가 사라진다 */
.il-phone {
  width: 100%; max-width: 430px; min-width: min(375px, 100%);
  margin-inline: auto;
  border-radius: var(--radius-xl);
  overflow: hidden; background: var(--bg-elevated);
  box-shadow: var(--shadow-lg);
}
/* ★ 620 → 760 (2026-08-26 27차). 스크롤은 그대로 둔다 —
   그룹 링크는 얼마든 길어질 수 있어 언젠가는 넘친다.
   다만 620px 은 블록 서넛이면 이미 넘쳐서, 고치는 동안 **아래가 어떻게 되는지**를
   보려면 미리보기 안을 매번 굴려야 했다. 760px 이면 흔한 그룹 링크 하나가
   대부분 한눈에 들어온다 (실제 폰 화면 높이와도 가깝다).
   overscroll-behavior: contain — 안쪽 끝에 닿아도 바깥 그룹 링크가 따라 굴러가지 않는다 */
.il-phone__screen { height: 800px; overflow-y: auto; overscroll-behavior: contain; }


/* ── 공개 화면 (.il-pg) ────────────────────────────────────────
   ★ 여기만 색이 tokens.css 에서 오지 않는다.

   왜 그런가 — 이 화면은 이노링크의 관리 도구가 아니라 우리가 대신
   만들어 주는 클라이언트 산출물이다. innored_basic 하드 룰은 관리 화면이
   지킬 규칙이지 이것이 지킬 규칙이 아니다 (feature-spec §18-3).
   QR 색을 사람이 고르게 한 것과 같은 판단이다.

   기본값을 여기 두고 JS 가 인라인 style 로 덮어쓴다.
   기본값이 있어야 JS 가 실패해도 읽을 수 있는 그룹 링크가 남는다 */
.il-pg {
  --pg-bg:       var(--bg);
  --pg-text:     var(--ink);
  --pg-btn:      var(--bg-elevated);
  --pg-btn-text: var(--ink);
  --pg-radius:   12px;

  min-height: 100%;
  background: var(--pg-bg); color: var(--pg-text);
  padding: var(--sp-6) var(--sp-5) var(--sp-10);
  font-family: var(--font-sans);
}
/* 화면 전체가 공개 화면인 경우 (page-public.html) */
.il-pg--full { min-height: 100vh; }

/* ── 폰의 안전 영역 (2026-09-10) ────────────────────────────────────
   공개 화면은 `viewport-fit=cover` 로 연다 (groups/public.blade.php) —
   아이폰 가로에서 노치 옆 띠까지 장면이 이어지게 하려는 것이다. 그런데
   cover 는 안쪽 여백을 화면이 직접 챙기게 만든다: 그냥 두면 가로로 눕혔을
   때 버튼 끝이 노치 밑으로 들어간다.

   max() 로 잰다 — 안전 영역이 없는 곳(데스크톱 · 미리보기 · 목록 그림)에서
   env() 는 0 이라 지금까지의 여백이 그대로 선다.
   아래도 챙긴다: 홈 인디케이터 위에 마지막 버튼이 걸린다 */
.il-pg {
  padding-left: max(var(--sp-5), env(safe-area-inset-left));
  padding-right: max(var(--sp-5), env(safe-area-inset-right));
  padding-bottom: max(var(--sp-10), env(safe-area-inset-bottom));
}

/* ── 넓은 화면에서 보는 공개 화면 (2026-08-26 33차) ──────────────────
   ★ 이 그룹 링크는 **폰에서 보라고 만든 것**이다. 인스타 바이오에서 눌러 들어온다.
     그런데 PC 로 열면 폰용으로 짠 것이 1920px 벌판에 늘어져,
     버튼 하나가 화면 절반을 가로지르고 가운데 520px 만 글이 있다.
     그 모습은 **실제로 사람들이 보는 모습이 아니다** — 만든 사람이 확인하러
     열었다가 잘못 만든 줄 알게 된다.

     그래서 넓은 화면에서는 폰 폭으로 세우고 바깥을 회색으로 둔다.
     링크트리·인포크 둘 다 같은 모양이다.

   폰에서는 이 규칙이 걸리지 않는다 — 통으로 편다.
   테두리도 그림자도 없다. 폰 안에서 폰 껍데기를 그리면 그것이야말로 흉내다 */
/* 폰에서는 없는 것과 같다.
   ★ 이 줄은 @media **앞**에 있어야 한다. 뒤에 두면 같은 구체성에서
     나중 것이 이겨 넓은 화면에서도 안 보인다 — 이 파일 맨 위에
     적어 둔 바로 그 함정이다 (§규칙) */
.il-pgqr { display: none; }

/* ★ 폰에서는 body 도 그 테마의 색이다 (2026-09-10). 본문(main)이 화면을
   다 덮으므로 평소에는 안 보이지만, 흰 바탕이 한 군데라도 남아 있으면
   언젠가 드러난다 — 주소창이 접혔다 펴지는 그 한 프레임이 그렇다.
   값은 서버가 준다 (groups/public.blade.php 의 --pg-bg) */
body[data-page="pagepublic"] { background: var(--pg-bg, var(--bg)); }

@media (min-width: 768px) {
  /* ★ 바깥도 그 테마의 색이다 (2026-09-10). 앞서는 회색 한 가지였는데,
     테마가 `결`이 되고부터 어긋났다 — 달빛 호수의 밤 옆에 사무실 회색이
     서면 사람이 고른 것은 장면인데 화면의 절반이 그 장면과 상관이 없다.
     링크트리도 바깥을 테마에서 뽑는다.

     값은 서버가 실어 보낸다 (groups/public.blade.php 의 --pg-outer ·
     Page::themeVars). 여기서 못 뽑는 까닭 — 색은 사람이 고르는 값이고,
     테마 클래스는 main 에 붙어 있어 body 에서는 닿지 않는다.
     기본값을 남겨 둔다: 값이 안 오면 지금까지의 회색으로 선다 */
  body[data-page="pagepublic"] { background: var(--pg-outer, var(--bg-subtle)); }

  /* ★ 둥근 카드가 아니라 **곧은 기둥**이다 (2026-09-09 — 링크트리가
     이 모양이다). 앞서는 모서리 28px 에 위아래 여백을 둔 카드였는데,
     장면 테마가 들어오자 폰 흉내가 아니라 **잘린 그림**으로 보였다.
     기둥은 화면 위끝에서 아래끝까지 곧게 선다 — 폰을 흉내 내는 것이
     아니라 좁게 보여 주는 것뿐이라는 말이 된다 */
  .il-pg--full {
    max-width: 440px; margin-inline: auto;
    min-height: 100vh;
    /* 그림자 위에 머리카락 한 줄. 바깥이 테마 색이 되면서(2026-09-10)
       어두운 테마에서는 검은 그림자가 검은 바탕에 묻혀, 기둥의 경계가
       통째로 사라졌다 — 한 줄은 글자색에서 뽑으므로 밝은 테마에서는
       어둡게, 어두운 테마에서는 밝게 선다 */
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--pg-text) 10%, transparent),
                var(--shadow-xl);
  }

  /* 오른쪽 아래 — 눈이 마지막에 닿는 자리다. 내용을 가리지 않는다 */
  .il-pgqr {
    display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
    position: fixed; right: var(--sp-6); bottom: var(--sp-6);
    padding: var(--sp-3);
    background: var(--bg-elevated);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
  }
  /* 찍히는 크기다. 화면에 대고 폰으로 읽으려면 이보다 작으면 잘 안 잡힌다 */
  .il-pgqr__code { display: block; width: 116px; background: var(--qr-bg); }
  .il-pgqr__code svg { display: block; width: 100%; height: auto; color: var(--ink); }
  .il-pgqr__cap { font-size: var(--fs-micro); color: var(--text-secondary); }
}

.il-pg__inner { max-width: 520px; margin-inline: auto; }

/* ── 맨 위 줄 (2026-09-10) ──────────────────────────────────────
   링크트리가 이 자리에 동그란 단추를 띄운다. 오른쪽 하나만 둔다 —
   왼쪽의 것은 그 서비스의 로고이고, 이 화면에 우리 로고는 박지 않는다
   (2026-09-01 에 맨 아래 INNOLINK 표시를 걷어낸 그 판단이다).

   ★ 줄에는 높이를 주지 않는다. 단추가 JS 로 켜지므로(공유는 읽기가
     아니다), 줄이 높이를 들면 JS 가 없는 자리에 빈 띠 한 줄이 남는다.
     자리를 차지하는 것은 단추 자신이다 (아래 margin-bottom) */
.il-pg__bar { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2); }

/* 색을 테마에서 뽑는다 — 글자색은 배경에서 정해지므로(Color::readableOn)
   밝은 바탕에서는 옅은 먹, 어두운 바탕에서는 옅은 흰빛이 된다.
   테마마다 단추를 따로 그리지 않아도 다섯 장면에 다 붙는다 */
.il-pg__share {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; margin-bottom: var(--sp-4);
  padding: 0; border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--pg-text) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--pg-text) 14%, transparent);
  color: var(--pg-text); cursor: pointer;
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  transition: background .15s ease, transform .12s ease;
}
/* 미리보기 · 목록 그림의 것은 그림이다 (pagepreview.js) — 누를 수 없으니
   손가락 모양도 뜨지 않는다. 생김새만 같다 */
.il-pg__share--flat { cursor: default; }
.il-pg__share:hover:not(.il-pg__share--flat) { background: color-mix(in srgb, var(--pg-text) 15%, transparent); }
.il-pg__share:active { transform: scale(.94); }
.il-pg__share:focus-visible { outline: 2px solid var(--pg-text); outline-offset: 2px; }

/* 복사했다는 말. 토스트를 띄우지 않는다 — 이 화면은 관리 도구가 아니라서
   app.js 를 안 읽는다 (bare 껍데기). 누른 자리 옆에서 한 번 말하고 사라진다.
   :empty 로 접는다: 빈 채로 서 있으면 안쪽 여백만큼 단추가 밀린다 */
.il-pg__said {
  margin-bottom: var(--sp-4); padding: 5px 10px;
  border-radius: var(--radius-full);
  font-size: var(--fs-caption); line-height: 1.2;
  color: var(--pg-text);
  background: color-mix(in srgb, var(--pg-text) 10%, transparent);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  opacity: 0; transition: opacity .2s ease;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.il-pg__said:empty { display: none; }
.il-pg__said.is-on { opacity: .92; }

/* 프로필 레이아웃 2종. 인포크 4 · 링크트리 5 를 둘로 줄였다 —
   나머지는 이 둘의 변주다 */
.il-pg__head { text-align: center; margin-bottom: var(--sp-8); }
/* 사진이 없으면 버튼색 바탕에 이름 첫 글자, 있으면 사진.
   background-size/position 을 미리 잡아 둔다 — 인라인으로는 이미지만 준다 */
/* 사진이 없으면 빈 동그라미다 (2026-09-08).
   제목의 첫 글자를 크게 그렸었는데, 그것이 `아직 안 넣었다` 가 아니라
   **그렇게 꾸민 것**으로 읽혔다 — 글자를 지우는 법을 찾게 된다.
   글자를 세우던 규칙(flex 가운데 · 글자 크기 · 글자색)도 같이 걷었다 */
.il-pg__avatar {
  width: 88px; height: 88px; border-radius: var(--radius-full);
  margin: 0 auto var(--sp-4);
  background: var(--pg-btn) center/cover no-repeat;
  overflow: hidden;
}
.il-pg__cover {
  height: 150px; border-radius: var(--radius-lg); margin-bottom: var(--sp-4);
  background: var(--pg-btn) center/cover no-repeat;
}
/* 사진이 없을 때만 옅게 둔다 — 빈 자리라는 뜻이다.
   사진이 들어온 자리를 옅게 하면 올린 사진이 바래 보인다 */
.il-pg__cover:not([style]) { opacity: .55; }
/* ── 꾸미기 화면에서만: 맨 위 그림이 누를 수 있는 것이 된다 (2026-09-08)
   모양과 사진을 고르는 자리가 왼쪽 편집 칸에서 폰 안으로 옮겨 왔다.
   pageedit.js 가 그려진 뒤에 이 클래스를 붙인다 — 공개 화면에는 안 붙는다.

   ★ 평소에는 아무 표시도 없다. 미리보기가 하는 일은 `공개 화면이 어떻게
     보이나` 를 말하는 것이라, 거기에 상시로 얹힌 손잡이는 그 답을
     흐린다. 손이 닿을 때만 뜬다 (hover · focus).

   ★ 점선이다. 실선 테두리는 커버 이미지의 **일부**로 읽힌다 —
     사진에 액자를 두른 줄 알고 지우는 법을 찾게 된다 */
.il-pg__top--edit { cursor: pointer; position: relative; }
.il-pg__top--edit::after {
  content: '';
  position: absolute; inset: -4px;
  border: 2px dashed var(--pg-text); border-radius: inherit;
  opacity: 0; transition: opacity var(--t-fast);
  pointer-events: none;
}
.il-pg__avatar.il-pg__top--edit::after { border-radius: var(--radius-full); }
.il-pg__top--edit:hover::after,
.il-pg__top--edit:focus-visible::after { opacity: .55; }
/* 브라우저 기본 테두리는 지운다 — 위 점선이 그 몫을 한다 */
.il-pg__top--edit:focus-visible { outline: none; }

/* ── 꾸미기 화면에서만: 제목 · 소개를 그 자리에서 고친다 (2026-09-08)
   블록 줄의 인라인 칸과 같은 손이다 — 글자처럼 보이다가 누르면 거기서 친다.
   pageedit.js 가 그려진 뒤에 contenteditable 과 이 클래스를 붙인다.

   ★ 연필은 **가짜 요소**(::after)다. 안에 <span> 을 넣으면 그것이 고칠 수
     있는 글자의 일부가 되어, 지우다 보면 아이콘까지 지워진다.
     mask 로 그려 currentColor 를 타게 한다 — 공개 화면은 색이 저마다라
     먹색으로 박아 두면 어두운 배경에서 안 보인다 */
/* 블록 줄의 연필과 **같은 획**이다 (pageedit.js 의 ICON_PEN).
   둘이 다르면 같은 일을 하는 표시가 화면 안에서 둘로 보인다 */
.il-pg__edit {
  cursor: text;
  --pen-mask: url("data:image/svg+xml,<svg xmlns='http%3A//www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M4 20h4l10-10a2.1 2.1 0 0 0-3-3L5 17z'/></svg>");
  --pen-w: .8em; --pen-gap: .25em;
  padding-left: calc(var(--pen-w) + var(--pen-gap));
}
/* ★ 연필의 무게를 왼쪽에서 받아 준다 (2026-09-08 4차). 글자는 가운데
   맞춤인데 연필이 줄 끝에 붙어 있어서, 가운데 맞춤이 **연필까지 넣어** 재고
   글자가 그만큼 왼쪽으로 밀렸다. 미리보기는 `공개 화면이 어떻게 보이나` 를
   말하는 자리라, 글자는 고치는 표시와 상관없이 정가운데여야 한다.

   왼쪽 안여백을 연필 폭만큼 준다 — 가운데 맞춤이 그 절반을 되돌려 준다.
   폭을 변수로 묶어 둔 까닭: 둘 중 하나만 고치면 다시 어긋난다.
   SNS 줄은 빈 그림자로 같은 일을 하는데(그쪽은 flex 라 안여백이 안 먹는다),
   여기는 글자 줄이라 안여백이 맞는 손이다 */
.il-pg__edit::after {
  content: ''; display: inline-block;
  width: var(--pen-w); height: var(--pen-w); margin-left: var(--pen-gap);
  vertical-align: baseline;
  background: currentColor; opacity: .45;
  -webkit-mask: var(--pen-mask) center/contain no-repeat;
  mask: var(--pen-mask) center/contain no-repeat;
}
/* ★ 커서만 깜빡인다 — 바탕도 밑줄도 링도 없다 (2026-09-08).
   블록 줄의 인라인 칸이 2026-08-26 13차에 먼저 온 자리다 (.il-be__inp).

   둘 다 꺼야 한다. `글자 칸은 무엇으로 누르든 항상 :focus-visible 에
   걸린다` — 키보드로 치는 곳이라 브라우저가 그렇게 정해 둔다. :focus 만
   끄면 전역 링(components.css)이 그대로 떠서, 여기에 상자가 **둘** 겹쳐
   보였다 (내가 그린 테두리 + 그 링).

   여기서 포커스를 말하는 것은 캐럿이다 — 깜빡이는 막대가 있어 상자 없이도
   어디에 치고 있는지 보인다. 단추·토글의 링은 그대로 둔다: 그쪽은 캐럿이
   없어 링을 끄면 정말로 어디에 있는지 사라진다 */
.il-pg__edit:focus,
.il-pg__edit:focus-visible { outline: none; box-shadow: none; }
.il-pg__edit:focus::after { opacity: 0; }   /* 고치는 중에는 연필이 비켜 준다 */

/* 소개가 비면 그리지 않는 것이 원래 규칙이다 (pagepreview.js) —
   고치는 동안에만 자리를 세운다. 넣을 곳이 없으면 처음 넣을 수가 없다 */
.il-pg__bio.is-empty::before {
  content: '소개 한 줄'; opacity: .45;
}

/* 제목도 같다 (2026-09-15). 공개 화면은 제목이 비면 **주소**를 대신
   그리는데(pagepreview.js), 만들기 화면에서 그 주소는 서버가 방금 뽑아
   준 임의 여덟 글자다 — 사람이 정한 적 없는 글자가 큰 제목으로 서 있었다.
   비워 두되 자리는 세운다: 넣을 곳이 없으면 처음 넣을 수가 없다 */
.il-pg__title.is-empty::before {
  content: '이름'; opacity: .35;
}


.il-pg__title {
  font-size: var(--fs-title); font-weight: var(--fw-title);
  letter-spacing: var(--ls-title); line-height: var(--lh-tight);
}
.il-pg__bio {
  margin-top: var(--sp-2); font-size: var(--fs-body); line-height: var(--lh-body);
  opacity: .82;
}
/* ★ 아이콘을 키웠다 (2026-08-26 27차 · 22 → 26px → 28차 30px).
   프로필 사진 88px · 제목 24px 사이에서 18px 짜리가 부스러기처럼 보였다.
   여기 아이콘은 **누르는 것**이라 손가락이 닿을 만해야 한다 —
   둘레 여백까지 더하면 40px 이 되어 터치 최소 크기(44px)에 가깝다.
   pagepreview.js 의 snsIcon() 이 24px 로 그리고, 여기서 한 번 더 못 박는다 —
   그려 주는 곳이 바뀌어도 크기가 흔들리지 않게 */
.il-pg__sns { display: flex; justify-content: center; gap: var(--sp-5); margin-top: var(--sp-4); }
.il-pg__sns a {
  color: inherit; opacity: .85;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;
}
.il-pg__sns a:hover { opacity: 1; }
.il-pg__sns svg { width: 30px; height: 30px; }

/* ── 꾸미기 화면에서만: SNS 줄을 폰 안에서 고친다 (2026-09-08) ──────
   pageedit.js 가 그려진 뒤에 붙인다 — 공개 화면에는 안 붙는다.

   ★ 아무것도 안 넣었을 때만 다섯을 세운다(.is-empty). 하나라도 넣으면
     넣은 것만 남고 끝에 연필이 붙는다 — 안 넣은 것까지 폰에 세워 두면
     미리보기가 공개 화면과 달라진다.
   ★ 빈 줄은 흐리다. 아직 그 자리에 없는 것들이라, 넣은 것과 같은 진하기로
     서 있으면 이미 붙은 줄로 읽힌다 */
/* 사이가 좁다 (2026-09-08 2차). 아이콘 칸이 이미 44px 이라 그 안에
   여백이 들어 있는데(그림은 30px), gap 을 12 로 두니 둘을 더해 한 뼘이
   됐다 — 다섯이 늘어선 빈 줄에서 특히 흩어져 보였다 */
.il-pg__sns--edit {
  gap: var(--sp-2); flex-wrap: wrap;
  /* 더하기의 폭과, 그것을 왼쪽으로 당기는 값 (2026-09-08 3차).
     한 곳에 묶어 둔다 — 아래 그림자가 이 둘로 제 폭을 계산한다.
     따로 적어 두면 하나만 고쳤을 때 아이콘이 한쪽으로 밀린다 */
  --plus-w: 28px; --plus-pull: 6px;
}
.il-pg__snsadd {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  border: 0; background: none; color: inherit; cursor: pointer;
}

/* ★ 넣은 것과 안 넣은 것이 **한눈에 갈려야** 한다 (2026-09-08 2차).
   흐리게만 두었더니 아이콘 다섯이 나란히 서서, 어느 것이 이미 붙어 있고
   어느 것이 아직 없는지 구분이 안 됐다 — 넣은 것 하나 없는 그룹 링크가
   다섯을 다 넣은 것처럼 보였다.
   안 넣은 것은 ① 더 흐리고 ② 점선 동그라미를 두르고 ③ + 를 단다.
   셋을 겹치는 까닭 — 색만으로 가르면 테마에 따라 그 차이가 사라진다 */
.il-pg__snsadd--off { opacity: .45; }
.il-pg__snsadd--off::before {
  content: ''; position: absolute; inset: 1px;
  border: 1.5px dashed currentColor; border-radius: var(--radius-full);
  opacity: .5;
}
.il-pg__snsadd--off:hover, .il-pg__snsadd--off:focus-visible { opacity: .9; }
/* 넣어 둔 것 — 공개 화면에 뜨는 그 진하기 그대로다 */
.il-pg__snsadd--on { opacity: .85; }
.il-pg__snsadd--on:hover, .il-pg__snsadd--on:focus-visible { opacity: 1; }

/* 넣는 것이라는 표시. 아이콘 오른쪽 위에 작게 얹는다.
   ★ 배경을 currentColor 로 두지 않는다 — 글자색을 transparent 로 만들면
     currentColor 도 그 값이 되어 **배지가 통째로 사라진다** (한 번 그랬다).
     칠은 글자색(--pg-text), 글자는 배경색(--pg-bg)으로 못 박는다 */
/* 동그라미 안의 + — 넣어 둔 아이콘 옆에 붙어 `채널 더하기` 를 말한다.
   연필이었는데(2026-09-08 1차) 그것이 하는 일은 고치기가 아니라 더 넣기
   하나다 — 고치는 것은 그 아이콘을 직접 누른다. 연필은 다른 말이었다.
   아이콘보다 작고 흐리다: 이 줄의 주인공은 넣어 둔 아이콘들이다.

   ★ 연필의 무게를 왼쪽에서 받아 준다 (2026-09-08 4차). 줄 안에 그냥 세우면
     가운데 맞춤이 **연필까지 넣어** 재서 아이콘들이 그만큼 왼쪽으로 밀린다.
     미리보기는 `공개 화면이 어떻게 보이나` 를 말하는 자리라, 아이콘은 고치는
     표시와 상관없이 정가운데여야 한다.
     같은 폭의 빈 그림자를 왼쪽에 세워 저울을 맞춘다 — 연필을 띄워
     (absolute) 놓는 길도 있지만, 그러면 폰이 좁아졌을 때 아이콘 위로
     올라탄다. 그림자는 줄과 같이 접힌다 */
/* 그림자의 폭은 `더하기 폭 − 당긴 만큼` 이다. 그래야 왼쪽에 남는 자리와
   오른쪽에 서는 것의 무게가 같아진다 (당긴 만큼은 오른쪽에서 빠졌다) */
.il-pg__sns--edit.has-pen::before {
  content: ''; flex: none; width: calc(var(--plus-w) - var(--plus-pull));
}
.il-pg__snspen {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--plus-w); height: 44px; padding: 0;
  /* 아이콘 쪽으로 조금 당긴다 — 줄 전체의 gap 은 아이콘끼리의 간격이라
     그것을 줄이면 다섯이 늘어선 빈 줄까지 같이 좁아진다 */
  margin-left: calc(var(--plus-pull) * -1);
  border: 0; background: none; color: inherit; cursor: pointer; opacity: .45;
}
.il-pg__snspen:hover, .il-pg__snspen:focus-visible { opacity: .9; }
/* 22px — 옆 SNS 아이콘(30px)보다는 작다. 이 줄의 주인공은 넣어 둔 것들이다 */
.il-pg__snspen svg { width: 22px; height: 22px; }

.il-pg__snsplus {
  position: absolute; top: 2px; right: 2px;
  display: flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: var(--radius-full);
  background: var(--pg-text); color: var(--pg-bg);
  font-size: 12px; line-height: 1; font-weight: 700;
}

/* 채널 고르는 판의 한 줄 (2026-09-08) — 아이콘 · 이름 · 넣음 표시.
   줄 전체가 눌린다: 아이콘만 누르게 두면 표적이 44px 도 안 된다 */
.il-pe__pick {
  display: flex; align-items: center; gap: var(--sp-3); width: 100%;
  padding: var(--sp-3); border: 0; border-radius: var(--radius-md);
  background: none; color: var(--ink); font: inherit; text-align: left;
  cursor: pointer;
}
.il-pe__pick:hover { background: var(--bg-subtle); }
.il-pe__pickicon { display: inline-flex; color: var(--text-secondary); }
.il-pe__pickicon svg { width: 22px; height: 22px; }
.il-pe__pickname { flex: 1 1 auto; font-weight: 600; }
/* `넣음` 표시를 걷어냈다 (2026-09-08 4차) — 이미 넣은 것은 이 판에
   아예 안 뜬다. 이 판이 하는 일은 더 넣기 하나다 */

/* 공유 판의 두 갈래 — 가로로 놓고 아이콘 밑에 이름을 적는다 (2026-09-08).
   둘뿐이라 세로로 쌓으면 판만 길어지고 `읽고 나서 고르기` 가 된다.
   나란히 놓으면 그림 둘을 한눈에 견준다.
   SNS 채널 판(.il-pe__pick)은 그대로 세로다 — 거기는 다섯이고, 다섯을
   가로로 늘어놓으면 이름이 아이콘 밑에서 줄바꿈된다 */
.il-pe__tiles { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.il-pe__tile {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
  /* 판을 280px 로 좁히면서 안여백도 같이 줄인다 (2026-09-08) —
     그대로 두면 두 칸이 글자 폭까지 밀려 `그룹 링크 열기` 가 두 줄이 된다 */
  padding: var(--sp-4) var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: none; color: var(--ink); font: inherit; text-align: center;
  text-decoration: none; cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.il-pe__tile:hover { border-color: var(--ink); background: var(--bg-subtle); }
.il-pe__tileicon { display: inline-flex; color: var(--text-secondary); }
.il-pe__tile:hover .il-pe__tileicon { color: var(--ink); }
.il-pe__tilename { font-size: var(--fs-caption); font-weight: 600; }

/* ★ 소제목 블록을 걷어냈다 (2026-09-01). 이 클래스는 `아직 블록이 없습니다`
   한 줄에만 남는다 — 묶음이 제목을 들게 되면서 제목만 있고 누를 수 없는
   줄을 따로 세울 이유가 없어졌다 (pagepreview.js §블록) */
.il-pg__heading {
  margin: var(--sp-8) 0 var(--sp-3); text-align: center;
  font-size: var(--fs-caption); font-weight: 700;
  letter-spacing: var(--ls-micro); opacity: .7;
}
.il-pg__heading:first-child { margin-top: 0; }

/* 링크 블록 3스타일.
   인포크의 네 번째(배경)를 뺐다 — 카드와의 차이를 미리보기 없이 구분할 수 없다 */
.il-pg__link {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-3); padding: var(--sp-4);
  background: var(--pg-btn); color: var(--pg-btn-text);
  border-radius: var(--pg-radius); text-decoration: none;
  transition: transform var(--t-fast);
}
.il-pg__link:hover { transform: translateY(-1px); }
.il-pg__link--simple { justify-content: center; text-align: center; }

/* ★ `카드` 를 걷어냈다 (2026-09-01). 그림을 폭 전체에 140px 로 깔고 그
   아래 제목을 두는 모양이었는데, 그룹 링크는 세로로 쌓는 화면이라 카드가
   둘만 되어도 화면이 그림으로 가득 차고 어느 것이 무엇인지 글자가 안 읽혔다.
   썸네일과 하는 일도 같았다 — 둘 다 `그림 + 제목` 이고 크기만 달랐다.
   규칙은 남긴다: 지난 데이터에 style='card' 가 남아 있어도 깨지지 않는다 */
.il-pg__link--card {
  flex-direction: column; align-items: stretch; gap: var(--sp-3);
  padding: 0; overflow: hidden;
}
.il-pg__link--card .il-pg__thumb { width: 100%; height: 140px; border-radius: 0; }
.il-pg__link--card .il-pg__ltext { padding: 0 var(--sp-4) var(--sp-4); }
.il-pg__thumb {
  flex: none; width: 44px; height: 44px; border-radius: 8px;
  background-color: var(--pg-bg);
  background-size: cover; background-position: center;
}
/* 아직 그림이 없는 자리. 흐리게 둬서 "여기 그림이 들어간다" 로 읽히게 한다 */
.il-pg__thumb.is-empty { opacity: .35; }
/* ★ 썸네일도 제목은 버튼 가운데다 (2026-08-26 15차).
   그림이 왼쪽에 서면 남은 폭의 왼쪽 끝에 글자가 붙는데, 그러면 짧은 제목일수록
   버튼이 한쪽으로 쏠려 보인다. 오른쪽에 그림만큼(44px + 사이 여백) 자리를
   비워 글자 상자를 좌우 대칭으로 만든다 — 그래야 `가운데` 가 버튼의 가운데다.
   (인포크·링크트리 둘 다 이 모양이다) */
.il-pg__link--thumb .il-pg__ltext {
  margin-right: calc(44px + var(--sp-3));
  text-align: center;
}
.il-pg__ltext { flex: 1 1 auto; min-width: 0; }
.il-pg__ltitle { display: block; font-size: var(--fs-body); font-weight: 700; }

/* ── 묶음 상자 (2026-09-01) ────────────────────────────────────────
   앞서 `모음` 은 격자였다 (.il-pg__grid — 2열 · 3열). 걷어냈다.
   폭 380 짜리 폰에서 2열이면 버튼 하나가 170px 인데, 거기에 그림과 제목이
   같이 들어가면 제목이 두 글자에서 잘렸다. 3열은 더했다.

   지금 묶음이 하는 일은 나란히 세우는 것이 아니라 **한 덩어리로 묶어
   보이는 것**이다. 자식은 밖에 선 블록과 똑같이 한 줄에 하나씩 서고,
   달라지는 것은 그 둘레에 상자가 하나 생긴다는 것뿐이다.

   상자는 배경으로 말하지 않는다 — 테마 배경색이 무엇이든(먹부터 흰 종이까지)
   읽히려면 색이 아니라 **선과 여백**이어야 한다. currentColor 를 옅게 깔면
   밝은 배경에서는 회색 선, 어두운 배경에서는 흰 선이 저절로 된다.

   마지막 자식의 아래 여백을 지운다 — 블록마다 붙어 있는 margin-bottom 이
   상자 안쪽 여백과 겹쳐 아래만 두 배로 벌어진다 */
.il-pg__box {
  margin-bottom: var(--sp-3);
  padding: var(--sp-3);
  border: 1px solid color-mix(in srgb, currentColor 22%, transparent);
  border-radius: calc(var(--pg-radius) + 6px);
}
/* 제목은 상자 안 맨 위다. 상자 밖에 두면 상자와 제목 사이가 벌어져
   `이 상자의 이름` 이 아니라 `그 위에 놓인 딴 줄` 로 읽힌다 */
.il-pg__boxtitle {
  margin: 2px 0 var(--sp-3); text-align: center;
  font-size: var(--fs-caption); font-weight: 700;
  letter-spacing: var(--ls-micro); opacity: .75;
}
.il-pg__boxinner > :last-child { margin-bottom: 0; }

/* 닫힌 그룹 링크 — 만료 안내가 아니다. 그룹 링크에는 만료가 없다 (erd.md §9-8) */
.il-pg__closed { margin: var(--sp-18) auto; max-width: 320px; text-align: center; }
.il-pg__closed h1 { font-size: var(--fs-heading); font-weight: var(--fw-heading); }
.il-pg__closed p { margin-top: var(--sp-2); font-size: var(--fs-body); opacity: .75; }


/* ── 테마 4종 (2026-09-09) ────────────────────────────────────────────
   ★ 2026-09-01 에 프리셋 6종을 걷어낸 자리다. 그때 왜 걷었나 —
     프리셋이 하는 일이 **배경색 · 버튼색 두 값을 한 번에 넣는 것뿐**이었고,
     그 두 칸이 바로 밑에 열려 있어서 고르고 나면 카드 이름과 실제 색이
     곧 어긋났다. `먹` 이 눌린 채 배경이 하늘색인 상태가 정상으로 여겨졌다.
     이름이 값을 못 따라가는 순간 프리셋은 안내가 아니라 거짓말이다.

   ★ 이번에는 테마가 **색이 아니라 결**이다. 그래서 어긋날 수가 없다:
       테마   바탕의 움직임 · 글꼴 · 버튼의 생김새 · 사진 테두리
       색     그 결이 입는 팔레트 (배경 · 버튼 두 칸은 그대로 열려 있다)
     테마를 고르면 그 결에 어울리는 색 한 벌이 두 칸에 **실제로 들어간다** —
     카드만 눌린 채 값이 그대로인 상태가 없다. 그 뒤에 색을 바꾸면 결은
     그대로 두고 팔레트만 갈린다. 아래 색들이 전부 --pg-bg · --pg-btn 에서
     color-mix 로 나오는 까닭이 그것이다 — 무슨 색을 고르든 결이 따라간다.

   ★ 풍차 · 하늘은 **잠긴 테마**다 (2026-09-09 3차). 위 규칙의 예외다 —
     팔레트가 아니라 그림 전체가 테마라, 색은 CSS 가 쥐고 색 칸은 잠긴다.
     어긋남은 없다: 카드가 광고하는 그림과 실제가 같은 CSS 다.

   ★ 움직임은 `prefers-reduced-motion` 에서 멈춘다. 어지럼증 · 전정기관
     질환이 있는 사람에게 큰 면적이 계속 흐르는 화면은 실제로 증상을 만든다
     (WCAG 2.3.3). 멈춰도 그림은 그대로 남는다 — 정지 화면이 곧 그 테마다.
   =================================================================== */

/* 글꼴은 테마가 갈아 끼운다. 기본값은 본문 글꼴이라, 테마가 없으면
   지금까지와 똑같다 */
.il-pg { font-family: var(--pg-font, var(--font-sans)); }

/* 바탕에 무엇을 깔든 글은 그 위에 선다 */
.il-pg { position: relative; isolation: isolate; overflow: hidden; }
.il-pg__inner { position: relative; z-index: 1; }

/* ── 오로라 ──────────────────────────────────────────────────────
   덩어리 넷이 서로 다른 주기로 흐른다. 하나짜리 그러데이션을 통째로
   움직이면 `배경이 밀린다` 로 보이는데, 주기가 어긋난 덩어리 여럿은
   경계가 서로를 지워 **색이 번지는 것**으로 보인다.

   transform 만 움직인다 — 그러데이션의 좌표(background-position)를
   흔들면 프레임마다 큰 면적을 다시 칠해 폰에서 눈에 띄게 버벅인다 */
.il-pg--aurora {
  --au-1: color-mix(in oklab, var(--pg-bg) 30%, #FF3D8B);
  --au-2: color-mix(in oklab, var(--pg-bg) 30%, #6A5BFF);
  --au-3: color-mix(in oklab, var(--pg-bg) 35%, #21D4E4);
  --au-4: color-mix(in oklab, var(--pg-bg) 40%, #FFB347);
}
.il-pg--aurora::before,
.il-pg--aurora::after {
  content: ''; position: absolute; inset: -30%; z-index: 0;
  pointer-events: none;
  /* 가장자리를 60% 에서 투명으로 끝낸다 — 원이 원으로 보이면 덩어리가
     아니라 공이 된다 */
  background-repeat: no-repeat;
  will-change: transform;
}
.il-pg--aurora::before {
  background-image:
    radial-gradient(38% 32% at 22% 26%, var(--au-1) 0%, transparent 62%),
    radial-gradient(42% 36% at 78% 16%, var(--au-2) 0%, transparent 60%);
  animation: il-au-a 26s ease-in-out infinite;
}
.il-pg--aurora::after {
  background-image:
    radial-gradient(44% 34% at 16% 78%, var(--au-3) 0%, transparent 62%),
    radial-gradient(40% 34% at 84% 88%, var(--au-4) 0%, transparent 60%);
  animation: il-au-b 34s ease-in-out infinite;
}
@keyframes il-au-a {
  0%, 100% { transform: translate3d(-3%, -2%, 0) scale(1);    }
  50%      { transform: translate3d( 5%,  4%, 0) scale(1.18); }
}
@keyframes il-au-b {
  0%, 100% { transform: translate3d( 3%,  2%, 0) scale(1.12); }
  50%      { transform: translate3d(-5%, -3%, 0) scale(1);    }
}

/* 버튼은 유리다 — 색을 덮지 않고 뒤의 오로라를 비친다.
   backdrop-filter 를 못 읽는 브라우저에서도 반투명 바탕과 테두리가
   남아서 버튼으로 읽힌다 (그때는 그냥 흐린 유리가 아닐 뿐이다) */
.il-pg--aurora .il-pg__link {
  background: color-mix(in srgb, var(--pg-btn) 16%, transparent);
  color: var(--pg-text);
  border: 1px solid color-mix(in srgb, var(--pg-btn) 30%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
          backdrop-filter: blur(14px) saturate(1.3);
  box-shadow: 0 8px 24px -12px rgb(0 0 0 / .45);
}
.il-pg--aurora .il-pg__link:hover {
  background: color-mix(in srgb, var(--pg-btn) 26%, transparent);
}
.il-pg--aurora .il-pg__box {
  border-color: color-mix(in srgb, var(--pg-btn) 26%, transparent);
  background: color-mix(in srgb, var(--pg-bg) 30%, transparent);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
/* 사진 둘레의 옅은 빛. 오로라 위에 사진이 그냥 얹히면 오려 붙인 것처럼
   보인다 — 빛 한 겹이 그 경계를 눅인다 */
.il-pg--aurora .il-pg__avatar {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pg-btn) 22%, transparent),
              0 12px 40px -12px rgb(0 0 0 / .6);
}
/* 제목은 굵고 좁게. Pretendard 는 가변 글꼴이라 900 까지 있다 —
   파일을 더 받지 않고 얻는 유일한 표정이다 */
.il-pg--aurora .il-pg__title {
  font-weight: 860; letter-spacing: -0.03em;
  text-shadow: 0 2px 20px rgb(0 0 0 / .35);
}
.il-pg--aurora .il-pg__bio { text-shadow: 0 1px 12px rgb(0 0 0 / .3); }

/* ── 풍차 (잠긴 테마) ────────────────────────────────────────────────
   ★ 배경이 팔레트가 아니라 **하나의 장면**이다 (2026-09-09 3차).
     달빛 호수의 밤 — 별이 깜빡이는 하늘, 달, 언덕과 나무의 실루엣,
     물가의 달 그림자, 그리고 창에 불이 켜진 풍차. 날개가 천천히 돈다.
     장면의 색들은 서로 맞물려 있어 배경 하나만 갈면 그림이 통째로
     깨진다 — 색은 CSS 가 쥐고, 편집 화면은 색 칸을 잠근다
     (Page::THEMES 의 locked · pageedit.js syncColorLock).

   그리는 법 — 파일을 받지 않는다. 하늘·물·달은 그러데이션, 풍차와
   언덕은 손으로 적은 SVG 실루엣이다 (data: URI). 전부 요소의 배경
   레이어로 겹치고, **돌아야 하는 날개만** ::after 로 뗐다 — 배경
   레이어는 저 혼자 회전할 수 없다.

   ★ 날개와 몸통은 같은 자(--mw)로 잰다. 몸통의 축(hub)이 SVG 좌표
     (100, 84)/300 에 있으므로, 날개 중심을 calc 로 그 점에 맞춘다 —
     둘을 따로 재면 화면 폭이 바뀔 때 날개가 몸통에서 떨어진다 */
.il-pg--mill {
  --mw: min(44%, 200px);             /* 풍차 몸통의 폭. 날개도 이 자를 쓴다 */
  --mr: 18px;                        /* 오른쪽 끝에서 몸통까지 */
  --wat: 64px;                       /* 물의 높이 */
  --mb: calc(var(--wat) - 10px);     /* 몸통 발 — 물가에 살짝 잠긴다 */

  /* 달빛 그림책의 결 — 명조가 어울린다 (고운바탕 0.51MB,
     이 테마를 쓰는 화면만 받는다. 시스템 명조가 뒤를 받친다) */
  --pg-font: 'Gowun Batang', 'Nanum Myeongjo', 'AppleMyungjo', 'Batang',
             ui-serif, Georgia, serif;
  color: #E9EFF9;

  /* 겹 순서(위→아래): 몸통 · 앞 언덕 · 먼 산 · 물결 · 물 · 구름 두 점 ·
     물안개 · 하늘. 값싼 겹 몇 장이 원근을 만든다 — 먼 산은 앞 언덕보다
     한 단 밝다: 밤에는 먼 것이 하늘빛에 섞인다.
     ★ 달을 걷어냈다 (2026-09-09). 빈 프로필 자리가 이 테마에서는 노란
       동그라미(--pg-btn)라, 달까지 있으면 하늘에 달이 둘이었다.
       물 위의 달 그림자도 같이 나갔다 — 달 없는 달 그림자는 거짓말이다 */
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 300'%3E%3Cpath d='M74 92 Q100 60 126 92 Z' fill='%23111A2E'/%3E%3Cpath d='M78 92 L60 292 L140 292 L122 92 Z' fill='%23111A2E'/%3E%3Ccircle cx='100' cy='84' r='7' fill='%23111A2E'/%3E%3Crect x='92' y='122' width='16' height='22' rx='2' fill='%23F5C86B'/%3E%3Crect x='99' y='122' width='2' height='22' fill='%23111A2E'/%3E%3Crect x='92' y='132' width='16' height='2' fill='%23111A2E'/%3E%3Crect x='86' y='212' width='28' height='32' rx='2' fill='%23F5C86B'/%3E%3Crect x='99' y='212' width='3' height='32' fill='%23111A2E'/%3E%3Crect x='86' y='227' width='28' height='3' fill='%23111A2E'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 430 90' preserveAspectRatio='none'%3E%3Cpath d='M0 62 Q50 44 105 56 Q160 66 215 54 Q270 44 325 58 Q380 68 430 52 L430 90 L0 90 Z' fill='%230E1626'/%3E%3Cellipse cx='84' cy='50' rx='20' ry='13' fill='%230E1626'/%3E%3Crect x='82' y='52' width='4' height='14' fill='%230E1626'/%3E%3Cellipse cx='330' cy='52' rx='16' ry='11' fill='%230E1626'/%3E%3Crect x='328' y='54' width='4' height='12' fill='%230E1626'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 430 80' preserveAspectRatio='none'%3E%3Cpath d='M0 70 L60 34 L120 62 L180 26 L240 58 L300 38 L360 64 L430 30 L430 80 L0 80 Z' fill='%23182642'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 430 40'%3E%3Cg stroke='%239FB8DC' stroke-width='2' stroke-linecap='round' opacity='.18'%3E%3Cpath d='M44 10 H92'/%3E%3Cpath d='M182 18 H262'/%3E%3Cpath d='M330 26 H392'/%3E%3Cpath d='M120 30 H162'/%3E%3Cpath d='M18 24 H48'/%3E%3C/g%3E%3C/svg%3E"),
    linear-gradient(180deg, #17233E 0%, #0C1426 100%),
    radial-gradient(ellipse 180px 44px at 72% 54px, rgba(255, 255, 255, .07), transparent 70%),
    radial-gradient(ellipse 220px 54px at 12% 26px, rgba(255, 255, 255, .05), transparent 70%),
    radial-gradient(120% 130px at 50% calc(100% - var(--wat) - 24px),
      rgba(96, 126, 178, .3), transparent 72%),
    linear-gradient(180deg, #10182E 0%, #1D2B47 48%, #2E4266 82%, #3A5077 100%);
  background-size:
    var(--mw) auto,
    100% 46px,
    100% 56px,
    100% 40px,
    100% var(--wat),
    auto,
    auto,
    auto,
    auto;
  background-position:
    right var(--mr) bottom var(--mb),
    left 0 bottom var(--wat),
    left 0 bottom calc(var(--wat) + 18px),
    left 0 bottom 8px,
    left 0 bottom 0,
    0 0,
    0 0,
    0 0,
    0 0;
  background-repeat: no-repeat;
}
/* 별 — 제자리에서 깜빡이기만 한다. 흐르면 배경이 주인공이 된다 */
.il-pg--mill::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(circle 1.5px at 12% 6%, rgba(255, 255, 255, .9) 50%, transparent 60%),
    radial-gradient(circle 1.2px at 34% 12%, rgba(255, 255, 255, .7) 50%, transparent 60%),
    radial-gradient(circle 1.7px at 55% 5%, rgba(255, 255, 255, .95) 50%, transparent 60%),
    radial-gradient(circle 1.2px at 72% 14%, rgba(255, 255, 255, .75) 50%, transparent 60%),
    radial-gradient(circle 1.5px at 88% 8%, rgba(255, 255, 255, .85) 50%, transparent 60%),
    radial-gradient(circle 1.2px at 44% 22%, rgba(255, 255, 255, .65) 50%, transparent 60%),
    radial-gradient(circle 1.4px at 80% 26%, rgba(255, 255, 255, .7) 50%, transparent 60%);
  animation: il-mill-twinkle 7s ease-in-out infinite alternate;
}
@keyframes il-mill-twinkle { from { opacity: .4; } to { opacity: 1; } }
/* 날개 — 핀터레스트의 그 풍차처럼 천천히 돈다. 26초 한 바퀴:
   바람개비가 아니라 풍차다, 빨리 돌면 장난감이 된다.
   ★ 돛은 선 하나가 아니라 **살 + 격자 판**이다 (2026-09-09 4차 —
     선만 그었더니 앙상하다는 말을 들었다). SVG 안에서 돛 하나를
     %3Cuse%3E 로 네 번 돌려 세운다 — 손으로 네 벌 그리면 하나만
     고치는 날이 온다 */
.il-pg--mill::after {
  content: ''; position: absolute; z-index: 0; pointer-events: none;
  width: calc(var(--mw) * 1.35); aspect-ratio: 1;
  right: calc(var(--mr) - var(--mw) * 0.175);
  bottom: calc(var(--mb) + var(--mw) * 0.405);
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cdefs%3E%3Cg id='s' stroke='%23111A2E' fill='none'%3E%3Cpath d='M100 100 L100 14' stroke-width='7' stroke-linecap='round'/%3E%3Crect x='104' y='17' width='21' height='70' stroke-width='5'/%3E%3Cpath d='M104 31 H125 M104 45 H125 M104 59 H125 M104 73 H125' stroke-width='2.5'/%3E%3C/g%3E%3C/defs%3E%3Cuse href='%23s'/%3E%3Cuse href='%23s' transform='rotate(90 100 100)'/%3E%3Cuse href='%23s' transform='rotate(180 100 100)'/%3E%3Cuse href='%23s' transform='rotate(270 100 100)'/%3E%3Ccircle cx='100' cy='100' r='9' fill='%23111A2E'/%3E%3C/svg%3E") center/contain no-repeat;
  will-change: transform;
  animation: il-mill-turn 26s linear infinite;
}
@keyframes il-mill-turn { to { transform: rotate(1turn); } }

/* 유성 — 별똥별 테마를 걷으면서 (2026-09-09) 그 테마의 유성만 이 밤하늘로
   옮겨 심었다. 한 바퀴(16초)에 세 번, 저마다 다른 자리에서 떨어진다 —
   꺼진 채(opacity 0) 다음 출발점으로 옮겨 가므로 옮기는 길은 안 보인다.
   한 번에 1초만 빛난다: 늘 떨어지고 있으면 유성이 아니다.

   ★ 자리는 __inner 의 의사요소다. .il-pg--mill 의 둘(::before 별밭 ·
     ::after 날개)이 차 있어서 세 번째 겹을 콘텐츠 상자에서 빌린다 —
     z-index -1 이라 글과 버튼 밑, 장면 위에 선다. 유성은 하늘 꼭대기를
     긋고 풍차는 바닥 오른쪽이라 겹칠 자리도 없다 */
.il-pg--mill .il-pg__inner::before {
  content: ''; position: absolute; z-index: -1; pointer-events: none;
  width: 190px; height: 2px; border-radius: 2px;
  right: 0; top: 10px;
  background: linear-gradient(90deg, rgba(233, 241, 249, 0), rgba(233, 241, 249, .95));
  filter: drop-shadow(0 0 6px rgba(213, 225, 255, .7));
  opacity: 0;
  will-change: transform, opacity;
  animation: il-mill-meteor 16s linear infinite;
}
@keyframes il-mill-meteor {
  /* 첫째 — 오른쪽 위 */
  0%     { opacity: 0; transform: translate3d(120px, -40px, 0) rotate(-38deg); }
  1.7%   { opacity: 1; }
  6.5%   { opacity: 0; transform: translate3d(-190px, 202px, 0) rotate(-38deg); }
  /* 둘째 — 가운데, 조금 낮게 */
  33%    { opacity: 0; transform: translate3d(-50px, 20px, 0) rotate(-38deg); }
  34.7%  { opacity: 1; }
  39.5%  { opacity: 0; transform: translate3d(-360px, 262px, 0) rotate(-38deg); }
  /* 셋째 — 왼쪽 멀리, 짧게 */
  66%    { opacity: 0; transform: translate3d(-160px, -10px, 0) rotate(-38deg); }
  67.7%  { opacity: 1; }
  71.5%  { opacity: 0; transform: translate3d(-420px, 192px, 0) rotate(-38deg); }
  100%   { opacity: 0; transform: translate3d(-420px, 192px, 0) rotate(-38deg); }
}

/* 버튼은 밤보다 한 단 밝은 유리다 — 거의 불투명해야 장면이 글자를
   씻어 내지 않는다 (먹 테마에서 배운 것) */
.il-pg--mill .il-pg__link {
  background: rgba(11, 18, 34, .82);
  color: #E9EFF9;
  border: 1px solid rgba(255, 255, 255, .15);
}
.il-pg--mill .il-pg__link:hover { background: rgba(22, 32, 54, .9); border-color: rgba(255, 255, 255, .32); }
.il-pg--mill .il-pg__box { border-color: rgba(255, 255, 255, .13); }
.il-pg--mill .il-pg__avatar {
  box-shadow: 0 0 0 1.5px rgba(233, 241, 249, .25),
              0 14px 44px -14px rgba(0, 0, 0, .7);
}
/* 명조는 굵기를 흉내 내면 맺음이 뭉개진다 — 크기로 세운다 (같은 px 에서
   고딕보다 작아 보이므로 한 단 키운다) */
.il-pg--mill .il-pg__title { font-weight: 400; letter-spacing: -0.01em; text-shadow: 0 2px 14px rgba(0, 0, 0, .5); }
.il-pg--mill .il-pg__ltitle { font-weight: 400; font-size: var(--fs-lead); }
.il-pg--mill .il-pg__bio { font-size: var(--fs-lead); opacity: .92; }
.il-pg--mill .il-pg__thumb { background-color: rgba(233, 241, 249, .1); }

/* ── 하늘 (잠긴 테마) ───────────────────────────────────────────────
   맑은 낮 — 다섯 중 유일한 밝은 장면이다. 구름 사이로 새 떼가
   왼쪽에서 오른쪽으로 천천히 날아간다 (한 번 건너는 데 48초).
   새 떼는 SVG 한 장이고 layer 통째로 흐른다 — 날갯짓까지 흉내 내면
   장면이 아니라 게임이 된다. 글꼴은 기본(Pretendard)이다:
   낮 하늘에는 표정을 더할 것이 없다 */
.il-pg--sky {
  color: #21374B;
  /* ★ 구름 오브제를 걷어냈다 (2026-09-09 7차). SVG 뭉게구름을 두 판
     그렸는데(곡선 → 원의 합집합) 어느 쪽도 장면에 붙지 않았다 —
     그러데이션 하늘은 결이 부드러운데 윤곽이 딱 떨어지는 흰 덩이가
     얹히니 스티커처럼 떴다. 구름은 ::before 의 안개 덩이(radial)만
     남긴다: 윤곽이 없어야 이 하늘의 결에 섞인다.
     이 테마의 오브제는 새 떼 하나다 — 둘이면 서로를 가린다 */
  background-image:
    linear-gradient(180deg, #9FCBEF 0%, #ABD6F2 45%, #C2E4EE 75%, #CFEEE6 100%);
}
/* 구름 — 가장자리에 큰 덩이들. 가운데는 새와 글의 자리라 비워 둔다 */
.il-pg--sky::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    radial-gradient(ellipse 170px 60px at 88% 10%, rgba(255, 255, 255, .8), transparent 70%),
    radial-gradient(ellipse 210px 70px at 4% 26%, rgba(255, 255, 255, .55), transparent 70%),
    radial-gradient(ellipse 100px 38px at 55% 6%, rgba(255, 255, 255, .6), transparent 70%),
    radial-gradient(ellipse 230px 85px at 12% 92%, rgba(255, 255, 255, .85), transparent 70%),
    radial-gradient(ellipse 190px 70px at 94% 80%, rgba(255, 255, 255, .7), transparent 70%);
}
/* ★ 새 떼도 걷어냈다 (2026-09-09 8차 — 구름 오브제에 이어).
   이 하늘은 오브제 없이 결로만 선다: 그러데이션과 안개 덩이.
   다섯 테마 중 유일하게 아무것도 움직이지 않는 밝은 장면이다 —
   `맑고 조용한 낮` 이 이 테마가 하는 말이다 */

/* 버튼은 구름이다 — 흰 바탕에 하늘빛 그림자 */
.il-pg--sky .il-pg__link {
  background: rgba(255, 255, 255, .8);
  color: #23374A;
  border: 1px solid rgba(46, 64, 83, .14);
  box-shadow: 0 6px 18px -10px rgba(46, 64, 83, .35);
}
.il-pg--sky .il-pg__link:hover { background: rgba(255, 255, 255, .95); }
.il-pg--sky .il-pg__box { border-color: rgba(46, 64, 83, .18); }
.il-pg--sky .il-pg__avatar {
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .9),
              0 10px 30px -10px rgba(46, 64, 83, .4);
}
.il-pg--sky .il-pg__thumb { background-color: rgba(46, 64, 83, .08); }

/* ── 움직임을 끈다 ───────────────────────────────────────────────
   어지럼증 · 전정기관 질환이 있는 사람에게 큰 면적이 계속 흐르는 화면은
   실제로 증상을 만든다 (WCAG 2.3.3). 멈춘 그림이 곧 그 테마다.

   ★ 목록의 그림에서도 끈다 (.il-pgc__scale). 거기서는 그룹 링크가 한
     화면에 여럿 서는데, 저마다 다른 주기로 흐르면 목록이 통째로 어지럽다 */
@media (prefers-reduced-motion: reduce) {
  .il-pg--aurora::before, .il-pg--aurora::after,
  .il-pg--mill::before, .il-pg--mill::after,
  .il-pg--mill .il-pg__inner::before { animation: none; }
}
.il-pgc__scale .il-pg--aurora::before,
.il-pgc__scale .il-pg--aurora::after,
.il-pgc__scale .il-pg--mill::before,
.il-pgc__scale .il-pg--mill::after,
.il-pgc__scale .il-pg--mill .il-pg__inner::before { animation: none; }

/* ── 블록별 클릭 (page-detail.html) ──────────────────────────────
   project-detail.html 의 링크별 성과와 같은 모양이다.
   막대는 표 안에서 비중을 말한다 — 숫자만 있으면 1위와 2위의 차이가
   얼마나 큰지 읽는 데 시간이 걸린다 */
/* ★ display 를 주지 않아 **여태 안 보이던 막대**다 (2026-08-26 38차).
   <span> 은 인라인이라 height 가 먹지 않는다 — 칸이 통째로 비어 있었다.

   39차에 비중 칸 안으로 들어왔다. 숫자 아래에 그 숫자만큼 찬다 —
   길이를 재는 바탕(track)이 함께 있어야 `얼마나 찼나` 가 읽힌다.
   바탕 없이 막대만 두면 46.6% 인지 80% 인지 눈으로는 알 수 없다 */
/* ★ 숫자를 막대 **왼쪽에 붙여** 한 줄로 둔다 (2026-08-26 40차).
   39차에는 숫자를 막대 위에 얹었는데, 막대가 칸을 가로지르는 동안 숫자는
   그 한가운데에 떠 있어 **둘이 여전히 남처럼 보였다** —
   가운데에 놓인 글자는 어느 쪽 끝과도 줄이 안 맞는다.

   한 줄에 나란히 두면 눈이 `46.6%` 를 읽고 곧바로 오른쪽 막대로 넘어간다.
   숫자 칸을 고정 폭으로 잡아 자릿수가 달라도 막대의 시작점이 흔들리지 않는다 —
   막대는 시작점이 같아야 길이를 견줄 수 있다 */
.il-bp__share {
  display: flex; align-items: center; gap: var(--sp-3);
}
.il-bp__share .il-num { flex: none; width: 52px; text-align: right; }
.il-bp__track {
  flex: 1 1 auto; height: 6px;
  border-radius: var(--radius-full); background: var(--bg-subtle);
  overflow: hidden;
}
.il-bp__bar {
  display: block; height: 100%; min-width: 2px;
  border-radius: var(--radius-full); background: var(--chart-1);
}

/* ── 블록별 클릭 표 (2026-08-26 38차) ────────────────────────────────
   칸마다 가운데 · 세로 가운데. 블록 그림 높이가 종류마다 달라
   위에 붙여 두면 숫자가 그림 꼭대기에 매달린 것처럼 보인다 */
.il-bp-table th,
.il-bp-table td { text-align: center; vertical-align: middle; }
.il-bp-table .il-pgd__mini { margin-inline: auto; }



/* ── 좁은 화면 ───────────────────────────────────────────────────
   1100px 아래에서는 미리보기를 편집 위로 올린다. 옆에 두면 둘 다 좁아져
   어느 쪽도 못 쓴다. 올라가면 sticky 도 푼다 — 화면에 붙어 따라오는
   폰 껍데기는 방해만 된다 */
@media (max-width: 1100px) {
  .il-pe { grid-template-columns: minmax(0, 1fr); gap: var(--sp-8); }
  .il-pe__preview { position: static; order: -1; }
  .il-phone__screen { height: 420px; }
}
@media (max-width: 640px) {
  .il-pe__row { grid-template-columns: minmax(0, 1fr); }
  .il-lc__stat--two { gap: var(--sp-4); }
}


/* ── 그룹 링크 만들기 (2026-08-26 2차 — pages.html 재작성) ────────────
   1차에서는 links.html 의 붙여 넣기 한 줄을 그대로 가져왔는데 걷어냈다.

   왜 링크와 같으면 안 되나
     링크는 목적지 URL 을 붙여 넣는 순간 **완성된다** — 단축 주소도 QR 도
     자동으로 붙고, 그 자리에서 복사해 나가면 끝이다.
     그룹 링크는 주소만 정하면 **빈 그룹 링크가 하나 생길 뿐**이다. 열어 봐야
     아무것도 없다. 그래서 만드는 자리에서 최소한의 모양은 정하고 가야 한다.

   무엇을 묻나 — 주소 · 제목 · 시작 테마 셋
     링크트리 온보딩(핸들 → 테마 → 프로필)에서 셋만 남겼다.
     인포크의 블록 폼처럼 라벨 위 · 칸 아래 · 구분선 · 하단 큰 버튼으로 쌓는다.

   미리보기를 따로 두지 않는다
     테마 카드 자체가 미리보기다 (링크트리 `Select a theme` 가 그렇다).
     제목을 치면 카드 세 장의 글자가 같이 바뀌므로, 고르는 것과 보는 것이
     한 자리에서 끝난다 — 폼 위에 폰을 하나 더 세울 이유가 없다. */

.il-pgnew { max-width: 640px; margin-inline: auto; }

/* 만들기 전용 판 (page-new.html). 목록·모달보다 넓게 잡는다 —
   이 화면에서 가장 중요한 것이 "어떻게 생길지 보는 것" 이라
   테마 카드에 자리를 준다. 셸(240px)을 끼고도 남는 폭이다 */
.il-pgnew--full { max-width: 720px; }

/* 카드가 곧 이 화면이다. 여백을 한 단 넉넉히 준다 */
.il-pgnew__card { padding: var(--sp-8); }

/* 카드가 커진 만큼 미리보기도 커진다 */
.il-pgnew--full .il-tpl__mock { height: 210px; gap: 8px; }
.il-pgnew--full .il-tpl__dot { width: 38px; height: 38px; }
.il-pgnew--full .il-tpl__btn { height: 18px; }
.il-pgnew--full .il-tpl__title { font-size: var(--fs-caption); }

.il-pgnew__hero { text-align: center; padding: var(--sp-12) 0 var(--sp-8); }
.il-pgnew__title {
  font-size: clamp(24px, 3.4vw, 34px); font-weight: 800;
  letter-spacing: -.03em; line-height: 1.25; margin-bottom: var(--sp-3);
}
.il-pgnew__sub { font-size: var(--fs-lead); color: var(--text-secondary); }

/* 인포크 블록 폼의 뼈대 — 라벨 위, 칸 아래, 사이에 구분선 */
.il-pgnew__row { padding: var(--sp-5) 0; border-bottom: 1px solid var(--border); }
.il-pgnew__row:first-child { padding-top: 0; }
.il-pgnew__row:last-of-type { border-bottom: 0; }
.il-pgnew__lab {
  margin-bottom: var(--sp-2);
  font-size: var(--fs-body); font-weight: 700; color: var(--ink);
}
.il-pgnew__req { color: var(--danger); margin-left: 2px; }
.il-pgnew__foot { padding-top: var(--sp-5); border-top: 1px solid var(--border); }

/* ── 주소 칸 ──────────────────────────────────────────────────────
   접두를 인풋 안에 박아 둔다 (링크트리 `Choose a username` · 인포크 둘 다).
   ilk.kr/p/ 를 사람이 적게 하면 반드시 한 번은 빼먹는다.

   테두리로만 상태를 말한다 — 통과하면 성공색, 막히면 위험색.
   글자 칸에 포커스 링을 두지 않는 것은 이 저장소의 규칙이다 */
.il-handle {
  display: flex; align-items: center;
  background: var(--bg-elevated);
  border: 1.5px solid var(--border-strong); border-radius: var(--radius-md);
  padding: 0 var(--sp-3) 0 var(--sp-4);
  transition: border-color var(--t-fast);
}
.il-handle:focus-within { border-color: var(--ink); }
/* ★ 상태를 `data-state` 로도 받는다 (2026-09-15).
   pageedit.js 의 paintHandle 은 `[data-pe-wrap].dataset.state` 에 적는데
   여기는 `.is-ok` · `.is-bad` 만 보고 있었다 — **테두리가 한 번도 안
   바뀌었다.** 통과·막힘을 말하려고 둔 색인데 말한 적이 없다.
   목업 시절 클래스 쪽도 남겨 둔다 (와이어프레임 page-new.html 이 쓴다) */
.il-handle.is-ok,  .il-handle[data-state="ok"]  { border-color: var(--success); }
.il-handle.is-bad, .il-handle[data-state="bad"] { border-color: var(--danger); }
.il-handle[data-state="ok"]  .il-handle__mark { color: var(--success); }
.il-handle[data-state="bad"] .il-handle__mark { color: var(--danger); }

/* ── 주소 밑 한 줄 + 중복 확인 (2026-09-15) ──────────────────────────
   버튼을 주소 칸 **옆이 아니라 밑**에 둔다. 옆에 두면 칸이 버튼만큼
   좁아지는데, 그 칸은 접두(innolink.conbus.co.kr/p/)까지 안에 들고
   있어서 정작 **사람이 치는 여덟 글자가 안 보인다.**
   버튼이 만들어 내는 글자가 바로 이 줄이라, 나란히 서는 편이 읽는
   순서와도 맞는다.

   판정 한 줄은 자리를 늘 잡아 둔다 (아래 .il-pe__note) — 글자가
   나타났다 사라지면 다음 칸이 위아래로 흔들린다 */
.il-pe__handlefoot {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  margin-top: var(--sp-2);
}
.il-pe__handlefoot > .il-pe__note { flex: 1 1 auto; margin-top: 0; min-width: 0; }
/* ★ 테두리를 준다 (2026-09-15 · 사용자 지적).
   il-btn-ghost 는 바탕도 테두리도 없다 — 그 자리가 **누를 수 있는 것**
   으로 안 읽혔다. 옆의 판정 한 줄과 같은 크기의 회색 글자라 그냥 문장의
   일부처럼 보였다. 눌러 봐야 아는 단추는 없는 단추와 같다.
   주된 동작이 아니므로(등록이 주다) 테두리만 두고 바탕은 비워 둔다 */
.il-pe__check {
  flex: none; white-space: nowrap;
  border: 1px solid var(--border-strong);
  color: var(--text-secondary);
}
.il-pe__check:hover:not([disabled]) { border-color: var(--ink); color: var(--ink); }
.il-pe__check[disabled] { opacity: .45; }
.il-handle__pre {
  flex: none; font-family: var(--font-mono); font-size: var(--fs-body);
  color: var(--text-muted); user-select: none;
}
.il-handle__input {
  flex: 1 1 auto; min-width: 0; height: 46px;
  border: 0; background: transparent; outline: none;
  font-family: var(--font-mono); font-size: var(--fs-body); color: var(--ink);
}
.il-handle__input:focus-visible { box-shadow: none; }
.il-handle__mark { flex: none; width: 20px; height: 20px; color: var(--success); }
.il-handle.is-bad .il-handle__mark { color: var(--danger); }

/* 주소 아래 한 줄. 자리를 늘 잡아 둔다 —
   글자가 나타났다 사라지면 아래 칸이 위아래로 흔들린다 */
.il-pgnew__note {
  display: block; margin-top: var(--sp-2); min-height: 18px;
  font-size: var(--fs-micro); color: var(--text-muted);
}
.il-pgnew__note.is-ok  { color: var(--success); font-weight: 700; }
.il-pgnew__note.is-bad { color: var(--danger);  font-weight: 700; }

/* ── 시작 테마 카드 ───────────────────────────────────────────────
   링크트리 `Select a theme` 의 템플릿 카드를 3장으로 줄였다.
   각 카드가 그 테마로 그려진 작은 그룹 링크라 고르는 것이 곧 미리보기다 */
.il-tpls { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
.il-tpl {
  padding: 0; cursor: pointer; text-align: center;
  border: 2px solid transparent; border-radius: var(--radius-lg);
  background: transparent;
}
.il-tpl__mock {
  /* 기본값을 여기 두고 JS 가 인라인으로 덮어쓴다 (.il-pg 와 같은 방식) */
  --tpl-bg:   var(--bg-subtle);
  --tpl-btn:  var(--border-strong);
  --tpl-text: var(--ink);

  display: flex; flex-direction: column; align-items: center;
  gap: 6px; height: 168px; padding: var(--sp-4) var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--tpl-bg); color: var(--tpl-text);
  overflow: hidden;
}
.il-tpl__dot {
  width: 30px; height: 30px; border-radius: var(--radius-full);
  background: var(--tpl-btn); flex: none;
}
/* 제목을 실제로 그린다 — 폼에 친 글자가 여기 들어와야 미리보기가 된다 */
.il-tpl__title {
  font-size: var(--fs-micro); font-weight: 700; line-height: 1.3;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.il-tpl__btn {
  width: 100%; height: 15px; border-radius: 5px;
  background: var(--tpl-btn); flex: none;
}
.il-tpl[aria-pressed="true"] { border-color: var(--ink); }
.il-tpl:focus-visible { box-shadow: var(--focus-ring); outline: none; }

/* 라벨 줄에 i 아이콘이 함께 선다. .il-infotip__btn 이 이미 margin-left:4px 를
   갖고 있어 여기서 gap 을 주면 아이콘만 글자에서 멀어진다
   (.il-field__head 와 같은 이유 — components.css) */
.il-pgnew__lab { display: flex; align-items: center; }

/* ── 목록 쪽 ─────────────────────────────────────────────────────
   만들기가 헤더 버튼으로 올라가면서 검색만 남았다 */
.il-pglist__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); margin-bottom: var(--sp-4);
}
.il-pglist__head h2 {
  font-size: var(--fs-heading); font-weight: var(--fw-heading);
  letter-spacing: var(--ls-heading);
}
/* 제목이 머리말로 올라간 뒤 이 줄에 남는 것은 검색뿐이다 (22차) */
.il-pglist__head--end { justify-content: flex-end; }
.il-pglist__search { width: 240px; max-width: 45vw; }

@media (max-width: 640px) {
  .il-tpls { gap: var(--sp-2); }
  .il-tpl__mock { height: 140px; }
  .il-pgnew--full .il-tpl__mock { height: 150px; }
  .il-pgnew--full .il-tpl__dot { width: 28px; height: 28px; }
  .il-pgnew__card { padding: var(--sp-5); }
  .il-pgnew__hero { padding: var(--sp-8) 0 var(--sp-6); }
}


/* ═══ 사진 자르기 (2026-08-26 16차 · cropper.js) ══════════════════════
   인포크·링크트리 둘 다 사진을 올리면 자를 자리를 먼저 묻는다.
   묻지 않으면 가로 사진이 동그란 자리에서 얼굴 반쪽만 남는다 */
.il-crop {
  display: flex; align-items: center; justify-content: center;
  min-height: 360px; padding: var(--sp-3);
  background: var(--ink); border-radius: var(--radius-md);
  overflow: hidden;
}
/* 그려진 사진의 **실제 사각형**. 잘라 낼 상자의 좌표계다 —
   무대를 기준으로 재면 사진 옆의 빈 곳까지 자를 수 있게 된다 */
.il-crop__fit { position: relative; line-height: 0; }
.il-crop__img { display: block; width: 100%; height: 100%; }

/* 남는 자리. 바깥은 box-shadow 한 줄로 덮는다 —
   네 조각을 따로 그리면 상자를 옮길 때마다 넷을 다시 계산해야 한다 */
.il-crop__box {
  position: absolute; box-sizing: border-box;
  border: 1px solid var(--bg-elevated);
  box-shadow: 0 0 0 9999px var(--overlay-strong);
  cursor: move; touch-action: none;
}
/* 링에 잉크를 겹칠 수 없다 — box-shadow 는 이미 바깥을 덮는 데 쓰고 있다.
   어두운 무대 위라 흰 테두리로 말한다 (--focus-ring-on-ink 와 같은 결) */
.il-crop__box:focus-visible { outline: 2px solid var(--on-ink); outline-offset: 3px; }

/* 모서리 손잡이. 네 곳만 둔다 — 비율이 잠겨 있어 변을 잡아도 하는 일이 같다 */
.il-crop__h {
  position: absolute; width: 14px; height: 14px;
  background: var(--bg-elevated); border: 1px solid var(--ink);
  border-radius: 2px;
}
.il-crop__h--nw { left: -7px; top: -7px;    cursor: nwse-resize; }
.il-crop__h--ne { right: -7px; top: -7px;   cursor: nesw-resize; }
.il-crop__h--sw { left: -7px; bottom: -7px; cursor: nesw-resize; }
.il-crop__h--se { right: -7px; bottom: -7px; cursor: nwse-resize; }

/* ── 맨 위 사진 (디자인 탭) ─────────────────────────────────────────
   동그란 사진과 커버는 잘리는 비율이 달라서 미리보기 모양도 다르다 */
.il-pe__img { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.il-pe__imgprev {
  flex: none; width: 64px; height: 64px;
  background: var(--bg-subtle) center/cover no-repeat;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-micro); color: var(--text-placeholder);
}
.il-pe__imgprev--cover { width: 128px; height: 64px; border-radius: var(--radius-md); }
.il-pe__imgacts { display: flex; gap: var(--sp-2); flex-wrap: wrap; }


/* ═══ 블록별 클릭 표의 첫 칸 (2026-08-26 36차) ════════════════════════
   블록을 **생긴 대로** 보여 준다. `제목 / 주소` 두 줄로 적어 두었더니
   어느 블록인지 안 떠올랐다 — 사람이 그룹 링크에서 보는 것은 그 버튼의 생김새다.

   공개 화면와 같은 마크업을 쓰고(pagepreview.js IL.blockMini) 크기만 줄인다.
   테마 색은 인라인 변수로 들어온다 — 기본값을 여기 둬서 그것이 빠져도
   선언이 통째로 무효가 되지 않게 한다 (.il-pg 와 같은 방식) */
.il-pgd__mini {
  --pg-bg:       transparent;
  --pg-text:     var(--ink);
  --pg-btn:      var(--bg-elevated);
  --pg-btn-text: var(--ink);
  --pg-radius:   10px;

  /* ★ 그룹 링크 바탕색을 깔지 않는다 (2026-08-26 37차).
     테마가 어두운 그룹 링크면 표 안에 검은 네모가 줄줄이 서서, 표가 아니라
     **어두운 띠**가 됐다. 여기서 보여 줄 것은 그룹 링크 배경이 아니라
     `그 버튼이 어떻게 생겼나` 하나다 — 버튼 색은 그대로 살아 있다 */
  flex: none; display: block; width: 190px;
  /* 그림이다 — 안의 <a> 가 눌리거나 Tab 에 걸리면 안 된다
     (linkBlock 이 tabindex="-1" 을 이미 붙이지만 두 겹으로 막는다) */
  pointer-events: none;
}
/* 동영상은 16:9 라 그대로 두면 칸이 높아진다 — 한 단 줄인다 */
.il-pgd__mini--video { width: 150px; }

/* SNS 는 아이콘 하나다. 버튼 모양을 흉내 내면 그룹 링크에 없는 것이 표에 생긴다 */
.il-pgd__sns {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  color: var(--ink); font-size: var(--fs-caption); font-weight: 600;
}
.il-pgd__sns svg { width: 22px; height: 22px; }
.il-pgd__mini .il-pg__link { margin-bottom: 0; padding: var(--sp-2); gap: var(--sp-2); }
.il-pgd__mini .il-pg__ltitle { font-size: var(--fs-caption); }
.il-pgd__mini .il-pg__thumb { width: 26px; height: 26px; border-radius: 5px; }
.il-pgd__mini .il-pg__link--card { padding: 0; }
.il-pgd__mini .il-pg__link--card .il-pg__thumb { width: 100%; height: 62px; border-radius: 0; }
.il-pgd__mini .il-pg__link--card .il-pg__ltext { padding: 0 var(--sp-2) var(--sp-2); }
.il-pgd__mini .il-pg__link--thumb .il-pg__ltext { margin-right: calc(26px + var(--sp-2)); }

.il-bp__dest {
  display: block; font-size: var(--fs-caption); color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}


/* 분석 기준 스위치 — 탭 줄의 오른쪽 끝에 선다 (2026-08-26 41차).
   탭과 같은 줄에 두는 이유: 이 스위치가 **그 탭들 전부**에 걸리기 때문이다.
   탭 안에 넣으면 그 탭에만 걸리는 것으로 읽힌다 */
.il-dimswitch {
  margin-left: auto; display: flex; align-items: center; gap: var(--sp-2);
  padding-right: var(--sp-4);
}


/* 그룹 링크 통계의 QR 그림 (2026-08-26 43차).
   link-detail.html 은 data-qrbuild 가 그리지만 여기서는 pagedetail.js 가
   IL.qrSvg 로 직접 넣는다 — 그 쪽은 편집까지 딸린 위젯이고 여기는 보기만 한다.
   흰 바탕을 유지한다: QR 은 어두운 데 올리면 못 읽는다 */
/* QR 그림 — 누르면 무엇으로 받을지 묻는 메뉴가 뜬다.

   ★ button 이다 (2026-09-08). 이름이 붙은 `내려받기` 줄을 걷어내면서 —
     같은 일을 하는 자리가 둘이었다 — 이 그림이 **받는 유일한 길**이 됐다.
     div 로 두면 탭으로 닿지도 엔터로 눌리지도 않는다 (ui.js 의
     [data-qr-dl] 은 click 갈고리 하나뿐이다).
     그래서 브라우저가 단추에 주는 기본 모양만 지운다 — 생김새는 그대로다.

   ★ 이름이 il-pgd__(그룹 링크 통계)였다. 링크 통계도 같은 모양이 되면서
     한 화면에 매인 이름이 거짓이 됐다 — 블록 이름으로 옮긴다 (2026-09-08).

   ★ 테두리와 흰 바탕을 두는 까닭 — 카드 배경과 QR 의 여백이 같은 색이라
     그것 없이는 그림의 끝이 어디인지 안 보인다. 누를 수 있는 것이면
     그 크기가 보여야 한다 */
.il-qrblock__btn {
  display: block; margin: 0; font: inherit; color: inherit; text-align: inherit;
  appearance: none;
  width: 132px; height: 132px; padding: var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--qr-bg); cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
/* 키보드로 닿은 것이 보여야 한다 — 이제 여기가 유일한 길이다 */
.il-qrblock__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.il-qrblock__btn:hover { border-color: var(--ink); box-shadow: var(--shadow-sm); }
.il-qrblock__btn svg { display: block; width: 100%; height: auto; color: var(--ink); }


/* ★ 관리자 그룹 링크 목록의 작은 미리보기를 걷어냈다 (2026-09-01).
   줄마다 진짜 그룹 링크를 0.53배로 축소해 그렸던 자리다 (200×240).

   그 그림은 **내 것을 보는 화면**(pages.html)에서 값을 한다 — 대여섯 장 중
   `어떤 그룹 링크였더라` 를 그림으로 답하는 자리이기 때문이다.
   여기는 전사를 표로 훑는 화면이고, 표에서 하는 일은 찾고 · 걸러 내고 ·
   대조하는 것이다. 그림은 그 어느 것도 돕지 않으면서 줄 높이를 세 배로
   만들고 한 화면에 들어오는 줄 수를 줄였다.
   그 자리에는 번호가 들어갔다 (pagetable.js) */

/* ══════════════════════════════════════════════════════════════════
   § DB 구조 도식 (erd.html)  ·  2026-08-26

   Mermaid 가 SVG 를 그린다. 색은 erd.js 가 토큰 값을 읽어 넘기므로
   여기서는 **자리와 테두리만** 잡는다 — 색을 두 곳에서 정하면 갈라진다.
   ────────────────────────────────────────────────────────────────── */

/* 범례. 선이 두 가지인 것이 요점이라 그림보다 먼저 읽혀야 한다 */
.il-erd__legend {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6);
  margin: 0 0 var(--sp-5); padding: var(--sp-4) var(--sp-5);
  list-style: none;
  font-size: var(--fs-caption); color: var(--text-secondary);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.il-erd__legend li { display: flex; align-items: center; gap: var(--sp-2); }
/* --fk 는 기본값 그대로다. 그래도 이름을 적어 둔다 —
   마크업에만 있고 CSS 에 없는 이름은 `지우다 말았나` 를 묻게 만든다 (csstest) */
.il-erd__key,
.il-erd__key--fk { flex: none; width: 26px; height: 2px; background: var(--ink); }
.il-erd__key--soft { height: 0; border-top: 2px dashed var(--text-muted); }
.il-erd__key--pk   { width: auto; height: auto; background: none; }

/* 그림이 넓다. 화면에 맞춰 줄이지 않고 **가로로 스크롤**한다 —
   스물다섯 개짜리 표 그림을 폭에 맞춰 줄이면 글자가 안 읽힌다 */
.il-erd__wrap {
  overflow-x: auto;
  padding: var(--sp-5);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
}
/* 그림이 그려지면 원문을 감춘다 (erd.js 가 hidden 을 단다).
   준비가 끝나기 전에는 원문이 보이고, 그려지면 자리를 내준다 */
/* ★ 그리는 동안 display:none 으로 감추지 않는다 (2026-08-26).
   Mermaid 는 이 자리에 SVG 를 넣고 **getBBox 로 재서** 크기를 정한다.
   숨겨 두면 모든 치수가 0 으로 나와 40×40 짜리 빈 그림이 된다 — 실제로 그랬다.
   그려지기 전에는 빈 div 라 어차피 자리를 안 차지한다 */
.il-erd__dia svg { display: block; height: auto; }

/* 라이브러리가 없을 때 남는 원문. 그 자체로 읽히는 글이라 감추지 않는다 */
.il-erd__src {
  margin: 0; padding: var(--sp-4);
  max-height: 460px; overflow: auto;
  font-family: var(--font-mono); font-size: var(--fs-micro); line-height: 1.6;
  color: var(--text-secondary);
  background: var(--bg-subtle); border-radius: var(--radius-md);
  white-space: pre;
}

/* ══════════════════════════════════════════════════════════════════
   § 설계도 — 붙어 다니는 목차 · 부 머리 (blueprint.html)  ·  2026-08-26

   여덟 절짜리 긴 글을 **네 부로 묶고**, 목차를 화면 위에 붙여 둔다.
   내용은 그대로다 — 계층과 위치 표시만 더한다.
   ────────────────────────────────────────────────────────────────── */

.il-bpnav {
  position: sticky; top: 0; z-index: 20;
  margin: 0 0 var(--sp-10);
  padding: var(--sp-3) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}
/* 좁은 화면에서는 가로로 민다. 접으면 세 줄이 되어 본문을 밀어낸다 */
.il-bpnav__inner {
  display: flex; align-items: center; gap: var(--sp-2);
  overflow-x: auto;
  white-space: nowrap;
  font-size: var(--fs-caption);
}
/* 부 이름은 누를 것이 아니다 — 색과 크기로 링크와 갈라 둔다 */
.il-bpnav__part {
  flex: none;
  padding-left: var(--sp-2);
  font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: var(--ls-micro); text-transform: uppercase;
  color: var(--text-muted);
}
.il-bpnav__part:first-child { padding-left: 0; }
.il-bpnav a {
  flex: none;
  padding: 4px var(--sp-2);
  color: var(--text-secondary); text-decoration: none;
  border-radius: var(--radius-sm);
}
.il-bpnav a:hover { background: var(--bg-subtle); color: var(--ink); }
/* 읽고 있는 절. 밑줄이 아니라 배경으로 표시한다 —
   가로로 미는 줄에서는 밑줄이 스크롤바와 겹쳐 보인다 */
.il-bpnav a.is-on {
  background: var(--ink); color: var(--bg-elevated); font-weight: 700;
}

/* 부 머리. 제목 위에 얹는 눈썹이다 — 새 h 단계를 만들지 않는다.
   단계를 하나 더 두면 h2 가 h3 로 밀리고 그 아래가 전부 따라 밀린다 */
.il-bppart {
  margin: var(--sp-12) 0 var(--sp-2);
  padding-top: var(--sp-5);
  border-top: 2px solid var(--ink);
  font-size: var(--fs-caption); font-weight: 700; color: var(--text-secondary);
}
.il-bppart span {
  display: inline-block; margin-right: var(--sp-2);
  padding: 2px var(--sp-2);
  font-size: var(--fs-micro); letter-spacing: var(--ls-micro);
  color: var(--bg-elevated); background: var(--ink);
  border-radius: var(--radius-sm);
}

/* 절이 답하는 물음. 제목만 보고도 건너뛸 수 있게 한 줄로 적는다 */
.il-bpq {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-caption); color: var(--text-muted);
}
.il-bpq strong { color: var(--text-secondary); font-weight: 620; }

/* 기능 30개를 손대는 정도 순서로 세운다 (78차).
   승계 → 개선 → 신규. 셋이 한 절 안에 있으므로 머리표가 계단처럼 읽혀야 한다 */
.il-bpsteps {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3);
  margin-bottom: var(--sp-8);
}
.il-bpstep {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--sp-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.il-bpstep__n {
  align-self: flex-start;
  padding: 2px var(--sp-2); margin-bottom: var(--sp-1);
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: var(--ls-micro);
  color: var(--bg-elevated); background: var(--ink);
  border-radius: var(--radius-sm);
}
@media (max-width: 720px) {
  .il-bpsteps { grid-template-columns: 1fr; }
}

/* 표 세 개의 머리. 갈래표를 제목 안에 넣어 어느 표를 보고 있는지가 늘 보이게 한다 */
.il-bph {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-2); padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.il-bph__tag {
  flex: none;
  padding: 3px var(--sp-3);
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: var(--ls-micro);
  color: var(--bg-elevated); background: var(--ink);
  border-radius: 999px;
}
