/* Brand intelligence console: the fixed left rail, the topbar, and every panel
 * the 대시보드 / AI 노출 분석 / AVS 점수 / 인용 출처 / 실행 과제 / 리포트 screens draw.
 * 리포트 화면은 .report-*(기간 요약 문서)와 .notification-*(이메일 리포트 전송 기록)
 * 둘을 함께 그린다.
 *
 * This file also carries the shell override. base.css still styles <header> as a
 * sticky top bar for the auth screen and for narrow viewports; from 761px up the
 * rules here turn the same element into a 244px rail. Keeping one element (and
 * therefore one set of selectors) was deliberate -- app.js and the e2e suite both
 * reach for `header [data-view]`.
 *
 * Loaded after workspace.css so a panel can reuse .badge/.pill/.empty without
 * re-declaring them. */

/* Rail, panel, and delta tokens are declared in css/tokens.css because the admin
 * console draws the same rail and the same card. */

/* ---------- shell ---------- */
/* 좌우 여백 한 값을 세 자리(main 패딩 · 제목 띠의 음수 마진 · 제목 안쪽 여백
 * 계산)가 같이 쓰므로 변수로 묶는다. 콘텐츠 접힘의 기준이 되는 컨테이너 선언
 * (@container content-col)은 css/layout.css의 main에 있다 -- 셸(레일↔탑바)은
 * 뷰포트 미디어쿼리, 콘텐츠는 컨테이너 쿼리로 역할이 갈린다. */
body[data-workspace-shell="rail"] main {
  --main-gutter: clamp(20px, 3vw, 44px);
}

/* 회의 피드백: 설명과 지표 라벨의 기본 크기를 한 단계 키운다. 어드민까지 공유하는
 * 전역 토큰은 건드리지 않고 워크스페이스 화면에서만 작은 세 단계를 올린다. */
body[data-workspace-shell="rail"] {
  --fs-1: 13px;
  --fs-2: 14px;
  --fs-3: 15px;
}

@media (min-width: 761px) {
  /* `> header`, not a descendant: 레일은 body 바로 아래 하나뿐인데, 자손으로 두면
   * 패널 안에 선 <header> 한 줄까지 레일 상자로 만들어 화면 왼쪽을 통째로 덮는다.
   * 실제로 노출 영역 상세 카드가 <header>를 쓰다가 좌측 메뉴를 가렸다. */
  body[data-workspace-shell="rail"] > header,
  body[data-workspace-shell="rail"][data-workspace-view] > header {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 20;
    width: var(--rail);
    border-right: 1px solid var(--rail-line);
    border-bottom: 0;
    background: var(--rail-bg);
    backdrop-filter: none;
    /* Not overflow:auto -- that clips the account/workspace flyout menus on both
     * axes. The nav list below is the only part that scrolls, so brand and
     * account rows can open menus that spill past the rail edge. */
    overflow: visible;
  }

  body[data-workspace-shell="rail"] header .nav {
    display: flex;
    flex-direction: column;
    /* The base header grid centers its cells; left as-is in the flex column it
     * shrink-wraps the brand and workspace badges to their text, so short
     * workspace names render as a floating pill narrower than the brand block. */
    align-items: stretch;
    gap: 14px;
    max-width: none;
    height: 100%;
    padding: 22px var(--rail-gutter) 18px;
  }

  /* Only the nav list scrolls; brand (top) and account (bottom) stay pinned so
   * their flyouts have a stable anchor and never get clipped. */
  body[data-workspace-shell="rail"] header .steps {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: visible;
    scrollbar-width: thin;
    /* 커스텀 색을 안 주면 밝은 OS 기본 스크롤바(흰 트랙+회색 막대)가 어두운 레일 위에
     * 그대로 떠 이질감이 크다. 트랙은 투명으로 둬 레일 배경이 그대로 비치게 한다. */
    scrollbar-color: var(--rail-line) transparent;
  }

  body[data-workspace-shell="rail"] header .steps::-webkit-scrollbar { width: 8px; }
  body[data-workspace-shell="rail"] header .steps::-webkit-scrollbar-track { background: transparent; }
  body[data-workspace-shell="rail"] header .steps::-webkit-scrollbar-thumb {
    border-radius: 999px;
    background: var(--rail-line);
  }
  body[data-workspace-shell="rail"] header .steps::-webkit-scrollbar-thumb:hover {
    background: var(--rail-text-dim);
  }

  body[data-workspace-shell="rail"] main {
    max-width: none;
    margin: 0 0 0 var(--rail);
    padding: 0 var(--main-gutter) 56px;
  }

  body[data-workspace-shell="rail"] #workspace > .title {
    position: sticky;
    top: 0;
    z-index: 6;
    margin: 0 calc(var(--main-gutter) * -1);
    /* 띠(배경·아랫줄)는 전폭 그대로 두고, 안쪽 여백으로 제목을 #content와 같은
     * 컬럼 좌측선에 앉힌다. 100%는 main 콘텐츠 폭이라 컬럼이 --content-max에
     * 닿기 전에는 max()가 기존 여백으로 떨어진다. */
    padding: 20px calc(max(0px, (100% - var(--content-max)) / 2) + var(--main-gutter)) 18px;
    border-bottom: 1px solid var(--line);
    /* Opaque, not translucent: panel headings scrolling underneath were showing
     * through the blur and reading as a second heading. */
    background: var(--bg);
  }

  body[data-workspace-shell="rail"] #workspace > .title h1 { font-size: var(--fs-6); }
  /* 상한만 있고 정렬이 없어 초광폭에서 본문이 왼쪽에 붙어 있었다 -- 남는 폭은
   * 좌우로 나눈다. 실행 배너도 같은 컬럼을 따라간다. */
  body[data-workspace-shell="rail"] #content,
  body[data-workspace-shell="rail"] #active-run-banner {
    max-width: var(--content-max);
    margin-inline: auto;
  }
  body[data-workspace-shell="rail"] #content { padding-top: 20px; }
}

/* Rail chrome. Scoped to the shell flag so the auth screen's header is untouched. */
body[data-workspace-shell="rail"] header .workspace-mode-switcher {
  grid-column: auto;
  padding: 0;
  border-right: 0;
}

/* Left edge: see --rail-inset in tokens.css. This toggle keeps a 1px border
 * (transparent until hover), so it subtracts it rather than paying it twice. */
body[data-workspace-shell="rail"] header .workspace-mode-toggle {
  width: 100%;
  padding: 4px calc(var(--rail-inset) - 1px);
  color: #fff;
}
body[data-workspace-shell="rail"] header .brand-copy b { display: block; font-size: var(--fs-5); letter-spacing: .04em; }
body[data-workspace-shell="rail"] header .brand-copy small { display: block; color: var(--rail-text-dim); font-size: var(--fs-1); }
body[data-workspace-shell="rail"] header .workspace-mode-toggle:not(.single-mode):hover,
body[data-workspace-shell="rail"] header .workspace-mode-toggle[aria-expanded="true"] {
  border-color: var(--rail-line);
  background: rgba(255, 255, 255, .06);
}

body[data-workspace-shell="rail"] header .workspace-account-switcher { min-width: 0; }
body[data-workspace-shell="rail"] header .workspace-account-toggle {
  width: 100%;
  padding: 8px calc(var(--rail-inset) - 1px);
  color: #d7e2e0;
  border-color: var(--rail-line);
  background: rgba(255, 255, 255, .04);
}

/* Long workspace names must not eat the rail: two lines then ellipsis. The
 * full name stays reachable via the toggle's title tooltip and the flyout. */
body[data-workspace-shell="rail"] header .workspace-account-toggle b {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

body[data-workspace-shell="rail"] header .steps {
  display: grid;
  /* Pack items to the top: the default (stretch) spreads rows across the
   * whole rail height, which read as huge dead gaps between menu items. */
  align-content: start;
  gap: 4px;
  /* One full-width column, not the implicit max-content one: an auto column
   * sizes to the longest label, so every row was narrower than the rail and the
   * hover/active pill stopped short of its right edge. */
  grid-template-columns: minmax(0, 1fr);
  padding: 0;
  border: 0;
  background: none;
}

.nav-group-label {
  margin: 14px 0 4px;
  padding: 0 var(--rail-inset);
  color: var(--rail-text-dim);
  font-size: var(--fs-1);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}

body[data-workspace-shell="rail"] header .steps button {
  display: flex;
  align-items: center;
  /* base.css centers the pill's contents for the horizontal top bar. In a
   * vertical list that centering is per-row, so each icon landed at a different
   * x depending on how long its label was. The rail wants one left edge. */
  justify-content: flex-start;
  gap: 11px;
  width: 100%;
  min-height: 44px;
  padding: 0 var(--rail-inset);
  color: var(--rail-text);
  border: 0;
  border-radius: var(--rail-radius);
  background: none;
  font-size: var(--fs-4);
  font-weight: 650;
  text-align: left;
  cursor: pointer;
  transition: background .16s ease, color .16s ease;
}

body[data-workspace-shell="rail"] header .steps button:hover { color: #fff; background: rgba(255, 255, 255, .06); }
body[data-workspace-shell="rail"] header .steps button.active {
  color: #fff;
  background: rgba(10, 189, 163, .22);
}

/* One drawn icon set, not Unicode glyphs. The rail used to mix blocks -- ◉ ◆ ▶
 * from Geometric Shapes, ⌕ ✦ ⚙ from elsewhere -- and every block has its own
 * ink coverage and baseline, so the column read as ragged even once the boxes
 * lined up. These are all 24-unit outlines at one stroke weight, so the optical
 * weight is uniform and `color` still drives them via currentColor.
 *
 * The icon inherits the row's colour rather than carrying its own: at #7d918d
 * it sat at 4.9:1 on --rail-bg while the label beside it sat at 8:1, so every
 * row read as a bright label next to a washed-out mark, and hover/active only
 * lit the label. Inheriting keeps the pair at one tone through every state --
 * the two rules below still override it where the icon is the accent. Stroke
 * is 1.7 rather than 1.8 because the box grew: the dense marks (the four-square
 * grid, the eye) were closing up into solid blobs at 18px. */
.nav-icon {
  width: var(--rail-icon);
  height: var(--rail-icon);
  flex: 0 0 auto;
  color: inherit;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

body[data-workspace-shell="rail"] header .steps button.active .nav-icon { color: var(--brand); }

.nav-badge {
  min-width: 20px;
  height: 20px;
  margin-left: auto;
  padding: 0 6px;
  display: grid;
  place-items: center;
  color: #04302a;
  border-radius: 10px;
  background: var(--brand);
  font-size: var(--fs-1);
}

body[data-workspace-shell="rail"] header .header-actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  /* base.css divides the top bar's actions from the nav with a left padding and
   * a light vertical rule. Stacked in the rail that rule is a stray bright line
   * on dark chrome, and the padding pushed this block off the rail's left edge. */
  padding: 12px 0 0;
  border-left: 0;
  border-top: 1px solid var(--rail-line);
}

/* Platform admin: a first-class rail item, not an account-menu action. Spans the
 * full width above the account row; when hidden it collapses with no empty gap
 * because it is display:none, not an empty grid cell. */
.rail-admin-link {
  display: none;
}
body[data-workspace-shell="rail"] header .rail-admin-link {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 11px;
  min-height: 42px;
  padding: 0 calc(var(--rail-inset) - 1px);
  color: var(--rail-text);
  border: 1px solid var(--rail-line);
  border-radius: var(--rail-radius);
  background: rgba(255, 255, 255, .04);
  font-size: var(--fs-3);
  font-weight: 700;
  text-decoration: none;
}
body[data-workspace-shell="rail"] header .rail-admin-link:hover { color: #fff; background: rgba(255, 255, 255, .09); }
body[data-workspace-shell="rail"] header .rail-admin-link .nav-icon { color: var(--brand); }

/* Flyout anchored to the rail's left edge and sized to spill a little past it,
 * over the content area, rather than being squeezed into 244px. */
body[data-workspace-shell="rail"] header .workspace-account-menu,
body[data-workspace-shell="rail"] header .workspace-mode-menu {
  left: 0;
  width: 264px;
  max-height: min(60vh, 460px);
}

/* ---------- topbar scope controls ---------- */
.title-actions {
  display: flex;
  flex: 0 0 auto;
  flex-wrap: wrap;
  align-items: end;
  justify-content: end;
  gap: 10px;
}

.scope-controls { display: flex; flex-wrap: wrap; justify-content: end; gap: 8px; }

.scope-run-button {
  height: 38px;
  flex: 0 0 auto;
  /* 고정 높이 버튼이라 줄바꿈이 곧 테두리 밖으로 흘러넘치는 것이 된다. */
  white-space: nowrap;
  align-self: end;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--control-radius);
  background: var(--surface);
  color: var(--brand-dark);
  font-size: var(--fs-2);
  font-weight: 800;
  cursor: pointer;
}

.scope-run-button:hover:not([aria-disabled="true"]) {
  border-color: var(--brand);
  background: var(--brand-soft);
}

/* 아직 고를 것이 남았다는 표시이지 고장이 아니다. opacity로 통째로 흐리면 비활성과
   구분이 가지 않으므로, 점선 테두리로 "채워지지 않은 자리"라고 말한다. */
.scope-run-button[aria-disabled="true"] {
  border-style: dashed;
  background: var(--surface-muted);
  color: var(--muted-strong);
  font-weight: 700;
}

/* 말풍선은 버튼 기준으로 띄워 상단바 높이에 관여하지 않는다. 감싸는 span이 없으면
   기준이 페이지가 되어 버튼을 따라다니지 못한다. */
.scope-run {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
  align-self: end;
}

.scope-run-tip {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 30;
  width: max-content;
  max-width: 262px;
  padding: 8px 10px;
  border-radius: var(--control-radius);
  background: var(--text);
  color: #fff;
  font-size: var(--fs-1);
  font-weight: 700;
  line-height: 1.5;
  text-align: left;
  /* .title p와 같은 규칙. 이것이 없으면 "워크스페이스"가 "워 / 크스페이스"로 잘린다. */
  word-break: keep-all;
  overflow-wrap: break-word;
  /* 안 보일 때도 접근성 트리에는 남겨 둔다. visibility로 끄면 aria-describedby가
     가리킬 것이 사라져 스크린리더에서 이유가 다시 없어진다. */
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity .12s ease, transform .12s ease;
  pointer-events: none;
}

.scope-run-tip::after {
  content: '';
  position: absolute;
  right: 16px;
  bottom: 100%;
  border: 5px solid transparent;
  border-bottom-color: var(--text);
}

.scope-run-button:hover + .scope-run-tip,
.scope-run-button:focus-visible + .scope-run-tip,
.scope-run.is-open .scope-run-tip {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .scope-run-tip { transition: none; transform: none; }
}

.scope-select { display: grid; gap: 3px; }
.scope-select > span { color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.scope-select select {
  min-width: 168px;
  height: 38px;
  padding: 0 12px;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--control-radius);
  background: var(--surface);
  font-size: var(--fs-2);
  font-weight: 650;
  cursor: pointer;
}

/* ---------- panels ---------- */
/* 이 파일이 콘솔의 카드를 정의하지만, 정작 카드 안쪽은 오랫동안 8·9·10·11·12px이
 * 섞여 있었다 -- 같은 "패널 안의 줄"이 노출 영역에서는 10px, 출처에서는 8px,
 * 추이에서는 9px이었다. 반경이 층위를 말하려면 층위마다 값이 하나여야 하므로
 * css/tokens.css의 계단을 읽는다. 계단 밖에 남는 것은 두 종류다: 차트 내부의
 * 막대·범례 캡(2~5px, 높이의 절반이라 이미 알약)과 레일 크롬(10px, admin.css와
 * 짝을 맞춘 값). */
.panel {
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}

.dashboard-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch;
  gap: 14px;
  margin-bottom: 14px;
}

/* 개요의 핵심 분석은 반폭 카드 두 장이 아니라 현재 상태 → 경쟁 환경 순서로 읽는다. */
.dashboard-overview-flow {
  display: grid;
  gap: 28px;
  margin-bottom: 22px;
}
.dashboard-overview-stage { min-width: 0; }
.dashboard-overview-kicker {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 9px;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  font-weight: 800;
  letter-spacing: .01em;
}
.dashboard-overview-kicker b {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 24px;
  color: var(--brand-dark);
  border-radius: 999px;
  background: var(--brand-soft);
  font-size: var(--fs-1);
}
.dashboard-overview-stage:not(.is-primary) .dashboard-overview-kicker b {
  color: #4f46a5;
  background: #f0effb;
}
.dashboard-overview-flow .panel {
  min-width: 0;
  padding: 26px 28px;
}
.dashboard-overview-flow .panel-head { margin-bottom: 18px; }
.dashboard-overview-flow .panel-head h2 {
  font-size: clamp(20px, 1.7vw, 22px);
  line-height: 1.3;
}
.dashboard-overview-flow .panel-copy {
  max-width: 760px;
  margin-top: 8px;
  color: var(--muted-strong);
  font-size: var(--fs-3);
}
.dashboard-overview-flow .panel-link,
.dashboard-overview-flow .observation-date { font-size: var(--fs-2); }
.dashboard-overview-flow .trend-tab {
  min-height: 40px;
  padding: 9px 17px;
  font-size: var(--fs-2);
}
.dashboard-overview-flow .panel-empty { font-size: var(--fs-3); }

/* 개요 PRISM은 상세 추이를 되풀이하지 않고 링과 5영역 요약만 한 화면에 묶는다. */
.dashboard-overview-prism .prism-metric-pane.is-compact:not([hidden]) {
  display: grid;
  grid-template-columns: minmax(460px, 1.15fr) minmax(330px, .85fr);
  align-items: center;
  gap: 26px 38px;
}
.dashboard-overview-prism .prism-metric-pane.is-compact[hidden] { display: none; }
.dashboard-overview-prism .trend-tabs.prism-metric-tabs { margin-bottom: 20px; }
.dashboard-overview-prism .prism-metric-tabs .trend-tab { padding: 9px 14px; }
.dashboard-overview-prism.exposure-panel.compact .area-chart.has-labels { max-width: 660px; }
.dashboard-overview-prism .area-outer-name { font-size: 18px; }
.dashboard-overview-prism .area-outer-score { font-size: 28px; }
.dashboard-overview-prism .area-chart.has-labels .area-center-label { font-size: var(--fs-3); }
.dashboard-overview-prism .area-chart.has-labels .area-center-score { font-size: 32px; }
.dashboard-overview-prism .area-chart.has-labels .area-code-mark text { font-size: var(--fs-4); }
.dashboard-overview-prism .prism-metric-area-list { gap: 10px; }
.dashboard-overview-prism .prism-metric-area {
  grid-template-columns: 30px minmax(0, 1fr) auto;
  gap: 12px;
  min-height: 68px;
  padding: 11px 14px;
}
.dashboard-overview-prism .area-code-chip {
  width: 26px;
  height: 26px;
  font-size: var(--fs-2);
}
.dashboard-overview-prism .prism-metric-area span { font-size: var(--fs-4); }
.dashboard-overview-prism .prism-metric-area span small {
  margin-top: 4px;
  font-size: var(--fs-1);
  line-height: 1.45;
}
.dashboard-overview-prism .prism-metric-area strong { font-size: var(--fs-6); }
.dashboard-overview-prism .prism-metric-area strong em { font-size: var(--fs-2); }
.prism-overview-insight {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 13px 15px;
  border-radius: var(--row-radius);
  background: var(--brand-soft);
  color: var(--muted-strong);
  font-size: var(--fs-3);
  line-height: 1.55;
}
.prism-overview-insight span {
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--surface);
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 850;
  white-space: nowrap;
}
.prism-overview-insight strong { color: var(--text); }
.dashboard-overview-prism .prism-help {
  margin: 18px 0 0;
  padding-top: 15px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-2);
}
.dashboard-overview-prism .prism-help summary { font-size: var(--fs-3); }

/* 전폭 경쟁 추이는 차트와 최신값이 개요의 두 번째 주인공으로 읽힐 만큼 키운다. */
.dashboard-overview-competitors .trend-tabs { margin-bottom: 18px; }
.dashboard-overview-competitors .trend-legend {
  gap: 9px 20px;
  margin-bottom: 14px;
  font-size: var(--fs-2);
}
.dashboard-overview-competitors .trend-chart { height: 300px; }
.dashboard-overview-competitors .trend-chart.is-scrollable { height: 312px; }
.dashboard-overview-competitors .trend-summary {
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-top: 16px;
}
.dashboard-overview-competitors .trend-summary-row {
  min-height: 84px;
  padding: 12px 14px;
  font-size: var(--fs-3);
}
.dashboard-overview-competitors .trend-summary-row strong { font-size: 22px; }
.dashboard-overview-competitors .trend-summary-row .trend-note { font-size: var(--fs-1); }
.dashboard-overview-competitors .trend-boundary-legend { font-size: var(--fs-2); }

@container content-col (width < 900px) {
  .dashboard-overview-prism .prism-metric-pane.is-compact:not([hidden]) {
    grid-template-columns: minmax(0, 1fr);
  }
  .dashboard-overview-prism.exposure-panel.compact .area-chart.has-labels { max-width: 620px; }
}

@container content-col (width < 600px) {
  .dashboard-overview-flow { gap: 22px; margin-bottom: 18px; }
  .dashboard-overview-flow .panel { padding: 20px; }
  .dashboard-overview-flow .panel-head { margin-bottom: 16px; }
  .dashboard-overview-flow .panel-aside {
    flex: 1 1 100%;
    width: 100%;
    margin-left: 0;
    text-align: left;
  }
  .dashboard-overview-prism .prism-metric-area { min-height: 62px; }
  .prism-overview-insight { grid-template-columns: minmax(0, 1fr); }
  .prism-overview-insight span { justify-self: start; }
  .dashboard-overview-competitors .trend-tabs { flex-wrap: wrap; }
  .dashboard-overview-competitors .trend-chart { height: 240px; }
  .dashboard-overview-competitors .trend-chart.is-scrollable { height: 252px; }
  /* 1fr의 자동 최소폭이 320px 화면에서 카드 내용만큼 2px 커지지 않게 한다. */
  .diagnostic-row { grid-template-columns: minmax(0, 1fr); min-width: 0; }
  .diagnostic-row > .panel { min-width: 0; max-width: 100%; }
}

/* 같은 층위 차트가 연속 4개면 아무것도 안 읽힌다(5장) -- 보조 차트 두 장은 접어 두고
 * 제목 한 줄로만 자리를 알린다. 삭제가 아니라 접기(R3). */
.dashboard-more {
  margin-bottom: 14px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
}

.dashboard-more > summary {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
}

.dashboard-more > summary::before { content: '▸'; color: var(--muted); }

.dashboard-more[open] > summary::before { content: '▾'; }

.dashboard-more > summary b { font-size: var(--fs-3); }

.dashboard-more > summary small { color: var(--muted); font-size: var(--fs-1); }

.dashboard-more > .dashboard-grid {
  margin: 0;
  padding: 0 14px 14px;
}

/* Panels in a grid row match heights, but their content must stay top-aligned:
 * a two-row 실행 과제 next to a fifteen-row 엔진별 노출률 would otherwise float in
 * the middle of its own card. */
.dashboard-grid > .panel {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.dashboard-grid > .panel > .panel-head { flex: 0 0 auto; }
/* Panels whose body is a single block (an empty-state note, a donut) would
 * otherwise leave a tall void under it when the neighbouring card is long. */
.dashboard-grid > .panel > .panel-empty,
.dashboard-grid > .panel > .sov-wrap {
  flex: 1 1 auto;
  align-content: center;
}
#content > .panel { margin-bottom: 14px; }

.panel-head {
  display: flex;
  /* wrap, not a rigid single row: a narrow card (4열 진단 카드) with a title and an
   * aside pill/link that don't both fit used to squeeze the *title itself* into a
   * two-line wrap ("경쟁사 대비 노출\n률", "인용 출\n처 품질") -- flex's default
   * min-width:auto only refuses to shrink below the widest unbreakable token, so the
   * browser wrapped the Korean title's own text before it ever let the row grow taller.
   * Letting the aside drop to its own line below the title fixes that without touching
   * every panel's aside content. */
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: start;
  gap: 6px 18px;
  margin-bottom: 14px;
}
.panel-head > div:first-child { min-width: 0; }

.panel-head h2 { margin: 0; font-size: var(--fs-5); letter-spacing: -.02em; }
/* 패널 부제를 담는 "?" 배지(.metric-info와 같은 모양) -- 2026-08-19 검토로 제목 밑에
 * 늘 깔려 있던 설명 문단을 걷어낸 자리다. h2는 블록 그대로 두고 배지만 인라인으로
 * 붙인다: h2를 flex로 바꾸면 긴 한국어 제목이 배지와 한 줄을 다투다 단어 중간에서
 * 꺾인다(.panel-head의 flex-wrap 주석이 말하는 그 현상). */
.panel-info { margin-left: 6px; vertical-align: middle; }
.panel-copy {
  margin: 7px 0 0;
  /* U-6 개정(2026-08-19): 정의·주의 문구는 전부 위 "?" 배지로 옮겼다. 여기 남는 것은
   * 매 실행 값이 달라지는 문장(추이 headline)뿐이라, 짚지 않아도 읽히도록 세워 둔다. */
  color: var(--text);
  font-size: var(--fs-2);
  line-height: 1.6;
  word-break: keep-all;
}

/* margin-left:auto, not just space-between: space-between only pushes the aside to the
 * row's far edge while it shares a line with the title. Once .panel-head wraps them onto
 * two lines, a lone second-line flex item sits at the line's start by default -- the auto
 * margin keeps it pinned right on either line. */
.panel-aside { flex: 0 0 auto; margin-left: auto; text-align: right; }
.panel-footer { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }

/* 각주는 읽고 나면 사라져야 하는 글이다. 칠한 박스는 패널 안에 두 번째
   카드가 있는 것처럼 보이게 만들어, 각주가 본문보다 무거워졌다. */
/* 78ch 상한은 되짚어보니 과했다 -- 폭 1300px대 패널에서 그 한도가 실제 렌더 폭의
 * 절반 남짓(~650px)이라, 문장이 그 폭에 안 맞으면 오른쪽 절반은 빈 채로 남고 문장만
 * 다음 줄로 꺾였다("기준선은 ... 평균이 달라 / 점선 위치도 영역별로 다릅니다"). 짧은
 * 줄이 읽기 편하다는 원래 의도와 반대로, 패널 폭을 다 못 쓰는 것으로 읽혔다. 폭 제한
 * 자체를 없애고 패널의 실제 폭(과 word-break:keep-all)에 맡긴다 -- 좁은 칸(4열 진단
 * 카드 등)에서는 어차피 그 폭이 먼저 걸린다. */
.panel-note {
  margin: 14px 0 0;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  line-height: 1.7;
  word-break: keep-all;
}
.panel-note b { display: block; color: var(--muted-strong); }

.panel-empty {
  margin: 0;
  padding: 22px 14px;
  color: var(--muted);
  border: 1px dashed var(--line-strong);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  font-size: var(--fs-2);
  line-height: 1.6;
  text-align: center;
  word-break: keep-all;
}
.panel-empty.compact { padding: 12px; font-size: var(--fs-1); }

.pill {
  display: inline-block;
  padding: 6px 11px;
  color: var(--muted-strong);
  border: 1px solid var(--line);
  border-radius: 9px;
  background: var(--surface-muted);
  font-size: var(--fs-1);
  font-weight: 750;
}
.pill.accent { color: var(--brand-dark); border-color: var(--brand-soft); background: var(--brand-soft); }
/* §8.4 "상대적 덜 추천" 경고 톤 -- .score-panel의 나머지 warning 계열과 같은 토큰. */
.pill.warning { color: var(--warning); border-color: var(--warning-soft); background: var(--warning-soft); }

.text-button {
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 800;
  text-decoration: none;
  white-space: nowrap;
}
.text-button:hover { text-decoration: underline; }

.back-link {
  display: inline-block;
  margin-bottom: 12px;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  font-weight: 700;
  text-decoration: none;
}
.back-link:hover { color: var(--brand-dark); }

.scope-banner {
  margin: 0 0 14px;
  padding: 11px 15px;
  color: var(--warning);
  border: 1px solid #f5dfbf;
  border-radius: var(--row-radius);
  background: var(--warning-soft);
  font-size: var(--fs-2);
}

.run-footnote {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: var(--fs-1);
}
.run-footnote b { font-family: monospace; }

/* Panel header link (dashboard panels launch into their deep page) */
.panel-link {
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 800;
  white-space: nowrap;
  text-decoration: none;
}
.panel-link:hover { text-decoration: underline; }

/* Overview summary strip: compact launchpad cards into the deep pages. This is
 * what makes the dashboard an overview rather than a copy of every page. */
.summary-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
.summary-value { font-size: var(--fs-6); letter-spacing: -.03em; line-height: 1.1; }
.summary-value .delta { margin-left: 7px; font-size: var(--fs-1); }
.summary-sub {
  color: var(--muted-strong);
  font-size: var(--fs-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.summary-empty { margin: 0; color: var(--muted); font-size: var(--fs-4); font-weight: 700; }

/* ---------- hero metric (U-11) ---------- */
/* overview의 주인공 -- AI 노출률 하나가 큰 숫자 + 스파크라인으로 서고, 나머지
 * 지표 셋은 아래 .metric-row.secondary에 한 단 작게 놓인다. 예전에는 네
 * 지표가 .metric-row 한 줄에 같은 무게로 서 있었다. */
.hero-metric {
  display: grid;
  gap: 6px;
  margin-bottom: 10px;
  padding: 20px 22px;
  border: 1px solid #bfe9e1;
  border-radius: var(--card-radius);
  background: var(--brand-soft);
  box-shadow: var(--panel-shadow);
}
.hero-metric:focus-visible { outline: 2px solid var(--brand-dark); outline-offset: 2px; }
.hero-metric-label { color: var(--muted-strong); font-size: var(--fs-2); font-weight: 700; }
.hero-metric-body { display: flex; align-items: baseline; flex-wrap: wrap; gap: 12px; }
.hero-metric-value { font-size: var(--fs-hero); font-weight: 800; letter-spacing: -.03em; line-height: 1.1; }
.hero-metric-spark { flex: 0 0 auto; margin-left: auto; align-self: center; }
.hero-metric-empty { margin: 0; color: var(--muted); font-size: var(--fs-4); font-weight: 700; }
.sparkline-svg { display: block; width: 120px; height: 32px; }
.sparkline-line { stroke: var(--brand-dark); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.sparkline-dot { fill: var(--brand-dark); }

/* ---------- headline metrics ---------- */
.metric-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}
/* secondaryMetricsRow: §10.1로 ARS·ABS가 더해져 다섯 장이 됐다(2026-08-06).
 * 넷 기준 고정 그리드로는 마지막 장이 넘치므로 auto-fit으로 바꿔 폭에 맞춰
 * 줄바꿈한다 -- 카드 수가 다시 바뀌어도 고정 값을 다시 셀 필요가 없다. */
.metric-row.secondary { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }

/* 2026-08-27 복구 커밋에서 아래 마크업과 반원 SVG만 돌아오고 스타일 묶음이
 * 누락됐다. SVG path의 기본 fill(검정)이 콘텐츠 폭 전체로 늘어나 대시보드를
 * 덮었으므로, 상단 네 지표는 이 컴포넌트 안에서 크기와 채움을 완결한다. */
.headline-score-grid {
  display: grid;
  grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
  align-items: stretch;
  gap: 14px;
  margin-bottom: 18px;
}

.headline-score-card {
  min-width: 0;
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}

.headline-score-card[data-availability="insufficient_data"],
.headline-score-card[data-availability="unavailable"] { background: var(--surface-muted); }

.headline-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}
.headline-card-label { display: grid; min-width: 0; gap: 3px; }
.headline-card-label > span {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text);
  font-size: var(--fs-2);
  font-weight: 800;
}
.headline-card-label > small,
.abs-hero-meta small,
.visual-metric-delta small { color: var(--muted); font-size: var(--fs-1); }
.headline-detail-link {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 5px;
  min-height: 28px;
  padding: 4px 7px;
  border-radius: 7px;
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 800;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
}
.headline-detail-link:hover { background: rgba(16, 151, 128, .09); }
.headline-detail-link:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.headline-detail-link span { font-size: var(--fs-3); line-height: 1; }

/* 데스크톱 1×4 구성에서 ABS는 두 칸, 나머지 지표는 한 칸씩을 쓴다.
 * 제목을 반원 왼쪽에 두면 두 칸의 폭이 정보가 아니라 빈 공간으로 소모되므로,
 * 제목 → 반원 → 이전 측정 순의 세로 흐름으로 놓는다. */
.abs-hero-card {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  padding: 18px 24px;
  border-color: #bfe9e1;
  background: linear-gradient(145deg, var(--surface) 0%, var(--brand-soft) 100%);
}
.abs-hero-card .headline-card-head {
  align-self: stretch;
  padding-top: 0;
}
.abs-hero-card .headline-card-label > span { font-size: var(--fs-5); letter-spacing: -.02em; }
.abs-hero-figure {
  display: grid;
  flex: 1 1 auto;
  align-content: center;
  min-width: 0;
  justify-items: center;
  gap: 0;
}
.abs-gauge-wrap { width: min(100%, 350px); min-width: 0; }
.abs-hero-meta {
  display: grid;
  justify-items: center;
  gap: 4px;
  width: min(100%, 350px);
  min-width: 0;
  min-height: 0;
  margin-top: -2px;
  text-align: center;
}
.abs-hero-meta > span { overflow-wrap: anywhere; }
.abs-hero-meta .delta { font-size: var(--fs-3); }

.semicircle-gauge-frame {
  position: relative;
  isolation: isolate;
  container-type: inline-size;
  width: 100%;
}
.semicircle-gauge {
  display: block;
  width: 100%;
  height: auto;
  margin-inline: auto;
  overflow: visible;
}
.semicircle-gauge-track,
.semicircle-gauge-zone { fill: none; }
.semicircle-gauge-track {
  stroke: #dce7e4;
  stroke-width: 16;
  stroke-linecap: round;
}
.semicircle-gauge-zone {
  stroke-width: 11;
  stroke-linecap: butt;
}
.semicircle-gauge-needle {
  stroke: var(--text);
  stroke-width: 3;
  stroke-linecap: round;
}
.semicircle-gauge-hub { fill: var(--text); }
.semicircle-gauge-tick { fill: var(--muted); font-size: 11px; font-weight: 700; }
.semicircle-gauge-zone-name { font-size: 9px; font-weight: 850; letter-spacing: .015em; }
.semicircle-gauge-zone-range { fill: var(--muted); font-size: 8px; font-weight: 700; }
.semicircle-gauge-zone-label:not(.is-current) { opacity: .78; }
.semicircle-gauge-zone-label.is-current .semicircle-gauge-zone-name {
  font-size: 10px;
  paint-order: stroke;
  stroke: var(--surface);
  stroke-width: 2px;
  stroke-linejoin: round;
}
.semicircle-gauge-score {
  position: absolute;
  z-index: 1;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: .18em .38em;
  border: 1px solid rgba(167, 218, 207, .2);
  border-radius: .4em;
  background: rgba(227, 245, 240, .38);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 2px 8px rgba(15, 75, 65, .025);
  color: var(--text);
  font-size: 34px;
  font-size: 9.444cqw;
  font-weight: 850;
  line-height: 1.1;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
}
.semicircle-gauge-band { fill: var(--muted-strong); font-size: 12px; font-weight: 850; letter-spacing: .04em; }
.semicircle-gauge.is-empty,
.semicircle-gauge-score.is-empty { opacity: .72; }

.visual-metric-card { display: flex; flex-direction: column; gap: 12px; }
.visual-metric-card .headline-card-label > span {
  font-size: var(--fs-5);
  letter-spacing: -.02em;
}
.visual-metric-card .headline-card-label .metric-info {
  width: 18px;
  height: 18px;
  font-size: 11px;
}
.visual-metric-card[data-kind="avs"] { border-color: #bfe9e1; background: var(--brand-soft); }
.visual-metric-value {
  margin-top: 4px;
  font-size: clamp(27px, 2.3vw, 36px);
  line-height: 1;
  letter-spacing: -.04em;
}
.visual-metric-value em { margin-left: 2px; font-size: var(--fs-2); font-style: normal; letter-spacing: 0; }
.visual-metric-delta { display: grid; gap: 2px; min-height: 36px; font-size: var(--fs-1); }
.visual-metric-rail {
  height: 8px;
  overflow: hidden;
  border-radius: 999px;
  background: #dce7e4;
}
.visual-metric-rail i { display: block; height: 100%; border-radius: inherit; background: var(--brand); }
.visual-metric-card[data-kind="ars"] .visual-metric-rail i { background: #e8894d; }
.visual-metric-card[data-kind="sov"] .visual-metric-rail i { background: #4d8fcb; }
.visual-metric-callout {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  align-items: start;
  gap: 8px;
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.visual-metric-callout > i {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--surface);
  color: var(--brand-dark);
  font-style: normal;
  font-weight: 850;
}
.visual-metric-callout p { margin: 1px 0 0; color: var(--muted-strong); font-size: var(--fs-1); line-height: 1.5; }

@container content-col (width < 1050px) {
  /* 네 카드를 억지로 좁히지 않고 ABS 한 행 + 지표 세 칸으로 바꾼다. */
  .headline-score-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .abs-hero-card { grid-column: 1 / -1; }
}

@container content-col (width < 760px) {
  .headline-score-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .visual-metric-card:last-child { grid-column: 1 / -1; }
}

@container content-col (width < 600px) {
  .headline-score-grid { grid-template-columns: minmax(0, 1fr); }
  .abs-hero-card,
  .visual-metric-card:last-child { grid-column: auto; }
  .headline-score-card { padding: 16px; }
}

.metric-card {
  display: grid;
  gap: 5px;
  align-content: start;
  min-height: 106px;
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
}
/* Flat tints, not gradients: the tone only has to separate these two cards from
 * the plain ones, and a diagonal ramp across a 106px card read as uneven fill
 * rather than as emphasis. The border still carries most of the distinction. */
.metric-card[data-tone="primary"] { border-color: #bfe9e1; background: var(--brand-soft); }
.metric-card[data-tone="accent"] { border-color: #cfe2f5; background: #eef5fd; }
.metric-card[data-availability="insufficient_data"],
.metric-card[data-availability="unavailable"] { background: var(--surface-muted); }

.metric-label { display: flex; align-items: center; gap: 6px; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
/* U-5 개정(2026-08-09): 지표 설명은 카드 전체가 아니라 이 배지에서만 뜬다 -- 어디를
 * 눌러야 하는지 보이도록. 툴팁 자체는 chart-tooltip.js의 is-note 변형(줄바꿈)으로 뜬다. */
.metric-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  color: var(--muted);
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  cursor: pointer;
}
.metric-info:hover, .metric-info:focus-visible { border-color: var(--brand); color: var(--brand-dark); }
.metric-info:focus-visible { outline: 2px solid var(--brand-dark); outline-offset: 2px; }
.metric-value { font-size: var(--fs-6); letter-spacing: -.03em; line-height: 1.1; }
.metric-card[data-availability="insufficient_data"] .metric-value { color: var(--muted); font-size: var(--fs-5); }
.metric-meta { display: grid; gap: 4px; margin: 0; }
.metric-meta small { color: var(--muted); font-size: var(--fs-1); line-height: 1.5; word-break: keep-all; }

/* 업계 기준선=50점 지수. 원점수(.metric-value)보다 작게 두어 어느 쪽이 그 카드의
   대표값인지 흔들지 않으면서, "이 숫자가 좋은 건지"에 답하는 한 줄을 붙인다. */
.metric-benchmark { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.metric-benchmark b { font-size: var(--fs-3); font-weight: 800; letter-spacing: -.02em; color: var(--brand-dark); }
.metric-benchmark em { color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 750; }
.metric-benchmark small { color: var(--muted); font-size: var(--fs-1); line-height: 1.5; word-break: keep-all; }
/* "업계 평균의 3.8배" -- 지수 옆에 붙는 칩. 색만 좋고 나쁨을 말하고 숫자는 그대로 배수다
   (ARS처럼 낮을수록 좋은 지표는 배수가 커질수록 down 톤이 붙는다). */
.metric-multiple, .score-multiple {
  display: inline-block; font-style: normal; font-weight: 800; font-size: var(--fs-1);
  padding: 1px 7px; border-radius: 999px; white-space: nowrap;
}
/* 색은 delta 칩과 같은 토큰(--pos/--neg)을 쓴다 -- 같은 화면에서 "좋아짐"이 두 가지
   초록으로 보이면 안 된다. 배경은 그 토큰을 그대로 옅게 깐다(color-mix, 폴백 없이도
   지원되는 브라우저 범위). */
.metric-multiple.up, .score-multiple.up {
  color: var(--pos); background: color-mix(in srgb, var(--pos) 12%, transparent);
}
.metric-multiple.down, .score-multiple.down {
  color: var(--neg); background: color-mix(in srgb, var(--neg) 12%, transparent);
}
.score-multiple { margin-right: 6px; }

.delta { font-size: var(--fs-1); font-style: normal; font-weight: 800; }
.delta.up { color: var(--pos); }
.delta.down { color: var(--neg); }
.delta.flat { color: var(--muted); font-weight: 700; }

/* ---------- exposure areas ---------- */
.area-chart-wrap {
  display: grid;
  /* 고리는 제 크기만큼만 쓰고 남는 가로는 라벨이 받는다. 고리 칸이 1fr이던 동안에는
   * 340px짜리 도넛이 700px 칸 한가운데 떠서 패널 가로 절반이 빈 칸이었고, 세로로는
   * 라벨 다섯 장이 쌓여 고리보다 두 배 높은 탓에 위아래로도 빈 칸이 남았다. */
  grid-template-columns: minmax(260px, 380px) minmax(0, 1fr);
  /* stretch, not center: 카드를 펼치면 오른쪽 열이 고리의 몇 배로 자라고, 가운데
   * 정렬이던 동안에는 고리가 그 한복판에 떠서 위아래로 화면 하나만큼 빈 칸이 생겼다.
   * 늘어난 칸 안에서 고리를 sticky로 붙여 두면, 펼친 카드를 읽어 내려가는 동안에도
   * 지금 읽는 조각이 어느 조각인지 옆에 남는다. */
  align-items: stretch;
  gap: 24px;
  margin-bottom: 2px;
}

/* 고리의 폭이 곧 0–100 눈금이다. 작게 그리면 평균과 점수의 반지름 차이가 몇 픽셀로
 * 눌려, 어느 쪽이 앞서는지 채도로 갈라 놔도 띠가 너무 얇아 안 보인다. 오른쪽 라벨
 * 열이 어차피 이만큼 높으니 남는 세로를 고리에 준다. */
.area-chart { position: sticky; top: 16px; display: block; width: 100%; max-width: 380px; margin: 0 auto; overflow: visible; }

/* 라벨을 단 고리는 제 이름을 들고 있으므로 옆에 붙어 다닐 목록이 없다 -- 스크롤을
 * 따라다닐 이유도 함께 사라진다. 이 상한은 고리가 아니라 상자(라벨 여백까지 든
 * viewBox) 기준이다: 560px이던 동안 지름은 250px 남짓이었고, 0–100 눈금 전체가
 * 60px짜리 띠에 눌려 60점과 100점이 같은 두께로 보였다. */
.area-chart.has-labels { position: static; max-width: 720px; }
/* 고리(.area-chart-stage) + 그 밑 각주(점선의 뜻, .panel-note)를 한 열로 묶는 상자 --
 * exposurePanel의 .area-chart-wrap.split은 2칸(고리 열·상세 패널 열)짜리 grid라, 이
 * 상자가 없으면 고리와 각주가 형제 grid item이 되어 각주가 둘째 칸(상세 패널 자리)에
 * 잘못 앉는다. */
.area-chart-column { display: flex; flex-direction: column; min-width: 0; }
/* flex, not `place-content: center`: 그 그리드는 트랙을 내용 크기로 줄여, width:100%인
 * SVG가 제 고유 크기(300px)로 주저앉는다. */
.area-chart-stage.centered { display: flex; align-items: center; justify-content: center; min-width: 0; }
.area-chart-stage.centered > .area-chart { width: 100%; }
.exposure-panel.compact .area-chart-column { flex: 1 1 auto; }
.area-chart-column > .area-chart-stage.centered { flex: 1 1 auto; }
/* 대시보드 요약 카드는 그리드 반 칸에 선다 -- 거기서 720px 상한은 어차피 닿지 않고,
 * 옆에 상세 패널도 없으므로 고리만 제 칸을 채우면 된다. */
.exposure-panel.compact .area-chart.has-labels { max-width: 560px; }

/* 조각 바깥의 이름과 점수. 이름은 조각 색이 아니라 본문 색으로 둔다 -- 다섯 색이
 * 글자에까지 오면 고리와 글자가 같은 세기로 경쟁해 어느 쪽도 먼저 읽히지 않는다.
 * 색이 하는 말(어느 조각인가)은 이미 배지와 위치가 하고 있다. */
/* 글자 크기는 viewBox 안에서 px 고정이다 -- 고리 지름이 400으로 커진 만큼 같이
 * 키우지 않으면 이름과 점수가 고리 옆에서 잔글씨로 눌린다. */
.area-outer-name { fill: var(--muted-strong); font-size: var(--fs-4); font-weight: 750; }
.area-outer-score { fill: var(--text); font-size: var(--fs-6); font-weight: 850; letter-spacing: -.03em; }
.area-outer-label.is-empty .area-outer-score { fill: var(--muted); font-size: var(--fs-4); font-weight: 700; }
/* 원점수가 딸린 라벨은 짚으면(툴팁) 뜬다 -- area-rail-nobase/nocover와 같은 cursor:help
   관례. 기본 포커스 사각형은 지우고, 대신 점수 글자에 밑줄로 "짚을 수 있다"를 알린다. */
.area-outer-label[tabindex] { cursor: help; }
.area-outer-label[tabindex]:focus { outline: none; }
.area-outer-label[tabindex]:hover .area-outer-score,
.area-outer-label[tabindex]:focus-visible .area-outer-score {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
/* 고른 영역의 이름만 본문 색으로 올라온다. 나머지 넷을 흐리게 만들지는 않는다 --
 * 다섯을 견주라고 그린 고리에서 넷을 죽이면 고른 값을 견줄 대상이 사라진다. */
.area-outer-label.is-selected .area-outer-name { fill: var(--text); font-weight: 850; }
.area-sector { cursor: pointer; transition: filter .16s ease; }
.area-sector:hover, .area-sector:focus-visible { filter: brightness(1.06) drop-shadow(0 6px 10px rgba(31, 41, 51, .18)); }
.area-sector.is-selected { filter: drop-shadow(0 3px 9px rgba(31, 41, 51, .3)); }
/* tabindex가 붙은 SVG 도형의 기본 포커스 링은 **도형이 아니라 바운딩 박스**를 두른다 --
 * 부채꼴 하나를 클릭하면 그 조각을 감싸는 검은 네모가 고리 위에 얹혀, 조각을 고른 것이
 * 아니라 뭔가 깨진 것으로 보였다. 링을 끄고, 키보드 포커스는 조각 윤곽선으로 표시한다
 * (마우스 클릭은 :focus-visible에 안 걸리므로 선택 표시는 .is-selected가 맡는다).
 * 세 종류가 다 tabindex를 갖는다: 조각·평균 미달 몫·미측정 조각(툴팁을 읽히려고). */
.area-sector:focus,
.area-shortfall:focus,
.area-empty:focus { outline: none; }
.area-sector:focus-visible,
.area-shortfall:focus-visible {
  stroke: var(--text);
  stroke-width: 2.5;
  paint-order: stroke fill;
}
.area-empty:focus-visible .area-track { stroke: var(--text); stroke-width: 2.5; }
/* 각 영역의 0–100 부채꼴 트랙. 영역 자체는 원형 차트의 원래 모양을 유지한다. */
.area-track { fill: var(--surface-soft); }
.area-empty-label { fill: var(--muted); font-size: var(--fs-1); font-weight: 800; }
.area-ring { stroke: var(--line); stroke-width: 1; }
.area-grid-ring { stroke: rgba(31, 41, 51, .16); stroke-width: 1; pointer-events: none; }
/* 부채꼴 사이에 각도 여백을 두지 않고 그 위에 고정 폭 직선을 얹는다. 그래서 중심에서
 * 바깥으로 가도 경계가 넓어지지 않고 처음부터 끝까지 같은 굵기의 막대로 보인다. */
.area-boundary {
  stroke: var(--surface);
  stroke-width: 5;
  stroke-linecap: butt;
  pointer-events: none;
}
/* 평균에 못 미친 몫. 트랙과는 확실히 다르되 영역 색과는 경쟁하지 않아야, 빈 자리가
 * 아니라 '여기까지가 평균'으로 읽힌다. */
.area-shortfall { pointer-events: auto; }
/* 평균선은 각 PRISM 조각과 같은 색 계열의 고채도 색이다. 흰 케이싱이 먼저 깔려
 * 옅은 트랙과 진한 채움 모두에서 색이 탁해지지 않고, 굵어진 점선이 기준선으로 선다. */
.area-baseline-casing { stroke: #fff; stroke-width: 6; stroke-opacity: .98; pointer-events: none; }
.area-baseline {
  stroke: var(--area-baseline-color, #087e67);
  stroke-width: 3;
  stroke-dasharray: 7 4;
  stroke-linecap: round;
  pointer-events: none;
  filter: drop-shadow(0 0 1.5px color-mix(in srgb, var(--area-baseline-color, #087e67) 60%, transparent));
}
.area-center-label { fill: var(--muted); font-size: var(--fs-1); font-weight: 800; }
.area-center-score { fill: var(--text); font-size: var(--fs-6); font-weight: 850; letter-spacing: -.04em; }
.area-center-delta { fill: var(--pos); font-size: var(--fs-1); font-weight: 800; }
/* 가운데 값이 지수일 때 원점수는 짚으면(툴팁) 뜬다 -- area-outer-label과 같은 관례. */
.area-center-score[tabindex] { cursor: help; }
.area-center-score[tabindex]:focus { outline: none; }
.area-center-score[tabindex]:hover,
.area-center-score[tabindex]:focus-visible {
  text-decoration: underline dotted;
  text-underline-offset: 4px;
}
/* 구멍이 커진 만큼 가운데 세 줄도 커진다. 라벨 모드에만 거는 이유는 라벨 없는 고리가
 * 지름 260을 그대로 쓰기 때문이다 -- 거기에 34px를 넣으면 구멍 밖으로 넘친다. */
.area-chart.has-labels .area-center-label { font-size: var(--fs-2); }
.area-chart.has-labels .area-center-score { font-size: var(--fs-6); }
.area-chart.has-labels .area-center-delta { font-size: var(--fs-2); }

/* 조각마다 그 영역의 PRISM 글자를 바깥에 단다 -- 고리와 카드를 잇는 것이 색뿐이면
 * 다섯 조각을 읽을 때마다 카드 다섯 장을 색으로 되짚어야 한다. pointer-events를 끄지
 * 않으면 배지가 조각의 hover·클릭을 가로챈다(조각이 곧 드릴다운 버튼이다). */
.area-code-mark { pointer-events: none; }
.area-code-mark circle { stroke: #fff; stroke-width: 1.5; }
.area-code-mark text { fill: #fff; font-size: var(--fs-1); font-weight: 850; letter-spacing: -.02em; }
.area-code-mark.is-empty circle { fill: var(--line-strong); }
.area-chart.has-labels .area-code-mark circle { stroke-width: 2; }
.area-chart.has-labels .area-code-mark text { font-size: var(--fs-4); }
/* 지금 옆 패널에 서 있는 영역. 배지에 테를 두르는 쪽이 조각을 물들이는 것보다 낫다 --
 * 조각 색은 이미 영역 정체를 말하고 있어서, 거기에 상태까지 얹으면 둘이 섞인다. */
.area-code-mark.is-selected circle { stroke: var(--text); stroke-width: 2.5; }

/* 고리(고르는 자리) 옆에 상세 패널(고른 것을 보는 자리). 카드 다섯 장을 옆 열에
 * 세우던 동안에는 하나를 펼칠 때마다 그 열만 자라 고리 옆이 세로로 비었는데, 이제
 * 한 번에 한 장만 서므로 열 높이가 고리와 비슷한 자리에 묶인다. 고리 쪽을 조금 더
 * 넓게 두는 것은 그쪽이 눈금(0–100)을 들고 있어서다. */
.area-chart-wrap.split {
  grid-template-columns: minmax(420px, 1.2fr) minmax(300px, 1fr);
  /* stretch, not start: 영역마다 축 개수와 질문 수가 달라 패널 높이가 들쭉날쭉한데,
   * 내용 높이에 맞춰 두면 짧은 영역을 고를 때마다 오른쪽 칸 아래가 통째로 비어
   * 상자가 허공에 떠 보인다. 칸을 채우고 글은 위에서부터 쌓는다. */
  align-items: stretch;
  gap: 22px;
}
/* 왼쪽 칸이 고리 대신 "아직 응답이 없다"는 한 줄짜리 안내(.panel-empty)로 대체될
 * 때는 위 stretch를 그대로 물려받으면 안 된다 -- 이 안내는 오른쪽에서 고른 영역이
 * 바뀔 때마다 같이 커지고 작아져서(오른쪽 상세 칸의 축 개수·대표 질문 줄바꿈에 그대로
 * 딸려간다), 똑같은 한 문장이 매번 다른 크기의 상자에 담긴 것처럼 보인다. 안내 자체는
 * 어느 영역을 골라도 내용이 안 바뀌므로 제 내용만큼의 고정 높이를 갖고, 고리가 있었다면
 * 차지했을 자리(대략 380px 정사각형)를 흉내 내 상자 크기가 늘 같게 만든다. */
.area-chart-wrap.split > .panel-empty {
  align-self: start;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 380px;
}
/* 색은 여기서 정하지 않는다 -- 고리의 sector 색과 반드시 같아야 하므로 렌더가
 * SERIES_COLORS에서 인라인으로 찍는다. 예전엔 이 자리에 4영역 시절 키(need /
 * attribute / trust)로 건 규칙이 있었는데, 7.1에서 PRISM 키로 바뀐 뒤로는 어느
 * 영역도 걸리지 않아 다섯 점이 전부 브랜드색으로 떨어졌다. */
/* 점이 아니라 글자다 -- 고리 바깥 배지와 같은 P·R·I·S·M을 들고 같은 색을 입는다.
 * 색만 같던 동안에는 카드가 어느 조각인지 말하려면 눈이 색을 왕복해야 했다. */
.area-code-chip {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  font-size: var(--fs-1);
  font-style: normal;
  font-weight: 850;
  letter-spacing: -.02em;
}
/* PRISM 영역이 안 붙은 질문 -- 칩을 지우면 그 줄만 들여쓰기가 빠져 열이 어긋난다. */
.area-code-chip.is-unclassified { background: var(--surface-muted); color: var(--muted); }
.baseline-chip { font-weight: 800; }
.gap-up { color: var(--pos); font-weight: 850; }
.gap-down { color: var(--neg); font-weight: 850; }

/* ---- 고른 영역 하나가 서는 패널 ---- */
.area-detail-pane {
  min-width: 0;
  padding: 16px 18px 18px;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-muted);
}
.area-pane-caption {
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--fs-1);
  font-weight: 700;
  word-break: keep-all;
}
.area-detail-head { display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: start; gap: 9px; }
.area-detail-name { display: grid; gap: 2px; color: var(--text); font-size: var(--fs-4); font-weight: 850; }
.area-detail-name small { color: var(--muted); font-size: var(--fs-1); font-weight: 650; word-break: keep-all; }
.area-detail-head strong { font-size: var(--fs-6); line-height: 1; letter-spacing: -.03em; }
.area-detail-head strong em { margin-left: 3px; color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 700; }
.area-detail-sample { margin: 10px 0 8px; color: var(--muted); font-size: var(--fs-1); font-weight: 650; }
.area-detail-card > .compare-bar { margin-bottom: 7px; }
.area-compare-note {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 14px;
  color: var(--text);
  font-size: var(--fs-2);
  font-weight: 650;
}
/* 기준선이 없는 이유는 한 문장이라 양끝 정렬할 짝이 없다 -- flex인 채로 두면 문장이
 * 통째로 왼쪽에 붙고 남는 자리가 어색하게 비어, 값이 빠진 줄로 보인다. */
.area-compare-note.is-nobase { display: block; line-height: 1.55; word-break: keep-all; }
/* 점수 자리에서 내려온 참고 값(신뢰성의 인용 출처 품질). 영역 점수와 나란히 서면 어느 쪽이
 * 점수인지 갈리지 않으므로, 왼쪽 띠로 한 층 들여쓰고 글자를 낮춘다 -- 붉게 칠하지 않는 것은
 * 이 값이 문제가 아니라 다른 종류의 값이기 때문이다. */
.area-diagnostic-note {
  display: block;
  margin: -6px 0 14px;
  padding-left: 10px;
  border-left: 2px solid var(--line-strong);
  color: var(--muted);
  font-size: var(--fs-1);
  font-weight: 650;
  line-height: 1.55;
  word-break: keep-all;
}
.area-diagnostic-note b { display: block; color: var(--muted-strong); font-weight: 800; }
/* 지금 값(compareBar) 옆에 회차별 흐름을 작게 얹는다 -- trendPanel의 214px 도표를
 * 그대로 쓰면 상세 카드 하나가 화면 절반을 먹으므로 이 안에서만 낮춘다. */
.area-trend-caption { margin: 0 0 6px; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.area-trend-mini { margin-bottom: 14px; }
.area-trend-mini .trend-chart { height: 120px; }
/* 점수를 만든 것이 무엇인지 한 문장. 아래 축 막대를 말로 옮긴 것이 아니라 어느 축이
 * 끌어올리고 어느 축이 끌어내렸는지를 짚는다 -- projection이 수치에서 직접 지은
 * 문장이라 옆에 찍힌 숫자와 어긋날 수 없다. */
.area-detail-insight {
  margin: 0 0 14px;
  padding: 10px 12px;
  border-radius: var(--row-radius);
  background: var(--surface);
  /* U-6: this is the generated "what made this score move" sentence (see the
   * comment above), not a caption -- it was 12px gray, exactly the pattern
   * §2.1 complains about (real body content pinned to secondary styling). */
  color: var(--text);
  font-size: var(--fs-3);
  line-height: 1.65;
  word-break: keep-all;
}
.area-detail-card > .text-button { margin-top: 12px; }

/* ---- 다섯을 한 축에서 견주는 레일 ---- */
/* 줄마다 같은 그리드 열을 쓰므로 막대의 0점과 100점이 다섯 줄에서 같은 x에 선다 --
 * 카드 다섯 장으로 흩어 놓던 동안에는 카드 폭이 제각각이라 막대끼리 견줄 수 없었고,
 * 고리는 조각마다 각도가 달라 애초에 그 일을 못 한다. */
.area-rail { display: grid; gap: 4px; margin-top: 16px; }
.area-rail-row {
  display: grid;
  grid-template-columns: 22px 132px minmax(80px, 1fr) 86px 68px 54px;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 1px solid transparent;
  border-radius: var(--row-radius);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.area-rail-row:hover { background: var(--surface-muted); }
.area-rail-row.is-selected { border-color: var(--line-strong); background: var(--surface-muted); }
.area-rail-name { display: grid; gap: 1px; color: var(--muted-strong); font-size: var(--fs-2); font-weight: 800; word-break: keep-all; }
.area-rail-name small { color: var(--muted); font-size: var(--fs-1); font-weight: 650; }
.area-rail-bar { min-width: 0; }
.area-rail-base { color: var(--muted); font-size: var(--fs-1); font-weight: 700; white-space: nowrap; }
/* 지수를 세운 줄에서 원점수와 업계 평균이 한 쌍으로 남는 칸. */
.area-rail-raw { color: var(--muted); font-size: var(--fs-1); font-weight: 700; white-space: nowrap; }
.area-rail-nobase { color: var(--muted); font-weight: 650; cursor: help; }
/* 미측정 영역의 표본 수 자리 -- 두 줄로 늘리면 다섯 줄 레일의 행 높이가 이 한 영역 때문에 전부 자란다. */
.area-rail-nocover { color: var(--muted-strong); font-weight: 700; cursor: help; }
/* 측정되지 않은 줄. 지우지 않는 것은 다섯 영역 중 무엇이 안 재졌는지가 그 자체로 읽을 값이어서다. */
.area-rail-row.is-uncovered { opacity: .72; }
.area-rail-empty { color: var(--muted); font-size: var(--fs-1); font-weight: 650; }
.area-rail-row > strong { font-size: var(--fs-5); line-height: 1; text-align: right; }
.area-rail-row > strong em { margin-left: 2px; color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 700; }
.area-rail-row > em { font-size: var(--fs-2); font-style: normal; font-weight: 800; text-align: right; }

/* 점수를 만든 축과 대표 질문. 카드마다 <details>로 접혀 있던 동안에는 손잡이를 눌러야
 * 나왔고, 다섯 장 중 어느 것도 펴지 않은 화면이 기본값이었다 -- 정작 점수가 무엇으로
 * 만들어졌는지는 아무 데도 없는 셈이었다. 이제 고른 영역 하나는 항상 펴져 있다. */
.area-detail-empty { margin: 0; color: var(--muted); font-size: var(--fs-1); font-weight: 650; word-break: keep-all; }
.area-detail-empty .text-button { margin-left: 4px; }
.area-monitoring-score { margin: 0 0 8px; color: var(--muted); font-size: var(--fs-1); font-weight: 700; }
/* 질문 상태는 알약이 아니라 점 하나다 -- 알약은 분류 표지로 읽혀 무엇이 노출됐다는
 * 것인지 말해 주지 못했고, 두 줄짜리 미리보기 옆에서 질문보다 먼저 눈에 들어왔다.
 * 뜻은 목록 머리에서 한 번만 말하고, 채운 점은 그 영역 색을 그대로 쓴다. */
.area-question-caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin: 12px 0 0;
  color: var(--muted-strong);
  font-size: var(--fs-1);
  font-weight: 800;
}
.area-question-caption small { display: flex; align-items: center; gap: 4px; color: var(--muted); font-weight: 700; }
.area-question-caption small .q-dot { margin-left: 4px; }
.q-dot {
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
}
.q-dot.is-on { border-color: transparent; background: var(--brand); }

/* 우리 점수는 채운 길이, 산업 평균은 그 위에 선 눈금. 둘이 같은 축에 있으니
 * 어느 쪽이 앞서는지가 숫자를 읽기 전에 먼저 보인다. */
.compare-bar {
  position: relative;
  display: block;
  height: 10px;
  border-radius: 5px;
  background: #e6eded;
}
.compare-bar[data-compact="1"] { height: 8px; }
.compare-bar > i { display: block; height: 100%; border-radius: inherit; background: var(--brand); }
.compare-baseline {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--text);
  box-shadow: 0 0 0 1.5px #fff;
}
.compare-bar.is-behind > i { opacity: .55; }

.legend { display: flex; flex-wrap: wrap; justify-content: end; gap: 12px; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.legend span { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
.legend i { display: inline-block; width: 16px; height: 4px; border-radius: 2px; }
/* 고리가 채도로 갈라 놓은 두 구간을 그대로 받는다. 색은 영역마다 다르므로 견본은
 * 대표색 하나로 두고, 말하는 것은 색이 아니라 진하기다. */
.legend-over { background: var(--brand); }
.legend-under { background: var(--brand); opacity: .3; }
.legend-baseline { height: 0 !important; border-top: 2px dashed #087e67; border-radius: 0 !important; }

/* ---------- meters ---------- */
.meter {
  display: block;
  height: 7px;
  border-radius: 4px;
  background: #e6eded;
  overflow: hidden;
}
.meter.compact { height: 6px; }
.meter i { display: block; height: 100%; border-radius: inherit; background: var(--brand); }

.stacked-bar { display: flex; height: 10px; margin: 8px 0 6px; border-radius: 5px; overflow: hidden; }
.stacked-bar i { height: 100%; }
.stacked-bar i.positive { background: var(--pos); }
.stacked-bar i.neutral { background: #c8d1d1; }
.stacked-bar i.negative { background: #e07a63; }

.sentiment-legend { display: flex; flex-wrap: wrap; gap: 12px; color: var(--muted-strong); font-size: var(--fs-2); }
.sentiment-legend span { display: flex; align-items: center; gap: 4px; }
.sentiment-legend i { width: 7px; height: 7px; border-radius: 50%; }
.sentiment-legend i.positive { background: var(--pos); }
.sentiment-legend i.neutral { background: #c8d1d1; }
.sentiment-legend i.negative { background: #e07a63; }

/* ---------- chart tooltip ---------- */
/* docs/plans/ROADMAP.md §2.1 V-4/U-9: shared floating tooltip for radial
 * sectors, trend-line points and donut slices -- js/views/chart-tooltip.js
 * shows/hides/positions this single element via data-tooltip attributes that
 * charts.js writes onto each shape, replacing native <title> (slow, unstyled,
 * invisible on touch). position:fixed because the tooltip is appended to
 * <body> and positioned from getBoundingClientRect(), which is viewport- not
 * document-relative. transform lifts it above the hovered/focused shape and
 * centers it horizontally without the JS having to know the tooltip's own
 * (post-render) width/height. */
.chart-tooltip {
  position: fixed;
  z-index: 40;
  transform: translate(-50%, calc(-100% - 10px));
  max-width: min(280px, calc(100vw - 24px));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  border-radius: var(--control-radius);
  padding: 6px 10px;
  color: #fff;
  background: var(--muted-strong);
  font-size: var(--fs-1);
  line-height: var(--lh-tight);
  box-shadow: 0 10px 24px rgba(31, 41, 51, .22);
  pointer-events: none;
}
.chart-tooltip[hidden] { display: none; }
/* U-5 개정(2026-08-09): 지표 카드 "?" 배지처럼 한 문장짜리 설명은 위 기본값(한 줄
 * 말줄임)에 뒷부분이 잘렸다 -- data-tooltip-wrap을 단 대상만 줄바꿈으로 전체를 보인다. */
.chart-tooltip.is-note {
  white-space: normal;
  text-overflow: clip;
  overflow: visible;
  max-width: min(260px, calc(100vw - 24px));
  text-align: left;
}

/* ---------- trend ---------- */
.trend-legend { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-bottom: 10px; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.trend-legend span { display: flex; align-items: center; gap: 5px; }
.trend-legend i { display: inline-block; width: 14px; height: 3px; border-radius: 2px; }
/* 축 라벨이 날짜 + 시각 두 줄이 되며 아래 여백이 12px 늘었다. 그만큼 상자를 키워
 * 선이 그려지는 면적은 예전 그대로 둔다. */
.trend-chart { height: 214px; }
.trend-chart-svg { display: block; width: 100%; height: 100%; overflow: visible; }

/* 회차가 쌓이면 도표가 상자보다 넓어진다(svg의 min-width). 좁히는 대신 흘려보내야
 * 시차 비례가 살아남는다 -- 폭이 고정이면 점이 겹치지 않게 두는 최소 몫이 축의
 * 절반을 먹어, 오래된 구간이 통째로 등간격으로 뭉개진다. */
.trend-chart.is-scrollable {
  /* 가로 스크롤바가 상자 안쪽을 먹는다. 높이를 그만큼 키우지 않으면 축 라벨의
   * 아랫줄(수행 시각)이 스크롤바에 가려진다. */
  height: 226px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.trend-chart.is-scrollable:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--control-radius);
}
.trend-chart.is-scrollable::-webkit-scrollbar { height: 8px; }
.trend-chart.is-scrollable::-webkit-scrollbar-thumb {
  border-radius: 999px;
  background: var(--border-strong, #c8d1d1);
}
.grid-line { stroke: #e9efef; stroke-width: 1; stroke-dasharray: 3 5; }
.trend-line { stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; }
.trend-dot { fill: #fff; stroke-width: 2.5; }
/* U-9: dots and slices are now keyboard-focusable (tabindex="0") so the
 * chart-tooltip.js tooltip they carry is reachable without a pointer -- they
 * need their own visible focus ring since the browser default outline on an
 * SVG circle/path is easy to lose against the chart. */
.trend-dot:focus-visible { outline: 2px solid var(--brand-dark); outline-offset: 2px; }
.axis-tick, .axis-label { fill: var(--muted); font-size: var(--fs-1); font-weight: 650; }
/* 라벨 두 줄 중 아랫줄(수행 시각). 날짜보다 한 단계 물러서야 눈이 날짜를 먼저 잡는다. */
.axis-label.axis-time { font-size: var(--fs-1); font-weight: 600; opacity: 0.75; }
/* 측정 기점이 바뀐 회차. 값 선보다 뒤에 깔리되 그리드보다는 분명해야, 계단이
 * 결과가 아니라 질문이 바뀐 지점이라는 걸 읽을 수 있다. */
.trend-boundary {
  stroke: var(--notice);
  stroke-width: 1.5;
  stroke-dasharray: 4 4;
  vector-effect: non-scaling-stroke;
}

.trend-boundary-legend {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 8px;
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: var(--row-radius);
  background: var(--surface-soft);
  color: var(--muted-strong);
  font-size: var(--fs-1);
  line-height: 1.6;
}
.trend-boundary-key {
  width: 14px;
  height: 0;
  margin-top: 9px;
  border-top: 1.5px dashed var(--notice);
}
.trend-boundary-legend b { font-weight: 800; }
.trend-boundary-legend ul { margin: 2px 0 0; padding-left: 16px; }
.trend-boundary-legend em { color: var(--muted); font-style: normal; font-weight: 700; }

.trend-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 8px; margin-top: 12px; }
/* 실행 과제 화면은 이 패널을 .dashboard-grid 반폭 칸에 놓는다 -- 라벨-값을 한 줄에
 * 나란히 두는 옛 레이아웃은 4장이 그 폭에 못 들어가 세로로 쌓였다. 라벨을 위,
 * 값·증감을 아래에 두는 카드형으로 바꿔 좁은 폭에서도 넉 장이 가로로 선다. */
/* 값과 증감을 고정 2열 그리드에 못박아 두면 카드가 좁아질 때 열이 줄지 못해 증감
 * 글자가 통째로 접힌다 -- "▼"만 남고 "12.5%p"가 다음 줄로 갈라져(값 폭이 카드마다
 * 달라 어떤 카드에서만) 도표가 깨져 보였다. 줄바꿈되는 flex로 두면 값 옆에 자리가
 * 있을 때만 나란히 서고, 모자라면 증감이 한 덩어리로 다음 줄에 내려간다. */
.trend-summary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 8px;
  padding: 9px 11px;
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  font-size: var(--fs-2);
}
.trend-summary-row span { flex: 0 0 100%; overflow-wrap: break-word; word-break: keep-all; color: var(--muted-strong); font-weight: 700; }
.trend-summary-row strong { font-size: var(--fs-4); }
/* 화살표와 숫자는 한 덩어리다(nowrap) -- 갈라지면 어느 값의 증감인지 안 읽힌다.
 * margin-left: auto는 같은 줄에 설 때도, 제 줄로 내려갔을 때도 오른쪽에 붙인다. */
.trend-summary-row em.delta { margin-left: auto; white-space: nowrap; }
/* 추천 순위 점수 카드에만 붙는 근거 한 줄("평균 2.0위 · 8/109") -- 점수만 남으면
 * "그래서 몇 위였나"가 사라진다. 제 줄을 쓰고, 긴 문장은 title로 붙는다. */
.trend-summary-row .trend-note {
  flex: 0 0 100%;
  margin-top: 1px;
  color: var(--muted);
  font-size: var(--fs-1);
  font-weight: 600;
}
/* forecast-chip(white-space: nowrap)은 좁은 카드 폭에 안 들어가므로 항상 자기 줄에 둔다 --
 * 줄바꿈 flex에서 그 "자기 줄"을 맡는 게 forecast-line이다(칩에 직접 100%를 주면 점선
 * 알약이 카드 폭만큼 늘어난다. dashboard.js::forecastChip 참고). */
.trend-summary-row .forecast-line { flex: 0 0 100%; margin-top: 2px; }

.trend-insight {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 10px;
  padding: 9px 11px;
  border-radius: var(--row-radius);
  background: var(--brand-soft);
}
.trend-insight span { padding: 4px 9px; color: var(--brand-dark); border-radius: 6px; background: #fff; font-size: var(--fs-1); font-weight: 850; }
.trend-insight strong { color: var(--text); font-size: var(--fs-2); }
.observation-date { color: var(--muted-strong); font-size: var(--fs-1); font-weight: 650; white-space: nowrap; }

/* ---------- share of voice / competitor ---------- */
/* The donut carries its own leader-line labels now (see donutWithLabels in charts.js), so it's the
 * whole card -- no side column to balance against, just centre it and let it run wide. */
.sov-wrap { display: flex; justify-content: center; }
.donut-chart { display: block; width: 100%; max-width: 160px; margin: 0 auto; }
/* donutWithLabels' viewBox is much wider than it is tall (room for labels either side of the
 * circle) -- the shared default above is still what the compact 출처 채널 구성 donut uses. */
.donut-chart-labeled { max-width: 640px; }
.donut-slice.is-target { filter: drop-shadow(0 3px 6px rgba(10, 189, 163, .28)); }
.donut-slice:hover, .donut-slice:focus-visible { filter: brightness(1.08); }
/* PRISM 고리 조각과 같은 문제 -- outline을 :focus-visible에만 껐더니 마우스 클릭(:focus지만
 * :focus-visible은 아니다)에서 기본 포커스 링이 살아나 조각의 바운딩 박스가 검은 네모로 떴다. */
.donut-slice:focus { outline: none; }
.donut-slice:focus-visible { stroke: var(--text); stroke-width: 2.5; paint-order: stroke fill; }
.donut-center-label { fill: var(--muted-strong); font-size: var(--fs-1); font-weight: 750; }
.donut-center-value { fill: var(--text); font-size: var(--fs-5); font-weight: 850; letter-spacing: -.03em; }
.donut-leader { fill: none; stroke-width: 1.5; opacity: .55; }
.donut-leader-label { fill: var(--text); font-size: var(--fs-2); font-weight: 750; }
.donut-leader-label.is-target { fill: var(--brand-dark); font-weight: 850; }
.donut-leader-label:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
.donut-leader-value { fill: var(--muted-strong); font-size: var(--fs-1); font-weight: 650; }

.competitor-list { display: grid; gap: 6px; }
.sov-row, .competitor-row {
  display: grid;
  /* 이름 칸에 90px 하한이 있던 동안에는 4열 진단 카드가 좁아질 때 행이 카드보다
   * 넓어져 맨 오른쪽 값("21.6%")부터 잘렸다. 하한을 풀면 이름이 말줄임(.sov-name ·
   * .competitor-name)으로 먼저 줄고 순위·막대·값은 끝까지 남는다. */
  grid-template-columns: 20px minmax(0, 1.6fr) minmax(32px, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--row-radius);
  font-size: var(--fs-3);
}
.sov-row.is-target, .competitor-row.is-target { background: var(--brand-soft); font-weight: 800; }

/* "기타"(5위 밖 브랜드 합산) 행을 펼치면 안에 누가 얼마나 있는지 본다 -- summary가 .sov-row 자체라 접혀 있을 때 다른 행과 똑같이 보인다. */
.sov-other > summary { cursor: pointer; list-style: none; }
.sov-other > summary::-webkit-details-marker { display: none; }
.sov-other-list { display: grid; gap: 4px; margin: 4px 0 0 30px; }
.sov-other-list .sov-row { padding: 4px 10px; font-size: var(--fs-2); background: var(--surface-soft); }

/* §10.4 1차 축소판: 핵심 미노출 질문군 -- PRISM 축 코드(P/R/I/S/M) + 라벨 +
 * 미노출 개수 + 경쟁사 평균을 한 줄에. .sov-row와 같은 4열 그리드를 쓰되
 * 코드 칸이 원형 배지가 아니라 글자칩이라 폭을 좁혀 둔다. */
.uncovered-list { display: grid; gap: 6px; }
.uncovered-row {
  display: grid;
  grid-template-columns: 28px minmax(70px, 1fr) auto minmax(90px, 1.4fr);
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--row-radius);
  font-size: var(--fs-3);
  background: var(--surface-soft);
}
.uncovered-code {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 6px;
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-weight: 800;
  font-size: var(--fs-1);
}
.uncovered-label { color: var(--muted-strong); }
.uncovered-row strong { font-size: var(--fs-4); }
.uncovered-row small { color: var(--muted); text-align: right; }
/* 신뢰도(답변 재현성) 행 -- 코드칩 없는 3열. .uncovered-row의 4열을 그대로 쓰면
 * 질문 라벨이 28px 칩 칸에 들어가 글자가 세로로 한 자씩 꺾인다(2026-08-18 실측). */
.consistency-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(90px, auto);
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--row-radius);
  font-size: var(--fs-3);
  background: var(--surface-soft);
}
.consistency-row .uncovered-label {
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.consistency-row strong { font-size: var(--fs-4); }
.consistency-row small { color: var(--muted); text-align: right; }
.sov-rank, .competitor-rank {
  display: grid;
  place-items: center;
  width: 21px;
  height: 21px;
  color: var(--muted-strong);
  border-radius: 50%;
  background: var(--surface-muted);
  font-size: var(--fs-1);
  font-weight: 850;
}
.sov-name, .competitor-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------- engines ---------- */
/* A Pro Max workspace runs ~18 provider branches. Listing them all inline made
 * the row twice the height of everything beside it, so the list scrolls once it
 * passes roughly eight engines. */
.engine-list {
  display: grid;
  align-content: start;
  gap: 8px;
  max-height: 430px;
  padding-right: 4px;
  overflow-y: auto;
}
.engine-row { padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--row-radius); background: var(--surface-muted); }
.engine-main { display: grid; grid-template-columns: minmax(110px, 160px) minmax(0, 1fr) 46px; align-items: center; gap: 10px; }
.engine-main > span { color: var(--text); font-size: var(--fs-3); font-weight: 800; }
.engine-main > span small {
  display: block;
  margin-top: 3px;
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 750;
}
.engine-main > strong { font-size: var(--fs-4); text-align: right; }
.engine-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin-top: 8px; color: var(--muted); font-size: var(--fs-1); }
.engine-peers { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.engine-peers span { padding: 3px 8px; color: var(--muted-strong); border: 1px solid var(--line); border-radius: 5px; background: var(--surface); font-size: var(--fs-1); font-weight: 700; }

/* ---------- AEO score ---------- */
/* 세 열이다: 고리 + 한 줄 해석 / 구성 요소 / 영역별 기여. 감정 구성이 네 번째 열로
 * 서 있던 동안에는 고리 열만 200px에서 끝나고 나머지가 500px까지 갔다 -- 고리 아래
 * 열 하나가 통째로 비는 여백이 패널 높이의 절반이었다. */
.score-body {
  display: grid;
  grid-template-columns: minmax(190px, .85fr) minmax(0, 1.15fr) minmax(0, 1.1fr);
  gap: 24px;
  align-items: start;
}
.score-ring { display: grid; justify-items: center; gap: 10px; }
.score-reading {
  margin: 0;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  line-height: 1.65;
  text-align: center;
  word-break: keep-all;
}
.ring-chart { display: block; width: 100%; max-width: 150px; }
.ring-track { stroke: #e6eded; }
.ring-value { stroke: var(--brand); stroke-linecap: round; }
.ring-label { fill: var(--muted); font-size: var(--fs-1); font-weight: 800; letter-spacing: .12em; }
.ring-score { fill: var(--text); font-size: var(--fs-6); font-weight: 850; letter-spacing: -.04em; }
.ring-score.is-empty { fill: var(--muted); font-size: var(--fs-3); font-weight: 700; letter-spacing: 0; }
/* 고리의 증감은 지수의 증감이라 위로 가는 쪽이 늘 좋은 쪽이다. 한 색으로 칠해 두면
 * 내려간 회차가 초록 ▼로 나온다. */
.ring-delta { fill: var(--pos); font-size: var(--fs-1); font-weight: 800; }
.ring-delta.down { fill: var(--neg); }
.ring-delta.flat { fill: var(--muted); }

.score-components { display: grid; gap: 14px; }
.score-component small { display: block; margin-top: 5px; color: var(--muted); font-size: var(--fs-1); line-height: 1.5; }
/* ABS 카드의 기여 한 줄("× 0.6 -> ABS에 32.6점")은 위의 입력 점수(fs-4)보다 작아야
 * 한다 -- 본문 크기를 물려받으면 32.6이 54.4와 같은 무게로 읽혀 둘 중 뭐가 입력이고
 * 뭐가 기여분인지 안 보인다. */
.score-component .score-contribution { margin-top: 3px; color: var(--muted-strong); font-size: var(--fs-2); font-weight: 700; }
/* 이 막대만은 채운 길이가 100점 만점 중 ABS 점수라, 못 채운 자리가 눈에 보여야 한다
 * (다른 화면의 stacked-bar는 늘 100%를 나눠 칠해 트랙이 드러날 일이 없다). */
.score-component .stacked-bar { background: var(--surface-muted); }
.score-aggregation-note {
  margin: 0;
  padding: 9px 11px;
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  color: var(--muted-strong);
  font-size: var(--fs-1);
  font-weight: 650;
  line-height: 1.55;
  word-break: keep-all;
}
.coverage-score-list { display: grid; gap: 2px; }
.coverage-score-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}
.coverage-score-row:last-child { border-bottom: none; }
.coverage-score-row > i {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #64748b;
  color: #fff;
  font-size: var(--fs-1);
  font-style: normal;
  font-weight: 850;
}
.coverage-score-row:nth-child(1) > i { background: #E56767; }
.coverage-score-row:nth-child(2) > i { background: #EFA24B; }
.coverage-score-row:nth-child(3) > i { background: #46A879; }
.coverage-score-row:nth-child(4) > i { background: #4D8FCB; }
.coverage-score-row:nth-child(5) > i { background: #8069C5; }
.coverage-score-row > span { min-width: 0; color: var(--muted-strong); font-size: var(--fs-2); font-weight: 750; }
.coverage-score-row > span small { margin: 1px 0 0; }
.coverage-score-row > strong { font-size: var(--fs-3); font-weight: 850; white-space: nowrap; }
.coverage-score-row > strong em { margin-left: 1px; color: var(--muted); font-size: var(--fs-1); font-style: normal; }
.coverage-score-composition > small code { color: var(--muted-strong); font-weight: 750; }
.score-block-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 5px; }
.score-block-head span { color: var(--muted-strong); font-size: var(--fs-2); font-weight: 750; }
.score-block-head small { color: var(--muted); font-size: var(--fs-1); }
.score-block-head strong { font-size: var(--fs-4); }
.score-block-head strong em { margin-left: 1px; color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 750; }
/* 같은 카드 안에서 두 번째로 서는 머리(검색·트렌드 표면) -- 첫 머리와 구분되게 위에
   여백과 실선을 두되, 글자 크기는 같게 두어 별개 카드로 읽히지 않게 한다. */
.score-block-subhead { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.score-note { display: block; margin-top: 7px; color: var(--muted); font-size: var(--fs-1); }

/* 엔진이 최대 10개까지 붙는 AVS 칸은 .score-component 카드로 쌓으면 이름이 줄바꿈되며
 * 세로로 길게 늘어진다 -- PRISM 레일(.area-rail-row)처럼 이름·막대·점수·표본을 한 줄
 * 그리드에 눌러 목록으로 읽히게 한다. */
.score-engine-list { display: grid; gap: 2px; }
.score-engine-row {
  display: grid;
  grid-template-columns: minmax(0, 140px) minmax(40px, 1fr) minmax(50px, 60px) minmax(58px, 64px);
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}
.score-engine-row:last-child { border-bottom: none; }
.score-engine-name { color: var(--muted-strong); font-size: var(--fs-2); font-weight: 750; word-break: keep-all; line-height: 1.35; }
/* 경쟁 브랜드가 함께 잡히지 않아 점유율 항이 만점이 된 엔진. 값을 숨기지 않고 표시만
   붙인다 -- 막대 길이의 기준에서는 이미 빠져 있어서, 표시가 없으면 왜 혼자 꽉 찬
   막대인지 화면에서 설명되지 않는다. */
.engine-flag {
  display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 4px;
  font-size: var(--fs-1); font-weight: 700; color: var(--muted);
  background: color-mix(in srgb, var(--muted) 12%, transparent); cursor: help;
}
.score-engine-row.is-uncontested .meter i { opacity: .45; }
.score-engine-row strong { font-size: var(--fs-3); font-weight: 800; text-align: right; }
.score-engine-row strong em { margin-left: 1px; color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 700; }
.score-engine-row small { color: var(--muted); font-size: var(--fs-1); font-weight: 650; text-align: right; white-space: nowrap; }

/* 질문쌍별 종합 점수 -- 질문 문장이 길어 엔진 목록의 한 줄 그리드에 못 눕는다.
 * 질문(2줄 말줄임) 위, 막대·점수·입력값 아래의 두 줄 행으로 쌓는다. */
.score-pair-list { display: grid; gap: 2px; }
.score-pair-row { padding: 7px 0; border-bottom: 1px solid var(--line); }
.score-pair-row:last-child { border-bottom: none; }
.score-pair-question {
  margin: 0 0 5px;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  font-weight: 650;
  line-height: 1.4;
  word-break: keep-all;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.score-pair-meter {
  display: grid;
  grid-template-columns: minmax(60px, 1fr) 60px auto;
  align-items: center;
  gap: 10px;
}
.score-pair-meter strong { font-size: var(--fs-3); font-weight: 800; text-align: right; }
.score-pair-meter strong em { margin-left: 1px; color: var(--muted); font-size: var(--fs-1); font-style: normal; font-weight: 700; }
.score-pair-meter small { color: var(--muted); font-size: var(--fs-1); font-weight: 650; text-align: right; white-space: nowrap; }

/* `.score-lineage`(재현 정보)는 화면에서 내려갔다 -- 기간 비교가 성립하는지는
 * 기간별 추이의 comparability 경고가 회차들을 실제로 대조해서 말한다. */

/* 지수 주요 영향 요인 / 우선 개선 -------------------------------------------- */
.driver-rows { display: grid; gap: 2px; }
.driver-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--surface-muted);
  font-size: var(--fs-2);
}
.driver-row:last-child { border-bottom: 0; }
.driver-row span { color: var(--muted-strong); font-weight: 750; }
.driver-row strong { font-size: var(--fs-3); }
.driver-row.positive strong { color: var(--pos); }
.driver-row.negative strong { color: var(--neg); }
.driver-row.flat strong { color: var(--muted); font-size: var(--fs-1); font-weight: 750; }
.driver-row small { color: var(--muted); font-size: var(--fs-1); }

.priority-action {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 9px;
  margin-top: 10px;
  padding: 11px 12px;
  border-radius: var(--row-radius);
  background: var(--warning-soft);
}
.priority-action > span {
  align-self: start;
  padding: 4px 9px;
  color: var(--warning);
  border-radius: 6px;
  background: #fbe6c8;
  font-size: var(--fs-1);
  font-weight: 850;
  white-space: nowrap;
}
.priority-action b { display: block; color: #6b4b2b; font-size: var(--fs-2); line-height: 1.5; word-break: keep-all; }
.priority-action small { display: block; margin-top: 4px; color: #8a6a49; font-size: var(--fs-1); line-height: 1.55; word-break: keep-all; }

/* 감정 구성은 지수 패널 안의 블록이 아니라 자기 패널이므로 막대가 화면 폭을 다 쓴다. */
.sentiment-panel .stacked-bar { height: 12px; border-radius: 6px; margin: 2px 0 10px; }

/* KEY INSIGHT ------------------------------------------------------------- */
.insight-copy {
  margin: 0;
  padding: 14px 16px;
  /* U-6: labeled "KEY INSIGHT" in the comment above and shown in its own
   * brand-tinted callout -- the one thing this box exists to make sure gets
   * read should not then be the same gray as a timestamp. */
  color: var(--text);
  border-left: 3px solid var(--brand);
  border-radius: 0 10px 10px 0;
  background: var(--brand-soft);
  font-size: var(--fs-3);
  line-height: 1.7;
  word-break: keep-all;
}
.insight-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; margin-top: 12px; }
.insight-facts > div { padding: 9px 11px; border-radius: var(--row-radius); background: var(--surface-muted); }
.insight-facts span { display: block; color: var(--muted-strong); font-size: var(--fs-1); }
.insight-facts b { font-size: var(--fs-3); }

/* Drill-down question set, grouped by measurement axis --------------------- */
.question-groups { display: grid; gap: 16px; }
.question-group h3 {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 9px;
  font-size: var(--fs-3);
}
.question-group h3 small { margin-left: auto; color: var(--muted); font-size: var(--fs-1); font-weight: 700; }
.group-index {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: var(--brand-dark);
  border-radius: 7px;
  background: var(--brand-soft);
  font-size: var(--fs-1);
  font-weight: 850;
}

.detail-side { display: grid; align-content: start; gap: 14px; }
/* The drill-down columns hold unrelated content, so a short question set must
 * not be stretched to the height of the two panels beside it. */
.detail-grid { align-items: start; }
.detail-grid > .panel, .detail-grid > .detail-side { height: auto; }

/* ---------- actions ---------- */
.task-list { display: grid; gap: 8px; }
.task-item {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 10px;
  padding: 11px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
}
.task-item b { display: block; font-size: var(--fs-3); line-height: 1.55; word-break: keep-all; }
.task-item small { display: block; margin-top: 5px; color: var(--muted); font-size: var(--fs-1); }
.priority {
  padding: 5px 10px;
  border-radius: 7px;
  font-size: var(--fs-1);
  font-weight: 850;
  white-space: nowrap;
}
.priority.critical, .priority.high { color: #9a3412; background: #ffe6d2; }
.priority.medium { color: #92400e; background: #fdf0d5; }
.priority.low { color: var(--brand-dark); background: var(--brand-soft); }

/* Forecast + outlook ------------------------------------------------------- */
/* A projected number always ships with the basis it came from, so it can never
 * be mistaken for a measurement. */
.forecast-chip {
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 3px 9px;
  color: var(--muted-strong);
  border: 1px dashed var(--line-strong);
  border-radius: 999px;
  background: var(--surface);
  font-size: var(--fs-1);
  font-weight: 650;
  white-space: nowrap;
}
.forecast-chip b { font-size: var(--fs-2); }
.forecast-chip em { color: var(--muted); font-style: normal; font-weight: 750; }

.outlook {
  display: block;
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--row-radius);
  background: var(--surface);
  font-size: var(--fs-1);
  font-weight: 650;
}
.outlook b { font-size: var(--fs-3); }
.outlook em { margin-left: 4px; color: var(--muted-strong); font-style: normal; font-weight: 800; }
.outlook small { display: block; margin-top: 3px; color: var(--muted); font-size: var(--fs-1); font-weight: 600; }
.outlook.muted { color: var(--muted); font-weight: 600; }

/* 2단계 심화 분석이 찾은 실제 인용 문단 -- 노출률 %가 아니라 "이 문장이 근거였다"는
 * 구체적 증거라 outlook과 다른 시각적 층위(인용문)로 보여준다. */
.action-evidence {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-left: 3px solid var(--line-strong);
  background: var(--surface);
  font-size: var(--fs-1);
  font-style: italic;
  color: var(--muted-strong);
}
.action-evidence cite {
  display: block;
  margin-top: 4px;
  font-style: normal;
  font-size: var(--fs-1);
  color: var(--muted);
}
.action-evidence cite a { color: inherit; text-decoration: underline; }
.action-evidence-types { margin-top: 6px; display: flex; gap: 4px; flex-wrap: wrap; font-style: normal; }

.trend-summary-row.is-own { background: var(--brand-soft); }
.trend-summary-row.is-own span b {
  margin-left: 6px;
  padding: 2px 7px;
  color: var(--brand-dark);
  border-radius: 5px;
  background: #fff;
  font-size: var(--fs-1);
}
.trend-legend span.is-own { color: var(--text); font-weight: 800; }

.scope-select.compact select { min-width: 128px; }

/* 사용자 지정 기간 구간. 기간 드롭다운 옆에 붙어 한 줄을 이룬다 -- 라벨 줄이 없는 대신
 * 위쪽 여백으로 드롭다운의 라벨 높이만큼 내려 맞춘다(그래야 컨트롤끼리 밑선이 맞는다). */
.scope-range {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* 기간 드롭다운은 위에 라벨 줄(12px + 3px gap)을 이고 있다 -- 이 구간에는 라벨이 없으므로
   * 그만큼 내려야 두 컨트롤의 밑선이 맞는다. */
  margin-top: 21px;
}
/* 좁아지면 줄바꿈되게 두되, 각 칸이 눌려 글자가 세로로 쪼개지지는 않게 한다("적/용"). */
.scope-range > * { flex: 0 0 auto; }
.scope-range > i { color: var(--muted); font-style: normal; }
.scope-range input[type="date"] {
  /* forms.css의 `input { width: 100% }`를 여기서 끊는다 -- 그대로 두면 날짜 칸이 줄 전체를
   * 차지하려 들어 서로를 밀어내고 옆 컨트롤 위로 넘친다(실측 327px). */
  width: 150px;
  height: 38px;
  padding: 0 10px;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--control-radius);
  background: var(--surface);
  font-family: inherit;
  font-size: var(--fs-2);
}
.scope-range input[type="date"]:invalid { border-color: var(--neg); }
.scope-range button {
  height: 38px;
  padding: 0 14px;
  white-space: nowrap;
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--control-radius);
  background: var(--surface-muted);
  font-family: inherit;
  font-size: var(--fs-2);
  font-weight: 700;
  cursor: pointer;
}
.scope-range button:hover { background: var(--surface); }

.comparability-warning {
  margin-top: 10px;
  padding: 11px 13px;
  color: var(--warning);
  border: 1px solid #f5dfbf;
  border-radius: var(--row-radius);
  background: var(--warning-soft);
  font-size: var(--fs-1);
}
.comparability-warning b { display: block; font-size: var(--fs-2); }
.comparability-warning ul { margin: 6px 0 0; padding-left: 18px; line-height: 1.6; }

/* ---------- sources ---------- */
.source-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin-bottom: 14px; }
.source-summary > div { padding: 11px 12px; border-radius: var(--row-radius); background: var(--surface-muted); }
.source-summary span { display: block; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.source-summary strong { font-size: var(--fs-6); letter-spacing: -.02em; }
/* 발행일 확인은 분모가 있어야 읽힌다 -- 값만 크게 두면 "총 몇 건 중"이 사라진다. */
.source-summary strong em { color: var(--muted); font-size: var(--fs-2); font-style: normal; font-weight: 700; }

/* 채널 구성: 한 줄 누적 막대 + 범례. 항목마다 풀폭 트랙을 주면 0.2%짜리가 87%짜리와
   같은 무게로 읽히고, 그 넷이 카드 높이의 절반을 가져간다. */
.source-mix { margin-bottom: 4px; }
.source-mix .stacked-bar { height: 12px; border-radius: 6px; margin: 2px 0 10px; }
.source-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: var(--fs-1); }
.source-legend-item { display: inline-flex; align-items: center; gap: 5px; color: var(--muted-strong); font-weight: 700; }
.source-legend-item i { width: 9px; height: 9px; border-radius: 3px; }
.source-legend-item b { color: var(--text); font-weight: 800; }
.source-legend-item small { color: var(--muted); font-weight: 600; }

.source-table { margin-top: 16px; overflow-x: auto; }
/* 열 순서: 인용한 AI·품질·인용·발행일·출처. 출처(제목)가 가장 길이가 들쭉날쭉해
   맨 앞에 두면 나머지 고정폭 열의 정렬이 흔들려 보인다 -- 폭이 일정한 열부터 앞에
   놓고, 가변폭인 출처를 맨 뒤(2.4fr, 남는 공간을 흡수)로 보낸다. */
.source-table-head, .source-table-row {
  display: grid;
  grid-template-columns: minmax(96px, 1.1fr) 52px 48px 86px minmax(180px, 2.4fr);
  gap: 10px;
  align-items: center;
  padding: 11px 4px;
  font-size: var(--fs-2);
}
.source-table-head { color: var(--muted-strong); border-bottom: 1px solid var(--line); font-size: var(--fs-1); font-weight: 800; }
/* 20행짜리 5열 표에서 세로 구분선 없이 gap만으로는 눈이 한 행을 옆칸까지 놓치기
   쉽다 -- .qa-row와 같은 방식으로 마우스가 올라간 행 전체를 옅게 밝힌다. */
.source-table-row { border-bottom: 1px solid var(--surface-muted); }
.source-table-row:hover { background: var(--surface-muted); }
.source-table-row a { color: var(--text); text-decoration: none; }
.source-table-row a:hover { color: var(--brand-dark); text-decoration: underline; }
.source-table-row small { display: block; margin-top: 2px; color: var(--muted); font-size: var(--fs-1); }
/* 발행일 칸의 "수정일" 배지가 좁은 열(86px)에서 날짜 뒤에 바로 붙으면 한글이
   음절 중간에서 줄바꿈됐다("수\n정일") -- nowrap으로 배지 자체는 안 쪼개지게 하고,
   대신 날짜와 배지 사이 공백에서만 줄이 바뀌게 한다. */
.source-table-row small.muted { display: inline; margin: 0; white-space: nowrap; }
/* 그리드 트랙은 기본 min-width가 auto라 긴 제목이 셀을 밀어 넓힌다. 두 줄로 깨지는
   대신 한 줄에서 잘리게 하려면 셀과 자식 양쪽에서 그 최소폭을 풀어야 한다. */
.source-main { min-width: 0; }
.source-main .source-title,
.source-main small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.source-main .source-title { font-weight: 700; }
.source-engines { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; min-width: 0; }
.source-engine {
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--surface-muted);
  color: var(--muted-strong);
  font-size: var(--fs-1);
  font-weight: 700;
  white-space: nowrap;
}
.source-engine-more { color: var(--muted); font-size: var(--fs-1); }
/* 품질은 등급이 붙을 때만 색이 붙는다 -- 숫자만으로는 84와 62가 같은 무게로 읽힌다. */
.source-table-row b[data-tier="strong"] { color: var(--pos); }
.source-table-row b[data-tier="weak"] { color: #b8791f; }
.source-table-row b[data-tier="risk"] { color: #c2543c; }

.domain-list { display: grid; gap: 5px; }
.domain-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 9px 11px;
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  font-size: var(--fs-2);
}

.domestic-list { display: grid; gap: 7px; }
.domestic-row { display: grid; grid-template-columns: minmax(80px, 1fr) minmax(60px, 2fr) auto; align-items: center; gap: 10px; font-size: var(--fs-2); }
.domestic-overlap { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 9px; margin-top: 12px; }
.domestic-overlap > div { padding: 10px; border-radius: var(--row-radius); background: var(--surface-muted); }
.domestic-overlap span { display: block; color: var(--muted-strong); font-size: var(--fs-1); }
.domestic-overlap strong { font-size: var(--fs-5); }

/* ---------- area detail page ---------- */
/* 제목·설명은 화면 머리가 이미 말했다. 히어로에 남는 것은 비교 하나뿐이라 감싸는
 * 상자를 따로 두지 않는다 -- 상자 안의 상자가 되면 정작 봐야 할 숫자가 한 겹 더
 * 안쪽으로 들어간다. */
.detail-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 16px;
  margin-bottom: 14px;
}
/* 비교 옆에 해석 한 문장. 이 화면에서 먼저 볼 것은 "우리가 평균 대비 어디인가"와
 * "무엇이 그 점수를 움직였나" 둘뿐이고, 나머지는 근거라 아래로 내려간다. */
.detail-lede {
  display: flex;
  flex: 1 1 300px;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 18px 22px;
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
  background: var(--surface);
}
.detail-lede > span { color: var(--muted-strong); font-size: var(--fs-1); font-weight: 800; }
.detail-lede > p { margin: 0; font-size: var(--fs-3); font-weight: 700; line-height: 1.65; word-break: keep-all; }
/* 우리 점수와 산업 평균이 한 상자에 담기므로, 어느 쪽이 우리 것인지는 크기가 아니라
 * 이름과 견본이 말해야 한다. 예전엔 큰 숫자에 아무 라벨이 없어 바로 옆 `산업 평균`이
 * 그 숫자의 설명처럼 읽혔다. */
.detail-score {
  display: grid;
  gap: 10px;
  flex: 1 1 auto;
  max-width: 520px;
  padding: 18px 22px;
  border: 1px solid #bfe9e1;
  border-radius: var(--panel-radius);
  background: var(--brand-soft);
}
/* 두 값은 이름 줄끼리, 숫자 줄끼리 맞아야 한다. flex로 두 덩어리를 나란히 놓으면
 * 숫자 높이가 서로 달라(34px vs 22px) 이름 줄이 위아래로 어긋난다 -- `prain global`이
 * `산업 평균`보다 한 단 높이 뜨던 것이 이것이다. display:contents로 각 덩어리를
 * 풀어 두 값이 같은 격자의 같은 행에 들어가게 한다. */
.detail-score-pair {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: max-content;
  grid-template-rows: auto auto;
  align-items: end;
  gap: 3px 18px;
}
.detail-score-pair > div { display: contents; }
.detail-score-pair span { display: flex; align-items: center; gap: 5px; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.detail-score-pair span i { display: inline-block; width: 12px; height: 4px; border-radius: 2px; }
.score-own span i { background: var(--brand); }
.score-baseline span i { height: 0; border-top: 2px dashed var(--text); border-radius: 0; }
.detail-score-pair strong { font-size: var(--fs-6); letter-spacing: -.04em; line-height: 1; }
.detail-score-pair strong em { margin-left: 2px; color: var(--muted); font-size: var(--fs-2); font-style: normal; font-weight: 700; }
/* 평균은 참조값이라 우리 점수보다 한 단 작게 둔다 -- 같은 크기면 둘 중 어느 것을
 * 봐야 하는지가 사라진다. */
.score-baseline strong { color: var(--muted-strong); font-size: var(--fs-6); }
.detail-score[data-availability="insufficient_data"] .score-own strong { color: var(--muted); font-size: var(--fs-5); }
.detail-gap { font-size: var(--fs-2); font-style: normal; font-weight: 850; }
.detail-gap.is-muted { color: var(--muted); font-weight: 650; line-height: 1.5; word-break: keep-all; }

/* 기준선 설명은 필요할 때만 펼친다 -- 항상 펼쳐 두면 오른쪽 열이 글 벽이 된다. */
.method-note { margin-top: 10px; color: var(--muted); font-size: var(--fs-1); }
.method-note > summary { color: var(--muted-strong); font-weight: 700; cursor: pointer; }
.method-note > p { margin: 6px 0 0; line-height: 1.6; word-break: keep-all; }

/* 카드마다 축의 종류가 다르므로, 막대 묶음 위에 그 축이 무엇인지 한 마디 얹는다. */
.area-axis-kind {
  margin: 0 0 7px;
  color: var(--muted);
  font-size: var(--fs-1);
  font-weight: 750;
}

.question-set { display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; counter-reset: question; }
.question-set li {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  align-items: baseline;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
}
.question-set li.is-exposed { border-color: #bfe9e1; background: var(--brand-soft); }
.question-flag { padding: 4px 9px; color: var(--muted-strong); border-radius: 6px; background: var(--surface); font-size: var(--fs-1); font-weight: 800; }
.question-set li.is-exposed .question-flag { color: var(--brand-dark); }
.question-set b { font-size: var(--fs-3); line-height: 1.55; word-break: keep-all; }
.question-set small { display: block; margin-top: 4px; color: var(--muted); font-size: var(--fs-1); }

.method-list { display: grid; gap: 8px; margin: 0 0 14px; padding-left: 20px; color: var(--text); font-size: var(--fs-3); line-height: 1.65; }
.method-facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 8px; }
.method-facts > div { padding: 9px 10px; border-radius: var(--row-radius); background: var(--surface-muted); }
.method-facts span { display: block; color: var(--muted-strong); font-size: var(--fs-1); }
.method-facts b { font-size: var(--fs-3); }

/* 펼친 영역 카드 안의 대표 질문 미리보기 */
.area-question-preview {
  display: grid;
  gap: 6px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}
.area-question-preview li {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
/* 점은 질문의 첫 줄에 맞춰 선다 -- 두 줄로 접힌 질문의 세로 한가운데로 떠오르면
 * 무엇의 상태인지 흐려진다. */
.area-question-preview .q-dot { margin-top: 6px; }
.area-question-preview li.is-exposed .area-question-text { color: var(--text); }
/* 질문 텍스트와 그 아래 경쟁사 배지를 한 열로 묶는다 -- min-width:0이 없으면 flex
 * 항목이 내용 길이만큼 늘어나 line-clamp/ellipsis가 먹지 않는다. */
.area-question-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.area-question-text {
  color: var(--muted-strong);
  font-size: var(--fs-2);
  line-height: 1.5;
  word-break: keep-all;
  /* 미리보기는 "이런 질문이었다"만 보이면 된다. 좁은 칸에서 긴 질문 하나가 여섯 줄로
   * 접히면 그 카드가 줄 높이를 정해 버리고, 짧은 카드 넷 아래가 전부 빈 칸이 된다.
   * 전문은 상세 화면의 `이 지표를 구성하는 질문`이 자른 데 없이 싣는다. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* 같은 답변에 함께 나온 경쟁 브랜드 -- qa-competitor-badge와 같은 알약 모양이되,
 * 여기는 이미 area-question-body 열 안이라 그 배지의 30px 왼쪽 여백 보정이 필요 없다. */
.area-question-competitors {
  display: inline-block;
  align-self: flex-start;
  max-width: 100%;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: var(--fs-1);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--muted-strong);
  background: var(--surface-muted);
}

/* 대시보드 요약형(컴팩트) 패널 -- 이름·점수를 옮겨 적던 범례 목록(.area-summary-*)은
 * 고리 바깥 라벨로 대체됐다(.area-outer-label). */

/* One grid for the whole list, not one per row: a content-sized label column
 * measured each row's own text, so every bar started at a different x. The rows
 * hand their cells straight to the list grid, which resolves one label width —
 * and one value width — for all of them. */
.engine-summary-list {
  display: grid;
  grid-template-columns: minmax(auto, max-content) minmax(60px, 1fr) auto;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-2);
}
.engine-summary-row { display: contents; }
/* 라벨 끝의 인터넷 사용/미사용·웹 사용이 같은 엔진의 두 변형을 가르므로 잘라내지
 * 않는다. 칼럼은 가장 긴 라벨 한 줄까지 넓어지고, 패널이 그보다 좁아지면 줄바꿈한다. */
.engine-summary-row > span { overflow-wrap: anywhere; }
.engine-summary-row span small {
  margin-left: 6px;
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-weight: 800;
}
.engine-summary-row strong { font-size: var(--fs-3); text-align: right; }
.area-breakdown-rows { display: grid; gap: 8px; }
/* 축 이름이 먼저다 -- 이름 칸을 막대에 양보하면 `공식·공공 근거`가 `공식·공…`으로
 * 잘려, 무슨 축인지 읽을 수 없는 채로 막대만 길게 남는다. */
.area-breakdown-row { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(38px, 1fr) auto; align-items: center; gap: 9px; margin-bottom: 8px; font-size: var(--fs-2); }
.area-breakdown-row.wide { grid-template-columns: minmax(120px, 200px) minmax(120px, 1fr) 52px 74px; margin-bottom: 0; }
/* 카드는 230px까지 좁아지므로 긴 축 이름은 자르지 말고 접는다 -- `티스토리 블…`은
 * 어느 출처인지 못 읽는 상태라, 두 줄이 되는 것보다 나쁘다. 폭이 넉넉한 상세 화면의
 * wide 변형만 한 줄로 묶어 둔다. */
.area-breakdown-row span { color: var(--muted-strong); line-height: 1.35; word-break: keep-all; }
.area-breakdown-row.wide span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 패널 폭 전체로 늘어난 막대는 길이 차이가 오히려 안 읽힌다 -- 눈이 훑어야 하는
 * 거리가 값의 차이보다 커진다. */
.breakdown-panel .area-breakdown-rows { max-width: 620px; }
.area-breakdown-row small { color: var(--muted); font-size: var(--fs-1); }
.area-detail-body .text-button { display: inline-block; margin-top: 12px; }

/* ---------- empty state ---------- */
.dashboard-empty {
  padding: 40px 32px;
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
  background: var(--surface);
  box-shadow: var(--panel-shadow);
  text-align: center;
}
.dashboard-empty h2 { margin: 4px 0 8px; font-size: var(--fs-6); }
/* 미시행 variant sits under the dashed headline row, so it trades the lone
 * hero padding for panel-scale spacing and a single primary CTA. */
.dashboard-empty.dashboard-not-run { padding: 32px; }
.dashboard-empty.dashboard-not-run .dashboard-empty-steps { max-width: 420px; margin-inline: auto; }
/* 실행이 도는 중인 빈 화면. 같은 자리를 쓰지만 "아무것도 없음"이 아니라 "아직 끝나지
 * 않음"이라, 브랜드색 테두리로 진행 배너와 같은 상태임을 알린다. */
.dashboard-empty.dashboard-running { padding: 32px; border-color: var(--brand); background: var(--brand-soft); }
.dashboard-empty.dashboard-running .dashboard-empty-steps { max-width: 420px; margin-inline: auto; }
.dashboard-empty > p { max-width: 560px; margin: 0 auto; color: var(--text); word-break: keep-all; }
.dashboard-empty-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-top: 26px; text-align: left; }
.step-card {
  padding: 15px 16px;
  color: inherit;
  border: 1px solid var(--line);
  border-radius: var(--card-radius);
  background: var(--surface-muted);
  text-decoration: none;
  transition: border-color .16s ease, background .16s ease;
}
.step-card:hover { border-color: var(--brand); background: var(--brand-soft); }
.step-card[data-tone="primary"] { border-color: var(--brand); background: var(--brand-soft); }
.step-card b { display: block; font-size: var(--fs-4); }
.step-card small { display: block; margin-top: 5px; color: var(--muted); font-size: var(--fs-2); line-height: 1.55; }

/* ---------- 대시보드 + 워크스페이스 조합 ---------- */
/* On 대시보드 the measurement panels come first and the workspace/project
 * surface follows, visually demoted so it reads as context rather than as a
 * second dashboard competing with the first. */
.brand-dashboard-section { margin-bottom: 26px; }

/* ---------- responsive ---------- */
/* U-10: collapsed onto the console's 3 breakpoints (≤760 / ≤1180 / >1180,
 * docs/plans/ROADMAP.md §2.1). This used to also have its own @media
 * (max-width: 1440px) step that nudged .score-body's column minmax/gap by a
 * few px -- a minor refinement, not a structural change (still 3 columns
 * either side of it), so it is dropped rather than folded into ≤1180 (which
 * uses a genuinely different 2-column .score-body). */
/* 2026-08-11: 콘텐츠 접힘을 뷰포트 미디어쿼리에서 @container content-col(파일 위
 * 셸 블록의 main 선언)로 이관. 구 @media 1180px는 레일 244px + 좌우 여백을 빼면
 * 실제로는 컬럼 ~865px에서 접히는 규칙이었는데, 기준이 뷰포트라 레일이 선 채로
 * 창만 줄이면(예: 1250px) 접힘이 늦어 4열 카드 안 행부터 잘렸다. 문턱은 컬럼
 * 폭으로 다시 잰 값: 880(구 1180 상당) · 720(구 760 상당). 셸 규칙(레일↔탑바)은
 * 아래 @media 760px에 그대로 남는다. */
@container content-col (width < 880px) {
  .dashboard-grid { grid-template-columns: 1fr; }
  /* .metric-row.secondary는 밖에서 별도 그리드 값을 갖고 있어(특정도가
   * .metric-row보다 높다) 이 규칙만으로는 접히지 않는다 -- 같이 짚어 준다. */
  .metric-row, .summary-strip, .metric-row.secondary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 고리와 구성 요소가 한 줄, 영역별 기여가 그 아래 한 줄. 세 열을 두 열로 접으면
   * 영역별 기여만 다음 줄 왼쪽에 반쪽으로 서고 오른쪽이 빈다. */
  .score-body { grid-template-columns: minmax(150px, .7fr) minmax(0, 1fr); }
  .score-body > .score-block { grid-column: 1 / -1; }
  /* 한 줄을 통째로 쓰는 폭에서 이름과 값 사이가 화면 절반만큼 벌어진다 -- 눈이 그
   * 빈 칸을 건너뛰어야 어느 값이 어느 영역의 것인지 짚인다. 두 열로 나눠 접는다. */
  .score-body > .score-block .driver-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 28px; }
  .area-chart-wrap { grid-template-columns: 1fr; }
  /* 상세 패널이 고리 아래로 내려간다. 옆에 붙이려면 최소 300px가 필요한데, 그걸
   * 밀어 넣으면 남는 폭이 고리에서 빠져 정작 눈금이 다시 눌린다. */
  .area-chart-wrap.split { grid-template-columns: minmax(0, 1fr); }
  /* 평균 열이 가장 먼저 접힌다 -- 같은 값이 막대의 눈금과 상세 패널에 이미 있다. */
  .area-rail-row { grid-template-columns: 22px 112px minmax(70px, 1fr) 62px 50px; gap: 10px; }
  .area-rail-base { display: none; }
}

/* 구 @media 760px의 콘텐츠 절반. 레일이 서 있어도 컬럼이 이만큼 좁으면(창 ~1000px
 * 미만) 같은 좁은 판이 필요하다 -- 뷰포트 기준이던 시절에는 레일 폭만큼 늦게 접혀
 * 이 구간이 통째로 빠져 있었다. */
@container content-col (width < 720px) {
  .title-actions { flex-direction: column; align-items: stretch; }
  .scope-select select { min-width: 0; width: 100%; }
  .detail-hero { flex-direction: column; align-items: stretch; }
  /* 고리 옆에 구성 요소를 붙여 두려면 막대에 남는 폭이 눈금 노릇을 못 한다. */
  .score-body { grid-template-columns: minmax(0, 1fr); }
  .score-body > .score-block .driver-rows { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
  /* 좁은 화면에서 접는 것은 인용 횟수와 발행일 -- 어느 AI가 인용했는지, 어떤
     출처였는지는 이 표를 읽는 이유 자체라 마지막까지 남긴다. 열 순서가
     인용한AI·품질·인용·발행일·출처이므로 3·4번째를 접는다. */
  .source-table-head, .source-table-row { grid-template-columns: minmax(80px, 1fr) 48px minmax(120px, 2fr); }
  .source-table-head > :nth-child(3), .source-table-row > :nth-child(3),
  .source-table-head > :nth-child(4), .source-table-row > :nth-child(4) { display: none; }
  .source-engines { flex-wrap: nowrap; overflow: hidden; }
  /* 모바일 레일은 업계 원점수(위 880px 규칙)와 격차를 접고, 영역·막대·현재 점수를
   * 남긴다. 고정 열 합계가 308px짜리 카드 안쪽 폭을 넘지 않게 한다. */
  .area-rail-row {
    grid-template-columns: 22px minmax(72px, 1fr) minmax(50px, 1fr) 58px;
    gap: 8px;
  }
  .area-rail-row > em { display: none; }
  /* 한 장씩 쌓인 점수 카드에서도 140/60/60/64px 고정 엔진 행은 모바일 폭보다
   * 넓다. 표본 수는 카드 설명에 합계가 있으므로 행에서는 접는다. */
  .score-engine-row { grid-template-columns: minmax(90px, 1.2fr) minmax(40px, 1fr) 50px; gap: 8px; }
  .score-engine-row > small { display: none; }
  /* 범례가 flex item의 max-content 폭(약 450px)을 고집하면 390px 화면 전체가 그 폭으로
   * 늘어나 가로 스크롤이 생긴다. 패널 너비를 받아 세 항목을 자연스럽게 줄바꿈한다. */
  .exposure-panel > .panel-head .panel-aside {
    flex: 1 1 100%;
    width: 100%;
    margin-left: 0;
    text-align: left;
  }
  .exposure-panel > .panel-head .legend { justify-content: start; gap: 6px 10px; width: 100%; }
}

@media (max-width: 760px) {
  /* Below the rail breakpoint the chrome collapses to a top bar, but it keeps
   * the rail's dark palette: the nav colours are declared outside the rail media
   * query, so a light bar here would render #a9b8b5 links on white. */
  /* Position is left to base.css on purpose: it makes the bar static on 분석 실행
   * so a sticky rail cannot sit on top of that screen's controls. Only the
   * palette is overridden here. */
  body[data-workspace-shell="rail"] > header {
    background: var(--rail-bg);
    border-bottom-color: var(--rail-line);
  }
  body[data-workspace-shell="rail"] header .nav {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 10px 12px;
    padding: 12px 16px;
  }
  body[data-workspace-shell="rail"] header .workspace-mode-switcher { grid-column: 1; }
  body[data-workspace-shell="rail"] header .header-actions {
    grid-column: 2;
    grid-row: 1;
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }
  body[data-workspace-shell="rail"] header .workspace-account-switcher,
  body[data-workspace-shell="rail"] header .steps { grid-column: 1 / -1; }
  /* The horizontal bar has no room for a full-width admin row; on mobile the
   * workspace/account menu's 플랫폼 관리자 item takes over. */
  body[data-workspace-shell="rail"] header .rail-admin-link { display: none; }
  body[data-workspace-shell="rail"] header .steps {
    display: flex;
    flex-wrap: nowrap;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: thin;
  }
  body[data-workspace-shell="rail"] header .steps button {
    width: auto;
    min-height: 40px;
    white-space: nowrap;
  }
  /* The rail size is tuned against a 15px label; this bar drops to 12px, and a
   * 20px mark beside it makes the row read as icon-first. */
  body[data-workspace-shell="rail"] header { --rail-icon: 17px; }
  .nav-group-label { display: none; }
  header .steps button span { font-size: var(--fs-1); }
  /* 콘텐츠 규칙(.title-actions · .score-body · .source-table 등)은 위
   * @container content-col (width < 720px) 블록으로 옮겼다 -- 여기는 셸만 남는다. */
}

/* ---------- 질문 카테고리 (분석 설정) ---------- */
/* 지금 무엇을 묻고 있는지와 언제부터 그랬는지를 한 카드에서 읽게 한다. 재설정은
 * 이후 모든 회차의 비교 기준을 옮기므로 눈에 띄되 주 동작처럼 보이지는 않는다. */
.category-set-panel { margin-top: 14px; }
.category-set-controls {
  display: flex;
  align-items: end;
  gap: 10px;
  text-align: left;
}
.category-set-controls label { display: grid; gap: 4px; font-size: var(--fs-1); font-weight: 700; }
.category-set-controls select { min-width: 160px; }

.category-set-head {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--card-radius);
  background: var(--surface-soft);
}
.category-set-head small { display: block; color: var(--muted); font-size: var(--fs-1); font-weight: 800; }
.category-set-head strong { font-size: var(--fs-3); word-break: keep-all; }

.category-set-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }

.category-set-questions { margin: 12px 0 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.category-set-questions li {
  display: grid;
  grid-template-columns: minmax(72px, max-content) minmax(0, 1fr);
  align-items: baseline;
  gap: 10px;
  padding: 9px 11px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  font-size: var(--fs-2);
  line-height: 1.6;
  word-break: keep-all;
}
.category-set-questions b { color: var(--brand-dark); font-size: var(--fs-1); font-weight: 800; }

@container content-col (width < 720px) {
  .category-set-controls { flex-wrap: wrap; }
  .category-set-questions li { grid-template-columns: 1fr; gap: 2px; }
}

/* ===== 2026-08-08 전면 재구성 (AIDEPrism_대시보드_구성안.docx) 신규 화면 ===== */

/* 대시보드 상단 KPI 4장(ABS·AVS·ARS·경쟁사 순위, 구성안 2.1절) -- metric-row.secondary가
 * 이미 auto-fit 그리드라 카드 수만 4장으로 줄이면 되지만, 4장일 때는 등분(auto-fit이
 * 폭에 따라 5번째 빈 칸을 만들 수 있음)을 확실히 하려고 breakpoint를 하나 못박는다.
 * `.metric-row.kpi-row-4`(두 클래스)로 걸어야 한다 -- `.kpi-row-4` 한 클래스로는
 * `.metric-row.secondary`(두 클래스, 위 671행)에 특이도로 져서 이 규칙이 죽은 채로
 * 카드 수가 바뀔 때마다 auto-fit이 폭에 따라 3+1처럼 줄을 깨뜨렸다. */
.metric-row.kpi-row-4 { grid-template-columns: repeat(4, minmax(150px, 1fr)); }
@container content-col (width < 720px) { .metric-row.kpi-row-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.metric-of-total { color: var(--muted); font-weight: 700; }

/* ABS·AVS·ARS·SoV 공통 PRISM 진단. 탭의 중앙값과 상단 KPI는 같은 payload 필드를
 * 읽고, 오른쪽 목록은 해당 지표의 영역별 분해만 보여준다. */
.prism-metric-tabs { flex-wrap: wrap; margin-bottom: 16px; }
.prism-inline-legend { display: flex; justify-content: flex-end; margin: -4px 0 10px; }
.prism-metric-pane {
  display: grid;
  grid-template-columns: minmax(360px, 1.1fr) minmax(260px, .9fr);
  align-items: center;
  gap: 24px;
}
.prism-metric-pane[hidden] { display: none; }
.prism-metric-pane.is-compact { display: block; }
.prism-metric-pane.is-compact[hidden] { display: none; }
.prism-coverage-meta { grid-column: 1 / -1; display: grid; gap: 8px; min-width: 0; }
.prism-membership-notice {
  margin: 0;
  padding: 9px 11px;
  border-left: 3px solid var(--notice);
  border-radius: 0 var(--row-radius) var(--row-radius) 0;
  background: color-mix(in srgb, var(--notice) 8%, var(--surface));
  color: var(--muted-strong);
  font-size: var(--fs-1);
  line-height: 1.55;
  word-break: keep-all;
}
.prism-metric-area-list { display: grid; gap: 8px; }
.prism-metric-area {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
}
.prism-metric-area span { font-size: var(--fs-2); font-weight: 750; }
.prism-metric-area span small { display: block; margin-top: 2px; color: var(--muted); font-size: var(--fs-1); font-weight: 600; }
.prism-metric-area strong { font-size: var(--fs-5); }
.prism-metric-area strong em { margin-left: 2px; color: var(--muted); font-size: var(--fs-1); font-style: normal; }
.prism-metric-area.is-empty { opacity: .65; }
@container content-col (width < 720px) {
  .prism-inline-legend { justify-content: flex-start; }
  .prism-metric-pane { grid-template-columns: 1fr; }
}

/* 대시보드 하단은 1×4 카드 벽 대신 2×1: 출처 품질과 우선 과제를 한 장씩 세로로 읽는다.
 * AVS·ARS 세부 진단은 상단 KPI의 자세히 보기에서 해당 상세 화면으로 이동한다. */
/* 2026-08-28: 인용 출처 품질·우선 실행 과제가 한 칸씩 전체 폭을 차지해 옆으로
 * 지나치게 길었다. 두 패널을 나란히 절반씩 두고, 우선 실행 과제 카드는 그 절반
 * 폭 안에서 세로로 쌓는다(아래 .action-panel .task-list). 좁은 화면 폴백은
 * 위 미디어쿼리의 .diagnostic-row 규칙이 그대로 되돌린다. */
.diagnostic-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* 점수 원인 분석은 PRISM 상세로 이동했지만 같은 컴포넌트를 쓰므로 상세용 행 스타일은
 * 유지한다. */
.score-drivers-panel .uncovered-list {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 14px;
}
.score-drivers-panel .uncovered-row {
  grid-template-columns: 28px minmax(70px, 1fr) auto minmax(90px, 1.4fr);
  min-width: 0;
}
.score-drivers-panel .uncovered-row > * { min-width: 0; }
@container content-col (width < 720px) {
  .score-drivers-panel .uncovered-list { grid-template-columns: minmax(0, 1fr); }
}
@container content-col (width < 420px) {
  .score-drivers-panel .uncovered-row { grid-template-columns: 28px minmax(0, 1fr) auto; }
  .score-drivers-panel .uncovered-row small {
    grid-column: 2 / -1;
    text-align: left;
  }
}
/* 2026-08-28: 평균 품질 점수를 도넛 왼쪽 별도 칸에 텍스트로 뒀었다 -- 도넛 구멍은
 * 비어 있고 점수 칸은 좁아 둘 다 옹색했다. 점수를 도넛 중앙으로 옮기고(donut()의
 * centerLabel/centerValue) 그만큼 도넛을 키워 칸을 [도넛, 범례] 둘로 줄인다. */
.source-quality-overview {
  display: grid;
  grid-template-columns: minmax(200px, .8fr) minmax(280px, 1.4fr);
  align-items: center;
  gap: 18px 28px;
}
.sources-panel.compact .sov-donut { display: flex; justify-content: center; }
.sources-panel.compact .donut-center-label { font-size: var(--fs-1); }
.sources-panel.compact .donut-center-value { font-size: clamp(26px, 2.2vw, 34px); }
.source-legend.compact {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 18px;
  font-size: var(--fs-2);
}
.source-legend.compact .source-legend-item { min-width: 0; }
.diagnostic-row > .action-panel .task-list {
  /* 패널이 절반 폭이라 카드 두 개를 옆으로 두면 다시 좁아진다 -- 세로로 쌓는다. */
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
}
@container content-col (width < 720px) {
  .source-quality-overview { grid-template-columns: minmax(0, 1fr); }
  .source-legend.compact { grid-template-columns: minmax(0, 1fr); }
  .diagnostic-row > .action-panel .task-list { grid-template-columns: minmax(0, 1fr); }
}

/* 위험 신호(ARS) 카드 -- 상세 페이지(풀폭)는 라벨 3개를 한 줄에 늘어놓으면 값이
   반대쪽 끝으로 밀려 라벨-값 매칭이 안 됐다. .source-summary 통계 박스와 같은
   틀(라벨 위·값 아래)로 3개를 가로로 나란히 둔다. */
.risk-signal-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
@container content-col (width < 600px) { .risk-signal-list { grid-template-columns: 1fr; } }
.risk-signal-row { padding: 11px 12px; border-radius: var(--row-radius); background: var(--surface-muted); }
.risk-signal-row span { display: block; color: var(--muted-strong); font-size: var(--fs-1); font-weight: 700; }
.risk-signal-row strong { display: block; margin-top: 2px; font-size: var(--fs-6); letter-spacing: -.02em; }
.risk-signal-row small { display: block; margin-top: 4px; color: var(--muted); font-size: var(--fs-1); }
.risk-signal-row.is-warning strong { color: #9a3412; }

/* 대시보드 개요의 압축 카드(4장 진단 행)는 폭이 좁아 3열이 욱여넣어진다 -- 기존
   라벨-값 한 줄 표시를 그대로 유지한다. */
.risk-signals-panel.compact .risk-signal-list { grid-template-columns: 1fr; }
.risk-signals-panel.compact .risk-signal-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 10px;
  padding: 8px 10px;
  background: var(--surface-muted);
}
.risk-signals-panel.compact .risk-signal-row span { font-size: var(--fs-2); }
.risk-signals-panel.compact .risk-signal-row strong { margin-top: 0; font-size: var(--fs-4); text-align: right; }
.risk-signals-panel.compact .risk-signal-row small { grid-column: 1 / -1; margin-top: 0; }

/* 경쟁사 대비 노출 추이 탭(노출률/SoV/추천 순위 점수, 2.3절) */
.trend-tabs { display: flex; gap: 6px; margin-bottom: 12px; }
.trend-tab {
  padding: 6px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted-strong);
  font-size: var(--fs-1);
  font-weight: 700;
  cursor: pointer;
}
.trend-tab.is-active { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-dark); }

/* 경쟁사 대비 노출률의 엔진 토글 -- 추이 탭과 같은 칩을 쓰되, 진단 카드 줄의 1/4 폭
 * 패널에도 들어가야 하므로 줄바꿈을 허용하고 여백을 줄인다. */
.competitor-engine-tabs { flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
.competitor-engine-tabs .trend-tab { padding: 4px 10px; }
.competitor-pane-note { display: block; margin-top: 8px; color: var(--muted); font-size: var(--fs-1); }

/* 엔진별 점수 구성 (PRISM 분석 화면) -- 카드 셋을 나란히: 고리(라벨 내장) 위, 엔진별
 * 분해/사유 문구 아래. 카드마다 테두리·배경을 둬 셋이 한 줄로 견줘 읽히게 한다 -- 테두리가
 * 없으면 값이 없는 ARS·ABS는 고리(측정 전)와 사유 한 줄만 남아 옆 AVS 카드의 12줄짜리
 * 엔진 목록과 높이가 크게 갈리는데, 카드 경계가 없으면 그 빈 여백이 "렌더가 덜 됐다"로 읽힌다.
 * align-items:stretch(그리드 기본값)로 셋의 높이를 맞추고, 카드 스스로도 height:100%로 그 늘어난
 * 칸을 채운다. */
.score-triple-panel .score-triple {
  display: grid;
  /* 열 수를 바깥 main 폭으로 추측하지 않고 카드가 실제로 필요한 최소 폭으로 정한다.
   * 420px짜리 카드를 놓을 수 있는 만큼만 배치하므로 브라우저 배율·레일·창 크기 조합과
   * 무관하게 3 → 2 → 1열이 같은 원리로 접힌다. min(100%, ...)은 모바일에서 최소폭
   * 자체가 화면을 밀어내지 않게 한다. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
  gap: 16px;
}
.score-triple-panel .score-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
  gap: 14px;
  height: 100%;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
}
.score-triple-panel .score-card > .score-ring { width: 100%; }
.score-triple-panel .score-card > .score-components,
.score-triple-panel .score-card > .score-reading {
  /* Flex items with width:100% can resolve against the grid track before this
   * card's horizontal padding is removed. Stretch to the content box instead,
   * and allow long engine labels/score headings to shrink inside that box. */
  align-self: stretch;
  min-width: 0;
}
.score-triple-panel .score-component,
.score-triple-panel .score-block-head,
.score-triple-panel .score-engine-list { min-width: 0; }
.score-triple-panel .score-block-head > :first-child {
  min-width: 0;
  overflow-wrap: anywhere;
}
.score-triple-panel .score-engine-name {
  min-width: 0;
  overflow-wrap: anywhere;
}
/* 질문 분석 화면 -- 질문×엔진 매트릭스. 행을 누르면 아래 .qa-detail-row가 펼쳐지며
 * 브랜드 목록·엔진별 선택/제외 이유(.question-competitors 등, 클릭 확장 상세 안에서
 * 재사용)를 보여준다. */
.qa-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; margin-bottom: 16px; }
.qa-stat {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface);
}
.qa-stat small { display: block; margin-bottom: 4px; color: var(--muted); font-size: var(--fs-1); }
.qa-stat strong { font-size: var(--fs-3); font-weight: 800; }
.qa-stat.is-strong strong { color: var(--pos); }
.qa-stat.is-weak strong { color: var(--warning); }
.qa-stat-question { display: inline-block; max-width: 60%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }

.qa-table-wrap { overflow-x: auto; }
/* table-layout: fixed + explicit widths per column class -- PRISM 구조별 표(위)와 질문별
 * 표(아래)는 서로 다른 <table>이라 열 너비를 브라우저가 각자 알아서 정하면(auto layout)
 * 같은 이름의 열(AI 챗/웹검색/국내/노출률)이 두 표에서 다른 x 위치에 떨어진다. 열 폭을
 * 고정해 두 표가 나란히 놓였을 때 같은 열끼리 맞춰 보이게 하고, 질문 열은 내용 길이에
 * 따라 표 폭 대부분을 먹어치우던 것을 막는다. */
.qa-table { width: 100%; min-width: 480px; border-collapse: collapse; font-size: var(--fs-1); table-layout: fixed; }
.qa-table th, .qa-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: center; white-space: nowrap; }
.qa-table thead th { color: var(--muted); font-weight: 800; background: var(--surface-muted); }
/* `.qa-table th, .qa-table td`(클래스+엘리먼트, 명시도 0-1-1)가 아래 열별 text-align
 * 규칙(명시도 0-1-0)보다 더 구체적이라 원래 늘 이겨 왔다 -- 질문 칸은 본문이
 * display:flex라 text-align이 애초에 영향을 안 줘서(align-items가 대신 배치) 우연히
 * 왼쪽 정렬로 "보였을" 뿐, <th>는 플레인 텍스트라 그 우연이 없어 가운데로 그려졌다.
 * `.qa-table .qa-col-*`로 명시도를 올려 이 칸들이 실제로 이기게 한다. 본문 셀은
 * 헤더와 클래스명이 달라(qa-rate-cell/qa-group-cell) 폭은 table-layout:fixed가 첫
 * 행(헤더) 기준으로 이어받지만 정렬은 안 물려받으므로 따로 명시한다. */
.qa-table .qa-col-group, .qa-table .qa-group-cell { width: 96px; border-left: 1px solid var(--line); }
/* 노출률 열도 그룹 열과 같은 구성(가운데 정렬·숫자 위/막대 아래·왼쪽 세로줄) -- 이 열만
 * 우정렬 가로 나열이던 동안 국내 검색과의 사이가 빈 띠처럼 벌어져 보였다. */
.qa-table .qa-col-rate, .qa-table .qa-rate-cell { width: 110px; border-left: 1px solid var(--line); }
.qa-col-rate { cursor: pointer; }
.qa-col-rate:hover { color: var(--text); }
.qa-col-rate:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.qa-table .qa-prism-count { width: 84px; color: var(--muted); }
/* 질문 열은 표가 옆으로 넘칠 때도 늘 보이게 고정한다 -- 엔진 그룹을 3열로 압축한
 * 뒤로는 잘 안 생기지만, 계정에 따라 여전히 좁은 화면에서는 넘칠 수 있다. 배경을
 * 명시해야 스크롤되는 뒤 칸이 고정 열 밑으로 비치지 않는다. */
/* 질문 열만 width를 안 준다 -- table-layout:fixed에서 폭 없는 열은 "나머지 전부"를
 * 받는다. 덕분에 PRISM 표(질문 수 열이 하나 더 있음)와 질문 표의 엔진 열이 저절로
 * 같은 x에 선다: 두 표의 첫 열 폭 차이가 정확히 '질문 수' 열 폭만큼이기 때문이다. */
.qa-table .qa-col-question {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
  text-align: left;
  white-space: normal;
}
.qa-table thead .qa-col-question { z-index: 2; background: var(--surface-muted); }

.qa-row { cursor: pointer; }
.qa-row:hover, .qa-row:hover .qa-col-question, .qa-row:hover .qa-question-cell { background: var(--surface-muted); }
.qa-row:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
/* 질문 칸은 절대 <td> 자신을 flex 컨테이너로 만들면 안 된다. `display:flex`는 <td>의
 * `display:table-cell`을 덮어써서 그 칸을 표의 열 계산에서 빼 버린다(브라우저가 익명
 * 셀로 감싼다) -- 그러면 열 폭(width)도, sticky도, 아래 테두리도 전부 안 먹고 칸이
 * 제 내용만큼만 좁아진다. 실측으로 헤더 열은 454px인데 본문 질문 칸만 181px로 좁아져
 * 있었고, 헤더/본문 어긋남·과한 줄바꿈·사라진 가로줄이 전부 여기서 나왔다.
 * flex는 칸 안의 래퍼(.qa-question-main)가 맡고 <td>는 평범한 표 칸으로 남긴다. */
.qa-question-cell { vertical-align: middle; text-align: left; white-space: normal; word-break: keep-all; }
.qa-question-main { display: flex; align-items: center; gap: 8px; }
.qa-question-text { font-weight: 700; }
.qa-competitor-badge {
  /* inline-block이라 알약이 내용만큼만 넓어진다(block이면 칸 전체를 채운 띠가 된다).
   * 질문 아래 자기 줄에 서고, 이름이 아무리 길어도 칸 안에서 ellipsis로 끝난다. */
  display: inline-block;
  /* 30px = 영역 칩 22px + .qa-question-main의 gap 8px. 배지를 질문 텍스트와 같은
   * x에 세워 한 줄짜리 블록으로 읽히게 한다(칩 아래로 파고들지 않는다). */
  max-width: calc(100% - 30px);
  margin: 5px 0 0 30px;
  vertical-align: top;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: var(--fs-1);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--muted-strong);
  background: var(--surface-muted);
}

/* 엔진 그룹 칸 -- 엔진 하나하나 대신 "노출/실행" 집계 하나만 찍는다. 개별 엔진은
 * title 툴팁과, 질문 행이면 클릭 시 펼쳐지는 상세(.question-engine-list)에 남는다. */
.qa-group-cell { min-width: 64px; }
.qa-group-cell.is-empty { color: var(--line); }
.qa-group-frac { display: block; font-weight: 700; font-variant-numeric: tabular-nums; }
.qa-group-cell.is-strong .qa-group-frac { color: var(--pos); }
.qa-group-cell.is-weak .qa-group-frac { color: var(--warning); }
.qa-group-bar-track { display: block; height: 4px; margin-top: 3px; border-radius: 999px; background: var(--surface-muted); overflow: hidden; }
.qa-group-bar { display: block; height: 100%; background: var(--brand); }
.qa-group-cell.is-strong .qa-group-bar { background: var(--pos); }
.qa-group-cell.is-weak .qa-group-bar { background: var(--warning); }

.qa-rate-cell strong { display: block; font-variant-numeric: tabular-nums; }
.qa-rate-cell.is-strong strong { color: var(--pos); }
.qa-rate-cell.is-weak strong { color: var(--warning); }
.qa-rate-bar-track { display: block; height: 4px; margin-top: 3px; border-radius: 999px; background: var(--surface-muted); overflow: hidden; }
.qa-rate-bar { display: block; height: 100%; background: var(--brand); }
.qa-rate-cell.is-strong .qa-rate-bar { background: var(--pos); }
.qa-rate-cell.is-weak .qa-rate-bar { background: var(--warning); }

.qa-detail-row td { padding: 14px 16px; background: var(--surface-muted); text-align: left; white-space: normal; cursor: default; }
.qa-prism-panel { margin-bottom: 20px; }
.spectrum-badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.spectrum-badge {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: var(--fs-1);
  font-weight: 800;
  color: var(--text);
  background: color-mix(in srgb, var(--spectrum-color) 22%, transparent);
}
.question-competitors { margin: 0 0 10px; font-size: var(--fs-1); }
.question-competitors > small { display: block; margin-bottom: 4px; color: var(--muted); font-weight: 700; }
.question-competitors .competitor-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.question-competitors .competitor-chips span { padding: 1px 8px; border-radius: 999px; background: var(--surface); }
/* 엔진 상세 -- 표와 같은 3그룹(AI 챗/웹검색/국내 검색) 열로 눕힌다. 엔진을 한 줄씩
 * 세로로 세우면 십수 개 계정에서 상세 하나가 화면을 다 먹고, 이유 텍스트가 오른쪽
 * 끝으로 밀려 어느 엔진의 이유인지 눈으로 잇기 어려웠다. 이유는 엔진 이름 바로
 * 아랫줄에 붙인다. */
.question-engine-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px 28px; align-items: start; }
.question-engine-group h4 { margin: 0 0 6px; padding-bottom: 4px; border-bottom: 1px solid var(--line); font-size: var(--fs-1); color: var(--muted-strong); }
.question-engine-group h4 small { margin-left: 4px; color: var(--muted); font-weight: 700; }
.question-engine-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 7px;
  padding: 3px 0;
  font-size: var(--fs-1);
  color: var(--muted);
}
.question-engine-row.is-exposed { color: var(--text); }
/* 기본 .question-flag(질문 세트 화면 공용)는 흰 상자 알약이라 엔진 수만큼 늘어서면
 * 그것만 보인다 -- 상세 안에서는 색조 배경의 얇은 태그로 줄인다. */
.question-engine-row .question-flag { padding: 0 5px; border-radius: 4px; font-size: var(--fs-1); font-weight: 700; color: var(--muted); background: color-mix(in srgb, var(--muted) 12%, transparent); }
.question-engine-row.is-exposed .question-flag { color: var(--pos); background: color-mix(in srgb, var(--pos) 12%, transparent); }
.question-engine-row .question-reason { flex: 1 1 100%; margin: 0; color: var(--muted); line-height: 1.5; }

/* AI 응답 & 출처 화면 -- 선택/제외 이유 */
.reason-columns { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.reason-columns h3 { margin: 0 0 8px; font-size: var(--fs-2); color: var(--muted-strong); }
.reason-list { margin: 0; padding-left: 18px; }
.reason-list li { margin-bottom: 6px; font-size: var(--fs-1); line-height: 1.6; word-break: keep-all; }
@container content-col (width < 660px) { .reason-columns { grid-template-columns: 1fr; } }

/* 리포트 화면 -- 결과지(A4 2장) 본문 스타일은 css/reports.css의 .report-sheets 절.
 * 여기는 화면 상단 버튼 줄과, 리포트 외 화면에도 걸리는 공용 인쇄 숨김만 남는다. */
.report-toolbar { display: flex; gap: 8px; justify-content: flex-end; margin-bottom: 12px; }
.report-panel { margin-bottom: 12px; }
@media print {
  /* body > header로 앱 레일만 집는다 -- 결과지 마스트헤드(.report-sheets 안 <header>)까지
   * 태그 선택자로 숨기면 인쇄물에서 리포트 머리띠가 사라진다. */
  body > header, .rail-admin-link, #scope-controls, .report-toolbar, .nav { display: none !important; }
  /* 레일을 숨긴 뒤에는 그 폭을 위해 남겨 둔 main 오프셋도 함께 걷는다. 오프셋이
   * 남으면 Chromium이 넓은 데스크톱 캔버스를 A4로 축소하기 전에 페이지를 나눠,
   * 결과지 한 장이 위·아래 두 PDF 페이지로 갈라진다. */
  body[data-workspace-shell="rail"] main {
    max-width: none;
    margin: 0;
    padding: 0;
  }
  body[data-workspace-shell="rail"] #content {
    max-width: none;
    margin: 0;
    padding: 0;
  }
}

/* 리포트 전송 기록(.notification-*) -- 정기 분석이 내보낸 이메일 리포트의 이력이라 이 화면 소속이다.
 * 새로고침 버튼은 .panel-aside(제목 줄 오른쪽)에 둔다 -- 이 화면의 다른 패널이 자기
 * 화면으로 가는 링크를 두는 자리와 같다. */
.notification-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 10px;
}

.notification-summary span {
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  color: var(--muted-strong);
}

.notification-summary b {
  color: var(--brand-dark);
  font-size: var(--fs-6);
}

.notification-summary small {
  font-size: var(--fs-1);
}

/* 목록 안의 버튼은 줄 높이에 맞춘 작은 .secondary다. 색·테두리는 css/forms.css. */
.notification-row button {
  padding: 7px 11px;
  font-size: var(--fs-2);
  white-space: nowrap;
}

.notification-list {
  display: grid;
  gap: 8px;
}

.notification-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  padding: 10px 12px;
}

.notification-row.unread {
  border-color: rgba(10, 189, 163, .38);
  background: var(--brand-soft);
}

.notification-row > div {
  min-width: 0;
  display: grid;
  gap: 4px;
}

.notification-row strong,
.notification-row small,
.notification-row span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.notification-row small,
.notification-row span {
  color: var(--muted);
  font-size: var(--fs-1);
}

.notification-row strong,
.notification-row small {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

#notifications-dialog {
  width: min(760px, 94vw);
  max-height: 85vh;
  overflow-y: auto;
}

#notifications-dialog > label {
  display: block;
  margin: 16px 0;
}

/* 실행 과제 화면의 답변 근거·전략 서사(2026-08-20). 위쪽 .strategy-panel은 LLM이
 * 쓴 진단·방향성·핵심 메시지, 아래 .evidence-panel은 그 서사가 딛고 선 집계다.
 * 두 패널 모두 본문 폭 안에서만 늘어나므로 여기서는 media/container 질의를 쓰지
 * 않는다 -- 좁아지면 그리드 열이 minmax로 먼저 줄고 칩 목록이 접힌다. */
.strategy-diagnosis {
  margin: 14px 0 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
  background: var(--surface-muted);
  color: var(--muted-strong);
  font-size: var(--fs-2);
  line-height: 1.75;
  word-break: keep-all;
}

.strategy-list { display: grid; gap: 8px; margin-top: 14px; }

.strategy-item {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr);
  align-items: start;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--row-radius);
}
.strategy-item > i {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--brand-soft);
  color: var(--brand-dark);
  font-size: var(--fs-1);
  font-style: normal;
  font-weight: 800;
}
.strategy-item b { font-size: var(--fs-3); }
.strategy-item .pill { margin-left: 8px; vertical-align: 2px; }
.strategy-item p {
  margin: 6px 0 0;
  color: var(--muted-strong);
  font-size: var(--fs-2);
  line-height: 1.7;
  word-break: keep-all;
}
/* 방향성 하나하나가 어떤 수치를 딛고 섰는지 -- 이 줄이 없으면 문장이 그냥 조언이 된다. */
.strategy-evidence {
  display: block;
  margin-top: 8px;
  padding-left: 10px;
  border-left: 2px solid var(--brand-soft);
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.6;
  word-break: keep-all;
}

.strategy-messages { margin-top: 18px; }
.strategy-messages h3 { margin: 0 0 8px; font-size: var(--fs-2); }
.strategy-messages ul { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; }
.strategy-messages li {
  padding: 10px 12px;
  border-radius: var(--row-radius);
  background: var(--surface-muted);
}
.strategy-messages li b { font-size: var(--fs-2); line-height: 1.6; word-break: keep-all; }
.strategy-messages li small {
  display: block;
  margin-top: 4px;
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.6;
  word-break: keep-all;
}

.evidence-head { margin: 20px 0 2px; font-size: var(--fs-2); }
.evidence-copy {
  margin: 0 0 10px;
  color: var(--muted);
  font-size: var(--fs-1);
  line-height: 1.6;
  word-break: keep-all;
}

/* 언급 대비 추천 행. .competitor-row의 4열을 그대로 쓰되 맨 앞 순위 칸이 없으므로
 * 이름/횟수/막대/값으로 다시 나눈다. */
.evidence-panel .competitor-row {
  grid-template-columns: minmax(0, 1.3fr) auto minmax(32px, 1fr) auto;
}
.evidence-count { color: var(--muted); font-size: var(--fs-1); white-space: nowrap; }
.evidence-panel .panel-note small { display: block; margin-top: 4px; color: var(--muted); font-size: var(--fs-1); }
.evidence-nometer { display: block; }

.evidence-areas { display: grid; gap: 8px; }
.evidence-area {
  display: grid;
  grid-template-columns: minmax(0, 92px) minmax(40px, 1fr) 44px;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-2);
}
/* 자사 몫이 한 자릿수인 영역에서는 막대가 거의 안 보인다 -- 값은 늘 숫자로도 읽히게 둔다. */
.evidence-area strong { font-size: var(--fs-2); text-align: right; }
.evidence-area small {
  grid-column: 1 / -1;
  margin-top: -4px;
  color: var(--muted);
  font-size: var(--fs-1);
}

.evidence-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.evidence-peers { display: grid; gap: 10px; }
.evidence-peer b { display: block; margin-bottom: 5px; font-size: var(--fs-2); }
