/* layer — 오너 대시보드/상세 보조 스타일 (Builder B, CONTRACT_V2 §6).
 *
 * @axe/ui 0.5.0 vendored CSS 에 없는 layer 고유 컴포넌트만 보강한다:
 *  - .layer-metric-grid / .layer-metric-card  (상단 KPI 카드 4 — 화면용 px)
 *  - .layer-status-light (관심도 신호등, HOT=danger pulse)
 *  - .layer-progress-mini (완독률 미니 막대 — .axe-progress 와 동형, 행 내 인라인)
 *  - .layer-spark (스파크라인 polyline 컨테이너)
 *  - .layer-heatmap (doc_detail 섹션 히트맵 세로 스택)
 *
 * 토큰: axe-ui.css(먼저 로드)가 :root 에 정의한 *실재* 토큰만 쓴다 — text 는
 * --text-primary/--text-secondary/--text-muted/--text-tertiary, 면은 --bg-base/
 * --bg-subtle/--bg-elevated, 보더는 --border-subtle/--border-default/--border-strong,
 * 포인트는 --accent(+--accent-soft/--accent-fg)/--danger(-soft)/--warning/--success.
 * ⚠ --fg/--fg-muted/--border(맨이름) 은 axe-ui 에 *없다* → light hex fallback 으로
 *   샌 채 다크에서 안 보였다(2026-06-20 수정). 새 규칙도 실재 토큰만 참조할 것.
 *
 * CSP: 오너 화면 CSP 는 style-src 'self' (unsafe-inline 없음) → 인라인 style=
 * 속성이 차단된다. 따라서 동적 폭(완독률·스파크·히트맵)은 템플릿이 data-* 로
 * 싣고 dashboard.js 가 CSSOM(element.style)으로 적용한다(JS-set 은 CSP 무관). */

/* ---- 상단 메트릭 스트립 -------------------------------------------------- */
/* KPI마다 별도 카드를 만들지 않고 하나의 상태 스트립 안에서 수치가 읽히게 한다. */

/* 칸막이는 카드의 border 가 아니라 grid gap 이 그린다 — auto-fit 이 몇 열로 접히든
 * 줄 끝에 붙는 유령 세로선이 생기지 않는다(320px 1열에서 실측). */
.layer-metric-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px;
  margin: 0 0 24px;
  border-block: 1px solid var(--border-subtle);
  background: var(--border-subtle);
}
.layer-metric-card {
  padding: 14px 18px;
  background: var(--bg-base);
  border: 0;
  border-radius: 0;
}
.layer-metric-card__label {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
  margin: 0 0 6px;
}
.layer-metric-card__value {
  font-size: 24px;
  font-weight: 650;
  line-height: 1.1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
/* 이 화면이 결국 보려는 수치 표시 — 카드 위 가로선으로 그리면 줄바꿈된 두 번째 줄에서
   윗줄에 붙은 선처럼 읽힌다. 라벨 앞 점은 어느 줄에 있든 자기 수치에 붙는다
   (목록의 관심도 신호등과 같은 어휘). */
.layer-metric-card--accent .layer-metric-card__label::before,
.layer-metric-card--hot .layer-metric-card__label::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 6px;
  border-radius: var(--radius-full, 9999px);
  vertical-align: 1px;
}
.layer-metric-card--accent .layer-metric-card__label::before {
  background: var(--workspace-blue, var(--accent));
}
.layer-metric-card--hot .layer-metric-card__label::before {
  background: var(--workspace-orange, var(--warning));
}
.layer-metric-card--hot .layer-metric-card__value {
  color: var(--text-primary);
}

/* ---- 관심도 신호등 ------------------------------------------------------- */
.layer-status-light {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  background: var(--border-strong);
  vertical-align: middle;
}
.layer-status-light--warm {
  background: var(--warning, #f59e0b);
}
.layer-status-light--hot {
  background: var(--danger, #dc2626);
  animation: layer-pulse 1.6s ease-in-out infinite;
}
@keyframes layer-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(220, 38, 38, 0.45);
  }
  50% {
    box-shadow: 0 0 0 5px rgba(220, 38, 38, 0);
  }
}

/* ---- 발송중 라이브 펄스 점 (Astryx StatusDot 독트린, D-layer-45) ----------
 * '라이브 상태 = 8px 점, 분류 = 배지'. .layer-status-light 계열을 승계하되
 * 발송 진행처럼 자동갱신 중인 상태에 opacity 펄스로 '살아 있음'을 표시한다.
 * role=img + aria-label 은 마크업이 담당. reduced-motion 시 애니메이션 정지. */
.layer-pulse-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full, 9999px);
  background: var(--accent);
  vertical-align: middle;
  animation: layer-pulse-opacity 2s ease-in-out infinite;
}
@keyframes layer-pulse-opacity {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}
@media (prefers-reduced-motion: reduce) {
  .layer-pulse-dot {
    animation: none;
  }
}

/* ---- 완독률 미니 막대 (행 내) ------------------------------------------- */
.layer-progress-mini {
  position: relative;
  display: inline-block;
  width: 64px;
  height: 6px;
  vertical-align: middle;
  background: var(--bg-subtle, #eef0f3);
  border-radius: 9999px;
  overflow: hidden;
}
.layer-progress-mini__fill {
  display: block;
  height: 100%;
  width: 0; /* JS 가 data-pct → style.width 적용 */
  background: var(--accent, #4338ca);
  border-radius: inherit;
}
.layer-progress-mini__fill--hot {
  background: var(--danger, #dc2626);
}
.layer-progress-mini__fill--warm {
  background: var(--warning, #f59e0b);
}
.layer-pct-label {
  margin-left: 6px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* ---- 스파크라인 --------------------------------------------------------- */
.layer-spark {
  display: inline-block;
  width: 84px;
  height: 24px;
  vertical-align: middle;
}
.layer-spark polyline {
  fill: none;
  stroke: var(--accent, #4338ca);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* ---- HOT 행 틴트 + 클릭 가능 행 ----------------------------------------- */
.layer-row-hot {
  background: var(--danger-soft, rgba(220, 38, 38, 0.06));
}
.layer-row-clickable {
  cursor: pointer;
}

/* ---- doc_detail 섹션 히트맵 --------------------------------------------- */
.layer-heatmap {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 12px 0;
}
.layer-heatmap__row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 1fr auto;
  align-items: center;
  gap: 12px;
}
.layer-heatmap__label {
  font-size: 13px;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.layer-heatmap__bar {
  position: relative;
  height: 8px;
  background: var(--bg-subtle, #eef0f3);
  border-radius: 9999px;
  overflow: hidden;
}
.layer-heatmap__fill {
  display: block;
  height: 100%;
  width: 0; /* JS 적용 */
  background: var(--accent, #4338ca);
  border-radius: inherit;
}
.layer-heatmap__val {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ---- 업로드/링크 폼 배치 ------------------------------------------------- */
.layer-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-5, 24px) var(--space-4, 16px);
  align-items: start;
}
.layer-section {
  margin: 0 0 28px;
}
.layer-section > h2 {
  margin: 0 0 12px;
}
.layer-muted {
  color: var(--text-muted);
}
.layer-mono {
  font-family: var(--font-mono, ui-monospace, monospace);
}
.layer-est {
  font-size: 11px;
  color: var(--text-tertiary);
}
.layer-inline-form {
  display: inline;
}

/* ---- 영구삭제(purge) disclosure — summary 디스클로저 마커 제거(버튼처럼 보이게) --- */
.layer-purge {
  display: inline;
}
.layer-purge > summary {
  list-style: none;
  cursor: pointer;
}
.layer-purge > summary::-webkit-details-marker {
  display: none;
}
.layer-purge__box {
  margin-top: 0.5rem;
}

/* ---- Layer 워크스페이스 보조 ------------------------------------------- */
/* 56px bar, 280px rails, disclosure와 중앙 geometry는 @axe/ui 0.19가 소유한다.
 * Layer는 화면별 중앙 폭과 실제 업무 문구만 보탠다. */
/* 중앙 폭 2단 — 어느 화면이 wide 인지는 여전히 템플릿이
 * `{% set workspace_width = "wide" %}` 로 고르지만(라우트 목록을 CSS 에 복제하지 않음),
 * wide 가 무엇인지는 @axe/ui 0.28.0 의 정본 modifier `.axe-workspace-shell--wide`
 * (캡 해제, 거터 유지)가 소유한다. 종전 서비스 로컬 76rem 재캡은 폐기 — 캡을 76rem 으로
 * 올려 두면 레일을 접어 얻은 280px 이 본문이 아니라 여백으로 간다. */
/* @axe/ui 0.19 갭 — layout.css 의 presence 규칙
 * `[data-shell=docs][data-has-sidebar=true][data-has-toc=false]`(0,5,0)이
 * workspace-shell 의 ≤1023.98px 1열 collapse(0,4,0)보다 세다. context 를 끈
 * route(편집기)에서 모바일에 280px 유령 레일이 남으므로 같은 계약을 더 높은
 * 특이성으로 다시 세운다. geometry 는 그대로 벤더 값(minmax(0,1fr))이다. */
@media (max-width: 1023.98px) {
  .axe-app-shell.axe-workspace-shell[data-shell="docs"][data-has-sidebar][data-has-toc]
    .axe-app-shell__main {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* context 를 끈 route(편집기) — 상단 바의 세 번째 칸도 함께 접는다. 0.19 의 바 그리드는
 * toc presence 를 보지 않으므로, 그대로 두면 ≥1440px 에서 아무것도 없는 280px 레일색
 * 블록이 바 오른쪽에 남는다(그 아래 열은 이미 비어 있다). */
.layer-shell-body[data-has-toc="false"] .axe-workspace-bar__right {
  display: none;
}
/* 접힌 상태는 제외한다 — 레일이 없는데 280px 첫 트랙을 잡으면 bar 왼쪽에 아무것도
 * 없는 레일색 칸이 남는다. 접힘 쪽 트랙 수는 코어가 이미 잡는다
 * (`[data-rail-collapsed] .axe-workspace-bar` → auto/1fr/auto). */
@media (min-width: 1024px) {
  .layer-shell-body[data-has-toc="false"]:not([data-rail-collapsed]) .axe-workspace-bar {
    grid-template-columns: var(--workspace-rail-w) minmax(0, 1fr);
  }
}
/* 터치 타깃 — 킷은 workspace 크롬(레일·라우트·컨텍스트·세션 링크)을 스스로
 * `(pointer: coarse)` 에서 44px 로 올리고 폼 컨트롤은 36px 밀도를 유지한다. 오너 화면은
 * 좁은 화면에서 폼이 주 작업이라 **서비스 로컬 재료만** 여기서 올린다 — 레일 링크는
 * 킷이 이미 소유하므로 이 목록에서 뺐다(같은 값을 두 곳에 적으면 킷이 값을 바꾸는 날
 * 소비자만 옛 값으로 남는다). */
@media (pointer: coarse), (max-width: 767.98px) {
  .layer-shell-body :is(
    .axe-input,
    .axe-btn,
    .layer-segment__item,
    .layer-upload__paste > summary,
    .layer-purge > summary,
    .layer-access-edit > summary,
    .layer-inline-details > summary
  ) {
    min-height: 44px;
  }
  /* 세그먼트·요약은 인라인이라 min-height 만으로는 글자가 위쪽에 붙는다. */
  .layer-shell-body :is(.layer-segment__item, .layer-upload__paste > summary) {
    display: inline-flex;
    align-items: center;
  }
  .layer-shell-body .layer-file-input::file-selector-button {
    min-height: 44px;
  }
  /* 네이티브 체크박스 — 라벨 행 전체가 타깃이지만 상자 자체도 손가락으로 짚을 수 있게. */
  .layer-shell-body .layer-check-row > input[type="checkbox"] {
    width: 20px;
    height: 20px;
  }
}
/* 좌측 레일 그룹 라벨은 **킷이 소유한다**. 종전 여기 있던 로컬 재정의(mono·xs·
 * uppercase·semibold)는 소비자가 킷 어휘의 시각을 다시 정하는 것이라 삭제했다 —
 * 디자인 결정은 @axe/ui 한 곳에서만 난다(디자인 SoT). 라벨과 링크의 위계는
 * 킷의 group-label 재료 + 그룹 아래 링크의 `data-level="2"` 들여쓰기가 함께 준다. */

/* 우측 컨텍스트 레일 — 정의(용어)와 절차만. 좌측 레일 항목을 되풀이하지 않는다.
 * 정의 목록 자체는 킷 어휘 `.axe-kv`(DescriptionList)가 소유한다 — 종전 여기 있던
 * `.layer-context-defs` 는 같은 모양을 서비스 로컬로 다시 그린 것이라 삭제했다. */
/* key 열 폭 — 킷이 표면마다 조정하라고 낸 손잡이(`--axe-kv-key-w`, 기본 8.75rem =
 * 상세 화면 실측치)를 280px 레일에 맞춰 좁힌다. 토큰 한 줄이라 어휘의 시각은 여전히
 * 킷이 갖는다(선언을 다시 쓰는 것과 손잡이를 돌리는 것은 다른 행위다). */
.axe-workspace-context .axe-kv {
  --axe-kv-key-w: 5.25rem;
}
.layer-context-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: var(--radius-full, 9999px);
  background: var(--border-strong);
  vertical-align: 1px;
}
.layer-context-dot--warm {
  background: var(--warning);
}
.layer-context-dot--hot {
  background: var(--danger);
}
.layer-context-steps {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--workspace-muted);
  font-size: var(--text-xs);
  line-height: 1.7;
}
.layer-workspace-note {
  margin: var(--space-4) 0 0;
  padding: var(--space-3);
  border-left: 2px solid var(--workspace-orange);
  color: var(--workspace-muted);
  font-size: var(--text-xs);
  line-height: 1.55;
}

/* ---- 오너 화면 섹션 — 카드 상자를 걷어낸다 ------------------------------ */
/* 중앙 캔버스가 이미 하나의 표면인데 섹션마다 상자를 겹치면 증거(표·수치)가
 * 장식에 눌린다. 그룹핑은 '규칙선 + 섹션 제목 + 리듬'이 맡는다.
 * 공개 표면(랜딩/로그인/게이트/뷰어/관심 접수)의 .axe-card 는 진짜 카드로 남는다. */
.layer-shell-body .axe-card.layer-section {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.layer-shell-body .layer-section {
  margin: 0 0 var(--space-8, 64px);
}
.layer-shell-body .layer-section:last-child {
  margin-bottom: 0;
}
/* Consumer Kit legacy-light currently flattens root palette tokens; workspace
 * aliases are selector-local, so keep those four aliases usable on older
 * external browsers as well. Remove when exporter emits selector fallbacks. */
@supports not (color: light-dark(#000, #fff)) {
  .axe-workspace-shell {
    --workspace-surface: #ffffff;
    --workspace-selected: #e4e4e2;
    --workspace-muted: #666663;
    --workspace-overlay: rgb(0 0 0 / 0.38);
  }
}

/* ---- 공유 URL 셀 -------------------------------------------------------- */
.layer-share-cell {
  display: flex;
  align-items: center;
  gap: 8px;
}
.layer-share-url {
  min-width: 0;
  flex: 1;
  /* 링크 텍스트 — 좁은 열에서도 값이 보이게 줄바꿈을 허용한다(종전 readonly input 은
     값이 잘려 빈 박스로 보였다, 2026-08-04 실측). */
  overflow-wrap: anywhere;
  word-break: break-all;
  font-size: 13px;
}
.layer-breadcrumb {
  margin: 0 0 8px;
}
.layer-page-head {
  margin: 0 0 24px;
}
/* page-head 액션 줄 (dashboard 업로드 CTA · doc_detail 편집/캠페인/보관) — 버튼·인라인폼을
   간격 있게 한 줄로. dashboard 는 <p> 라 기본 margin 을 리셋(__row flex 내 정렬 어긋남 방지),
   doc_detail 은 <div> 라 gap 만 유효. 실재 토큰만. */
.layer-page-head__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2, 8px);
  flex-wrap: wrap;
  margin: 0;
}
.layer-section-meta {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin: 8px 0 0;
}

/* ====================================================================== */
/* 공개 표면 — 워크스페이스와 분리된 단일 목적 랜딩/인증                       */
/* ====================================================================== */
.layer-public-shell {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--bg-base);
  color: var(--text-primary);
}
.layer-public-bar {
  position: sticky;
  z-index: var(--z-sticky, 100);
  top: 0;
  min-height: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-inline: clamp(1rem, 4vw, 3rem);
  border-bottom: 1px solid var(--border-subtle);
  background: color-mix(in srgb, var(--bg-base) 92%, transparent);
  backdrop-filter: blur(16px);
}
.layer-public-bar__brand {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  color: var(--brand-claret);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  text-decoration: none;
}
.layer-public-bar__actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.layer-public-main {
  min-height: calc(100vh - 56px);
  min-height: calc(100dvh - 56px);
}
.layer-hero {
  position: relative;
  padding: clamp(5rem, 11vw, 9rem) 0 clamp(4rem, 8vw, 7rem);
  overflow: clip;
}
.layer-hero::after {
  position: absolute;
  right: max(4vw, 1rem);
  bottom: 10%;
  width: min(26vw, 320px);
  aspect-ratio: 1;
  border: 1px solid color-mix(in srgb, var(--brand-claret) 24%, transparent);
  border-radius: 50%;
  content: "";
  opacity: 0.55;
  pointer-events: none;
}
.layer-hero__title {
  max-width: 13ch;
  font-family: var(--font-sans);
  font-size: clamp(2.45rem, 1.35rem + 4vw, 4.5rem);
  font-weight: 650;
  line-height: 1.04;
  letter-spacing: -0.045em;
  color: var(--text-primary);
  white-space: pre-line;
  margin: 0;
}
.layer-hero__lede {
  font-size: var(--text-lg, 1.1rem);
  color: var(--text-secondary);
  max-width: 48ch;
  line-height: 1.6;
  margin: 0;
}
.layer-band {
  padding: var(--space-8, 64px) 0;
  /* 앵커 착지(#features '기능 살펴보기')가 sticky topbar(56px) 밑으로 숨지 않게.
     데스크톱 포함 전역 — 기존 scroll-margin 규칙이 ≤1023.98px 에만 있어 ≥1024px 미보정. */
  scroll-margin-top: calc(var(--app-shell-topbar-h, 56px) + var(--space-3, 12px));
}
.layer-band--alt {
  background: var(--bg-subtle);
  border-top: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}
.layer-band__head {
  margin: 0 0 var(--space-6, 32px);
}
.layer-band__eyebrow {
  font-size: var(--text-sm, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 8px;
}
.layer-band__title {
  font-family: var(--font-sans);
  font-size: var(--text-2xl, 1.6rem);
  font-weight: 650;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  margin: 0;
}
.layer-feature__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-bottom: var(--space-3, 12px);
  border-radius: var(--radius-md, 8px);
  background: var(--accent-soft);
  color: var(--accent);
}
.layer-feature__icon svg {
  width: 20px;
  height: 20px;
}
/* 3단계 스텝 */
.layer-step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 9999px;
  background: var(--accent);
  color: var(--accent-fg);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: var(--text-base, 1rem);
}
.layer-step__title {
  font-weight: 600;
  font-size: var(--text-base, 1rem);
  color: var(--text-primary);
  margin: 0;
}
.layer-step__body {
  color: var(--text-secondary);
  margin: 0;
}
/* 랜딩 풋터 (base.html {% block footer %}) */
.layer-footer {
  padding: var(--space-6, 32px) 0;
}
.layer-footer__copy {
  color: var(--text-muted);
  font-size: var(--text-sm, 0.9rem);
}

/* ====================================================================== */
/* 인증(로그인) — 중앙 정렬 ~400px 카드                                     */
/* ====================================================================== */
.layer-auth {
  display: flex;
  min-height: calc(100vh - 56px);
  min-height: calc(100dvh - 56px);
  align-items: center;
  justify-content: center;
  padding: clamp(var(--space-6), 7vw, var(--space-10));
}
.layer-auth__card {
  width: 100%;
  max-width: 400px;
  border: 0;
  background: transparent;
  box-shadow: none;
}
.layer-auth__brand {
  display: inline-block;
  margin-bottom: var(--space-1, 4px);
}

/* ---- HTML 에러 페이지 (partials/error.html) ---------------------------- */
/* .layer-auth 중앙정렬 그릇 재사용 + empty-state. 에러 상태코드는 제목 위 소형
 * 모노 라벨로. 실재 토큰만(가짜 --fg 류 금지 — 다크모드 invisible 함정). */
.layer-error-state {
  width: 100%;
  max-width: 520px;
}
.layer-error-code {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--text-sm, 0.9rem);
  letter-spacing: 0.08em;
  margin: 0;
}
.layer-auth__card .axe-btn {
  width: 100%;
}
.layer-auth__divider {
  display: flex;
  align-items: center;
  gap: var(--space-3, 12px);
  color: var(--text-tertiary);
  font-size: var(--text-sm, 0.9rem);
}
.layer-auth__divider::before,
.layer-auth__divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border-subtle);
}

/* ====================================================================== */
/* 활성/보관함 세그먼트 컨트롤                                              */
/* ====================================================================== */
.layer-segment {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md, 8px);
}
.layer-segment__item {
  padding: 4px 14px;
  font-size: 13px;
  font-weight: 500;
  border-radius: calc(var(--radius-md, 8px) - 2px);
  color: var(--text-secondary);
  text-decoration: none;
  transition:
    background var(--duration-fast, 120ms) ease,
    color var(--duration-fast, 120ms) ease;
}
@media (hover: hover) {
  .layer-segment__item:hover {
    color: var(--text-primary);
    background: var(--bg-subtle);
  }
}
.layer-segment__item--active,
.layer-segment__item--active:hover {
  background: var(--accent);
  color: var(--accent-fg);
}

/* ====================================================================== */
/* 문서 목록 표 — 제목 셀 + 미세 zebra                                      */
/* ====================================================================== */
.layer-doc-title {
  display: inline-block;
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
  font-weight: 600;
  color: var(--text-primary);
  text-decoration: none;
}
.layer-doc-table tbody tr:nth-child(even):not(.layer-row-hot) {
  background: color-mix(in srgb, var(--bg-subtle) 45%, transparent);
}
/* Astryx hover:hover 게이트 (D-layer-45) — 시각 hover 피드백은 hover 가능 포인터에서만.
   터치 기기의 sticky hover(탭 후 잔상)를 차단(Astryx 전 컴포넌트 규율). 링크·행 클릭
   어포던스는 서버렌더/포커스로 병행 유지(제목은 여전히 <a>, 행은 [data-href]). */
@media (hover: hover) {
  .layer-doc-title:hover {
    color: var(--accent);
    text-decoration: underline;
  }
  /* zebra(0,3,2)가 axe-ui hover(.axe-data-table__tr:hover, 0,2,0)를 이겨 짝수행 hover
     피드백이 죽는다 → 동일 specificity·후순위 hover 로 클릭 어포던스 복원. */
  .layer-doc-table tbody tr:nth-child(even):hover {
    background: color-mix(in srgb, var(--accent) 4%, transparent);
  }
}

/* ====================================================================== */
/* 섹션 카드 헤더 밴드 (doc_detail)                                         */
/* ====================================================================== */
.layer-section > h2 {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 8px;
  border-bottom: 1px solid var(--border-subtle);
  padding-bottom: var(--space-3, 12px);
  margin-bottom: var(--space-4, 16px);
}
/* 섹션 제목의 괄호 부연 — 상속된 h2 크기로 두면 제목과 같은 목소리로 소리친다.
   `<h2>제목 <span class="layer-muted">(부연)</span></h2>` 관용구를 한 번에 낮춘다. */
.layer-section > h2 .layer-muted {
  min-width: 0;
  font-size: var(--text-sm, 0.875rem);
  font-weight: var(--weight-regular, 400);
  line-height: 1.5;
}

/* ====================================================================== */
/* doc_detail — 인플레이스 접근/허용목록 편집 + 링크 폼 그룹                 */
/* (템플릿이 참조하나 정의가 없던 클래스 — 무스타일 방지)                    */
/* ====================================================================== */
.layer-allowlist {
  list-style: none;
  margin: var(--space-3, 12px) 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2, 8px);
}
.layer-allowlist__item {
  display: flex;
  align-items: center;
  gap: var(--space-2, 8px);
  flex-wrap: wrap;
}
.layer-access-edit {
  margin-top: var(--space-2, 8px);
}
.layer-access-edit > summary {
  cursor: pointer;
  color: var(--text-secondary);
  font-size: 13px;
}
.layer-access-edit[open] {
  padding: var(--space-3, 12px);
  margin-top: var(--space-2, 8px);
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md, 8px);
}
.layer-access-edit__current {
  font-size: 12px;
  margin: 0 0 var(--space-2, 8px);
}
.layer-access-edit__confirm {
  display: flex;
  gap: var(--space-2, 8px);
  align-items: flex-start;
  font-size: 13px;
  margin: var(--space-2, 8px) 0;
}
.layer-access-edit__empty-warn {
  margin: var(--space-2, 8px) 0;
}
/* 전용(dedicated) 링크에서만 의미있는 수신자 필드 — dashboard.js 가 종류 변경 시
   [data-dedicated-field] 에 hidden 을 토글한다(실제 hide 는 axe-ui 의 전역
   [hidden]{display:none!important} 가드가 담당하나, hook 을 명시해 의도를 남긴다). */
[data-dedicated-field][hidden] {
  display: none;
}
.layer-form-check {
  grid-column: 1 / -1;
}
/* '새 링크' 폼 그룹 — 7필드를 접근·식별 / 전송·제약 두 fieldset 으로 묶어 정돈.
   fieldset 의 기본 min-width:min-content 쿼크가 내부 grid 줄바꿈을 막으므로 0 으로. */
.layer-form-group {
  min-width: 0;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md, 8px);
  padding: var(--space-3, 12px) var(--space-4, 16px) var(--space-4, 16px);
  margin: 0 0 var(--space-3, 12px);
}
.layer-form-group legend {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  padding: 0 var(--space-2, 8px);
}

/* ====================================================================== */
/* 키보드 포커스 링 (오너 인터랙티브 — :focus-visible 만)                   */
/* ====================================================================== */
/* 제목 링크(.layer-doc-title)가 실제 키보드 포커스 대상 — 행 클릭(data-href)은 마우스
   편의일 뿐, <tr> 은 tabindex 없어 포커스 불가. 죽은 .layer-row-clickable:focus-visible
   (적용된 적 없는 거짓 어포던스)를 제거하고 실제 interactive 인 제목 링크에 포커스 링. */
.layer-doc-title:focus-visible,
.layer-purge > summary:focus-visible,
.layer-access-edit > summary:focus-visible,
.layer-segment__item:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}

/* ====================================================================== */
/* 반응형 (≤767.98px) — 셸 collapse 와 정합. 내부 그리드만 추가 처리.         */
/* ====================================================================== */
@media (max-width: 767.98px) {
  .layer-heatmap__row {
    grid-template-columns: 1fr;
    gap: var(--space-1, 4px);
  }
  .layer-heatmap__row .layer-heatmap__val {
    justify-self: start;
  }
  .layer-share-cell {
    flex-wrap: wrap;
  }
  .layer-hero {
    padding: var(--space-8, 64px) 0 var(--space-7, 48px);
  }
}

/* ====================================================================== */
/* 공유 카드 미리보기 (doc_detail) — OG 언퍼 카드 모양을 오너에게 그대로 보여줌   */
/* (D-layer-22). 썸네일(브랜드 1200×630) 위, 아래 host·제목·요약. 실재 토큰만.     */
/* ====================================================================== */
.layer-share-preview {
  margin: var(--space-4, 16px) 0;
  max-width: 480px;
  border: 1px solid var(--border-subtle, #e5e5e5);
  border-radius: var(--radius-md, 8px);
  overflow: hidden;
  background: var(--bg-elevated, #fff);
}
.layer-share-preview__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1200 / 630;
  background: var(--bg-subtle, #f5f5f5);
}
.layer-share-preview__body {
  padding: var(--space-3, 12px) var(--space-4, 16px);
  border-top: 1px solid var(--border-subtle, #e5e5e5);
}
.layer-share-preview__host {
  margin: 0 0 var(--space-1, 4px);
  font-size: var(--text-sm, 0.8125rem);
  color: var(--text-muted, #888);
  overflow-wrap: anywhere;
}
.layer-share-preview__title {
  margin: 0;
  font-size: var(--text-base, 1rem);
  font-weight: 600;
  color: var(--text-primary, #1a1a1a);
  line-height: 1.35;
}
.layer-share-preview__summary {
  margin: var(--space-1, 4px) 0 0;
  font-size: var(--text-sm, 0.8125rem);
  color: var(--text-secondary, #555);
  line-height: 1.4;
}

/* ====================================================================== */
/* 캠페인 상세 (campaign.html) — 헤더 위계 · 머지열 압축 · 표 스크롤 (D-layer-22) */
/* 실재 토큰만(--text-*/-bg-*/-border-*/-accent*/-radius*/-space*). 가짜 --fg 금지.  */
/* ====================================================================== */

/* --- 헤더 위계: 제목 > 서브타이틀(제목) > 메타 줄 --- */
.layer-campaign-head > h1 {
  margin: 0;
}
.layer-campaign-head__subject {
  margin: 4px 0 0;
  color: var(--text-secondary);
  font-size: var(--text-lg, 1.05rem);
  line-height: 1.4;
}
.layer-campaign-head__meta {
  display: flex;
  align-items: center;
  gap: 8px 10px;
  flex-wrap: wrap;
  margin: 12px 0 0;
}
/* 메타 아이템 — badge 사이의 muted 라벨(과한 · 나열 대신 gap 으로 분리). 앞에
   얇은 구분점을 넣어 badge 와 라벨군을 시각적으로 구분(첫 아이템 제외). */
.layer-meta-item {
  color: var(--text-muted);
  font-size: var(--text-sm, 0.85rem);
  white-space: nowrap;
}
.layer-meta-item + .layer-meta-item::before,
.axe-badge + .layer-meta-item::before {
  content: "·";
  margin-right: 10px;
  color: var(--border-strong, var(--text-tertiary));
}

/* --- 머지 열 압축 요약 — 1줄·작은 글씨·muted, 행 높이 낮게 --- */
.layer-merge-cell {
  font-size: var(--text-sm, 0.8125rem);
  color: var(--text-muted);
  white-space: nowrap;
  max-width: 340px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}
/* 배열 토큰 → 작은 muted chip "키 · N행"(원시 배열 미출력) */
.layer-merge-chip {
  display: inline-block;
  padding: 1px 7px;
  margin-right: 6px;
  border-radius: 9999px;
  background: var(--bg-subtle);
  border: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  font-size: var(--text-xs, 0.75rem);
  line-height: 1.5;
  vertical-align: middle;
}
/* 대표 스칼라 — 키(muted 라벨) + 값. 나머지는 +N 카운트(hover=전체). */
.layer-merge-scalar {
  vertical-align: middle;
}
.layer-merge-scalar__k {
  color: var(--text-tertiary);
  margin-right: 3px;
}
.layer-merge-more {
  display: inline-block;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: 9999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--text-xs, 0.72rem);
  font-weight: 600;
  cursor: default;
}

/* --- 수신자표 스크롤 컨테이너 — 45행+ 이 카드 안에서 스크롤(페이지 길이 억제) --- */
/* .axe-data-table 이 자체 overflow-x:auto 를 가지므로 세로 스크롤은 바깥 래퍼가 맡는다. */
.layer-table-scroll {
  max-height: 460px;
  overflow-y: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md, 8px);
}
/* 안쪽 axe-data-table 의 자체 보더를 중복 제거(래퍼가 보더를 그림). */
.layer-table-scroll > .axe-data-table {
  border: 0;
  border-radius: 0;
}
/* sticky thead — 스크롤 시 헤더 고정. axe-ui thead 배경을 명시(투명 시 행이 비침). */
.layer-recipients-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--bg-elevated, var(--bg-base));
  box-shadow: inset 0 -1px 0 var(--border-default);
}
/* compact 밀도(Astryx 표 밀도 3단 중 compact, D-layer-45) — 셀 패딩 4px(세로)/8px(가로),
 * 폰트 크기는 유지(밀도는 패딩만 바꾼다). 45행 발송 리포트·목록 표의 스크롤을 절반으로.
 * 그룹 헤더(.layer-group-header__cell 12/16)는 자체 패딩 유지 — 데이터 셀에만 적용. */
.layer-recipients-table tbody td,
.layer-campaign-table tbody td {
  padding: 4px 8px;
}
/* 헤더는 가로 패딩을 셀과 맞춰 열 정렬 — 세로만 약간 여유(sticky 헤더 스캔성). */
.layer-recipients-table thead th,
.layer-campaign-table thead th {
  padding: 6px 8px;
}

/* --- 상단 상태 콜아웃 스택 정돈 — 여러 개(pull/발송/미구성/저장/머지)가 쌓일 때 --- */
/* 각 콜아웃은 .layer-section(28px 하단 여백)이라 연달아 쌓이면 간격이 과하다. 인접
   콜아웃끼리는 좁은 간격으로 묶고(그룹 리듬), 마지막 콜아웃과 다음 섹션 사이만 넓게. */
.axe-callout.layer-section + .axe-callout.layer-section {
  margin-top: -16px;
}

/* ====================================================================== */
/* S3 — 메일 표면 (목록/상세 분리·발송 리포트·409 해법·템플릿 허브)          */
/* CSP style-src 'self' — campaign_detail/list/new/editor/templates 인라인   */
/* style 이관. 실재 토큰만(가짜 --axe-border 류 금지 — 다크에서 invisible).  */
/* ====================================================================== */

/* page-head 우측 primary(새 캠페인) 정렬 */
.layer-page-head__row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-4, 16px);
  flex-wrap: wrap;
}
/* 제목 묶음이 액션 줄을 밀어내지 않게 — 긴 제목은 줄바꿈, 액션은 우측 유지. */
.layer-page-head__ident {
  min-width: 0;
  flex: 1 1 28ch;
}
.layer-page-head__ident > h1 {
  margin: 0;
  overflow-wrap: anywhere;
}

/* 섹션 헤더(제목 + 우측 액션 버튼) */
.layer-section-head {
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
}
.layer-section-head__title {
  margin: 0;
}

/* 목록 표 — 숫자 열 우정렬 + 실패 카운트 강조 */
.axe-num {
  text-align: right;
}
.layer-campaign-table .axe-num {
  font-variant-numeric: tabular-nums;
}
.layer-fail-count {
  color: var(--danger);
  font-weight: 600;
}
.axe-actions-th,
.layer-tpl-actions {
  white-space: nowrap;
}
.layer-tpl-actions {
  gap: var(--space-2, 8px);
}

/* 모노스페이스 textarea(본문·푸터·HTML 편집 입력) — 인라인 font-family 이관 */
.layer-mono-input {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  line-height: 1.6;
  resize: vertical;
}

/* fieldset 리셋(수신 대상 필터 등) — 인라인 border:0;padding:0;margin:0 이관 */
.layer-fieldset-reset {
  border: 0;
  padding: 0;
  margin: 0;
}

/* 폼 검증 attached 에러 칩 (Astryx FieldStatus, D-layer-45) — 에러 메시지가 인풋 하단에
 * '붙은' 칩. 부모 .axe-form-field 가 flex gap(--space-2) 이므로 그 gap 까지 상쇄해야
 * 순효과 6px 겹침이 된다(gap 미상쇄 −6px 는 실제로 +2px 간격 — D-45 QA). 인풋 뒤로
 * 깔리는 스택은 에러 인풋 쪽 z-index:1 이 만든다(positioned 칩은 static 인풋 위에
 * 그려지는 게 CSS 페인팅 기본이라 칩 z-index 만으로는 불가). 하단만 radius 8px →
 * 인풋과 한 덩어리. bg=danger-soft + text=danger, role=alert(마크업). 등장 모션은
 * '동적 삽입일 때만'(dashboard.js 가 --animate 부여) — 서버렌더 초기 페인트는 무애니. */
.layer-field-error {
  margin: calc(-6px - var(--space-2, 8px)) 0 0;
  padding: 12px 12px 8px;
  background: var(--danger-soft);
  color: var(--danger);
  font-size: 12.5px;
  line-height: 1.4;
  border-bottom-left-radius: var(--radius-md, 8px);
  border-bottom-right-radius: var(--radius-md, 8px);
  position: relative;
  z-index: 0;
}
/* 에러 인풋 — danger 보더 귀속 강조 + z-index:1 로 겹친 칩 상단 6px 위에 그려짐. */
.layer-form-field--error .axe-input {
  border-color: var(--danger);
  position: relative;
  z-index: 1;
}
/* 동적 삽입 등장 모션 — JS 가 삽입 직후 --animate 부여(rAF). 초기 서버렌더엔 미부여. */
.layer-field-error--animate {
  animation: layer-field-error-in var(--duration-base, 180ms) ease;
}
@keyframes layer-field-error-in {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .layer-field-error--animate {
    animation: none;
  }
}

/* 이메일 미리보기 iframe 박스 — 하드코딩 #f4f4f5→실재 bg, --axe-border→실재 토큰 */
.layer-email-preview-box {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md, 8px);
  overflow: hidden;
  background: var(--bg-subtle);
  margin-top: var(--space-3, 12px);
}
.layer-email-preview-frame {
  width: 100%;
  height: 520px;
  border: 0;
  display: block;
  background: var(--bg-subtle);
}

/* 편집 details(본문·설정 편집) */
.layer-edit-details {
  margin-top: var(--space-5, 20px);
}
.layer-edit-details__summary {
  cursor: pointer;
  font-weight: 600;
}
.layer-edit-form {
  margin-top: var(--space-4, 16px);
}

/* 발송 리포트 — 퍼널 요약 */
.layer-funnel {
  display: flex;
  align-items: stretch;
  gap: var(--space-2, 8px);
  flex-wrap: wrap;
  margin: var(--space-2, 8px) 0 0;
}
.layer-funnel__step {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 18px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md, 8px);
  background: var(--bg-subtle);
  min-width: 96px;
}
.layer-funnel__label {
  font-size: 12px;
  color: var(--text-secondary);
}
.layer-funnel__value {
  font-size: 22px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
.layer-funnel__arrow {
  align-self: center;
  color: var(--text-muted);
}
.layer-report-caveat {
  margin-top: var(--space-3, 12px);
}
.layer-report-open,
.layer-report-click {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 리포트 셀 인라인 비율 막대 (Astryx dashboard '셀 안 ProgressBar + 수치 2줄', D-layer-45).
 * 트랙 = accent-soft, 채움 = accent, radius full, 폭 = 값/캠페인 최대값(JS applyServerBars).
 * 막대는 수치 텍스트 위에 얹힌 2줄 스택 — 값 0·픽셀미포함이면 템플릿이 막대를 생략한다. */
.layer-ratio-bar {
  display: block;
  width: 72px;
  max-width: 100%;
  height: 5px;
  margin-bottom: 3px;
  background: var(--accent-soft);
  border-radius: var(--radius-full, 9999px);
  overflow: hidden;
}
.layer-ratio-bar__fill {
  display: block;
  height: 100%;
  width: 0; /* JS(applyServerBars) 가 data-pct → style.width 적용 */
  background: var(--accent);
  border-radius: inherit;
}
.layer-ratio-bar__num {
  display: block;
}

/* 리포트 상태별 그룹 접이 (Astryx grouped table, D-layer-45).
 * 그룹 헤더 = colSpan 전폭 행(bg-subtle·패딩 12/16·셰브론+라벨+count 배지).
 * 그룹 ≥2 일 때만 [data-group-toggle] 로 접이(dashboard.js). 접힘 = data-collapsed
 * 로 데이터 행 숨김. 단일 그룹은 정적 헤더(셰브론·토글 없음). */
.layer-group-header__cell {
  background: var(--bg-subtle);
  padding: 12px 16px;
  text-align: start;
  font-weight: 600;
  color: var(--text-secondary);
  box-shadow: inset 0 -1px 0 var(--border-default);
}
/* 접이 = th 안의 실제 <button>(표준 disclosure) — tr 에 role=button 을 얹으면 표 row
 * 시맨틱이 깨진다(button 은 children presentational, D-45 QA). 버튼이 셀을 가득 채워
 * 행 전체가 클릭 타깃(셀 패딩 12/16 을 버튼이 승계). */
.layer-group-header__cell--toggle {
  padding: 0;
}
.layer-group-header__toggle {
  display: block;
  width: 100%;
  padding: 12px 16px;
  background: none;
  border: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  text-align: start;
  cursor: pointer;
  user-select: none;
}
.layer-group-header__chevron {
  display: inline-block;
  margin-right: 8px;
  color: var(--text-muted);
  transition: transform var(--duration-fast, 120ms) ease;
}
.layer-group-header__label {
  color: var(--text-primary);
}
.layer-group-header__count {
  margin-left: 8px;
}
/* 접힘 상태 — 데이터 행 숨김 + 셰브론 회전(▾→▸). aria-expanded 는 JS 가 동기. */
.layer-group[data-collapsed] .layer-group__row {
  display: none;
}
.layer-group[data-collapsed] .layer-group-header__chevron {
  transform: rotate(-90deg);
}
/* keyboard 포커스 — 접이 버튼 :focus-visible 링(Enter/Space 는 네이티브 버튼). */
.layer-group-header__toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
@media (prefers-reduced-motion: reduce) {
  .layer-group-header__chevron {
    transition: none;
  }
}
.layer-report-cta {
  margin-top: var(--space-3, 12px);
  align-items: flex-start;
  flex-wrap: wrap;
}
.layer-canary-list {
  margin-top: var(--space-4, 16px);
}
.layer-canary-list__ul {
  margin: var(--space-2, 8px) 0 0;
  padding-left: 1.2em;
}

/* 발송본 뷰어 — 메타 정의 리스트 */
.layer-message-meta {
  margin: 0;
  display: grid;
  gap: 6px;
}
.layer-message-meta__row {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: var(--space-3, 12px);
  align-items: baseline;
}
.layer-message-meta__row dt {
  color: var(--text-secondary);
  font-size: 13px;
}
.layer-message-meta__row dd {
  margin: 0;
  color: var(--text-primary);
}

/* 진행 뷰(sending) 복구 details */
.layer-recover {
  margin-top: var(--space-3, 12px);
}
.layer-recover > summary {
  cursor: pointer;
}

/* 인라인 details(템플릿으로 저장·이름변경) — summary 버튼 + 펼침 폼 */
.layer-inline-details {
  display: inline-block;
}
.layer-inline-details > summary {
  list-style: none;
  cursor: pointer;
}
.layer-inline-details > summary::-webkit-details-marker {
  display: none;
}
.layer-save-tpl-form {
  margin-top: var(--space-3, 12px);
  max-width: 460px;
}
.layer-save-tpl-draft {
  margin-top: var(--space-3, 12px);
}
.layer-rename-form {
  margin-top: var(--space-2, 8px);
  gap: var(--space-2, 8px);
  align-items: center;
}

/* 시작점 선택(campaign_new) — 라디오 행 */
.layer-start-choice {
  margin: var(--space-2, 8px) 0;
}
.layer-radio-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-2, 8px);
  cursor: pointer;
}
.layer-start-hint {
  padding-left: 1.5em;
}
.layer-dup-opt {
  font-size: 13px;
  color: var(--text-secondary);
}

/* 읽기전용 에디터 CTA 바 */
.ed-readonly-cta {
  display: flex;
  gap: var(--space-3, 12px);
  align-items: flex-start;
  flex-wrap: wrap;
  padding: 0 var(--space-4, 16px) var(--space-3, 12px);
}

/* 버전 컨트롤·정렬 유틸(인라인 style 이관) */
.layer-version-controls {
  margin-top: var(--space-3, 12px);
  align-items: flex-end;
  flex-wrap: wrap;
}
.layer-version-note {
  margin-top: var(--space-3, 12px);
}
.layer-align-end {
  align-items: flex-end;
}
.layer-wrap {
  flex-wrap: wrap;
}
.layer-mt-8 {
  margin-top: 8px;
}
.layer-recipient-add,
.layer-merge-upload,
.layer-send-all {
  margin-top: var(--space-4, 16px);
}
.layer-dataset-dl {
  margin-top: var(--space-3, 12px);
}
.layer-dataset-note,
.layer-callout-sub {
  margin-top: var(--space-2, 8px);
}
.layer-break-all {
  word-break: break-all;
}
.layer-merge-help > summary {
  cursor: pointer;
  color: var(--text-secondary);
}
.layer-row-archived {
  opacity: 0.6;
}

/* diff 뷰(templates.html) — 인라인 style 이관, 실재 토큰만 */
.layer-diff {
  margin: 0;
  overflow-x: auto;
  background: var(--bg-subtle);
  border-radius: var(--radius-md, 8px);
  padding: 14px 16px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  line-height: 1.5;
}
.layer-diff__line {
  display: block;
}
.layer-diff__line--add,
.layer-diff-legend-add {
  color: var(--success);
}
.layer-diff__line--del,
.layer-diff-legend-del {
  color: var(--danger);
}
.layer-diff__line--hunk {
  color: var(--text-muted);
  font-weight: 600;
}

/* ====================================================================== */
/* S4 — 문서 표면 (목록 검색/정렬 · 업로드 1급 · 상세 tab 4분할 · 링크 분석 병합) */
/* 실재 토큰만(가짜 토큰 금지 — 다크에서 invisible).                          */
/* ====================================================================== */

/* 문서 목록 툴바 — 좌 검색 / 우 정렬 세그먼트 (모바일 줄바꿈) */
.layer-doc-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4, 16px);
  flex-wrap: wrap;
  margin: 0 0 var(--space-4, 16px);
}
.layer-doc-toolbar__search {
  display: flex;
  align-items: center;
  gap: var(--space-2, 8px);
  flex: 1 1 260px;
  min-width: 0;
}
.layer-doc-toolbar__search .axe-input {
  min-width: 0;
  flex: 1;
  max-width: 320px;
}
.layer-doc-toolbar__sort {
  margin: 0;
}

/* 목록 소스 종류 배지(신뢰/PDF) — 제목 옆 소형 병기 */
.layer-doc-kind {
  margin-left: var(--space-2, 8px);
  vertical-align: middle;
}

/* 업로드 1급 카드 — 접이식(details) 승격판 */
.layer-upload-card__title {
  margin-top: 0;
}
.layer-upload-card__lede {
  margin: calc(-1 * var(--space-2, 8px)) 0 var(--space-4, 16px);
}
.layer-upload__paste {
  margin-top: var(--space-5, 24px);
}
.layer-upload__paste > summary {
  cursor: pointer;
}

/* 파일 입력 — .axe-input(36px inline-flex 단일행 상자)에 네이티브 file 컨트롤을
 * 넣으면 브라우저 버튼이 상자를 밀고 나온다. 파일 입력은 '상자'가 아니라 버튼 +
 * 파일명이므로 정본 버튼 토큰만 빌려 쓰고 상자는 두지 않는다. */
.layer-file-input {
  min-width: 0;
  max-width: 100%;
  color: var(--text-secondary);
  font-size: var(--text-sm);
}
.layer-file-input::file-selector-button {
  margin-right: var(--space-3, 12px);
  padding: 0 var(--space-3, 12px);
  min-height: 32px;
  border: 1px solid var(--border-control, var(--border-strong));
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  color: var(--text-primary);
  font: inherit;
  cursor: pointer;
  transition: border-color var(--duration-fast) var(--ease-out);
}
.layer-file-input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm, 4px);
}
/* 이동 없는 테두리 피드백이라 (hover: hover) 만으로 게이트한다 — 이 파일의 다른 hover
   규칙과 같은 관용구(터치에서 sticky hover 가 남지 않게). D-45 hover 게이트 테스트가 지킨다. */
@media (hover: hover) {
  .layer-file-input::file-selector-button:hover {
    border-color: var(--border-control-hover, var(--border-strong));
  }
}

/* 체크박스 행 — 네이티브 input 과 라벨의 baseline 정렬(라벨이 두 줄이어도 안 밀림). */
.layer-check-row {
  display: flex;
  gap: var(--space-2, 8px);
  align-items: flex-start;
  cursor: pointer;
}
.layer-check-row > input[type="checkbox"] {
  flex: 0 0 auto;
  margin: 0.2em 0 0;
  accent-color: var(--accent);
}

/* 폼 그리드에서 한 줄을 다 쓰는 칸(제출 버튼·긴 설명 체크박스). */
.layer-form-grid__full {
  grid-column: 1 / -1;
}

/* 문서 상세 tab 4분할(개요/공유/질문/설정) — layer-segment 재사용 + 여백만 */
.layer-doc-tabs {
  margin: 0 0 var(--space-6, 24px);
}

/* 새 링크 폼 용도 프리셋 — 라디오 행(줄바꿈 허용) */
.layer-link-presets {
  display: flex;
  gap: var(--space-4, 16px);
  flex-wrap: wrap;
}
.layer-link-presets__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

/* 공유 링크 표 정렬 버튼 disabled — 분석 로드 전/실패 시. 벤더 sort-btn 은 항상
   활성 전제라 :disabled 시각이 없어(cursor:pointer + hover 색 전환 그대로) '눌리는
   척' 하는 죽은 버튼이 된다 → 여기서 보정(값은 analytics.json 병합 후에만 존재).
   color 재선언은 벤더 hover 색전환(동일 specificity)을 후순위 캐스케이드로 무력화
   — hover 셀렉터 직접 사용은 hover-gate 규약(test_astryx6_d45) 위반이라 이 방식. */
.axe-data-table__sort-btn:disabled {
  cursor: default;
  color: inherit;
}
.axe-data-table__sort-btn:disabled .axe-data-table__sort-arrow {
  opacity: 0.35;
}

/* 질문 답변 폼 (D-layer-61) — 행 아래 펼쳐지는 인라인 답변. */
.layer-question-reply__form {
  display: grid;
  gap: 8px;
  padding: 4px 0 8px;
}

.layer-question-reply__log {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
}

/* 공유 링크 관리 패널 (P1-2) — 행 아래 지연 로드되는 조각. */
.layer-link-panel {
  display: grid;
  gap: 14px;
  padding: 6px 0 10px;
}

.layer-link-panel__title {
  margin: 0 0 6px;
  font-size: 14px;
}

.layer-link-search {
  margin: 8px 0 12px;
  max-width: 320px;
}

/* 되돌릴 수 없는 행동의 ghost 버튼 — 시선을 뺏지 않되 '끄기' 와 구분되게 (P1-4). */
.layer-btn-danger-ghost {
  color: var(--danger);
  border-color: var(--danger);
}
@media (hover: hover) {
  .layer-btn-danger-ghost:hover {
    background: var(--danger-soft, rgba(190, 30, 45, 0.08));
  }
}

/* 방문자 페이지네이션 (P1-6) */
[data-visitors-pager] {
  margin-top: 12px;
}

/* 레일 미답변 배지 (P2-6) — 숫자 하나. 링크 라벨과 같은 줄에 붙어 "여기 몇 건" 만
 * 말한다(색으로만 알리지 않게 수를 그대로 쓴다). */
.layer-rail-badge {
  display: inline-block;
  min-width: 1.5em;
  margin-left: 6px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--accent-soft, rgba(190, 30, 45, 0.12));
  color: var(--accent, inherit);
  font-size: var(--text-xs, 0.75rem);
  font-weight: var(--weight-medium, 500);
  line-height: 1.6;
  text-align: center;
}

/* 인박스 본문 셀 — 원문 그대로 보여 주되 한 줄이 표를 밀지 않게. */
.layer-inbox-body {
  max-width: 46ch;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* 인박스 딥링크가 지목한 행 (P2-6) — 어느 줄로 왔는지 눈으로 확인되게. 색만 쓰지
 * 않고 좌측 굵은 경계로도 표시한다(forced-colors·색각 이상에서도 보이게). */
.layer-row-target > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--accent, currentColor);
}
.layer-row-target > td {
  background: var(--accent-soft, rgba(190, 30, 45, 0.08));
}

/* 데스크톱 상단 빈 띠 제거 (P2 리뷰) — 1440px 이상에서는 topbar 안의 컨트롤이 전부
 * 숨겨진다(모바일 드로어 트리거·컨텍스트 토글). 남는 건 56px 짜리 빈 줄뿐인데,
 * 화면 맨 위 한 줄은 가장 비싼 자리다. 벤더 geometry 는 그대로 두고 이 폭에서만
 * 높이 변수를 0 으로 접는다 — 레일·컨텍스트·본문의 100vh 계산이 전부 이 변수를
 * 참조하므로 한 곳만 바꾸면 정합이 유지된다(레일 음수 마진도 0 이 된다).
 * 1439px 이하는 컨텍스트 토글이 실제로 살아 있어 건드리지 않는다(모바일 동작 불변).
 *
 * 접힌 상태는 예외다 — 접기 토글의 **펼침용** 인스턴스가 바로 그 topbar 좌측 칸에
 * 살기 때문이다(@axe/ui 0.28.0 계약). 접혔는데도 바를 감추면 레일을 되돌릴 어포던스가
 * 화면에서 사라져 localStorage 를 지우기 전엔 못 편다 — 그때만 바가 다시 선다. */
@media (min-width: 1440px) {
  .layer-shell-body:not([data-rail-collapsed]) {
    --workspace-topbar-h: 0px;
  }
  .layer-shell-body:not([data-rail-collapsed]) > .axe-app-shell__topbar {
    display: none;
  }
  /* 한 변수가 두 가지 높이를 잰다 — topbar 와 **rail 머리**(brand 행,
   * `flex: 0 0 var(--workspace-topbar-h)`). 위에서 0 으로 접으면 rail 머리까지 0 이 돼
   * `overflow:hidden` 에 잘린다: 이 폭에서 레일의 "Layer" 워드마크가 통째로 사라져
   * 있었고, 이제는 접기 토글이 사는 자리이기도 하다(펼친 상태의 유일한 접기 어포던스).
   * 그래서 rail 머리에서만 벤더 기본값을 되돌린다 — topbar 는 계속 접힌 채다.
   * 값은 벤더 `--workspace-topbar-h` 기본값(axe-ui.css)과 lockstep 이다. */
  .layer-shell-body .axe-workspace-rail__brand {
    --workspace-topbar-h: 56px;
  }
}

/* 전역 퍼널 필터 바 (P3-3) — 온보딩 큐의 필터 폼과 같은 격자이되, 이 파일에 둬서
 * 모든 화면이 쓸 수 있게 한다(onboarding.css 는 그 페이지에서만 로드된다).
 * 좁은 폭에서는 한 줄에 하나씩 — 3열을 320px 에 밀어 넣으면 select 가 못 읽는다. */
.layer-filter-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  align-items: end;
}
.layer-filter-bar__actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
@media (max-width: 640px) {
  .layer-filter-bar {
    grid-template-columns: 1fr;
  }
}

/* 퍼널 단계에 비율 폭을 준다 (P3-3) — 수만 늘어놓으면 어느 단에서 떨어졌는지 눈으로
 * 세어야 한다. 폭은 첫 단 대비 비율이고, 0 이어도 라벨이 읽히도록 최소 폭을 남긴다. */
.layer-funnel--scaled .layer-funnel__step {
  flex: 1 1 auto;
}
.layer-funnel__meter {
  margin-top: 6px;
  height: 4px;
  border-radius: 2px;
  background: var(--border-subtle);
  overflow: hidden;
}
.layer-funnel__meter-fill {
  display: block;
  height: 100%;
  width: 0; /* JS(applyServerBars) 가 data-pct → style.width 적용 */
  background: var(--accent, currentColor);
}

/* AI 조회 패널 (D-layer-64, P4) — 우측 rail 안에 산다.
 * 폭 제한(≥1440px)은 벤더가 이미 한다: axe-ui.css 가 1439.98px 이하에서
 * .axe-app-shell__toc 를 숨기므로 여기 미디어쿼리를 더하지 않는다. */
.layer-ai {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md, 8px);
  background: var(--bg-subtle);
  margin-bottom: var(--space-3, 12px);
}
.layer-ai__head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.layer-ai__title {
  font-size: 13px;
}
.layer-ai__badge {
  font-size: 11px;
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  padding: 1px 7px;
}
.layer-ai__hint {
  font-size: 12px;
  color: var(--text-secondary);
  margin: 0;
}
/* 로그는 자체 스크롤 — 대화가 길어져도 rail 이 길어지지 않는다. */
.layer-ai__log {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 46vh;
  overflow-y: auto;
  font-size: 12.5px;
  line-height: 1.55;
}
.layer-ai__log:empty {
  display: none;
}
.layer-ai__row {
  white-space: pre-wrap; /* 모델 답의 줄바꿈 보존 — textContent 라 마크업은 안 산다 */
  overflow-wrap: anywhere;
  border-radius: var(--radius-sm, 6px);
  padding: 6px 8px;
}
.layer-ai__row--me {
  background: var(--accent-soft, rgba(190, 30, 45, 0.08));
}
.layer-ai__row--bot {
  background: var(--bg-canvas, transparent);
  border: 1px solid var(--border-subtle);
}
.layer-ai__row--tool,
.layer-ai__row--error {
  font-size: 12px;
  color: var(--text-secondary);
  padding: 2px 0;
}
.layer-ai__row--error {
  color: var(--danger, #b3261e);
}
/* 답이 가리키는 화면으로 가는 링크 (P5). 내부 경로만 링크가 되고(ai-panel.js 화이트리스트),
   레일이 좁아 긴 경로가 넘치므로 어디서든 접히게 둔다. */
.layer-ai__link {
  color: var(--accent, #be1e2d);
  text-decoration: underline;
  overflow-wrap: anywhere;
}
.layer-ai__form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.layer-ai__input {
  resize: vertical;
  min-height: 48px;
  font-size: 12.5px;
}
.layer-ai__send {
  align-self: flex-end;
}
