/*
 * Design tokens (color/spacing/radius/shadow/motion/type) live in
 * /shared/design-tokens/tokens.css — loaded BEFORE this file via <link> in
 * index.html. Do NOT redeclare `--ds-*` or theme overrides here.
 */

* {
  box-sizing: border-box;
}

/* ---- Commerce price comparison card v1 -----------------------------------------------
   판매처별 확정 배송비와 같은 규격이 결속된 행만 순위를 갖는다. 데스크톱은 비교표처럼
   읽히는 행, 520px 이하는 순위·총액 중심 세로 목록이다. 색은 기존 테마 토큰만 쓴다. */
/* 2026-08-26 공용 위젯 카드 셸로 이관(차별화 축① 1차 슬라이스).
   컨테이너·표면·실선·모서리·그림자·본문색·상단 여백은 이제
   .wiz-card[data-wiz-density="comfortable"] 가 소유한다(wizon-widget-card-shell.css).
   여기 남는 건 이 카드«만»의 것 — 이름 붙은 컨테이너 하나다. */
.commerce-price-card {
  container-name: commerce-price;
}

.commerce-price-state {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-3);
  margin-top: var(--wds-space-4);
  padding: var(--wds-space-4) var(--wds-space-5);
  border: 1px solid var(--wizon-ai-popover-border);
  border-left: 3px solid var(--wds-color-wizon-accent);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
}

.commerce-price-state h3,
.commerce-price-state p {
  overflow-wrap: anywhere;
}

.commerce-price-state h3 {
  margin: 0;
  font-size: var(--wds-font-size-title-l);
  line-height: var(--wds-line-height-tight);
}

.commerce-price-state p {
  margin: var(--wds-space-1) 0 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-label);
}

.commerce-state-retry {
  justify-self: start;
  min-height: var(--wds-control-height-md);
  padding: var(--wds-space-2) var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font: inherit;
  font-weight: var(--wds-font-weight-medium);
}

.commerce-state-retry:hover,
.commerce-state-retry:focus-visible {
  background: var(--wizon-ai-hover-soft-bg);
}

.commerce-state-retry:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: 2px;
}

/* .commerce-card-head 는 이 묶음에서 빠졌다 — 배치(display/align/justify/gap/padding)와
   아래쪽 실선을 공용 셸의 .wiz-card__head[data-wiz-rule="on"] 가 소유한다. */
.commerce-toolbar,
.commerce-section-head,
.commerce-condition-row,
.commerce-ads,
.commerce-offer {
  display: flex;
  align-items: center;
}

/* .commerce-example-label 은 이 묶음에서 빠졌다 — 셸의 .wiz-card__eyebrow 가 같은
   값을 소유한다(muted · caption · label leading). 나머지 캡션들은 카드 헤더 밖이라
   이번 슬라이스 범위가 아니다. */
.commerce-why span,
.commerce-offer-total > span,
.commerce-offer-unit > span,
.commerce-section-head span {
  display: block;
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

/* ★ .commerce-card-head h3 / .commerce-card-head p 규칙을 지웠다. 그냥 중복이라서가
   아니다: 자손 선택자(0,1,1)는 셸의 .wiz-card__title(0,1,0)을 «특이도로 이긴다».
   남겨 두면 셸을 입혀도 제목·부제는 계속 옛 규칙이 그리고, 화면은 안 바뀌는데
   토큰만 바꾼 듯한 착시가 생긴다. 지워야 셸이 실제로 소유한다.
   제목 위 4px 여백은 이제 __headings 의 gap 이 낸다. */
.commerce-toolbar p,
.commerce-notes p {
  margin: var(--wds-space-1) 0 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-label);
}

.commerce-why {
  flex: 0 0 auto;
  padding-left: var(--wds-space-4);
  border-left: 2px solid var(--wds-color-wizon-accent);
  text-align: right;
}

.commerce-why strong {
  display: block;
  margin-top: var(--wds-space-1);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
}

.commerce-toolbar {
  flex-wrap: wrap;
  gap: var(--wds-space-3);
  justify-content: space-between;
  padding: var(--wds-space-3) var(--wds-space-5);
  background: var(--wizon-ai-canvas);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
}

.commerce-toolbar p {
  margin: 0;
}

.commerce-sort {
  display: inline-flex;
  flex: 0 0 auto;
  padding: var(--wds-space-1);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
}

.commerce-sort button,
.commerce-question-chip {
  min-height: var(--wds-control-height-sm);
  padding: var(--wds-space-2) var(--wds-space-3);
  border: 0;
  border-radius: calc(var(--wizon-ai-radius-control) - var(--wds-space-1));
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-medium);
}

.commerce-sort button[aria-pressed="true"] {
  background: var(--wizon-ai-text-primary);
  color: var(--wds-color-text-on-primary);
}

.commerce-sort button:focus-visible,
.commerce-question-chip:focus-visible,
.commerce-price-card a:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: 2px;
}

.commerce-offers {
  display: grid;
}

.commerce-offer {
  display: grid;
  grid-template-columns: 52px minmax(104px, 0.85fr) minmax(142px, 1.15fr) minmax(126px, 1fr) minmax(132px, 0.9fr);
  gap: var(--wds-space-3);
  min-width: 0;
  padding: var(--wds-space-4) var(--wds-space-5);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
}

.commerce-offer:first-child {
  background: color-mix(in srgb, var(--wds-color-wizon-accent) 7%, var(--wizon-ai-surface));
}

.commerce-offer-rank {
  display: flex;
  align-items: baseline;
  gap: var(--wds-space-1);
  color: var(--wizon-ai-text-primary);
}

.commerce-offer-rank strong {
  font-size: var(--wds-font-size-headline-m);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.commerce-offer-rank span,
.commerce-offer-seller span,
.commerce-offer-total small,
.commerce-offer-unit small,
.commerce-condition-row small {
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.commerce-offer-seller,
.commerce-offer-total,
.commerce-offer-unit,
.commerce-offer-actions,
.commerce-condition-row > span {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-1);
}

.commerce-offer-seller strong,
.commerce-offer-total strong,
.commerce-offer-unit strong {
  overflow-wrap: anywhere;
  font-size: var(--wds-font-size-body-1);
  font-variant-numeric: tabular-nums;
}

.commerce-offer-total strong {
  font-size: var(--wds-font-size-title-l);
}

.commerce-offer-actions {
  justify-items: start;
}

.commerce-price-card a {
  color: var(--wds-color-link);
  font-size: var(--wds-font-size-caption);
  text-decoration: none;
}

.commerce-price-card a:hover {
  text-decoration: underline;
}

.commerce-final-check {
  display: inline-flex;
  align-items: center;
  min-height: var(--wds-control-height-sm);
  padding: var(--wds-space-2) var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font-weight: var(--wds-font-weight-medium);
  white-space: nowrap;
}

.commerce-notes,
.commerce-conditions,
.commerce-ads,
.commerce-question-chips {
  margin: var(--wds-space-4) var(--wds-space-5) 0;
}

.commerce-notes {
  padding: var(--wds-space-3) var(--wds-space-4);
  border-left: 2px solid var(--wds-color-wizon-accent);
  background: var(--wizon-ai-canvas);
}

.commerce-notes p {
  margin-top: var(--wds-space-1);
}

.commerce-conditions {
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
}

.commerce-section-head {
  justify-content: space-between;
  gap: var(--wds-space-3);
  padding: var(--wds-space-3) var(--wds-space-4);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
  background: var(--wizon-ai-canvas);
}

.commerce-condition-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--wds-space-3);
  padding: var(--wds-space-3) var(--wds-space-4);
}

.commerce-condition-row > strong {
  font-variant-numeric: tabular-nums;
}

.commerce-ads {
  flex-wrap: wrap;
  gap: var(--wds-space-2) var(--wds-space-4);
  padding-top: var(--wds-space-3);
  border-top: 1px solid var(--wizon-ai-popover-border);
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
}

.commerce-ads a {
  display: inline-flex;
  gap: var(--wds-space-2);
}

.commerce-ads a span {
  padding-inline: var(--wds-space-2);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
}

.commerce-question-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wds-space-2);
  padding-bottom: var(--wds-space-5);
}

.commerce-question-chip {
  border: 1px solid var(--wizon-ai-popover-border);
  background: var(--wizon-ai-surface);
}

.commerce-question-chip:hover,
.commerce-question-chip:focus-visible {
  background: var(--wizon-ai-hover-soft-bg);
  color: var(--wizon-ai-text-primary);
}

/* Category intelligence stays separate from the exact-product price table: it
   presents verified observations and server-owned display sequences, never a
   browser-calculated cross-product rank. */
.commerce-category-head,
.commerce-category-toolbar,
.commerce-category-product-main,
.commerce-category-product,
.commerce-category-detail li {
  display: flex;
  min-width: 0;
}

.commerce-category-head,
.commerce-category-toolbar {
  justify-content: space-between;
  gap: var(--wds-space-4);
  padding: var(--wds-space-5);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
}

.commerce-category-head h3 {
  margin: var(--wds-space-1) 0;
  font-size: var(--wds-font-size-title-l);
  line-height: var(--wds-line-height-tight);
}

/* The portal prose renderer numbers generic answer headings. Card-local labels
   are product names, not answer sections, so the category card owns them. */
.assistant .message-body .commerce-category-card h3::before,
.assistant .message-body .commerce-category-card h4::before,
.assistant .message-body .commerce-category-card h5::before {
  content: none;
}

.commerce-category-card { counter-reset: md-h3 md-h4 md-h5; }

.commerce-category-head p,
.commerce-category-toolbar p,
.commerce-category-note {
  margin: 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-label);
}

.commerce-category-checked {
  flex: 0 0 auto;
  text-align: right;
}

.commerce-category-toolbar {
  align-items: center;
  flex-wrap: wrap;
  padding-block: var(--wds-space-3);
  background: var(--wizon-ai-canvas);
}

.commerce-category-products {
  display: grid;
}

.commerce-category-product {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(176px, .45fr) minmax(120px, .24fr);
  gap: var(--wds-space-4);
  align-items: start;
  padding: var(--wds-space-5);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
}

.commerce-category-product[data-expanded="true"] {
  background: color-mix(in srgb, var(--wds-color-wizon-accent) 5%, var(--wizon-ai-surface));
}

.commerce-category-product-main {
  gap: var(--wds-space-3);
}

.commerce-category-media {
  flex: 0 0 88px;
  width: 88px;
  margin: 0;
}

.commerce-category-media img {
  display: block;
  width: 88px;
  height: 88px;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  object-fit: contain;
  background: var(--wizon-ai-canvas);
}

.commerce-category-media figcaption,
.commerce-category-price span,
.commerce-category-price small,
.commerce-category-detail small {
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.commerce-category-media figcaption {
  margin-top: var(--wds-space-1);
}

.commerce-category-copy {
  min-width: 0;
}

.commerce-category-brand {
  margin: 0 0 var(--wds-space-1);
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
}

.commerce-category-copy h4 {
  margin: 0;
  overflow-wrap: anywhere;
  font-size: var(--wds-font-size-body-1);
  line-height: var(--wds-line-height-tight);
}

.commerce-category-advantages,
.commerce-category-detail ul {
  display: grid;
  gap: var(--wds-space-1);
  margin: var(--wds-space-2) 0 0;
  padding: 0;
  list-style: none;
}

.commerce-category-advantages {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.commerce-category-advantages li::before {
  content: "•";
  margin-right: var(--wds-space-1);
  color: var(--wds-color-wizon-accent);
}

.commerce-category-specs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wds-space-1) var(--wds-space-2);
  margin: var(--wds-space-2) 0 0;
}

.commerce-category-specs div {
  display: inline-flex;
  gap: var(--wds-space-1);
  padding: var(--wds-space-1) var(--wds-space-2);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  font-size: var(--wds-font-size-caption);
}

.commerce-category-specs dt { color: var(--wizon-ai-text-muted); }
.commerce-category-specs dd { margin: 0; color: var(--wizon-ai-text-primary); }

.commerce-category-price {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-1);
  text-align: right;
}

.commerce-category-price strong {
  overflow-wrap: anywhere;
  font-size: var(--wds-font-size-title-l);
  font-variant-numeric: tabular-nums;
}

.commerce-category-price b {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  font-variant-numeric: tabular-nums;
}

.commerce-category-expand {
  min-height: var(--wds-control-height-md);
  padding: var(--wds-space-2) var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
}

.commerce-category-expand[aria-expanded="true"],
.commerce-category-expand:hover {
  background: var(--wizon-ai-hover-soft-bg);
}

.commerce-category-expand:focus-visible,
.commerce-category-detail a:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: 2px;
}

.commerce-category-detail {
  grid-column: 1 / -1;
  min-width: 0;
  padding-top: var(--wds-space-3);
  border-top: 1px dashed var(--wizon-ai-popover-border);
}

.commerce-category-detail h5 {
  margin: 0;
  font-size: var(--wds-font-size-body-2);
}

.commerce-category-detail li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--wds-space-2);
  align-items: baseline;
  padding: var(--wds-space-2) 0;
  border-bottom: 1px solid var(--wizon-ai-popover-border);
  font-size: var(--wds-font-size-caption);
}

.commerce-category-detail li small,
.commerce-category-detail li a {
  grid-column: 1 / -1;
}

.commerce-category-detail b { font-variant-numeric: tabular-nums; }

.commerce-category-detail > p {
  margin: var(--wds-space-3) 0 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.commerce-category-detail > p a {
  display: inline;
  margin-left: var(--wds-space-1);
}

.commerce-category-caution {
  padding-left: var(--wds-space-2);
  border-left: 2px solid var(--wds-color-wizon-accent);
}

.commerce-category-note {
  margin: var(--wds-space-4) var(--wds-space-5) var(--wds-space-5);
  padding: var(--wds-space-3) var(--wds-space-4);
  border-left: 2px solid var(--wds-color-wizon-accent);
  background: var(--wizon-ai-canvas);
}

/* The category surface is intentionally editorial and dense: a product row has
   one identity/spec rail, one verified-price rail and one controlled disclosure,
   instead of repeating equal generic cards. */
.commerce-category-card {
  overflow: hidden;
  box-shadow: 0 10px 28px color-mix(in srgb, var(--wizon-ai-text-primary) 8%, transparent);
}

.commerce-category-head {
  align-items: flex-end;
  background: linear-gradient(120deg, color-mix(in srgb, var(--wds-color-wizon-accent) 7%, var(--wizon-ai-surface)), var(--wizon-ai-surface) 56%);
}

.commerce-category-head h3 {
  max-width: 26ch;
  font-size: var(--wds-font-size-display-s);
}

.commerce-category-toolbar {
  border-bottom-color: color-mix(in srgb, var(--wizon-ai-popover-border) 72%, var(--wds-color-wizon-accent));
}

.commerce-category-product {
  grid-template-columns: minmax(0, 1fr) minmax(204px, .42fr) minmax(126px, .22fr);
  gap: var(--wds-space-5);
  padding-block: calc(var(--wds-space-5) + var(--wds-space-1));
  transition: background-color 160ms ease;
}

.commerce-category-product[data-expanded="true"] {
  background: color-mix(in srgb, var(--wds-color-wizon-accent) 6%, var(--wizon-ai-surface));
}

.commerce-category-product-main { gap: var(--wds-space-4); }

.commerce-category-media,
.commerce-category-media img {
  width: 96px;
}

.commerce-category-media { flex-basis: 96px; }

.commerce-category-media img {
  height: 96px;
  border-color: color-mix(in srgb, var(--wizon-ai-popover-border) 72%, var(--wds-color-wizon-accent));
  background: color-mix(in srgb, var(--wds-color-wizon-accent) 3%, var(--wizon-ai-canvas));
}

.commerce-category-media--missing {
  display: grid;
  min-height: 96px;
  place-items: center;
  border: 1px dashed var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
  text-align: center;
}

.commerce-category-brand {
  color: var(--wds-color-wizon-accent);
  font-weight: var(--wds-font-weight-semibold);
  letter-spacing: .02em;
}

.commerce-category-copy h4 {
  font-size: var(--wds-font-size-title-l);
  line-height: 1.38;
}

.commerce-category-advantages {
  gap: 2px;
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-label);
}

.commerce-category-advantages li::before {
  content: none;
}

.commerce-category-advantages li {
  padding-left: var(--wds-space-2);
  border-left: 2px solid color-mix(in srgb, var(--wds-color-wizon-accent) 62%, transparent);
}

.commerce-category-specs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--wds-space-3);
  margin-top: var(--wds-space-3);
  padding-top: var(--wds-space-2);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.commerce-category-specs div,
.commerce-category-all-specs div {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr);
  gap: var(--wds-space-2);
  padding: var(--wds-space-1) 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

.commerce-category-specs dd,
.commerce-category-all-specs dd { overflow-wrap: anywhere; }

.commerce-category-price {
  align-content: start;
  gap: var(--wds-space-2);
  padding-left: var(--wds-space-4);
  border-left: 1px solid var(--wizon-ai-popover-border);
  text-align: left;
}

.commerce-category-price strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-display-s);
  letter-spacing: -.025em;
  line-height: 1;
}

.commerce-category-price b {
  color: var(--wds-color-wizon-accent);
  font-weight: var(--wds-font-weight-semibold);
}

.commerce-category-price-provenance {
  margin: 0;
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.commerce-category-price > a {
  display: inline-flex;
  width: fit-content;
  min-height: var(--wds-control-height-sm);
  align-items: center;
  margin-top: var(--wds-space-1);
  padding: 0 var(--wds-space-2);
  border-bottom: 1px solid color-mix(in srgb, var(--wds-color-link) 45%, transparent);
  color: var(--wds-color-link);
  font-weight: var(--wds-font-weight-medium);
}

.commerce-category-expand {
  align-self: center;
  border-color: color-mix(in srgb, var(--wds-color-wizon-accent) 38%, var(--wizon-ai-popover-border));
  font-weight: var(--wds-font-weight-semibold);
}

.commerce-category-expand[aria-expanded="true"] {
  border-color: var(--wds-color-wizon-accent);
  color: var(--wds-color-wizon-accent);
}

.commerce-category-detail {
  padding-top: var(--wds-space-4);
  border-top-style: solid;
}

.commerce-category-detail-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(240px, .8fr);
  gap: var(--wds-space-4) var(--wds-space-6);
}

.commerce-category-detail[data-motion="open"] .commerce-category-detail-inner {
  animation: commerce-category-detail-in 180ms ease-out both;
}

@keyframes commerce-category-detail-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.commerce-category-detail-heading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--wds-space-3);
  grid-column: 1 / -1;
}

.commerce-category-detail-heading p {
  margin: 0;
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
}

.commerce-category-detail ul { margin: 0; }

.commerce-category-detail li {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--wds-space-2) var(--wds-space-4);
}

.commerce-category-detail li a {
  width: fit-content;
  font-weight: var(--wds-font-weight-medium);
}

.commerce-category-all-specs {
  display: grid;
  align-content: start;
  gap: 0 var(--wds-space-3);
  margin: 0;
  padding: var(--wds-space-3);
  border-left: 2px solid var(--wds-color-wizon-accent);
  background: color-mix(in srgb, var(--wds-color-wizon-accent) 3%, var(--wizon-ai-canvas));
}

.commerce-category-detail > .commerce-category-detail-inner > p { margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .commerce-category-product { transition: none; }
  .commerce-category-detail[data-motion="open"] .commerce-category-detail-inner { animation: none; }
}

@container commerce-price (max-width: 900px) {
  .commerce-category-product {
    grid-template-columns: minmax(0, 1fr) minmax(160px, .42fr);
  }

  .commerce-category-expand {
    grid-column: 1 / -1;
  }

  .commerce-category-detail-inner {
    grid-template-columns: 1fr;
  }
}

@container commerce-price (max-width: 520px) {
  .commerce-card-head {
    align-items: flex-start;
    padding: var(--wds-space-4);
  }

  .commerce-why {
    display: none;
  }

  .commerce-toolbar {
    align-items: stretch;
    padding: var(--wds-space-3) var(--wds-space-4);
  }

  .commerce-sort {
    width: 100%;
  }

  .commerce-sort button {
    flex: 1 1 50%;
    min-height: var(--wds-control-height-md);
  }

  .commerce-toolbar p {
    width: 100%;
  }

  .commerce-offer {
    grid-template-columns: 42px minmax(0, 1fr) auto;
    grid-template-areas:
      "rank seller total"
      "rank unit unit"
      "rank actions actions";
    gap: var(--wds-space-2) var(--wds-space-3);
    padding: var(--wds-space-4);
  }

  .commerce-offer-rank { grid-area: rank; }
  .commerce-offer-seller { grid-area: seller; }
  .commerce-offer-total { grid-area: total; text-align: right; }
  .commerce-offer-unit { grid-area: unit; }
  .commerce-offer-actions { grid-area: actions; grid-template-columns: 1fr; }

  .commerce-offer-total strong {
    font-size: var(--wds-font-size-title-l);
  }

  .commerce-final-check {
    justify-content: center;
    min-height: var(--wds-control-height-md);
  }

  .commerce-notes,
  .commerce-conditions,
  .commerce-ads,
  .commerce-question-chips {
    margin-inline: var(--wds-space-4);
  }

  .commerce-condition-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .commerce-condition-row a {
    grid-column: 1 / -1;
  }

  .commerce-question-chip {
    min-height: var(--wds-control-height-md);
  }

  .commerce-price-state {
    padding: var(--wds-space-4);
  }

  .commerce-state-retry {
    width: 100%;
  }

  .commerce-category-head,
  .commerce-category-toolbar,
  .commerce-category-product {
    padding-inline: var(--wds-space-4);
  }

  .commerce-category-head,
  .commerce-category-toolbar {
    align-items: stretch;
  }

  .commerce-category-checked {
    text-align: left;
  }

  .commerce-category-toolbar .commerce-sort {
    width: 100%;
  }

  .commerce-category-toolbar .commerce-sort button {
    flex: 1 1 0;
    min-width: 0;
    padding-inline: var(--wds-space-1);
  }

  .commerce-category-product {
    grid-template-columns: minmax(0, 1fr);
  }

  .commerce-category-product-main {
    align-items: flex-start;
  }

  .commerce-category-media,
  .commerce-category-media img {
    width: 72px;
  }

  .commerce-category-media { flex-basis: 72px; }
  .commerce-category-media img { height: 72px; }
  .commerce-category-media--missing { min-height: 72px; }

  .commerce-category-copy h4 { font-size: var(--wds-font-size-body-1); }

  .commerce-category-specs { grid-template-columns: 1fr; }

  .commerce-category-price {
    padding: var(--wds-space-3);
    border: 1px solid var(--wizon-ai-popover-border);
    border-radius: var(--wizon-ai-radius-control);
    background: var(--wizon-ai-canvas);
    text-align: left;
  }

  .commerce-category-expand { width: 100%; }
  .commerce-category-detail li { grid-template-columns: minmax(0, 1fr) auto; }
  .commerce-category-detail li b { grid-column: 1 / -1; }
  .commerce-category-detail-heading { align-items: flex-start; flex-direction: column; }
  .commerce-category-detail-inner { gap: var(--wds-space-4); }
  .commerce-category-note { margin-inline: var(--wds-space-4); }
}

@media (prefers-reduced-motion: reduce) {
  .commerce-price-card * {
    scroll-behavior: auto;
  }
}

html,
body {
  width: 100%;
  min-width: 320px;
  height: 100%;
  margin: 0;
}

/* WS-K2 — 한국어 어절 단위 줄바꿈 기본값 (lang 게이트·상속 기반, WS-K1 admin과 동일 패턴).
   keep-all: 한글 음절 중간 분리 방지(라틴 무영향). overflow-wrap 동반: 공백 없는 초장문
   토큰(URL/코드/ID)은 넘칠 때만 끊어 오버플로 방지. body에만 걸어 상속되므로 더 높은
   특이도의 기존 규칙(overflow-wrap: anywhere, .message-body pre의 overflow: auto 등)이
   언제나 이겨 코드/URL/mono 예외를 자동 존중. 근거: docs/product/218. */
body:lang(ko) {
  word-break: keep-all;
  overflow-wrap: break-word;
}

button,
input,
select,
textarea {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled {
  cursor: not-allowed;
  opacity: 0.58;
}

.app-shell {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  width: 100%;
  min-height: 100vh;
}

.sidebar {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-height: 100vh;
  padding: 18px;
  background: #111827;
  color: #f8fafc;
  border-right: 1px solid #0f172a;
}

.brand-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 46px;
}

.brand-row strong {
  display: block;
  font-size: var(--ds-text-body-16);
  line-height: 1.2;
}

.brand-row span {
  display: block;
  margin-top: 3px;
  color: #b8c2cc;
  font-size: var(--ds-text-caption-12);
}
.sidebar-section {
  display: grid;
  gap: 8px;
}

.sidebar-section.grow {
  flex: 1;
  min-height: 0;
}

.section-label,
.eyebrow {
  margin: 0;
  color: #6b7785;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1.2;
  text-transform: uppercase;
}

.sidebar .section-label {
  color: #9aa7b4;
}

select,
input,
textarea {
  width: 100%;
  min-height: 42px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  color: var(--ink);
  outline: none;
}

select,
input {
  padding: 0 12px;
}

textarea {
  display: block;
  padding: 11px 12px;
  line-height: 1.45;
  resize: vertical;
}

select:focus,
input:focus,
textarea:focus {
  border-color: var(--ds-input-border-focus);
  box-shadow: 0 0 0 2px var(--ds-input-ring-focus);
}

.recent-list {
  display: grid;
  align-content: start;
  gap: 6px;
  overflow-x: hidden;
  overflow-y: auto;
  min-height: 0;
}

.recent-item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px;
  width: 100%;
  min-height: 50px;
  padding: 2px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: #f8fafc;
  text-align: left;
}

/* "답변 대기 중" 배지 — 사이드바 최근 채팅 행. .ds-badge--dot 토큰을 그대로 쓰고
   (71-component-rulebook.md §4.6) 위치만 이 행에 맞춘다. absolute라 base(grid 2열)와
   chatgpt-reference-v1(block) 두 레이아웃 모두에서 격자/흐름에 끼지 않고 떠 있으므로,
   테마별로 따로 자리를 잡을 필요가 없다 — .recent-item은 두 테마 모두 position:relative. */
.recent-item .recent-pending-badge {
  position: absolute;
  top: 6px;
  right: 6px;
  pointer-events: none;
  z-index: 1;
}

.recent-primary {
  display: grid;
  align-content: center;
  gap: 5px;
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 7px 8px;
  border: 0;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: inherit;
  text-align: left;
}

@media (hover: hover) {
  .recent-item:hover {
    border-color: rgba(255, 255, 255, 0.15);
    background: rgba(255, 255, 255, 0.07);
  }
}

.recent-item span,
.recent-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.recent-item small {
  color: #9aa7b4;
  font-size: var(--ds-text-micro-11);
}

.recent-actions {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  opacity: 0;
  pointer-events: none;
}

/* Reveal on focus (tap) always; reveal on :hover only for hover-capable (non-touch)
   devices. On iOS Safari a :hover rule that reveals hidden content makes the FIRST tap a
   hover-only gesture (the click is swallowed → two taps needed). Base rule counterpart to
   the .chatgpt-reference-v1 guard (doc 143, 20260709-mobile-recent-hover-firsttap). */
.recent-item:focus-within .recent-actions {
  opacity: 1;
  pointer-events: auto;
}

@media (hover: hover) {
  .recent-item:hover .recent-actions {
    opacity: 1;
    pointer-events: auto;
  }
}

.recent-action {
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: currentColor;
}

.main-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 100vh;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 78px;
  padding: 18px 24px;
  background: rgba(255, 255, 255, 0.92);
  border-bottom: 1px solid var(--line);
}

.topbar h1 {
  margin: 3px 0 0;
  font-size: var(--ds-text-title-20);
  font-weight: 600;
  line-height: 1.25;
}

.status-stack {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  max-width: 240px;
  padding: 0 10px;
  border-radius: 8px;
  background: var(--accent-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.status-pill.soft {
  border-color: rgba(249, 115, 22, 0.22);
  background: #fff4eb;
  color: #9a4d00;
}

.workbench {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 380px;
  gap: 0;
  flex: 1;
  min-height: 0;
}

.chat-pane,
.context-pane {
  min-height: 0;
}

.chat-pane {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  /* Single implicit column MUST be minmax(0, 1fr): without it the auto column sizes to the widest
     child's max-content (~420px from the composer/card), which on a phone (<420px pane) overflows
     the pane and pushed the question card's right side — badge + close X — off-screen (doc 166 후속
     mobile fix). Identical to the current desktop rendering (content already fills the pane there). */
  grid-template-columns: minmax(0, 1fr);
  background: #fbfcfd;
}

.message-list {
  display: flex;
  flex-direction: column;
  gap: 18px;
  min-height: 0;
  overflow: auto;
  padding: 32px min(7vw, 72px);
}

/* "맨 아래로" jump button (ChatGPT/Claude parity). Nested INSIDE the composer form (already
   position:relative) and anchored with bottom:100% so it floats just above the ComposerBar and
   tracks its autogrowing height in pure CSS. It is deliberately NOT a child of the .chat-pane grid:
   an absolutely-positioned child there collapses the grid's minmax(0,1fr) row on iOS Safari, which
   shoved the composer to the middle (doc 170 regression). Hidden until the user scrolls up. */
.scroll-to-bottom {
  position: absolute;
  left: 50%;
  bottom: 100%; /* top edge of the composer */
  margin-bottom: 12px;
  z-index: 30;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-surface, #fff);
  color: var(--cg-text, var(--text));
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, 8px);
  transition: opacity 160ms ease, transform 160ms ease, background 120ms ease;
}
.scroll-to-bottom.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.scroll-to-bottom:hover {
  background: var(--cg-hover-soft, var(--surface-2));
}
.scroll-to-bottom:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 2px;
}
.scroll-to-bottom .scroll-to-bottom-icon,
.scroll-to-bottom [data-icon] {
  display: inline-flex;
}
.scroll-to-bottom .scroll-to-bottom-icon svg,
.scroll-to-bottom svg {
  width: 18px;
  height: 18px;
}
@media (prefers-reduced-motion: reduce) {
  .scroll-to-bottom {
    transition: opacity 160ms ease;
    transform: translate(-50%, 0);
  }
}

.welcome {
  display: grid;
  gap: 12px;
  max-width: 720px;
  margin: auto;
  padding: 8px;
}

.welcome h2 {
  margin: 0;
  font-size: var(--ds-text-heading-32);
  font-weight: 600;
  line-height: 1.12;
}

.welcome p {
  max-width: 620px;
  margin: 0;
  color: var(--muted);
  line-height: 1.6;
}

.prompt-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-top: 8px;
}

.prompt-row button,
.feedback-row button {
  min-height: 38px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  color: var(--ink);
  text-align: left;
}

.prompt-row button:hover,
.feedback-row button:hover,
.secondary-button:hover {
  border-color: var(--accent);
}

.message {
  display: grid;
  grid-template-columns: 42px minmax(0, 760px);
  gap: 12px;
  align-items: start;
}

.message.user {
  justify-content: end;
}

/* E-B1: 시맨틱 토큰 매핑(다크 적응 + 라이트 근사) — docs/product/218, .chat-failure 선례 */
.message-label {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: color-mix(in srgb, var(--ds-color-ink) 8%, var(--ds-color-surface));
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.message.user .message-label {
  background: var(--ds-feedback-warn-bg);
  color: var(--ds-feedback-warn-fg);
}

.message-body {
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--ds-shadow-xs);
}

.message.user .message-body {
  background: var(--accent-soft);
}

/* Question card — WDS AI-guidelines "되묻기" shell, docked above the composer.
   Themed entirely with WIZON portal tokens (--cg-* → --wizon-ai-*), monochrome to match
   the rest of the shell. The primary action reuses the composer send treatment (--cg-send-*).
   Placement: #orchestrationDock sits between the message list and the composer. */
.orchestration-dock {
  width: 100%;
  max-width: var(--cg-chat-max-width, 800px);
  margin: 0 auto;
  padding: 0 var(--cg-composer-gutter, 12px) 10px;
  box-sizing: border-box;
}

.orchestration-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  /* doc 167 §4.2: inline card sits one rank below the sheet (18) — popover-tier 16. */
  border-radius: var(--wizon-ai-radius-popover, 16px);
  background: var(--cg-menu-bg, var(--surface, #fff));
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line)), var(--cg-menu-shadow);
}

.orchestration-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-muted, var(--muted));
}

.orchestration-card-status {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cg-muted, var(--muted));
}

.orchestration-card-context {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Close (X) — cancel the card when asked wrong by mistake (doc 166 §3.4). */
.orchestration-card-close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -6px -6px -6px 0;
  padding: 0;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  background: transparent;
  color: var(--cg-muted, var(--muted));
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
}

.orchestration-card-close:hover {
  background: var(--cg-surface-secondary);
  color: var(--cg-text, var(--text));
}

.orchestration-card-close:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 1px;
}

/* Collapsed state left in the thread after a question card is closed — a "다시 선택" note plus
   the original prompt and re-selectable option chips (Claude AskUserQuestion parity). */
.reask-dismissed {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 640px;
  padding: 12px 14px;
  /* doc 167 §4.2: collapsed remnant is the demoted rank — menu-tier 12. */
  border-radius: var(--wizon-ai-menu-radius, 12px);
  background: var(--cg-surface-secondary);
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line));
}

.reask-dismissed-head {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-muted, var(--muted));
}

/* Answered variant — the closed card transitions here once the user re-picks an option. Compact
   single line, visually distinct from the closed state (research: answered ≠ dismissed). */
.reask-dismissed.reask-resolved {
  display: inline-flex;
  padding: 8px 12px;
}

.reask-resolved .reask-dismissed-head {
  color: var(--cg-muted, var(--muted));
}

.chatgpt-reference-v1 .reask-resolved-icon .wds-inline-icon {
  color: var(--cg-success);
}

.reask-dismissed-icon {
  display: inline-flex;
  flex: none;
}

.reask-dismissed-prompt {
  margin: 0;
  font-size: var(--cg-text-body-size, 16px);
  color: var(--cg-text, var(--text));
}

.reask-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.reask-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 6px 12px;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  background: var(--cg-surface, #fff);
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line));
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-text, var(--text));
  cursor: pointer;
  transition: background-color 120ms ease, box-shadow 120ms ease;
}

.reask-chip:hover {
  background: var(--cg-surface-secondary);
  box-shadow: inset 0 0 0 1px var(--cg-muted, var(--muted));
}

.reask-chip:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 1px;
}

.reask-chip-pill {
  padding: 1px 6px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-hover);
  color: var(--cg-text, inherit);
  font-size: var(--ds-text-micro-11);
}

/* "다시 열기" — reopen a closed text-only card (no chips to re-select). */
.reask-reopen-row {
  display: flex;
}

.reask-reopen {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  background: var(--cg-surface, #fff);
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line));
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-text, var(--text));
  cursor: pointer;
  transition: background-color 120ms ease, box-shadow 120ms ease;
}

.reask-reopen:hover {
  background: var(--cg-surface-secondary);
  box-shadow: inset 0 0 0 1px var(--cg-muted, var(--muted));
}

.reask-reopen:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 1px;
}

.orchestration-card-title {
  margin: 0;
  font-size: var(--cg-text-title-size, 18px);
  font-weight: var(--cg-text-title-weight, 600);
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: var(--cg-text, inherit);
}

.orchestration-options {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.orchestration-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 10px 12px;
  text-align: left;
  cursor: pointer;
  border: 0;
  border-radius: var(--wizon-ai-radius-menu-row, 10px);
  background: transparent;
  color: var(--cg-text, inherit);
  transition: background 140ms ease, box-shadow 140ms ease, transform 90ms ease;
}

/* Hairline divider between consecutive options — a grouped list, not stacked boxes. */
.orchestration-opt + .orchestration-opt {
  border-top: 1px solid var(--cg-hover);
}

.orchestration-opt:hover,
.orchestration-opt:focus-visible {
  outline: none;
  background: var(--cg-hover-soft, var(--surface));
  box-shadow: inset 0 0 0 1.5px var(--cg-focus-visible-ring, var(--cg-focus-ring));
}

/* Hide the dividers touching a filled row so its rounded highlight isn't cut by a hairline. */
.orchestration-opt:hover,
.orchestration-opt:focus-visible,
.orchestration-opt:hover + .orchestration-opt,
.orchestration-opt:focus-visible + .orchestration-opt {
  border-top-color: transparent;
}

.orchestration-opt:active {
  transform: scale(0.99);
}

/* Plain leading glyph — the filled 34px tile per row added weight; a muted icon in a slim slot
   keeps scannability without the boxiness (doc 167 P1-B). */
.orchestration-opt-icon {
  flex: none;
  width: 22px;
  display: grid;
  place-items: center;
  color: var(--cg-muted-2, var(--muted));
}

.orchestration-opt-icon svg {
  width: 19px;
  height: 19px;
}

.orchestration-opt-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.orchestration-opt-title {
  font-size: var(--cg-text-label-size, 14px);
  font-weight: var(--cg-text-label-active-weight, 500);
}

.orchestration-opt-desc {
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-muted, var(--muted));
}

.orchestration-opt-pill {
  flex: none;
  padding: 2px 10px;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  font-size: var(--ds-text-micro-11);
  font-weight: 500;
  color: var(--cg-text, inherit);
  background: var(--cg-hover);
}

.orchestration-opt-key {
  flex: none;
  padding: 2px 8px;
  border-radius: var(--ds-radius-xs, 6px);
  font-size: var(--ds-text-micro-11);
  font-variant-numeric: tabular-nums;
  color: var(--cg-muted, var(--muted));
  background: var(--cg-hover-soft, rgba(0, 0, 0, 0.04));
}

.orchestration-other {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 14px;
  border-radius: var(--wizon-ai-menu-radius, 12px);
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line));
  transition: box-shadow 140ms ease;
}

.orchestration-other:focus-within {
  box-shadow: inset 0 0 0 1.5px var(--cg-text, var(--muted));
}

.orchestration-other-label {
  flex: none;
  font-size: var(--cg-text-meta-size, 12px);
  color: var(--cg-muted, var(--muted));
}

.orchestration-other-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 9px 0;
  border: 0;
  background: transparent;
  color: var(--cg-text, inherit);
  font: inherit;
  font-size: var(--ds-text-body-14);
}

.orchestration-other-input:focus {
  /* Suppress the global input:focus blue ring (--ds-input-ring-focus); the .orchestration-other
     container already shows a monochrome focus-within border. */
  outline: none;
  border-color: transparent;
  box-shadow: none;
}

.orchestration-other-input::placeholder {
  color: var(--cg-input-placeholder, var(--muted));
}

.orchestration-card-foot {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
}

.orchestration-card-submit {
  padding: 9px 18px;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  cursor: pointer;
  background: var(--cg-send-bg, #0d0d0d);
  color: var(--cg-send-fg, #fff);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  transition: opacity 140ms ease, transform 90ms ease;
}

.orchestration-card-submit:hover {
  opacity: 0.9;
}

.orchestration-card-submit:active {
  transform: scale(0.98);
  opacity: 0.85;
}

/* Skip ("건너뛰기") — ghost secondary, pushed to the left of the submit button. */
.orchestration-card-skip {
  margin-right: auto;
  padding: 9px 14px;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill, 999px);
  cursor: pointer;
  background: transparent;
  color: var(--cg-muted, #8f8f8f);
  font-size: var(--ds-text-caption-13);
  font-weight: 500;
  transition: background 140ms ease, color 140ms ease;
}
.orchestration-card-skip:hover {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.04));
  color: var(--cg-text, #0d0d0d);
}
.orchestration-card-skip:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, #0d0d0d);
  outline-offset: 2px;
}

.message.pending .message-body {
  color: var(--muted);
}

.message.failed .message-body {
  color: var(--cg-text, #0d0d0d);
}

/* 20260802-notice-surface (북극성 ③, doc 217 §11.3): 세 번째 상태 — 답변도 실패도 아닌 알림.
   ★카드로 만들지 않는다. doc 143 §1.5가 카드 남발을 금하고, 실패 카드(.chat-failure)와 같은
   무게를 주면 «읽고 넘어갈 것»과 «대응해야 할 것»의 구분이 사라진다. 면·테두리 없이 아이콘
   하나와 조용한 한 줄로 둔다. 색은 muted — 답변 본문보다 뒤로 물러나야 한다. */
/* ★특이도: 셸 규칙 `.chatgpt-reference-v1 .message-body p`(0,2,1)가 이긴다. 알림은
   .message-body 안에 있으므로 무접두 `.chat-notice`(0,1,0)로는 color/font-size 가 절대 안
   먹는다 — 배포본 실측에서 muted 대신 #0d0d0d, caption-13 대신 16px 이었다. 계약은 «선언»만
   읽어 GREEN 이었다. 이 파일의 다른 규칙들과 같은 셸 접두 + 요소 한정으로 (0,3,1)을 만든다. */
.chatgpt-reference-v1 .message-body p.chat-notice {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: start;
  gap: 8px;
  width: min(620px, 100%);
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  line-height: 1.6;
}

.chatgpt-reference-v1 .message-body .chat-notice-icon {
  display: grid;
  place-items: center;
  color: var(--cg-muted);
}

.chat-failure {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: start;
  gap: 12px;
  width: min(620px, 100%);
  padding: 14px 16px;
  /* 다크모드 리터럴 금지 (retry 버튼 준거, 아래 .chat-failure-retry 주석): 오류 카드
     표면·테두리를 시맨틱 토큰으로 플립. 라이트=거의 무변화(bad-fg 4% + surface ≈ 원본 은은한 톤),
     다크=near-black 표면 + 붉은 테두리로 flip → 검은 캔버스 위 연분홍 카드/안 보이는 제목 해소.
     4%는 격리 하네스 라이트 렌더에서 원본 근사 최적값(6/8%는 과채도)으로 확정. */
  border: 1px solid color-mix(in srgb, var(--ds-feedback-bad-fg) 24%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--ds-feedback-bad-fg) 4%, var(--ds-color-surface));
}

.chat-failure-icon {
  color: var(--ds-feedback-bad-fg);
}

.chat-failure-copy {
  min-width: 0;
}

.chat-failure-copy strong {
  display: block;
  margin-bottom: 4px;
  font-size: var(--ds-text-body-14);
  font-weight: 600;
}

.chat-failure-copy p {
  margin: 0;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-body-14);
  line-height: 1.5;
}

.chat-failure-copy small {
  display: block;
  margin-top: 6px;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-micro-11);
}

/* 217: 원시 오류 코드를 기본 접힌 "기술 정보"로 강등(관측성/UX 분리). 토큰만 사용해 라이트/다크
   모두 muted 톤 유지, 기본 마커는 숨기고 요약을 muted 캡션처럼. */
.chat-failure-detail {
  margin-top: 6px;
}

.chat-failure-detail > summary {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-micro-11);
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.chat-failure-detail > summary::-webkit-details-marker {
  display: none;
}

.chat-failure-detail > small {
  margin-top: 4px;
}

.chat-failure-retry {
  min-height: 32px;
  padding: 0 11px;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 7px;
  /* P1-6 다크모드 리터럴 금지 (doc art-direction, 2026-07-17): 표면·텍스트·호버를
     함께 토큰화해 라이트=무변화(#fff/#0d0d0d/#f4f4f4), 다크=surface #000·text #ececec·
     hover #212121 로 flip → 두 테마 모두 대비 유지. 패턴은 styles.css:11492-11493 준거. */
  background: var(--cg-surface, #fff);
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
  white-space: nowrap;
}

.chat-failure-retry:hover {
  background: var(--cg-hover-soft, #f4f4f4);
}

@media (max-width: 520px) {
  .chat-failure {
    grid-template-columns: 22px minmax(0, 1fr);
  }

  .chat-failure-retry {
    grid-column: 2;
    justify-self: start;
  }
}

.message-body p {
  margin: 0 0 10px;
  line-height: 1.65;
  /* WS-K2: 읽기 문단의 rag/고아줄 개선(Safari 26+/Chrome, Firefox는 우아 폴백). */
  text-wrap: pretty;
}

.message-body p:last-child {
  margin-bottom: 0;
}

.message-body pre,
.mini-card code {
  display: block;
  overflow: auto;
  max-width: 100%;
  margin: 12px 0 0;
  padding: 10px;
  border-radius: 8px;
  background: #111827;
  color: #e5e7eb;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--ds-text-caption-12);
  line-height: 1.5;
}

.feedback-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
}

/* Model + elapsed time cluster (doc 164 §후속2): both are non-interactive "how it was made" meta,
   pushed together to the action row's end. */
.answer-meta-cluster {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
/* Answer elapsed time (ChatGPT/Claude parity) — muted meta; the cluster handles right-alignment. */
.answer-elapsed {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--ds-text-caption-12);
  font-variant-numeric: tabular-nums;
  color: var(--cg-muted, #8f8f8f);
}
.answer-elapsed svg {
  width: 13px;
  height: 13px;
}

.feedback-note {
  margin-top: 12px;
  color: var(--success);
  font-size: var(--ds-text-caption-13);
}

/* P1-A: Inline feedback reason picker (doc 199 §1.3, §1.5) — replaces feedback-row in-place
   when user clicks dislike button. Single-select reason chips + optional correction textarea. */
/* 싫어요 이유 피커 — doc 344 시각 재설계.
   ★이 블록에는 하드코딩 색도 `var(--토큰, #hex)` 폴백도 없다. 폴백은 토큰이 죽어도
   조용히 통과하기 때문에, 이 패널이 디자인 시스템 밖에서 그려지던 것을 아무도 못 봤다
   (2026-08-01 실측: 미정의 토큰 26개를 참조했고 하드코딩 hex 50개가 화면을 칠했다).
   ★`[data-theme="dark"]` 대응 규칙이 없는 것은 누락이 아니다 — --cg-* 는 다크에서
   토큰 자체가 뒤집힌다(실측 12/14, --cg-send-bg #0d0d0d→#ffffff). 다크 규칙을 다시
   쓰면 그 반전을 두 번 적용하게 된다. */
.feedback-picker-row {
  display: flex;
  flex-direction: column;
  gap: var(--cg-composer-gutter);
  margin-top: var(--cg-composer-gutter);
  padding: var(--cg-composer-gutter);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--cg-menu-radius);
  background: var(--cg-surface-secondary);
  box-shadow: var(--cg-shadow-float-xs);
}

/* 이 패널에서 유일한 질문 문장이라 본문색으로 올린다(예전엔 보조색이라 흐렸다). */
.feedback-picker-label {
  font-size: var(--cg-text-label-size);
  font-weight: var(--cg-text-label-active-weight);
  line-height: var(--cg-text-label-leading);
  color: var(--cg-text);
}

/* 2열 그리드. 한국어 라벨 4개는 한 줄에 안 들어가고, wrap flex는 3+1로 깨져
   마지막 칩이 고아가 된다 (doc 344 §2). */
.feedback-reason-chips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--cg-menu-gutter);
}

/* 좁은 화면에선 1열. 실측(2026-08-01, 라이브 getComputedStyle): 컨테이너 319px에서
   칩 4개 중 2개가, 343px에서 「표현·형식 문제예요」가 2줄로 접혔다. 알약 칩이 2줄이
   되면 행 높이가 어긋난다. 520px는 정본 브레이크포인트다(breakpoints.md §2). */
@media (max-width: 520px) {
  .feedback-reason-chips {
    grid-template-columns: 1fr;
  }
}

.feedback-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--cg-menu-gutter);
  padding: 8px 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-text-soft);
  font-size: var(--cg-text-label-size);
  font-family: inherit;
  line-height: var(--cg-text-label-leading);
  cursor: pointer;
  appearance: none;
  transition: background-color var(--cg-transition-basic-duration) var(--cg-ease-move),
              color var(--cg-transition-basic-duration) var(--cg-ease-move),
              border-color var(--cg-transition-basic-duration) var(--cg-ease-move);
}

.feedback-chip:hover {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

/* 선택은 «채움 반전» 하나로 말한다. 경계색 변화는 한국어 소자에서 잘 안 보인다. */
.feedback-chip[aria-pressed="true"] {
  border-color: transparent;
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  font-weight: var(--cg-text-label-active-weight);
}

/* 체크 아이콘은 색 외의 두 번째 단서다(색각 이상 대비). 항상 자리를 차지하게 두고
   보이기만 토글한다 — display 토글이면 선택할 때마다 칩 폭이 변해 라벨이 줄바꿈된다. */
.feedback-chip .wds-inline-icon {
  flex: none;
  opacity: 0;
  transition: opacity var(--cg-transition-basic-duration) var(--cg-ease-move);
}

.feedback-chip[aria-pressed="true"] .wds-inline-icon {
  opacity: 1;
}

/* focus-visible은 hover와 다른 시각이어야 한다(예전엔 구분이 없었다).
   outline을 쓰는 이유: box-shadow와 달리 배경을 덮지 않아 선택 반전과 겹쳐도 보인다. */
.feedback-chip:focus-visible,
.feedback-action-button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring);
  outline-offset: 2px;
}

/* doc 209 C-2: 평점은 동의 없이 수집되지만 교정문은 계정 동의가 있어야 저장된다.
   사용자가 텍스트를 쓰기 시작하는 자리 바로 위에 둔다. */
.feedback-picker-disclosure {
  margin: 0;
  font-size: var(--cg-text-meta-size);
  line-height: var(--cg-text-label-leading);
  color: var(--cg-text-soft);
}

.feedback-correction {
  padding: 8px 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-sm);
  background: var(--cg-surface);
  color: var(--cg-text);
  font-size: var(--cg-text-label-size);
  font-family: inherit;
  line-height: var(--cg-text-label-leading);
  resize: vertical;
  min-height: 60px;
  max-height: 120px;
}

.feedback-correction::placeholder {
  color: var(--cg-input-placeholder);
}

.feedback-correction:focus-visible {
  border-color: var(--cg-text);
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 1px;
}

.feedback-picker-actions {
  display: flex;
  gap: var(--cg-menu-gutter);
  justify-content: flex-end;
}

.feedback-action-button {
  padding: 8px 16px;
  border: 1px solid transparent;
  border-radius: var(--ds-radius-pill);
  background: transparent;
  color: var(--cg-text-soft);
  font-size: var(--cg-text-label-size);
  font-family: inherit;
  font-weight: var(--cg-text-label-active-weight);
  line-height: var(--cg-text-label-leading);
  cursor: pointer;
  appearance: none;
  transition: background-color var(--cg-transition-basic-duration) var(--cg-ease-move),
              color var(--cg-transition-basic-duration) var(--cg-ease-move);
}

/* ★주버튼을 :first-child로 잡지 않는다. DOM 순서가 바뀌면 조용히 뒤집혀서
   «건너뛰기»가 주액션처럼 보이게 된다. 의미(data 속성)에 건다. */
.feedback-action-button[data-feedback-submit="tagged"] {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

.feedback-action-button[data-feedback-submit="tagged"]:hover {
  background: var(--wds-color-wizon-accent-hover);
}

.feedback-action-button[data-feedback-submit="skip"]:hover {
  background: var(--cg-hover);
  color: var(--cg-text);
}

.composer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 88px;
  gap: 10px;
  padding: 16px min(7vw, 72px) 22px;
  background: linear-gradient(180deg, rgba(251, 252, 253, 0.1), #fbfcfd 34%);
}

.composer textarea {
  max-height: 180px;
  min-height: 48px;
  border-color: #cdd5de;
  box-shadow: var(--shadow);
}

.primary-button,
.secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  padding: 0 14px;
  border-radius: 8px;
  font-weight: 600;
}

.primary-button {
  border: 1px solid var(--ds-button-primary-bg);
  background: var(--ds-button-primary-bg);
  color: var(--ds-button-primary-fg);
}

.primary-button:hover {
  background: var(--ds-button-primary-bg-hover);
  border-color: var(--ds-button-primary-bg-hover);
}

.secondary-button {
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}

.wide {
  width: 100%;
}

.context-pane {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  background: var(--surface);
  border-left: 1px solid var(--line);
}

.tabs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 4px;
  padding: 12px;
  border-bottom: 1px solid var(--line);
}

.tab-button {
  min-height: 38px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.tab-button.active {
  border-color: var(--cg-text);
  background: var(--accent-soft);
}

.tab-content {
  display: grid;
  align-content: start;
  gap: 14px;
  min-height: 0;
  overflow: auto;
  padding: 16px;
}

.panel-block {
  display: grid;
  gap: 10px;
}

.panel-block h2 {
  margin: 0;
  font-size: var(--ds-text-body-16);
  line-height: 1.2;
}

.panel-block p {
  margin: 0;
  color: var(--muted);
  font-size: var(--ds-text-caption-13);
  line-height: 1.5;
}

.ops-status-panel {
  gap: 12px;
}

.ops-status-head,
.ops-status-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.ops-status-head h2 {
  margin-top: 3px;
}

.ops-status-summary {
  align-items: flex-start;
}

.ops-version-code {
  overflow: hidden;
  max-width: 190px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #f8fafc;
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--ds-text-caption-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ops-status-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.ops-status-card {
  display: grid;
  gap: 5px;
  min-width: 0;
  min-height: 94px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
}

.ops-status-card strong,
.ops-status-card span,
.ops-status-card small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ops-status-card strong {
  color: var(--ink);
  font-size: var(--ds-text-caption-12);
}

.ops-status-card span {
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.ops-status-card small {
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
}

.ops-status-card.is-ok,
.status-pill.is-ok {
  border-color: rgba(22, 163, 74, 0.24);
  background: #ecfdf3;
  color: #166534;
}

.ops-status-card.is-warning,
.status-pill.is-warning {
  border-color: rgba(217, 119, 6, 0.24);
  background: #fffbeb;
  color: #92400e;
}

.ops-status-card.is-error,
.status-pill.is-error {
  border-color: rgba(220, 38, 38, 0.24);
  background: #fef2f2;
  color: #991b1b;
}

.ops-meta-list {
  margin-top: 0;
}

.account-management-panel {
  gap: var(--ds-space-4);
}

.account-head-actions,
.account-section-head,
.account-member-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
  min-width: 0;
}

.account-head-actions {
  flex-wrap: wrap;
  justify-content: flex-end;
}

.account-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--ds-space-3);
}

.account-section {
  display: grid;
  align-content: start;
  gap: var(--ds-space-3);
  min-width: 0;
  padding: var(--ds-space-4);
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-solid);
}

.account-section-head {
  align-items: flex-start;
}

.account-section-head h3 {
  margin: 0;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-body-14);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.account-section-head p {
  margin-top: var(--ds-space-1);
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.account-kv-list div {
  grid-template-columns: 76px minmax(0, 1fr);
  padding: var(--ds-space-2) 0;
}

.account-member-list,
.account-role-list,
.identity-control-list {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-member-row,
.identity-control-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: var(--ds-space-3);
  min-width: 0;
  min-height: 42px;
  padding: var(--ds-space-2) 0;
  border-bottom: 1px solid var(--ds-color-line);
}

.account-member-row:last-child,
.identity-control-row:last-child {
  border-bottom: 0;
}

.account-member-row strong,
.account-member-row span,
.identity-control-row span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-member-row strong {
  display: block;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-body-14);
}

.account-member-row span,
.identity-control-row span {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.account-permission-chip,
.account-status-badge {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  max-width: 100%;
  padding: 0 var(--ds-space-2);
  border: 1px solid var(--ds-chip-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-chip-bg);
  color: var(--ds-chip-fg);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  white-space: nowrap;
}

.account-status-badge.is-active {
  border-color: var(--ds-badge-ok-bg);
  background: var(--ds-badge-ok-bg);
  color: var(--ds-badge-ok-fg);
}

.account-status-badge.is-pending {
  border-color: var(--ds-badge-warn-bg);
  background: var(--ds-badge-warn-bg);
  color: var(--ds-badge-warn-fg);
}

.account-status-badge.is-disabled {
  border-color: var(--ds-badge-bad-bg);
  background: var(--ds-badge-bad-bg);
  color: var(--ds-badge-bad-fg);
}

.account-admin-only {
  margin: 0;
  padding: var(--ds-space-3);
  border: 1px dashed var(--ds-card-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-13);
  line-height: var(--ds-leading-body);
}

.account-action-feedback {
  margin: 0;
  padding: var(--ds-space-3);
  border: 1px solid var(--ds-badge-ok-bg);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-badge-ok-bg);
  color: var(--ds-badge-ok-fg);
  font-size: var(--ds-text-caption-13);
  line-height: var(--ds-leading-body);
}

.account-inline-form,
.account-member-actions {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-inline-form {
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  align-items: end;
}

.account-inline-form label,
.account-action-row {
  display: grid;
  gap: var(--ds-space-1);
  min-width: 0;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
}

.account-inline-form .btn {
  min-height: 32px;
}

.account-member-actions {
  grid-template-columns: minmax(0, 1fr) repeat(3, minmax(72px, auto));
  align-items: end;
}

.account-member-actions .btn {
  min-width: 0;
  min-height: 32px;
  white-space: normal;
}

.account-audit-toolbar,
.account-audit-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-audit-toolbar {
  flex-wrap: wrap;
}

.account-audit-toolbar strong {
  display: block;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-caption-13);
}

.account-audit-toolbar span {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.account-audit-list {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-audit-row {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
  padding: var(--ds-space-2) 0;
  border-bottom: 1px solid var(--ds-color-line);
}

.account-audit-row:last-child {
  border-bottom: 0;
}

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

.account-audit-row strong {
  display: block;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--ds-weight-semibold);
}

.account-audit-row span,
.account-audit-row time {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.account-audit-meta {
  justify-content: flex-start;
  flex-wrap: wrap;
}

.account-notification-list {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-notification-row {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
  padding: var(--ds-space-2) 0;
  border-bottom: 1px solid var(--ds-color-line);
}

.account-notification-row > div {
  display: grid;
  gap: var(--ds-space-1);
  min-width: 0;
}

.account-notification-row:last-child {
  border-bottom: 0;
}

.account-notification-row strong,
.account-notification-row span,
.account-notification-row time {
  min-width: 0;
  overflow-wrap: anywhere;
  white-space: normal;
}

.account-notification-row strong {
  display: block;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--ds-weight-semibold);
}

.account-notification-row span,
.account-notification-row time {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.account-notification-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-start;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-notification-action {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: flex-start;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-notification-action .btn {
  min-height: 30px;
}

.account-notification-note {
  display: grid;
  flex: 1 1 180px;
  gap: var(--ds-space-1);
  min-width: 0;
}

.account-notification-note span {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
}

.account-notification-note .ds-input {
  min-width: 0;
}

.account-notification-history {
  display: grid;
  gap: var(--ds-space-2);
  min-width: 0;
  padding-top: var(--ds-space-3);
  border-top: 1px solid var(--ds-color-line);
}

.account-notification-history-filters {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(118px, 148px);
  align-items: end;
  gap: var(--ds-space-2);
  min-width: 0;
}

.account-notification-history-filters label {
  display: grid;
  gap: var(--ds-space-1);
  min-width: 0;
}

.account-notification-history-filters label span,
.account-notification-history-result {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
}

.account-notification-history-filters .ds-input {
  min-width: 0;
  width: 100%;
}

.account-notification-history-filters .btn {
  justify-self: start;
  min-height: 32px;
}

.account-notification-history-result {
  align-self: center;
  grid-column: 1 / -1;
  justify-self: start;
  white-space: nowrap;
}

.account-notification-meta span,
.account-notification-meta time {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 var(--ds-space-2);
  border: 1px solid var(--ds-chip-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-chip-bg);
}

.upload-form,
.run-form {
  display: grid;
  gap: 8px;
}

.upload-form {
  grid-template-columns: minmax(0, 1fr) 104px 92px;
}

.upload-form .secondary-button {
  border-color: var(--line);
  background: #ffffff;
  color: var(--ink);
}

.app-menu-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.app-menu-chip {
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 8px;
  background: var(--accent-soft);
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.app-menu-chip:hover {
  border-color: var(--accent);
  background: #d9f0f5;
}

.app-detail-panel {
  border: 1px solid var(--cg-menu-border);
  display: grid;
  gap: 12px;
  padding: 14px;
  border-radius: 8px;
  background: #f8fbfc;
}

.app-detail-panel h3 {
  margin: 2px 0 0;
  font-size: 17px;
  line-height: 1.25;
}

.app-detail-panel p {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: var(--ds-text-caption-13);
  line-height: 1.5;
}

.app-workflow-panel {
  border: 1px solid var(--cg-menu-border);
  display: grid;
  gap: 12px;
  padding: 14px;
  border-radius: 8px;
  background: #f8fbfc;
}

.app-workflow-head h3 {
  margin: 2px 0 0;
  font-size: var(--ds-text-body-16);
  line-height: 1.3;
}

.app-workflow-steps {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.app-workflow-steps li {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 8px;
  align-items: start;
}

.app-workflow-steps li > span {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill, 999px);
  background: #ffffff;
  color: var(--cg-text-soft);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}

.app-workflow-steps strong {
  display: block;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  line-height: 1.35;
}

.app-workflow-steps small {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}

.app-workflow-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.app-workflow-actions span {
  min-height: 28px;
  padding: 6px 9px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill, 999px);
  background: rgba(255, 255, 255, 0.78);
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.app-input-fields {
  border: 1px solid var(--cg-menu-border);
  display: grid;
  gap: 10px;
  padding: 12px;
  border-radius: 8px;
  background: #f8fbfc;
}

.app-input-head {
  display: grid;
  gap: 3px;
}

.app-input-head span {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}

.app-input-field {
  display: grid;
  gap: 5px;
  min-width: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.app-input-field small {
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  line-height: 1.35;
}

.app-input-field--checkbox {
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: center;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
}

.app-input-field--checkbox input {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
}

.app-detail-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 0;
}

.app-detail-meta div {
  min-width: 0;
  padding: 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
}

.app-detail-meta dt {
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}

.app-detail-meta dd {
  min-width: 0;
  margin: 3px 0 0;
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.app-result-card {
  border: 1px solid var(--cg-menu-border);
  display: grid;
  gap: 10px;
  padding: 12px;
  border-radius: 8px;
  background: #f8fbfc;
}

.app-result-card strong {
  font-size: var(--ds-text-body-14);
  line-height: 1.35;
}

.operator-progress-panel {
  display: grid;
  gap: 10px;
  margin-top: 4px;
  padding-top: 10px;
  border-top: 1px solid var(--cg-menu-border);
}

.operator-progress-current-step {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
}

.operator-progress-current-step div {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.operator-progress-current-step small,
.operator-progress-milestone small {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.35;
  overflow-wrap: anywhere;
}

.operator-progress-current-step strong,
.operator-progress-step strong,
.operator-progress-milestone strong {
  min-width: 0;
  overflow-wrap: anywhere;
}

.operator-progress-counts {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
}

.operator-progress-counts div {
  display: grid;
  gap: 1px;
  min-width: 0;
  padding: 7px 8px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.64);
}

.operator-progress-counts b {
  color: var(--ink);
  font-size: var(--ds-text-body-14);
  line-height: 1.1;
}

.operator-progress-counts em {
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
  font-style: normal;
  font-weight: 600;
}

.operator-progress-steps,
.operator-progress-milestones {
  display: grid;
  gap: 6px;
}

.operator-progress-step,
.operator-progress-milestone {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 7px;
  align-items: center;
  min-width: 0;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--ink);
  font-size: var(--ds-text-caption-12);
}

.operator-progress-step.is-current {
  border-color: var(--cg-text);
  background: rgba(236, 253, 245, 0.72);
}

.operator-progress-milestone {
  grid-template-columns: auto minmax(0, 1fr);
}

.operator-progress-milestone small {
  grid-column: 2;
}

/* E-B1: 시맨틱 토큰 매핑(다크 적응 + 라이트 근사) — docs/product/218, .chat-failure 선례 */
.operator-progress-status {
  display: inline-grid;
  place-items: center;
  min-width: 48px;
  min-height: 24px;
  padding: 4px 7px;
  border-radius: var(--ds-radius-pill, 999px);
  background: color-mix(in srgb, var(--ds-color-ink) 6%, var(--ds-color-surface));
  color: var(--ds-color-muted);
  font-size: var(--ds-text-micro-11);
  line-height: 1;
  white-space: nowrap;
}

.operator-progress-status--completed,
.operator-progress-status--done,
.operator-progress-status--available {
  background: var(--ds-feedback-ok-bg);
  color: var(--ds-feedback-ok-fg);
}

.operator-progress-status--waiting,
.operator-progress-status--waiting-input,
.operator-progress-status--running {
  background: var(--ds-feedback-warn-bg);
  color: var(--ds-feedback-warn-fg);
}

.operator-progress-status--failed {
  background: var(--ds-feedback-bad-bg);
  color: var(--ds-feedback-bad-fg);
}

.required-input-form {
  display: grid;
  gap: 10px;
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 8px;
  background: #ffffff;
}

.required-input-head {
  display: grid;
  gap: 3px;
}

.required-input-head strong {
  font-size: var(--ds-text-body-14);
}

.required-input-head small,
.required-input-field small {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.4;
}

.required-input-field {
  display: grid;
  gap: 5px;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.required-input-actions {
  display: flex;
  justify-content: flex-end;
}

.workflow-action-panel {
  display: grid;
  gap: 10px;
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 8px;
  background: rgba(248, 251, 252, 0.88);
}

.workflow-action-head {
  display: grid;
  gap: 2px;
}

.workflow-action-head small,
.workflow-action-head span,
.approved-manual-map-form small,
.submission-readiness-row small,
.required-document-row small,
.company-context-row small {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.4;
}

.submission-readiness-panel,
.required-documents-panel,
.company-context-panel {
  display: grid;
  gap: 10px;
  margin-top: 10px;
  padding: 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 8px;
  background: #ffffff;
}

.submission-readiness-list,
.required-documents-list,
.company-context-list {
  display: grid;
  gap: 8px;
}

.submission-readiness-group {
  display: grid;
  gap: 6px;
}

.submission-readiness-group > b {
  color: #334155;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.submission-readiness-row {
  display: grid;
  gap: 3px;
  min-width: 0;
  padding: 8px 9px;
  border: 1px solid rgba(148, 163, 184, 0.26);
  border-radius: 8px;
  background: #f8fafc;
}

.submission-readiness-row span {
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13);
  line-height: 1.35;
}

.submission-readiness-row.is-blocking {
  border-color: rgba(185, 28, 28, 0.28);
  background: #fff7f7;
}

.submission-readiness-row.is-renewal {
  border-color: rgba(180, 83, 9, 0.28);
  background: #fffbeb;
}

.submission-readiness-row.is-public-mydata {
  border-color: rgba(3, 105, 161, 0.24);
  background: #f0f9ff;
}

.submission-readiness-row.is-deferred {
  border-color: rgba(71, 85, 105, 0.22);
  background: #f8fafc;
}

.required-document-row,
.company-context-row {
  display: grid;
  gap: 4px;
  min-width: 0;
  padding: 9px;
  border: 1px solid rgba(148, 163, 184, 0.28);
  border-radius: 8px;
  background: #f8fafc;
}

.required-document-row b,
.company-context-row b {
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.required-document-row strong,
.company-context-row span {
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13);
  line-height: 1.35;
}

.required-document-row.is-blocking {
  border-color: rgba(185, 28, 28, 0.28);
  background: #fff7f7;
}

.required-document-row.is-blocking b {
  color: #b91c1c;
}

.company-context-row.is-muted {
  opacity: 0.68;
}

.workflow-action-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: stretch;
}

.workflow-action-button {
  min-height: 34px;
  padding: 7px 10px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 8px;
  background: #ffffff;
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1.2;
}

.workflow-action-button:disabled {
  cursor: not-allowed;
  opacity: 0.52;
}

.approved-manual-map-form {
  display: grid;
  grid-template-columns: minmax(180px, 1.1fr) minmax(160px, 1fr) minmax(160px, 1fr) auto;
  gap: 8px;
  align-items: end;
  width: 100%;
  padding: 10px;
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-radius: 8px;
  background: #ffffff;
}

.approved-manual-map-form > div {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.approved-manual-map-form strong {
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13);
}

/* ============================================================================
 * 답변 신뢰 패널 = 파일 패널의 '플로팅 둥근 카드' 도킹(20260710-dock-card-redesign)을 그대로 재사용.
 * 헤더(.chatgpt-route-page-head)·탭(.chatgpt-route-tabs)·타이포·route 토큰은 route-page가 소유.
 * 여기서는 카드 위치/모양만: 둥근 카드가 우측 gutter를 OVERLAY(push 없음 → 대화 위치·폭 불변).
 * 값은 파일 패널 카드(#portalPage docked)와 100% 동일(inset 12·radius 16·풀보더·그림자·width 34%/480).
 * #trustPanel 은 .chat-pane 의 '마지막 자식'이라 thread-hide sibling 규칙에 안 걸려 대화가 유지된다.
 * ========================================================================== */
@media (min-width: 901px) {
  /* 지오메트리는 body.side-dock-open이 아니라 패널 자신에 건다: closeTrustPanel이 body
   * 클래스를 퇴장 애니메이션보다 먼저 제거해서, 닫히는 ~190ms 동안 패널이 절대배치를
   * 잃고 일반 route 블록으로 풀리며 대화 위로 풀폭 점프(화면 깜빡임)했다. 가시성은
   * [hidden] 규칙이 소유하므로 카드 모양은 닫힘이 끝날 때까지 유지된다. */
  .chatgpt-reference-v1 #trustPanel.chatgpt-route-page {
    position: absolute;
    inset: 12px 12px 12px auto;
    width: clamp(360px, 34%, 480px);
    margin: 0;
    max-width: none;
    padding: 20px 20px calc(20px + var(--wizon-safe-bottom, 0px));
    overflow-y: auto;
    overflow-x: hidden;
    background: var(--cg-menu-bg, var(--bg));
    border: 1px solid var(--line);
    border-radius: 16px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16);
    z-index: 40;
  }
}
/* 모바일: 파일 패널의 풀스크린 route 와 동일하게 전체를 덮는다 */
@media (max-width: 900px) {
  /* 풀스크린 route: 스레드를 불투명하게 덮고(배경 없으면 뒤 대화가 비쳐 겹침 — 이전 버그),
     헤더+탭은 고정하고 본문만 스크롤한다(고정 헤더/스크롤 바디 패턴). z-index는 모바일
     top-bar(<65) 위로 올려 패널 자체 헤더만 보이게 한다(back 아이콘 간헐 노출 해소). */
  #trustPanel.chatgpt-route-page {
    position: fixed;
    inset: 0;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    z-index: 100;
    background: var(--cg-bg, var(--wizon-ai-canvas, #fcfcfc));
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  #trustPanel .chatgpt-route-page-inner {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    gap: 0;
    overflow: hidden;
  }
  /* 컴팩트 앱바 헤더: [< back] 타이틀 인라인(좁은 화면 세로 공간 활용) — 고정. */
  #trustPanel .trust-route-head {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: calc(10px + var(--wizon-safe-top, 0px)) 15px 10px;
    background: var(--cg-bg, var(--wizon-ai-canvas, #fcfcfc));
  }
  #trustPanel .trust-route-head h1 {
    display: block;
    font-size: var(--ds-text-title-18);
    font-weight: 500;
    line-height: 1.25;
  }
  /* 탭(출처/처리 과정)도 헤더 아래 고정. */
  #trustPanel .chatgpt-route-tabs {
    flex: 0 0 auto;
    padding: 0 15px 10px;
    background: var(--cg-bg, var(--wizon-ai-canvas, #fcfcfc));
    box-shadow: inset 0 -1px 0 var(--cg-menu-border, #e3e3e3);
  }
  /* 본문(소스 카드)만 스크롤. */
  #trustPanel .trust-route-body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: 12px 15px calc(15px + var(--wizon-safe-bottom, 0px));
    scrollbar-width: none;
  }
  #trustPanel .trust-route-body::-webkit-scrollbar {
    display: none;
  }
}
#trustPanel.chatgpt-route-page[hidden] {
  display: none;
}
/* 패널 내부 스크롤바 숨김(스크롤 기능은 유지): 스크롤바 트랙이 둥근 카드(radius 16)의
 * 모서리를 각지게 깨뜨림 — .trust-chips와 동일한 숨김 관례. */
#trustPanel.chatgpt-route-page {
  scrollbar-width: none;
}
#trustPanel.chatgpt-route-page::-webkit-scrollbar {
  display: none;
}
/* route-page-inner 는 gap-lg(40px)라 트러스트엔 과하다 -> 파일 패널 도킹 레일 톤으로 좁힌다 */
.trust-route-page .chatgpt-route-page-inner {
  gap: 16px;
}
/* route-page-head 는 이미 flex space-between(제목 좌 · 액션 우) -> 그대로 쓰고 닫기만 추가 */
.trust-panel-close {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: var(--cg-hover-soft, #f2f3f5);
  color: var(--cg-text, #1f2937);
  cursor: pointer;
}
.trust-panel-close:hover {
  background: var(--cg-hover, #ececec);
}
.trust-panel-close:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 2px;
}
.trust-panel-close svg {
  width: 18px;
  height: 18px;
}
/* 닫기 아이콘: 웹 도킹 = X / 모바일 풀 = 뒤로(파일 패널과 동일 위치=헤더 좌측) */
.trust-panel-close-x {
  display: inline-flex;
}
.trust-panel-close-back {
  display: none;
}
@media (max-width: 900px) {
  .trust-panel-close-x {
    display: none;
  }
  .trust-panel-close-back {
    display: inline-flex;
  }
  .trust-route-head .trust-panel-close {
    order: -1;
  }
}

/* ============================================================================
 * 아티팩트 패널(표 → 시트 편집, doc 171 P1) — 배치 E2-a2: #trustPanel의 도킹 카드 모양(둥근
 * 카드·그림자·보더)은 그대로 쓰되, 데스크톱에서는 그리드 흐름에서 완전히 분리된 `position: fixed`
 * 오버레이로 뜬다(대화가 밀리지 않고 그 위에 얹힘 — non-modal, 배경 클릭으로 안 닫힘). z-index는
 * 새 계열을 만들지 않고 다른 fixed 최상위 오버레이(.user-msg-menu 등)와 같은 200 계열을 재사용한다.
 * 3단계 폭(default/wide/full) + 드래그 커스텀 폭은 data-panel-width 속성으로 전환되고, "custom"은
 * 어떤 폭 규칙과도 매치하지 않으므로 JS가 얹는 인라인 width가 그대로 이긴다. 헤더는 마크업에서
 * .trust-route-head 클래스를 함께 얹어 기존 모바일 뒤로가기 order 규칙(아래)을 그대로 상속한다.
 * ========================================================================== */
@media (min-width: 901px) {
  .chatgpt-reference-v1 #artifactPanel.chatgpt-route-page {
    position: fixed;
    inset: 12px 12px 12px auto;
    width: clamp(360px, 38%, 520px);
    margin: 0;
    max-width: none;
    padding: 20px 20px calc(20px + var(--wizon-safe-bottom, 0px));
    overflow-y: auto;
    overflow-x: hidden;
    background: var(--cg-menu-bg, var(--bg));
    border: 1px solid var(--line);
    border-radius: 16px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16);
    z-index: 200;
    display: flex;
    flex-direction: column;
  }
  /* 넓게: 대화창 폭 절반 정도까지(최대 900px) — 여전히 우측 카드 도킹 모양 유지. */
  .chatgpt-reference-v1 #artifactPanel.chatgpt-route-page[data-panel-width="wide"] {
    width: min(50vw, 900px);
  }
  /* 전체: 화면을 완전히 덮는 전면 취득 — 대화가 시각적으로 가려지므로 카드 느낌(라운드·인셋)은
     내려놓고 모바일 풀스크린과 동일한 엣지투엣지 취급으로 전환한다. */
  .chatgpt-reference-v1 #artifactPanel.chatgpt-route-page[data-panel-width="full"] {
    inset: 0;
    width: 100vw;
    border-radius: 0;
  }
  /* 드래그 리사이즈 핸들: 패널 좌측 경계에 얇은 히트영역 + 호버/포커스 시 보이는 그립 바.
     데스크톱 전용(모바일은 풀스크린 시트 유지 — 아래 @media (max-width: 900px)에서 숨김). */
  .chatgpt-reference-v1 #artifactPanel .artifact-panel-resize-handle {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 8px;
    cursor: col-resize;
    touch-action: none;
    z-index: 1;
  }
  .chatgpt-reference-v1 #artifactPanel .artifact-panel-resize-handle::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 3px;
    height: 48px;
    border-radius: var(--ds-radius-pill, 999px);
    background: var(--cg-menu-border, var(--line));
    opacity: 0;
    transition: opacity var(--wds-duration-fast) ease;
  }
  .chatgpt-reference-v1 #artifactPanel .artifact-panel-resize-handle:hover::before,
  .chatgpt-reference-v1 #artifactPanel .artifact-panel-resize-handle:focus-visible::before,
  .chatgpt-reference-v1 #artifactPanel.is-resizing .artifact-panel-resize-handle::before {
    opacity: 1;
  }
  .chatgpt-reference-v1 #artifactPanel .artifact-panel-resize-handle:focus-visible {
    outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
    outline-offset: 2px;
  }
  /* 드래그 중에는 포인터가 8px 핸들을 벗어나는 게 정상 궤적이라, 전역 커서를 col-resize로 고정하고
     본문 텍스트가 끌려 선택되는 것을 막는다(클래스는 begin/endArtifactPanelResize가 토글). */
  body.artifact-panel-resizing {
    cursor: col-resize;
    -webkit-user-select: none;
    user-select: none;
  }
  /* 헤더 우측 액션(폭 토글 + 닫기) 묶음. */
  #artifactPanel .artifact-route-head-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
  }
  .artifact-panel-width-toggle {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    background: var(--cg-hover-soft, #f2f3f5);
    color: var(--cg-text, #1f2937);
    cursor: pointer;
  }
  .artifact-panel-width-toggle:hover {
    background: var(--cg-hover, #ececec);
  }
  .artifact-panel-width-toggle:focus-visible {
    outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
    outline-offset: 2px;
  }
  .artifact-panel-width-toggle svg {
    width: 18px;
    height: 18px;
  }
  /* 닫기 버튼 가시성: 아티팩트 패널만 32→40px로 키운 히트영역(트러스트 패널의 .trust-panel-close는
     건드리지 않음 — 회귀 방지를 위해 ID로 스코프). */
  #artifactPanel .trust-panel-close {
    width: 40px;
    height: 40px;
  }
  #artifactPanel .trust-panel-close svg {
    width: 20px;
    height: 20px;
  }
}
@media (max-width: 900px) {
  #artifactPanel.chatgpt-route-page {
    position: fixed;
    inset: 0;
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    z-index: 100;
    background: var(--cg-bg, var(--wizon-ai-canvas, #fcfcfc));
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  /* flex/min-height/gap now live in the unconditional #artifactPanel .chatgpt-route-page-inner
     rule below (doc 171 A1 — desktop needs the exact same flex-column fill, see that rule's
     comment) — this mobile-only block keeps just the delta: clip the fullscreen sheet's own
     overflow so nothing scrolls past the window chrome. */
  #artifactPanel .chatgpt-route-page-inner {
    overflow: hidden;
  }
  #artifactPanel .artifact-route-head {
    flex: 0 0 auto;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: calc(10px + var(--wizon-safe-top, 0px)) 15px 10px;
    background: var(--cg-bg, var(--wizon-ai-canvas, #fcfcfc));
  }
  #artifactPanel .artifact-route-head h1 {
    display: block;
    font-size: var(--ds-text-title-18);
    font-weight: 500;
    line-height: 1.25;
  }
  #artifactPanel .artifact-route-body {
    padding: 12px 15px;
  }
  /* 폭 토글·드래그 리사이즈는 데스크톱 전용(모바일은 기존 풀스크린 시트 유지) — 토글은 숨기고,
     헤더 액션 묶음(닫기만 남음)을 기존 "뒤로가기 왼쪽" order 규칙 그대로 앞으로 보낸다. */
  .artifact-panel-width-toggle,
  .artifact-panel-resize-handle {
    display: none;
  }
  #artifactPanel .artifact-route-head-actions {
    order: -1;
    /* Live-verified regression: this group only had display:flex on desktop (>=901px) — with just
       the width-toggle (hidden on mobile) and close button, a single visible child looked fine
       without it. Now that the titlebar carries 2 download buttons + a divider + close (doc 171
       A1), the missing flex on mobile let the div's default block layout wrap them onto a second
       row, pushing the header taller and the title out of vertical center. */
    display: flex;
    align-items: center;
    gap: 4px;
  }
}
#artifactPanel.chatgpt-route-page[hidden] {
  display: none;
}
#artifactPanel.chatgpt-route-page {
  scrollbar-width: none;
}
#artifactPanel.chatgpt-route-page::-webkit-scrollbar {
  display: none;
}
/* 엑셀 새창 골격(doc 171 A1): .chatgpt-route-page-inner의 공용 규칙(이 파일 아래쪽, 12862줄 근방)은
   display:grid로 콘텐츠 높이만큼만 차지한다 — 트러스트 패널처럼 스크롤되는 카드형 콘텐츠엔 맞지만,
   시트 창은 그리드(.artifact-route-body)가 창의 남은 세로 공간을 전부 채워야 한다(항목 4). 데스크톱
   에서도(모바일은 위 @media (max-width: 900px)에서 이미 flex-column이었다 — 이제 그 델타만 남김)
   flex 컬럼으로 바꿔 .artifact-route-body의 flex:1 1 auto가 실제로 작동하게 한다. ID 선택자라
   위쪽 공용 grid 규칙(클래스 2개, 이 파일 뒤쪽에서 선언되어 소스 순서상 이긴다)보다 특이도가 높아
   미디어 쿼리 안팎 어디서든 확실히 이긴다 — 실렌더로 검증됨(폭 토글/드래그 리사이즈 시 Univer 캔버스
   가 자체 ResizeObserver로 즉시 재도장하는 것도 함께 확인). */
#artifactPanel .chatgpt-route-page-inner {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 0;
}
/* 타이틀바 좌측: 파일 아이콘 + 파일명(h1) — 폭이 좁을 때 파일명이 잘리도록 min-width:0 필요. */
.artifact-titlebar-file {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  min-width: 0;
}
.artifact-titlebar-file-icon {
  display: inline-flex;
  flex: 0 0 auto;
}
.artifact-titlebar-file h1 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 타이틀바 우측 다운로드 버튼과 폭 토글/닫기 사이 구분선 — .chatgpt-library-view-divider와
   동일한 톤(1px, 얇은 세로 바)을 이 컨텍스트에 맞춰 재선언. */
.artifact-titlebar-divider {
  width: 1px;
  height: 20px;
  flex: 0 0 auto;
  background: var(--cg-menu-border, var(--line));
}
.artifact-titlebar-save-button {
  min-height: 34px;
  padding: 0 var(--ds-space-3);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-sm);
  background: var(--cg-surface, var(--ds-color-surface));
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.artifact-titlebar-save-button:hover:not(:disabled) {
  background: var(--cg-hover-soft);
}
.artifact-titlebar-save-button:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
.artifact-titlebar-save-button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.artifact-workbook-risk {
  flex: 0 0 auto;
  margin: var(--ds-space-2) var(--ds-space-3) 0;
}
/* 값 목록(데이터 유효성) 폴백 안내 — doc 544 §15.
   ★이 규칙과 app.js 의 workbookV2DataValidationNoticeHtml 은 «반드시 함께» 읽어야 한다: 마크업만
   접어도 펼쳤을 때 다시 그리드를 밀어내고, 상한만 걸어도 접힌 요약이 없으면 처음부터 잘린 목록이
   보인다.
   실측(2026-08-30, 오너의 실제 견적서 6시트 · 73행 × 9열 · 규칙 24개, 1440×900): 수리 전 안내는
   평면 <p>+<ul> 이라 469px(패널 안쪽 834px 의 56.2%)를 먹고 그리드에 209px 만 남겼다. 규칙 200개
   에서는 안내 3285px, 그리드 **0px** — 시트 편집기에 시트가 아예 없었다.

   상한이 px 가 아니라 «패널 안쪽 대비 %» 인 이유: 이 결함의 본질은 «안내가 패널을 이긴다» 이므로
   기준은 패널이어야 한다. 고정 px 는 패널이 짧아지는 순간(폰 가로, 좁은 도킹 폭) 같은 결함으로
   되돌아간다. 이 자리에서 %가 실제로 해석되는 것은 확인된 사실이다 — #artifactPanel 이
   position:fixed + inset 으로 높이가 확정이고 .chatgpt-route-page-inner 가 flex:1 1 auto 라
   포함 블록 높이가 definite 다(실렌더 대조: 상한 30% → 안내 250px / 그리드 428px).
   산식: 그리드 = 100% − 크롬(타이틀바+리본+상태바, 실측 ≈19%) − 안내 상한(30%) ≳ 51%.
   접힌 기본 상태에서는 안내가 51px 고정이라 규칙 1개든 200개든 그리드가 627px(75.2%)로 «같다».

   ★스크롤 상자는 <details> 가 아니라 이 바깥 요소다. <details> 를 flex 컬럼으로 만들고 안쪽
   목록에 flex:1 1 auto + min-height:0 을 주는 «보통의» 방법은 여기서 조용히 안 먹는다: 크롬은
   summary 를 뺀 나머지를 UA 섀도의 ::details-content 블록에 담으므로 그 목록은 details 의 flex
   자식이 아니고, 따라서 줄지 않는다. 실측으로 잡았다 — 겉보기 높이는 상한대로 250px 인데
   scrollHeight 가 720px 이라 목록이 overflow:visible 로 그리드 «위에» 그려지고 있었다. 그래서
   상한과 overflow 를 같은 요소(이 바깥 상자)에 두고, 정직 고지가 스크롤에 딸려 사라지지 않게
   summary 를 sticky 로 붙인다. */
#artifactPanel [data-workbook-validation-notice] {
  max-height: 30%;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0;
  background: var(--cg-hover-soft);
}
.artifact-validation-notice-summary {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  /* ★`background: inherit` 로 두면 안 된다: summary 의 부모는 배경을 가진 안내 슬롯이 아니라
     <details> 라서 투명을 물려받고, sticky 로 떠 있는 동안 목록이 글자 뒤로 비쳐 지나간다
     (실측 2026-08-30: computed background-color 가 rgba(0,0,0,0) 이었다). 같은 토큰을 직접
     쓴다 — 위 슬롯과 한 값이므로 테마가 바뀌어도 같이 움직인다. */
  background: var(--cg-hover-soft);
  cursor: pointer;
  list-style: none;
}
.artifact-validation-notice[open] .artifact-validation-notice-summary {
  border-bottom: 1px solid color-mix(in srgb, var(--cg-text) 8%, transparent);
}
/* Safari 는 ::marker 가 아니라 ::-webkit-details-marker 로 삼각형을 그린다 — 둘 다 지워야
   아래 자체 표식(▸/▾)과 이중으로 보이지 않는다. */
.artifact-validation-notice-summary::-webkit-details-marker {
  display: none;
}
.artifact-validation-notice-summary::marker {
  content: "";
}
.artifact-validation-notice-summary:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: -2px;
}
.artifact-validation-notice-headline {
  color: var(--cg-text, var(--fg));
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}
.artifact-validation-notice-headline::before {
  content: "▸ ";
  color: var(--cg-muted, var(--muted));
}
.artifact-validation-notice[open] .artifact-validation-notice-headline::before {
  content: "▾ ";
}
/* 펼침 안내를 «요약 문구»가 아니라 ::after 로 두는 이유: 열림 상태에 따라 문구가 뒤집혀야 하는데
   (닫힘 「어느 셀인지 보기」 / 열림 「접기」) 본문에 박아 두면 열린 뒤에도 「보기」라고 남는다.
   보조기술은 이 장식 문구가 아니라 <details>/<summary> 자체의 확장 상태를 읽는다. */
.artifact-validation-notice-headline::after {
  content: " — 어느 셀인지 보기";
  color: var(--cg-muted, var(--muted));
  font-weight: 400;
}
.artifact-validation-notice[open] .artifact-validation-notice-headline::after {
  content: " — 접기";
}
.artifact-validation-notice-hint {
  color: var(--cg-muted, var(--muted));
  font-size: var(--ds-text-caption-12);
}
.artifact-validation-notice-body {
  padding: 0 12px 8px;
}
.artifact-validation-notice-group + .artifact-validation-notice-group {
  margin-top: 8px;
}
.artifact-validation-notice-group h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 2px;
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.artifact-validation-notice-group h3 span {
  color: var(--cg-muted, var(--muted));
  font-weight: 400;
}
.artifact-validation-notice-group ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.artifact-validation-notice-group li {
  padding: 2px 0;
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}
.artifact-validation-notice-group li b {
  margin-right: 6px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
/* 커스텀 반응형 리본(doc 171 A3-a) — Univer 내장 리본을 숨기고(같은 자리에) 얹는 자체 리본.
   Univer(0.25.1) 내장 리본은 [data-u-comp="headerbar"] 하나에 탭 줄(시작/수식/데이터)과 아이콘
   툴바([data-u-comp="ribbon-toolbar"])가 함께 들어있다 — 실렌더로 확인: 이 anchor의 textContent가
   "시작수식데이터..."이고 자식이 정확히 이 둘 + 텍스트박스. 수식바([data-u-comp="formula-bar"])는
   헤더바 형제라 이 규칙에 걸리지 않고 그대로 유지된다.
   doc 555 §채택 A3(2026-08-27 재실측) — UniverSheetsCorePreset 은 `toolbar: false` 옵션이 실재한다
   (mountArtifactSheet() 의 createUniver 호출부 참조 — 이제 그 옵션도 같이 끈다). 이 규칙은 옵션이
   실패하거나(버전업으로 이름이 바뀌거나 사라지면) 렌더가 그 옵션을 무시하는 경우를 대비한 안전망으로
   남긴다 — 셀렉터가 안 맞아도 CSS 는 그대로 매칭 시도하고, 매칭 실패 시 내장 리본이 다시 보이는
   방향으로 fail-visible(레이아웃 파손 아님). (이 자리의 예전 메모는 "그런 옵션 자체가 존재하지
   않는다"고 적었는데, 이는 minified 번들에서 unquoted 객체 키를 quoted-string grep 으로 찾다 놓친
   오판이었다 — 실제로는 `{header:n=!0,toolbar:s=!0,footer:l=!0}` 형태로 존재한다.) */
#artifactSheetContainer [data-u-comp="headerbar"] {
  display: none;
}
/* 리본 자체: 홈 탭 핵심 그룹만(실행취소·재실행 / 굵게·기울임·밑줄 / 정렬 좌·중·우 / 표시형식 /
   자동합계) — 탭 줄(삽입·수식·데이터)과 색상(글꼴색·채우기)은 각각 A3-c/A3-b로 제외. container
   query로 자기 자신의 렌더 폭을 재서 3모드로 축약 — data-panel-width 속성(default/wide/full)이
   아니라 실제 px를 재는 이유: 드래그로 만든 "custom" 폭은 그 속성과 매치하는 CSS 규칙이 없어(E2-a2,
   인라인 style.width가 이김) 속성 셀렉터로는 드래그 중 반응형을 못 잡는다 — container query는 드래그
   폭 포함 항상 실제 렌더 폭을 본다. */
.artifact-ribbon {
  container-type: inline-size;
  container-name: artifact-ribbon;
  position: relative;
  flex: 0 0 auto;
  padding: 4px 8px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-hover-soft, #f8f8f8);
}
/* 컴팩트 팝오버가 열려 있을 때만 리본 전체(자신 + 절대배치 자식)를 그리드보다 위 스태킹 레이어로
   올린다 — 실렌더로 확인된 회귀: Univer 자체 그리드 <canvas>가 position:absolute; z-index:8로
   그려지고(인라인 스타일, 벤더 유틸리티 클래스 중 최대값도 univer-z-20 — 실측), 리본은 z-index
   없이 auto라 DOM 순서와 무관하게 캔버스가 항상 위에 그려져 팝오버가 그 밑에 깔려 클릭도 시각도
   막혔었다. 30 = Univer 쪽에서 실측된 최대치(20)보다 여유 있게 높음. 색상 팝오버(doc 171 A3-b)도
   같은 회귀에 노출되므로 동일 규칙에 편입. */
.artifact-ribbon[data-ribbon-overflow-open="true"],
.artifact-ribbon[data-ribbon-color-popover-open="true"] {
  z-index: 30;
}
/* 리본 탭 줄 (doc 544 P1 → §12 시각 재설계, 목업 2층) — 파일·홈·삽입·수식·데이터·보기.
   ★P1 의 «카드형»(활성 탭만 표면색 + 테두리로 본문과 이어 붙이는 엑셀 2007 형태)은 §12 에서
     목업(sheet-concept-a `.rtab`)의 «밑줄형»으로 교체됐다: 배경은 어느 탭도 칠하지 않고,
     활성 탭만 잉크색 글자 + 아래 2px 잉크 밑줄로 선다. 카드형을 되살리면 리본 본문
     (--cg-hover-soft)과 활성 탭(--cg-surface)이 서로 다른 두 표면을 붙여 놓게 되고,
     목업의 «한 장의 종이» 인상이 깨진다.
   ★hover 배경(--cg-hover)은 그대로 둔다 — 상태(밑줄+잉크)와 hover(배경)의 «채널»이 다르므로
     §11.2-(b) 의 «상태색 == hover색» 결함이 구조적으로 재발할 수 없다.
   폰(≤520px)에서는 아래 미디어 블록이 이 줄을 가로 스크롤 스냅 «칩 행»으로 바꾼다(M1) —
   터치에서 밑줄은 히트영역을 못 그리므로 그 폭에서만 채워진 pill 로 남는다(§5.2-M1). */
.artifact-ribbon-tabs {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  padding: 0 8px;
  margin: -4px -8px 4px;
  border-bottom: 1px solid var(--cg-menu-border);
}
.artifact-ribbon-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  height: 34px;
  padding: 0 16px;
  border: none;
  /* 밑줄은 «항상» 있고 색만 바뀐다 — 활성일 때만 border 를 만들면 탭이 2px 씩 들썩인다. */
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  /* ★활성/비활성이 «같은» 무게다 — 목업의 600→800 대비를 여기서는 쓰지 않는다. 이유 두 가지,
     둘 다 실측이다.
     (1) 타이포 계약이 웨이트 팔레트를 {400,500,600} + 예외 2개(300 컴포저 글리프 1곳 ·
         700 모바일 워드마크 1곳)로 못박고 상한을 «각 1곳»으로 래칫한다
         (test_typography_contract T4). 800 은커녕 700 도 여기 둘 수 없어, 목업의 두 단계
         대비는 잘해야 500→600 한 단계로 줄어든다.
     (2) 무게가 상태를 말하면 활성 탭이 넓어져 뒤따르는 탭이 오른쪽으로 밀린다 — 탭을 누를
         때마다 줄 전체가 움찔한다. 보이지 않는 굵은 사본(::after)으로 폭을 미리 잡는 수를
         한 번 넣었다가 «양성 대조»에서 걷어냈다: 예약을 지워도 실렌더 오프셋이 소수점까지
         동일했다(937 / 993.75 / 1040.13 / 1096.88 / 1153.63 / 1220.75, 두 번 모두). 이 앱은
         font-synthesis-weight:none 이라 미로드 웨이트를 합성하지 않으므로, 게이트가 재는
         환경에서 500 과 600 은 «같은 폭»으로 그려진다 — 예약은 하는 일이 없었고 그것을
         지키는 검사도 재는 것이 없었다.
     활성 표시는 잉크색(--cg-muted → --cg-text)과 2px 밑줄이 함께 말한다 — 목업의 세 신호 중
     둘이고, 엑셀 웹·구글 시트도 이 둘만 쓴다. */
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
/* R1 (doc 544 §5.4): 탭의 hover 도 반드시 이 가드 안. 가드가 없으면 터치에서 «지나간» 탭의 배경이
   끈적여 사용자는 그 탭이 열린 줄 안다. */
@media (hover: hover) {
  .artifact-ribbon-tab:hover {
    background: var(--cg-hover);
    color: var(--cg-text);
  }
}
.artifact-ribbon-tab:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: -2px;
}
.artifact-ribbon-tab[aria-selected="true"] {
  border-bottom-color: var(--cg-text);
  background: transparent;
  color: var(--cg-text);
}
/* 배선 없는 탭(파일·삽입·데이터)의 한 줄 안내. 회색 더미 버튼 대신 «그 기능이 지금 어디 있는지»를
   말한다(doc 544 §3.3-4). 컨트롤이 아니므로 리본 활성/비활성과 무관하게 항상 읽힌다. */
.artifact-ribbon-panel-note {
  margin: 0;
  padding: 6px 4px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.5;
}
/* 그룹 상자 — 목업 3층 「각 그룹 하단에 그룹 라벨」. 라벨은 최대 폭(>901px)과 컴팩트 "⋯" 드롭다운
   에서만 보인다(중간 폭은 아이콘만 있는 1줄이어야 하므로). */
.artifact-ribbon-groupbox {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 0 0 auto;
  gap: 1px;
}
/* 파일 탭 「버전」 그룹 (doc 544 §11.1) — 저장/버전 기록은 워크북 문서에서만 보인다
   (openArtifactPanel 이 타이틀바 원본과 같은 hidden 을 쓴다). 둘 다 숨겨졌을 때 그룹 라벨과
   뒤 구분선만 남으면 «빈 그룹» 화면이 되므로 통째로 숨긴다. :has() 는 이 파일이 이미
   150여 곳에서 쓰는 관례다. 인접 형제(+)로 구분선까지 걷는 것이 요점 — 그룹만 숨기면
   패널 왼쪽에 구분선이 홀로 남는다. */
[data-ribbon-groupbox="file-version"]:not(:has(button:not([hidden]))),
[data-ribbon-groupbox="file-version"]:not(:has(button:not([hidden]))) + .artifact-ribbon-sep {
  display: none;
}
.artifact-ribbon-groupbox-body {
  display: flex;
  align-items: center;
  /* §12 — 목업 `.rgroup .items{gap:6px}`(환산 4px). 2px 는 버튼들이 한 덩어리로 붙어 보여
     «그룹 안»의 구분이 사라졌다. */
  gap: 4px;
}
.artifact-ribbon-groupbox-label {
  display: none;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  /* §12 — 목업 `.glabel{font-weight:600}`. 라벨이 400 이면 버튼 글자와 무게가 같아 «캡션»으로
     읽히지 않고 또 하나의 컨트롤처럼 보였다. */
  font-weight: 600;
  line-height: 1.2;
}
/* 세로 맞춤 아이콘: 가로 맞춤 아이콘을 90° 돌려 쓴다 — left→top / center→middle / right→bottom 으로
   정확히 대응하므로 아이콘 표(shared/wds/wds-icons.js, 관제 콘솔 사본과 바이트 동일성 게이트로
   묶임)를 늘리지 않는다. */
.artifact-ribbon-icon--vertical {
  display: inline-flex;
  transform: rotate(90deg);
}
/* ₩ · % · , · 행 · 열 — 아이콘 표를 늘리지 않는 문자 버튼(엑셀도 표시 형식 프리셋은 문자다).
   .artifact-ribbon-label-text 가 아니라서 컴팩트 폭에서도 남는다 = 아이콘 없는 빈 버튼이 되지 않는다. */
.artifact-ribbon-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 14px;
  flex: 0 0 auto;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1;
}
/* ⓑ «자기 고지»(doc 544 P1 done_when 7 / doc 550 §6)의 규칙은 markup 과 함께 doc 550 S2-b 에서
   사라졌다 — 홈 탭의 서식 컨트롤이 전부 저장되므로 가리킬 문장이 없다. 되살릴 때는 index.html 의
   그 자리에 남긴 주석을 먼저 읽어라: 위험 알림이 아니라 사실 고지이므로 위험색이 아닌 상태바와 같은
   muted 잉크를 썼고, 모든 폭에서 보였다(폰 포함) — 컴팩트에서 사라지면 «저장되는 줄 알았다»가 바로
   그 폭에서 생긴다. */
/* ★가로로 «넘치면 스크롤»한다 — 모든 폭에서. 원래는 overflow:hidden 이었고, 컨트롤이 10개이던
   doc 171 A3-a 시절에는 넘칠 일이 없었다. P1 이 홈 탭을 18개로 늘리면서 중간 폭(561~900px)에서
   실제로 넘쳤는데 그 구간에는 "⋯" 오버플로 토글이 없어(그건 ≤560px 전용) 「표시 형식」 그룹이
   «보이지도 않고 닿을 수도 없게» 잘렸다(900px 실렌더로 확인: scrollWidth 900 / clientWidth 884,
   2026-08-27). 최대 폭에서도 같은 일이 있었다(1561 / 1382). hidden 은 그 사실을 «조용히» 숨긴다.
   스크롤바는 숨기고 좌우 페이드로 «더 있음»만 알린다 — 리본 안의 가로 스크롤바는 28px 줄에서
   내용을 반쯤 먹는다. 색상 팝오버는 containing block 이 .artifact-ribbon(position:relative)이라
   이 스크롤 상자의 클립 밖에 남는다(overflow:hidden 이던 때와 같은 이유, 아래 팝오버 주석 참조). */
.artifact-ribbon-row {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  mask-image: linear-gradient(90deg, currentColor 0, currentColor calc(100% - 12px), transparent 100%);
}
.artifact-ribbon-row::-webkit-scrollbar {
  display: none;
}
.artifact-ribbon-group {
  display: flex;
  align-items: center;
  gap: 4px;
  flex: 0 0 auto;
}
/* §12 — 목업의 그룹 구분은 «짧은 칸막이»가 아니라 그룹 옆면을 세로로 가르는 선이다
   (`.rgroup{border-right:1px solid #ececec}` + 좌우 18px 여백). 20px 짜리 토막은 28px 버튼
   옆에서 위아래가 붕 떠 보였다. 28px = 버튼 높이와 같게 세우고 여백을 목업 리듬으로 벌린다.
   ★리본 한 줄은 «모든 폭에서» 가로 스크롤한다(위 .artifact-ribbon-row 주석) — 이 여백이
     늘어난 만큼 스크롤 폭이 늘어날 뿐, 잘려서 닿지 못하는 컨트롤은 생기지 않는다. */
.artifact-ribbon-sep {
  width: 1px;
  height: 28px;
  flex: 0 0 auto;
  margin: 0 8px;
  background: var(--cg-menu-border, var(--line));
}
.artifact-ribbon-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  padding: 0 8px;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  /* §12 — 목업 `.rbtn{font-weight:700}`. 12px 한글에서 700 은 뭉개지므로 600 으로 앉힌다
     (글리프 버튼 ₩ % , 병합 이 이미 쓰는 무게와 같아 한 줄 안에서 무게가 갈리지 않는다). */
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
/* R1 (doc 544 §5.4): 리본 버튼의 :hover는 전부 이 가드 안. doc 544 P0가 이 자리에 「보기」 눈금선
   토글을 넣으면서 이 공용 규칙이 그 토글의 hover도 소유하게 됐다 — 가드가 없으면 폰에서 한 번
   누른 토글의 배경이 «끈적여» 눌린 채로 남고, 사용자는 눈금선이 아직 그 상태인 줄 안다. */
@media (hover: hover) {
  .artifact-ribbon-btn:hover {
    background: var(--cg-hover, #ececec);
    color: var(--cg-text, var(--text));
  }
  .artifact-ribbon-btn:disabled:hover {
    background: transparent;
    color: var(--cg-text-soft, var(--muted));
  }
}
.artifact-ribbon-btn:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
.artifact-ribbon-btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
/* 토글 활성 상태(굵게/기울임/밑줄/정렬/세로 맞춤/표시 형식 프리셋).
   ★--ds-chip-bg-active + --accent 조합을 «쓰지 않는다». P0 레인이 상태바 토글에서 실렌더로 잡은
     것과 같은 결함이 이 공용 규칙에도 있었다(styles.css 의 눈금선 토글 주석 참조): 이 앱에서
     --ds-chip-bg-active → --ds-color-accent → --wizon-ai-action-primary-bg 이고 --accent 도 같은
     잉크로 접혀, 배경과 글자가 «같은 색»이 된다 — 굵게를 켜면 검은 사각형만 남고 B 가 사라졌다.
     주액션 쌍(--cg-send-bg / --cg-send-fg)은 배경과 글자가 «짝»으로 정의된 유일한 잉크 쌍이라
     라이트/다크 어느 쪽으로 뒤집혀도 대비가 유지되고, hover(--cg-hover)와도 확실히 구분된다.
   ★raw 색 리터럴도, var() «폴백» 리터럴도 쓰지 않는다 — 색상 부채 래칫(anti-drift-static-baseline
     .json raw-color)은 폴백 안의 리터럴까지 그대로 센다. 이 파일의 다수 관례가 폴백 없는 형태다. */
.artifact-ribbon-btn[aria-pressed="true"] {
  /* §12 — 목업 `.rbtn.on{background:#e8efff;color:#155eef}`: 눌림은 «반전된 검은 칩»이 아니라
     «연한 파랑 바닥 + 파랑 잉크»다. --cg-send-bg 쌍(검정/흰색)은 §11.3 이 hover 충돌을 피하려
     급히 잡은 자리였고, 리본 한 줄에 굵게·기울임·정렬이 동시에 켜지면 검은 사각형이 여러 개
     생겨 «주액션 버튼»처럼 읽혔다.
     ★--ad-blue-tint / --ad-blue 는 배경과 잉크가 «짝»으로 정의된 쌍이다: 틴트가
       color-mix(파랑, --wizon-ai-surface) 라 라이트(#fff)에서는 아주 연한 파랑, 다크(#000)
       에서는 아주 어두운 파랑이 되고, --ad-blue 자신은 다크에서 --wds-blue-400 으로 밝아진다
       (styles.css 「아트디렉션 v2」 블록). 어느 테마에서도 배경 != 글자가 유지된다 —
       --ds-chip-bg-active 가 두 값 모두 같은 잉크로 접혀 «검은 사각형»이 됐던 함정
       (P0/P1 주석)과 갈리는 지점이 바로 이 «짝으로 정의됐는가»다.
     ★hover 토큰(--cg-hover)과 겹치지 않는다 — §11.3 이 세운 계약이 그대로 지켜진다
       (§11.2-(b): 상태색 == hover색이면 클릭하는 순간 시각차가 0 이었다). */
  background: var(--ad-blue-tint);
  color: var(--ad-blue);
}
.artifact-ribbon-btn .wds-inline-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
}
/* 최대(>900px)에서만, 또는 컴팩트 팝오버가 열려있을 때만 보임 — 아래 @container 규칙. */
.artifact-ribbon-label-text {
  display: none;
}
.artifact-ribbon-select-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.artifact-ribbon-select {
  height: 28px;
  min-height: 0; /* 전역 select { min-height:42px } 누수 차단 — .artifact-sheet-container select와 동일 이유 */
  padding: 0 6px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-xs, 6px);
  background: var(--bg, #fff);
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  /* §12 — 목업 `.rsel{font-weight:600}`. 옆 버튼들과 같은 무게라야 한 그룹으로 읽힌다. */
  font-weight: 600;
  cursor: pointer;
}
.artifact-ribbon-select:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
.artifact-ribbon-select:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
/* 글꼴색/채우기색 split-button (doc 171 A3-b) — 엑셀 그대로: 아이콘 본체(마지막 사용색 즉시 재적용)
   + ▾ 캐럿(팔레트 팝오버) 두 개의 독립 클릭 타겟이 한 몸처럼 붙어있다. 아이콘 하단 색상바
   (.artifact-ribbon-color-swatch)는 사용자가 실제로 고른 마지막 색을 인라인 style.background로
   반영 — 사용자 피드백 원문 "색상바는 색상이 변경에 따라 안바뀌고요"가 지적한 결함의 직접 수정. */
.artifact-ribbon-splitbtn {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}
.artifact-ribbon-splitbtn-main {
  padding-right: 4px;
}
.artifact-ribbon-splitbtn-caret {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 28px;
  border: none;
  border-radius: 0 6px 6px 0;
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  cursor: pointer;
}
/* R1 (doc 544 §5.4 / P1 done_when 6): 리본의 «모든» :hover 는 이 가드 안. 아래 네 규칙은
   doc 171 A3-a/A3-b 때 가드 없이 착지했고, 터치에서 한 번 누른 캐럿/스와치/"⋯"가 눌린 채로
   남아 사용자가 그 색이 적용된 줄 아는 함정이 그대로 있었다. 폰(≤520px)에서 이 컨트롤들이
   실제로 손가락에 닿게 되는 P1 에서 함께 닫는다. ★var() 폴백 리터럴은 «그대로 둔다» —
   지우면 색상 부채 래칫 수가 움직여 이 작업의 델타가 리본 골격 밖으로 번진다. */
@media (hover: hover) {
  .artifact-ribbon-splitbtn-caret:hover {
    background: var(--cg-hover, #ececec);
    color: var(--cg-text, var(--text));
  }
}

.artifact-ribbon-splitbtn-caret:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
.artifact-ribbon-splitbtn-caret:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
.artifact-ribbon-splitbtn-caret .wds-inline-icon {
  width: 12px;
  height: 12px;
}
.artifact-ribbon-color-icon-wrap {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.artifact-ribbon-color-swatch {
  width: 16px;
  height: 3px;
  border-radius: 1px;
  background: #000000; /* 초기값(글꼴색 검정) — background-color 컨트롤은 JS 마운트 시 #ffff00로 갱신 */
}
/* "채우기 없음"/"자동" 초기화 상태 — 리터럴 색 대신 대각선 체크 패턴으로 "색 없음"을 시각적으로
   구분(엑셀의 빗금 없음 스와치와 동일한 관례). */
.artifact-ribbon-color-swatch.is-empty {
  background: repeating-linear-gradient(-45deg, #e02020 0, #e02020 1px, transparent 1px, transparent 3px);
}
/* position:absolute with NO static top/left here on purpose — .artifact-ribbon-splitbtn deliberately
   has no `position` set, so this popover's containing block resolves up to .artifact-ribbon itself
   (already position:relative), the SAME escape hatch the compact "⋯" overflow dropdown uses to get
   out from under .artifact-ribbon-row's `overflow: hidden` (live-verified regression: a splitbtn-
   local position:relative put the popover's containing block back INSIDE the clipped row, and it
   silently rendered but was invisible — hidden=false, real innerHTML, zero pixels shown). JS
   (openArtifactRibbonColorPopover) sets the actual left/top inline per open, anchored to the
   triggering split-button's own rect. */
.artifact-ribbon-color-popover {
  position: absolute;
  padding: 8px;
  width: max-content;
  background: var(--cg-menu-bg, var(--bg));
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-sm, 10px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  z-index: 5;
}
.artifact-ribbon-color-popover-reset {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 4px 6px;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  text-align: left;
  cursor: pointer;
}
@media (hover: hover) {
  .artifact-ribbon-color-popover-reset:hover,
  .artifact-ribbon-color-popover-custom:hover {
    background: var(--cg-hover, #ececec);
  }
}

.artifact-ribbon-color-popover-reset .artifact-ribbon-color-swatch {
  width: 14px;
  height: 14px;
  border-radius: var(--ds-radius-2xs, 3px);
  border: 1px solid var(--cg-menu-border, var(--line));
}
.artifact-ribbon-color-popover-label {
  margin: 6px 2px 4px;
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-micro-11);
}
.artifact-ribbon-color-popover-sep {
  height: 1px;
  margin: 4px 0;
  background: var(--cg-menu-border, var(--line));
}
.artifact-ribbon-color-theme-grid {
  display: grid;
  grid-template-columns: repeat(10, 18px);
  gap: 2px;
}
.artifact-ribbon-color-standard-row {
  display: grid;
  grid-template-columns: repeat(10, 18px);
  gap: 2px;
}
.artifact-ribbon-color-swatch-btn {
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: var(--ds-radius-2xs, 3px);
  cursor: pointer;
  position: relative;
}
@media (hover: hover) {
  .artifact-ribbon-color-swatch-btn:hover {
    outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
    outline-offset: 1px;
  }
}

.artifact-ribbon-color-swatch-btn:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
/* 현재 선택 범위의 실제 색과 일치하는 스와치에 체크 표시 — 팝오버를 열 때마다 다시 계산(스펙 항목
   4 "현재 셀 색을 팔레트에서 체크 표시"). */
.artifact-ribbon-color-swatch-btn.is-current::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2px solid var(--accent, #2f6bff);
  border-radius: var(--ds-radius-2xs, 3px);
}
.artifact-ribbon-color-popover-custom {
  display: block;
  width: 100%;
  margin-top: 4px;
  padding: 4px 6px;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  text-align: left;
  cursor: pointer;
}
/* 실제 색상 선택은 절대 여기서 다시 그리지 않는다 — "다른 색…" 클릭은 네이티브
   <input type="color">.click()을 그대로 호출해 OS 컬러피커를 띄운다(사용자 지시: "다른색 클릭했을
   때는 컬러피커 컴포넌트 사용하여 띄워주시면 됩니다"). opacity:0 + 절대배치로 시각적으로만 숨기고
   display:none은 쓰지 않는다 — 일부 브라우저는 display:none 요소의 .click()으로 네이티브 다이얼로그를
   띄우지 못한다. */
.artifact-ribbon-color-native-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
/* 정렬/표시형식/자동합계 묶음 — 기본(중간·최대 폭)은 그냥 행의 일부로 흐름, 컴팩트(≤560px)에서만
   아래 @container 규칙이 숨기고 "⋯" 팝오버로 대체한다(마크업 복제 없이 같은 DOM을 재배치). */
.artifact-ribbon-overflow-group {
  display: flex;
  align-items: center;
  gap: 2px;
}
.artifact-ribbon-overflow-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: auto;
  flex: 0 0 auto;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  cursor: pointer;
}
@media (hover: hover) {
  .artifact-ribbon-overflow-toggle:hover {
    background: var(--cg-hover, #ececec);
    color: var(--cg-text, var(--text));
  }
}

.artifact-ribbon-overflow-toggle:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
.artifact-ribbon-overflow-toggle .wds-inline-icon {
  width: 16px;
  height: 16px;
}
/* 최대(>900px): 그룹 라벨 표시(스펙 항목 4 "최대: 그룹 라벨 표시"). */
@container artifact-ribbon (min-width: 901px) {
  /* 목업 3층 「각 그룹 하단에 그룹 라벨」 — 최대 폭에서만. 중간 폭(561~900px)은 아이콘만 있는
     1줄이어야 하므로 라벨을 켜면 리본이 두 줄이 되어 그리드가 그만큼 짧아진다.
     ★여기서 «버튼별» 라벨 텍스트(.artifact-ribbon-label-text)는 켜지 않는다. doc 171 A3-a 때는
       그룹 상자가 없어 버튼 텍스트가 「그룹 라벨 표시」의 대역이었지만, P1 이 진짜 그룹 라벨을
       들이면서 둘을 함께 켜면 홈 탭 한 줄이 1561px 이 된다 — 컨테이너는 1382px 이고
       .artifact-ribbon-row 는 overflow:hidden 이며 "⋯" 토글은 이 폭에서 display:none 이라,
       「표시 형식」과 「셀」 그룹이 «보이지도 않고 닿을 수도 없게» 잘렸다(1440px 실렌더로 확인,
       2026-08-27). 엑셀도 최대 폭에서 아이콘 버튼에 글자를 달지 않고 그룹 라벨만 단다.
       버튼 텍스트는 컴팩트 "⋯" 드롭다운에서만 남는다(그 자리에선 메뉴 항목 이름이라 필요하다).
       접근성 이름은 각 버튼의 aria-label 이 계속 들고 있다. */
  .artifact-ribbon-groupbox-label {
    display: block;
  }
}
/* 컴팩트(≤560px): 정렬/표시형식/자동합계를 "⋯" 팝오버 뒤로 감춘다(스펙 항목 4 "기본: 컴팩트 1줄 —
   핵심 아이콘만 + 오버플로 팝오버"). 열렸을 때는 같은 DOM을 세로 드롭다운으로 절대배치 전환 —
   버튼을 복제하지 않으므로 aria-pressed 등 상태 동기화가 저절로 하나만 존재한다. */
@container artifact-ribbon (max-width: 560px) {
  .artifact-ribbon-overflow-group {
    display: none;
  }
  .artifact-ribbon-overflow-toggle {
    display: inline-flex;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    position: absolute;
    top: 100%;
    right: 8px;
    margin-top: 4px;
    padding: 6px;
    gap: 2px;
    width: max-content;
    background: var(--cg-menu-bg, var(--bg));
    border: 1px solid var(--cg-menu-border, var(--line));
    border-radius: var(--ds-radius-sm, 10px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
    z-index: 5;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-sep {
    display: none;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-label-text {
    display: inline;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-btn {
    justify-content: flex-start;
  }
  /* 드롭다운 안에서는 그룹 상자도 세로로 편다 — 가로 배치인 채로 절대배치 메뉴에 들어가면 메뉴가
     리본보다 넓어져 화면 밖으로 나간다. 그룹 라벨은 여기서 메뉴의 섹션 제목 노릇을 하므로 켠다. */
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox,
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox-body,
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-group {
    flex-direction: column;
    align-items: stretch;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox-label {
    display: block;
    order: -1;
    padding: 4px 8px 2px;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-splitbtn {
    align-items: stretch;
  }
}
/* 폰(≤520px) — doc 544 M1·M2. 520 은 이 앱이 이미 44곳에서 쓰는 폰 경계다(§5.1, 새 브레이크포인트
   발명 금지).
   ★이 블록은 위 @container 블록 «뒤»에 와야 한다. 미디어 쿼리는 특이도를 올리지 않으므로
     .artifact-ribbon-overflow-group{display:none}(컨테이너, 클래스 1개)과 아래
     .artifact-ribbon-overflow-group{display:flex}(미디어, 클래스 1개)는 소스 순서로 갈린다 —
     이 파일이 이미 상태바 토글 높이에서 같은 함정을 실측으로 겪었다(390px 히트영역 44×22).
   ★폰에서 "⋯" 오버플로를 «끈다»: 가로 스크롤이 오버플로를 대신하므로 두 메커니즘이 겹치면 같은
     명령이 두 군데 생긴다(§5.2-M2). 토글 버튼을 숨기는 것만으로는 부족하다 — 데스크톱 폭에서
     열어둔 채로 창을 좁히면 data-ribbon-overflow-open 이 남으므로 그 상태의 절대배치도 되돌린다. */
@media (max-width: 520px) {
  /* M1 — 탭 줄을 가로 스크롤 스냅 칩 행으로. 활성 칩은 «채워진 pill»이다(밑줄이 아니다: 터치에서
     밑줄은 히트영역이 어디까지인지 안 보인다). 좌우 페이드 마스크로 «더 있음»을 알린다. */
  .artifact-ribbon-tabs {
    gap: 6px;
    padding: 4px 8px;
    margin: -4px -8px 4px;
    align-items: center;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* R6 — 이 스크롤러는 가로만 먹는다. 그리드 컨테이너의 touch-action 은 Univer 소유라 절대
       덮어쓰지 않는다(§8-7: 회귀 증상은 «셀이 안 눌린다»로 나타난다). */
    touch-action: pan-x;
    /* 마스크는 «알파»만 읽는다 — currentColor 를 쓰면 raw 색 리터럴(#000)을 새로 들이지 않고도
       같은 페이드가 나온다. 색상 부채 래칫은 이 자리의 리터럴도 그대로 센다. */
    mask-image: linear-gradient(90deg, transparent 0, currentColor 12px, currentColor calc(100% - 12px), transparent 100%);
  }
  .artifact-ribbon-tabs::-webkit-scrollbar {
    display: none;
  }
  .artifact-ribbon-tab {
    scroll-snap-align: start;
    height: 44px; /* R4 — 히트영역 44px */
    padding: 0 14px;
    border: none;
    border-radius: var(--ds-radius-pill);
    margin-bottom: 0;
    background: var(--cg-hover-soft);
    /* §5.2-M1 «채워진 pill» — radius 999px 는 폭≤높이가 되는 순간 원으로 붕괴한다.
       실측(390px, chromium): 1글자 «홈» 탭이 38.4×44 로 폭<높이 → 기본 활성 탭이 검은
       «원»으로 렌더됐다(padding 0 14px·radius 999px 는 저작대로 적용된 상태였다 — 원인은
       내용 폭 그 자체). 44(높이)+20 = 64px 를 바닥으로 깔면 최장 라벨 «데이터»(59.1px)까지
       전부 같은 폭의 pill 이 된다(폭/높이 1.45). 버튼 텍스트는 기본 중앙 정렬이라 짧은
       라벨도 칩 가운데에 선다. */
    min-width: 64px;
  }
  .artifact-ribbon-tab[aria-selected="true"] {
    background: var(--cg-send-bg);
    color: var(--cg-send-fg);
  }
  /* M2 — 그룹 본문을 가로 스크롤 툴바 1행으로. 가로 스크롤 자체는 이제 «모든 폭»의 기본값이라
     (위 .artifact-ribbon-row 참조) 여기서는 터치에만 필요한 것만 더한다: R6 의 pan-x 와 관성
     스크롤. 그룹 라벨은 숨기고 그룹 사이 세로 구분선만 남긴다. */
  .artifact-ribbon-row {
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x;
  }
  .artifact-ribbon-groupbox-label {
    display: none;
  }
  .artifact-ribbon-overflow-group {
    display: flex;
  }
  .artifact-ribbon-overflow-toggle {
    display: none;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group {
    position: static;
    flex-direction: row;
    align-items: center;
    margin-top: 0;
    padding: 0;
    width: auto;
    background: transparent;
    border: none;
    box-shadow: none;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-sep {
    display: block;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-label-text {
    display: none;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox,
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox-body,
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-group {
    flex-direction: row;
    align-items: center;
  }
  .artifact-ribbon[data-ribbon-overflow-open="true"] .artifact-ribbon-overflow-group .artifact-ribbon-groupbox-label {
    display: none;
  }
  /* R4 — 아이콘 전용이어도 터치 타깃은 44×44 이상. select 는 손가락으로 열어야 하므로 같은 높이. */
  .artifact-ribbon-btn,
  .artifact-ribbon-splitbtn-main {
    min-width: 44px;
    height: 44px;
    justify-content: center;
  }
  .artifact-ribbon-splitbtn-main {
    min-width: 36px;
  }
  .artifact-ribbon-splitbtn-caret {
    width: 24px;
    height: 44px;
  }
  .artifact-ribbon-select {
    height: 44px;
  }
  .artifact-ribbon-select--font-family {
    max-width: 108px;
  }
  .artifact-ribbon-select--font-size {
    max-width: 68px;
  }
}
/* 시트 본문(엑셀 새창 골격, doc 171 A1 — 항목 4): 고정 min-height 420px 대신 flex:1 1 auto +
   min-height:0로 창의 남은 세로 공간을 그대로 채운다. 부모 .chatgpt-route-page-inner가 이제
   flex-column(위 규칙)이라 이 flex:1 1 auto가 실제로 늘어날 공간을 받는다 — 그 전에는 inner가
   display:grid(콘텐츠 높이만큼만)라 420px 고정값 밑으로 빈 여백만 생겼었다(실렌더로 확인된
   회귀 원인). border/radius 제거 — 창 자체가 시트이므로 엣지투엣지, 카드 테두리를 이중으로
   두지 않는다. */
.artifact-route-body {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* 포털 전역 폼 스타일(select,input,textarea { min-height:42px })이 Univer 내부 입력에 새면 28px
   수식바 행 안의 이름상자가 42px로 부풀어 아래가 잘린다 — min-height만 넓게(모든 Univer 입력)
   국소 해제한다. 이건 무해하다: 어느 Univer 입력이든 42px 하한이 사라져도 자기 높이를 쓴다. */
.artifact-sheet-container input,
.artifact-sheet-container select,
.artifact-sheet-container textarea {
  min-height: 0;
}
/* 포털 전역 input의 border-radius(14px)·border·box-shadow(포커스 링)·background가 새면 Univer
   이름상자(name box)만 라운드+파란 포커스 링이 떠서 옆 수식창(Univer 기본 스타일 그대로)과 따로
   논다(실사용자 스크린샷 — doc 171 A2 fix). 이 시각 중화는 반드시 이름상자 하나로만 스코프한다:
   Univer의 다른 내부 입력(이름 정의 Insert/Edit 다이얼로그, 범위 선택기 등)까지 테두리·포커스
   표시를 지우면 WCAG 2.4.7(포커스 가시성) 위반이 된다(코드리뷰 HIGH). 이름상자 마커는 실브라우저
   DOM으로 확정: 수식바([data-u-comp="formula-bar"]) 안의 [data-u-comp="defined-name"] > input.
   오른쪽 구분선 테두리는 이 input이 아니라 defined-name 컨테이너 DIV에 있으므로 border:0으로
   지워지지 않는다. */
#artifactSheetContainer [data-u-comp="defined-name"] input {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  outline: 0;
}
#artifactSheetContainer [data-u-comp="defined-name"] input:focus,
#artifactSheetContainer [data-u-comp="defined-name"] input:focus-visible {
  box-shadow: none;
  outline: 0;
}
/* 수식 입력줄 토글 (doc 544 §3.2 「보기」 탭 「표시」 그룹, P2) — Univer 네이티브 수식바(이름상자
   포함 한 행)를 CSS 층에서만 숨긴다. 벤더의 sheets-ui `formulaBar` 는 프리셋 «생성 시» 옵션이라
   런타임 토글 API 가 없다(app.js 수식바 토글 블록의 벤더 실측 주석). data-formula-bar-hidden 은
   refreshArtifactFormulaBarToggleState 가 세우는 패널 속성. display:none 뒤 그리드가 그 높이를
   되찾는지는 스모크 게이트(portal-sheet-engine-browser-smoke-gate)가 실렌더 px 로 잰다. 이
   셀렉터가 버전업에 늙어 매칭이 깨지면 수식바가 «다시 보이는» 안전 실패다(doc 544 §8-3 관례). */
#artifactPanel[data-formula-bar-hidden="true"] #artifactSheetContainer [data-u-comp="formula-bar"] {
  display: none;
}

/* 폰 수식바 축약형 (doc 544 §5.2-M3 / §10 구현 기록) — 벤더 DOM 은 옮기지 않는다(§5.2-M3:
   bottom sheet 명시 기각, §8-3 셀렉터 취약성). 축약(기본): 이름상자 좌측 고정 폭을 줄여
   fx 1줄 표시 폭을 최대화한다 — 폭의 정본은 벤더 유틸(.univer-w-24 = 96px 이름상자,
   .univer-w-\[100px\] 래퍼)이고 여기는 id 셀렉터 특이도로 이긴다. 탭하면 app.js 가 패널에
   data-formula-bar-expanded="true" 를 세우고 아래 규칙이 수식바를 3줄 높이로 늘린다 —
   벤더 자체 ResizeObserver 가 컨테이너 크기를 따라 doc 캔버스를 재배치한다(실측 2026-08-30,
   390×844 헤드리스 크롬: height 84px 오버라이드 → univer-doc-main-canvas 27→83px, 그리드
   무손상). 높이 전환은 벤더가 이미 갖고 있다(univer-transition-[height] 0.15s linear) —
   새 전환을 만들지 않는다. fx «말줄임(…)»은 불가: 값이 canvas 텍스트라(실측 136×27)
   CSS text-overflow 가 닿지 않는다 — 1줄 클리핑 + 탭 확장으로 대체(§10 편차 기록).
   셀렉터가 벤더 버전업으로 늙으면 아무 규칙도 안 붙고 내장 수식바가 원형 그대로 보인다
   — «내장 위젯이 다시 보이는» 안전 실패(§8-3 관례). touch-action 은 만지지 않는다(R6). */
@media (max-width: 520px) {
  /* 이름상자 축소 — 64px 는 «AA100» 급 셀 참조가 12px 폰트로 들어가는 폭. 래퍼(:has)와
     이름상자 본체를 함께 줄여야 한다: 래퍼만 줄이면 본체(96px)가 밖으로 넘친다(실측).
     transition: none 인 이유 — 이름상자는 벤더가 univer-transition-all(all 0.15s)을 달아
     두어, 데스크톱→폰 리사이즈 순간 96→64 width «전환»이 0.15s 걸린다. 화면은 이름상자가
     움찔 줄어드는 애니메이션이고, 스모크 게이트는 리사이즈 직후 판독에서 전환 중간값
     (실측 2026-08-30: 96/95.83/95.77px)을 읽어 빨개진다. 폰에는 hover 도 없어(R1) 이
     전환이 하는 일이 없다 — 끄면 리사이즈 즉시 최종 폭이 서고 판독이 결정적이 된다. */
  #artifactSheetContainer [data-u-comp="formula-bar"] > div:has([data-u-comp="defined-name"]),
  #artifactSheetContainer [data-u-comp="defined-name"] {
    width: 64px;
    transition: none;
  }
  /* 탭 확장 — 2~3줄. 84px 는 벤더 자체 확장 상태(.univer-h-20 = 80px)와 같은 급이다.
     84px 고정값이라 --wizon-vvh 불요(§8-8 은 100dvh 류 전면 배치에만 해당). */
  #artifactPanel[data-formula-bar-expanded="true"] [data-u-comp="formula-bar"] {
    height: 84px;
  }
  /* Univer 는 바의 height 전환을 먼저 칠하고 doc canvas 의 inline height 는 자체
     ResizeObserver 에서 다음 프레임에 갱신한다. 그 한 프레임 동안 캔버스 아래가 비는 것을
     막아, 실제 편집 면이 확장 바를 즉시 채우게 한다. min-height 만 두므로 벤더가 다음
     프레임에 쓰는 정확한 bitmap/client height 는 그대로 권위가 있고, 축약 상태에는 닿지 않는다. */
  #artifactPanel[data-formula-bar-expanded="true"]
    [data-u-comp="formula-bar"] canvas[data-u-comp="render-canvas"] {
    min-height: calc(100% - 1px);
  }
}
.artifact-sheet-container {
  flex: 1 1 auto;
  min-height: 0;
  overflow-x: auto;
  overflow-y: auto;
}
.artifact-sheet-status {
  margin: 0;
  padding: 24px 4px;
  color: var(--cg-muted, var(--muted, #6b7280));
  font-size: var(--ds-text-caption-13);
  text-align: center;
}
.artifact-sheet-status--error {
  color: var(--ds-badge-warn-fg, #b45309);
}
/* 창 최하단 상태바 — 다운로드 버튼은 타이틀바로 옮겨갔으니(위) 여기는 "준비" + 셀 개수만 남는다.
   줌/시트탭은 Univer가 그리드 안에 자체적으로 그리므로(실렌더로 확인) 여기서 중복하지 않는다. */
.artifact-status-bar {
  display: flex;
  align-items: center;
  /* §12 — 목업 `.statusbar{gap:22px}`(환산 16px). 10px 는 「준비 / 선택 / 토글」이 한 덩어리로
     붙어 읽혀 어디까지가 한 항목인지 안 보였다. 폰(≤520px)은 아래 블록이 따로 좁힌다. */
  gap: 14px;
  height: 28px;
  flex: 0 0 auto;
  padding: 0 4px;
  border-top: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-hover-soft, #f4f4f4);
  color: var(--cg-muted, var(--muted, #6b7280));
  font-size: var(--ds-text-caption-12);
}
.artifact-status-ready {
  color: var(--cg-text-soft, var(--muted));
  font-weight: 500;
}
.artifact-cell-count {
  color: var(--cg-muted, var(--muted, #6b7280));
  font-size: var(--ds-text-caption-12);
  /* 실측 회귀 (2026-08-29, iOS Safari 시뮬레이터 390pt · 크롬 375px): 선택 집계가 길어지면
     flex 가 이 칸을 18px 까지 줄였고, 기본값 `white-space: normal` 이라 "5행 × 4열" 이 세 줄로
     접혀 상태바가 28px → 63px 로 자랐다. 짧은 고정 라벨이므로 줄바꿈도 축소도 허용하지 않는다 —
     양보하는 쪽은 폰 블록에서 말줄임을 받는 선택 집계다(doc 544 M6). */
  flex: 0 0 auto;
  white-space: nowrap;
}
.artifact-workbook-save-status {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-muted, var(--muted));
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 선택 집계(doc 171 A2) — 상태바 우측, 엑셀과 동일하게 평균/개수/합계. 빈 문자열이면(단일 셀·빈
   선택) 완전히 사라져 "준비"/셀개수 사이 남는 빈 여백이 안 생긴다. */
.artifact-selection-summary {
  margin-left: auto;
  color: var(--cg-muted, var(--muted, #6b7280));
  font-size: var(--ds-text-caption-12);
  white-space: nowrap;
}
.artifact-selection-summary:empty {
  display: none;
}
/* 상태바의 여유 공간을 저장상태 <output>이 흡수하게 해서 선택집계 + 눈금선 토글이 항상 오른쪽에
   붙게 한다(doc 544 M6 「좌측 요약 · 우측 토글」). margin-left:auto를 둘 다에 주면 남는 공간이
   두 auto 마진에 반씩 나뉘어 선택집계가 가운데로 떠 버린다 — 그래서 «미는 쪽»을 하나로 만든다.
   .artifact-status-bar로 스코프해 컴포저 쪽 같은 클래스에는 닿지 않는다. */
.artifact-status-bar .artifact-workbook-save-status {
  flex: 1 1 auto;
}
/* 눈금선 토글 (doc 544 P0, 목업 8층) — 리본 「보기」 그룹과 같은 명령을 상태바에서도 누른다.
   aria-pressed="true" = 눈금선이 보인다(= 문서 모드 OFF). 상태 표현은 버튼 배경이 아니라
   안의 스위치(.artifact-status-toggle-switch)가 맡는다 — §11.3. P0 의 «pressed=false 쪽
   배경 강조»는 오너 실화면 결함 보고로 폐기됐다(§11.2-(b)): 그 강조색이 hover 와 같은
   토큰(--cg-hover)이라 마우스가 올라간 채 클릭하는 순간에는 두 상태가 픽셀 하나도 다르지
   않았다. 상태(스위치/--cg-send-bg 쌍)와 hover(--cg-hover)의 토큰을 겹치지 않게 유지하라. */
.artifact-status-gridlines-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  flex: 0 0 auto;
  height: 22px;
  padding: 0 6px;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  /* ★--cg-* 토큰에 raw 폴백을 달지 않는다. 색상 부채 래칫(design-system/governance/
     anti-drift-static-baseline.json, raw-color 상한 961)은 var() «안»의 리터럴도 그대로 센다 —
     이 블록이 처음 착지했을 때 폴백 5개(#6b7280 ×2 · #ececec ×2 · #2f6bff ×1)만으로 상한을
     966 으로 넘겨 파이프라인 #5077 을 붉혔다. 토큰은 body 의 .chatgpt-reference-v1 에서
     정의되므로(styles.css:14876 근방) 이 패널에서 항상 해석된다 — 폴백은 값이 아니라 부채였다.
     이 파일의 다수 관례도 폴백 없는 형태다: var(--cg-muted) 167곳 · var(--cg-hover) 38곳. */
  color: var(--cg-muted);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  white-space: nowrap;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.artifact-status-gridlines-toggle .wds-inline-icon {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}
/* 스위치 (doc 544 §11.3 — 목업 sheet-concept-a 의 .tg 그대로): 트랙 + ::after 노브.
   켜짐(aria-pressed="true" = 눈금선 보임) = 트랙이 --cg-send-bg 로 차고 노브가 오른쪽으로
   이동. 노브 이동은 transform 만 쓴다(레이아웃 속성 애니메이션 금지 관례 — left 를 굴리면
   합성기 밖에서 프레임을 만든다). 색 토큰에 raw 폴백을 달지 않는 것은 위 토글 블록과 같은
   이유(색상 부채 래칫은 var() «안»의 리터럴도 그대로 센다).
   ★리본 쪽 눈금선/수식바 토글의 «반전 강조»는 여기서 삭제됐다(§11.2-(b) — hover 와 같은
     토큰이라 클릭 순간 시각차 0). 이제 공용 눌림 규칙(.artifact-ribbon-btn[aria-pressed=
     "true"] = --cg-send-bg 쌍)을 굵게·틀 고정과 똑같이 탄다 — 별도 규칙 자체가 없다. */
.artifact-status-toggle-switch {
  position: relative;
  width: 26px;
  height: 14px;
  flex: 0 0 auto;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-menu-border, var(--line));
  transition: background 120ms ease;
}
.artifact-status-toggle-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  /* 10px 정사각 + pill 토큰 = 원. 50% 리터럴은 raw-border-radius 래칫을 +1 시킨다(실측:
     이 블록이 처음 착지했을 때 상한 168 → 169 로 게이트가 빨개졌다). */
  border-radius: var(--ds-radius-pill);
  background: var(--bg);
  transition: transform 120ms ease;
}
/* §12 — 켜짐 트랙을 목업 `.tg.on{background:#155eef}` 의 파랑으로. §11.3 이 --cg-send-bg 를
   고른 이유(«hover 와 겹치지 않는 짝 토큰»)는 그대로 유효하고, --ad-blue 도 같은 조건을
   만족한다: hover(--cg-hover)와 다르고, 다크에서 --wds-blue-400 으로 스스로 밝아지며,
   꺼짐 트랙(--cg-menu-border)과도 라이트/다크 양쪽에서 갈린다. 리본 눌림 강조와 «같은 파랑»을
   쓰는 것이 요점이다 — 한 화면에서 «켜짐»이 두 가지 색이면 사용자가 규칙을 못 세운다.
   ★치수(26×14 트랙 / 10px 노브 / translateX(12px))는 §11.3 그대로 둔다: 목업 34×18 은
     2000px 캔버스 기준이고 실화면 환산(×0.72)이 24.5×13 이라 이미 목업 값이다. */
.artifact-status-gridlines-toggle[aria-pressed="true"] .artifact-status-toggle-switch {
  background: var(--ad-blue);
}
.artifact-status-gridlines-toggle[aria-pressed="true"] .artifact-status-toggle-switch::after {
  transform: translateX(12px);
}
.artifact-status-gridlines-toggle:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 1px;
}
.artifact-status-gridlines-toggle:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
/* 페이지 업/다운 (doc 558 ⓒ) — 기본은 «없는 것»이다. 데스크톱 상태바에는 이 두 칸이 들어갈
   자리도 없고(M6 가 폰에서 컨트롤 5개를 2개로 줄인 것과 같은 이유) 넓은 화면에는 이미 휠과
   Univer 자체 스크롤바가 있다. 폰 규칙은 아래 @media (max-width: 520px) 블록이 켠다.
   ★이 기본 규칙이 그 미디어 블록보다 «앞»에 있어야 한다: 특이도가 같아(클래스 1개) 소스
   순서가 이기고, 뒤에 두면 display:none 이 폰 규칙을 덮어써 버튼이 영영 안 보인다 —
   아래 「★아래 두 블록은 «기본 규칙 뒤»에 와야 한다」 주석이 같은 함정을 height 로 이미
   실측해 두었다.
   색 토큰에 raw 폴백을 달지 않는 것은 바로 위 눈금선 토글과 같은 이유다(색상 부채 래칫은
   var() «안»의 리터럴도 그대로 센다). --ds-radius-xs 의 길이 폴백만 그 규칙과 동일하게 둔다. */
.artifact-status-page-scroll {
  display: none;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.artifact-status-page-scroll .wds-inline-icon {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
}
.artifact-status-page-scroll:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 1px;
}
.artifact-status-page-scroll:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
/* 줌 (doc 597 P1-3 · doc 544 §13) — 엑셀 상태줄 맨 오른쪽의 «− / 배율 / +». 슬라이더는 쓰지
   않는다: 28px 상태바에 슬라이더를 넣으면 트랙이 6px 로 눌려 조준이 안 되고, 엑셀에서도 실제로
   손이 가는 것은 양끝의 −/+ 다.
   색 토큰에 raw 폴백을 달지 않는 것은 위 눈금선 토글·페이지 스크롤과 같은 이유다(색상 부채
   래칫은 var() «안»의 리터럴도 그대로 센다). --ds-radius-xs 의 «길이» 폴백만 그 관례대로 둔다. */
.artifact-status-zoom {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: 0 0 auto;
}
.artifact-status-zoom-btn,
.artifact-status-zoom-level {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  height: 22px;
  border: none;
  border-radius: var(--ds-radius-xs, 6px);
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.artifact-status-zoom-btn {
  width: 22px;
  padding: 0;
}
.artifact-status-zoom-btn .wds-inline-icon {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}
/* 배율 라벨은 «10%»~«400%» 사이를 오간다. 폭이 내용 따라 움직이면 −/+ 가 클릭할 때마다
   좌우로 흔들려 연타가 빗나간다 — 최대 문자열 기준으로 자리를 미리 잡고 숫자는 등폭으로 쓴다. */
.artifact-status-zoom-level {
  min-width: 42px;
  padding: 0 4px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.artifact-status-zoom-btn:focus-visible,
.artifact-status-zoom-level:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 1px;
}
.artifact-status-zoom-btn:disabled,
.artifact-status-zoom-level:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}
/* R1 (doc 544 §5.4): hover는 반드시 이 안에서. 이 앱이 이미 실측으로 남긴 함정 — 가드 없이 쓴
   :hover는 터치에서 «끈적여» 배경이 눌린 채로 남고, 사용자는 그 서식이 적용된 줄 안다. */
@media (hover: hover) {
  .artifact-status-gridlines-toggle:hover {
    background: var(--cg-hover);
    color: var(--cg-text);
  }
  .artifact-status-gridlines-toggle:disabled:hover {
    background: transparent;
    color: var(--cg-muted);
  }
  /* doc 558 ⓒ 도 같은 가드 안에 둔다 — 이 버튼은 «폰 전용»이라 hover 가 걸릴 일이 거의
     없지만, 가드를 빼면 hover 를 흉내내는 터치 환경에서 배경이 눌린 채 남는다(R1). */
  .artifact-status-page-scroll:hover {
    background: var(--cg-hover);
    color: var(--cg-text);
  }
  .artifact-status-page-scroll:disabled:hover {
    background: transparent;
    color: var(--cg-muted);
  }
  /* doc 597 P1-3 — 줌도 같은 가드 안에. R1: 가드 없는 :hover 는 터치에서 «끈적여» 배경이
     눌린 채 남고, 사용자는 그 배율이 적용된 줄 안다. */
  .artifact-status-zoom-btn:hover,
  .artifact-status-zoom-level:hover {
    background: var(--cg-hover);
    color: var(--cg-text);
  }
  .artifact-status-zoom-btn:disabled:hover,
  .artifact-status-zoom-level:disabled:hover {
    background: transparent;
    color: var(--cg-muted);
  }
}

/* ★아래 두 블록은 «기본 규칙 뒤»에 와야 한다. 실측으로 잡힌 회귀(2026-08-27, 390px):
   .artifact-status-gridlines-toggle{height:22px} 와 미디어 블록의 height:44px 는 특이도가
   같아(클래스 1개) 소스 순서가 이긴다 — 미디어 블록을 이 파일 위쪽(패널 모바일 절)에 두었더니
   히트영역이 44×44 가 아니라 44×22 로 렌더됐다. 미디어 쿼리는 특이도를 «올리지 않는다». */
@media (max-width: 900px) {
  /* R3 (doc 544 §5.4) — 이 폭부터 패널이 풀스크린 시트라 상태바가 화면 «물리적» 최하단에 붙는다.
     홈 인디케이터/제스처 바가 먹는 만큼을 안전영역 변수로 비운다. height를 auto로 푸는 이유:
     28px 고정인 채로 padding-bottom을 더하면 내용이 그 패딩 밖으로 밀린다.
     ★여기에 100dvh를 쓰지 않는다 — 고정 배치에 뷰포트 높이가 필요하면 var(--wizon-vvh, 100dvh)
     여야 한다(R2, doc 544 §8-8). 이 규칙은 flex 흐름 안이라 뷰포트 높이 자체가 필요 없다. */
  .artifact-status-bar {
    height: auto;
    min-height: 28px;
    padding-bottom: var(--wizon-safe-bottom, 0px);
  }
}
/* 폰(≤520px) — doc 544 M6 「2단 축약: 좌측 선택 요약 · 우측 눈금선 토글 1개」.
   520은 이 앱이 이미 44곳에서 쓰는 폰 경계다(doc 544 §5.1 — 새 브레이크포인트 발명 금지).
   "준비" 라벨만 버린다(장식). 셀 개수·저장 상태·선택 집계는 좌측 요약으로 남고, 우측에는
   눈금선 토글 하나뿐이다 — 수식바 토글·줌은 P0에서 «만들지 않았다»(P2 「보기」 탭).
   ★리본 자체의 칩/가로 스크롤 변환(M1·M2)은 P0 범위가 아니다. 여기서 하지 마라. */
@media (max-width: 520px) {
  .artifact-status-bar {
    gap: 8px;
    padding-left: 8px;
    padding-right: 8px;
  }
  .artifact-status-ready {
    display: none;
  }
  /* R4 — 아이콘 전용이어도 터치 타깃은 44×44 이상. 라벨 텍스트를 숨겨 좁은 폭에서도 다른
     요약이 밀려나지 않게 하고, 크기는 히트영역으로 되돌려 준다. */
  .artifact-status-gridlines-toggle {
    min-width: 44px;
    height: 44px;
    padding: 0;
  }
  .artifact-status-gridlines-toggle-text {
    display: none;
  }
  .artifact-status-gridlines-toggle .wds-inline-icon {
    width: 18px;
    height: 18px;
  }
  /* doc 558 ⓒ — 폰에서만 나타난다. R4 대로 아이콘 전용이어도 터치 타깃은 44×44 이상.
     상태바가 이 폭에서 height:auto + min-height:28px 이므로(위 900px 블록) 44px 버튼이
     들어가면 상태바가 그만큼 자란다 — 잘리지 않는다. */
  .artifact-status-page-scroll {
    display: inline-flex;
    min-width: 44px;
    height: 44px;
    padding: 0;
  }
  /* 좌측 요약이 폭을 넘길 때 «양보하는 쪽»은 선택 집계 하나다. 셀 개수는 기본 규칙에서
     flex:0 0 auto + nowrap 이라 접히지 않으므로, 남는 압력을 여기서 말줄임으로 흡수한다.
     min-width:0 이 없으면 flex 아이템은 자기 내용 폭 아래로 안 줄어 말줄임이 영영 안 걸리고,
     nowrap 인 채 상태바를 가로로 밀어낸다(실측 2026-08-29: scrollWidth 399 > 375).
     ★.artifact-status-bar 로 한 겹 올려 쓴다 — 기본 규칙과 특이도가 같으면 소스 순서에
     매달리는데, 그 함정은 바로 위 눈금선 토글 height 에서 이미 한 번 났다. */
  .artifact-status-bar .artifact-selection-summary {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* doc 597 P1-3 — 줌은 폰에서 숨긴다. M6 이 하단에 허용한 것은 「좌측 선택 요약 · 우측 눈금선
     토글 1개」이고, 44px 히트영역 3개를 더 넣으면 그 문장이 깨진다. M6 이 말한 「보기」 탭 이관은
     아직 안 했다(doc 544 §13 「남은 것」) — 폰에는 지금도 줌이 없으므로 이 숨김은 후퇴가 아니라
     현상 유지다. ★.artifact-status-bar 로 한 겹 올려 쓴다: 기본 규칙과 특이도가 같으면 소스
     순서에 매달리고, 그 함정은 눈금선 토글 height 에서 이미 한 번 났다(위 주석). */
  .artifact-status-bar .artifact-status-zoom {
    display: none;
  }
}
/* P2 「클릭형 셀 출처 배지」 폴백: Univer 벤더 코어에 셀 단위 렌더 훅이 없어(app.js의
   cellSourceBarHtml 주석 참고) 캔버스 위 마커 대신 이 하단 바로 대체 — 셀 하나를 선택했을 때만
   보이고, hidden 속성이 innerHTML 비움과 함께 토글된다(renderArtifactCellSourceBar). */
.artifact-cell-source-bar {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  flex: 0 0 auto;
  padding: 6px var(--ds-space-3);
  border-top: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-hover-soft);
  color: var(--cg-text, var(--text));
  font-size: var(--ds-text-caption-12);
}
.artifact-cell-source-bar[hidden] {
  display: none;
}
.artifact-cell-source-label {
  overflow: hidden;
  color: var(--cg-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.artifact-cell-source-action {
  flex: 0 0 auto;
  margin-left: auto;
  padding: 3px var(--ds-space-2);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-sm);
  background: var(--cg-surface, var(--ds-color-surface));
  color: var(--accent, var(--cg-text, var(--text)));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.artifact-cell-source-action:hover {
  background: var(--cg-hover-soft);
}
.artifact-cell-source-action:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
/* P0 후속 「시트 생성 직후 다음작업 카드」: 셀 출처 바(위)와 같은 하단 자리, 상태바(아래) 바로
   위. innerHTML 비움과 함께 hidden이 토글된다(renderSheetNextActionCard/clearSheetNextActionCard,
   cellSourceBarHtml과 같은 컨벤션). 새 색 토큰 없이 기존 var()만 재사용한다. */
.artifact-next-action-card {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  flex: 0 0 auto;
  padding: var(--ds-space-2) var(--ds-space-3);
  border-top: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-hover-soft);
}
.artifact-next-action-card[hidden] {
  display: none;
}
.artifact-next-action-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-2);
}
.artifact-next-action-title {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.artifact-next-action-dismiss {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
.artifact-next-action-dismiss svg {
  width: 14px;
  height: 14px;
}
.artifact-next-action-dismiss:hover {
  background: var(--cg-surface, var(--ds-color-surface));
  color: var(--cg-text, var(--text));
}
.artifact-next-action-dismiss:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
.artifact-next-action-items {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2);
}
.artifact-next-action-item {
  flex: 0 0 auto;
  padding: 3px var(--ds-space-2);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-sm);
  background: var(--cg-surface, var(--ds-color-surface));
  color: var(--accent, var(--cg-text, var(--text)));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.artifact-next-action-item:hover {
  background: var(--cg-hover-soft);
}
.artifact-next-action-item:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
/* 중복 통계바 제거(doc 171 A2 리뷰): Univer 내장 선택통계 위젯(영문 Max/Min/Sum/Count/Average)을
   숨겨 우리 한글 상태바 집계(.artifact-selection-summary — 평균·개수·합계)만 남긴다. 둘이 동시에
   보이면 "합계가 두 개"로 사용자 혼란이라 병합 전 해소.

   ⚠ 셀렉터 버전 취약성: 벤더된 Univer UMD(0.25.1)는 클래스를 유틸리티(univer-*, Tailwind류)로
   난독 생성해 시맨틱 클래스가 없다. 그래서 안정적 앵커 2겹으로 좁힌다 —
     (1) 상태바 루트의 data 속성 [data-range-selector] (선택 범위 통계 바에 Univer가 부여, 실렌더
         확인). 시트탭(1fr)·줌(100%)은 이 SECTION의 형제 그리드 칼럼이라 규칙에 안 걸린다.
     (2) 그 안에서 통계 블록만 감싸는 래퍼 .univer-max-w-fit — 실렌더에서 #artifactSheetContainer
         내 정확히 1개(통계 블록 전용, 시트탭/줌과 클래스 구분).
   Univer 버전업으로 이 속성/클래스가 바뀌면 규칙은 '매칭 실패 → 내장 위젯 다시 노출'로 안전하게
   fail-visible 된다(레이아웃 파손 아님). 그때 실렌더로 셀렉터만 갱신하면 된다. 통계 블록만
   display:none 하고 시트탭·줌·시트 그리드는 건드리지 않는다(실렌더로 형제 visible 확인). */
#artifactSheetContainer [data-range-selector] .univer-max-w-fit {
  display: none;
}

/* 중복 줌 제거 (doc 597 P1-3 후속 — GPT 독립 검수 보고, 2026-08-30 재현됨).
   바로 위 통계바 규칙의 주석은 「시트탭(1fr)·줌(100%)은 형제 그리드 칼럼이라 규칙에 안 걸린다」고
   적어 두었는데, 그때는 **우리 줌이 없어서** 벤더 줌 하나만 있는 것이 옳았다. 우리 상태바에 줌이
   생긴 지금 그 문장이 그대로 중복의 원인이 됐다 — 사용자에게 같은 기능이 두 개다.
   doc 544 §12 「리본/상태바는 우리가 소유한다」에 따라 우리 것을 남기고 벤더 것을 숨긴다.

   ⚠ 셀렉터 앵커 2겹 (실렌더로 확인한 0.25.1 구조):
     footer > SECTION[data-range-selector] (grid-cols-[1fr,auto,auto,auto])
       ├ DIV     ← 시트탭 (slide-tab-bar / sheet-bar-append-button)
       ├ DIV     ← 통계 블록 자리 (.univer-max-w-fit — 위 규칙이 담당)
       └ SECTION ← 줌 (버튼 3개, "100%")
   (1) `footer` 로 그리드 «영역»의 동명 요소를 배제하고, (2) 직계 `> section` 으로 좁힌다 —
   이 그리드에서 SECTION 은 줌 칼럼 하나뿐이고 시트탭·통계는 DIV 다.
   ★벤더 DOM 을 «옮기지» 않는다(doc 544 §8-3). 버전업으로 태그/속성이 바뀌면 규칙은
   '매칭 실패 → 벤더 줌 다시 노출'로 fail-visible 된다 — 최악이 «줌이 두 개»이지 결코
   «시트탭이 사라짐»이 아니다. 그 방향을 지키는 것이 이 셀렉터의 계약이다. */
#artifactSheetContainer footer [data-range-selector] > section {
  display: none;
}

/* 시트 탭 바 엑셀식 리스타일 + ◀▶ 네비/≡ 전체 시트 메뉴 (doc 171 A2.1, 사용자 피드백: "하단의 시트
   추가하는 부분을 엑셀처럼"). 실렌더로 확인한 Univer(0.25.1) 구조:
     grid(=[data-range-selector]) 1열(1fr, flex) 안에 두 형제 DIV —
       (a) 시트 추가 버튼 wrapper: [data-u-comp="sheet-bar-append-button"] × 2(+/변환)의 부모
       (b) 탭 바 wrapper: [data-u-comp="slide-tab-bar"](role=tablist)의 부모
     둘 다 시맨틱 클래스가 없는 Univer 유틸리티 클래스라 앵커는 오직 [data-u-comp] 속성만 신뢰.
   버튼/탭 자체는 손대지 않고(클릭 핸들러 유지) 색만 엑셀처럼 덮어쓴다 — 활성 탭은 Univer가 붙이는
   유틸리티 클래스(univer-bg-white univer-font-bold univer-text-primary-700 univer-shadow, 파랑)를
   흰 배경+초록 텍스트로, 비활성 탭은 연회색 배경으로. 다크모드 변형(dark:!univer-*)은 이 앱에서
   Univer 컨테이너에 .dark 클래스를 붙이는 배선이 없어 도달 불가 — 라이트만 다룬다. */
#artifactSheetContainer [data-u-comp="slide-tab-item"] {
  background: transparent;
  color: var(--cg-muted, #6b7280);
  font-weight: 500;
  border-radius: 4px 4px 0 0 !important; /* univer-rounded = 전체 라운드; 엑셀은 위쪽만 */
  box-shadow: none !important; /* 비활성 탭엔 그림자 없음 */
}
#artifactSheetContainer [data-u-comp="slide-tab-item"]:hover {
  background: var(--cg-hover-soft, #f4f4f4);
}
#artifactSheetContainer [data-u-comp="slide-tab-item"][aria-selected="true"] {
  background: var(--cg-surface, #fff) !important;
  color: var(--success, #12805c);
  font-weight: 600; /* doc 160 T4 weight palette caps at 600 — no 700 in this app */
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line)) !important;
}
/* 시트 추가(+)·변환 버튼 — 이미 정사각형에 가까운 Univer 기본 스타일을 24×24 고정 + 우리 hover 톤으로
   엑셀 느낌만 더한다. 클릭 커맨드는 Univer 것 그대로(CSS만). */
#artifactSheetContainer [data-u-comp="sheet-bar-append-button"] {
  width: 24px !important;
  height: 24px !important;
  border-radius: 4px !important;
}
#artifactSheetContainer [data-u-comp="sheet-bar-append-button"]:hover {
  background: var(--cg-hover-soft, #f4f4f4) !important;
}
/* Univer가 탭 바 오버플로우 시 자체적으로 붙이는 ‹›(아이콘 univerjs-icon-more-icon, 하나는
   univer-rotate-180) 네이티브 스크롤 버튼 — 실렌더로 뒤늦게 발견(시트 1~2개일 땐 존재하지 않다가
   overflow가 실제로 생겨야 나타남 — data-u-comp="sheet-bar-append-button"을 +/변환 버튼과 공유해
   처음엔 놓쳤다). 이미 스크롤 동작 + disabled 판정까지 정확히 구현돼 있지만, "시트 1개=present+
   disabled"(doc 171 A2.1 스펙)를 못 만족(개수 부족이면 아예 DOM에 없음). 그래서 항상 present인
   우리 ◀▶(.artifact-sheet-tabnav-btn, 아래)를 유지하고 Univer 자체 버튼은 중복 표시되지 않도록
   숨긴다 — 우리 버튼과 별개 세트라 켜 두면 화살표가 두 벌 보인다. */
#artifactSheetContainer [data-u-comp="sheet-bar-append-button"]:has(.univerjs-icon-more-icon) {
  display: none;
}
/* ◀▶ 네비 + ≡ 전체 시트 메뉴 — Univer가 만들지 않는, 우리가 직접 주입하는 크롬(app.js
   mountArtifactSheetTabBarChrome). 시트가 많아 탭 바가 넘칠 때(overflow-hidden이라 넘친 탭은
   네이티브 스크롤바 없이 그냥 안 보임 — 실측 확인) 좌우로 스크롤하고, ≡는 전체 시트 목록 팝오버를
   연다. flex `order`로 탭 바 앞(엑셀 순서: 네비/≡ → 탭 → +)에 오도록 시각적으로만 재배치 — DOM
   이동·커맨드 배선 변경 없음(inline style로 Univer 소유 wrapper 두 개에 order만 부여). */
.artifact-sheet-tabnav {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 1px;
  flex: 0 0 auto;
  margin-right: 2px;
}
.artifact-sheet-tabnav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--cg-muted, #6b7280);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.artifact-sheet-tabnav-btn .wds-inline-icon {
  width: 15px;
  height: 15px;
}
.artifact-sheet-tabnav-btn:hover:not(:disabled) {
  background: var(--cg-hover-soft, #f4f4f4);
  color: var(--cg-text, var(--text));
}
.artifact-sheet-tabnav-btn:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
/* ◀▶는 탭 바가 실제로 넘칠 때만 활성 — 시트 1개(넘침 없음)면 여기 걸려 진짜 disabled(장식 아님,
   doc 171 A2.1 스펙). ≡는 시트가 하나뿐이어도 항상 활성(목록에 1개라도 뜬다). */
.artifact-sheet-tabnav-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.artifact-sheet-tabnav-menu {
  display: flex;
  flex-direction: column;
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  min-width: 168px;
  max-height: 240px;
  overflow-y: auto;
  padding: 4px;
  border-radius: 8px;
  background: var(--cg-menu-bg, var(--cg-surface, #fff));
  box-shadow: inset 0 0 0 1px var(--cg-menu-border, var(--line)), var(--cg-menu-shadow);
  z-index: 20;
}
.artifact-sheet-tabnav-menu[hidden] {
  display: none;
}
.artifact-sheet-tabnav-menu-item {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 6px 8px;
  border: none;
  border-radius: 4px;
  background: transparent;
  color: var(--cg-text, var(--text));
  font-size: var(--ds-text-caption-13); /* doc 160 T4 bans hand-tuned half-pixel font-size values */
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.artifact-sheet-tabnav-menu-item:hover {
  background: var(--cg-hover-soft, #f4f4f4);
}
.artifact-sheet-tabnav-menu-item.is-active {
  color: var(--success, #12805c);
  font-weight: 600;
}
.artifact-sheet-tabnav-menu-item .wds-inline-icon {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}

/* P0-B: 답변 신뢰 chip 행(하단) + 통일 패널(신뢰도·출처·처리 과정). 배지를 답변 위→아래로 내려
   출처와 한 줄에 묶고, chip 탭 시 #trustPanel(파일 패널 크롬)을 연다(doc 161 §7 — 단일 패널).
   --conf-accent = vivid 도트, --conf-fg = 어두운 텍스트(WCAG 1.4.3, tint 위 ~6.5:1). */
.trust-chip[data-tier="high"],
.trust-tier-badge[data-tier="high"] {
  --conf-accent: var(--success, #12805c);
  --conf-fg: #0a5f43;
}
.trust-chip[data-tier="medium"],
.trust-tier-badge[data-tier="medium"] {
  --conf-accent: var(--ds-badge-warn-fg, #b45309);
  --conf-fg: #8a3f07;
}
.trust-chip[data-tier="low"],
.trust-tier-badge[data-tier="low"] {
  --conf-accent: var(--muted, #6b7280);
  --conf-fg: #4b5563;
}

/* --- bottom chip row --- */
.trust-chips {
  display: flex;
  gap: 7px;
  margin-top: 12px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 2px;
}
.trust-chips::-webkit-scrollbar {
  display: none;
}
.trust-chip {
  scroll-snap-align: start;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  /* Matched to the web source tag (.citation-tag, 20px) so every answer tag is one size family.
     Below the 24px WCAG 2.5.8 comfort target, but the source tag it mirrors is itself an
     interactive 20px control and the 7px inter-chip gap gives the spacing exception headroom. */
  min-height: 20px;
  padding: 0 9px;
  border-radius: var(--ds-radius-pill, 999px);
  /* Unified with the web source tag (.citation-tag, doc 164 §후속): soft-fill pill + soft
     border so every answer-footer tag reads as one family. The filled surface (not white)
     carries the control boundary; the whole row shares the source-tag surface language. */
  border: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-hover-soft, var(--surface-2));
  color: var(--cg-text, #1f2937);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.trust-chip:hover {
  background: var(--cg-hover, var(--surface-2));
  border-color: var(--cg-muted, var(--muted));
}
.trust-chip:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 2px;
}
.trust-chip--confidence {
  color: var(--conf-fg);
}
.trust-chip-text {
  font-weight: 600;
}
.trust-chip-cnt {
  display: inline-grid;
  place-items: center;
  min-width: 16px;
  height: 16px;
  padding: 0 5px;
  border-radius: var(--ds-radius-pill, 999px);
  /* White inset on the soft-fill chip so the count stays legible as a nested badge. */
  background: var(--surface, #fff);
  color: var(--muted, #475569);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}
.trust-chip-ic {
  display: inline-flex;
  /* Colored symbol like the source tag's favicon (doc 164 §후속3). Functional-color axes
     (styles.css 아트디렉션 v2): Blue = 문서·출처. 처리 과정 overrides to Violet (AI) below. */
  color: var(--ad-blue, #155eef);
}
.trust-chip--process .trust-chip-ic {
  color: var(--ad-violet, #7c5cff);
}
.trust-chip--verification .trust-chip-ic {
  color: var(--ad-green, #12805c);
}
.trust-chip--role-trace .trust-chip-ic {
  color: var(--ad-blue, #155eef);
}
/* Specificity must beat the shell default (.chatgpt-reference-v1 .wds-inline-icon = 20px), or the
   icon stays 20px and inflates the 20px chip. */
.chatgpt-reference-v1 .trust-chip-ic svg {
  width: 13px;
  height: 13px;
}
/* doc 164 §후속2: model info as a non-interactive meta badge (doc 161 §7 B2), now clustered with
   the elapsed time at the action row's end — muted, borderless, no cursor. Model + duration read
   as one "how it was made" group; the trust-chip row above stays all-interactive. */
/* Identical metrics to .answer-elapsed (same size/weight/color) so the model + duration cluster
   reads as one uniform meta pair (doc 164 §후속3). */
.answer-model-meta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--cg-muted, #8f8f8f);
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
}
.answer-model-meta-ic {
  display: inline-flex;
}
.answer-model-meta-ic svg {
  width: 13px;
  height: 13px;
}

/* --- shared meter (chip + panel tier badge) --- */
.trust-meter {
  display: inline-flex;
  gap: 3px;
}
.trust-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line, #d7dbe1);
}
.trust-dot.filled {
  background: var(--conf-accent);
}

/* --- unified panel: file-panel chrome + tabs + cards (doc 158 → #trustPanel, doc 161 §7) --- */
/* tabs reuse .chatgpt-route-tabs base; this adds a sticky rail below the header */
.trust-panel-tabs {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 2px 0 10px;
  margin-bottom: 4px;
  background: var(--surface, #fff);
  border-bottom: 1px solid var(--line);
}
.trust-panel-tabs button:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 2px;
}
.trust-panel-tabs button.is-active {
  font-weight: 600;
}
.trust-tab-cnt {
  display: inline-grid;
  place-items: center;
  min-width: 17px;
  height: 17px;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-hover-soft, #eef1f5);
  color: var(--muted, #475569);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.trust-panel-body {
  display: grid;
  gap: 10px;
}
.trust-panel-tier {
  padding: 4px 0 2px;
}
.trust-tier-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border-radius: var(--ds-radius-pill, 999px);
  background: color-mix(in srgb, var(--conf-accent) 12%, transparent);
  color: var(--conf-fg);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.trust-why {
  display: grid;
  gap: 5px;
}
.trust-why-row {
  margin: 0;
  font-size: var(--ds-text-caption-13);
  line-height: 1.55;
  color: var(--muted, #4b5563);
}
.trust-why-k {
  font-weight: 600;
  color: var(--cg-text, #374151);
  margin-right: 4px;
}

.process-route-widget {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  padding: 14px;
  border: 1px solid var(--line, #e5e7eb);
  border-radius: 12px;
  background: var(--surface, #fff);
  /* 깊이 2단(아트디렉션 v2): 카드만 띄운다 */
  box-shadow: 0 1px 2px rgba(16, 16, 20, 0.05), 0 4px 14px rgba(16, 16, 20, 0.04);
}
.process-route-icon.md-chip {
  width: 30px;
  height: 30px;
  border-radius: 9px;
}
.process-route-icon.md-chip .wds-inline-icon {
  width: 16px;
  height: 16px;
}
.process-route-copy {
  display: grid;
  gap: 4px;
  min-width: 0;
}
.process-route-copy > small {
  color: var(--ad-blue, #155eef);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  letter-spacing: 0.04em;
}
.process-route-copy > strong {
  color: var(--cg-text, #1f2937);
  font-size: var(--ds-text-body-15);
}
.process-route-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 2px;
}
.process-route-badges span {
  padding: 3px 6px;
  border: 1px solid var(--line, #dfe3e8);
  border-radius: var(--ds-radius-xs, 6px);
  background: var(--cg-hover-soft, #f7f8fa);
  color: var(--muted, #596273);
  font-size: var(--ds-text-micro-11);
  line-height: 1.2;
}
.process-route-shadow {
  margin: 4px 0 0;
  padding-top: 7px;
  border-top: 1px solid var(--line);
  color: var(--muted, #667085);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}
.process-route-shadow strong {
  color: var(--cg-text, #374151);
}
/* 상태 콜아웃: 처리 완료=그린 / 자동 전환=앰버 — 본문 콜아웃과 동일 문법 */
.process-status {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  padding: 11px 13px;
  border: 1px solid var(--line, #e5e7eb);
  border-radius: 12px;
}
.process-status[data-tone="green"] {
  border-color: color-mix(in srgb, var(--ad-green) 16%, transparent);
  background: var(--ad-green-tint);
}
.process-status[data-tone="amber"] {
  border-color: color-mix(in srgb, var(--ad-amber) 22%, transparent);
  background: var(--ad-amber-tint);
}
.process-status-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.process-status-copy strong {
  font-size: var(--ds-text-caption-13);
  line-height: 1.45;
}
.process-status[data-tone="green"] .process-status-copy strong { color: var(--ad-green); }
.process-status[data-tone="amber"] .process-status-copy strong { color: var(--ad-amber); }
.process-status-copy span,
.process-status-copy small {
  color: var(--cg-text-soft, var(--muted, #667085));
  font-size: var(--ds-text-caption-13);
  line-height: 1.5;
}
.process-status-copy small {
  color: var(--cg-muted, var(--muted, #667085));
  font-size: var(--ds-text-caption-12);
}
/* One-line recap header of the process panel (doc 165) — the gist at a glance. */
.process-summary-head {
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  color: var(--cg-text, var(--ink));
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.process-sec-label {
  margin: 24px 0 10px;
  color: var(--cg-muted, var(--muted, #7b8492));
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.process-timeline {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0 0 0 2px;
  list-style: none;
}
.process-step {
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  gap: 0 10px;
  padding-bottom: 18px;
  align-items: start;
}
.process-step:last-child {
  padding-bottom: 2px;
}
.process-step:not(:last-child)::before {
  content: "";
  position: absolute;
  top: 28px;
  bottom: 2px;
  left: 11px;
  width: 2px;
  border-radius: 2px;
  background: var(--line, #dfe3e8);
}
/* 상태 도트: 단계 의미색 틴트 원 + 아이콘 (아트디렉션 v2) */
.process-dot {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--ad-green-tint);
  color: var(--ad-green);
}
.process-dot[data-tone] .wds-inline-icon {
  /* 특이도 (0,3,0): 전역 .chatgpt-reference-v1 .wds-inline-icon(20px)을 이겨야 틴트 원이 산다 */
  width: 13px;
  height: 13px;
}
.process-dot[data-tone="blue"] { background: var(--ad-blue-tint); color: var(--ad-blue); }
.process-dot[data-tone="amber"] { background: var(--ad-amber-tint); color: var(--ad-amber); }
.process-dot[data-tone="violet"] { background: var(--ad-violet-tint); color: var(--ad-violet); }
.process-step-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}
.process-step-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-height: 24px;
}
.process-step-row strong {
  color: var(--cg-text, #1f2937);
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  line-height: 24px;
  letter-spacing: -0.01em;
}
.process-step-copy small,
.process-step time {
  color: var(--cg-muted, var(--muted, #7b8492));
  font-size: var(--ds-text-caption-12);
  line-height: 1.5;
}
.process-files {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 6px;
}
/* 모델 단계의 라이선스 칩. 문서 조회 단계의 .process-files와 같은 자리·같은 리듬이라 간격
   값을 그대로 따른다(새 spacing 토큰을 만들지 않는다). 색은 기존 아트디렉션 축의 green/amber만
   쓰고 중립은 --line/--muted로 — 새 색 토큰을 만들면 형제 선택자가 옛 토큰에 남는 문제가
   그대로 재현된다. */
.process-model-governance {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 6px;
}
.model-gov-chip {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill);
  font-size: var(--ds-text-micro-11);
  line-height: 1.5;
  white-space: nowrap;
  color: var(--muted);
}
.model-gov-chip[data-tone="green"] {
  border-color: color-mix(in srgb, var(--ad-green) 30%, transparent);
  background: var(--ad-green-tint);
  color: var(--ad-green);
}
.model-gov-chip[data-tone="amber"] {
  border-color: color-mix(in srgb, var(--ad-amber) 34%, transparent);
  background: var(--ad-amber-tint);
  color: var(--ad-amber);
}
.process-step time {
  flex: none;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* source cards — mockup anatomy: [n] · type · 관련도{ko} / title / snippet */
.trust-card-list {
  display: grid;
  gap: 8px;
}
.trust-card {
  display: block;
  padding: 11px;
  border: 1px solid var(--line, #e5e7eb);
  border-radius: 11px;
  text-decoration: none;
  color: inherit;
}
.trust-card:hover {
  background: var(--cg-hover-soft, #f7f8fa);
}
.trust-source-location-open {
  display: inline-flex;
  min-height: 32px;
  align-self: flex-start;
  align-items: center;
  gap: var(--ds-space-1);
  margin-top: 2px;
  padding: var(--ds-space-1) var(--ds-space-2);
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--ds-color-surface);
  color: var(--ds-color-muted);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  cursor: pointer;
}
.trust-source-location-open:hover {
  border-color: var(--accent);
  color: var(--ink);
}
.trust-source-location-open:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.trust-source-location-open .wds-inline-icon {
  width: 14px;
  height: 14px;
}
@media (pointer: coarse) {
  .trust-source-location-open {
    min-height: 44px;
  }
}
.trust-empty {
  padding: 12px 0;
  font-size: var(--ds-text-caption-13);
  color: var(--muted, #6b7280);
}

/* Public verification and role-trace summaries intentionally expose aggregates and mapped
   labels only. Identifiers, claim text, scope digests, and internal payload paths stay server-side. */
.verification-summary {
  display: grid;
  gap: 12px;
}
.verification-status {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px;
  border: 1px solid color-mix(in srgb, var(--ad-green, #12805c) 22%, var(--line, #e5e7eb));
  border-radius: 11px;
  background: color-mix(in srgb, var(--ad-green-tint, #e8f7f0) 70%, transparent);
  color: var(--cg-text, #1f2937);
}
.verification-status[data-status="unsupported"],
.verification-status[data-status="mixed"] {
  border-color: color-mix(in srgb, var(--ad-amber, #b45309) 24%, var(--line, #e5e7eb));
  background: color-mix(in srgb, var(--ad-amber-tint, #fff4d6) 72%, transparent);
}
.verification-status-icon {
  display: inline-flex;
  color: var(--ad-green, #12805c);
}
.verification-status[data-status="unsupported"] .verification-status-icon,
.verification-status[data-status="mixed"] .verification-status-icon {
  color: var(--ad-amber, #b45309);
}
.verification-status-icon svg {
  width: 18px;
  height: 18px;
}
.verification-status strong,
.verification-status small {
  display: block;
}
.verification-status strong {
  font-size: var(--ds-text-body-14);
  line-height: 20px;
}
.verification-status small {
  margin-top: 2px;
  color: var(--cg-muted, #7b8492);
  font-size: var(--ds-text-caption-12);
}
.verification-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.verification-metrics > div,
.verification-count-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid var(--line, #e5e7eb);
  border-radius: 9px;
  background: var(--cg-hover-soft, #f7f8fa);
}
.verification-metrics span,
.verification-count-row span {
  color: var(--cg-muted, #7b8492);
  font-size: var(--ds-text-caption-12);
}
.verification-metrics strong,
.verification-count-row strong {
  color: var(--cg-text, #1f2937);
  font-size: var(--ds-text-body-14);
  font-variant-numeric: tabular-nums;
}
.verification-counts {
  display: grid;
  gap: 6px;
}
.verification-note {
  margin: 0;
  color: var(--cg-muted, #7b8492);
  font-size: var(--ds-text-caption-12);
  line-height: 1.5;
}
.role-trace-widget {
  display: grid;
  gap: 7px;
  padding: 11px;
  border: 1px solid color-mix(in srgb, var(--ad-blue, #155eef) 20%, var(--line, #e5e7eb));
  border-radius: 11px;
  background: color-mix(in srgb, var(--ad-blue-tint, #edf4ff) 62%, transparent);
}
.role-trace-widget-head,
.role-trace-checks {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
}
.role-trace-widget-head strong {
  color: var(--cg-text, #1f2937);
  font-size: var(--ds-text-caption-13);
}
.role-trace-widget-head > span:last-child,
.role-trace-widget p,
.role-trace-checks {
  color: var(--cg-muted, #7b8492);
  font-size: var(--ds-text-caption-12);
}
.role-trace-widget p {
  margin: 0;
  line-height: 1.5;
}
.role-trace-checks span {
  padding: 3px 7px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-surface, #fff);
}

/* follow-up questions row — action nudges below the answer, distinct from the trust chips */
.followup-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 8px;
}
.followup-chip {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 12px;
  border-radius: var(--ds-radius-pill, 999px);
  border: 1px solid var(--line-strong);
  background: var(--surface, #fff);
  color: var(--cg-text, #1f2937);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background 0.15s ease;
}
.followup-chip:hover {
  background: var(--cg-hover-soft, #f7f8fa);
}
/* 라벨 + '›' 어포던스 (doc 361 §11, 소유자 요청 2026-08-07). 캐럿은 «고를 수 있다»는
   신호이므로 라벨보다 옅게 두고, 호버에서만 또렷해진다. 색·간격은 기존 칩 토큰을
   그대로 쓴다 — 새 토큰을 만들면 형제 선택자가 옛 값에 남는다(디자인 트랙 교훈). */
.followup-chip__label {
  min-width: 0;
}
.followup-chip__caret {
  margin-left: 6px;
  opacity: 0.45;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.followup-chip:hover .followup-chip__caret,
.followup-chip:focus-visible .followup-chip__caret {
  opacity: 0.9;
  transform: translateX(1px);
}
@media (prefers-reduced-motion: reduce) {
  .followup-chip__caret {
    transition: opacity 0.15s ease;
  }
  .followup-chip:hover .followup-chip__caret,
  .followup-chip:focus-visible .followup-chip__caret {
    transform: none;
  }
}
.followup-chip:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 2px;
}

.evidence-card {
  border: 1px solid var(--cg-menu-border);
  margin-top: 12px;
  border-radius: 8px;
  background: #f8fbfc;
}

.evidence-card summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 3px;
  padding: 11px 12px;
  color: var(--cg-text-soft);
  font-weight: 600;
}

.evidence-card summary small {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1.4;
}

.evidence-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 12px 10px;
}

.evidence-meta span,
.evidence-note {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}

.source-list {
  display: grid;
  gap: 8px;
  padding: 0 12px 12px;
}

.source-card {
  display: grid;
  gap: 6px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
}

.source-card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}

.source-card-head strong,
.source-card-head span {
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-12);
  line-height: 1.35;
}

.source-card-head span {
  color: var(--muted);
  white-space: nowrap;
}

.source-snippet {
  margin: 0;
  color: #334155;
  font-size: var(--ds-text-caption-13);
  line-height: 1.55;
}

.evidence-note {
  margin: 0;
  padding: 0 12px 12px;
}

.document-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 4px;
}

.document-actions button {
  min-height: 30px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
  color: var(--ink);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.document-actions button:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.run-form label,
.login-card label {
  display: grid;
  gap: 7px;
  color: #425160;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

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

.mini-card,
.app-card {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: #ffffff;
}

.mini-card {
  display: grid;
  gap: 5px;
  padding: 12px;
}

.mini-card.selected-document {
  background: #f0fafc;
  box-shadow: inset 3px 0 0 var(--accent);
}

.mini-card strong,
.app-card strong {
  display: block;
  overflow-wrap: anywhere;
  font-size: var(--ds-text-body-14);
  line-height: 1.35;
}

.mini-card span,
.app-card small {
  display: block;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.app-card {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  padding: 11px;
  color: var(--ink);
  text-align: left;
}

.app-card:hover,
.app-card.selected {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.app-icon {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: #111827;
  color: #ffffff;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
}

.context-list {
  display: grid;
  gap: 8px;
  margin: 0;
}

.context-list div {
  display: grid;
  grid-template-columns: 82px minmax(0, 1fr);
  gap: 8px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
}

.context-list dt {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.context-list dd {
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13);
}

.empty-note {
  margin: 0;
  padding: 12px;
  border: 1px dashed var(--line);
  border-radius: 8px;
  color: var(--muted);
  font-size: var(--ds-text-caption-13);
  line-height: 1.5;
}

.noise-note {
  margin: 6px 0 0;
  padding: 0 4px;
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
  line-height: 1.5;
}

/* .login-dialog uses ds-modal Tier 3 tokens (71 §4.2).
 * Aligned to ds-modal--sm (560px) per Phase 3.3 user confirm (2026-05-24). */
.login-dialog {
  width: min(560px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--ds-modal-border);
  border-radius: var(--ds-modal-radius);
  box-shadow: var(--ds-modal-shadow);
  background: var(--ds-modal-surface);
  outline: none;
}

.login-dialog::backdrop {
  background: var(--ds-modal-overlay);
}

.login-card {
  display: grid;
  gap: var(--ds-space-4);
  padding: var(--ds-space-6);
  background: var(--ds-modal-surface);
}

.login-card h2 {
  margin: 3px 0 0;
  font-size: 22px;
}

.subtle {
  margin: 8px 0 0;
  color: var(--muted);
  font-size: var(--ds-text-body-14);
  line-height: 1.5;
}

.error-text {
  min-height: 18px;
  margin: 0;
  color: var(--danger);
  font-size: var(--ds-text-caption-13);
}

/* Enterprise AI Workspace product refresh */
.app-shell {
  grid-template-columns: 308px minmax(0, 1fr);
}.theme-toggle {
  width: 100%;
  min-height: 40px;
  border: 1px solid rgba(226, 232, 240, 0.16);
  border-radius: var(--ds-radius-pill, 999px);
  background: rgba(255, 255, 255, 0.08);
  color: #f8fafc;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  transition: background var(--motion), border-color var(--motion), transform var(--motion);
}

.theme-toggle:hover,
.nav-item:hover,
.nav-item.active {
  border-color: rgba(34, 211, 238, 0.38);
  background: rgba(255, 255, 255, 0.1);
}

.theme-toggle:hover,
.nav-item:hover {
  transform: translateY(-1px);
}

.nav-section {
  gap: 7px;
}

.nav-item {
  display: grid;
  gap: 3px;
  width: 100%;
  min-height: 54px;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: transparent;
  color: #e2e8f0;
  text-align: left;
  transition: background var(--motion), border-color var(--motion), transform var(--motion);
}

.nav-item span {
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  line-height: 1.25;
}

.nav-item small {
  color: #94a3b8;
  font-size: var(--ds-text-micro-11);
  line-height: 1.3;
}

select,
input,
textarea {
  border-color: var(--line);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--ink);
}

.main-pane {
  background: var(--bg);
}

.workspace-hero {
  min-height: 96px;
  padding: 22px 30px;
  background: var(--ds-color-surface);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(18px);
}

.hero-copy {
  margin-top: 6px;
  color: var(--muted);
  font-size: var(--ds-text-body-14);
  line-height: 1.45;
}

.status-pill {
  min-height: 34px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--accent-soft);
  color: var(--accent);
}

.status-pill.soft {
  border-color: rgba(6, 182, 212, 0.24);
  background: var(--ds-color-cyan-soft);
  color: #0891b2;
}

.status-pill.glass {
  border-color: var(--line);
  background: rgba(255, 255, 255, 0.62);
  color: var(--ink-soft);
}

[data-theme="dark"] .status-pill.glass {
  background: rgba(255, 255, 255, 0.06);
}

.workbench {
  grid-template-columns: minmax(0, 1fr) minmax(340px, 430px);
}

.chat-pane {
  background:
    linear-gradient(180deg, rgba(6, 182, 212, 0.04), transparent 300px),
    var(--bg);
}

.message-list {
  gap: 20px;
  padding: 36px min(6vw, 72px);
}

.workspace-welcome {
  width: min(1120px, 100%);
  max-width: none;
  grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
  align-items: center;
  margin: auto;
  gap: 22px;
}

.welcome-intro,
.artifact-workspace,
.app-command-grid button {
  border: 1px solid var(--line);
  border-radius: var(--radius-2xl);
  background: var(--ds-color-surface);
  box-shadow: var(--shadow-panel);
}

.welcome-intro {
  display: grid;
  gap: 14px;
  padding: clamp(22px, 4vw, 38px);
}

.welcome h2 {
  max-width: 760px;
  font-size: clamp(30px, 4vw, 48px);
  letter-spacing: 0;
}

.artifact-workspace {
  display: grid;
  gap: 16px;
  padding: 20px;
}

.artifact-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.artifact-head h3 {
  margin: 3px 0 0;
  font-size: 22px;
}

.artifact-head span {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.artifact-preview-grid {
  display: grid;
  gap: 10px;
}

.artifact-preview-card {
  display: grid;
  gap: 5px;
  min-height: 72px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.artifact-preview-card strong {
  font-size: var(--ds-text-body-14);
}

.artifact-preview-card span {
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
}

.app-command-grid {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.app-command-grid button {
  display: grid;
  gap: 5px;
  min-height: 90px;
  padding: 16px;
  color: var(--ink);
  text-align: left;
  transition: border-color var(--motion), transform var(--motion), box-shadow var(--motion);
}

.app-command-grid button:hover,
.prompt-row button:hover,
.mini-card:hover,
.app-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow);
}

.app-command-grid strong {
  font-size: var(--ds-text-body-15);
}

.app-command-grid span {
  color: var(--muted);
  font-size: var(--ds-text-caption-13);
}

.section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.section-head h3 {
  margin: 2px 0 0;
  font-size: var(--ds-text-title-18);
  line-height: 1.25;
}

.prompt-row button,
.feedback-row button,
.message-label,
.message-body,
.mini-card,
.app-card,
.app-detail-panel,
.app-workflow-panel,
.app-input-fields,
.evidence-card,
.source-card,
.app-result-card,
.empty-note,
.document-actions button,
.app-menu-chip,
.login-dialog,
.login-card {
  border-radius: var(--radius-lg);
}

.message {
  grid-template-columns: 42px minmax(0, 820px);
}

.message-body {
  background: var(--ds-color-surface);
  box-shadow: var(--shadow-panel);
}

.message.user .message-body {
  background: var(--accent-soft);
}

.message-document-location-row {
  display: flex;
  margin-top: var(--ds-space-2);
}

.message.user .message-document-location-row {
  justify-content: flex-end;
}

.message-document-location-chip {
  display: inline-flex;
  min-height: 32px;
  max-width: min(100%, 420px);
  align-items: center;
  gap: var(--ds-space-1);
  padding: var(--ds-space-1) var(--ds-space-2);
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--ds-color-surface);
  color: var(--muted);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  line-height: 1.35;
  cursor: pointer;
}

.message-document-location-chip:hover {
  border-color: var(--accent);
  color: var(--ink);
}

.message-document-location-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.message-document-location-chip .wds-inline-icon {
  width: 14px;
  height: 14px;
  flex: 0 0 auto;
}

@media (pointer: coarse) {
  .message-document-location-chip {
    min-height: 44px;
  }
}

/* ── 제목 사다리 (v8, 2026-08-07) ──
   ★실측으로 잡은 결함: `##`(h4)와 `###`(h5)가 **둘 다 16px** 이라 화면에서 구분이 안 됐고,
   본문도 16px 이라 «굵은 문단»으로만 보였다. 마크다운 3단 구조가 화면에서 1단으로
   뭉개진 것이 「문서처럼 안 읽힌다」의 가장 큰 원인이다.
   연구 근거: 위계 신호 중 **크기가 가장 강하다**. 그래서 굵기·색이 아니라 크기로 세 칸을
   벌린다 — 20 / 18 / 16.
   ★여백도 문서 관례로 바꾼다: 제목은 **위로 넓고 아래로 좁아야** 아래 본문과 한 덩어리로
   묶인다(24 / 8). 기존 16/9 는 위아래가 거의 같아 제목이 어느 쪽에 속하는지 모호했다.
   ★굵기 (v10, 2026-08-07 — 소유자 승인). v8 은 UA 기본 굵기를 그대로 뒀는데, 그 값이
   타이포 계약(doc 160: 400·500·600)을 벗어나 있었다. 이제 semibold 토큰으로 내린다.
   ★정적 CSS 만 읽으면 이 규칙에 굵기 선언이 없어 «본문 400 을 물려받는다»고 읽힌다 —
     실측해야 UA 기본값이 이기고 있다는 게 보인다. 라이브 계산값으로 확인할 것.
   ★유예했던 이유였던 충돌은 실측으로 해소됐다: h5 는 본문과 같은 16px 이라 semibold 로
     내리면 `**강조**`(16px·semibold)와 값이 같아지지만, h5 에는 **섹션 번호가 항상
     앞에 붙는다**(h3 있는 문서 `1.1.1`, 없는 문서 `1.1` — 두 분기 모두 확인). 인라인
     강조에는 번호가 없으므로 화면에서 섞이지 않는다. */
.message-body h3,
.message-body h4,
.message-body h5 {
  margin: var(--ds-space-6) 0 var(--ds-space-2);
  color: var(--ink);
  font-weight: var(--ds-weight-semibold);
  line-height: 1.3;
}

.message-body h3 {
  font-size: var(--ds-text-title-20);
}

.message-body h4 {
  font-size: var(--ds-text-title-18);
}

.message-body h5 {
  font-size: var(--ds-text-body-16);
}

/* ── 문단 분리 (v8) ──
   ★실측: 문단 간격 10px 인데 행 높이는 27.2px — **0.37줄**밖에 안 벌어져 여러 문단이 한
   덩어리로 흘렀다. 「문맥·문단이 분류가 안 된다」는 인상의 직접 원인이다.
   0.74줄(20px)로 벌린다 — 한 줄을 통째로 비우면 목록·표와의 리듬이 무너지고, 0.5줄 아래면
   지금 문제가 그대로 남는다.
   ★범위를 좁게 잡는다. 전역 `.message-body p` 를 건드리면 사용자 말풍선과 위젯 내부
   문단(고지·근거 표기·타일 라벨)까지 벌어진다. **답변의 최상위 문단만** 겨냥한다 —
   마크다운 렌더러는 블록을 `.message-body` 의 직계 자식으로 넣는다.

   ★★특이도를 «일부러 낮게» 잡는다 — (0,2,1). 처음엔
   `.chatgpt-reference-v1 .message.assistant .message-body > p`(0,4,1)로 썼다가
   `test_table_card_prose_specificity` 에 걸렸다. 그 게이트는 카드가 만드는 <p>
   (`.md-table-provenance`·`.md-table-tile-label` 등, 0,3,0)가 **모든 산문 규칙을
   이겨야** 한다고 요구하는데, 0,4,1 은 그것들을 눌러 버린다. `> p` 라서 실제로는
   카드 문단에 닿지 않지만, 게이트는 «닿을 수 있는가»가 아니라 특이도만 보고 보수적으로
   막는다 — 그 보수성이 옳다. 여기서 예외를 뚫는 대신 특이도를 낮춘다.
   여백을 거는 규칙은 `.message-body p`(0,1,1) 하나뿐이라 (0,2,1)로 충분히 이긴다. */
.assistant .message-body > p {
  margin-bottom: var(--ds-space-5);
}

/* ── 섹션 자동 번호 (v9, 2026-08-07) ──
   ★레퍼런스: Perplexity Research Report(1. / 1.1 / 1.2)·Dovetail(3.3). 번호가 붙는
   순간 «대화 답변»이 «문서»로 읽힌다 — 조사한 문서형 AI 답변이 예외 없이 쓰는 장치다.
   ★렌더러를 안 고친다. 번호는 «표현»이지 «내용»이 아니므로 CSS 카운터로 붙인다 —
   모델 출력에 번호를 넣으면 복사·내보내기한 원문이 오염되고, 답변마다 번호가 어긋난다.
   ★답변마다 1부터 다시 센다(카운터 리셋을 답변 뿌리에 둔다).
   ★번호는 본문보다 흐리게 — 문서의 «가구»이지 내용이 아니다. */
.assistant .message-body {
  counter-reset: md-h3 md-h4 md-h5 md-table;
}
.assistant .message-body h3 {
  counter-increment: md-h3;
  counter-reset: md-h4 md-h5;
}
.assistant .message-body h4 {
  counter-increment: md-h4;
  counter-reset: md-h5;
}
.assistant .message-body h5 {
  counter-increment: md-h5;
}
.assistant .message-body h3::before,
.assistant .message-body h4::before,
.assistant .message-body h5::before {
  color: var(--cg-muted);
  font-variant-numeric: tabular-nums;
  font-weight: inherit;
}
.assistant .message-body h3::before {
  content: counter(md-h3) ".";
}
/* ★`#` 이 하나도 없는 답변에서는 `##` 가 최상위다. 그때 `0.1` 로 찍히면 안 된다 —
   실제 답변은 `##` 로 시작하는 경우가 흔하다. `:has()` 로 갈라 준다(이 리포에서 이미
   140곳 넘게 쓰는 확립된 패턴). */
.assistant .message-body:has(h3) h4::before {
  content: counter(md-h3) "." counter(md-h4);
}
.assistant .message-body:not(:has(h3)) h4::before {
  content: counter(md-h4) ".";
}
.assistant .message-body:has(h3) h5::before {
  content: counter(md-h3) "." counter(md-h4) "." counter(md-h5);
}
.assistant .message-body:not(:has(h3)):has(h4) h5::before {
  content: counter(md-h4) "." counter(md-h5);
}
.assistant .message-body:not(:has(h3)):not(:has(h4)) h5::before {
  content: counter(md-h5) ".";
}

.message-body code:not(pre code) {
  padding: 2px 5px;
  border-radius: var(--ds-radius-xs, 6px);
  background: var(--surface-2);
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}

.message-body pre,
.code-block,
.mini-card code {
  border-radius: var(--radius-lg);
  background: #0b1020;
}

/* Code-block card (doc 164): fenced code renders as a card — header bar (language label + copy
   button) over a horizontally scrolling body — matching ChatGPT/Claude. The body stays dark in
   both light and dark themes (like GitHub) so one syntax palette serves both; the header is a
   lifted tone with a hairline divider. Colors are fixed here (not --cg-* tokens) because a
   syntax theme is a self-contained palette on a fixed dark surface. */
.code-card {
  /* ★v10 — 표와 같은 이유로 산문 리듬(20)에 맞춘다. 16 이면 이 블록 앞뒤에서만
     간격이 좁아져 문서의 세로 리듬이 끊긴다. */
  margin: var(--ds-space-5) 0;
  border: 1px solid #23262f;
  border-radius: 12px;
  overflow: hidden;
  background: #0d1017;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.code-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 8px 6px 14px;
  background: #161a22;
  border-bottom: 1px solid #23262f;
}
.code-card-lang {
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: #b3b9c5;
}
.code-card-copy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: #aeb4c0;
  font: inherit;
  font-size: var(--ds-text-caption-12);
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.code-card-copy:hover {
  background: rgba(255, 255, 255, 0.07);
  color: #e6e9ef;
}
.code-card-copy:focus-visible {
  outline: none;
  border-color: var(--cg-focus-ring, #6b8afd);
  box-shadow: 0 0 0 2px rgba(107, 138, 253, 0.35);
}
.code-card-copy.is-copied {
  color: #6ee7a8;
}
.code-card-copy-icon {
  display: inline-flex;
}
.code-card-copy-icon svg,
.code-card-copy-icon .wds-inline-icon {
  width: 14px;
  height: 14px;
}
.code-card-scroll {
  overflow-x: auto;
}
.code-card pre.code-block {
  margin: 0;
  padding: 12px 14px;
  border-radius: 0;
  background: transparent;
}
.code-card pre.code-block code {
  font-family: inherit;
  font-size: var(--ds-text-caption-13);
  line-height: 1.6;
  color: #dfe3ea;
  white-space: pre;
}
@media (prefers-reduced-motion: reduce) {
  .code-card-copy {
    transition: none;
  }
}

/* Long code blocks (>18 lines) start collapsed: a height-capped, bottom-faded preview with a
   더보기/접기 toggle (render2 — mobile scroll-bloat guard). Copy still grabs the full source. */
.code-card--collapsible.is-collapsed .code-card-scroll {
  max-height: 22rem;
  overflow-y: hidden;
  position: relative;
}
.code-card--collapsible.is-collapsed .code-card-scroll::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3.25rem;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(13, 16, 23, 0), #0d1017);
}
.code-card-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 8px;
  border: 0;
  border-top: 1px solid #23262f;
  background: #12151d;
  color: #aeb4c0;
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.code-card-toggle:hover {
  background: rgba(255, 255, 255, 0.05);
  color: #e6e9ef;
}
.code-card-toggle:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px rgba(107, 138, 253, 0.4);
}
@media (prefers-reduced-motion: reduce) {
  .code-card-toggle {
    transition: none;
  }
}

/* highlight.js token palette (atom-one-dark), scoped to the card so it never leaks. */
.code-card .hljs-comment,
.code-card .hljs-quote {
  color: #7c828d;
  font-style: italic;
}
.code-card .hljs-doctag,
.code-card .hljs-keyword,
.code-card .hljs-formula {
  color: #c678dd;
}
.code-card .hljs-section,
.code-card .hljs-name,
.code-card .hljs-selector-tag,
.code-card .hljs-deletion,
.code-card .hljs-subst {
  color: #e06c75;
}
.code-card .hljs-literal {
  color: #56b6c2;
}
.code-card .hljs-string,
.code-card .hljs-regexp,
.code-card .hljs-addition,
.code-card .hljs-attribute,
.code-card .hljs-meta .hljs-string {
  color: #98c379;
}
.code-card .hljs-attr,
.code-card .hljs-variable,
.code-card .hljs-template-variable,
.code-card .hljs-type,
.code-card .hljs-selector-class,
.code-card .hljs-selector-attr,
.code-card .hljs-selector-pseudo,
.code-card .hljs-number {
  color: #d19a66;
}
.code-card .hljs-symbol,
.code-card .hljs-bullet,
.code-card .hljs-link,
.code-card .hljs-meta,
.code-card .hljs-selector-id,
.code-card .hljs-title {
  color: #61aeee;
}
.code-card .hljs-built_in,
.code-card .hljs-title.class_,
.code-card .hljs-class .hljs-title {
  color: #e6c07b;
}
.code-card .hljs-emphasis {
  font-style: italic;
}
.code-card .hljs-strong {
  font-weight: 600;
}
.code-card .hljs-link {
  text-decoration: underline;
}

/* Non-http markdown links (local paths) degrade to an inline code chip; break long paths so
   they wrap inside the bubble instead of forcing horizontal overflow. */
.message-body code.md-path {
  word-break: break-all;
}

/* Markdown renderer v2 (doc 161 P1): real lists/tables/quotes/callouts from renderMarkdownLite.
   Tokens only (--cg-* 와 --wds-* + legacy fallbacks) — no raw colors, no !important. */
.message-body .md-list {
  margin: var(--ds-space-2) 0 var(--ds-space-5);
  padding-left: 22px;
  display: grid;
  /* ★v11 — 항목 간격을 스케일로 올린다(5px → 12px). v8 이 산문 여백을 스케일로 접을 때
     목록 «안»은 손대지 않아 임의값이 남아 있었다.
     ★근거는 취향이 아니라 실측이다: 줄바꿈된 항목 «안»의 줄 사이가 7px 인데 항목 «사이»가
     5px 이었다 — 항목끼리가 줄끼리보다 «가까워서» 두 줄짜리 항목이 두 개 항목처럼 읽혔다.
     항목 경계가 보이려면 항목 사이 > 줄 사이여야 한다.
     ★8px(--ds-space-2) 도 조건은 넘지만 여유가 1px 뿐이라 폰트·폭·모바일에서 쉽게 뒤집힌다.
     문단 간격(20px)보다는 작아야 목록이 «한 묶음»으로 남는다 — 그 사이 값이 12px 이다. */
  gap: var(--ds-space-3);
}
.message-body .md-list li {
  line-height: 1.62;
}
.message-body .md-list li::marker {
  color: var(--cg-muted, var(--muted));
}
.message-body .md-list ul,
.message-body .md-list ol {
  /* ★중첩 목록은 부모 항목에 «붙어야» 한다 — 자기 항목 사이(8px)보다 부모와의 거리가
     가까워야 종속 관계로 읽힌다. 그래서 위 여백은 한 칸 더 작게 잡는다. */
  margin: var(--ds-space-1) 0 0;
  padding-left: 18px;
  display: grid;
  /* ★최상위(12px)보다 좁혀 위계를 준다. 다만 줄 사이(7px)는 넘어야 하므로 8px 이 하한이다. */
  gap: var(--ds-space-2);
}
/* ── 답변 속 차트 (차트 표준 규칙 5) ─────────────────────────────────────────────
   ★카드로 승격하지 않는다. 표를 카드에서 내린 v7 과 같은 판단이며, 차트는 본문의
   또 하나의 «형제 블록»이다 — 표의 다른 «뷰»가 아니다(토글하지 않는다).
   ★모든 값은 토큰이다. 안티드리프트 래칫이 여유 0이라 원시 hex·그림자·반경·크기를
   하나도 더 넣을 수 없다. 계열색은 `--ds-chart-slot-*`(두 표면에서 검증 통과). */
.md-chart {
  margin: var(--ds-space-5) 0;   /* 산문 리듬과 같은 값 — 차트에서만 리듬이 끊기지 않게 */
  position: relative;
}

/* ★타입 사다리 — 크기«와» 굵기 둘로 역할을 가른다. 크기만으로 나누면
   범례가 부제와 같은 층으로 읽힌다(목업 실측에서 둘 다 14/400 이었다). */
.md-chart-title {
  font-size: var(--ds-text-body-16);
  font-weight: var(--ds-weight-semibold);
  color: var(--ink);
}
.md-chart-subtitle {
  font-size: var(--ds-text-body-14);
  font-weight: var(--ds-weight-regular);
  color: var(--cg-text-soft, var(--muted));
  margin-top: var(--ds-space-1);
}
.md-chart-footnote {
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-regular);
  color: var(--cg-muted, var(--muted));
  margin-top: var(--ds-space-2);
}
.md-chart-area {
  margin-top: var(--ds-space-3);
  position: relative;
}
.md-chart-area svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  touch-action: none;
}
/* 글자 폭 측정용 — 화면에 나오지 않는다 */
.md-chart-measure {
  position: absolute;
  visibility: hidden;
  width: 0;
  height: 0;
}

/* 격자·축 — 1px «실선», 표면에서 한 단계. 점선은 눈에 띄어 데이터와 경쟁하고
   «임계값/추정»으로 오독된다. */
.md-chart-grid {
  stroke: var(--cg-menu-border, var(--line));
  stroke-width: 1;
}
.md-chart-tick {
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-regular);
  fill: var(--cg-text-soft, var(--muted));
  font-variant-numeric: tabular-nums;
}
/* 값은 이 표면에서 가장 굵다 — 축 라벨보다 위계가 높다 */
.md-chart-value {
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
  fill: var(--ink);
  font-variant-numeric: tabular-nums;
}

.md-chart-line {
  fill: none;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
/* 마커·조각의 «2px 표면 링/간격» — 마크를 가르는 것은 테두리가 아니라 여백이다 */
.md-chart-dot,
.md-chart-slice {
  stroke: var(--bg);
  stroke-width: 2;
}
.md-chart-cross {
  stroke: var(--cg-menu-border, var(--line));
  stroke-width: 1;
  pointer-events: none;
}
.md-chart-lift {
  fill: var(--cg-hover-soft);
  pointer-events: none;
}
.md-chart-focus-dot {
  pointer-events: none;
}
/* 히트 영역은 «칠해진 픽셀»이 아니라 잡을 수 있는 넓이 */
.md-chart-hit {
  fill: transparent;
}
.md-chart-hit:focus-visible,
.md-chart-slice:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
}

/* ★키 모양이 마크를 비춘다 — 범례와 툴팁이 «같은» 모양을 써야 한 계열에 인코딩이
   둘로 갈리지 않는다(Carbon: 범례는 색·모양·크기와 데이터의 연결을 정의한다). */
.md-chart-key {
  display: inline-block;
  flex: none;
}
.md-chart-key.line {
  width: var(--ds-space-3);
  height: 2px;
  border-radius: var(--ds-radius-2xs);
}
.md-chart-key.rect {
  width: var(--ds-space-2);
  height: var(--ds-space-2);
  border-radius: var(--ds-radius-2xs);
}

.md-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-2) var(--ds-space-4);
  margin-top: var(--ds-space-3);
}
.md-chart-legend-item {
  /* ★아래 터치 슬롭(::after)의 기준 상자. 보이는 크기는 이 규칙이 그대로 소유한다. */
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--ds-weight-medium);
  color: var(--ink);
  background: none;
  border: 0;
  padding: var(--ds-space-1) var(--ds-space-2);
  margin: calc(var(--ds-space-1) * -1) calc(var(--ds-space-2) * -1);
  border-radius: var(--ds-radius-xs);
  cursor: pointer;
}
/* ★터치에서 `:hover` 는 «다른 곳을 누를 때까지» 붙는다 — 마우스가 없으니 뗄 계기가 없다.
   범례는 `aria-pressed` 로 켜짐/꺼짐을 말하는데, 끈적이는 면이 그 신호와 겹쳐 «어느 계열이
   켜져 있나»를 거짓으로 읽히게 만든다. 2026-08-08 표 행에서 같은 병을 고쳤다(같은 가드). */
@media (hover: hover) {
  .md-chart-legend-item:hover:not([disabled]) {
    background: var(--cg-hover-soft);
  }
}
.md-chart-legend-item:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}
.md-chart-legend-item[disabled] {
  cursor: default;
}
/* ★숨김을 «흐림»만으로 표시하면 색약·저대비에서 안 보인다 — 취소선으로 형태도 준다 */
.md-chart-legend-item[aria-pressed="false"] {
  color: var(--cg-muted, var(--muted));
}
.md-chart-legend-item[aria-pressed="false"] .md-chart-legend-name {
  text-decoration: line-through;
}
.md-chart-legend-item[aria-pressed="false"] .md-chart-key {
  opacity: 0.35;
}

/* ★깊이: 차트는 평면이고 떠 있는 것은 툴팁 하나뿐이다. 그림자는 시스템 토큰을 쓴다. */
.md-chart-tip {
  position: absolute;
  z-index: 5;
  min-width: 128px;
  pointer-events: none;
  /* 반전 칩 — 정의된 잉크/바탕 쌍을 뒤집어 쓴다. 없는 토큰을 지어내면
     선언이 통째로 무효가 되어 배경이 투명해진다(뷰토글에서 겪은 결함). */
  background: var(--ink);
  color: var(--bg);
  border-radius: var(--ds-radius-xs);
  box-shadow: var(--ds-shadow-md);
  padding: var(--ds-space-2) var(--ds-space-3);
  font-size: var(--ds-text-caption-12);
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 120ms ease, transform 120ms ease;
}
.md-chart-tip[data-open] {
  opacity: 1;
  transform: none;
}
/* 툴팁 안에서는 «값»이 앞장서고 이름이 따라온다 — 범례와 반대다.
   여기서는 이미 계열을 알고 숫자를 원한다. */
.md-chart-tip-head {
  font-weight: var(--ds-weight-semibold);
  margin-bottom: var(--ds-space-1);
}
.md-chart-tip-row {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
}
.md-chart-tip-row + .md-chart-tip-row {
  margin-top: var(--ds-space-1);
}
.md-chart-tip-name {
  flex: 1;
  opacity: 0.72;
}
.md-chart-tip-value {
  font-weight: var(--ds-weight-semibold);
  font-variant-numeric: tabular-nums;
}
/* 수화 전·검증 실패 시에는 소스가 그대로 남는다 — 깨진 차트를 그리지 않는다 */
.md-chart[data-chart-pending] .md-chart-source,
.md-chart:not([data-chart-type]) .md-chart-source {
  display: block;
}
.md-chart[data-chart-type] .md-chart-source {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  .md-chart-tip {
    transition: none;
  }
}

/* Two-zone card (user request 2026-07-18, ref: 상세내역 report): the wrap is a tinted outer card
   holding a header band (toolbar) above a distinct white table block (.md-table-frame). No
   overflow clip here — the frame owns its own rounded clip; the wrap just pads the two zones. */
.md-table-wrap {
  /* ★v7 — 카드 승격을 되돌린다(사용자 승인, 2026-08-06 목업 B안).
     v6는 이 블록을 뉴스 위젯과 같은 «들어올린 카드»로 만들었다(반경 22px·리프트
     그림자·여백 24px·흰 면). 한 답변에 표가 둘 이상 나오면 산문 → 카드 → 산문이
     반복되며 답변이 «문서»가 아니라 «위젯 나열»로 읽혔다 — 사용자 지적의 원인이다.

     ★업계 실측(Mobbin 2026-08-06: Claude·ChatGPT·Grok·Perplexity·Mistral Le Chat)에서
     답변 속 표를 카드로 승격한 제품은 하나도 없었다. 전부 본문 흐름 안의 평면 표다.
     카드는 축·범례가 있어 경계가 필요한 «차트»에만 쓴다(Databricks Genie·Langdock).

     ★래퍼 자체는 남긴다 — 없애면 안 된다. 이 요소는 고지(risk notice) 마운트 앵커이자
     모바일 액션 알약의 위치 기준이고, 제목·종류칩·뷰토글이 여기 안에서 산문 규칙을
     이기는 특이도를 얻는다. «카드가 아니게» 만드는 것이지 «없애는» 것이 아니다. */
  position: relative;
  /* ★v10 — 산문 리듬에 맞춘다. v7 이 여기에 12/16 을 임의로 넣는 바람에 표 앞뒤만
     16px 이 되어, 문단·목록·인용이 모두 20px 인 흐름에서 표에서만 리듬이 끊겼다.
     ★선언값이 아니라 **실제 렌더 간격**으로 잡은 결함이다. 위쪽 12 는 앞 문단의
     20 과 상쇄돼 화면에는 20 으로 보이고, 아래쪽 16 만 튄다 — 선언만 읽으면
     «12/16 두 곳이 어긋난다»고 오진한다. 위아래 모두 산문과 같은 값으로 통일한다. */
  margin: var(--ds-space-5) 0;
}
/* The framed table block — a white surface with its own hairline + radius, sat inside the tinted
   card so it reads as a separate object from the header band above it. This is also the
   non-scrolling layer that anchors the edge-fade affordance. */
.md-table-frame {
  /* ★자기 테두리를 버린다. 카드가 곧 프레임이라 안쪽이 테두리를 유지하면 이중 테두리가
     된다 — 그 겹침이 «문서» 느낌의 절반이었다. 엣지 페이드는 여기 그대로 산다. */
  position: relative;
  overflow: hidden;
  background: var(--cg-surface, #fff);
}
/* The inner layer scrolls; the frame stays put so the edge fades can sit fixed at its edges. */
.md-table-scroll {
  overflow-x: auto;
  scrollbar-width: none;
}
.md-table-scroll::-webkit-scrollbar {
  display: none;
}
/* Desktop / mouse pointers can't flick a wide table sideways the way touch can, so show a real,
   always-visible horizontal scrollbar under the table there. Touch devices (coarse pointer) keep
   the hidden bar + edge fades — the drag gesture is the natural affordance. Styling the WebKit
   scrollbar also opts the bar out of macOS overlay auto-hide, so it stays visible while it's needed
   (overflow-x:auto still only paints it when the table actually overflows). */
@media (hover: hover) and (pointer: fine) {
  .md-table-scroll {
    scrollbar-width: thin;
    scrollbar-color: var(--cg-scrollbar-thumb) var(--cg-scrollbar-track);
  }
  .md-table-scroll::-webkit-scrollbar {
    display: block;
    height: 10px;
  }
  /* Mirror the app's existing themed scrollbar (see .chatgpt-reference-v1 scrollbar block): the
     dark-mode-aware --cg-scrollbar-thumb token + inset thumb, not a hardcoded gray. */
  .md-table-scroll::-webkit-scrollbar-thumb {
    border: 3px solid transparent;
    border-radius: var(--ds-radius-pill, 999px);
    background: var(--cg-scrollbar-thumb);
    background-clip: content-box;
  }
}
.md-table-scroll:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: -2px;
}
/* Honest "more content" fades (doc 168): JS sets data-fade-left/right only while there is
   actually content beyond that edge, so the gradient never lies about scrollability. */
.md-table-frame::before,
.md-table-frame::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 26px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease;
  z-index: 1;
}
.md-table-frame::before {
  left: 0;
  background: linear-gradient(90deg, var(--cg-surface, #fff), transparent);
}
.md-table-frame::after {
  right: 0;
  background: linear-gradient(270deg, var(--cg-surface, #fff), transparent);
}
.md-table-frame[data-fade-left="1"]::before {
  opacity: 1;
}
.md-table-frame[data-fade-right="1"]::after {
  opacity: 1;
}
.md-table {
  width: 100%;
  min-width: 340px;
  border-collapse: collapse;
  font-size: var(--cg-text-label-size, 14px);
}
.md-table th,
.md-table td {
  padding: var(--ds-space-2) var(--ds-space-3);
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  text-align: left;
  vertical-align: top;
  line-height: 1.5;
}
/* 3+ columns = a comparison grid: give every column readable breathing room so a narrow
   viewport SCROLLS the grid instead of squeezing Korean text into letter ribbons (NN/g:
   wordy cells stay legible in at most 2 mobile columns — beyond that, preserve structure). */
.md-table--wide th,
.md-table--wide td {
  min-width: 132px;
}
/* ── 타이포 위계 (①, doc 234) ──
   ★실측: 헤더도 본문도 14px에 굵기는 500/600 두 칸뿐이었다. 100 차이는 눈에 거의 안
   보이므로 헤더와 데이터를 가르는 것이 사실상 회색 하나였다 — 「문서 같다」는 인상의 뿌리.
   조사 결론이 「글꼴을 바꾸지 말고 굵기로 위계를 세워라」인데 그 채널을 안 쓰고 있었다.
   사다리를 세 칸으로 벌린다: 본문 400 < 행 식별자 600 < 열 머리글 700.
   ★열 머리글은 작아지고 굵어진다 — 데이터 표의 관례이자, 크기·굵기 두 채널을 동시에 쓰는
   유일한 방법이다. 작아진 만큼 자간을 열어 판독성을 지킨다(조사: 작은 크기에서 자간 증가).
   ★모바일 kv 스택은 thead를 display:none으로 숨기므로 이 변경이 닿지 않는다
   (`test_table_typographic_hierarchy.py`가 그 전제를 지킨다). */
.md-table thead th {
  /* ★v7 — 머리글 행을 연회색 밴드로 세운다(사용자 요청 2026-08-06: 「진짜 표처럼 타이틀·
     내용 구분」). 카드를 걷어내며 흰 면이 사라지자 머리글과 본문을 가르는 채널이 글자
     색·크기·굵기뿐이 되었다 — 면(background)이 그 셋보다 먼저 읽힌다.
     ★hex 폴백을 붙이지 않는다. `var(--x, #fff)` 의 폴백도 드리프트 래칫의 raw-color 로
     세어지고, 그 카운터는 여유가 0이다. 토큰이 없으면 투명이 되는 편이 낫다 —
     폴백이 죽은 토큰을 숨기는 문제도 같이 피한다. */
  background: var(--cg-hover-soft);
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-bold);
  letter-spacing: 0.03em;
  white-space: nowrap;
}
.md-table tbody th {
  font-weight: var(--ds-weight-semibold);
}
/* ★본문 굵기를 «명시»한다. 상속에 맡기면 사다리의 맨 아래 칸이 어디서 오는지 알 수 없고,
   위쪽 산문 규칙이 바뀌면 위계가 조용히 무너진다. */
.md-table tbody td {
  font-weight: var(--ds-weight-regular);
}
.md-table tbody tr:last-child th,
.md-table tbody tr:last-child td {
  border-bottom: 0;
}
/* Standard alignment (F1 table card redesign, doc 171): a numeric column right-aligns its
   header AND its data cells together — header/data alignment mismatch was the main legibility
   complaint in the B안 review. Tabular figures keep digit columns from jittering row to row. */
.md-table .is-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Row hover only makes sense in the real grid — the kv mobile stack below repurposes th/td as
   block-level label/value pairs, where a row "highlight" would just be visual noise. */
/* ★`@media (hover: hover)` 가 없으면 터치 기기에서 이 배경이 «끈적인다».
   iOS 는 탭한 요소에 `:hover` 를 걸고 **다른 곳을 누를 때까지 유지**한다 — 마우스가 없으니
   뗄 계기가 없다. 2026-08-08 iPhone 17 실측에서 카드 줄을 탭하면 회색 띠가 남았고, 그
   띠에 «검은 사각형»이 뚫려 보였다: 이 규칙은 `tr` 이 아니라 **`th`/`td` 에** 칠하는데
   카드 리스트에서 행이 `display: grid` 라 셀 사이 `column-gap` 이 칠해지지 않고 캔버스가
   비친다. 원인을 찾기까지 캐럿·고정 열·탭 하이라이트·눌림 클래스·텍스트 선택을 차례로
   지웠다 — 전부 아니었고, 답은 «마우스 전용 피드백이 터치에 새어 나온 것»이었다.
   ★리포는 이 가드를 이미 30곳에서 쓴다. 이 표면만 빠져 있었다. */
@media (hover: hover) {
  .md-table tbody tr:hover th,
  .md-table tbody tr:hover td {
    background: var(--cg-hover-soft, #f7f7f8);
  }
}
/* Totals row (F1): the last body row is flagged when its row-header label matches a summary
   word (합계/총계/총합/계/소계/Total/Sum) — a heavier top rule + bold weight sets it apart from
   the data rows above it without a full background block. */
.md-table .md-table-total-row th,
.md-table .md-table-total-row td {
  border-top: 1.5px solid var(--cg-menu-border, #e3e3e3);
  /* ★토큰이어야 한다. 원래 `#fcfcfc` 였는데 원시 hex 라 테마를 못 따라갔다 — 다크에서
     글자만 밝아지고 면은 흰색에 남아 대비 **1.15:1**, 사실상 안 보였다(2026-08-08 실측.
     라이트에서는 18.94:1 이라 아무 신호가 없었다).
     ★지표 타일 띠·머리글 밴드가 이미 쓰는 «요약 면» 어휘를 그대로 쓴다. 셋 다 같은 성격의
     면이라 어휘를 나눌 이유가 없다. */
  background: var(--cg-hover-soft);
  font-weight: 600;
}
/* Formula-cell indicator (F1, visual only — evaluation lands in F2): a small dot after a cell
   whose raw text starts with "=" flags it as a spreadsheet-style formula reference. */
.md-table .md-formula-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-left: var(--ds-space-1);
  vertical-align: middle;
  border-radius: 50%;
  background: #16a34a;
}
/* 2-column key-value table → stacked label/value cards on a phone (doc 168, Codex-TUI record
   transform): rows are independent items (no comparison axis), so stacking loses nothing and
   reads like the list the narrow screen wants. The generic 2-col header adds no information
   once each label sits directly above its value, so it is dropped (CSS-Tricks canonical). */
@media (max-width: 520px) {
  .md-table--kv,
  .md-table--kv tbody,
  .md-table--kv tr,
  .md-table--kv th,
  .md-table--kv td {
    display: block;
  }
  .md-table--kv thead {
    display: none;
  }
  .md-table--kv tbody tr {
    padding: var(--ds-space-2) var(--ds-space-3);
  }
  .md-table--kv tbody tr + tr {
    border-top: 1px solid var(--cg-menu-border, var(--line));
  }
  .md-table--kv tbody th,
  .md-table--kv tbody td {
    padding: 0;
    border-bottom: 0;
  }
  .md-table--kv tbody th {
    margin-bottom: 2px;
    font-size: var(--cg-text-meta-size, 12px);
    color: var(--cg-muted, var(--muted));
  }
  /* The stacked card reads top-to-bottom (label above value) — a right-aligned numeric value
     against the card's full width would float away from its label, so realign left here. */
  .md-table--kv tbody .is-num {
    text-align: left;
  }
  /* ★kv 스택은 th/td를 block으로 바꾼다. 거기서 sticky는 의미가 없고 배경만 남아
     스택 카드의 라벨 줄에 엉뚱한 면이 생긴다. */
  .md-table-scroll .md-table--kv th:first-child,
  .md-table-scroll .md-table--kv td:first-child {
    position: static;
    background: transparent;
    box-shadow: none;
  }

  /* ── 3열 이상 표 = 카드 리스트 (B2 — 요약 줄 + 펼침, 소유자 결정 2026-08-08) ──
     ★2열 표는 위 `md-table--kv` 가 이미 라벨/값 카드로 스택한다. 여기서 다루는 것은 3열
     이상, 즉 «비교 축이 있는» 표다. 그래서 통째로 카드로 쪼개지 않는다 — 접힌 상태에서
     이름과 대표값이 한 줄로 남아 세로로 정렬되고, 그래서 열 방향 비교가 살아 있다.
     ★조사 경고를 그대로 받는다: 「카드는 훑기용, 표는 비교용」. 행을 통째로 카드로 쪼개는
     B1 안은 5행 표를 화면 4개 높이로 만들면서 「어느 분기가 가장 컸나」를 잃는다 —
     좁은 화면에서 «공간을 아껴 읽는다»는 목표와 반대로 간다.
     ★DOM 은 표 그대로다. 표시만 바꾼다 — 시맨틱·내보내기·수식 치환이 전부 그대로 산다. */
  .md-table--wide[data-card-list="1"],
  .md-table--wide[data-card-list="1"] tbody,
  .md-table--wide[data-card-list="1"] th,
  .md-table--wide[data-card-list="1"] td {
    display: block;
  }
  /* ★머리글을 지우지 않고 감춘다. 스크린리더는 여전히 열 이름을 듣고, 각 값 앞에는
     아래 `::before` 가 같은 이름을 다시 붙인다. */
  .md-table--wide[data-card-list="1"] thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .md-table--wide[data-card-list="1"] tbody tr {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    column-gap: var(--ds-space-3);
    padding: var(--ds-space-3) var(--ds-space-1);
    /* ★44px 는 스케일 단계가 아니라 터치 표적이다(같은 파일 알약 주석과 같은 상수). */
    min-height: var(--md-table-pill-target, 44px);
    border-top: 1px solid var(--cg-menu-border, var(--line));
    cursor: pointer;
  }
  .md-table--wide[data-card-list="1"] tbody th,
  .md-table--wide[data-card-list="1"] tbody td {
    padding: 0;
    border: 0;
  }
  .md-table--wide[data-card-list="1"] tbody tr:focus-visible {
    outline: 2px solid var(--cg-focus-ring, var(--accent));
    outline-offset: 2px;
  }
  /* ★탭한 행에 회색 면과 «검은 사각형»이 남았다(2026-08-08 iPhone 17 실측).
     추측을 두 번 하고 두 번 틀린 뒤에야 측정으로 좁혔다. 증거 셋:
       1. Chrome 에서 같은 DOM·같은 선언으로 재현하니 행 안에 면을 그리는 것은 초록
          수식 점 둘뿐이고, 행을 덮는 외부 요소는 **0개**였다 → 레이아웃이 아니다.
       2. 시뮬레이터에서 **다른 곳을 탭하자 회색 면과 검은 사각형이 함께 사라졌다**.
          행은 펼쳐진 채였다 → 상태가 아니라 «탭에 딸린 일시 표시»다.
       3. 리포 전역에 `-webkit-tap-highlight-color` 선언이 하나도 없다 → 이 표면은
          Safari 기본 탭 하이라이트를 그대로 쓰고 있었다.
     ★행이 `display: grid` 라 하이라이트가 칠하는 클라이언트 사각형이 셀별로 쪼개지고,
     그 사이에 네모난 조각이 남는다 — 그것이 «검은 사각형»으로 보였다.
     ★`user-select: none` 을 행 전체에 주지 **않는다**. 그러면 폰에서 숫자 하나를 길게
     눌러 복사하는 길이 막히고, 「표 전체를 내보내세요」는 그보다 나쁜 답이다. */
  .md-table--wide[data-card-list="1"] tbody tr[data-card-row] {
    -webkit-tap-highlight-color: transparent;
    /* ★진짜 원인은 **텍스트 선택**이었다. Chrome 에서 같은 행을 선택시켜 재보니 선택
       하이라이트가 클라이언트 사각형 **8개**로 쪼개졌다 — 첫 줄에서 이름 칸이
       `x 4→609`, 값 칸이 `x 621→753`. 그 사이 그리드 간격이 칠해지지 않고 남아
       **캔버스가 비쳐 보이는 검은 조각**이 된다. 회색 띠는 선택 하이라이트 자체다.
       탭이 선택을 만드는 이유: 이름 칸은 `1fr` 이라 짧은 글자 뒤로 빈 공간이 넓고,
       그 빈 곳을 누르면 Safari 가 선택 제스처로 읽는다.
       ★그래서 «누르는 상자»는 선택 불가로, «데이터»는 선택 가능으로 나눈다. 행 전체를
       막는 쉬운 답은 폰에서 숫자 하나 복사하는 길을 없앤다 — 아래에서 되돌린다. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
  }
  /* ★값과 상세는 다시 고를 수 있게 되돌린다. 카드 리스트를 만든 이유가 좁은 화면에서
     값을 «읽게» 하는 것인데, 읽은 값을 가져갈 수 없으면 반쯤만 한 것이다. */
  .md-table--wide[data-card-list="1"] tbody [data-card="value"],
  .md-table--wide[data-card-list="1"] tbody [data-card="detail"] {
    -webkit-user-select: text;
    user-select: text;
  }
  /* 요약 줄 — 이름 왼쪽, 대표값 오른쪽. 접혀 있어도 이 두 칸은 언제나 보인다. */
  .md-table--wide[data-card-list="1"] tbody [data-card="key"] {
    grid-column: 1;
    text-align: left;
    font-weight: var(--ds-weight-semibold);
  }
  .md-table--wide[data-card-list="1"] tbody [data-card="value"] {
    grid-column: 2;
    text-align: right;
    font-variant-numeric: tabular-nums;
  }
  /* ★펼침 표시는 생성 콘텐츠다. 셀에 텍스트 노드를 넣으면 복사·엑셀·CSV 가 전부
     「1,200 ▾」이 된다 — 내보내기는 `textContent` 를 읽고 복사는 raw `outerHTML` 을 싣는다. */
  .md-table--wide[data-card-list="1"] tbody tr[data-card-row] [data-card="value"]::after {
    content: "▾";
    margin-left: var(--ds-space-2);
    color: var(--cg-muted);
    font-size: var(--cg-text-meta-size);
  }
  .md-table--wide[data-card-list="1"] tbody tr[data-expanded="1"] [data-card="value"]::after {
    content: "▴";
  }
  /* 상세 — 펼쳤을 때만. 라벨:값 한 줄. */
  .md-table--wide[data-card-list="1"] tbody [data-card="detail"] {
    grid-column: 1 / -1;
    display: flex;
    align-items: baseline;
    /* ★`space-between` 이면 안 된다(2026-08-08 iOS 시뮬레이터 실측). 셀은 자식이 하나가
       아니다 — 수식 평가 셀은 「값 텍스트 + 평가 표시 점」 둘을 담고, flex 는 익명 텍스트
       노드까지 아이템으로 세므로 [라벨][값][점] **셋**이 고르게 벌어져 값이 한가운데로
       떠 버린다. 라벨만 밀어내면 값과 점은 붙은 채 오른쪽으로 간다. */
    justify-content: flex-start;
    gap: var(--ds-space-1);
    padding-top: var(--ds-space-1);
  }
  .md-table--wide[data-card-list="1"] tbody [data-card="detail"]::before {
    content: attr(data-label);
    margin-right: auto;
    padding-right: var(--ds-space-3);
    color: var(--cg-muted);
    font-size: var(--cg-text-meta-size);
  }
  .md-table--wide[data-card-list="1"] tbody tr:not([data-expanded="1"]) [data-card="detail"] {
    display: none;
  }
  /* ★스택에서 sticky 는 의미가 없고 배경만 남아 이름 줄에 엉뚱한 면이 생긴다
     (위 `md-table--kv` 가 같은 이유로 같은 것을 한다). */
  /* ★추이 열도 «오른쪽 고정»이다 — 첫 열 고정의 거울상이라 같은 병이 걸린다.
     2026-08-08 iPhone 17 실측: 카드를 펼치면 이름 오른쪽에 검은 사각형이 떴다. 스택에서
     `position: sticky` 는 붙을 축이 없어 아무 일도 안 하는데 `background`·`box-shadow`·
     `z-index: 2` 는 그대로 살아 남의 줄 «위»에 면을 그린다(다크 캔버스라 검정으로 보였다).
     ★캐럿인 줄 알고 `caret-color` 부터 손댔다가 틀렸다 — 화면만 보고 원인을 지어낸 것이다.
     선언을 읽으니 리포 주석이 이 실패 모드를 kv 변형에 대해 이미 적어 두고 있었다. */
  /* ★카드 리스트에서는 레일을 그리지 않는다. 레일의 일은 «행과 행을 세로로 잇는 것»인데,
     스택에서는 행 사이가 카드 경계로 갈라져 선이 토막난다 — 이으려던 것을 못 잇고
     조각만 남는다. 순서는 이미 카드가 위에서 아래로 읽히는 것이 말해 준다.
     ★`content: none` 으로 끈다. 규칙 자체를 좁은 폭 밖에 두면 넓은 화면과 어긋난다. */
  .md-table--wide[data-card-list="1"] th.md-table-timeline::before,
  .md-table--wide[data-card-list="1"] td.md-table-timeline::before,
  .md-table--wide[data-card-list="1"] th.md-table-timeline::after,
  .md-table--wide[data-card-list="1"] td.md-table-timeline::after {
    content: none;
  }
  .md-table--wide[data-card-list="1"] th.md-table-timeline,
  .md-table--wide[data-card-list="1"] td.md-table-timeline {
    padding-left: 0;
  }
  .md-table-scroll .md-table--wide[data-card-list="1"] .md-table-sparkline-head,
  .md-table-scroll .md-table--wide[data-card-list="1"] .md-table-sparkline-cell,
  .md-table-scroll .md-table--wide[data-card-list="1"] th:first-child,
  .md-table-scroll .md-table--wide[data-card-list="1"] td:first-child {
    position: static;
    background: transparent;
    box-shadow: none;
    /* ★`width` 도 되돌려야 한다. 추이 열은 넓은 화면에서 「내용만큼만」 차지하려고
       `width: 1%` 를 쓰는데, 스택에서는 그 선언이 `grid-column: 1 / -1` 을 **이겨**
       상세 줄 하나만 좁아진다(2026-08-08 실측: 다른 상세 749px vs 추이 132px).
       고정을 되돌릴 때 면·그림자만 챙기고 폭을 빠뜨린 것이 이 결함이었다 — 넓은 화면
       전용 선언은 «전부» 되돌려야 한다. */
    width: auto;
  }
  /* ★선도 오른쪽 끝에 앉아야 한다. 넓은 화면에서 선은 좁은 열 «가운데»에 놓이려고
     `margin: 0 auto` 를 쓰는데, 상세 줄이 전체 폭이 되자 그 auto 가 216px 로 풀려
     선이 허공 한가운데 떴다(2026-08-08 실기기 실측: 셀은 4→753 인데 선은 473→537).
     ★같은 카드 안에서 다른 상세 값은 전부 오른쪽 끝 정렬이다 — 선만 다른 축에 서면
     「이 줄은 다른 종류인가」로 읽힌다. 취향이 아니라 형제와의 일관성 문제다. */
  .md-table--wide[data-card-list="1"] tbody [data-card="detail"] .md-table-sparkline {
    margin: 0;
  }
  /* ★알약이 떠 있으므로 마지막 행·근거 표기를 가리지 않도록 카드가 자리를 비운다.
     position:relative가 없으면 알약이 카드가 아니라 더 바깥을 기준으로 앉는다. */
  .md-table-wrap {
    position: relative;
    /* ★44px는 «스케일 단계»가 아니라 터치 표적 크기다(애플·구글 권장). 버튼 크기와 카드가
       비우는 자리가 한 상수에서 나와야 둘이 어긋나지 않는다 — 따로 적으면 한쪽만 바뀐다. */
    --md-table-pill-target: 44px;
    padding-bottom: calc(var(--ds-space-6) + var(--md-table-pill-target));
  }
  .md-table--kv {
    min-width: 0;
  }
}
/* Table toolbar row (F1 table card redesign, doc 171 B안): a dedicated header row ABOVE the
   table body (title block left, icon-only actions right) — a distinct layer from the grid below
   it (own white background + hairline divider), replacing the old hover-tinted single-line bar.
   Sits in normal flow, not absolutely positioned over the table. */
.md-table-toolbar {
  /* ★v7 — 카드 헤더 밴드에서 «표 제목 행»으로 바뀐다. 흐름 안에 머무는 것은 그대로다
     (절대 배치로 표 위를 덮지 않는다 — 그 판정은 v6에서 이미 내려졌고 유효하다).
     정렬을 flex-start → center 로 바꾼다: 부제가 화면에서 사라져(sr-only) 제목이 한 줄이
     되었으므로, 오른쪽 액션과 광학 중심을 맞추는 쪽이 맞다. */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
  padding: 0 0 var(--ds-space-2);
  background: transparent;
}
.md-table-titles {
  /* 부제가 sr-only(position: absolute)라 흐름 밖이다 — 그래서 이 줄은 «제목 + 종류 칩»
     한 행이다. 구조는 유지한다: 스크린리더는 여전히 제목 다음에 «N열 × M행»을 듣는다.
     ★v11 — column → row. 종류 칩이 툴바에서 토글과 액션 아이콘 «사이»에 있어 「표 / 막대 /
     추이」가 3분할 세그먼트로 읽혔다(실측: 그 줄에서 색이 채워진 유일한 요소가 «누를 수
     없는» 칩이었고, 정작 선택된 「막대」는 흰색이었다). 분류는 메타데이터이므로 제목 옆으로
     옮긴다 — 근접성이 «컨트롤이 아니다»를 구조로 말한다. */
  display: flex;
  flex-direction: row;
  align-items: baseline;
  gap: var(--ds-space-2);
  flex: 1 1 auto;
  min-width: 0;
}
.md-table-title {
  /* ★v7 — 22px 헤드라인에서 «표 제목»으로 내린다(사용자 요청 2026-08-06).
     22px/600은 카드 헤드라인 크기였다. 카드를 걷어낸 지금 그 크기는 본문 h3(20px)보다
     커서 표가 여전히 «독립 위젯»으로 읽힌다. 18px/700 은 본문 h3 아래·본문 16px 위에
     앉아 «이 표의 이름»으로 읽히는 자리다.
     ★굵기로는 올릴 수 없다 — 시도했다가 타이포 계약(T4)에 걸렸다. 원시 굵기 700은
     **모바일 상단바 WIZON 워드마크 한 곳**에만 허용된 브랜드 예외이고, 래칫이 그 예외가
     번지는 것을 막는다(그 게이트는 주석까지 세므로 여기에도 선언 형태로 적지 않는다).
     셸도 `--ds-weight-bold`를 600으로 덮으므로 토큰 경로로도 닿지 못한다.
     이 표면에서 굵기 사다리는 400/500/600 세 칸이 전부다.
     → 위계는 **크기(18 > 행 식별자 14 > 머리글 12)와 액센트 바**가 나눠 진다. 굵기는
     행 식별자와 같은 600이지만 4px 크기 차와 바가 «표의 이름»을 충분히 세운다.
     ★왼쪽 액센트 바(::before)가 «제목» 신호를 담당한다. 색을 글자에 칠하지 않는 이유 —
     매 답변에 채도색이 번지면 링크·강조와 경쟁한다(doc 345 잉크 규율). 바는 면적이
     좁아 그 예산 안에 들어가고, `--accent`라 사용자가 고른 강조색·다크모드를 따라간다. */
  /* ★flex 로 짜지 않는다. `applyTableCardTitle`(app.js)이 이 노드에 `textContent`를
     그대로 대입해 제목을 갱신하므로 자식 요소를 두면 조용히 지워진다. 또 flex 컨테이너의
     익명 텍스트 아이템에는 `text-overflow: ellipsis`가 걸리지 않는다.
     → 바는 절대배치 `::before`(DOM이 아니라 CSS라 textContent 대입에도 살아남는다),
       본문은 padding-left로 비켜 앉힌다. */
  /* ★v12 — `nowrap` + 말줄임을 **두 줄 줄바꿈**으로 바꾼다(2026-08-08).
     실측이 원인을 지목했다: 390px 에서 제목 196px 중 **87px(44%)이 잘렸고**, 같은 폭에서
     뷰 토글만 숨기니 87px → 7px 로 떨어졌다. 즉 잘림의 주범은 폭이 아니라 «같은 줄을
     쓰는 컨트롤»이었다. 토글은 A안에서 사라졌지만, 제목이 한 줄로 고정된 한 더 긴 제목은
     같은 자리에서 다시 잘린다 — 구조로 닫는다.
     ★업계도 제목을 컨트롤과 겨루게 두지 않는다(2026-08-08 실측): Claude 는 표 제목을
     산문 H3 18px/600 으로 표 위에 따로 놓고(우리와 같은 값·다른 자리), ChatGPT 는 제목
     없이 산문 한 문장이 그 역할을 한다. 어느 쪽도 잘리지 않는다.
     ★두 줄에서 멈춘다. 무한정 늘면 제목이 문단이 되어 표를 아래로 밀어낸다. */
  position: relative;
  padding-left: var(--ds-space-3);
  overflow: hidden;
  white-space: normal;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  font-size: var(--ds-text-title-18);
  font-weight: var(--ds-weight-semibold);
  letter-spacing: -0.01em;
  line-height: 1.3;
  color: var(--cg-text, #0d0d0d);
}
.md-table-title::after {
  /* 제목 왼쪽 액센트 바. `height: 1em`이라 글자 크기를 따라간다.
     ★v9 에서 `::before` → `::after` 로 옮겼다. 바는 절대배치라 문서 순서와 무관하게
     같은 자리에 그려지고, 비워진 `::before` 를 표 번호가 쓴다(아래). */
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 4px;
  height: 1em;
  transform: translateY(-50%);
  border-radius: var(--ds-radius-xs, 6px);
  background: var(--accent);
}
/* ── 표 번호 (v9) ──
   ★학술 표준 확인: 표 제목은 **위**에 둔다(APA·MLA·Chicago 공통). 아래로 내리는 것은
   그림 캡션의 관례다. 즉 우리 배치는 이미 표준이므로 «번호»만 더한다.
   APA 는 «표 번호 + 제목»을 쓰므로 「표 1. 사대보험 요율」 형태가 된다.
   ★폴백 제목(설명 없는 "표 N")에는 안 붙인다 — 그건 감춰져 있고, 번호만 남으면 다시
   «의미 없는 라벨»이 된다. 번호는 설명이 있을 때만 의미가 있다. */
.assistant .message-body .md-table-wrap {
  counter-increment: md-table;
}
.assistant .message-body .md-table-title:not([data-title-fallback])::before {
  content: "표 " counter(md-table) ". ";
  color: var(--cg-muted);
  font-variant-numeric: tabular-nums;
}
/* ── 폴백 제목은 화면에서 감춘다 (v7-2, 실측 기반) ──
   ★실제 답변 3건이 모두 "표 1" 이었다 — 모델이 표부터 쓰기 시작해 승격할 헤딩이 없다.
   그건 «이 표의 이름»이 아니라 기계가 붙인 일련번호다. 카드 시절엔 헤더 안 헤드라인이라
   그러려니 했지만, 인라인에서는 액센트 바까지 달려 **의미 없는 라벨이 오히려 강조**된다.
   "N열 × M행" 을 화면에서 뺀 것과 정확히 같은 이유다.
   ★지우지 않고 감춘다: 표가 여럿일 때 스크린리더는 이름으로 구분하고, 아티팩트가 진짜
   제목을 주면 `applyTableCardTitle` 이 표식을 걷어내 그대로 드러난다. */
.md-table-title[data-title-fallback] {
  position: absolute;
  width: 1px;
  height: 1px;
  padding-left: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.md-table-title[data-title-fallback]::before {
  content: none;
}
/* ★제목이 감춰지면 툴바의 아래 여백도 뺀다. 액션 버튼(34px)은 hover 영역이라 자리를
   지켜야 하지만, 그 아래 8px 은 «제목과 표를 띄우는» 간격이라 제목이 없으면 근거가 없다.
   실측: 폴백일 때 표 위 빈 띠 42px → 34px.
   ★모바일은 이미 문제가 아니다 — 거기서는 액션이 하단 알약으로 절대배치돼 흐름에서
   빠지므로 툴바 높이가 패딩만 남는다. */
.md-table-toolbar:has(.md-table-title[data-title-fallback]) {
  padding-bottom: 0;
}
.md-table-subtitle {
  /* ★v7 — 화면에서 감춘다(사용자 지적 2026-08-06). "3열 × 6행"은 표의 «판정용 수치»이지
     읽는 사람이 쓰는 정보가 아니다 — 원시 데이터를 1차 표면에 올리지 않는다는 원칙과
     같은 결이다. 다만 지우지는 않는다: 표의 크기는 스크린리더 사용자에게는 실제로
     유용한 사전 정보라(표에 들어가기 전에 규모를 안다) sr-only로 남긴다.
     ★전역 `.visually-hidden`을 쓰지 않는 이유 둘: 마크업의 클래스를 바꾸면 렌더러 계약
     문자열이 깨지고, 그 유틸은 전 선언이 `!important`인데 이 블록(마크다운 렌더러 v2)은
     `!important` 금지가 걸려 있다.
     ★레거시 `margin: -1px` 관용구는 안 쓴다 — `position: absolute`라 이미 흐름 밖이라
     불필요하고, 원시 px 여백이라 간격 스케일 게이트에 걸린다. */
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.md-table-actions {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  flex: 0 0 auto;
}
/* ── 액션 페이드 (v7) ──
   ★v6의 판정을 뒤집지 않는다. 옛 오버레이가 폐기된 사유는 «표 머리글 셀을 덮었다»는
   것이었고 그 판정은 지금도 옳다 — 그래서 액션은 **흐름 안 제목 행에 그대로 둔다**
   (절대배치 없음). 바뀌는 것은 «쉴 때의 세기»뿐이다: 한 답변에 표가 셋이면 상주
   아이콘이 12개가 되어 산문을 압도한다는 것이 사용자 지적의 일부였다.
   ★정밀 포인터에서만 건다. 터치에서는 hover가 없어 영영 못 찾는다 — 그쪽은 하단
   알약이 늘 보이는 기존 계약을 그대로 쓴다.
   ★`:focus-within`이 필수다. opacity:0 은 포커스 가능성을 없애지 않으므로, 이게 없으면
   키보드 사용자가 «보이지 않는 버튼»에 탭으로 들어간다.
   ★자리는 늘 차지한다(visibility/display 를 안 쓴다) — 나타날 때 제목이 밀리면 안 된다. */
@media (hover: hover) and (pointer: fine) {
  .message-body .md-table-wrap .md-table-actions {
    opacity: 0;
    transition: opacity 140ms ease;
  }
  .message-body .md-table-wrap:hover .md-table-actions,
  .message-body .md-table-wrap:focus-within .md-table-actions {
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .message-body .md-table-wrap .md-table-actions {
    transition: none;
  }
}
/* Icon-only action buttons (no border, no visible chrome at rest) — the file-format icons
   themselves distinguish copy/xlsx/csv/sheet, so the button chrome stays out of the way until
   hover/focus. */
.md-table-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.md-table-copy:hover {
  background: var(--cg-hover-soft, #f4f4f4);
  color: var(--cg-text, var(--text));
}
.md-table-copy:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
.md-table-copy.is-copied {
  color: var(--accent, #2f6bff);
}
.md-table-copy-icon {
  display: inline-flex;
}
.md-table-copy-icon svg,
.md-table-copy-icon .wds-inline-icon {
  width: 18px;
  height: 18px;
}
@media (any-pointer: coarse), (max-width: 520px) {
  /* ── 차트 범례의 터치 슬롭 (2026-08-08 실기기) ──
     ★iPhone 17(402×874pt)에서 처음 재 봤다. 탭은 동작하지만 항목이 **67×30px** 이라
     WCAG 2.2 SC 2.5.8(24×24)은 넘어도 Apple HIG 의 44pt 는 못 넘는다.
     ★보이는 크기는 안 건드린다. 30px 을 44px 로 키우면 범례 줄이 데스크톱에서도 두꺼워져
     차트의 리듬이 바뀐다 — 이 파일이 이미 쓰는 방법(.citation-tag::after)대로 보이지 않는
     슬롭으로 히트 영역만 넓힌다. 폭은 이미 44 를 넘으므로 높이만.
     ★자기 칸 밖으로 나가지 않는다. 슬롭은 안 보이므로 겹치면 엉뚱한 계열이 꺼진다. */
  .md-chart-legend-item::after {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }
  /* Safety net: keep the 4 buttons from overflowing the toolbar row at narrow/touch widths. */
  /* ── 모바일 액션 알약 (v10-3) ──
     ★Mobbin의 ChatGPT가 우리와 같은 문제를 푼 방식이다 — 답변 안의 표에서 액션을 헤더가
     아니라 하단 알약으로 뺀다. 헤더 오른쪽은 한 손 조작에서 엄지가 닿기 가장 먼 자리다.
     ★DOM을 옮기지 않는다. 버튼을 복제하면 같은 기능이 둘이 되어 포커스 순서·상태·
     data-table-copy 훅이 갈린다. 같은 요소를 CSS로 재배치할 뿐이다. */
  .md-table-actions {
    position: absolute;
    left: 50%;
    bottom: var(--ds-space-3);
    transform: translateX(-50%);
    /* ★`left:50%`인 절대 요소는 «가용 폭»이 컨테이너의 50%로 잘린다. 알약 내용(196px)이
       그보다 넓으면 아래 flex-wrap이 발동해 3+1로 접힌다 — 실기기(iPhone 402pt)에서만
       드러났고 데스크톱 폭에서는 안 보였다. max-content로 내용 폭을 되찾는다.
       max-width는 내용이 더 늘어도 카드를 넘지 않게 하는 상한이다. */
    width: max-content;
    max-width: calc(100% - var(--ds-space-6));
    z-index: 4;
    /* ★기존 계약: 320px에서 4버튼이 넘치지 않고 접힌다. 알약이 돼도 유지한다. */
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--ds-space-1);
    padding: var(--ds-space-1);
    border-radius: var(--wizon-ai-radius-pill, 999px);
    background: var(--cg-surface, var(--ds-color-surface));
    box-shadow: 0 6px 20px -6px color-mix(in srgb, var(--ds-black) 28%, transparent),
      inset 0 0 0 1px var(--cg-menu-border, var(--line));
  }
  /* ★34px는 엄지로 누르기에 작다(애플·구글 권장 44px). 알약에서만 키운다 —
     데스크톱은 마우스라 34px로 충분하고, 헤더가 넓어지면 제목이 밀린다. */
  .md-table-copy {
    width: var(--md-table-pill-target);
    height: var(--md-table-pill-target);
  }
}
@media (prefers-reduced-motion: reduce) {
  .md-table-copy {
    transition: none;
  }
  .artifact-titlebar-button {
    transition: none;
  }
}
/* Sheet-window titlebar download buttons (doc 171 A1) — same 34x34 icon-only convention as
   .md-table-copy above (F1), kept as its own ruleset (not a shared selector list) because
   test_table_action_buttons_are_icon_only_with_tooltips pins ".md-table-copy {" as a standalone
   selector string. */
.artifact-titlebar-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.artifact-titlebar-button:hover {
  background: var(--cg-hover-soft, #f4f4f4);
  color: var(--cg-text, var(--text));
}
.artifact-titlebar-button:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
.artifact-titlebar-button.is-copied {
  color: var(--accent, #2f6bff);
}
.artifact-titlebar-button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.artifact-titlebar-button:disabled:hover {
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
}
.artifact-titlebar-button-icon {
  display: inline-flex;
}
.artifact-titlebar-button-icon svg,
.artifact-titlebar-button-icon .wds-inline-icon {
  width: 18px;
  height: 18px;
}

/* KaTeX math (render2, self-hosted). Inline math inherits answer color; display math centers and
   scrolls horizontally if an equation is wider than the bubble. */
.message-body .katex {
  font-size: 1.05em;
}
.message-body .md-math-block {
  margin: var(--ds-space-4) 0;
  padding: 4px 2px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}
.message-body .md-math-block .katex-display {
  margin: 0;
}
.message-body .md-math-fallback {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}

/* <kbd> keyboard keys (render2). */
.message-body .md-kbd {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-bottom-width: 2px;
  border-radius: var(--ds-radius-xs, 6px);
  background: var(--cg-hover-soft, var(--surface-2));
  color: var(--cg-text, var(--text));
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
  line-height: 1.4;
  white-space: nowrap;
}

/* Inline emphasis (render2b): explicit so a cascaded font-style/text-decoration reset can't strip
   *italic* / ~~strikethrough~~. Struck text is de-emphasized (muted) like GitHub/Notion. */
.message-body em {
  font-style: italic;
}
.message-body del {
  text-decoration: line-through;
  color: var(--cg-text-soft, var(--muted));
}

/* Thematic break (render2b2): a quiet full-width hairline for "---" section dividers — no default
   inset border, tokenized so light/dark both read as a subtle rule. */
.message-body .md-hr {
  height: 0;
  margin: var(--ds-space-6) 0;
  border: 0;
  border-top: 1px solid var(--cg-menu-border, var(--line));
}

/* Mermaid diagrams (doc 169). Before hydration (or on load/parse failure) the source <pre> shows as
   the fallback; once rendered, the SVG shows and a toggle flips between diagram and source. */
.message-body .mermaid-block {
  margin: 12px 0 14px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: 12px;
  overflow: hidden;
  background: var(--cg-surface, #fff);
}
.message-body .mermaid-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 8px 6px 14px;
  background: var(--cg-hover-soft, var(--surface-2));
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}
.message-body .mermaid-label {
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  color: var(--cg-text-soft, var(--muted));
}
.message-body .mermaid-toggle {
  padding: 3px 9px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.message-body .mermaid-toggle:hover {
  background: var(--cg-sidebar-active-bg);
  color: var(--cg-text, var(--text));
}
.message-body .mermaid-toggle:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent, #2f6bff));
  outline-offset: 1px;
}
/* Render area: hidden until the SVG is in; scrolls horizontally if the diagram is wide. */
.message-body .mermaid-render {
  display: none;
  padding: 16px;
  overflow-x: auto;
  text-align: center;
}
.message-body .mermaid-render svg {
  max-width: 100%;
  height: auto;
}
.message-body .mermaid-block.is-rendered .mermaid-render {
  display: block;
}
.message-body .mermaid-block.is-rendered.show-source .mermaid-render {
  display: none;
}
/* Source is the default/fallback view (pending or error) and the "소스 보기" view. It shows the raw
   mermaid code, so it uses the dark code-card palette (readable light-on-dark) rather than the light
   diagram surface — this also overrides any global <pre> background that would clash. */
.message-body .mermaid-source {
  margin: 0;
  padding: 12px 14px;
  overflow-x: auto;
  background: #0d1017;
  color: #dfe3ea;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--ds-text-caption-13);
  line-height: 1.55;
  white-space: pre;
}
.message-body .mermaid-source code {
  color: inherit;
  background: none;
}
.message-body .mermaid-block.is-rendered .mermaid-source {
  display: none;
}
.message-body .mermaid-block.is-rendered.show-source .mermaid-source {
  display: block;
}
@media (prefers-reduced-motion: reduce) {
  .message-body .mermaid-toggle {
    transition: none;
  }
}

/* GFM task list (render2): non-interactive checkbox glyph + label. Read-only — the model states
   status. The <li> drops its marker and aligns the box with the first text line. */
.message-body .md-task-item {
  list-style: none;
  margin-left: -22px;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.message-body .md-task-box {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  margin-top: 3px;
  border: 1.5px solid var(--cg-menu-border, var(--line));
  border-radius: 5px;
  background: var(--cg-surface, #fff);
  color: #fff;
}
.message-body .md-task-box[data-checked="true"] {
  border-color: var(--accent, #2f6bff);
  background: var(--accent, #2f6bff);
}
.message-body .md-task-box svg,
.message-body .md-task-box .wds-inline-icon {
  width: 12px;
  height: 12px;
}
.message-body .md-task-label {
  flex: 1 1 auto;
}

.md-quote {
  /* ★v10 — 표와 같은 이유로 산문 리듬(20)에 맞춘다. 16 이면 이 블록 앞뒤에서만
     간격이 좁아져 문서의 세로 리듬이 끊긴다. */
  margin: var(--ds-space-5) 0;
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--cg-menu-border, var(--line));
  color: var(--cg-text-soft, var(--muted));
}
.md-callout {
  display: grid;
  gap: 6px;
  margin: var(--ds-space-4) 0;
  padding: 10px 12px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: 12px;
  background: var(--cg-hover-soft, var(--surface-2));
}
.md-callout-head {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: var(--cg-text-label-size, 14px);
  font-weight: 600;
}
.md-callout[data-callout="warning"] .md-callout-head {
  color: var(--wizon-ai-danger-text, var(--danger));
}
.message-body .md-callout-head .wds-inline-icon,
.md-callout-head .wds-inline-icon {
  width: 16px;
  height: 16px;
  flex: none;
}
.md-callout-body > p:last-child,
.md-callout-body > .md-list:last-child {
  margin-bottom: 0;
}
.md-heading {
  display: flex;
  align-items: center;
  gap: 7px;
}
.message-body .md-heading .wds-inline-icon,
.md-heading .wds-inline-icon {
  width: 18px;
  height: 18px;
  flex: none;
  color: var(--cg-text-soft, var(--muted));
}

/* in-place thinking (doc 139 제안 A): 답변 슬롯에 그대로, 최종 답변과 동일 타이포.
   회색↔잉크 모노크롬 shimmer(제품 토큰 --cg-*) + dots. 회전 오브/정적 진행칩 폐기. */
.thinking-inline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: inherit;
}

.thinking-shimmer {
  background: linear-gradient(
    90deg,
    var(--cg-muted, var(--muted)) 35%,
    var(--cg-text, var(--ink)) 50%,
    var(--cg-muted, var(--muted)) 65%
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: thinking-shimmer 1.7s linear infinite;
}

@keyframes thinking-shimmer {
  from {
    background-position: 210% 0;
  }
  to {
    background-position: -210% 0;
  }
}

.thinking-dots {
  display: inline-flex;
  gap: 4px;
}

.thinking-dots i {
  width: 5px;
  height: 5px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-text, var(--ink));
  animation: thinking-dot 1.1s ease-in-out infinite;
}

.thinking-dots i:nth-child(2) {
  animation-delay: 0.15s;
}

.thinking-dots i:nth-child(3) {
  animation-delay: 0.3s;
}

@keyframes thinking-dot {
  0%,
  80%,
  100% {
    opacity: 0.3;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-3px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .thinking-shimmer {
    animation: none;
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--cg-muted, var(--muted));
  }

  .thinking-dots i {
    animation: none;
  }
}

/* Live progressive status shown until the first answer token (doc 165). Reuses .thinking-shimmer
   for the sweep; the label crossfades (out-up / in-up) when the pipeline stage changes. */
.stream-status {
  display: flex;
  align-items: center;
  min-height: 1.6em;
  font-size: var(--ds-text-body-15);
}
.stream-status-label {
  display: inline-block;
  font-weight: 500;
}
.status-swap-exit {
  animation: status-swap-out 200ms ease-out forwards;
}
.status-swap-enter {
  animation: status-swap-in 200ms ease-out forwards;
}
@keyframes status-swap-out {
  to {
    opacity: 0;
    transform: translateY(-4px);
  }
}
@keyframes status-swap-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .status-swap-exit,
  .status-swap-enter {
    animation-duration: 1ms;
  }
}

/* ---- 스트리밍 카드 스켈레톤 (T3, 스켈레톤 선행 트랙) ------------------------------------
   오케스트레이션 홀드가 카드 타입으로 확정되는 즉시 상태 라인 대신 마운트되고(app.js
   resolveOrchHold), finalize 패치가 실제 카드로 교체한다. 타입별 min-height는 실제 위젯의
   대략적 높이를 예약해 교체 시 레이아웃 점프(CLS)를 줄인다. 셸은 위젯과 같은 라운드
   (--ds-radius-lg)의 중립 표면, 내부 바/블록은 thinking-shimmer 키프레임을 재사용한
   저채도 스윕 — 잉크 모노톤 원칙(카드 본색은 완성본만 쓴다). */
.stream-card-skeleton {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 4px;
  padding: 20px 22px;
  border-radius: var(--ds-radius-lg);
  border: 1px solid var(--line);
  background: var(--cg-surface);
  animation: status-swap-in 200ms ease-out both;
}
.stream-card-skeleton .sk-head {
  display: flex;
  align-items: center;
  min-height: 1.6em;
  font-size: var(--cg-text-label-size);
}
.stream-card-skeleton .sk-line,
.stream-card-skeleton .sk-block,
.stream-card-skeleton .sk-dot,
.stream-card-skeleton .sk-figure,
.stream-card-skeleton .sk-seg-pill {
  display: block;
  border-radius: var(--ds-radius-xs);
  background: linear-gradient(90deg, var(--cg-hover-soft) 35%, var(--line) 50%, var(--cg-hover-soft) 65%);
  background-size: 220% 100%;
  animation: thinking-shimmer 1.7s linear infinite;
}
.stream-card-skeleton .sk-line {
  height: 12px;
}
.stream-card-skeleton .sk-block {
  width: 100%;
}
/* v3: 실위젯 내부 레이아웃 미러 — 헤더(제목/부제 + 우측 큰 수치), 본문 패널(시간대 셀 스트립 /
   차트+기간 세그먼트 / 리드+행). 데이터가 앉을 자리만 shimmer, 프레임은 정적. */
.stream-card-skeleton .sk-widget-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
.stream-card-skeleton .sk-ident {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
  min-width: 0;
}
.stream-card-skeleton .sk-title {
  height: 18px;
  width: 34%;
}
.stream-card-skeleton .sk-subtitle {
  width: 52%;
}
.stream-card-skeleton .sk-figure {
  width: 112px;
  height: 46px;
  border-radius: var(--ds-radius-sm);
  flex: none;
}
.stream-card-skeleton .sk-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--ds-radius-sm);
  background: rgba(255, 255, 255, 0.08);
}
.stream-card-skeleton .sk-hourly {
  flex-direction: row;
  justify-content: space-between;
  gap: 10px;
}
.stream-card-skeleton .sk-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  flex: 1;
}
.stream-card-skeleton .sk-cell-label {
  width: 26px;
  height: 10px;
}
.stream-card-skeleton .sk-dot {
  width: 26px;
  height: 26px;
  border-radius: var(--ds-radius-pill);
}
.stream-card-skeleton .sk-cell-value {
  width: 20px;
}
.stream-card-skeleton .sk-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.stream-card-skeleton .sk-row-label {
  width: 22%;
}
.stream-card-skeleton .sk-row-value {
  width: 42%;
}
.stream-card-skeleton .sk-seg {
  display: flex;
  gap: 8px;
}
.stream-card-skeleton .sk-seg-pill {
  flex: 1;
  height: 34px;
  border-radius: var(--ds-radius-sm);
}
.stream-card-skeleton .sk-news {
  background: var(--cg-hover-soft);
}
.stream-card-skeleton .sk-news .sk-row {
  justify-content: flex-start;
}
.stream-card-skeleton .sk-thumb {
  width: 44px;
  height: 44px;
  border-radius: var(--ds-radius-sm);
  flex: none;
}
.stream-card-skeleton .sk-news .sk-row-value {
  width: 64%;
}
/* P2 (docs/53 Phase 2): 여행·비주얼 스켈레톤 — 두 카드 모두 라이트 표면(기본 셸 그대로),
   여행=헤더+히어로+day 칩+일정 행, 비주얼=이미지 모자이크 3타일+텍스트 행 미러. */
.stream-card-skeleton[data-card-skeleton="travel"] {
  min-height: 360px;
}
.stream-card-skeleton .sk-stops {
  background: var(--cg-hover-soft);
}
.stream-card-skeleton .sk-stops .sk-row {
  justify-content: flex-start;
}
.stream-card-skeleton[data-card-skeleton="visual"] {
  min-height: 300px;
}
.stream-card-skeleton .sk-mosaic {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 8px;
}
.stream-card-skeleton .sk-tile {
  display: block;
  height: 150px;
  border-radius: var(--ds-radius-xs);
  background: linear-gradient(90deg, var(--cg-hover-soft) 35%, var(--line) 50%, var(--cg-hover-soft) 65%);
  background-size: 220% 100%;
  animation: thinking-shimmer 1.7s linear infinite;
}
/* 타입별 셸 = 실제 위젯의 배경 아이덴티티(사용자 결정 2026-07-22): 스켈레톤이 "그 카드가
   오는 중"임을 배경만으로 예고하고, finalize 교체 때 배경이 연속되어 스냅감이 사라진다.
   날씨=딥블루(#0d285e, .weather-widget), 금융=잉크 그라디언트(.finance-widget 인라인 surface),
   뉴스=라이트 표면(.news-feed). 다크 셸의 바/라벨은 화이트 계열 스윕으로 뒤집는다. */
.stream-card-skeleton[data-card-skeleton="finance"] {
  min-height: 300px;
  background: #101216; /* 실위젯 잉크 그라디언트의 중간값 — 래칫 예산상 플랫 단색 */
}
.stream-card-skeleton .sk-chart {
  height: 160px;
}
.stream-card-skeleton[data-card-skeleton="weather"] {
  min-height: 340px;
  background: #0d285e;
}
/* 주간 씬: 실위젯의 낮 하늘 그라디언트에 맞춘 밝은 블루 (라이브 실측 대비) */
.stream-card-skeleton[data-card-skeleton="weather"][data-sky="day"] {
  background: #4f97e0;
}
/* 다크 셸 공용 보더 — 래칫 예산상 rgba 1회로 통합(개별 선언 2회였던 것을 축약) */
.stream-card-skeleton[data-card-skeleton="weather"],
.stream-card-skeleton[data-card-skeleton="finance"] {
  border-color: rgba(255, 255, 255, 0.09);
}
/* 뉴스 스켈레톤 — renderNewsFeed 의 6구획(헤더/레일/히어로/2단/카드그리드/푸터)을 그대로
   미러링한다(2026-08-20, newsFeedSkeletonHtml). 열 채움 셀은 전부 <i> 태그라 아래 태그
   선택자 하나로 채움+스윕을 준다 — 감싸개(div/span)는 shimmer를 받지 않는다.
   ★스윕은 기존 thinking-shimmer(background-position 애니메이션)와 톤·타이밍은 맞추되
   구현은 transform 전용 오버레이로 새로 짠다(웹 성능 규칙: 모션은 transform/opacity만).
   기존 thinking-shimmer 자체는 범위 밖이라 손대지 않는다. */
.stream-card-skeleton[data-card-skeleton="news"] {
  min-height: 900px;
}
.stream-card-skeleton .sk-news-body {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.stream-card-skeleton .sk-news-body > * {
  animation: status-swap-in 220ms ease-out both;
}
.stream-card-skeleton .sk-news-body > *:nth-child(1) { animation-delay: 0ms; }
.stream-card-skeleton .sk-news-body > *:nth-child(2) { animation-delay: 90ms; }
.stream-card-skeleton .sk-news-body > *:nth-child(3) { animation-delay: 180ms; }
.stream-card-skeleton .sk-news-body > *:nth-child(4) { animation-delay: 270ms; }
.stream-card-skeleton .sk-news-body > *:nth-child(5) { animation-delay: 360ms; }
.stream-card-skeleton .sk-news-body > *:nth-child(6) { animation-delay: 450ms; }
.stream-card-skeleton .sk-news-body i {
  position: relative;
  overflow: hidden;
  display: block;
  border-radius: var(--ds-radius-xs);
  background: var(--cg-hover-soft);
}
.stream-card-skeleton .sk-news-body i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--line) 45%, transparent 90%);
  transform: translateX(-120%);
  animation: sk-news-sweep 1.7s linear infinite;
}
@keyframes sk-news-sweep {
  to {
    transform: translateX(120%);
  }
}
.stream-card-skeleton .sk-news-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.stream-card-skeleton .sk-news-title {
  width: 40%;
  height: 26px;
}
.stream-card-skeleton .sk-news-chips {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
.stream-card-skeleton .sk-news-chip {
  width: 52px;
  height: 20px;
  border-radius: var(--ds-radius-xs);
}
.stream-card-skeleton .sk-news-count {
  width: 26px;
  height: 14px;
}
.stream-card-skeleton .sk-news-rail {
  display: flex;
  gap: 8px;
  overflow: hidden;
}
.stream-card-skeleton .sk-news-tab {
  flex: none;
  width: 92px;
  height: 44px;
  border-radius: var(--ds-radius-pill);
}
.stream-card-skeleton .sk-news-tab:nth-child(2) { width: 72px; }
.stream-card-skeleton .sk-news-tab:nth-child(3) { width: 108px; }
.stream-card-skeleton .sk-news-tab:nth-child(4) { width: 84px; }
.stream-card-skeleton .sk-news-tab:nth-child(5) { width: 96px; }
.stream-card-skeleton .sk-news-tab:nth-child(6) { width: 78px; }
.stream-card-skeleton .sk-news-hero {
  position: relative;
  aspect-ratio: 744 / 452;
  border-radius: var(--ds-radius-md);
  overflow: hidden;
  background: var(--cg-hover-soft);
}
.stream-card-skeleton .sk-news-hero-band {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 18px;
}
.stream-card-skeleton .sk-news-hero-top {
  display: flex;
  align-items: center;
  gap: 10px;
}
.stream-card-skeleton .sk-news-kicker {
  width: 64px;
  height: 19px;
  border-radius: var(--ds-radius-pill);
}
.stream-card-skeleton .sk-news-byline {
  width: 100px;
  height: 20px;
}
.stream-card-skeleton .sk-news-hero-title {
  height: 24px;
}
.stream-card-skeleton .sk-news-hero-title:nth-of-type(1) { width: 88%; }
.stream-card-skeleton .sk-news-hero-title:nth-of-type(2) { width: 58%; }
.stream-card-skeleton .sk-news-hero-excerpt {
  height: 19px;
}
/* i 형제 셈은 클래스가 아니라 태그 기준이라, 앞선 두 i.sk-news-hero-title 뒤이므로
   3/4번째가 이 두 줄이다 (1/2번째는 제목이 차지한다). */
.stream-card-skeleton .sk-news-hero-excerpt:nth-of-type(3) { width: 96%; }
.stream-card-skeleton .sk-news-hero-excerpt:nth-of-type(4) { width: 52%; }
.stream-card-skeleton .sk-news-second {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.stream-card-skeleton .sk-news-second-cell {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto;
  column-gap: 12px;
  row-gap: 6px;
}
.stream-card-skeleton .sk-news-second-title {
  grid-column: 1;
  height: 20px;
}
.stream-card-skeleton .sk-news-second-title:nth-of-type(2) { width: 70%; }
.stream-card-skeleton .sk-news-second-excerpt {
  grid-column: 1;
  height: 19px;
  width: 90%;
}
.stream-card-skeleton .sk-news-second-shot {
  grid-column: 2;
  grid-row: 1 / span 2;
  width: 64px;
  height: 64px;
  flex: none;
}
/* 실측(2026-08-20, 375px): .news-second-foot(출처+시각+북마크 버튼 행)이 34px — 스켈레톤이
   이 행을 아예 안 그려서 2단 칸 하나당 실물보다 짧게 예약되고 있었다. */
.stream-card-skeleton .sk-news-second-foot {
  grid-column: 1 / -1;
  width: 55%;
  height: 32px;
}
.stream-card-skeleton .sk-news-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.stream-card-skeleton .sk-news-section-title {
  width: 96px;
  height: 22px;
}
.stream-card-skeleton .sk-news-arrows {
  display: flex;
  gap: 6px;
}
.stream-card-skeleton .sk-news-arrow {
  width: 28px;
  height: 28px;
  border-radius: var(--ds-radius-sm);
}
.stream-card-skeleton .sk-news-cards {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(2, minmax(0, auto));
  grid-auto-columns: calc((100% - 32px) / 3);
  gap: 16px;
  overflow: hidden;
}
/* 정본 폭 분기점 래칫(520/521/900/901)의 대상이 아니다 — 폭 기반 앳룰이 아니라 컨테이너
   기반이고, 값도 실제 .news-cards 컨테이너 쿼리(styles.css)와 같은 620이다: 사이드 패널이
   열려 피드 자체 폭이 줄어드는 경우까지 잡기 위해 뷰포트가 아니라 이 요소 자신의 인라인
   크기를 쓴다. */
@container (max-width: 620px) {
  .stream-card-skeleton .sk-news-cards {
    grid-auto-columns: calc((100% - 16px) / 2);
  }
}
/* 실물(styles.css)도 이 폭에서 한 번 더 접는다 — 카드 1열, 2단 1열, 히어로 4:3(744/452보다
   같은 폭에 더 큰 키). 스켈레톤이 이 분기점을 안 따라가면 375px에서 정확히 CLS가 남는다
   (2026-08-20 실측: 380px 미포함 상태에서 실물 히어로/2단이 예약보다 커짐). */
@container (max-width: 380px) {
  .stream-card-skeleton .sk-news-hero {
    aspect-ratio: 4 / 3;
  }
  .stream-card-skeleton .sk-news-second {
    grid-template-columns: 1fr;
  }
  .stream-card-skeleton .sk-news-second-cell {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .stream-card-skeleton .sk-news-cards {
    grid-auto-columns: 100%;
    gap: 18px;
  }
}
.stream-card-skeleton .sk-news-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.stream-card-skeleton .sk-news-card-shot {
  width: 100%;
  aspect-ratio: 16 / 10;
  border-radius: var(--ds-radius-sm);
}
.stream-card-skeleton .sk-news-card-title {
  height: 20px;
}
/* i 형제 셈은 태그 기준이라 sk-news-card-shot(1번째 i)이 먼저다: 제목 두 줄은 2·3번째,
   요약 두 줄은 4·5번째. */
.stream-card-skeleton .sk-news-card-title:nth-of-type(3) { width: 65%; }
.stream-card-skeleton .sk-news-card-excerpt {
  height: 19px;
}
.stream-card-skeleton .sk-news-card-excerpt:nth-of-type(4) { width: 92%; }
.stream-card-skeleton .sk-news-card-excerpt:nth-of-type(5) { width: 55%; }
/* 실측(2026-08-20, 375px): .news-card-foot(출처+시각+북마크 버튼 행)이 36px — 12px 텍스트
   한 줄로만 예약했더니 카드마다 실물보다 24px씩 짧아, 카드가 5장 이상일 때 누적 오차가
   전체 스켈레톤 높이 격차의 가장 큰 몫이었다. */
.stream-card-skeleton .sk-news-card-byline {
  height: 36px;
  width: 50%;
}
.stream-card-skeleton .sk-news-foot {
  display: flex;
  align-items: center;
  gap: 12px;
}
.stream-card-skeleton .sk-news-source-chip {
  width: 88px;
  height: 32px;
  border-radius: var(--ds-radius-pill);
}
.stream-card-skeleton .sk-news-subscribe {
  width: 96px;
  height: 26px;
  border-radius: var(--ds-radius-pill);
  margin-inline-start: auto;
}
.stream-card-skeleton .sk-lead {
  height: 150px;
}
.stream-card-skeleton[data-card-skeleton="weather"] .sk-line,
.stream-card-skeleton[data-card-skeleton="weather"] .sk-block,
.stream-card-skeleton[data-card-skeleton="weather"] .sk-dot,
.stream-card-skeleton[data-card-skeleton="weather"] .sk-figure,
.stream-card-skeleton[data-card-skeleton="finance"] .sk-line,
.stream-card-skeleton[data-card-skeleton="finance"] .sk-block,
.stream-card-skeleton[data-card-skeleton="finance"] .sk-figure,
.stream-card-skeleton[data-card-skeleton="finance"] .sk-seg-pill {
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.1) 35%,
    rgba(255, 255, 255, 0.22) 50%,
    rgba(255, 255, 255, 0.1) 65%
  );
  background-size: 220% 100%;
}
/* .thinking-shimmer의 텍스트 그라디언트는 테마 잉크 기반이라 다크 셸에서 안 보인다 — 화이트 스윕으로
   재정의. background 축약형은 background-clip까지 리셋하므로 텍스트 클립을 반드시 재선언한다
   (빠뜨리면 라벨이 글자 대신 회색 블록으로 칠해진다 — 하니스 실측). */
.stream-card-skeleton[data-card-skeleton="weather"] .sk-label,
.stream-card-skeleton[data-card-skeleton="finance"] .sk-label {
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.55) 35%,
    #ffffff 50%,
    rgba(255, 255, 255, 0.55) 65%
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@media (prefers-reduced-motion: reduce) {
  .stream-card-skeleton {
    animation-duration: 1ms;
  }
  .stream-card-skeleton .sk-line,
  .stream-card-skeleton .sk-block,
  .stream-card-skeleton .sk-dot,
  .stream-card-skeleton .sk-figure,
  .stream-card-skeleton .sk-seg-pill,
  .stream-card-skeleton .sk-tile {
    animation: none;
    background: var(--cg-hover-soft);
  }
  .stream-card-skeleton .sk-news-body > * {
    animation: none;
  }
  .stream-card-skeleton .sk-news-body i::after {
    animation: none;
    background: none;
  }
}

/* Step 2a: 완성 응답을 답변 슬롯에서 단어 단위 blur-in으로 재생한다.
   라이브 토큰 스트리밍이 아니라 이미 도착한 응답의 in-place 등장 연출이며,
   실제 SSE 스트리밍은 별도 백엔드 트랙(Step 2b)에서 소스만 교체한다.
   긴 답변(> REVEAL_MAX_WORDS)은 동시 blur 애니메이션 폭주를 피해 블록 페이드. */
.reveal-word {
  display: inline-block;
  animation: reveal-word-in 0.42s var(--cg-ease-enter, cubic-bezier(0.19, 1, 0.22, 1)) both;
  will-change: filter, transform, opacity;
}

@keyframes reveal-word-in {
  from {
    filter: blur(6px);
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    filter: blur(0);
    opacity: 1;
    transform: none;
  }
}

.message-body.is-revealing-block {
  animation: reveal-word-in 0.5s var(--cg-ease-enter, cubic-bezier(0.19, 1, 0.22, 1)) both;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-word,
  .message-body.is-revealing-block {
    animation: none;
  }
}

.composer {
  grid-template-columns: minmax(0, 1fr) 96px;
  background: linear-gradient(180deg, transparent, var(--bg) 35%);
}

.composer textarea {
  border-radius: var(--radius-xl);
  background: var(--ds-color-surface);
  box-shadow: var(--shadow);
}

.primary-button,
.secondary-button {
  border-radius: var(--radius-md);
}

.primary-button {
  border-color: var(--accent);
  background: var(--ds-button-primary-bg);
}

.context-pane {
  background: var(--ds-color-surface);
  border-left: 1px solid var(--line);
}

.tabs {
  display: flex;
  overflow-x: auto;
  grid-template-columns: none;
  gap: 6px;
  padding: 13px;
}

.tab-button {
  flex: 0 0 auto;
  min-height: 36px;
  border-radius: var(--ds-radius-pill, 999px);
  padding: 0 12px;
}

.tab-button.active {
  border-color: var(--cg-text);
  background: var(--accent-soft);
  color: var(--accent);
}

.tab-content {
  gap: 16px;
  padding: 18px;
}

.panel-block h2 {
  font-size: 17px;
}

.tool-status-list,
.workflow-timeline,
.knowledge-grid {
  display: grid;
  gap: 10px;
}

.tool-status-card,
.workflow-step {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.tool-status-card small,
.workflow-step small {
  display: block;
  margin-top: 3px;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
}

.status-dot,
.workflow-step > span {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}

.workflow-step.active {
  border-color: var(--cg-text);
  background: linear-gradient(180deg, var(--surface), var(--accent-soft));
}

.source-list.compact {
  padding: 0;
}

[data-theme="dark"] .sidebar .section-label,
[data-theme="dark"] .brand-row span {
  color: #94a3b8;
}

[data-theme="dark"] .upload-form .secondary-button,
[data-theme="dark"] .prompt-row button,
[data-theme="dark"] .feedback-row button,
[data-theme="dark"] .document-actions button {
  background: var(--surface);
  color: var(--ink);
}

[data-theme="dark"] .source-snippet {
  color: var(--ds-color-ink-soft);
}

@media (max-width: 1200px) {
  .workbench {
    grid-template-columns: minmax(0, 1fr);
  }

  .context-pane {
    min-height: 0;
    max-height: min(520px, 48vh);
    border-top: 1px solid var(--line);
    border-left: 0;
  }
}

@media (max-width: 900px) {
  .app-shell {
    grid-template-columns: 1fr;
  }

  .sidebar {
    min-height: auto;
    border-right: 0;
  }

  .nav-section {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .sidebar-section.grow {
    max-height: min(260px, 38vh);
  }

  .topbar {
    align-items: flex-start;
    flex-direction: column;
    padding: 16px;
  }

  .status-stack {
    justify-content: flex-start;
  }

  .message-list {
    padding: 22px 16px;
  }

  .message {
    grid-template-columns: 34px minmax(0, 1fr);
  }

  .message-label {
    width: 32px;
    height: 32px;
  }

  .prompt-row {
    grid-template-columns: 1fr;
  }

  .app-command-grid {
    grid-template-columns: 1fr;
  }

  .composer {
    grid-template-columns: 1fr;
    padding: 12px 16px 16px;
  }

  .upload-form {
    grid-template-columns: 1fr;
  }
}

/* AI Native reference adaptation: light-first product workspace */
.app-shell {
  grid-template-columns: 292px minmax(0, 1fr);
}

.sidebar {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.94)),
    var(--surface);
  color: var(--ink);
  border-right: 1px solid var(--line);
  box-shadow: 1px 0 0 rgba(255, 255, 255, 0.7);
}

.brand-row strong,
.nav-item span,
.recent-item span {
  color: var(--ink);
}

.brand-row span,
.nav-item small,
.recent-item small,
.sidebar .section-label {
  color: var(--muted);
}
.theme-toggle {
  border-color: var(--line);
  background: var(--surface);
  color: var(--ink-soft);
  box-shadow: var(--ds-shadow-xs);
}

.theme-toggle:hover,
.nav-item:hover,
.nav-item.active {
  background: linear-gradient(180deg, #ffffff, #f3f6ff);
}

.nav-item {
  color: var(--ink);
}

.recent-item {
  color: var(--ink);
}

.recent-item:hover {
  background: #f8faff;
}

.sidebar select {
  background: #ffffff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
}

.sidebar .secondary-button {
  border-color: var(--line);
  background: #111827;
  color: #ffffff;
}
[data-theme="dark"] .brand-row strong,
[data-theme="dark"] .nav-item span,
[data-theme="dark"] .recent-item span {
  color: #f8fafc;
}

[data-theme="dark"] .theme-toggle {
  border-color: rgba(226, 232, 240, 0.16);
  background: rgba(255, 255, 255, 0.08);
  color: #f8fafc;
}

[data-theme="dark"] .theme-toggle:hover,
[data-theme="dark"] .nav-item:hover,
[data-theme="dark"] .nav-item.active {
  border-color: rgba(34, 211, 238, 0.38);
  background: rgba(255, 255, 255, 0.1);
}

[data-theme="dark"] .recent-item:hover {
  border-color: rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.07);
}

[data-theme="dark"] .sidebar .secondary-button {
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.08);
  color: #ffffff;
}

.workspace-hero {
  position: sticky;
  top: 0;
  z-index: 20;
}

.context-pane {
  background: rgba(255, 255, 255, 0.84);
  backdrop-filter: blur(18px);
}

[data-theme="dark"] .context-pane {
  background: rgba(24, 24, 27, 0.86);
}

.context-panel-head {
  padding: 4px 2px 2px;
}

.context-panel-head h2 {
  margin-top: 3px;
  font-size: 19px;
}

/* Calm Portal v1: ChatGPT/Claude-style product surface */
.app-shell {
  grid-template-columns: 264px minmax(0, 1fr);
}

.sidebar {
  gap: 14px;
  padding: 16px;
  background: rgba(255, 255, 255, 0.96);
  color: var(--ink);
}

.brand-row {
  min-height: 42px;
}
.new-chat-button {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: #111827;
  color: #ffffff;
  font-weight: 600;
}

.new-chat-button:hover {
  background: #020617;
}

.nav-section {
  gap: 5px;
}

.nav-item {
  min-height: 38px;
  padding: 0 12px;
  border-radius: var(--ds-radius-sm, 10px);
}

.nav-item span {
  font-size: var(--ds-text-body-14);
}

.nav-item small {
  display: none;
}

.recent-list {
  gap: 3px;
}

.recent-item {
  min-height: 38px;
  padding: 8px 10px;
}

.theme-toggle {
  min-height: 34px;
}

.workspace-hero {
  min-height: 76px;
  padding: 16px 28px;
  background: rgba(255, 255, 255, 0.86);
}

.topbar h1 {
  font-size: var(--ds-text-title-18);
}

.hero-copy {
  font-size: var(--ds-text-caption-13);
}

.status-stack {
  gap: 6px;
}

.status-pill {
  min-height: 30px;
  font-size: var(--ds-text-micro-11);
}

.workbench {
  grid-template-columns: minmax(0, 1fr) minmax(360px, 420px);
}

html[data-portal-tab="home"] .workbench {
  grid-template-columns: minmax(0, 1fr);
}

html[data-portal-tab="home"] .context-pane {
  display: none;
}

.chat-pane {
  background: #ffffff;
}

.message-list {
  padding: 36px clamp(22px, 7vw, 96px);
}

.calm-chat-home {
  width: min(760px, 100%);
  max-width: none;
  justify-items: center;
  align-self: center;
  margin: auto;
  gap: 18px;
  padding: 24px 8px 18px;
  text-align: center;
}

.home-project-pill {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  max-width: min(100%, 620px);
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: rgba(255, 255, 255, 0.78);
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.calm-chat-home h2 {
  max-width: 720px;
  margin: 0;
  font-size: clamp(30px, 4vw, 42px);
  font-weight: 600;
  line-height: 1.18;
  letter-spacing: 0;
  word-break: keep-all;
}

.calm-chat-home p {
  max-width: 620px;
  margin: 0;
  color: var(--muted);
  font-size: var(--ds-text-body-15);
  line-height: 1.7;
  word-break: keep-all;
}

.quick-start-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  width: min(640px, 100%);
  margin-top: 8px;
}

.quick-start-grid button {
  min-height: 46px;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-md, 14px);
  background: #ffffff;
  color: var(--ink);
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  text-align: left;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: border-color var(--motion), box-shadow var(--motion), transform var(--motion);
}

.quick-start-grid button:hover {
  box-shadow: 0 10px 24px rgba(15, 23, 42, 0.08);
  transform: translateY(-1px);
}

.composer {
  width: min(760px, calc(100% - 44px));
  margin: 0 auto;
  padding: 0 0 28px;
  background: transparent;
}

.composer textarea {
  min-height: 58px;
  border-radius: var(--ds-radius-lg, 18px);
  background: #ffffff;
}

.composer .primary-button {
  min-height: 58px;
  border-radius: var(--ds-radius-lg, 18px);
  background: #111827;
}

.context-pane {
  background: rgba(255, 255, 255, 0.92);
}

.right-panel-empty {
  display: none;
}

[data-theme="dark"] .sidebar {
  background: rgba(9, 9, 11, 0.96);
}

[data-theme="dark"] .new-chat-button {
  background: #f8fafc;
  color: #09090b;
}

[data-theme="dark"] .chat-pane {
  background:
    radial-gradient(circle at 50% 12%, rgba(129, 140, 248, 0.11), transparent 32%),
    var(--bg);
}

[data-theme="dark"] .home-project-pill,
[data-theme="dark"] .quick-start-grid button,
[data-theme="dark"] .composer textarea {
  background: rgba(24, 24, 27, 0.88);
}

@media (max-width: 900px) {
  .app-shell {
    grid-template-columns: 1fr;
  }

  .sidebar {
    min-height: auto;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }

  .nav-section {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .nav-item {
    justify-content: start;
    text-align: left;
  }

  .workspace-hero {
    display: none;
  }

  .quick-start-grid {
    grid-template-columns: 1fr;
  }

  .composer {
    width: calc(100% - 28px);
    grid-template-columns: 1fr;
  }
}

.mini-card,
.app-card,
.app-detail-panel,
.app-workflow-panel,
.app-input-fields,
.source-card,
.tool-status-card,
.workflow-step {
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.9);
}

[data-theme="dark"] .mini-card,
[data-theme="dark"] .app-card,
[data-theme="dark"] .app-detail-panel,
[data-theme="dark"] .app-workflow-panel,
[data-theme="dark"] .app-input-fields,
[data-theme="dark"] .source-card,
[data-theme="dark"] .tool-status-card,
[data-theme="dark"] .workflow-step {
  background: rgba(24, 24, 27, 0.92);
}

.document-actions button {
  border-radius: var(--ds-radius-pill, 999px);
}

.message-body {
  border-radius: var(--radius-xl);
}

.message-label {
  border-radius: var(--ds-radius-md, 14px);
}

@media (max-width: 900px) {
  .app-shell {
    grid-template-columns: 1fr;
  }
}

/* Artifact Canvas v1 */
html[data-portal-tab="outputs"] .workbench {
  grid-template-columns: minmax(420px, 0.95fr) minmax(520px, 0.78fr);
}

.artifact-studio {
  display: grid;
  grid-template-columns: minmax(220px, 0.72fr) minmax(320px, 1.08fr);
  align-items: start;
  gap: 14px;
}

.artifact-library,
.artifact-canvas-shell {
  display: grid;
  gap: 12px;
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  background: rgba(255, 255, 255, 0.88);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}

.artifact-library {
  padding: 14px;
  max-height: 70vh;
  overflow: auto;
}

.artifact-canvas-shell {
  padding: 16px;
  background: rgba(255, 255, 255, 0.92);
}

.empty-artifact-canvas {
  min-height: 220px;
  align-content: center;
}

.artifact-list-item {
  color: var(--ink);
  text-align: left;
}

.artifact-path-line {
  display: block;
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.artifact-list-item.selected-artifact {
  border-color: var(--cg-text);
  background: linear-gradient(180deg, var(--cg-surface), var(--cg-hover-soft));
  box-shadow: inset 3px 0 0 var(--accent);
}

.artifact-preview-button {
  width: 100%;
  color: var(--ink);
  text-align: left;
}

.artifact-canvas-toolbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.artifact-canvas-toolbar h3 {
  margin: 3px 0 0;
  font-size: var(--ds-text-title-20);
  line-height: 1.25;
  word-break: keep-all;
}

.artifact-canvas-toolbar p:not(.eyebrow) {
  max-width: 100%;
  margin: 6px 0 0;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.artifact-mode-switch {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--surface-2);
}

.artifact-mode-switch button {
  min-height: 30px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: transparent;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.artifact-mode-switch button.active {
  background: var(--surface);
  color: var(--accent);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
}

.artifact-meta-row,
.artifact-action-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.artifact-meta-row span {
  min-height: 28px;
  padding: 6px 9px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--surface);
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.artifact-action-row button {
  min-height: 34px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.artifact-action-row button:hover {
  border-color: var(--cg-menu-border);
  background: var(--accent-soft);
}

.artifact-action-row .primary-inline {
  border-color: transparent;
  background: #111827;
  color: #ffffff;
}

.artifact-canvas-body {
  min-width: 0;
}

.artifact-document-preview,
.artifact-editor {
  width: 100%;
  min-height: 420px;
  max-height: 58vh;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-xl);
  background: var(--surface);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

.artifact-document-preview {
  padding: 18px;
}

.artifact-document-preview p,

.artifact-document-preview h3,
.artifact-document-preview h4,
.artifact-document-preview h5 {
  margin: 18px 0 10px;
  color: var(--ink);
}

.artifact-editor {
  padding: 16px;
  color: var(--ink);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--ds-text-caption-13);
  line-height: 1.6;
  resize: vertical;
}

.artifact-version-rail {
  display: grid;
  gap: 10px;
  padding-top: 2px;
}

.artifact-version-rail > div:first-child {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.artifact-version-rail strong {
  font-size: var(--ds-text-caption-13);
}

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

.artifact-version-list button {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 2px 10px;
  align-items: center;
  min-height: 54px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  text-align: left;
}

.artifact-version-list button.active {
  border-color: var(--cg-text);
  background: var(--accent-soft);
}

.artifact-version-list button > span {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--surface-2);
  color: var(--accent);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}

.artifact-version-list small {
  color: var(--muted);
  font-size: var(--ds-text-micro-11);
}

[data-theme="dark"] .artifact-library,
[data-theme="dark"] .artifact-canvas-shell,
[data-theme="dark"] .artifact-document-preview,
[data-theme="dark"] .artifact-editor,
[data-theme="dark"] .artifact-list-item.selected-artifact {
  background: rgba(24, 24, 27, 0.9);
}

[data-theme="dark"] .artifact-action-row .primary-inline {
  background: #f8fafc;
  color: #09090b;
}

@media (max-width: 1200px) {
  html[data-portal-tab="outputs"] .workbench {
    grid-template-columns: 1fr;
  }

  .artifact-studio {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 900px) {
  .artifact-canvas-toolbar {
    display: grid;
  }

  .artifact-mode-switch {
    width: fit-content;
  }

  .artifact-document-preview,
  .artifact-editor {
    min-height: 320px;
  }
}

/* Premium Product Detail System v1 */
:root {
  --premium-surface: var(--ds-color-surface);
  --premium-surface-strong: var(--ds-color-surface-solid);
  --premium-border: var(--ds-color-line);
  --premium-shadow: var(--ds-shadow-xs);
}

/* 강조 컬러(accent) — 개인 설정. app.js가 문서 루트에 data-accent를 세우면
   선택·강조 테두리, 폼 accent-color, --accent-soft 배경, 그라디언트가 이 값을 쓴다
   (이전엔 --accent가 정의된 적 없어 fallback #2f6bff로 고정됐다). focus ring은 별도
   토큰 --cg-focus-ring을 쓰므로 대상이 아니다. 블랙/그레이는 다크 배경에서 그대로면
   테두리가 안 보이므로 라이트·다크를 따로 정의한다. */
:root[data-accent="ink"] {
  --accent: #1a1a1a;
  --accent-2: #3d3d3d;
  --accent-soft: rgba(17, 17, 17, 0.06);
}
:root[data-accent="gray"] {
  --accent: #6b7280;
  --accent-2: #9ca3af;
  --accent-soft: rgba(107, 114, 128, 0.12);
}
:root[data-accent="blue"] {
  --accent: #155eef;
  --accent-2: #4f83ff;
  --accent-soft: rgba(21, 94, 239, 0.10);
}
:root[data-theme="dark"][data-accent="ink"] {
  --accent: #d4d4d4;
  --accent-2: #a3a3a3;
  --accent-soft: rgba(255, 255, 255, 0.10);
}
:root[data-theme="dark"][data-accent="gray"] {
  --accent: #9ca3af;
  --accent-2: #6b7280;
  --accent-soft: rgba(156, 163, 175, 0.15);
}
:root[data-theme="dark"][data-accent="blue"] {
  --accent: #4f83ff;
  --accent-2: #155eef;
  --accent-soft: rgba(79, 131, 255, 0.15);
}

/* 외부 링크 경고(safetyExternalLinkWarning). app.js가 포털 밖으로 나가는 링크에만
   data-external을 달면, 링크 라벨 뒤에 작은 외부 이동 아이콘(↗)을 붙여 사용자가
   눌러서 나가기 전에 알아채게 한다 — passive 표시라 클릭을 막지 않는다. */
a[data-external="true"]::after {
  content: "↗";
  display: inline-block;
  margin-inline-start: 0.15em;
  font-size: 0.85em;
  line-height: 1;
  vertical-align: baseline;
  opacity: 0.7;
}

.premium-product-shell-v1 {
  /* 2026-08-01 셸 층 중복 제거. body 에 셸 클래스 6개가 index.html 에서 항상 함께 붙어
     있어(토글 없음), 같은 특이도로 같은 속성을 거는 선언은 마지막 것만 이긴다. 여기서
     지던 선언은 화면에 한 번도 닿은 적이 없어 지웠다 — 계산 스타일 무변화로 검증. */
  line-height: var(--ds-leading-reading);
}

[data-theme="dark"] .premium-product-shell-v1 {
  background:
    radial-gradient(circle at 52% 8%, rgba(129, 140, 248, 0.12), transparent 28%),
    linear-gradient(180deg, #09090b 0%, #111113 100%);
}

.premium-product-shell-v1 .app-shell {
  grid-template-columns: 268px minmax(0, 1fr);
}

.premium-product-shell-v1 .sidebar {
  padding: 18px 14px;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(22px);
}

.premium-product-shell-v1 .brand-row strong {
  font-size: var(--ds-text-title-18);
  font-weight: var(--ds-weight-semibold);
}

.premium-product-shell-v1 .section-label,
.premium-product-shell-v1 .eyebrow {
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
  letter-spacing: 0;
}

.premium-product-shell-v1 .nav-item {
  grid-template-columns: 28px minmax(0, 1fr);
  align-items: center;
  min-height: 40px;
  padding: 7px 10px;
  border-radius: 12px;
  /* --ds-motion-hover 는 정의가 유실돼 이 선언이 통째로 무효였다(2026-08-01).
     원문은 `a52b7b910` design-system/tokens/motion/motion.css:5 에서 복원 —
     ★`all`이 아니라 명시적 속성 목록이다. 옛 --ds-motion-standard 는 값이 같은
     --ds-motion-default 로 옮겼다. 토큰으로 되살리지 않은 이유: ds.primitive 의
     motion 그룹은 $type:transition 이라 속성 목록을 담을 수 없고, 이 파일 머리말이
     --ds-* 재선언을 금지한다. */
  transition:
    transform var(--ds-motion-default),
    border-color var(--ds-motion-default),
    box-shadow var(--ds-motion-default),
    background var(--ds-motion-default);
}

.premium-product-shell-v1 .nav-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--premium-border);
  border-radius: 8px;
  background: #ffffff;
  color: var(--accent);
  font-size: var(--ds-text-micro-11);
  font-weight: var(--ds-weight-semibold);
}

.premium-product-shell-v1 .nav-item.active {
  box-shadow: inset 3px 0 0 var(--accent);
}

.premium-product-shell-v1 .recent-item,
.premium-product-shell-v1 .new-chat-button,
.premium-product-shell-v1 .theme-toggle {
  transition:
    transform var(--ds-motion-default),
    border-color var(--ds-motion-default),
    box-shadow var(--ds-motion-default),
    background var(--ds-motion-default);
}

.workspace-identity {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
}

.workspace-cover {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 16px;
  color: #ffffff;
  font-weight: var(--ds-weight-bold);
}

.premium-product-shell-v1 .workspace-hero {
  min-height: 82px;
  background: rgba(255, 255, 255, 0.78);
  box-shadow: var(--ds-shadow-hairline);
}

.premium-product-shell-v1 .topbar h1 {
  font-size: var(--ds-text-title-20);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-title);
}

.state-indicator {
  position: relative;
  gap: 7px;
  font-weight: var(--ds-weight-semibold);
}

.state-indicator::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: var(--ds-radius-pill, 999px);
  background: currentColor;
  box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 14%, transparent);
}

.premium-product-shell-v1 .chat-pane {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(248, 250, 252, 0.98));
}

.premium-product-shell-v1 .calm-chat-home {
  animation: fade-in-up 420ms cubic-bezier(0.16, 1, 0.3, 1);
}

.premium-product-shell-v1 .calm-chat-home h2 {
  font-size: clamp(34px, 4.4vw, var(--ds-text-display-40));
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.premium-product-shell-v1 .calm-chat-home p,
.premium-product-shell-v1 .message-body p,
.premium-product-shell-v1 .artifact-document-preview p {
  font-size: var(--ds-text-body-15);
  line-height: var(--ds-leading-reading);
  font-weight: var(--ds-weight-regular);
}

.premium-card,
.premium-product-shell-v1 .mini-card,
.premium-product-shell-v1 .app-card,
.premium-product-shell-v1 .app-detail-panel,
.premium-product-shell-v1 .app-workflow-panel,
.premium-product-shell-v1 .app-input-fields,
.premium-product-shell-v1 .artifact-library,
.premium-product-shell-v1 .artifact-canvas-shell,
.premium-product-shell-v1 .evidence-card,
.premium-product-shell-v1 .source-card {
  border-color: var(--premium-border);
  background: var(--premium-surface-strong);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}

.soft-hover-lift,
.premium-product-shell-v1 .quick-start-grid button,
.premium-product-shell-v1 .mini-card,
.premium-product-shell-v1 .app-card,
.premium-product-shell-v1 .artifact-preview-card,
.premium-product-shell-v1 .artifact-action-row button {
  transition:
    transform var(--ds-motion-default),
    border-color var(--ds-motion-default),
    box-shadow var(--ds-motion-default),
    background var(--ds-motion-default);
}

.soft-hover-lift:hover,
.premium-product-shell-v1 .quick-start-grid button:hover,
.premium-product-shell-v1 .mini-card:hover,
.premium-product-shell-v1 .app-card:hover,
.premium-product-shell-v1 .artifact-preview-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--premium-shadow);
}

.result-highlight {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 4px;
}

.result-highlight span {
  min-height: 30px;
  padding: 6px 10px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill, 999px);
  background: rgba(255, 255, 255, 0.72);
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

.app-result-card.result-highlight {
  display: grid;
  justify-content: stretch;
}
.premium-product-shell-v1 .message {
  grid-template-columns: 38px minmax(0, 780px);
}

.premium-product-shell-v1 .message-body {
  padding: 16px 18px;
  border-color: var(--premium-border);
  border-radius: 20px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}

.streaming-cursor {
  display: inline-block;
  width: 7px;
  height: 1.12em;
  margin-left: 2px;
  border-radius: 2px;
  background: var(--cg-text, var(--ink));
  vertical-align: -2px;
  animation: streaming-cursor 900ms steps(2, jump-none) infinite;
}

.composer-surface {
  display: grid;
  gap: 8px;
  width: min(790px, calc(100% - 44px));
  padding: 10px;
  border: 1px solid var(--premium-border);
  border-radius: 26px;
  background: rgba(255, 255, 255, 0.88);
  box-shadow: 0 18px 56px rgba(15, 23, 42, 0.14);
  backdrop-filter: blur(18px);
}

.composer-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 4px;
}

.composer-tool-button {
  min-height: 28px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: rgba(248, 250, 252, 0.86);
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

.composer-tool-button:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

.composer-input-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 92px;
  gap: 8px;
  align-items: end;
}

.composer-surface textarea {
  min-height: 52px;
  border: 0;
  border-radius: var(--ds-radius-lg, 18px);
  background: transparent;
  box-shadow: none;
  font-size: var(--ds-text-body-15);
  line-height: var(--ds-leading-body);
}

.composer-surface textarea:focus {
  box-shadow: none;
}

.artifact-live-badge {
  display: inline-flex;
  align-items: center;
  min-height: 20px;
  margin-left: 6px;
  padding: 0 7px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--ds-color-cyan-soft);
  color: #0891b2;
  font-size: 10px;
  font-weight: var(--ds-weight-bold);
  text-transform: none;
}

.premium-product-shell-v1 .artifact-document-preview {
  font-size: var(--ds-text-body-15);
  line-height: var(--ds-leading-document);
}

@keyframes fade-in-up {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes streaming-cursor {
  50% {
    opacity: 0;
  }
}

[data-theme="dark"] .premium-product-shell-v1 .sidebar,
[data-theme="dark"] .composer-surface,
[data-theme="dark"] .result-highlight span {
  background: rgba(24, 24, 27, 0.86);
}

[data-theme="dark"] .premium-product-shell-v1 .workspace-hero {
  background: rgba(9, 9, 11, 0.72);
}

@media (max-width: 900px) {
  .composer-surface {
    width: calc(100% - 28px);
  }

  .composer-input-row {
    grid-template-columns: 1fr;
  }
}

/* AI Workspace Product Renewal v28 */
:root {
  --ds-leading-body: 1.58;
}

/* 20260708-mobile-dialog-tokens: WIZON mobile dialog design tokens. On mobile,
   content-panel modals (settings, search, …) go full-screen edge-to-edge like
   ChatGPT; small confirmation alerts (delete, share) stay centered. Opt a <dialog>
   into the full-screen treatment with the [data-mobile-fullscreen] attribute — the
   rule that consumes these tokens lives at the end of this file
   (search "20260708-mobile-dialog-fullscreen-system").
   NOTE: --wizon-mobile-breakpoint is the single source of truth for the mobile
   breakpoint; CSS cannot use a custom property inside a media-query condition, so the
   520px literals in the media queries must be kept in sync with this token. */
:root {
  --wizon-mobile-breakpoint: 520px;
  --wizon-mobile-dialog-inline-size: 100vw;
  /* Track the live visual viewport so full-screen dialogs (search, settings) shrink
     with the iOS keyboard and their sticky header stays put — same fix as the shell
     (styles.css "20260709-mobile-keyboard-fix"). Falls back to 100dvh pre-JS. */
  --wizon-mobile-dialog-block-size: var(--wizon-vvh, 100dvh);
  --wizon-mobile-dialog-margin: 0;
  --wizon-mobile-dialog-radius: 0;
}

.service-product-v28 .app-shell {
  grid-template-columns: 260px minmax(0, 1fr);
}

.service-product-v28 .sidebar {
  padding: 18px 14px 16px;
  background: rgba(255, 255, 255, 0.96);
  border-right: 1px solid rgba(15, 23, 42, 0.08);
  box-shadow: none;
}

.service-product-v28 .brand-row {
  padding: 0 2px 8px;
}
.service-product-v28 .brand-row strong {
  font-size: var(--ds-text-body-16);
  font-weight: 600;
  line-height: 1.18;
}

.service-product-v28 .new-chat-button {
  min-height: 44px;
  border: 0;
  border-radius: 13px;
  background: #0f172a;
  box-shadow: 0 10px 28px rgba(15, 23, 42, 0.14);
}

.service-product-v28 .nav-section {
  gap: 3px;
}

.service-product-v28 .nav-item {
  grid-template-columns: 26px minmax(0, 1fr);
  min-height: 38px;
  padding: 7px 9px;
  border-radius: 11px;
  color: var(--ink-soft);
}

.service-product-v28 .nav-item.active {
  background: #f6f7ff;
  box-shadow: inset 3px 0 0 var(--accent);
}

.service-product-v28 .nav-icon {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: #ffffff;
}

.service-product-v28 .recent-item {
  min-height: 36px;
  border-radius: var(--ds-radius-sm, 10px);
}

html[data-portal-tab="home"] .service-product-v28 .workspace-hero {
  display: none;
}

.service-product-v28 .chat-pane {
  min-height: 100vh;
  background: linear-gradient(180deg, #ffffff 0%, #fbfcfd 100%);
}

.service-product-v28 .message-list {
  padding: clamp(42px, 9vh, 92px) clamp(22px, 7vw, 104px) 28px;
}

.service-product-v28 .calm-chat-home {
  width: min(720px, 100%);
  gap: 17px;
  padding-top: 0;
}

.service-product-v28 .home-project-pill {
  min-height: 32px;
  border-color: rgba(15, 23, 42, 0.1);
  background: rgba(255, 255, 255, 0.86);
  color: #667085;
}

.service-product-v28 .calm-chat-home h2 {
  font-size: clamp(34px, 4.2vw, 44px);
  font-weight: 600;
  line-height: 1.16;
}

.service-product-v28 .quick-start-grid button {
  min-height: 48px;
  border-radius: 15px;
  font-weight: 600;
}

.service-product-v28 .result-highlight span {
  color: #667085;
}

.service-product-v28 .composer-surface {
  width: min(790px, calc(100% - 48px));
  margin-bottom: 22px;
  border-radius: var(--ds-radius-2xl, 28px);
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 18px 56px rgba(15, 23, 42, 0.13);
}

.service-product-v28 .composer-toolbar {
  align-items: center;
}

.composer-model-pill {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  margin-left: auto;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--ds-radius-pill, 999px);
  background: #f8fafc;
  color: var(--muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

.service-product-v28 .composer-surface textarea {
  min-height: 54px;
}

.service-product-v28 .composer .primary-button {
  min-height: 52px;
  border: 0;
  border-radius: var(--ds-radius-lg, 18px);
  background: #0f172a;
}

.service-product-v28 .context-pane {
  background: rgba(255, 255, 255, 0.96);
}

[data-theme="dark"] .service-product-v28 {
  background:
    radial-gradient(circle at 50% 14%, rgba(129, 140, 248, 0.13), transparent 28%),
    linear-gradient(180deg, #09090b 0%, #101014 100%);
}

[data-theme="dark"] .service-product-v28 .sidebar,
[data-theme="dark"] .service-product-v28 .chat-pane,
[data-theme="dark"] .service-product-v28 .composer-surface {
  background: rgba(15, 15, 18, 0.96);
}

[data-theme="dark"] .service-product-v28 .nav-item.active {
  background: rgba(129, 140, 248, 0.14);
}

[data-theme="dark"] .composer-model-pill {
  background: rgba(255, 255, 255, 0.06);
}

@media (max-width: 900px) {
  .service-product-v28 .app-shell {
    grid-template-columns: 1fr;
  }

  .service-product-v28 .chat-pane {
    min-height: calc(100vh - 280px);
  }

  .service-product-v28 .message-list {
    padding: 38px 18px 24px;
  }

  .composer-model-pill {
    margin-left: 0;
  }

  .approved-manual-map-form {
    grid-template-columns: 1fr;
  }
}

/* ====================================================================== *
 * .btn — unified button system (71-component-rulebook.md §4.1)
 * 5 variants: primary, secondary, ghost, danger, link. No other variants.
 * Solid backgrounds are ONLY allowed for primary and danger.
 * Phase 3.1.E (2026-05-24): all JS/HTML callsites migrated to .btn.
 * Legacy .primary-button / .secondary-button / .primary-inline /
 * .composer-tool-button CSS rules below are orphaned and slated for
 * removal in Phase 4 lint (test_token_usage_lint.py).
 * ====================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ds-space-2);
  border: 1px solid transparent;
  border-radius: var(--ds-radius-xs);
  font: inherit;
  font-weight: var(--ds-weight-semibold);
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  transition:
    background-color var(--ds-motion-fast),
    border-color var(--ds-motion-fast),
    color var(--ds-motion-fast),
    box-shadow var(--ds-motion-fast);
}

.btn:focus-visible {
  outline: 2px solid var(--ds-color-accent);
  outline-offset: 2px;
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn.btn--sm { min-height: 28px; padding: 0 var(--ds-space-3); font-size: var(--ds-text-caption-13); }
.btn.btn--md { min-height: 36px; padding: 0 var(--ds-space-4); font-size: var(--ds-text-body-14); }
.btn.btn--lg { min-height: 44px; padding: 0 var(--ds-space-5); font-size: var(--ds-text-body-15); }

.btn.btn--primary {
  background: var(--ds-button-primary-bg);
  color: var(--ds-button-primary-fg);
  border-color: var(--ds-button-primary-bg);
}
.btn.btn--primary:hover:not(:disabled) {
  background: var(--ds-button-primary-bg-hover);
  border-color: var(--ds-button-primary-bg-hover);
}

.btn.btn--secondary {
  background: var(--ds-button-secondary-bg);
  color: var(--ds-button-secondary-fg);
  border-color: var(--ds-button-secondary-border);
}
.btn.btn--secondary:hover:not(:disabled) {
  background: var(--ds-button-secondary-bg-hover);
  border-color: var(--ds-color-line-strong);
}

.btn.btn--ghost {
  background: transparent;
  color: var(--ds-button-ghost-fg);
  border-color: transparent;
}
.btn.btn--ghost:hover:not(:disabled) {
  background: var(--ds-button-ghost-bg-hover);
}

.btn.btn--danger {
  background: var(--ds-button-danger-bg);
  color: var(--ds-button-danger-fg);
  border-color: var(--ds-button-danger-bg);
}
.btn.btn--danger:hover:not(:disabled) {
  background: var(--ds-button-danger-bg-hover);
  border-color: var(--ds-button-danger-bg-hover);
}

.btn.btn--link {
  background: transparent;
  color: var(--ds-button-link-fg);
  border-color: transparent;
  padding-left: 0;
  padding-right: 0;
  min-height: auto;
}
.btn.btn--link:hover:not(:disabled) {
  text-decoration: underline;
}

/* ====================================================================== *
 * .ds-input — unified input system (71-component-rulebook.md §4.4)
 * Sizes: sm 32px, md 40px (default), lg 48px.
 * States: idle / hover / focus / disabled / invalid.
 * Error state changes border only — never bg.
 * ====================================================================== */

.ds-input {
  width: 100%;
  border: 1px solid var(--ds-input-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-input-bg);
  color: var(--ds-input-fg);
  font: inherit;
  outline: none;
  transition:
    border-color var(--ds-motion-fast),
    box-shadow var(--ds-motion-fast);
}

.ds-input::placeholder { color: var(--ds-input-placeholder); }

.ds-input.ds-input--sm { min-height: 32px; padding: 0 12px; font-size: var(--ds-text-caption-13); }
.ds-input.ds-input--md { min-height: 40px; padding: 0 14px; font-size: var(--ds-text-body-14); }
.ds-input.ds-input--lg { min-height: 48px; padding: 0 16px; font-size: var(--ds-text-body-15); }

.ds-input:hover:not(:disabled):not([aria-invalid="true"]) {
  border-color: var(--ds-input-border-hover);
}

.ds-input:focus,
.ds-input:focus-visible {
  border-color: var(--ds-input-border-focus);
  box-shadow: 0 0 0 2px var(--ds-input-ring-focus);
}

.ds-input:disabled {
  background: var(--ds-input-bg-disabled);
  color: var(--ds-input-fg-muted);
  cursor: not-allowed;
}

/* Native <select> chevron (Phase 3.6) — replace browser-default arrow with
 * a token-driven inline SVG so the visual stays consistent across OS/UA. */
select.ds-input {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-image: var(--ds-input-chevron);
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
  padding-right: 32px;
}
select.ds-input::-ms-expand { display: none; }

.ds-input[aria-invalid="true"] {
  border-color: var(--ds-input-border-invalid);
}

/* Search wrapper: leading icon + optional trailing clear button */
.ds-search {
  position: relative;
  display: block;
}

.ds-search .ds-input {
  padding-left: 36px;
}

.ds-search__icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--ds-input-fg-muted);
  pointer-events: none;
}

.ds-search__clear {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: var(--ds-radius-xs);
  color: var(--ds-input-fg-muted);
  font: inherit;
  line-height: 1;
}

.ds-search__clear:hover {
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-ink);
}

/* ====================================================================== *
 * .ds-modal — unified modal system (71-component-rulebook.md §4.2)
 * 3-slot anatomy: .ds-modal__header / .ds-modal__body / .ds-modal__footer
 * Sizes: sm 560px, md 720px (default), lg 960px.
 * Light/dark via Tier 2 swap (no [data-theme="dark"] selectors here).
 * Coexists with legacy .login-dialog for incremental migration; new modals
 * MUST use .ds-modal*.
 * ====================================================================== */

.ds-modal__overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--ds-space-6);
  background: var(--ds-modal-overlay);
}
.ds-modal__overlay.is-open { display: flex; }

.ds-modal {
  background: var(--ds-modal-surface);
  border: 1px solid var(--ds-modal-border);
  border-radius: var(--ds-modal-radius);
  box-shadow: var(--ds-modal-shadow);
  display: flex;
  flex-direction: column;
  max-height: 90vh;
  width: 100%;
}

.ds-modal.ds-modal--sm { max-width: 560px; }
.ds-modal.ds-modal--md { max-width: 720px; }
.ds-modal.ds-modal--lg { max-width: 960px; }

.ds-modal__header {
  padding: var(--ds-space-6);
  border-bottom: 1px solid var(--ds-modal-border);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ds-space-4);
  flex-shrink: 0;
}

.ds-modal__body {
  padding: var(--ds-space-6);
  overflow-y: auto;
  flex: 1 1 auto;
}

.ds-modal__footer {
  padding: var(--ds-space-6);
  border-top: 1px solid var(--ds-modal-border);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ds-space-3);
  flex-shrink: 0;
}

/* ====================================================================== *
 * .ds-chip — segmented + count (71-component-rulebook.md §4.5)
 * 2 variants only. Coexists with legacy .tab-button via selector grouping.
 * ====================================================================== */
.ds-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  background: var(--ds-chip-bg);
  color: var(--ds-chip-fg);
  border: 1px solid var(--ds-chip-border);
  font: inherit;
  font-size: var(--ds-text-body-14);
  cursor: pointer;
  transition: background var(--ds-motion-fast), color var(--ds-motion-fast), border-color var(--ds-motion-fast);
}
.ds-chip:hover:not([aria-disabled="true"]) {
  background: var(--ds-chip-bg-hover);
}
.ds-chip:focus-visible {
  outline: 2px solid var(--ds-color-accent);
  outline-offset: 2px;
}
.ds-chip[aria-pressed="true"],
.ds-chip.is-active {
  background: var(--ds-chip-bg-active);
  color: var(--ds-chip-fg-active);
  border-color: var(--ds-chip-bg-active);
}
.ds-chip.ds-chip--segmented {
  min-height: 32px;
  padding: 0 var(--ds-space-3);
  border-radius: var(--ds-radius-xs);
}
.ds-chip.ds-chip--count {
  min-height: 22px;
  padding: 0 var(--ds-space-2);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-chip-count-bg);
  color: var(--ds-chip-count-fg);
  border-color: transparent;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

/* Security-events panel filter chips (period / category / view). Reuses
 * .ds-chip--segmented; this only lays the chips out in a wrapping row. */
.security-filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-1);
  margin: var(--ds-space-2) 0;
}

/* ====================================================================== *
 * .ds-badge — status indicator (71-component-rulebook.md §4.6)
 * 5 variants: ok, warn, bad, info, neutral. Dot variant: 8px round, fg only.
 * ====================================================================== */
.ds-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  min-height: 22px;
  padding: 2px var(--ds-space-2);
  border-radius: var(--ds-radius-pill);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  background: var(--ds-badge-neutral-bg);
  color: var(--ds-badge-neutral-fg);
}
.ds-badge.ds-badge--ok      { background: var(--ds-badge-ok-bg);   color: var(--ds-badge-ok-fg); }
.ds-badge.ds-badge--warn    { background: var(--ds-badge-warn-bg); color: var(--ds-badge-warn-fg); }
.ds-badge.ds-badge--bad     { background: var(--ds-badge-bad-bg);  color: var(--ds-badge-bad-fg); }
.ds-badge.ds-badge--info    { background: var(--ds-badge-info-bg); color: var(--ds-badge-info-fg); }
.ds-badge.ds-badge--neutral { background: var(--ds-badge-neutral-bg); color: var(--ds-badge-neutral-fg); }

.ds-badge.ds-badge--dot {
  width: 8px;
  height: 8px;
  min-height: 0;
  padding: 0;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}
.ds-badge.ds-badge--dot.ds-badge--ok      { color: var(--ds-badge-ok-fg); }
.ds-badge.ds-badge--dot.ds-badge--warn    { color: var(--ds-badge-warn-fg); }
.ds-badge.ds-badge--dot.ds-badge--bad     { color: var(--ds-badge-bad-fg); }
.ds-badge.ds-badge--dot.ds-badge--info    { color: var(--ds-badge-info-fg); }
.ds-badge.ds-badge--dot.ds-badge--neutral { color: var(--ds-badge-neutral-fg); }

/* ====================================================================== *
 * .ds-tile — dashboard/hub stat tile (71-component-rulebook.md §4.7)
 * Anatomy: [dot? · number · label]. Same visual weight per row.
 * ====================================================================== */
.ds-tile {
  background: var(--ds-tile-bg);
  border: 1px solid var(--ds-tile-border);
  border-radius: var(--ds-tile-radius);
  padding: var(--ds-tile-padding);
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-2);
  min-height: 84px;
}
.ds-tile__top {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  color: var(--ds-tile-label-fg);
  font-size: var(--ds-text-micro-11);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ds-tile__num {
  font-size: var(--ds-text-heading-32);
  font-weight: var(--ds-weight-semibold);
  color: var(--ds-tile-num-fg);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.ds-tile.ds-tile--muted .ds-tile__num { color: var(--ds-color-ink-soft); }

/* ====================================================================== *
 * .ds-checkbox — minimal pattern (rulebook §4.8 not yet defined)
 * Native <input type="checkbox"> with custom appearance.
 * ====================================================================== */
.ds-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  border: 1.5px solid var(--ds-checkbox-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-solid);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  transition: border-color var(--ds-motion-fast), background var(--ds-motion-fast);
  vertical-align: middle;
  flex-shrink: 0;
}
.ds-checkbox:hover:not(:disabled) {
  border-color: var(--ds-checkbox-border-hover);
}
.ds-checkbox:checked {
  background: var(--ds-checkbox-bg-checked);
  border-color: var(--ds-checkbox-bg-checked);
}
.ds-checkbox:checked::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--ds-checkbox-fg-checked);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0, 43% 62%);
}
.ds-checkbox:focus-visible {
  outline: 2px solid var(--ds-color-accent);
  outline-offset: 2px;
}

/* ====================================================================== *
 * .ds-card — generic card (71-component-rulebook.md §4.3)
 * 3 variants: default, interactive, static. Optional 3-slot anatomy.
 * ====================================================================== */
.ds-card {
  background: var(--ds-card-bg);
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-card-radius);
  padding: var(--ds-card-padding);
  box-shadow: var(--ds-card-shadow);
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-3);
  transition: border-color var(--ds-motion-fast), box-shadow var(--ds-motion-fast), transform var(--ds-motion-fast);
}

.ds-card.ds-card--interactive:hover {
  border-color: var(--ds-card-border-hover);
  box-shadow: var(--ds-card-shadow-hover);
  transform: translateY(-1px);
}

.ds-card.ds-card--static {
  transition: none;
  cursor: default;
}

.ds-card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
}
.ds-card__body { flex: 1 1 auto; min-width: 0; }
.ds-card__footer {
  display: flex;
  gap: var(--ds-space-2);
  justify-content: flex-end;
  margin-top: var(--ds-space-2);
}

/* WDS AI Portal alignment — conversation-first shell */
.wds-ai-portal-v1 {
  /* 2026-08-01 셸 층 중복 제거. body 에 셸 클래스 6개가 index.html 에서 항상 함께 붙어
     있어(토글 없음), 같은 특이도로 같은 속성을 거는 선언은 마지막 것만 이긴다. 여기서
     지던 선언은 화면에 한 번도 닿은 적이 없어 지웠다 — 계산 스타일 무변화로 검증. */
  font-size: var(--ds-text-body-15);
}

.wds-ai-portal-v1 .app-shell {
  grid-template-columns: 260px minmax(0, 1fr);
}
.wds-ai-portal-v1 .brand-row {
  padding: 0;
}
.wds-ai-portal-v1 .brand-row strong {
  color: var(--ds-color-on-accent);
  font-size: var(--ds-text-title-18);
  font-weight: var(--ds-weight-semibold);
}

.wds-ai-portal-v1 .brand-row span,
.wds-ai-portal-v1 .sidebar .section-label,
.wds-ai-portal-v1 .recent-item small {
  color: color-mix(in srgb, var(--ds-color-on-accent) 68%, transparent);
}

.wds-ai-portal-v1 .new-chat-button {
  min-height: 42px;
  border: 1px solid color-mix(in srgb, var(--ds-color-on-accent) 18%, transparent);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-button-secondary-bg);
  color: var(--ds-button-secondary-fg);
  box-shadow: none;
  font-weight: var(--ds-weight-semibold);
}

.wds-ai-portal-v1 .theme-toggle,
.wds-ai-portal-v1 .nav-item {
  border-radius: var(--ds-radius-xs);
  transform: none;
}

.wds-ai-portal-v1 .nav-item {
  grid-template-columns: 26px minmax(0, 1fr);
  min-height: 38px;
  padding: var(--ds-space-2) var(--ds-space-3);
  color: var(--ds-color-on-accent);
}

.wds-ai-portal-v1 .nav-item span:not(.nav-icon) {
  display: block;
  color: color-mix(in srgb, var(--ds-color-on-accent) 84%, transparent);
}

.wds-ai-portal-v1 .nav-item:hover,
.wds-ai-portal-v1 .nav-item.active {
  border-color: color-mix(in srgb, var(--ds-color-on-accent) 18%, transparent);
  background: color-mix(in srgb, var(--ds-color-on-accent) 9%, transparent);
  transform: none;
}

.wds-ai-portal-v1 .nav-item.active {
  box-shadow: inset 3px 0 0 var(--ds-color-accent-2);
}

.wds-ai-portal-v1 .nav-item:hover span:not(.nav-icon),
.wds-ai-portal-v1 .nav-item.active span:not(.nav-icon) {
  color: var(--ds-color-on-accent);
}

.wds-ai-portal-v1 .nav-icon {
  width: 22px;
  height: 22px;
  border: 1px solid color-mix(in srgb, var(--ds-color-on-accent) 16%, transparent);
  border-radius: var(--ds-radius-xs);
  background: color-mix(in srgb, var(--ds-color-on-accent) 8%, transparent);
  color: var(--ds-color-on-accent);
}

.wds-ai-portal-v1 .recent-item {
  min-height: 40px;
  border-radius: var(--ds-radius-xs);
  color: var(--ds-color-on-accent);
}

.wds-ai-portal-v1 .main-pane,
.wds-ai-portal-v1 .chat-pane {
  background: var(--ds-color-bg);
}

.wds-ai-portal-v1 .workspace-hero {
  min-height: 72px;
  padding: var(--ds-space-4) var(--ds-space-6);
  background: var(--ds-color-surface-solid);
  border-bottom: 1px solid var(--ds-color-line);
  box-shadow: none;
  backdrop-filter: none;
}

.wds-ai-portal-v1 .hero-copy {
  margin-top: var(--ds-space-1);
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-13);
  line-height: var(--ds-leading-body);
}

.wds-ai-portal-v1 .status-stack {
  gap: var(--ds-space-2);
}

.wds-ai-portal-v1 .status-pill {
  min-height: 28px;
  border: 1px solid var(--ds-badge-neutral-bg);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-badge-neutral-bg);
  color: var(--ds-badge-neutral-fg);
  box-shadow: none;
}

.wds-ai-portal-v1 .status-pill.soft {
  background: var(--ds-badge-info-bg);
  color: var(--ds-badge-info-fg);
  border-color: var(--ds-badge-info-bg);
}

.wds-ai-portal-v1 .workbench {
  grid-template-columns: minmax(0, 1fr) minmax(340px, 400px);
}

html[data-portal-tab="home"] .wds-ai-portal-v1 .workspace-hero,
html[data-portal-tab="home"] .wds-ai-portal-v1 .context-pane {
  display: none;
}

html[data-portal-tab="home"] .wds-ai-portal-v1 .workbench {
  grid-template-columns: minmax(0, 1fr);
}

.wds-ai-portal-v1 .message-list {
  gap: var(--ds-space-5);
  padding: clamp(var(--ds-space-8), 8vh, var(--ds-space-10)) clamp(var(--ds-space-5), 7vw, 104px) var(--ds-space-6);
}

.wds-ai-portal-v1 .calm-chat-home {
  width: min(760px, 100%);
  gap: var(--ds-space-5);
  text-align: center;
}

.wds-ai-portal-v1 .home-project-pill {
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-color-surface-solid);
  color: var(--ds-color-ink-soft);
  box-shadow: var(--ds-shadow-xs);
}

.wds-ai-portal-v1 .calm-chat-home h2 {
  margin: 0;
  color: var(--ds-color-ink);
  font-size: clamp(var(--ds-text-heading-32), 4vw, var(--ds-text-display-40));
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.wds-ai-portal-v1 .calm-chat-home p {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-body-15);
  line-height: var(--ds-leading-reading);
}

.wds-ai-portal-v1 .quick-start-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ds-space-2);
}

.wds-ai-portal-v1 .quick-start-grid button {
  min-height: 44px;
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-card-bg);
  color: var(--ds-color-ink);
  box-shadow: none;
  font-weight: var(--ds-weight-medium);
}

.wds-ai-portal-v1 .quick-start-grid button:hover {
  border-color: var(--ds-card-border-hover);
  box-shadow: var(--ds-card-shadow);
  transform: none;
}

.wds-ai-portal-v1 .portal-context-strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--ds-space-2);
}

.wds-ai-portal-v1 .portal-context-strip span,
.wds-ai-portal-v1 .composer-chip {
  min-height: 26px;
  padding: var(--ds-space-1) var(--ds-space-2);
  border: 1px solid var(--ds-chip-border);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-chip-bg);
  color: var(--ds-chip-fg);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
}

.wds-ai-portal-v1 .message {
  grid-template-columns: 38px minmax(0, 780px);
}

.wds-ai-portal-v1 .message-body {
  padding: var(--ds-space-4) var(--ds-space-5);
  border-color: transparent;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  box-shadow: none;
}

.wds-ai-portal-v1 .message.user {
  justify-content: end;
}

.wds-ai-portal-v1 .message.user .message-body {
  border: 1px solid var(--ds-color-line);
  background: var(--ds-color-accent-soft);
  box-shadow: var(--ds-shadow-xs);
}

.wds-ai-portal-v1 .message-label {
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-ink-soft);
}
.wds-ai-portal-v1 .answer-activity {
  margin-top: var(--ds-space-3);
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-solid);
  box-shadow: var(--ds-shadow-xs);
}

.wds-ai-portal-v1 .answer-activity summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-3);
  min-height: 42px;
  padding: 0 var(--ds-space-4);
  cursor: pointer;
}

.wds-ai-portal-v1 .answer-activity summary span {
  color: var(--ds-color-ink);
  font-weight: var(--ds-weight-semibold);
}

.wds-ai-portal-v1 .answer-activity summary small,
.wds-ai-portal-v1 .evidence-note {
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
}

.wds-ai-portal-v1 .evidence-strip,
.wds-ai-portal-v1 .source-list {
  display: grid;
  gap: var(--ds-space-2);
  padding: 0 var(--ds-space-4) var(--ds-space-4);
}

.wds-ai-portal-v1 .source-card {
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-solid);
  box-shadow: none;
}

.wds-ai-portal-v1 .composer-surface {
  grid-template-columns: 1fr;
  grid-template-rows: auto auto auto auto;
  align-content: start;
  width: min(860px, calc(100% - var(--ds-space-8)));
  gap: var(--ds-space-2);
  margin: 0 auto var(--ds-space-5);
  padding: var(--ds-space-3);
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-md);
  background: var(--ds-color-surface-solid);
  box-shadow: var(--ds-shadow-md);
  backdrop-filter: none;
}

.wds-ai-portal-v1 .composer-status-rail {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: var(--ds-space-3);
  min-height: 20px;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  line-height: var(--ds-leading-body);
}

.wds-ai-portal-v1 .composer-attachment-lane,
.wds-ai-portal-v1 .composer-action-dock {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-2);
  min-height: 32px;
}

.wds-ai-portal-v1 .composer-prompt-body,
.wds-ai-portal-v1 .composer-input-row {
  grid-column: 1 / -1;
  display: block;
  width: 100%;
}

.wds-ai-portal-v1 .composer-surface textarea {
  width: 100%;
  min-height: 58px;
  max-height: 160px;
  padding: var(--ds-space-3);
  border: 1px solid var(--ds-input-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-input-bg);
  color: var(--ds-input-fg);
  box-shadow: none;
  resize: none;
}

.wds-ai-portal-v1 .composer-surface textarea:focus {
  border-color: var(--ds-input-border-focus);
  box-shadow: 0 0 0 2px var(--ds-input-ring-focus);
}

.wds-ai-portal-v1 .composer-tool-button,
.wds-ai-portal-v1 .composer-model-pill {
  min-height: 32px;
  border: 1px solid var(--ds-button-secondary-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-button-secondary-bg);
  color: var(--ds-button-secondary-fg);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--ds-weight-medium);
}

.wds-ai-portal-v1 .composer-tool-button:hover {
  border-color: var(--ds-color-line-strong);
  background: var(--ds-button-secondary-bg-hover);
  color: var(--ds-button-secondary-fg);
}

.wds-ai-portal-v1 .composer-model-pill {
  margin-left: auto;
  color: var(--ds-color-muted);
}

.wds-ai-portal-v1 #sendButton {
  min-height: 36px;
  border-radius: var(--ds-radius-xs);
}

.wds-ai-portal-v1 .context-pane {
  background: var(--ds-color-surface-solid);
  border-left: 1px solid var(--ds-color-line);
}

.wds-ai-portal-v1 .tabs {
  padding: var(--ds-space-3);
  border-bottom: 1px solid var(--ds-color-line);
}

.wds-ai-portal-v1 .tab-button {
  border-radius: var(--ds-radius-xs);
}

.wds-ai-portal-v1 .panel-block,
.wds-ai-portal-v1 .app-detail-panel,
.wds-ai-portal-v1 .app-workflow-panel,
.wds-ai-portal-v1 .app-input-fields,
.wds-ai-portal-v1 .app-result-card,
.wds-ai-portal-v1 .mini-card,
.wds-ai-portal-v1 .app-card {
  border-radius: var(--ds-radius-xs);
  box-shadow: none;
}

@keyframes pulse {
  50% {
    opacity: 0.45;
  }
}

@media (max-width: 900px) {
  .wds-ai-portal-v1 .app-shell {
    grid-template-columns: 1fr;
  }

  .wds-ai-portal-v1 .sidebar {
    min-height: auto;
  }

  .wds-ai-portal-v1 .workbench {
    grid-template-columns: 1fr;
  }

  .wds-ai-portal-v1 .context-pane {
    display: block;
  }

  html[data-portal-tab="home"] .wds-ai-portal-v1 .context-pane {
    display: none;
  }

  .wds-ai-portal-v1 .quick-start-grid {
    grid-template-columns: 1fr;
  }

  .wds-ai-portal-v1 .composer-surface {
    width: calc(100% - var(--ds-space-5));
  }

  .wds-ai-portal-v1 .composer-status-rail,
  .wds-ai-portal-v1 .composer-action-dock {
    align-items: stretch;
    flex-direction: column;
  }

  .wds-ai-portal-v1 .composer-model-pill {
    margin-left: 0;
  }

  .ops-status-head,
  .ops-status-summary {
    align-items: stretch;
    flex-direction: column;
  }

  .ops-status-grid {
    grid-template-columns: 1fr;
  }

  .account-grid {
    grid-template-columns: 1fr;
  }

  .account-head-actions,
  .account-section-head,
  .account-member-meta {
    align-items: stretch;
    flex-direction: column;
  }

  .account-member-row,
  .identity-control-row {
    grid-template-columns: 1fr;
  }

  .account-inline-form,
  .account-member-actions,
  .account-audit-toolbar,
  .account-audit-meta,
  .account-notification-history-filters,
  .account-notification-meta {
    align-items: stretch;
    flex-direction: column;
  }

  .account-inline-form,
  .account-member-actions,
  .account-notification-history-filters {
    grid-template-columns: 1fr;
  }

  .account-notification-history-result {
    justify-self: start;
  }

  .ops-version-code {
    max-width: 100%;
  }
}

/* WDS pattern fidelity pass — Login / AI Chat / Light-first workspace */
.wds-pattern-fidelity-v2 {
  /* 2026-08-01 셸 층 중복 제거. body 에 셸 클래스 6개가 index.html 에서 항상 함께 붙어
     있어(토글 없음), 같은 특이도로 같은 속성을 거는 선언은 마지막 것만 이긴다. 여기서
     지던 선언은 화면에 한 번도 닿은 적이 없어 지웠다 — 계산 스타일 무변화로 검증. */
  /* 위즈온 accent = 잉크(WDS 블루 아님). WDS 색은 로고 브랜드 색이고, 위즈온의 accent는
     잉크 모노톤이다(관제 admin-wds-bridge.css가 이미 확립한 표준을 포털에 정렬).
     on-accent도 함께 잉크-fg로 잡아야 다크에서 accent가 흰색으로 뒤집힐 때 글자가
     검정으로 뒤집혀 대비가 유지된다(안 그러면 흰 위 흰 글자). 향후 WDS에 위즈온 색
     정의가 추가되면 그쪽으로 옮긴다. 근거: token-namespaces.md + 사용자 결정 2026-07-22. */
  --ds-color-accent: var(--wizon-ai-action-primary-bg);
  --ds-color-accent-soft: var(--wizon-ai-sidebar-active-bg);
  --ds-color-on-accent: var(--wizon-ai-action-primary-fg);
  /* 포커스 링/보더도 잉크로 확장(accent와 동일 근거). 보더선은 솔리드 잉크(accent를 따라감,
     라이트 #0d0d0d/다크 #fff — 다크에서 흰선으로 플립), 링은 settings-v2가 이미 쓰는
     반투명 잉크 halo(--wizon-ai-focus-ring)로 통일. shell-tokens가 --wds-color-focus-ring을
     잉크로 오버라이드하지만 wds.css 로드 순서에 밀려 라이브에선 블루가 이기므로 여기서 직접
     박는다. 근거: 사용자 결정 2026-07-22("포커스 링도 잉크로"). */
  --ds-input-border-focus: var(--wizon-ai-action-primary-bg);
  --ds-input-ring-focus: var(--wizon-ai-focus-ring);
  /* doc 345 §4 / doc 221 W-1 「색은 의미(액션·상태)에만」 — 주액션은 잉크다.
     ★여기가 --wds-button-bg(WDS 기본 파랑 #1252b2)를 가리키는 바람에 .btn--primary 가
     «기본 상태에서만» 파랑이었다. 바로 아래 hover 는 이미 잉크였으므로, 버튼이 쉬고
     있을 땐 파랑이다가 손을 올리면 검정으로 튀었다(2026-08-01 실측: 라이트
     rgb(18,82,178)→#262626, 다크 rgb(60,143,253)→#e3e3e3). 그 모순을 없앤다. */
  --ds-button-primary-bg: var(--wizon-ai-action-primary-bg);
  --ds-button-primary-bg-hover: var(--wizon-ai-action-primary-bg-hover); /* C-2: hover도 잉크 리프트(블루 잔재 제거) */
  --ds-button-link-fg: var(--wds-color-link);
  min-height: 100vh;
  letter-spacing: 0;
}

.wds-pattern-fidelity-v2 .app-shell {
  grid-template-columns: 252px minmax(0, 1fr);
  background: var(--ds-color-bg);
}

.wds-pattern-fidelity-v2 .sidebar {
  gap: var(--ds-space-4);
  padding: var(--ds-space-5) var(--ds-space-4);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-ink-soft);
  border-right: 1px solid var(--ds-color-line);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .brand-row {
  min-height: 42px;
  padding: 0;
}

.wds-pattern-fidelity-v2 .workspace-cover {
  width: 34px;
  height: 34px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-accent-soft);
  color: var(--ds-color-accent);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .brand-row strong {
  color: var(--ds-color-ink);
  font-size: var(--ds-text-title-18);
  font-weight: var(--ds-weight-semibold);
}

.wds-pattern-fidelity-v2 .brand-row span,
.wds-pattern-fidelity-v2 .sidebar .section-label,
.wds-pattern-fidelity-v2 .recent-item small {
  color: var(--ds-color-muted);
}

.wds-pattern-fidelity-v2 .new-chat-button,
.wds-pattern-fidelity-v2 .theme-toggle {
  min-height: 40px;
  border: 1px solid var(--ds-button-secondary-border);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-button-secondary-bg);
  color: var(--ds-button-secondary-fg);
  box-shadow: none;
  font-weight: var(--ds-weight-semibold);
}

.wds-pattern-fidelity-v2 .new-chat-button:hover,
.wds-pattern-fidelity-v2 .theme-toggle:hover {
  border-color: var(--ds-color-line-strong);
  background: var(--ds-button-secondary-bg-hover);
  transform: none;
}

.wds-pattern-fidelity-v2 .nav-item {
  grid-template-columns: 28px minmax(0, 1fr);
  min-height: 38px;
  padding: var(--ds-space-2) var(--ds-space-3);
  border: 1px solid transparent;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--ds-color-ink-soft);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .nav-item span:not(.nav-icon) {
  color: var(--ds-color-ink-soft);
  font-weight: var(--ds-weight-medium);
}

.wds-pattern-fidelity-v2 .nav-icon {
  width: 24px;
  height: 24px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs);
  background: var(--ds-color-surface-solid);
  color: var(--ds-color-muted);
}

.wds-pattern-fidelity-v2 .nav-item:hover {
  border-color: var(--ds-color-line);
  background: var(--ds-color-surface-solid);
  transform: none;
}

.wds-pattern-fidelity-v2 .nav-item.active {
  border-color: var(--ds-color-accent);
  background: var(--ds-color-accent-soft);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .nav-item.active span:not(.nav-icon),
.wds-pattern-fidelity-v2 .nav-item.active .nav-icon {
  color: var(--ds-color-accent);
}

.wds-pattern-fidelity-v2 .recent-item {
  min-height: 38px;
  border-radius: var(--ds-radius-xs);
  color: var(--ds-color-ink-soft);
}

.wds-pattern-fidelity-v2 .recent-item:hover {
  border-color: var(--ds-color-line);
  background: var(--ds-color-surface-solid);
}

.wds-pattern-fidelity-v2 .main-pane,
.wds-pattern-fidelity-v2 .chat-pane {
  background: var(--ds-color-bg);
}

.wds-pattern-fidelity-v2 .workspace-hero {
  min-height: 70px;
  padding: var(--ds-space-4) var(--ds-space-7);
  background: var(--ds-color-surface-solid);
  border-bottom: 1px solid var(--ds-color-line);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .workbench {
  grid-template-columns: minmax(0, 1fr) minmax(320px, 380px);
}

.wds-pattern-fidelity-v2 .chat-pane {
  grid-template-rows: auto minmax(0, 1fr) auto;
}

.wds-pattern-fidelity-v2 .ai-chat-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ds-space-2);
  width: min(760px, calc(100% - var(--ds-space-8)));
  margin: var(--ds-space-5) auto 0;
  color: var(--ds-color-ink);
}

.wds-pattern-fidelity-v2 .assistant-identity {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  min-width: 0;
}

.wds-pattern-fidelity-v2 .assistant-mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-ink-soft);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

.wds-pattern-fidelity-v2 .assistant-identity strong {
  display: block;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-body-14);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.wds-pattern-fidelity-v2 .assistant-identity span:not(.assistant-mark) {
  display: block;
  margin-top: 2px;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  line-height: var(--ds-leading-tight);
}

.wds-pattern-fidelity-v2 .assistant-state {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-1);
  min-height: 28px;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-medium);
  white-space: nowrap;
}

.wds-pattern-fidelity-v2 .assistant-state-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--ds-radius-pill);
  background: var(--ds-color-accent);
}

.wds-pattern-fidelity-v2 .message-list {
  align-items: center;
  gap: var(--ds-space-4);
  padding: var(--ds-space-7) var(--ds-space-6) var(--ds-space-5);
}

.wds-pattern-fidelity-v2 .calm-chat-home {
  width: min(760px, 100%);
  margin: 0 auto;
  padding: var(--ds-space-7);
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-radius-lg);
  background: var(--ds-card-bg);
  box-shadow: var(--ds-shadow-xs);
  text-align: left;
}

.wds-pattern-fidelity-v2 .home-project-pill {
  width: fit-content;
  min-height: 26px;
  border-color: var(--ds-color-line);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-muted);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .calm-chat-home h2 {
  color: var(--ds-color-ink);
  font-size: var(--ds-text-heading-32);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.wds-pattern-fidelity-v2 .calm-chat-home p {
  color: var(--ds-color-ink-soft);
  font-size: var(--ds-text-body-15);
  line-height: var(--ds-leading-body);
}

.wds-pattern-fidelity-v2 .quick-start-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.wds-pattern-fidelity-v2 .quick-start-grid button {
  min-height: 42px;
  border-radius: var(--ds-radius-xs);
  background: var(--ds-button-secondary-bg);
  color: var(--ds-button-secondary-fg);
  box-shadow: none;
  text-align: left;
}

.wds-pattern-fidelity-v2 .portal-context-strip {
  justify-content: flex-start;
}

.wds-ai-portal-v1 .wds-home-surface,
.wds-pattern-fidelity-v2 .wds-home-surface {
  width: min(720px, 100%);
  margin: auto;
  padding: 0 var(--ds-space-2);
  border: 0;
  background: transparent;
  box-shadow: none;
  text-align: center;
}

.wds-ai-portal-v1 .wds-home-kicker,
.wds-pattern-fidelity-v2 .wds-home-kicker {
  margin: 0;
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
  letter-spacing: 0;
}

.wds-ai-portal-v1 .wds-home-surface h2,
.wds-pattern-fidelity-v2 .wds-home-surface h2 {
  margin: 0;
  color: var(--ds-color-ink);
  font-size: var(--ds-text-title-20);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-tight);
}

.wds-ai-portal-v1 .wds-home-surface p,
.wds-pattern-fidelity-v2 .wds-home-surface p {
  max-width: none;
  margin: 0;
  color: var(--ds-color-ink-soft);
  font-size: var(--ds-text-body-14);
  line-height: var(--ds-leading-body);
}

.wds-ai-portal-v1 .prompt-chip-row,
.wds-pattern-fidelity-v2 .prompt-chip-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--ds-space-2);
  margin-top: var(--ds-space-3);
}

.wds-ai-portal-v1 .prompt-chip,
.wds-pattern-fidelity-v2 .prompt-chip {
  min-height: 34px;
  padding: 0 var(--ds-space-3);
  border: 1px solid var(--ds-chip-border);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-chip-bg);
  color: var(--ds-chip-fg);
  font-size: var(--ds-text-body-14);
  font-weight: var(--ds-weight-medium);
  cursor: pointer;
}

.wds-ai-portal-v1 .prompt-chip:hover,
.wds-pattern-fidelity-v2 .prompt-chip:hover {
  border-color: var(--ds-color-line-strong);
  background: var(--ds-color-surface-muted);
}

.wds-pattern-fidelity-v2 .message {
  width: min(760px, 100%);
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
}

.wds-pattern-fidelity-v2 .message-body {
  width: 100%;
  padding: var(--ds-space-3) 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .message.assistant .message-body,
.wds-pattern-fidelity-v2 .message.system .message-body {
  background: transparent;
}

.wds-pattern-fidelity-v2 .message.user {
  justify-items: end;
}

.wds-pattern-fidelity-v2 .message.user .message-body {
  width: fit-content;
  max-width: min(620px, 82%);
  padding: var(--ds-space-3) var(--ds-space-4);
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-lg);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-ink);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .composer-surface,
.wds-pattern-fidelity-v2 .wds-composer-bar {
  width: min(760px, calc(100% - var(--ds-space-8)));
  margin: 0 auto var(--ds-space-6);
  padding: var(--ds-space-2);
  border: 1px solid var(--ds-card-border);
  border-radius: var(--ds-radius-lg);
  background: var(--ds-color-surface-solid);
  box-shadow: var(--ds-shadow-xs);
}

.wds-pattern-fidelity-v2 .composer-prompt-body {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--ds-space-2);
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .composer-surface textarea {
  min-height: 40px;
  max-height: 160px;
  padding: 10px 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  resize: none;
}

.wds-pattern-fidelity-v2 .composer-icon-button {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  min-width: 34px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill);
  background: var(--ds-color-surface-solid);
  color: var(--ds-color-ink);
  font-size: var(--ds-text-body-16);
  font-weight: var(--ds-weight-semibold);
  line-height: 1;
  cursor: pointer;
}

.wds-pattern-fidelity-v2 .composer-icon-button:hover {
  border-color: var(--ds-color-line-strong);
  background: var(--ds-color-surface-muted);
}

.wds-pattern-fidelity-v2 .composer-action-dock {
  display: inline-flex;
  align-items: center;
  gap: var(--ds-space-2);
}

.wds-pattern-fidelity-v2 .composer-model-pill {
  min-height: 30px;
  padding: 0 var(--ds-space-2);
  border: 1px solid transparent;
  border-radius: var(--ds-radius-pill);
  color: var(--ds-color-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
}

.wds-pattern-fidelity-v2 #sendButton,
.wds-pattern-fidelity-v2 .composer-send-button {
  border-color: var(--ds-color-accent);
  background: var(--ds-color-accent);
  color: var(--ds-color-on-accent);
}

.wds-pattern-fidelity-v2 #sendButton:disabled {
  border-color: var(--ds-color-line);
  background: var(--ds-color-surface-muted);
  color: var(--ds-color-muted);
  cursor: not-allowed;
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .chat-pane,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .chat-pane {
  grid-template-rows: auto auto auto;
  align-content: center;
  padding-bottom: clamp(var(--ds-space-8), 8vh, var(--ds-space-10));
}

/* 20260726-route-page-not-empty-chat: the rule above centres the EMPTY CHAT HOME
   vertically, but data-chat-state="empty" only says "no messages" — it stays set while
   a route page (/drive, /library, ...) is open, so a route with short content floated
   to the middle of the viewport under the fixed topbar. Measured on /drive at 390px:
   0 items = 65px dead space, 2 items = 163px, 4 items = 101px, 8+ items = 20px
   (normal). The gap scales inversely with content, which is why an audit seeded with
   9 rows never saw it while a real, nearly empty drive shows it to every user.
   .chat-pane computes to display:block here, so grid-template-rows above is inert and
   only align-content lands. Specificity (0,3,2) beats that rule's (0,3,1), so no
   !important is needed, and the chat home keeps its centring because it is never
   portal-route-open. */
html[data-chat-state="empty"] body.portal-route-open .chat-pane {
  align-content: start;
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .ai-chat-header,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .ai-chat-header {
  margin-bottom: var(--ds-space-5);
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .message-list,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .message-list {
  justify-content: center;
  min-height: 0;
  overflow: visible;
  padding: 0 var(--ds-space-6) var(--ds-space-4);
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .wds-home-surface,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .wds-home-surface {
  margin: 0 auto;
  padding: 0;
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .prompt-chip-row,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .prompt-chip-row {
  justify-content: center;
}

html[data-chat-state="empty"] .wds-ai-portal-v1 .composer-surface,
html[data-chat-state="empty"] .wds-pattern-fidelity-v2 .composer-surface {
  margin: 0 auto;
  box-shadow: var(--ds-shadow-xs);
}

/* ChatGPT reference visual pass for the WDS AI chat surface.
   20260710-dead-base-rule-removed (P1-B): 여기 있던 `.chatgpt-reference-v1 { #ffffff/#0d0d0d }`
   리터럴 base 규칙은 `body.chatgpt-reference-v1 { background:var(--cg-bg); color:var(--cg-text) }`
   (L8893+, 특정성 0,1,1 > 0,1,0 + 후순위)에 가려 죽어 있었고, 이 클래스는 index.html의 <body>
   전용이라 비-body 매치도 없다 → 런타임 무변화. 다크모드 하드코딩 랜드마인 제거. */

.chatgpt-reference-v1 .app-shell {
  grid-template-columns: 260px minmax(0, 1fr);
  background: #ffffff;
}

.chatgpt-reference-v1.sidebar-collapsed .app-shell {
  grid-template-columns: 52px minmax(0, 1fr);
}

.visually-hidden {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

.chatgpt-reference-v1 .sidebar {
  position: relative;
  z-index: 120;
  gap: 0;
  padding: 8px 6px 10px;
  overflow: visible;
  background: #f9f9f9;
  color: var(--cg-text);
  border-right: 1px solid #ececec;
  font-family: var(--wizon-ai-font-family); /* 20260711-typography-contract: 리터럴 시스템 스택 → 계약 토큰 */
}

.chatgpt-reference-v1 .sidebar[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-sidebar-rail {
  display: none;
}

.chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
  position: relative;
  z-index: 140;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-height: 100vh;
  padding: 8px 6px;
  background: #f9f9f9;
  border-right: 1px solid #ececec;
  overflow: visible;
}

.chatgpt-reference-v1 .chatgpt-sidebar-rail[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-rail-button {
  display: inline-grid;
  place-items: center;
  /* 20260704-sidebar-rail-chatgpt-measured: Chrome reference keeps 40px hit areas for collapsed rail items at x=6. */
  width: 40px;
  height: 36px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-rail-button:hover {
  background: #ececec;
}

.chatgpt-reference-v1 .chatgpt-tooltip-host {
  position: relative;
  overflow: visible;
}

.chatgpt-reference-v1 .chatgpt-tooltip {
  position: absolute;
  top: 50%;
  left: calc(100% + 16px);
  z-index: 1400;
  display: none;
  align-items: center;
  gap: 8px;
  min-height: 26px;
  padding: 4px 8px;
  border-radius: 8px;
  background: #1b1b1b;
  color: #ffffff;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.2);
  font-family: var(--wizon-ai-font-family); /* 20260711-typography-contract: 리터럴 시스템 스택 → 계약 토큰 */
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  line-height: 16px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%);
  transition: opacity 120ms ease, transform 120ms ease, visibility 120ms ease;
  visibility: hidden;
  white-space: nowrap;
  -webkit-font-smoothing: antialiased;
}

.chatgpt-reference-v1 .chatgpt-tooltip-host[data-tooltip-placement="top"] > .chatgpt-tooltip {
  top: auto;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
}

.chatgpt-reference-v1 .chatgpt-tooltip-host[data-tooltip-open="true"] > .chatgpt-tooltip {
  display: inline-flex;
  opacity: 1;
  transform: translateY(-50%);
  visibility: visible;
}

/* 20260717-tooltip-fixed-1: the tooltip used to reveal two ways — this host-descendant rule
   (JS-set [data-tooltip-open]) AND a pure-CSS `:hover`/`:focus-visible` fallback. The fallback
   could never carry position:fixed viewport coordinates (CSS can't read
   getBoundingClientRect), so a host inside an `overflow: hidden` card (the table toolbar)
   clipped at the card edge instead of floating free. Opening is now unified on the JS path for
   BOTH triggers — pointerenter (mouse) and a `:focus-visible`-gated `focus` listener (keyboard)
   — so every reveal always gets a measured, viewport-fixed position (see
   setChatGptTooltipOpen / openChatGptTooltipFixedPosition in app.js). `:focus-visible` gating
   still excludes a plain mouse CLICK (which only matches bare `:focus`, dropped for the same
   reason as before — it fires on a click too and left the tooltip stuck after clicking the
   sidebar toggle), so that regression cannot return. Once reparented to <body> on open, the
   tooltip is no longer a DOM child of the host, so its OWN [data-tooltip-open] attribute (not
   the host's) drives visibility — see the .chatgpt-tooltip[data-tooltip-open="true"] rule
   below; the host-descendant rule above still covers the instant before JS reparents it. */
.chatgpt-reference-v1 .chatgpt-tooltip[data-tooltip-open="true"] {
  display: inline-flex;
  opacity: 1;
  visibility: visible;
}

.chatgpt-reference-v1 .chatgpt-tooltip-host[data-tooltip-placement="top"][data-tooltip-open="true"] > .chatgpt-tooltip {
  transform: translateX(-50%) translateY(0);
}

.chatgpt-reference-v1 .chatgpt-tooltip-label {
  color: #ffffff;
  font-weight: 600;
  letter-spacing: normal;
}

.chatgpt-reference-v1 .chatgpt-tooltip-shortcut {
  color: #afafaf;
  font-weight: 500;
  letter-spacing: normal;
}

/* Touch/coarse-pointer devices get no hover affordances: the icon tooltips and the citation
   hover-preview are pointer-only. Some mobile browsers mis-report (hover: hover), which let a
   TAPPED tooltip/preview stick and overlap the UI (reported mobile 겹침 bug). A coarse-pointer
   guard hides them on a NARROW screen (reliable) or any touch-capable device — on touch/mobile the
   tap-to-open panel and self-evident icons cover the intent. */
@media (max-width: 520px), (any-pointer: coarse) {
  .chatgpt-reference-v1 .chatgpt-tooltip,
  .citation-preview {
    display: none !important;
  }
}

.chatgpt-reference-v1 .chatgpt-rail-brand {
  width: 36px;
  margin-bottom: 8px;
}

.chatgpt-reference-v1 .chatgpt-rail-account {
  align-self: flex-start;
  width: 38px;
  height: 40px;
  margin-top: auto;
  margin-bottom: 4px;
  margin-left: 2px;
  border-radius: var(--ds-radius-sm, 10px);
}

.chatgpt-reference-v1 .chatgpt-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  padding: 2px 4px 10px 8px;
  margin-bottom: 2px;
}

.chatgpt-reference-v1 .chatgpt-sidebar-head strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-16);
  font-weight: 500;
}

.chatgpt-product-mode-switcher {
  position: relative;
}

/* 20260725-sidebar-wordmark-only: the drawer's workspace switcher and the mobile top app bar's
   workspace chip are the same control, so only one may exist at a time. Desktop has no app bar →
   the button IS the switcher. Mobile has the chip → the drawer shows a plain wordmark, boxed like
   the button so the header height and the wordmark's x-position do not shift between the two.
   Swapping ELEMENTS (rather than hiding parts of the button) is what keeps the a11y tree honest:
   a display:none button leaves the tree entirely instead of announcing a menu it no longer opens. */
.chatgpt-reference-v1 .chatgpt-sidebar-wordmark {
  display: none;
  align-items: center;
  min-height: 44px;
  padding: 0 10px;
}

.chatgpt-product-mode-button {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}

.chatgpt-product-mode-button:hover,
.chatgpt-product-mode-button[aria-expanded="true"] {
  background: var(--wizon-ai-hover-bg, #ececec);
}

.chatgpt-product-mode-button > span:not([data-icon]) {
  color: var(--wizon-ai-text-muted, #6f6f6f);
  font-size: var(--ds-text-body-14);
}

.chatgpt-product-mode-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 272px;
  padding: 8px;
  border: 1px solid var(--wizon-ai-popover-border, #e3e3e3);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-popover-bg, #ffffff);
  box-shadow: var(--wizon-ai-popover-shadow, 0 8px 12px rgba(0, 0, 0, 0.08));
  z-index: var(--wizon-ai-popover-z, 80);
}

.chatgpt-product-mode-menu button {
  display: grid;
  width: 100%;
  min-height: 58px;
  grid-template-columns: 28px minmax(0, 1fr) 20px;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--wizon-ai-text-primary, #0d0d0d);
  text-align: left;
  cursor: pointer;
}

.chatgpt-product-mode-menu button:hover,
.chatgpt-product-mode-menu button.is-selected {
  background: var(--wizon-ai-hover-bg, #ececec);
}

.chatgpt-product-mode-menu button span:nth-child(2) {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.chatgpt-product-mode-menu small {
  color: var(--wizon-ai-text-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12);
}

.chatgpt-product-mode-menu button > span:last-child {
  opacity: 0;
}

.chatgpt-product-mode-menu button.is-selected > span:last-child {
  opacity: 1;
}

.chatgpt-reference-v1 [data-product-modes][hidden],
.chatgpt-reference-v1 [data-sidebar-destination][hidden],
.chatgpt-reference-v1 [data-sidebar-more-action][hidden] {
  display: none !important;
}

.chatgpt-reference-v1 .chatgpt-sidebar-utilities {
  display: grid;
  gap: 0;
  margin: -6px 8px 12px;
  padding-top: 8px;
  border-top: 1px solid var(--wizon-ai-sidebar-border, #ececec);
}

.chatgpt-reference-v1 .chatgpt-sidebar-utilities .chatgpt-sidebar-link {
  width: 100%;
}

/* The product selector reuses reasoning-popover only for the mobile top-layer
   sheet machinery. On desktop it remains a sidebar-anchored 272px menu; the
   generic reasoning menu's later 124px rule must never collapse or offset it. */
@media (min-width: 521px) {
  body.chatgpt-reference-v1 .chatgpt-product-mode-menu.reasoning-popover {
    left: 0;
    right: auto;
    top: calc(100% + 8px);
    bottom: auto;
    width: 272px;
    min-width: 272px;
    max-height: min(340px, calc(100vh - 16px));
    padding: 8px;
    overflow-x: visible;
  }
}

.chatgpt-reference-v1 .chatgpt-icon-button {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: #4b5563;
  cursor: pointer;
}

/* Only show a focus ring for keyboard navigation. Native <dialog>.showModal() autofocuses
   its first focusable child (e.g. the settings/close X), which painted the browser's default
   focus ring even when the dialog was opened by touch. :focus-visible scopes the ring to
   keyboard users so touch users see none (doc 143 mobile focus hardening; ref: MDN
   :focus-visible). */
.chatgpt-reference-v1 .chatgpt-icon-button:focus:not(:focus-visible) {
  outline: none;
}

@media (hover: hover) {
  .chatgpt-reference-v1 .chatgpt-icon-button:hover {
    background: #ececec;
    color: var(--cg-text);
  }
}

.chatgpt-reference-v1 .chatgpt-sidebar-group {
  display: grid;
  gap: 0;
  margin-bottom: 16px;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link,
.chatgpt-reference-v1 .new-chat-button.chatgpt-sidebar-link {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  justify-content: start;
  column-gap: 12px;
  min-height: var(--cg-sidebar-item-height);
  width: var(--cg-sidebar-item-width);
  max-width: 100%;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text);
  box-shadow: none;
  font-size: var(--cg-text-label-size, 14px); /* 20260711-typography-contract: 라벨 토큰(모바일 17px 전파) */
  font-weight: 400;
  line-height: var(--cg-text-label-leading, 1.45); /* 데스크톱 14×1.45≈20px 동등, 모바일 17px에 비례 */
  text-align: left;
  /* 20260802-sidebar-link-no-underline: 이 규칙은 <a>(프로젝트·드라이브·일정·라이브러리·아카이브·
     휴지통)와 <button>(새 채팅·검색)에 함께 걸린다. 리셋이 없으면 앵커만 브라우저 기본 밑줄을 받아
     같은 드로어에 두 종류의 행이 생긴다(iPhone 17 시뮬 실촬영, 배포 0583703ab). */
  text-decoration: none;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link > [data-icon] {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link > span:not([data-icon]) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-sidebar-shortcut {
  justify-self: end;
  margin-left: 8px;
  color: #8a8a8a;
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  letter-spacing: 0;
  line-height: 16px;
}

.chatgpt-reference-v1 .chatgpt-sidebar-shortcut[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link.active {
  background: #ececec;
}
@media (hover: hover) {
  .chatgpt-reference-v1 .chatgpt-sidebar-link:hover {
    background: #ececec;
  }
}

.chatgpt-reference-v1 .chatgpt-sidebar-link svg,
.chatgpt-reference-v1 .chatgpt-icon-button svg,
.chatgpt-reference-v1 .chatgpt-account-menu svg,
.chatgpt-reference-v1 .chatgpt-more-menu svg,
.chatgpt-reference-v1 .chatgpt-rail-button svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--wds-icon-stroke, 1.7);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chatgpt-reference-v1 .chatgpt-more-menu {
  /* 20260704-sidebar-more-popover-chatgpt: Chrome-measured ChatGPT "더 보기" menu opens beside the sidebar (x 250, w 258, h 120). */
  position: absolute;
  left: 250px;
  top: var(--sidebar-more-menu-top, 271px);
  z-index: 70;
  display: block;
  width: 258px;
  height: 120px;
  padding: 6px 0;
  border: 0 solid rgba(0, 0, 0, 0.05);
  border-radius: 16px;
  background: #ffffff;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .chatgpt-more-menu[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-more-menu button {
  display: flex;
  align-items: center;
  gap: 6px;
  width: calc(100% - 12px);
  height: 36px;
  min-height: 36px;
  margin: 0 6px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-more-menu button:hover {
  background: #f4f4f4;
}

.chatgpt-reference-v1 .chatgpt-more-menu button > [data-icon] {
  display: inline-grid;
  flex: 0 0 20px;
  place-items: center;
}

.chatgpt-reference-v1 .chatgpt-more-menu button svg {
  width: 20px;
  height: 20px;
}

.chatgpt-reference-v1 .chatgpt-account-area,
.chatgpt-reference-v1 .chatgpt-account-menu,
.chatgpt-reference-v1 .chatgpt-rail-account {
  --chatgpt-account-area-padding-top: calc(var(--wizon-ai-space-unit) * 2.25);
  --chatgpt-account-button-gap: var(--ds-space-2, 8px);
  --chatgpt-account-button-pad-y: var(--cg-menu-gutter);
  --chatgpt-account-button-pad-right: var(--cg-menu-gutter);
  --chatgpt-account-button-pad-left: var(--ds-space-2, 8px);
  --chatgpt-account-button-radius: var(--wizon-ai-radius-menu-row);
  --chatgpt-account-avatar-size: var(--ds-space-6, 24px);
  --chatgpt-account-avatar-bg: var(--wizon-ai-account-avatar-bg);
  --chatgpt-account-avatar-fg: var(--wizon-ai-account-avatar-fg);
  --chatgpt-account-avatar-font-size: var(--wds-font-size-caption);
  --chatgpt-account-text-size: var(--wds-font-size-body-2);
  --chatgpt-account-text-line-height: calc(var(--wizon-ai-space-unit) * 5);
  --chatgpt-account-caption-size: var(--wds-font-size-caption);
  --chatgpt-account-caption-line-height: var(--ds-space-4, 16px);
  --chatgpt-account-menu-width: var(--wizon-ai-account-menu-width);
  --chatgpt-account-menu-radius: var(--wizon-ai-radius-popover);
  --chatgpt-account-menu-gutter: var(--cg-menu-gutter);
  --chatgpt-account-menu-row-gap: var(--cg-menu-gutter);
  --chatgpt-account-menu-row-height: var(--wizon-ai-menu-row-height);
  --chatgpt-account-menu-row-radius: var(--wizon-ai-radius-menu-row);
  --chatgpt-account-menu-row-icon-size: var(--wizon-ai-icon-size-md);
  --chatgpt-account-menu-row-pad-y: var(--cg-menu-gutter);
  --chatgpt-account-menu-row-pad-left: calc(var(--wizon-ai-space-unit) * 2.5);
  --chatgpt-account-menu-row-pad-right: var(--ds-space-7, 32px);
  --chatgpt-account-menu-row-font-size: var(--wds-font-size-body-2);
  --chatgpt-account-menu-row-line-height: calc(var(--wizon-ai-space-unit) * 5);
  --chatgpt-account-menu-head-height: var(--wizon-ai-account-menu-head-height);
  --chatgpt-account-menu-head-gap: var(--ds-space-2, 8px);
  --chatgpt-account-menu-head-margin-bottom: calc(var(--wizon-ai-space-unit) * 2.25);
  --chatgpt-account-menu-separator-margin-block: var(--wizon-ai-space-unit);
  --chatgpt-account-menu-separator-margin-inline: var(--ds-space-4, 16px);
}

.chatgpt-reference-v1 .chatgpt-account-area {
  position: relative;
  margin-top: auto;
  padding-top: var(--chatgpt-account-area-padding-top);
}

.chatgpt-reference-v1 .chatgpt-account-area::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 1px;
  background: var(--cg-sidebar-border);
}

.chatgpt-reference-v1 .chatgpt-account-button {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--chatgpt-account-button-gap);
  width: var(--cg-sidebar-account-width);
  max-width: 100%;
  height: var(--cg-sidebar-account-height);
  min-height: var(--cg-sidebar-account-height);
  padding: var(--chatgpt-account-button-pad-y) var(--chatgpt-account-button-pad-right) var(--chatgpt-account-button-pad-y) var(--chatgpt-account-button-pad-left);
  border: 0;
  border-radius: var(--chatgpt-account-button-radius);
  background: transparent;
  color: var(--cg-text);
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-account-button:hover,
.chatgpt-reference-v1 .chatgpt-account-button[aria-expanded="true"] {
  background: var(--cg-hover);
}

.chatgpt-reference-v1 .chatgpt-account-avatar {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: var(--chatgpt-account-avatar-size);
  height: var(--chatgpt-account-avatar-size);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--chatgpt-account-avatar-bg);
  color: var(--chatgpt-account-avatar-fg);
  font-size: var(--chatgpt-account-avatar-font-size);
  font-weight: 600;
}

/* 프로필 사진이 있으면 이니셜 대신 이미지가 배지를 채운다. 크기·모양은 배지가
   이미 정하므로 여기서 다시 정하지 않고 상속·꽉채움만 지시한다. */
.chatgpt-reference-v1 .chatgpt-account-avatar-image {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.chatgpt-reference-v1 .chatgpt-account-copy {
  display: grid;
  min-width: 0;
  gap: 0;
}

.chatgpt-reference-v1 .chatgpt-account-copy strong,
.chatgpt-reference-v1 .chatgpt-account-menu-head strong {
  overflow: hidden;
  color: var(--cg-text);
  font-size: var(--chatgpt-account-text-size);
  font-weight: 400;
  line-height: var(--chatgpt-account-text-line-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-account-copy small,
.chatgpt-reference-v1 .chatgpt-account-menu-head small {
  color: var(--cg-muted);
  font-size: var(--chatgpt-account-caption-size);
  line-height: var(--chatgpt-account-caption-line-height);
}

.chatgpt-reference-v1 .chatgpt-account-menu {
  position: absolute;
  left: var(--account-menu-left, 2px);
  top: var(--account-menu-top, auto);
  bottom: var(--account-menu-bottom, calc(100% - 5px));
  z-index: 80;
  display: block;
  width: var(--chatgpt-account-menu-width);
  max-height: var(--account-menu-max-height, min(360px, calc(100vh - 16px)));
  padding: var(--chatgpt-account-menu-gutter) 0;
  border: 0;
  border-radius: var(--chatgpt-account-menu-radius);
  background: var(--cg-menu-bg);
  box-shadow: var(--cg-menu-shadow);
  overflow-y: auto;
  overscroll-behavior: contain;
}

.chatgpt-reference-v1 .chatgpt-account-menu[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-rail-account-menu {
  left: var(--account-menu-left, calc(100% + 8px));
  top: var(--account-menu-top, auto);
  bottom: var(--account-menu-bottom, 8px);
  z-index: 120;
  transform-origin: left bottom;
}

.chatgpt-reference-v1 .chatgpt-account-menu-head {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-account-menu-head-gap);
  width: calc(100% - (var(--chatgpt-account-menu-gutter) * 2));
  min-height: var(--chatgpt-account-menu-head-height);
  margin: 0 var(--chatgpt-account-menu-gutter) var(--chatgpt-account-menu-head-margin-bottom);
  padding: var(--chatgpt-account-menu-row-pad-y) var(--chatgpt-account-menu-row-pad-left);
  border: 0;
  border-radius: var(--chatgpt-account-menu-row-radius);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-account-menu button {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-account-menu-row-gap);
  width: calc(100% - (var(--chatgpt-account-menu-gutter) * 2));
  height: var(--chatgpt-account-menu-row-height);
  min-height: var(--chatgpt-account-menu-row-height);
  margin: 0 var(--chatgpt-account-menu-gutter);
  padding: var(--chatgpt-account-menu-row-pad-y) var(--chatgpt-account-menu-row-pad-right) var(--chatgpt-account-menu-row-pad-y) var(--chatgpt-account-menu-row-pad-left);
  border: 0;
  border-radius: var(--chatgpt-account-menu-row-radius);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--chatgpt-account-menu-row-font-size);
  font-weight: 400;
  line-height: var(--chatgpt-account-menu-row-line-height);
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-account-menu .chatgpt-account-menu-head {
  gap: var(--chatgpt-account-menu-head-gap);
  height: var(--chatgpt-account-menu-head-height);
  min-height: var(--chatgpt-account-menu-head-height);
  margin: 0 var(--chatgpt-account-menu-gutter);
  padding: var(--chatgpt-account-menu-row-pad-y) var(--chatgpt-account-menu-row-pad-left);
}

.chatgpt-reference-v1 .chatgpt-account-menu button:not(.chatgpt-account-menu-head) [data-icon] {
  display: inline-grid;
  flex: 0 0 var(--chatgpt-account-menu-row-icon-size);
  place-items: center;
  width: var(--chatgpt-account-menu-row-icon-size);
  height: var(--chatgpt-account-menu-row-icon-size);
}

.chatgpt-reference-v1 .chatgpt-account-menu button:not(.chatgpt-account-menu-head) [data-icon] svg {
  width: var(--chatgpt-account-menu-row-icon-size);
  height: var(--chatgpt-account-menu-row-icon-size);
}

.chatgpt-reference-v1 .chatgpt-account-menu button:not(.chatgpt-account-menu-head) span:not([data-icon]) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-account-menu button:hover,
.chatgpt-reference-v1 .chatgpt-account-menu-head:hover {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-menu-separator {
  height: 1px;
  margin: var(--chatgpt-account-menu-separator-margin-block) var(--chatgpt-account-menu-separator-margin-inline);
  background: var(--cg-sidebar-border);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog {
  width: min(680px, calc(100vw - 32px));
  max-width: none;
  height: min(600px, calc(100vh - 48px));
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: #ffffff;
  color: var(--cg-text);
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog::backdrop {
  background: rgba(0, 0, 0, 0.28);
}

.chatgpt-reference-v1 .chatgpt-settings-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  height: 100%;
}

.chatgpt-reference-v1 .chatgpt-settings-head {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  align-items: center;
  min-height: 56px;
  padding: 0;
  border-bottom: 1px solid #ececec;
}

.chatgpt-reference-v1 .chatgpt-settings-head .chatgpt-icon-button {
  width: 36px;
  height: 36px;
  margin-left: 15px;
  padding: 0;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-settings-head h2 {
  margin: 0;
  padding-left: 16px;
  font-size: var(--ds-text-title-18);
  line-height: 28px;
  font-weight: 400;
}

.chatgpt-reference-v1 .chatgpt-settings-body {
  display: grid;
  grid-template-columns: 180px minmax(0, 1fr);
  min-height: 0;
}

.chatgpt-reference-v1 .chatgpt-settings-tabs {
  display: grid;
  align-content: start;
  gap: 0;
  padding: 4px 0;
  border-right: 1px solid #ececec;
  overflow: auto;
}

.chatgpt-reference-v1 .chatgpt-settings-tabs button {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 167px;
  min-height: 36px;
  margin: 0 6px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  line-height: 20px;
  font-weight: 400;
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-settings-tabs button:hover,
.chatgpt-reference-v1 .chatgpt-settings-tabs button.is-active {
  background: rgba(0, 0, 0, 0.04);
}

.chatgpt-reference-v1 .chatgpt-settings-tabs button:focus:not(:focus-visible) {
  outline: none;
}

.chatgpt-reference-v1 .chatgpt-settings-panel {
  display: grid;
  align-content: start;
  gap: 0;
  padding: 0 16px;
  overflow: auto;
}

.chatgpt-reference-v1 .chatgpt-settings-panel h3 {
  margin: 0;
  font-size: var(--ds-text-title-18);
  line-height: 28px;
  font-weight: 400;
}

.chatgpt-reference-v1 .settings-panel-section {
  min-width: 0;
  background: inherit;
}

.chatgpt-reference-v1 .settings-section-header {
  display: flex;
  min-height: 60px;
  align-items: flex-start;
  padding: 12px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.10);
}

.chatgpt-reference-v1 .settings-section-title {
  min-width: 0;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-title-18);
  font-weight: 400;
  line-height: 28px;
  letter-spacing: 0;
}

.chatgpt-reference-v1 .settings-description {
  margin: 0;
  color: #6f6f6f;
  font-size: var(--ds-text-body-14);
  line-height: 1.5;
}

.chatgpt-reference-v1 .settings-section-note {
  margin: 15px -16px 0;
  padding: 0 12px 0 24px;
  color: rgb(93, 93, 93);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
  letter-spacing: 0.01em;
}

.chatgpt-reference-v1 .settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  min-height: 60px;
  border-bottom: 1px solid #f0f0f0;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
}

.chatgpt-reference-v1 .settings-row-stacked {
  align-items: flex-start;
  padding: 12px 0;
}

.chatgpt-reference-v1 .settings-row-copy {
  display: grid;
  min-width: 0;
  max-width: 310px;
  gap: 4px;
}

.chatgpt-reference-v1 .settings-row-label {
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0;
}

.chatgpt-reference-v1 .settings-row-description {
  color: rgb(93, 93, 93);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0;
}

.chatgpt-reference-v1 .settings-row-value {
  min-width: 0;
  max-width: 260px;
  overflow: hidden;
  color: rgb(93, 93, 93);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .settings-pill,
.chatgpt-reference-v1 .settings-danger-pill,
.chatgpt-reference-v1 .settings-combobox {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 82px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid rgba(0, 0, 0, 0);
  border-radius: 8px;
  background: #ffffff;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  line-height: 14px;
}

.chatgpt-reference-v1 .settings-choice-control {
  position: relative;
  display: inline-grid;
  justify-items: end;
}

.chatgpt-reference-v1 .settings-combobox:hover,
.chatgpt-reference-v1 .settings-combobox.is-open,
.chatgpt-reference-v1 .settings-pill:hover,
.chatgpt-reference-v1 .settings-danger-pill:hover {
  background: rgba(0, 0, 0, 0.04);
}

.chatgpt-reference-v1 .settings-danger-pill {
  color: #e02e2a;
}

.chatgpt-reference-v1 .settings-pill-disabled,
.chatgpt-reference-v1 .settings-pill-disabled:hover {
  background: transparent;
  color: var(--cg-muted, #6f6f6f);
  cursor: default;
  opacity: 0.72;
}

.chatgpt-reference-v1 .settings-combobox svg {
  width: 16px;
  height: 16px;
  stroke-width: var(--wds-icon-stroke, 1.7);
}

.chatgpt-reference-v1 .settings-choice-popover {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  z-index: 85;
  display: grid;
  width: 220px;
  padding: 6px;
  border: 0;
  border-radius: 16px;
  background: var(--cg-menu-bg, #ffffff);
  color: var(--cg-text, #0d0d0d);
  box-shadow: var(--cg-menu-shadow, 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62));
}

.chatgpt-reference-v1 .settings-choice-option {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 18px;
  align-items: center;
  width: 208px;
  min-height: 36px;
  padding: 6px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 .settings-choice-option:hover,
.chatgpt-reference-v1 .settings-choice-option:focus-visible,
.chatgpt-reference-v1 .settings-choice-option.is-selected {
  background: rgba(0, 0, 0, 0.04);
  outline: none;
}

.chatgpt-reference-v1 .settings-choice-option span:first-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .settings-choice-option svg {
  width: 16px;
  height: 16px;
  justify-self: end;
  stroke-width: var(--wds-icon-stroke, 1.7);
}

html[data-theme="dark"] .chatgpt-reference-v1 .settings-choice-option:hover,
html[data-theme="dark"] .chatgpt-reference-v1 .settings-choice-option:focus-visible,
html[data-theme="dark"] .chatgpt-reference-v1 .settings-choice-option.is-selected {
  background: rgba(255, 255, 255, 0.10);
}

.chatgpt-reference-v1 .settings-switch {
  position: relative;
  width: 32px;
  height: 20px;
  /* Never let the flex row shrink the track — in the stacked row (wide description text)
     on a narrow phone it was squeezed from 32px to ~25px, so toggles looked uneven. */
  flex: 0 0 auto;
  padding: 2px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: #3a83f7;
  cursor: pointer;
}

.chatgpt-reference-v1 .settings-switch[aria-checked="false"] {
  background: rgba(0, 0, 0, 0.16);
}

html[data-theme="dark"] .chatgpt-reference-v1 .settings-switch[aria-checked="false"] {
  background: rgba(255, 255, 255, 0.24);
}

.chatgpt-reference-v1 .settings-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  right: 3px;
  width: 14px;
  height: 14px;
  border-radius: var(--ds-radius-pill, 999px);
  background: #ffffff;
}

.chatgpt-reference-v1 .settings-switch[aria-checked="false"]::after {
  right: auto;
  left: 3px;
}

@media (max-width: 520px) {
  /* Full-screen sizing comes from the shared mobile-dialog rule
     ([data-mobile-fullscreen], see "20260708-mobile-dialog-fullscreen-system");
     only the settings-specific inner layout lives here. */
  .chatgpt-reference-v1 .chatgpt-settings-head {
    grid-template-columns: 52px minmax(0, 1fr);
  }

  .chatgpt-reference-v1 .chatgpt-settings-head .chatgpt-icon-button {
    margin-left: 9px;
  }

  .chatgpt-reference-v1 .chatgpt-settings-head h2 {
    padding-left: 0;
  }

  .chatgpt-reference-v1 .chatgpt-settings-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }

  .chatgpt-reference-v1 .chatgpt-settings-tabs {
    display: flex;
    gap: 4px;
    padding: 6px;
    overflow-x: auto;
    overflow-y: hidden;
    border-right: 0;
    border-bottom: 1px solid var(--cg-menu-border, #ececec);
    scrollbar-width: none;
  }

  .chatgpt-reference-v1 .chatgpt-settings-tabs::-webkit-scrollbar {
    display: none;
  }

  .chatgpt-reference-v1 .chatgpt-settings-tabs button {
    flex: 0 0 auto;
    width: auto;
    max-width: 180px;
  }

  .chatgpt-reference-v1 .chatgpt-settings-panel {
    min-width: 0;
    padding: 0 16px;
  }

  .chatgpt-reference-v1 .settings-row-copy {
    max-width: 100%;
  }
}

.chatgpt-reference-v1 .settings-shortcut-list {
  display: flex;
  flex-direction: column;
  gap: 32px;
  margin: 0 -4px 0 -4px;
  padding: 16px 0 24px;
}

.chatgpt-reference-v1 .settings-shortcut-group {
  display: grid;
  gap: 0;
}

.chatgpt-reference-v1 .settings-shortcut-group-title {
  margin: 0 0 4px;
  padding: 0 12px 0 20px;
  color: rgb(93, 93, 93);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  letter-spacing: 0.01em;
}

.chatgpt-reference-v1 .settings-shortcut-row {
  display: flex;
  min-height: 53px;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px 10px 16px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  cursor: pointer;
  text-align: left;
}

.chatgpt-reference-v1 .settings-shortcut-row:hover {
  background: rgba(0, 0, 0, 0.04);
  border-radius: 8px;
}

.chatgpt-reference-v1 .settings-shortcut-label {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-16);
  font-weight: 400;
  line-height: 24px;
  letter-spacing: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .settings-shortcut-keys {
  display: flex;
  flex: 0 0 150px;
  width: 150px;
  height: 36px;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
  color: rgb(93, 93, 93);
}

.chatgpt-reference-v1 .settings-shortcut-keys span {
  display: inline-flex;
  min-width: 24px;
  height: 24px;
  align-items: center;
  justify-content: center;
  padding: 0 6px;
  border-radius: var(--ds-radius-pill, 999px);
  color: rgb(93, 93, 93);
  font-size: var(--ds-text-body-16);
  font-weight: 400;
  line-height: 24px;
}

.chatgpt-reference-v1 .brand-row {
  min-height: 42px;
  padding: 0 4px 12px;
  gap: 0;
}
.chatgpt-reference-v1 .brand-row strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-16);
  font-weight: 500;
}

.chatgpt-reference-v1 .sidebar .brand-row span,
.chatgpt-reference-v1 .nav-section .section-label {
  display: none;
}

.chatgpt-reference-v1 .sidebar-section {
  position: relative;
  gap: 2px;
  margin: 0;
}

.chatgpt-reference-v1 .sidebar-section.grow {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  gap: 0;
  min-height: 0;
  max-height: calc(100vh - 210px);
}

.chatgpt-reference-v1 .new-chat-button,
.chatgpt-reference-v1 .theme-toggle {
  justify-content: flex-start;
  min-height: 40px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
  box-shadow: none;
  font-size: var(--ds-text-body-14);
  font-weight: 400;
}

.chatgpt-reference-v1 .new-chat-button:hover,
.chatgpt-reference-v1 .theme-toggle:hover {
  background: #ececec;
}

.chatgpt-reference-v1 .nav-item {
  grid-template-columns: minmax(0, 1fr);
  min-height: 40px;
  padding: 0 10px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .nav-item:hover,
.chatgpt-reference-v1 .nav-item.active {
  background: #ececec;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .nav-item span:not(.nav-icon),
.chatgpt-reference-v1 .nav-item.active span:not(.nav-icon) {
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
}

.chatgpt-reference-v1 .sidebar .nav-icon {
  display: none;
}

.chatgpt-reference-v1 .sidebar .section-label {
  color: #6f6f6f;
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
}

.chatgpt-reference-v1 .chatgpt-recent-header {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  min-height: 32px;
  /* 20260704-sidebar-recent-header-chatgpt: Chrome-measured ChatGPT recent header uses a 32px row with text starting at x=16. */
  padding: 0 2px 0 10px;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-recent-title {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 2px;
  min-width: 0;
  height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  line-height: 20px;
}

.chatgpt-reference-v1 .chatgpt-recent-title svg {
  width: 14px;
  height: 14px;
  color: #8a8a8a;
}

.chatgpt-reference-v1 .chatgpt-recent-header-actions {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  opacity: 0;
  pointer-events: auto;
  transition: opacity 100ms ease;
}

.chatgpt-reference-v1 .chatgpt-recent-header:focus-within .chatgpt-recent-header-actions,
.chatgpt-reference-v1 .chatgpt-recent-header:has([data-recent-header-action="more"][aria-expanded="true"]) .chatgpt-recent-header-actions {
  opacity: 1;
  pointer-events: auto;
}

/* Reveal-on-hover only on real hover devices. On iOS the section :hover fired on the FIRST
   tap of a recent row (the row lives inside .sidebar-section), showing the header ✏️/⋯ and
   swallowing that tap — so the conversation only opened on the second tap. Guarded, the
   first tap now opens the conversation directly. (:focus-within / aria-expanded above stay
   unguarded so keyboard + the open menu still reveal the actions.) */
@media (hover: hover) {
  .chatgpt-reference-v1 .sidebar-section:hover .chatgpt-recent-header-actions {
    opacity: 1;
    pointer-events: auto;
  }
}

.chatgpt-reference-v1 .chatgpt-recent-header-action {
  display: inline-grid;
  place-items: center;
  width: calc(var(--wizon-ai-space-unit) * 7);
  height: calc(var(--wizon-ai-space-unit) * 7);
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .chatgpt-recent-header-action:hover {
  background: var(--cg-hover);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-recent-header-action:focus-visible {
  outline: 1px solid var(--cg-focus-visible-ring);
  outline-offset: -1px;
  background: var(--cg-focus-bg);
}

.chatgpt-reference-v1 .chatgpt-recent-header-action svg {
  width: 18px;
  height: 18px;
}

.chatgpt-reference-v1 .recent-list {
  /* 20260705-recent-row-token-contract: keep measured ChatGPT row geometry, but resolve every value through AI shell/WDS tokens. */
  --chatgpt-recent-row-height: var(--cg-sidebar-item-height);
  --chatgpt-recent-row-inner-height: calc(var(--chatgpt-recent-row-height) - (var(--wizon-ai-space-unit) / 2));
  --chatgpt-recent-row-radius: var(--wizon-ai-radius-control);
  --chatgpt-recent-row-pad-block: calc(var(--wizon-ai-space-unit) / 4);
  --chatgpt-recent-row-pad-right: var(--wizon-ai-space-unit);
  --chatgpt-recent-title-pad-left: calc(var(--wizon-ai-space-unit) * 2.5);
  --chatgpt-recent-action-size: calc(var(--wizon-ai-space-unit) * 7);
  --chatgpt-recent-action-offset: calc(var(--wizon-ai-space-unit) / 2);
  --chatgpt-recent-action-fade: var(--ds-space-6, 24px);
  --chatgpt-recent-title-pad-right: calc((var(--chatgpt-recent-action-size) * 2) + var(--chatgpt-recent-action-fade) + var(--wizon-ai-space-unit));
  --chatgpt-recent-font-size: var(--wds-font-size-body-2);
  --chatgpt-recent-line-height: calc(var(--wizon-ai-space-unit) * 5);
  --chatgpt-recent-rename-pad-x: calc(var(--wizon-ai-space-unit) * 1.5);
  --chatgpt-recent-rename-radius: calc(var(--chatgpt-recent-row-radius) - (var(--wizon-ai-space-unit) / 2));
  --chatgpt-recent-select-indent: calc(var(--wizon-ai-space-unit) * 8.5);
  display: block;
  gap: calc(var(--wizon-ai-space-unit) / 2);
  flex: 0 1 auto;
  overflow-x: hidden;
  overflow-y: auto;
}

body.chatgpt-reference-v1 .citation-impact-queue-entry {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto 16px;
  align-items: center;
  gap: 8px;
  width: calc(100% - 8px);
  margin: 2px 4px 8px;
  padding: 9px 10px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
  border-radius: var(--wizon-ai-radius-control);
  background: color-mix(in srgb, var(--ad-amber) 8%, var(--cg-sidebar-bg));
  color: var(--cg-text);
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .citation-impact-queue-entry[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .citation-impact-queue-entry:focus-visible {
  outline: 2px solid var(--cg-text);
  outline-offset: 2px;
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .citation-impact-queue-entry:hover {
    background: color-mix(in srgb, var(--ad-amber) 13%, var(--cg-sidebar-bg));
  }
}

.citation-impact-queue-entry__icon,
.citation-impact-queue-entry__icon svg,
.citation-impact-queue-entry > [data-icon="chevron-right"],
.citation-impact-queue-entry > [data-icon="chevron-right"] svg {
  width: 18px;
  height: 18px;
}

.citation-impact-queue-entry__copy {
  min-width: 0;
  display: grid;
  gap: 1px;
}

.citation-impact-queue-entry__copy strong,
.citation-impact-queue-entry__copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.citation-impact-queue-entry__copy strong {
  font-size: var(--ds-text-caption-13);
  line-height: 18px;
}

.citation-impact-queue-entry__copy small {
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
  line-height: 16px;
}

.citation-impact-queue-entry__badge {
  display: inline-grid;
  min-width: 20px;
  height: 20px;
  padding: 0 5px;
  place-items: center;
  border-radius: var(--ds-radius-pill);
  background: var(--ad-amber);
  color: var(--cg-send-fg);
  font-size: var(--ds-text-micro-11);
  font-weight: var(--wds-font-weight-semibold);
}

.citation-impact-queue-entry[data-status="error"] {
  background: color-mix(in srgb, var(--cg-danger-fg) 8%, var(--cg-sidebar-bg));
}

.chatgpt-reference-v1 .recent-item {
  position: relative;
  display: block;
  width: 100%;
  overflow: hidden;
  min-height: var(--chatgpt-recent-row-height);
  padding: var(--chatgpt-recent-row-pad-block) var(--chatgpt-recent-row-pad-right) var(--chatgpt-recent-row-pad-block) 0;
  border: 0;
  border-radius: var(--chatgpt-recent-row-radius);
  color: var(--cg-text);
  font-size: var(--chatgpt-recent-font-size);
}

/* Guard the hover background behind @media (hover: hover): on iOS Safari a :hover rule on
   a tappable row makes the FIRST tap a hover-only gesture (the click is swallowed, so the
   row highlights but does not open — a second tap is needed). Touch devices must not have
   :hover styling on the recent rows (20260709-mobile-recent-hover-firsttap, doc 143). */
@media (hover: hover) {
  .chatgpt-reference-v1 .recent-item:hover {
    background: var(--cg-hover);
  }
}

.chatgpt-reference-v1 .recent-item:has([data-recent-action="more"][aria-expanded="true"]) {
  background: var(--cg-sidebar-active-bg);
}

.chatgpt-reference-v1 .recent-primary {
  display: grid;
  width: 100%;
  min-height: var(--chatgpt-recent-row-inner-height);
  padding: 0 var(--chatgpt-recent-title-pad-right) 0 var(--chatgpt-recent-title-pad-left);
  border-radius: var(--chatgpt-recent-row-radius);
  color: var(--cg-text);
  font-size: var(--chatgpt-recent-font-size);
  font-weight: 400;
  line-height: var(--chatgpt-recent-line-height);
  /* Removes the 300ms tap delay and the extra hover-tap on touch, so a single tap opens
     the chat (iOS double-tap mitigation; recommended alongside the @media hover guards). */
  touch-action: manipulation;
}

.chatgpt-reference-v1 .recent-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .recent-primary small {
  display: none;
}

.chatgpt-reference-v1 .recent-rename-form {
  display: grid;
  align-items: center;
  width: 100%;
  min-height: var(--chatgpt-recent-row-inner-height);
  padding: 0 calc(var(--wizon-ai-space-unit) * 2);
}

.chatgpt-reference-v1 .recent-rename-input {
  width: 100%;
  height: var(--chatgpt-recent-action-size);
  min-width: 0;
  padding: 0 var(--chatgpt-recent-rename-pad-x);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-recent-rename-radius);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--chatgpt-recent-font-size);
  font-weight: 400;
  line-height: var(--chatgpt-recent-line-height);
  outline: none;
}

.chatgpt-reference-v1 .recent-rename-input:focus,
.chatgpt-reference-v1 .recent-rename-input:focus-visible {
  border-color: var(--cg-muted-2);
  box-shadow: none;
  outline: none;
}

html[data-theme="dark"] .chatgpt-reference-v1 .recent-rename-input {
  border-color: var(--cg-menu-border);
  background: var(--cg-hover);
  color: var(--cg-text);
}

html[data-theme="dark"] .chatgpt-reference-v1 .recent-rename-input:focus,
html[data-theme="dark"] .chatgpt-reference-v1 .recent-rename-input:focus-visible {
  border-color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .recent-actions {
  display: inline-flex;
  position: absolute;
  top: 50%;
  right: var(--chatgpt-recent-action-offset);
  transform: translateY(-50%);
  gap: 0;
  padding-left: var(--chatgpt-recent-action-fade);
  padding-right: 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--cg-hover) 0%, transparent), var(--cg-hover) var(--chatgpt-recent-action-fade));
}

.chatgpt-reference-v1 .recent-item:has([data-recent-action="more"][aria-expanded="true"]) .recent-actions {
  opacity: 1;
  pointer-events: auto;
}

/* Reveal the row actions on focus (tap) or when the row's ⋯ menu is open. The :hover
   reveal is gated behind @media (hover: hover) on purpose: on iOS Safari, tapping an
   element whose :hover reveals content makes the FIRST tap a hover-only gesture (the
   click is swallowed, so the row highlights but does not open — a second tap is needed).
   Touch devices therefore must not depend on :hover for this reveal (doc 143 item C fix,
   20260709-mobile-recent-hover-firsttap). */
.chatgpt-reference-v1 .recent-item:focus-within .recent-actions {
  opacity: 1;
  pointer-events: auto;
}

@media (hover: hover) {
  .chatgpt-reference-v1 .recent-item:hover .recent-actions {
    opacity: 1;
    pointer-events: auto;
  }
}

.chatgpt-reference-v1 .recent-action {
  width: var(--chatgpt-recent-action-size);
  height: var(--chatgpt-recent-action-size);
  color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .recent-item:focus-within .recent-action,
.chatgpt-reference-v1 .recent-item:has([data-recent-action="more"][aria-expanded="true"]) .recent-action {
  pointer-events: auto;
}

@media (hover: hover) {
  .chatgpt-reference-v1 .recent-item:hover .recent-action {
    pointer-events: auto;
  }
}

.chatgpt-reference-v1 .recent-action:hover {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .recent-pin-action.is-pinned {
  color: var(--cg-text);
}

.chatgpt-reference-v1 .recent-action svg {
  width: 17px;
  height: 17px;
}

.chatgpt-reference-v1 .recent-item.is-selecting .recent-primary {
  padding-left: var(--chatgpt-recent-select-indent);
}

.chatgpt-reference-v1 .recent-item.is-selected {
  background: var(--cg-hover);
}

.chatgpt-reference-v1 .recent-select-control {
  position: absolute;
  top: 50%;
  left: 6px;
  z-index: 2;
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  transform: translateY(-50%);
  cursor: pointer;
}

.chatgpt-reference-v1 .recent-select-control input {
  position: absolute;
  inset: 0;
  opacity: 0;
  z-index: 1;
  pointer-events: none;
  cursor: pointer;
}

.chatgpt-reference-v1 .recent-select-box {
  display: inline-grid;
  place-items: center;
  width: 17px;
  height: 17px;
  border: 1.5px solid var(--cg-muted-2);
  border-radius: 5px;
  background: var(--cg-surface);
  color: var(--cg-text);
  pointer-events: none;
}

.chatgpt-reference-v1 .recent-select-control.is-focused .recent-select-box,
.chatgpt-reference-v1 .recent-select-control input:focus + .recent-select-box,
.chatgpt-reference-v1 .recent-select-control input:focus-visible + .recent-select-box {
  outline: 1px solid var(--cg-focus-visible-ring);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--cg-focus-bg);
}

.chatgpt-reference-v1 .recent-select-control input:checked + .recent-select-box {
  border-color: var(--cg-send-bg);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

.chatgpt-reference-v1 .recent-select-box svg {
  width: 13px;
  height: 13px;
  stroke-width: 2.4;
}

.chatgpt-reference-v1 .chatgpt-recent-menu {
  --chatgpt-recent-menu-width: calc(var(--wizon-ai-space-unit) * 46.5);
  --chatgpt-recent-menu-gutter: var(--cg-menu-gutter);
  --chatgpt-recent-menu-radius: var(--wizon-ai-radius-popover);
  --chatgpt-recent-menu-row-gap: var(--cg-menu-gutter);
  --chatgpt-recent-menu-row-height: var(--wizon-ai-menu-row-height);
  --chatgpt-recent-menu-row-radius: var(--wizon-ai-radius-menu-row);
  --chatgpt-recent-menu-row-pad-y: var(--cg-menu-gutter);
  --chatgpt-recent-menu-row-pad-left: calc(var(--wizon-ai-space-unit) * 2.5);
  --chatgpt-recent-menu-row-pad-right: var(--ds-space-7, 32px);
  --chatgpt-recent-menu-row-font-size: var(--wds-font-size-body-2);
  --chatgpt-recent-menu-row-line-height: calc(var(--wizon-ai-space-unit) * 5);
  --chatgpt-recent-menu-icon-size: calc(var(--wizon-ai-space-unit) * 4.5);
  --chatgpt-recent-menu-fallback-left: calc(100% - (var(--chatgpt-recent-menu-width) + var(--wizon-ai-space-unit)));
  position: absolute;
  top: var(--recent-menu-top, var(--cg-sidebar-item-height));
  left: var(--recent-menu-left, var(--chatgpt-recent-menu-fallback-left));
  right: auto;
  z-index: var(--wizon-ai-popover-z, 20);
  display: grid;
  width: var(--chatgpt-recent-menu-width);
  max-height: var(--recent-menu-max-height, min(calc(var(--wizon-ai-space-unit) * 90), calc(100vh - var(--ds-space-6, 24px))));
  overflow-y: auto;
  padding: var(--chatgpt-recent-menu-gutter) 0;
  border: 0;
  border-radius: var(--chatgpt-recent-menu-radius);
  background: var(--cg-menu-bg);
  box-shadow: var(--cg-menu-shadow);
}

.chatgpt-reference-v1 .chatgpt-recent-menu[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-recent-menu button {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-recent-menu-row-gap);
  width: calc(var(--chatgpt-recent-menu-width) - (var(--chatgpt-recent-menu-gutter) * 2));
  min-height: var(--chatgpt-recent-menu-row-height);
  margin: 0 var(--chatgpt-recent-menu-gutter);
  padding: var(--chatgpt-recent-menu-row-pad-y) var(--chatgpt-recent-menu-row-pad-right) var(--chatgpt-recent-menu-row-pad-y) var(--chatgpt-recent-menu-row-pad-left);
  border: 0;
  border-radius: var(--chatgpt-recent-menu-row-radius);
  background: transparent;
  color: var(--cg-text);
  font-size: var(--chatgpt-recent-menu-row-font-size);
  font-weight: 400;
  line-height: var(--chatgpt-recent-menu-row-line-height);
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-recent-menu button[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-recent-menu button:hover:not(:disabled) {
  background: var(--cg-hover);
}

.chatgpt-reference-v1 .chatgpt-recent-menu button:disabled {
  color: var(--cg-muted-2);
  cursor: default;
}

.chatgpt-reference-v1 .chatgpt-recent-menu [data-recent-menu-action^="delete"] {
  color: var(--cg-danger-fg);
}

.chatgpt-reference-v1 .chatgpt-recent-menu svg {
  width: var(--chatgpt-recent-menu-icon-size);
  height: var(--chatgpt-recent-menu-icon-size);
}

.chatgpt-reference-v1 .main-pane,
.chatgpt-reference-v1 .workbench,
.chatgpt-reference-v1 .chat-pane {
  background: #ffffff;
}

.chatgpt-reference-v1 .workspace-hero,
.chatgpt-reference-v1 .context-pane {
  display: none;
}

.chatgpt-reference-v1 .workbench {
  grid-template-columns: minmax(0, 1fr);
}

.chatgpt-reference-v1 .chat-pane {
  grid-template-rows: minmax(0, 1fr) auto;
  min-height: 100vh;
}

.chatgpt-reference-v1 .message-list {
  align-items: stretch;
  width: min(768px, calc(100% - 48px));
  width: min(calc(var(--cg-chat-max-width) - (var(--cg-thread-gutter) * 2)), calc(100% - (var(--cg-thread-gutter) * 3)));
  margin: 0 auto;
  padding: 32px 0 24px;
}

.chatgpt-reference-v1 .message {
  width: 100%;
}

.chatgpt-reference-v1 .message.assistant .message-body,
.chatgpt-reference-v1 .message.system .message-body {
  padding: 10px 0;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .message.user .message-body {
  max-width: min(620px, 78%);
  padding: 10px 16px;
  border: 0;
  border-radius: var(--ds-radius-xl, 22px);
  background: #f4f4f4;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-empty-home {
  display: grid;
  gap: 0;
  width: 100%;
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-home-title {
  display: inline-flex;
  align-items: baseline;
  justify-content: normal;
  justify-self: center;
  width: auto;
  min-height: 42px;
  margin: 0;
  color: var(--cg-text);
  font-size: 24px;
  /* ⓐ 홈 제목이 본문과 같은 굵기(400)라 위계가 없었다. 제목·칩3·컴포저가 함께 있어
     요소는 더 많은데 위계는 더 약한 상태였다(2026-08-02 실측). 크기는 24px 유지 —
     굵기만으로 초점을 세운다. */
  font-weight: var(--wds-font-weight-semibold);
  line-height: 28px;
}

.chatgpt-reference-v1 .chatgpt-prompt-shelf {
  justify-content: center;
  gap: 8px;
  margin-top: 0;
}

.chatgpt-reference-v1 .prompt-chip {
  min-height: 40px;
  padding: 0 15px;
  border: 0 solid rgba(0, 0, 0, 0.05);
  border-radius: var(--ds-radius-pill, 999px);
  background: #ffffff;
  color: #3f3f3f;
  font-size: var(--ds-text-body-14);
  font-weight: 400;
}

.chatgpt-reference-v1 .prompt-chip:hover {
  border-color: #d9d9d9;
  background: #f7f7f7;
}

.chatgpt-reference-v1 .chatgpt-composer-shell,
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
  display: grid;
  width: min(768px, calc(100% - 48px));
  width: min(calc(var(--cg-chat-max-width) - (var(--cg-thread-gutter) * 2)), calc(100% - (var(--cg-thread-gutter) * 3)));
  min-height: 52px;
  margin: 0 auto 28px;
  padding: 5px 8px;
  gap: 0;
  grid-template-rows: auto auto;
  border: 0 solid rgba(0, 0, 0, 0.05);
  border-radius: var(--ds-radius-2xl, 28px);
  border-radius: calc(var(--cg-composer-radius) + (var(--cg-composer-compact-gutter) / 2));
  background: #ffffff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04), 0 2px 8px rgba(0, 0, 0, 0.04), 0 4px 80px 8px rgba(0, 0, 0, 0.024);
}

.chatgpt-reference-v1 .composer-attachment-lane {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
  padding: 0 4px 6px 44px;
}

.chatgpt-reference-v1 .composer-attachment-lane[hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-attachment-status {
  min-width: 0;
  padding: 2px 8px 5px 44px;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12);
  line-height: 16px;
}

.chatgpt-reference-v1 .composer-attachment-status[hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-attachment-status[data-tone="success"] {
  color: var(--ad-green, var(--wds-green-700, #15803d));
}

.chatgpt-reference-v1 .composer-attachment-status[data-tone="error"] {
  color: var(--cg-danger-fg, var(--wds-red-700, #b42318));
}

.chatgpt-reference-v1 .composer-attachment-status[data-tone="warning"] {
  color: var(--cg-warning-fg);
}

.chatgpt-reference-v1 .composer-chip-removable {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 26px;
  max-width: min(420px, 100%);
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 5px 5px 5px 7px;
  border: 1px solid #e7e7e7;
  border-radius: 13px;
  background: #f7f7f7;
  color: #2f2f2f;
  font: inherit;
  font-size: var(--ds-text-caption-13);
  line-height: 16px;
  cursor: default;
}

.chatgpt-reference-v1 .composer-attachment-file-icon {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  overflow: hidden;
  background: var(--cg-surface);
  color: var(--ad-blue, var(--wds-brand-blue, #155eef));
  box-shadow: inset 0 0 0 1px var(--cg-menu-border);
}

.chatgpt-reference-v1 .composer-attachment-file-icon svg {
  width: 19px;
  height: 19px;
}

.chatgpt-reference-v1 .composer-attachment-art {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  user-select: none;
}

.chatgpt-reference-v1 .composer-attachment-copy {
  display: grid;
  min-width: 0;
  gap: 1px;
}

.chatgpt-reference-v1 .composer-attachment-type {
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12);
  line-height: 14px;
}

.chatgpt-reference-v1 .composer-chip-label {
  overflow: hidden;
  min-width: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .composer-chip-remove {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: transparent;
  color: #6f6f6f;
  cursor: pointer;
}

.chatgpt-reference-v1 .composer-chip-remove svg {
  width: 14px;
  height: 14px;
}

.chatgpt-reference-v1 .composer-chip-removable:hover {
  border-color: #d9d9d9;
  background: #efefef;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .composer-chip-remove:hover {
  background: rgba(0, 0, 0, 0.06);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .composer-chip-remove:focus-visible {
  outline: 1px solid var(--cg-focus-visible-ring, var(--cg-focus-ring, #8b5cf6));
  outline-offset: 2px;
}

html[data-theme="dark"] .chatgpt-reference-v1 .composer-chip-removable {
  border-color: rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.08);
  color: var(--cg-text, #ececec);
}

html[data-theme="dark"] .chatgpt-reference-v1 .composer-chip-remove {
  color: var(--cg-muted, #b4b4b4);
}

html[data-theme="dark"] .chatgpt-reference-v1 .composer-chip-removable:hover {
  border-color: rgba(255, 255, 255, 0.2);
  background: rgba(255, 255, 255, 0.12);
  color: var(--cg-text, #f4f4f4);
}

html[data-theme="dark"] .chatgpt-reference-v1 .composer-chip-remove:hover {
  background: rgba(255, 255, 255, 0.12);
  color: var(--cg-text, #f4f4f4);
}

.composer-drop-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--wizon-layer-scrim, 190);
  display: grid;
  place-items: center;
  padding: 32px;
  pointer-events: none;
  background: color-mix(in srgb, var(--wizon-ai-surface, #fff) 82%, transparent);
  backdrop-filter: blur(4px);
}

.composer-drop-overlay[hidden] {
  display: none;
}

.composer-drop-overlay-panel {
  display: grid;
  place-items: center;
  width: min(560px, calc(100vw - 48px));
  min-height: 240px;
  padding: 32px;
  border: 2px dashed var(--ad-blue, var(--wds-brand-blue, #155eef));
  border-radius: var(--ds-radius-lg, 24px);
  background: var(--wizon-ai-surface, #fff);
  color: var(--cg-text, #2f2f2f);
  box-shadow: var(--ds-shadow-lg, 0 24px 64px rgba(15, 23, 42, 0.16));
  text-align: center;
}

.composer-drop-overlay-panel strong {
  margin-top: 16px;
  font-size: var(--ds-text-title-20, 20px);
  line-height: 28px;
}

.composer-drop-overlay-panel > span:last-child {
  margin-top: 6px;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-body-14);
}

.composer-drop-overlay-icon {
  display: inline-grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 16px;
  background: var(--ad-blue-tint, color-mix(in srgb, var(--wds-blue-500, #3c8ffd) 11%, #fff));
  color: var(--ad-blue, var(--wds-brand-blue, #155eef));
}

.composer-drop-overlay-icon svg {
  width: 26px;
  height: 26px;
}

@media (max-width: 520px) {
  .composer-drop-overlay {
    padding: 20px;
  }

  .composer-drop-overlay-panel {
    width: 100%;
    min-height: 200px;
    padding: 24px;
  }

  .chatgpt-reference-v1 .composer-chip-removable {
    max-width: 100%;
  }
}

.chatgpt-reference-v1 .composer-prompt-body {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  grid-template-rows: minmax(42px, auto);
  grid-template-areas: "lead input actions";
  align-items: center;
  gap: 0 8px;
}

.chatgpt-reference-v1 .composer-leading-action {
  grid-area: lead;
}

.chatgpt-reference-v1 .composer-textarea-scroll {
  grid-area: input;
  display: block;
  min-width: 0;
  max-height: 256px;
  overflow-x: hidden;
  overflow-y: hidden;
  scrollbar-width: thin;
}

.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) .composer-prompt-body {
  min-height: 42px;
  margin-block: 0;
}

.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) textarea {
  min-height: 26px;
  height: 26px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) .composer-textarea-scroll {
  align-self: center;
  display: flex;
  align-items: center;
}

.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) textarea {
  align-self: center;
}

.chatgpt-reference-v1 .composer-surface textarea {
  display: block;
  flex: 0 0 auto;
  width: 100%;
  min-height: 42px;
  max-height: 256px;
  box-sizing: border-box;
  padding: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-body-16);
  line-height: 26px;
  overflow: hidden;
  resize: none;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline textarea {
  padding: 16px 0 16px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline,
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-multiline {
  min-height: min(300px, calc(var(--composer-visible-input-height, 42px) + 44px));
  max-height: 300px;
  padding: 9px 8px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-prompt-body {
  grid-template-rows: minmax(0, auto) 36px;
  grid-template-areas:
    "input input input"
    "lead spacer actions";
  align-items: end;
  margin: -10px 0 0;
  padding: 0 10px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-textarea-scroll {
  max-height: 256px;
  overflow-y: hidden;
}

/* 20260704-composer-empty-placeholder-guard: keep an empty placeholder in the one-line ChatGPT layout even if a stale multiline state is present. */
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty,
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-multiline.is-empty,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown),
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) {
  min-height: 52px;
  max-height: 52px;
  padding: 5px 8px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-prompt-body,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto;
  grid-template-rows: minmax(42px, auto);
  grid-template-areas: "lead input actions";
  align-items: center;
  min-height: 42px;
  padding: 0;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty textarea,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) textarea {
  min-height: 26px !important;
  height: 26px !important;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-textarea-scroll {
  align-self: center;
  display: flex;
  align-items: center;
  overflow-y: hidden;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty textarea,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) textarea {
  align-self: center;
  padding: 0;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-leading-action,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-action-dock,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-leading-action,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-action-dock {
  align-self: center;
}

/* 20260704-composer-empty-inline-height-guard: an empty ChatGPT composer must snap back to the one-line optical center even if a stale inline textarea height remains. */
.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) {
  min-height: 52px;
  max-height: 52px;
  padding: 5px 8px;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto;
  grid-template-rows: minmax(42px, auto);
  grid-template-areas: "lead input actions";
  align-items: center;
  min-height: 42px;
  padding: 0;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea {
  min-height: 26px !important;
  height: 26px !important;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll {
  align-self: center;
  display: flex;
  align-items: center;
  overflow-y: hidden;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-leading-action,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-action-dock,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-leading-action,
.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-action-dock {
  align-self: center;
}

body.chatgpt-reference-v1 .composer-textarea-scroll:focus-within {
  outline: none;
  box-shadow: none;
}

body.chatgpt-reference-v1 .composer-textarea-scroll.is-scrollable textarea {
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
}

.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-leading-action,
.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-action-dock {
  align-self: end;
}

.chatgpt-reference-v1 .composer-surface textarea::placeholder {
  color: #8a8a8a;
}

.chatgpt-reference-v1 .composer-icon-button {
  display: inline-grid;
  place-items: center;
  width: 36px;
  height: 36px;
  min-width: 36px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: transparent;
  color: var(--cg-text);
  font-size: 24px;
  font-weight: 300;
}

.chatgpt-reference-v1 .composer-icon-button svg,
.chatgpt-reference-v1 .wds-inline-icon {
  /* 20260710-icon-size-tokens (아트디렉션 P0-4): 기본 아이콘 크기를 WDS 토큰으로 (md=1.25rem=20px 동일값). */
  width: var(--wds-icon-size-md, 20px);
  height: var(--wds-icon-size-md, 20px);
  fill: none;
  stroke: currentColor;
  stroke-width: var(--wds-icon-stroke, 1.7);
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ===== 아트디렉션 v2 (doc 161, 사용자 승인 목업) =====
   기능색 4축: Blue 정보·모델·문서 / Green 완료 / Amber 주의·전환 / Violet AI·요약.
   값은 전부 WDS 팔레트 토큰에서 파생(raw hex는 토큰 폴백만) — 장식 금지, 의미 있을 때만.
   원시 데이터 격리: 파일명·ms·모델ID는 1차 표면 노출 금지(확장자 칩·초 단위·표시 라벨만). */
:root {
  --ad-blue: var(--wds-brand-blue, #155eef);
  --ad-green: var(--wds-green-700, #15803d);
  --ad-amber: var(--wds-amber-700, #b45309);
  --ad-violet: var(--wds-violet-600, #6938ef);
  /* 틴트는 현재 서피스와 섞어 만들므로 라이트/다크 모두에서 자동으로 맞는 바닥색이 된다 */
  --ad-blue-tint: color-mix(in srgb, var(--wds-blue-500, #3c8ffd) 11%, var(--wizon-ai-surface, #fff));
  --ad-green-tint: color-mix(in srgb, var(--wds-green-600, #16a34a) 10%, var(--wizon-ai-surface, #fff));
  --ad-amber-tint: color-mix(in srgb, var(--wds-amber-500, #f59e0b) 13%, var(--wizon-ai-surface, #fff));
  --ad-violet-tint: color-mix(in srgb, var(--wds-violet-500, #7c5cfc) 11%, var(--wizon-ai-surface, #fff));
}
/* 다크에서는 본색을 밝은 변형으로 (700 계열은 다크 바닥에서 대비 부족) */
html[data-theme="dark"] {
  --ad-blue: var(--wds-blue-400, #66aaff);
  --ad-green: var(--wds-green-400, #4ade80);
  --ad-amber: var(--wds-amber-400, #fbbf24);
  --ad-violet: var(--wds-violet-500, #7c5cfc);
}

/* 의미 아이콘 틴트 칩 — 내비/액션 아이콘은 무채색 유지, 색은 "의미" 전용 */
.md-chip {
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 7px;
}
.md-chip--sm {
  width: 20px;
  height: 20px;
  border-radius: var(--ds-radius-xs, 6px);
}
.md-chip[data-tone] .wds-inline-icon {
  width: 14px;
  height: 14px;
}
.md-chip--sm[data-tone] .wds-inline-icon {
  width: 12px;
  height: 12px;
}
.md-chip[data-tone="blue"] { background: var(--ad-blue-tint); color: var(--ad-blue); }
.md-chip[data-tone="green"] { background: var(--ad-green-tint); color: var(--ad-green); }
.md-chip[data-tone="amber"] { background: var(--ad-amber-tint); color: var(--ad-amber); }
.md-chip[data-tone="violet"] { background: var(--ad-violet-tint); color: var(--ad-violet); }

/* 콜아웃 톤 스킨 (기본 형태는 .md-callout 기존 규칙, 여기서 의미색만 입힘) */
.md-callout[data-callout="summary"] {
  border-color: color-mix(in srgb, var(--ad-violet) 16%, transparent);
  background: var(--ad-violet-tint);
}
.md-callout[data-callout="summary"] .md-callout-head { color: var(--ad-violet); }
.md-callout[data-callout="warning"] {
  border-color: color-mix(in srgb, var(--ad-amber) 22%, transparent);
  background: var(--ad-amber-tint);
}
.md-callout[data-callout="warning"] .md-callout-head { color: var(--ad-amber); }
.md-callout[data-callout="note"] {
  border-color: color-mix(in srgb, var(--ad-blue) 14%, transparent);
  background: var(--ad-blue-tint);
}
.md-callout[data-callout="note"] .md-callout-head { color: var(--ad-blue); }

/* 본문 문서 출처 태그의 아이콘: 블루 틴트 사각 (파비콘과 같은 14px 슬롯) */
.citation-tag .citation-tag-doc {
  display: inline-grid;
  place-items: center;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  background: var(--ad-blue-tint);
  color: var(--ad-blue);
}
.citation-tag .citation-tag-doc .wds-inline-icon {
  width: 10px;
  height: 10px;
}

/* 문서 확장자 칩 (처리 과정 탭 · 원시 파일명 격리) */
.source-ext-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  border: 1px solid color-mix(in srgb, var(--ad-blue) 16%, transparent);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--ad-blue-tint);
  color: var(--ad-blue);
  font: inherit;
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  letter-spacing: 0.03em;
  line-height: 1.5;
  cursor: pointer;
  transition: border-color var(--wds-duration-fast) ease;
}
.source-ext-chip .wds-inline-icon {
  width: 12px;
  height: 12px;
  flex: none;
}
.source-ext-chip:hover {
  border-color: color-mix(in srgb, var(--ad-blue) 38%, transparent);
}
.source-ext-chip:focus-visible {
  outline: 2px solid var(--cg-text, #0d0d0d);
  outline-offset: 1px;
}
.source-ext-more {
  align-self: center;
  color: var(--cg-muted, var(--muted));
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}

/* 출처 카드 v2 (아트디렉션 §4): 파비콘+사이트명 헤더 / 제목 2줄 / 스니펫 2줄.
   번호 배지 → 우측 뮤트 인덱스, 선택 = 블루 링 + "인용됨". 드로어·신뢰 패널 공용. */
.source-card-v2 {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 13px;
  box-shadow: 0 1px 2px rgba(16, 16, 20, 0.04);
  transition: box-shadow var(--wds-duration-fast) ease, background var(--wds-duration-fast) ease;
}
.source-card-v2:hover {
  box-shadow: 0 1px 2px rgba(16, 16, 20, 0.05), 0 4px 14px rgba(16, 16, 20, 0.05);
}
.source-card-head-v2 {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.source-ext-chip--static {
  cursor: default;
}
/* 표준 출처 태그 원자 (doc 161 §8): 파비콘 + 이름. 카드 v2 헤더와 뉴스 피드 kicker가 이 한
   컴포넌트를 공유 — 답변의 모든 웹 출처 표식이 동일하게 읽힌다. .news-fav가 파비콘 베이스. */
.source-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.source-tag-fav {
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 4px; /* matches the .news-fav favicon box these tags share */
}
.source-tag-name {
  overflow: hidden;
  min-width: 0;
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.source-card-cited {
  display: none;
  flex: none;
  margin-left: auto;
  align-items: center;
  gap: 4px;
  color: var(--ad-blue);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}
.source-card-cited .wds-inline-icon {
  width: 11px;
  height: 11px;
}
.source-card-v2.is-selected .source-card-cited {
  display: inline-flex;
}
.source-card-v2.is-selected {
  border-color: transparent;
  box-shadow: 0 0 0 2px var(--ad-blue), 0 4px 14px rgba(16, 16, 20, 0.06);
}
.source-card-v2.is-highlighted {
  box-shadow: 0 0 0 2px var(--ad-blue), 0 0 0 6px color-mix(in srgb, var(--ad-blue) 18%, transparent);
  transition: box-shadow 220ms ease;
}
.source-card-title-v2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  line-height: 1.45;
  letter-spacing: -0.01em;
  text-wrap: pretty;
}
.source-card-snippet-v2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--cg-muted, var(--muted));
  font-size: var(--ds-text-caption-12);
  line-height: 1.55;
}

.chatgpt-reference-v1 .composer-icon-button:hover {
  background: #f4f4f4;
}

.chatgpt-reference-v1 .composer-action-dock {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  grid-area: actions;
  grid-column: auto;
  justify-self: end;
  width: auto;
  min-height: 38px;
  gap: 6px;
  flex-wrap: nowrap;
}

.chatgpt-reference-v1 .composer-model-pill {
  display: inline-grid;
  grid-template-columns: auto 16px;
  align-items: center;
  column-gap: 3px;
  min-height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: #6f6f6f;
  font-size: var(--ds-text-caption-13);
  font-weight: 400;
  line-height: 20px;
  cursor: pointer;
}

.chatgpt-reference-v1 .composer-model-pill > span {
  display: inline-flex;
  align-items: center;
  min-height: 20px;
}

.chatgpt-reference-v1 .composer-model-pill:hover,
.chatgpt-reference-v1 .composer-model-pill[aria-expanded="true"] {
  background: #f4f4f4;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .composer-caret {
  justify-content: center;
}

.chatgpt-reference-v1 .composer-caret svg {
  width: 16px;
  height: 16px;
}

.chatgpt-reference-v1 .composer-send-button,
.chatgpt-reference-v1 #sendButton {
  width: 38px;
  height: 38px;
  min-width: 38px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: #0d0d0d;
  color: #ffffff;
  font-size: 22px;
  font-weight: 500;
}

.chatgpt-reference-v1 .composer-send-button:hover,
.chatgpt-reference-v1 #sendButton:hover {
  background: #000000;
}

.chatgpt-reference-v1 #sendButton:disabled {
  background: color-mix(in srgb, var(--ds-color-ink) 12%, var(--ds-color-surface));
  color: var(--ds-color-muted);
}

.chatgpt-reference-v1 .composer-send-button.composer-primary-disabled,
.chatgpt-reference-v1 #sendButton.composer-primary-disabled {
  background: color-mix(in srgb, var(--ds-color-ink) 12%, var(--ds-color-surface));
  color: var(--ds-color-muted);
  cursor: not-allowed;
}

.chatgpt-reference-v1 .composer-send-button.composer-primary-stop,
.chatgpt-reference-v1 #sendButton.composer-primary-stop {
  background: #0d0d0d;
  color: #ffffff;
  cursor: pointer;
}

.chatgpt-reference-v1 .composer-send-button.composer-primary-stop svg,
.chatgpt-reference-v1 #sendButton.composer-primary-stop svg {
  width: 18px;
  height: 18px;
}

.chatgpt-reference-v1 .composer-mic-button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.chatgpt-reference-v1 .composer-mic-button:disabled:hover {
  background: transparent;
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .chat-pane {
  grid-template-rows: minmax(0, 0.755fr) auto auto auto minmax(0, 1fr);
  min-height: 100vh;
  padding: 0;
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .message-list {
  grid-row: 2;
  justify-content: end;
  min-height: auto;
  overflow: visible;
  padding: 0;
  margin: 0 auto 14px;
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .chatgpt-composer-shell {
  grid-row: 3;
  margin: 0 auto;
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .chatgpt-prompt-shelf {
  grid-row: 4;
  display: flex;
  justify-content: center;
  gap: 8px;
  /* 20260704-empty-action-shelf-chatgpt: ChatGPT keeps the prompt chip shelf on the same 768px layout rail as the composer, then centers the chips inside it. */
  width: min(768px, calc(100% - 48px));
  margin: 24px auto 0;
}

/* 20260823-loading-chat-state: `loading` means "a thread is addressed and its messages have
   not arrived yet". It shares every rule below with `active` on purpose — the frame around a
   thread must not move when the messages land, and it must never be the centred new-chat home
   the shell used to assert before anything knew which screen this was. Rule: any selector that
   keys on [data-chat-state="active"] carries a "loading" sibling, pinned by
   tests/test_conversation_reload_flash.py. */
html[data-chat-state="active"] .chatgpt-reference-v1 .chatgpt-prompt-shelf,
html[data-chat-state="loading"] .chatgpt-reference-v1 .chatgpt-prompt-shelf,
.chatgpt-reference-v1 .chatgpt-prompt-shelf[hidden] {
  display: none;
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04);
}

.chatgpt-reference-v1.is-auth-gate .app-shell {
  background: #ffffff;
}

@media (max-width: 900px) {
  .chatgpt-reference-v1 .app-shell {
    grid-template-columns: 52px minmax(0, 1fr);
  }

  .chatgpt-reference-v1 .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 70;
    display: flex;
    width: min(260px, calc(100vw - 52px));
    box-shadow: var(--cg-menu-shadow);
  }

  .chatgpt-reference-v1:not(.sidebar-collapsed) .app-shell {
    grid-template-columns: 1fr;
  }

  .chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
    display: flex;
  }

  .chatgpt-reference-v1 .message-list,
  .chatgpt-reference-v1 .chatgpt-composer-shell,
  .chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
    width: min(100% - 24px, 768px);
  }

  .chatgpt-reference-v1 .chatgpt-home-title {
    font-size: 24px;
  }

  .chatgpt-reference-v1 .chatgpt-prompt-shelf {
    display: none;
  }

  .chatgpt-reference-v1 .composer-model-pill {
    display: inline-flex;
    max-width: 68px;
  }
}

/* 20260708-composer-mobile-two-row-v2: the actual two-row reflow lives at the end of this file (search "20260708-composer-mobile-two-row-v2") so it can beat the higher-specificity single-row empty-state rules (styles.css:7071,7120,11772,11823) with matching-specificity + !important + later source order. */

/* WDS AI guideline detail pass: ComposerBar menus, modes, and MessageActions. */
.chatgpt-reference-v1 .chatgpt-composer-shell {
  position: relative;
}

.chatgpt-reference-v1 .composer-mode-slot {
  display: inline-flex;
  min-width: 0;
  margin: 0 0 6px;
}

.chatgpt-reference-v1 .composer-mode-slot[hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-action-dock {
  grid-area: actions;
}

.chatgpt-reference-v1 .composer-mode-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 210px;
  min-height: 32px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: #f4f4f4;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  white-space: nowrap;
  cursor: pointer;
}

.chatgpt-reference-v1 .composer-mode-chip span:not(.composer-mode-icon):not(.composer-mode-remove) {
  overflow: hidden;
  text-overflow: ellipsis;
}

.chatgpt-reference-v1 .composer-mode-icon,
.chatgpt-reference-v1 .composer-mode-remove {
  display: inline-grid;
  place-items: center;
  color: #5f6368;
}

.chatgpt-reference-v1 .composer-popover,
.chatgpt-reference-v1 .reasoning-popover {
  position: absolute;
  z-index: 60;
  top: calc(100% + 8px);
  bottom: auto;
  display: grid;
  min-width: 260px;
  padding: 6px;
  border: 1px solid #e3e3e3;
  border-radius: 16px;
  background: #ffffff;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.14), 0 4px 14px rgba(0, 0, 0, 0.08);
}

.chatgpt-reference-v1 .composer-popover[hidden],
.chatgpt-reference-v1 .reasoning-popover[hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-popover {
  left: var(--composer-menu-left, 0);
  top: var(--composer-menu-top, calc(100% + 8px));
  bottom: var(--composer-menu-bottom, auto);
  width: 100%;
  max-height: var(--composer-menu-max-height, min(264px, calc(100vh - 190px)));
  padding: 6px 0;
  border: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .composer-popover::-webkit-scrollbar {
  width: 10px;
}

.chatgpt-reference-v1 .reasoning-popover {
  left: var(--reasoning-menu-left, auto);
  right: var(--reasoning-menu-right, 62px);
  top: var(--reasoning-menu-top, calc(100% + 8px));
  bottom: var(--reasoning-menu-bottom, auto);
  width: 124px;
  min-width: 124px;
  max-height: var(--reasoning-menu-max-height, min(340px, calc(100vh - 16px)));
  padding: 6px 0;
  border: 0;
  border-radius: 16px;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .reasoning-model-menu {
  right: var(--reasoning-menu-right, -60px);
  width: 126px;
  min-width: 126px;
}

.chatgpt-reference-v1 .composer-menu-item,
.chatgpt-reference-v1 .reasoning-menu-item {
  display: grid;
  align-items: center;
  min-height: 36px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  text-align: left;
  cursor: pointer;
}

.chatgpt-reference-v1 [data-gpt-oss-runtime-restore][hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-menu-item {
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 10px;
  padding: 0 10px;
  margin: 0 6px;
}

.chatgpt-reference-v1 .reasoning-menu-item {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  width: 112px;
  min-height: 36px;
  margin: 0 6px;
  padding: 6px 10px;
  line-height: 20px;
}

.chatgpt-reference-v1 #reasoningModelMenu,
.chatgpt-reference-v1 #reasoningLevelMenu {
  width: 190px;
  min-width: 190px;
}

.chatgpt-reference-v1 #reasoningModelMenu .reasoning-menu-item,
.chatgpt-reference-v1 #reasoningLevelMenu .reasoning-menu-item {
  width: auto;
}

.chatgpt-reference-v1 .reasoning-model-group-title {
  margin: 6px 6px 2px;
  padding: 0 10px;
  color: #8a8a8a;
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  line-height: 16px;
}

.chatgpt-reference-v1 .reasoning-model-option.is-planned {
  cursor: default;
}

.chatgpt-reference-v1 .reasoning-model-option.is-planned > span:first-child {
  color: #8a8a8a;
}

.chatgpt-reference-v1 .reasoning-model-badge {
  flex: 0 0 auto;
  padding: 1px 8px;
  border-radius: var(--ds-radius-pill, 999px);
  background: #ececec;
  color: #5d5d5d;
  font-size: var(--ds-text-micro-11);
  line-height: 16px;
  white-space: nowrap;
}

/* Model labels and status badges vary by runtime state. Size the desktop popover to
   its widest row; JS supplies the measured width and clamps it to the viewport. */
.chatgpt-reference-v1 #reasoningModelMenu {
  width: var(--reasoning-menu-width, max-content);
  min-width: min(220px, calc(100vw - 16px));
  max-width: calc(100vw - 16px);
}

.chatgpt-reference-v1 #reasoningModelMenu .reasoning-menu-item {
  box-sizing: border-box;
  width: auto;
}

.chatgpt-reference-v1 #reasoningMenu {
  width: 210px;
  min-width: 210px;
}

.chatgpt-reference-v1 #reasoningMenu .reasoning-menu-item {
  width: auto;
}

.chatgpt-reference-v1 .reasoning-future-menu {
  width: 200px;
  padding: 12px;
}

.chatgpt-reference-v1 .reasoning-future-empty {
  margin: 0;
  font-size: var(--ds-text-body-14);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .reasoning-future-hint {
  margin: 4px 0 0;
  font-size: var(--ds-text-caption-12);
  line-height: 1.5;
  color: #8a8a8a;
}

.chatgpt-reference-v1 .reasoning-menu-item > span:first-child {
  white-space: nowrap;
}

.chatgpt-reference-v1 .composer-menu-copy {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: 12px;
}

.chatgpt-reference-v1 .composer-menu-copy strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  white-space: nowrap;
}

.chatgpt-reference-v1 .composer-menu-copy small {
  overflow: hidden;
  color: #8a8a8a;
  font-size: var(--ds-text-caption-13);
  font-weight: 400;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .composer-menu-item:hover,
.chatgpt-reference-v1 .reasoning-menu-item:hover {
  background: #f4f4f4;
}

/* 2026-08-01 (doc 345 §5): 「이미지 만들기」 아이콘만 핑크 #e83e9d 였다. 같은 메뉴의 다른
   아이콘 6개는 전부 잉크(#3f3f3f)라 하나만 튀었고, doc 221 W-1의 「색은 의미(액션·상태)에만」
   에도 어긋난다 — 메뉴 항목의 종류는 의미색이 아니다. ChatGPT도 이 자리 아이콘이 전부
   무채색이다. 규칙을 지우면 12655행의 --cg-text-soft 가 그대로 적용돼 형제와 같아진다.
   ★함께 지운 `color: #4b5563` 은 이미 죽은 선언이었다 — 12655행에 같은 선택자·같은
   특이도(0,2,0) 규칙이 뒤에 있어 그쪽이 이긴다(형제 실측이 #3f3f3f인 이유). display 와
   place-items 는 12655에 없으므로 여기 남긴다. */
.chatgpt-reference-v1 .composer-menu-icon,
.chatgpt-reference-v1 .composer-menu-chevron,
.chatgpt-reference-v1 .reasoning-check,
.chatgpt-reference-v1 .composer-menu-check {
  display: inline-grid;
  place-items: center;
}

.chatgpt-reference-v1 .composer-menu-dynamic {
  display: grid;
}

.chatgpt-reference-v1 .composer-menu-dynamic[hidden] {
  display: none;
}

.chatgpt-reference-v1 .composer-menu-inline-option {
  grid-template-columns: 28px minmax(0, 1fr) 20px;
}

.chatgpt-reference-v1 .composer-menu-app-glyph {
  width: 20px;
  height: 20px;
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
  line-height: 20px;
}

.chatgpt-reference-v1 .composer-menu-check {
  opacity: 0;
}

.chatgpt-reference-v1 .composer-menu-item.is-selected .composer-menu-check {
  opacity: 1;
}

.chatgpt-reference-v1 .composer-menu-divider {
  height: 1px;
  margin: 6px 0;
  background: #ececec;
}

.chatgpt-reference-v1 .reasoning-popover .composer-menu-divider {
  margin: 4px 0;
}

.chatgpt-reference-v1 .reasoning-menu-title {
  width: 112px;
  min-height: 36px;
  margin: 0 6px;
  padding: 8px 10px;
  color: rgb(143, 143, 143);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
  font-weight: 400;
}

.chatgpt-reference-v1 .reasoning-model-item {
  margin-top: 0;
}

html[data-chat-state="active"] .chatgpt-reference-v1 .composer-popover,
html[data-chat-state="loading"] .chatgpt-reference-v1 .composer-popover {
  top: var(--composer-menu-top, auto);
  bottom: var(--composer-menu-bottom, calc(100% + 10px));
}

/* The upward flip is for composer-anchored popovers only: with an active chat the
   composer sits at the bottom of the viewport, so its menus must open above it.
   The sidebar product selector borrows .reasoning-popover purely for the mobile
   top-layer sheet machinery, but it is anchored to the sidebar head at the very
   top of the page — flipping it put its bottom edge 10px ABOVE the sidebar, i.e.
   off-screen ("메뉴가 위로 펼쳐져 안 보임", intermittent because it only happens
   once a conversation is open). The desktop guard at
   `.chatgpt-product-mode-menu.reasoning-popover` ties this rule on specificity
   (0,3,1) and loses on source order, so exclude the selector explicitly here. */
html[data-chat-state="active"] .chatgpt-reference-v1 .reasoning-popover:not(.chatgpt-product-mode-menu),
html[data-chat-state="loading"] .chatgpt-reference-v1 .reasoning-popover:not(.chatgpt-product-mode-menu) {
  top: var(--reasoning-menu-top, auto);
  bottom: var(--reasoning-menu-bottom, calc(100% + 10px));
}

.chatgpt-reference-v1 .reasoning-menu-item .reasoning-check {
  opacity: 0;
}

.chatgpt-reference-v1 .reasoning-menu-item.is-selected .reasoning-check {
  opacity: 1;
}

.chatgpt-reference-v1 .message-actions {
  display: flex;
  align-items: center;
  gap: 0;
}

.chatgpt-reference-v1 .message-action-button,
.chatgpt-reference-v1 .feedback-row .message-action-button {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  min-width: 32px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: #4b5563;
  cursor: pointer;
}

.chatgpt-reference-v1 .message-action-button:hover {
  background: #f4f4f4;
  color: var(--cg-text);
}

/* 소리로 듣기 재생 중: 눌린(재생) 상태를 유지 표시 — 같은 버튼이 정지 토글이 된다. */
.chatgpt-reference-v1 .message-action-button.is-speaking {
  background: var(--cg-hover, #f4f4f4);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .feedback-row.message-actions {
  margin-top: 14px;
}

.wds-pattern-fidelity-v2 .context-pane {
  background: var(--ds-color-surface-solid);
  border-left: 1px solid var(--ds-color-line);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .tabs {
  gap: var(--ds-space-2);
  padding: var(--ds-space-3);
  background: var(--ds-color-surface-solid);
}

.wds-pattern-fidelity-v2 .tab-button {
  min-height: 32px;
  border-radius: var(--ds-radius-xs);
}

.wds-pattern-fidelity-v2 .panel-block,
.wds-pattern-fidelity-v2 .app-detail-panel,
.wds-pattern-fidelity-v2 .app-workflow-panel,
.wds-pattern-fidelity-v2 .app-input-fields,
.wds-pattern-fidelity-v2 .app-result-card,
.wds-pattern-fidelity-v2 .mini-card,
.wds-pattern-fidelity-v2 .app-card,
.wds-pattern-fidelity-v2 .artifact-studio,
.wds-pattern-fidelity-v2 .artifact-editor {
  border-color: var(--ds-card-border);
  border-radius: var(--ds-radius-sm);
  background: var(--ds-color-surface-solid);
  box-shadow: none;
}

.wds-pattern-fidelity-v2 .login-dialog {
  width: min(390px, calc(100vw - var(--wds-space-8, 2rem)));
  max-width: none;
  padding: 0;
  border: 0;
  background: transparent;
  box-shadow: none;
  outline: 0;
}

.wds-pattern-fidelity-v2 .login-dialog::backdrop {
  background: color-mix(in srgb, var(--wds-color-surface, var(--ds-color-bg)) 86%, transparent);
  backdrop-filter: blur(1px);
}

.wds-pattern-fidelity-v2 .login-service-badge .login-service-logo {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--wds-radius-full);
  background: var(--wds-color-surface-muted);
  color: var(--wds-color-text-muted);
  font-size: var(--wds-font-size-caption);
}

.wds-pattern-fidelity-v2 .login-surface ._brand_1p22z_32 {
  font-weight: var(--wds-font-weight-regular);
}

.wds-pattern-fidelity-v2 .login-service-name {
  display: inline;
  width: auto;
  height: auto;
  border-radius: 0;
  background: transparent;
  color: inherit;
  font-size: inherit;
  font-weight: var(--wds-font-weight-medium);
  line-height: inherit;
  white-space: nowrap;
}

.wds-pattern-fidelity-v2 .login-password-toggle {
  display: grid;
  place-items: center;
  width: var(--wds-control-height-sm);
  height: var(--wds-control-height-sm);
  border: 0;
  border-radius: var(--wds-button-radius);
  background: transparent;
  color: var(--wds-color-text-muted);
  cursor: pointer;
}

.wds-pattern-fidelity-v2 .login-password-toggle:hover {
  background: var(--wds-color-surface-hover);
  color: var(--wds-color-text);
}

.wds-pattern-fidelity-v2 .login-password-toggle:focus-visible {
  outline: 2px solid var(--wds-color-focus-ring);
  outline-offset: 2px;
}

.wds-pattern-fidelity-v2 .login-password-icon--eye-off,
.wds-pattern-fidelity-v2 .login-password-toggle[aria-pressed="true"] .login-password-icon--eye {
  display: none;
}

.wds-pattern-fidelity-v2 .login-password-toggle[aria-pressed="true"] .login-password-icon--eye-off {
  display: block;
}

.wds-pattern-fidelity-v2 .login-field-error {
  margin: 0;
}

.wds-pattern-fidelity-v2 .login-field-error:empty {
  display: none;
}

.wds-pattern-fidelity-v2 .login-surface ._label_2lf8x_7,
.wds-pattern-fidelity-v2 .login-surface ._root_1ergb_2,
.wds-pattern-fidelity-v2 .login-surface ._label_1ergb_100 {
  /* WDS Login art direction: avoid heavy text inside the auth surface. */
  font-weight: var(--wds-font-weight-regular);
}

.wds-pattern-fidelity-v2 .login-surface ._field_2lf8x_2 {
  display: flex;
  flex-direction: column;
  gap: var(--wds-space-2);
}

.wds-pattern-fidelity-v2 .login-surface ._label_2lf8x_7 {
  display: block;
  color: var(--wds-color-text);
  font-size: var(--wds-font-size-body-2);
  line-height: 1.4;
}

.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100,
.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:hover,
.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:focus,
.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:focus-visible {
  width: auto;
  min-width: 0;
  min-height: 0;
  height: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--wds-input-fg);
  box-shadow: none;
  outline: none;
  line-height: normal;
}

.wds-pattern-fidelity-v2 .login-surface ._root_1ergb_2 {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-2);
  color: var(--wds-color-text-muted);
  font-size: var(--wds-font-size-body-2);
  line-height: 1.4;
}

.wds-pattern-fidelity-v2 .login-surface ._label_1ergb_100 {
  color: var(--wds-color-text-muted);
  font-size: var(--wds-font-size-body-2);
  line-height: 1.4;
}

.wds-pattern-fidelity-v2 .login-options-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-3);
  min-height: var(--wds-control-height-md);
}

/* Invite-accept mode (portal-invite-accept-screen, app.js enterInviteAcceptMode()):
 * hides the username/current-password field rows and the remember-me/forgot-
 * password row when a `?invite_token=` deep link swaps the login form into
 * "set a password to accept the invite" mode, reusing #passwordChangeFields'
 * two fields instead. A bare [hidden] attribute is not enough here -- both
 * ._field_2lf8x_2 above and .login-options-row set display:flex with equal or
 * higher specificity than the UA [hidden] rule (author origin always beats
 * UA origin) -- so this follows the same explicit [hidden]-override
 * convention already used elsewhere in this file (e.g. .sidebar[hidden],
 * #trustPanel.chatgpt-route-page[hidden]).
 */
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._field_2lf8x_2[hidden] {
  display: none;
}

.wds-pattern-fidelity-v2 .login-options-row[hidden] {
  display: none;
}

.wds-pattern-fidelity-v2 .login-link-button,
.wds-pattern-fidelity-v2 .login-help-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--wds-control-height-md);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wds-color-primary-text);
  font: inherit;
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-regular);
  line-height: 1.4;
  text-decoration: none;
  cursor: pointer;
}

.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2 {
  font-weight: var(--wds-font-weight-medium);
}

.wds-pattern-fidelity-v2 .login-help {
  margin: 0;
}

.wds-pattern-fidelity-v2 .login-help span {
  color: var(--wds-color-primary-text);
  font-weight: var(--wds-font-weight-regular);
}

.wds-pattern-fidelity-v2 .login-form-message[data-empty="true"] {
  display: none;
}

/* P0-2: #loginError ships with the WDS FormMessage error variant class
 * (`_error_tqd1n_40`, see shared/wds/ui-web/styles.css) baked into its
 * markup for the common failure case. setLoginFormMessage() in app.js
 * toggles `data-variant` for success/info copy (reset mail sent, invite
 * accepted) — these two rules reuse the same WDS `*-text` ink tokens the
 * shared FormMessage success/info variants use (rather than inventing new
 * colors) and win on specificity (class+attribute vs. the single class
 * above), so a confirmation no longer reads as a red alert. */
.wds-pattern-fidelity-v2 .login-form-message[data-variant="success"] {
  color: var(--wds-color-success-text);
}
.wds-pattern-fidelity-v2 .login-form-message[data-variant="info"] {
  color: var(--wds-color-info-text);
}

.wds-pattern-fidelity-v2 .login-button-spinner[hidden] {
  display: none !important;
}

/* 20260705-login-ai-token-alignment: login keeps WDS structure, with product styling resolved through current AI shell tokens. */
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-dialog {
  --chatgpt-login-backdrop-bg: var(--wizon-ai-login-backdrop-bg);
  width: min(390px, calc(100vw - (var(--wizon-ai-thread-gutter, 16px) * 2)));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-dialog::backdrop {
  background: var(--chatgpt-login-backdrop-bg);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface {
  --chatgpt-login-surface-padding: var(--wizon-ai-login-surface-padding);
  --chatgpt-login-surface-gap: var(--wizon-ai-login-surface-gap);
  --chatgpt-login-header-gap: var(--wizon-ai-login-header-gap);
  --chatgpt-login-body-gap: var(--wizon-ai-login-body-gap);
  --chatgpt-login-actions-gap: var(--wizon-ai-login-actions-gap);
  --chatgpt-login-field-gap: var(--wizon-ai-login-field-gap);
  --chatgpt-login-surface-border: var(--wizon-ai-login-surface-border);
  --chatgpt-login-surface-shadow: var(--wizon-ai-login-surface-shadow);
  --chatgpt-login-link-fg: var(--cg-text, var(--wizon-ai-login-link-fg));
  --chatgpt-login-link-hover-fg: var(--cg-text, var(--wizon-ai-login-link-hover-fg));
  --chatgpt-login-help-label-fg: var(--cg-muted, var(--wizon-ai-login-help-label-fg));
  --chatgpt-login-link-font-size: var(--wizon-ai-login-link-font-size);
  --chatgpt-login-link-font-weight: var(--wizon-ai-login-link-font-weight);
  --chatgpt-login-link-line-height: var(--wizon-ai-login-link-line-height);
  --chatgpt-login-link-target-height: var(--wizon-ai-login-link-target-height);
  --chatgpt-login-link-row-gap: var(--wizon-ai-login-link-row-gap);
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-login-surface-gap);
  width: 100%;
  padding: var(--chatgpt-login-surface-padding);
  border: 1px solid var(--chatgpt-login-surface-border);
  border-radius: var(--wizon-ai-radius-popover, 16px);
  background: var(--cg-surface, var(--wizon-ai-surface, #ffffff));
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
  box-shadow: var(--chatgpt-login-surface-shadow);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-service-badge .login-service-logo {
  border-radius: var(--wizon-ai-radius-pill, 999px);
  background: var(--cg-hover-soft, var(--wizon-ai-hover-soft-bg, #f4f4f4));
  color: var(--cg-muted, var(--wizon-ai-text-muted, #6f6f6f));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-service-name {
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._subtitle_1p22z_53,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._root_1ergb_2,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._label_1ergb_100 {
  color: var(--cg-muted, var(--wizon-ai-text-muted, #6f6f6f));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._label_2lf8x_7 {
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

/* 20260705-login-layout-surface-token-qa: restore the WDS LoginSurface anatomy for the app-local hashed classes. */
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._header_1p22z_24,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-body,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-actions {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._header_1p22z_24 {
  gap: var(--chatgpt-login-header-gap);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-service-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-2);
  min-width: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._subtitle_1p22z_53 {
  margin: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-body {
  gap: var(--chatgpt-login-body-gap);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._field_2lf8x_2 {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-login-field-gap);
  min-width: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._label_2lf8x_7 {
  margin: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 {
  box-sizing: border-box;
  width: 100%;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-actions {
  gap: var(--chatgpt-login-actions-gap);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-form-message {
  margin: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._footer_1p22z_65 {
  margin: 0;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 {
  border-color: var(--cg-menu-border, var(--wizon-ai-popover-border, #e3e3e3));
  border-radius: var(--wizon-ai-radius-control, 8px);
  background: var(--cg-surface, var(--wizon-ai-surface, #ffffff));
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2:focus-within {
  border-color: var(--cg-focus-visible-ring, var(--wizon-ai-focus-visible-ring, rgba(13, 13, 13, 0.16)));
  box-shadow: 0 0 0 1px var(--cg-focus-visible-ring, var(--wizon-ai-focus-visible-ring, rgba(13, 13, 13, 0.16)));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._leading_1h2ox_45,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._trailing_1h2ox_46,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-password-toggle {
  color: var(--cg-muted, var(--wizon-ai-text-muted, #6f6f6f));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-password-toggle {
  border-radius: var(--wizon-ai-radius-control, 8px);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-password-toggle:hover {
  background: var(--cg-hover-soft, var(--wizon-ai-hover-soft-bg, #f4f4f4));
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-password-toggle:focus-visible,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-link-button:focus-visible,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help-link:focus-visible,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2:focus-visible {
  outline: 1px solid var(--cg-focus-visible-ring, var(--wizon-ai-focus-visible-ring, rgba(13, 13, 13, 0.16)));
  outline-offset: 2px;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:hover,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:focus,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100:focus-visible {
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
  caret-color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._wrap_1h2ox_2 ._input_1h2ox_100::placeholder {
  color: var(--cg-input-placeholder, var(--wizon-ai-input-placeholder, #8a8a8a));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._box_1ergb_3 {
  border-color: var(--cg-muted-2, var(--wizon-ai-text-muted-2, #8a8a8a));
  background: var(--cg-surface, var(--wizon-ai-surface, #ffffff));
  color: var(--cg-send-fg, var(--wizon-ai-action-primary-fg, #ffffff));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._input_1ergb_3:checked + ._box_1ergb_3 {
  border-color: var(--cg-send-bg, var(--wizon-ai-action-primary-bg, #0d0d0d));
  background: var(--cg-send-bg, var(--wizon-ai-action-primary-bg, #0d0d0d));
}

/* 20260705-login-admin-contact-token-link: make the admin contact link share the password-help token contract. */
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-login-link-row-gap);
  width: 100%;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-link-button,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help-link {
  color: var(--chatgpt-login-link-fg);
  font-size: var(--chatgpt-login-link-font-size);
  font-weight: var(--chatgpt-login-link-font-weight);
  line-height: var(--chatgpt-login-link-line-height);
  min-height: var(--chatgpt-login-link-target-height);
  text-decoration: none;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help-link {
  flex: 0 0 auto;
  margin-left: auto;
  white-space: nowrap;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help span {
  color: var(--chatgpt-login-help-label-fg);
  font-size: var(--chatgpt-login-link-font-size);
  font-weight: var(--chatgpt-login-link-font-weight);
  line-height: var(--chatgpt-login-link-line-height);
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-link-button:hover,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-help-link:hover {
  color: var(--chatgpt-login-link-hover-fg);
  text-decoration: none;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2._primary_lt829_48 {
  border-radius: var(--wizon-ai-radius-control, 8px);
  background: var(--cg-send-bg, var(--wizon-ai-action-primary-bg, #0d0d0d));
  color: var(--cg-send-fg, var(--wizon-ai-action-primary-fg, #ffffff));
  font-weight: 500;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2._secondary_lt829_64 {
  border-color: var(--cg-menu-border, var(--wizon-ai-popover-border, #e3e3e3));
  border-radius: var(--wizon-ai-radius-control, 8px);
  background: var(--cg-surface, var(--wizon-ai-surface, #ffffff));
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
  font-weight: 500;
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2._secondary_lt829_64:hover:not(:disabled) {
  border-color: var(--cg-menu-border, var(--wizon-ai-popover-border, #e3e3e3));
  background: var(--cg-hover-soft, var(--wizon-ai-hover-soft-bg, #f4f4f4));
  color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}

.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2:disabled,
.chatgpt-reference-v1.wds-pattern-fidelity-v2 .login-surface ._button_lt829_2[aria-disabled="true"] {
  background: var(--cg-disabled-bg, var(--wizon-ai-disabled-bg, #d9d9d9));
  color: var(--cg-send-fg, var(--wizon-ai-action-primary-fg, #ffffff));
}

.wds-pattern-fidelity-v2.is-auth-gate .app-shell {
  background: var(--ds-color-bg);
  visibility: hidden;
  pointer-events: none;
  user-select: none;
}

.wds-pattern-fidelity-v2.is-auth-gate .ai-chat-header,
.wds-pattern-fidelity-v2.is-auth-gate .composer-surface,
.wds-pattern-fidelity-v2.is-auth-gate .calm-chat-home,
.wds-pattern-fidelity-v2.is-auth-gate .context-pane {
  filter: none;
}

@media (max-width: 900px) {
  .wds-pattern-fidelity-v2 .app-shell {
    grid-template-columns: 1fr;
  }

  .wds-pattern-fidelity-v2 .sidebar {
    min-height: auto;
  }

  .wds-pattern-fidelity-v2 .ai-chat-header,
  .wds-pattern-fidelity-v2 .composer-surface {
    width: calc(100% - var(--ds-space-5));
  }

  .wds-pattern-fidelity-v2 .ai-chat-header {
    justify-content: flex-start;
    margin-top: var(--ds-space-4);
  }

  .wds-pattern-fidelity-v2 .message-list {
    padding: var(--ds-space-5) var(--ds-space-3);
  }

  .wds-pattern-fidelity-v2 .calm-chat-home {
    padding: var(--ds-space-5);
  }

  .wds-pattern-fidelity-v2 .quick-start-grid {
    grid-template-columns: 1fr;
  }

  .wds-pattern-fidelity-v2 .nav-section {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .wds-pattern-fidelity-v2 .nav-item {
    grid-template-columns: 24px minmax(0, 1fr);
    justify-content: start;
    min-width: 0;
    text-align: left;
  }

  .wds-pattern-fidelity-v2 .nav-item span:not(.nav-icon) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

}

/* ChatGPT theme parity layer: keep the WIZON shell light/dark colors on one palette. */
.chatgpt-reference-v1 {
  /* 2026-08-01 셸 층 중복 제거. body 에 셸 클래스 6개가 index.html 에서 항상 함께 붙어
     있어(토글 없음), 같은 특이도로 같은 속성을 거는 선언은 마지막 것만 이긴다. 여기서
     지던 선언은 화면에 한 번도 닿은 적이 없어 지웠다 — 계산 스타일 무변화로 검증. */
  --cg-chat-max-width: var(--wizon-ai-chat-max-width, 800px);
  --cg-chat-gutter: var(--wizon-ai-chat-gutter, 20px);
  --cg-thread-gutter: var(--wizon-ai-thread-gutter, 16px);
  --cg-composer-gutter: var(--wizon-ai-composer-gutter, 12px);
  --cg-composer-compact-gutter: var(--wizon-ai-composer-compact-gutter, 8px);
  --cg-composer-radius: var(--wizon-ai-composer-radius, 24px);
  --cg-menu-gutter: var(--wizon-ai-menu-gutter, 6px);
  --cg-menu-radius: var(--wizon-ai-menu-radius, 12px);
  --cg-bg: var(--wizon-ai-canvas, #fcfcfc);
  --cg-surface: var(--wizon-ai-surface, #ffffff);
  --cg-sidebar-bg: var(--wizon-ai-sidebar-bg, #f9f9f9);
  --cg-sidebar-border: var(--wizon-ai-sidebar-border, #ececec);
  --cg-sidebar-item-height: var(--wizon-ai-sidebar-row-height, 36px);
  --cg-sidebar-item-width: var(--wizon-ai-sidebar-row-width, 248px);
  --cg-sidebar-account-width: var(--wizon-ai-account-button-width, 246px);
  --cg-sidebar-account-height: var(--wizon-ai-account-button-height, 52px);
  --cg-text: var(--wizon-ai-text-primary, #0d0d0d);
  --cg-text-soft: var(--wizon-ai-text-secondary, #3f3f3f);
  --cg-muted: var(--wizon-ai-text-muted, #6f6f6f);
  --cg-muted-2: var(--wizon-ai-text-muted-2, #8a8a8a);
  /* 2026-08-01 복원. .chatgpt-library-preview-dialog 의 grid-template-rows 가 참조하는데
     정의가 없어 선언이 무효였다(값은 그 자리에 남아 있던 폴백 56px). ★--chatgpt-* 이름이지만
     14357행의 --chatgpt-route-gap-* 블록에 두지 않는다 — 그 블록은 .chatgpt-route-page
     스코프라 다이얼로그에 닿지 않을 수 있다. 여기(.chatgpt-reference-v1)는 body 레벨이다. */
  --chatgpt-header-height: 56px;
  --cg-hover: var(--wizon-ai-hover-bg, #ececec);
  --cg-hover-soft: var(--wizon-ai-hover-soft-bg, #f4f4f4);
  --cg-focus-bg: var(--wizon-ai-focus-bg, #f3f3f3);
  --cg-focus-ring: var(--wizon-ai-focus-ring, rgba(13, 13, 13, 0.16));
  --cg-focus-visible-ring: var(--wizon-ai-focus-visible-ring, var(--cg-focus-ring));
  --cg-scrollbar-thumb: var(--wizon-ai-scrollbar-thumb, #c7c7c7);
  --cg-scrollbar-track: var(--wizon-ai-scrollbar-track, transparent);
  --cg-sidebar-active-bg: var(--wizon-ai-sidebar-active-bg, rgba(0, 0, 0, 0.05));
  --cg-menu-bg: var(--wizon-ai-popover-bg, #ffffff);
  --cg-menu-border: var(--wizon-ai-popover-border, #e3e3e3);
  --cg-user-bubble-bg: var(--wizon-ai-message-user-bg, #f4f4f4);
  --cg-composer-bg: var(--wizon-ai-composer-bg, #ffffff);
  --cg-composer-border: var(--wizon-ai-composer-border, rgba(0, 0, 0, 0.05));
  --cg-input-placeholder: var(--wizon-ai-input-placeholder, #8a8a8a);
  --cg-send-bg: var(--wizon-ai-action-primary-bg, #0d0d0d);
  --cg-send-fg: var(--wizon-ai-action-primary-fg, #ffffff);
  --cg-disabled-bg: var(--wizon-ai-disabled-bg, #d9d9d9);
  --cg-danger-fg: var(--wizon-ai-danger-text, rgb(186, 38, 35));
  /* 경고(warning). danger와 같은 층에 둔다 — 이 자리가 비어 있던 탓에 경고 표면이
     개인 설정인 --accent(ink/gray/blue)를 빌려 썼고, 파란 accent를 고른 사용자에게는
     의료 경고가 파란 막대로 나왔다. 위험도가 취향으로 결정되면 안 된다.
     셸 토큰이 테마별 값을 갖는다(라이트 amber-700 / 다크 amber-500) — 한 값으로는
     두 테마를 못 덮기 때문이다: amber-700은 라이트 4.57:1인데 다크 3.21:1, amber-500은
     다크 7.50:1인데 라이트 1.95:1. 폴백도 토큰이라 색 리터럴이 늘지 않는다. */
  --cg-warning-fg: var(--wizon-ai-warning-text, var(--wds-amber-700));
  --cg-danger-bg: var(--wizon-ai-danger-bg, #ff002a);
  --cg-danger-bg-hover: var(--wizon-ai-danger-bg-hover, #e50026);
  /* doc 167 §4.1 (phantom-token cleanup): these two names were consumed by the question-card
     family as if they were tokens but never defined — every use silently fell to its literal
     fallback (and --cg-surface-secondary had DIFFERENT fallbacks per call site, 0.03 vs 0.05).
     Defined here for real: success rides the art-direction green axis (doc 161, dark-aware),
     the secondary surface rides the themed hover-soft neutral. */
  --cg-success: var(--ad-green, #15803d);
  --cg-surface-secondary: var(--cg-hover-soft);
  --cg-shadow: var(--wizon-ai-composer-shadow, 0 0 0 1px rgba(0, 0, 0, 0.04), 0 2px 8px rgba(0, 0, 0, 0.04), 0 4px 80px 8px rgba(0, 0, 0, 0.024));
  --cg-menu-shadow: var(--wizon-ai-popover-shadow, 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62));
  --cg-dialog-shadow: var(--wizon-ai-dialog-shadow, var(--cg-menu-shadow));
  /* anti-drift reconcile: --cg-floating-shadow was never defined anywhere, so
     every var(--cg-floating-shadow, <literal>) call site always fell through
     to its own hardcoded fallback (same phantom-token shape as the
     --cg-success cleanup above). 7 call sites, only 4 distinct values —
     defined here for real, one token per value, fallback dropped at each
     site. */
  --cg-shadow-float-lg: 0 18px 48px rgba(15, 15, 15, 0.16);
  --cg-shadow-float-xl: 0 24px 72px rgba(0, 0, 0, 0.24);
  --cg-shadow-float-md: 0 18px 54px rgba(0, 0, 0, 0.2);
  --cg-shadow-float-xs: 0 1px 2px rgba(15, 15, 15, 0.12);
  --cg-transition-basic-duration: var(--wizon-ai-transition-basic-duration, 150ms);
  --cg-ease-enter: var(--wizon-ai-ease-enter, cubic-bezier(0.19, 1, 0.22, 1));
  --cg-ease-exit: var(--wizon-ai-ease-exit, cubic-bezier(0.8, 0, 0.4, 1));
  --cg-ease-move: var(--wizon-ai-ease-move, cubic-bezier(0.65, 0, 0.35, 1));
  color-scheme: light;
}

body.chatgpt-reference-v1 {
  background: var(--cg-bg);
  color: var(--cg-text);
  font-family: var(--wizon-ai-font-family, -apple-system-body, ui-sans-serif, -apple-system, "system-ui", "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol");
  overflow: hidden;
}

body.chatgpt-reference-v1 button,
body.chatgpt-reference-v1 input,
body.chatgpt-reference-v1 textarea,
body.chatgpt-reference-v1 select {
  font-family: inherit;
}

@media (max-width: 900px) {
  .chatgpt-reference-v1 {
    /* 20260705-mobile-account-bottom-safe: keep the full account row inside short mobile viewports. */
    --cg-sidebar-account-height: 44px;
  }

  .chatgpt-reference-v1 .chatgpt-account-area {
    padding-top: 6px;
  }

  .chatgpt-reference-v1 .chatgpt-account-button {
    padding: 5px 6px 5px 8px;
  }
}

html[data-theme="dark"] .chatgpt-reference-v1 {
  color-scheme: dark;
}

html[data-theme="dark"] body.chatgpt-reference-v1,
html[data-theme="dark"] body.chatgpt-reference-v1.premium-product-shell-v1,
html[data-theme="dark"] body.chatgpt-reference-v1.service-product-v28 {
  background: var(--cg-bg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .app-shell,
.chatgpt-reference-v1 .main-pane,
.chatgpt-reference-v1 .workbench,
.chatgpt-reference-v1 .chat-pane,
.chatgpt-reference-v1.is-auth-gate .app-shell {
  background: var(--cg-bg);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .app-shell,
body.chatgpt-reference-v1 .main-pane,
body.chatgpt-reference-v1 .workbench,
body.chatgpt-reference-v1 .chat-pane {
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
}

html[data-theme="dark"] body.chatgpt-reference-v1 .app-shell,
html[data-theme="dark"] body.chatgpt-reference-v1 .main-pane,
html[data-theme="dark"] body.chatgpt-reference-v1 .workbench,
html[data-theme="dark"] body.chatgpt-reference-v1 .chat-pane,
html[data-theme="dark"] body.chatgpt-reference-v1.service-product-v28 .chat-pane,
html[data-theme="dark"] body.chatgpt-reference-v1.premium-product-shell-v1 .app-shell {
  background: var(--cg-bg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .sidebar,
.chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
  background: var(--cg-sidebar-bg);
  border-right-color: var(--cg-sidebar-border);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .sidebar {
  height: 100dvh;
  min-height: 0;
  overflow: visible;
}

body.chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
  height: 100dvh;
  min-height: 0;
  overflow: visible;
}

html[data-theme="dark"] body.chatgpt-reference-v1 .sidebar,
html[data-theme="dark"] body.chatgpt-reference-v1.service-product-v28 .sidebar,
html[data-theme="dark"] body.chatgpt-reference-v1.premium-product-shell-v1 .sidebar,
html[data-theme="dark"] body.chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
  background: var(--cg-sidebar-bg);
  border-right-color: var(--cg-sidebar-border);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-sidebar-head strong,
.chatgpt-reference-v1 .brand-row strong,
.chatgpt-reference-v1 .chatgpt-sidebar-link,
.chatgpt-reference-v1 .new-chat-button.chatgpt-sidebar-link,
.chatgpt-reference-v1 .new-chat-button,
.chatgpt-reference-v1 .theme-toggle,
.chatgpt-reference-v1 .nav-item,
.chatgpt-reference-v1 .nav-item span:not(.nav-icon),
.chatgpt-reference-v1 .nav-item.active span:not(.nav-icon),
.chatgpt-reference-v1 .chatgpt-recent-title,
.chatgpt-reference-v1 .recent-item,
.chatgpt-reference-v1 .recent-primary,
.chatgpt-reference-v1 .chatgpt-account-button,
.chatgpt-reference-v1 .chatgpt-account-copy strong,
.chatgpt-reference-v1 .chatgpt-account-menu-head strong,
.chatgpt-reference-v1 .chatgpt-home-title,
.chatgpt-reference-v1 .message-body,
.chatgpt-reference-v1 .message-body p,
.chatgpt-reference-v1 .message-body li,
.chatgpt-reference-v1 .message-body h3,
.chatgpt-reference-v1 .message-body h4,
.chatgpt-reference-v1 .message-body h5,
.chatgpt-reference-v1 .message-body strong,
.chatgpt-reference-v1 .message.assistant .message-body,
.chatgpt-reference-v1 .message.system .message-body,
.chatgpt-reference-v1 .composer-surface textarea,
.chatgpt-reference-v1 .composer-menu-copy strong,
.chatgpt-reference-v1 .chatgpt-settings-head h2,
.chatgpt-reference-v1 .chatgpt-settings-panel h3 {
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-icon-button,
.chatgpt-reference-v1 .chatgpt-rail-button,
.chatgpt-reference-v1 .composer-icon-button,
.chatgpt-reference-v1 .message-action-button,
.chatgpt-reference-v1 .feedback-row .message-action-button,
.chatgpt-reference-v1 .composer-menu-icon,
.chatgpt-reference-v1 .composer-menu-chevron,
.chatgpt-reference-v1 .reasoning-check,
.chatgpt-reference-v1 .composer-mode-icon,
.chatgpt-reference-v1 .composer-mode-remove {
  color: var(--cg-text-soft);
}

.chatgpt-reference-v1 .chatgpt-sidebar-shortcut,
.chatgpt-reference-v1 .sidebar .section-label,
.chatgpt-reference-v1 .chatgpt-recent-title svg,
.chatgpt-reference-v1 .chatgpt-recent-header-action,
.chatgpt-reference-v1 .recent-action,
.chatgpt-reference-v1 .recent-primary small,
.chatgpt-reference-v1 .chatgpt-account-copy small,
.chatgpt-reference-v1 .chatgpt-account-menu-head small,
.chatgpt-reference-v1 .settings-description,
.chatgpt-reference-v1 .composer-model-pill,
.chatgpt-reference-v1 .composer-menu-copy small,
.chatgpt-reference-v1 .reasoning-menu-title,
.chatgpt-reference-v1 .source-snippet,
.chatgpt-reference-v1 .evidence-card summary small,
.chatgpt-reference-v1 .evidence-note {
  color: var(--cg-muted);
}

/* 20260710-hover-pointer-guard (아트디렉션 P0-1): 통합 인터랙션 상태 레이어를 hover/state로 분리.
   :hover는 진짜 hover 포인터에서만 — iOS Safari는 탭 후 :hover가 남아(첫탭 hover 문제, doc 147 규칙1)
   아이콘버튼·사이드바·recent 행 등이 눌린 색으로 고착됐다. 상태(.active/.is-selected/[aria-expanded])는
   포인터와 무관하므로 가드 밖 유지. 새 :hover 규칙은 반드시 @media (hover: hover) 안에 쓸 것. */
.chatgpt-reference-v1 .chatgpt-sidebar-link.active,
.chatgpt-reference-v1 .nav-item.active,
.chatgpt-reference-v1 .chatgpt-account-button[aria-expanded="true"],
.chatgpt-reference-v1 .chatgpt-settings-tabs button.is-active,
.chatgpt-reference-v1 .recent-item.is-selected,
.chatgpt-reference-v1 .composer-model-pill[aria-expanded="true"] {
  background: var(--cg-hover);
  color: var(--cg-text);
}
@media (hover: hover) {
  .chatgpt-reference-v1 .chatgpt-sidebar-link:hover,
  .chatgpt-reference-v1 .new-chat-button:hover,
  .chatgpt-reference-v1 .theme-toggle:hover,
  .chatgpt-reference-v1 .nav-item:hover,
  .chatgpt-reference-v1 .chatgpt-icon-button:hover,
  .chatgpt-reference-v1 .chatgpt-rail-button:hover,
  .chatgpt-reference-v1 .chatgpt-account-button:hover,
  .chatgpt-reference-v1 .chatgpt-settings-tabs button:hover,
  .chatgpt-reference-v1 .chatgpt-recent-header-action:hover,
  .chatgpt-reference-v1 .recent-item:hover,
  .chatgpt-reference-v1 .recent-action:hover,
  .chatgpt-reference-v1 .chatgpt-recent-menu button:hover:not(:disabled),
  .chatgpt-reference-v1 .composer-icon-button:hover,
  .chatgpt-reference-v1 .composer-model-pill:hover,
  .chatgpt-reference-v1 .composer-menu-item:hover,
  .chatgpt-reference-v1 .reasoning-menu-item:hover,
  .chatgpt-reference-v1 .message-action-button:hover,
  .chatgpt-reference-v1 .feedback-row .message-action-button:hover {
    background: var(--cg-hover);
    color: var(--cg-text);
  }
}

.chatgpt-reference-v1 .chatgpt-sidebar-link.active,
.chatgpt-reference-v1 .chatgpt-sidebar-link.active:hover {
  background: var(--cg-sidebar-active-bg);
}

.chatgpt-reference-v1 .chatgpt-more-menu,
.chatgpt-reference-v1 .chatgpt-account-menu,
.chatgpt-reference-v1 .chatgpt-recent-menu,
.chatgpt-reference-v1 .composer-popover,
.chatgpt-reference-v1 .reasoning-popover,
.chatgpt-reference-v1 .chatgpt-settings-dialog {
  background: var(--cg-menu-bg);
  border-color: var(--cg-menu-border);
  color: var(--cg-text);
  box-shadow: var(--cg-menu-shadow);
}

.chatgpt-reference-v1 .chatgpt-more-menu button,
.chatgpt-reference-v1 .chatgpt-account-menu button,
.chatgpt-reference-v1 .chatgpt-recent-menu button,
.chatgpt-reference-v1 .composer-menu-item,
.chatgpt-reference-v1 .reasoning-menu-item,
.chatgpt-reference-v1 .chatgpt-settings-tabs button,
.chatgpt-reference-v1 .settings-row,
.chatgpt-reference-v1 .settings-pill,
.chatgpt-reference-v1 .settings-combobox,
.chatgpt-reference-v1 .settings-switch {
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-more-menu button:hover,
.chatgpt-reference-v1 .chatgpt-account-menu button:hover {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-account-menu {
  border: 0;
  border-radius: var(--chatgpt-account-menu-radius, var(--wizon-ai-radius-popover));
  box-shadow: var(--cg-menu-shadow);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog {
  border: 0;
  border-radius: 16px;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .reasoning-popover {
  width: 124px;
  min-width: 124px;
  padding: 6px 0;
  border: 0;
  border-radius: 16px;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .reasoning-model-menu {
  width: 126px;
  min-width: 126px;
}

.chatgpt-reference-v1 .chatgpt-recent-menu {
  border: 0;
  border-radius: 16px;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.08), 0 0 1px rgba(0, 0, 0, 0.62);
}

.chatgpt-reference-v1 .chatgpt-recent-menu [data-recent-menu-action^="delete"]:not(:disabled) {
  color: var(--cg-danger-fg);
}

.chatgpt-reference-v1 .chatgpt-settings-tabs button:hover,
.chatgpt-reference-v1 .chatgpt-settings-tabs button.is-active {
  background: rgba(0, 0, 0, 0.04);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-menu-separator,
.chatgpt-reference-v1 .composer-menu-divider,
.chatgpt-reference-v1 .chatgpt-settings-head,
.chatgpt-reference-v1 .chatgpt-settings-tabs,
.chatgpt-reference-v1 .settings-row {
  border-color: var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-menu-separator,
.chatgpt-reference-v1 .composer-menu-divider {
  background: var(--cg-menu-border);
}

.chatgpt-reference-v1 .settings-pill,
.chatgpt-reference-v1 .settings-combobox,
.chatgpt-reference-v1 .prompt-chip {
  background: var(--cg-surface);
  border-color: rgba(0, 0, 0, 0);
  color: var(--cg-text-soft);
}

.chatgpt-reference-v1 .settings-combobox:hover,
.chatgpt-reference-v1 .settings-pill:hover {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .settings-switch {
  background: #3a83f7;
}

html[data-theme="dark"] .chatgpt-reference-v1 .settings-switch::after {
  background: var(--cg-bg);
}

.chatgpt-reference-v1 .prompt-chip:hover {
  background: var(--cg-hover);
  border-color: var(--cg-menu-border);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  min-height: 40px;
  padding: 10px 16px 10px 14px;
  /* ⓑ 하드 테두리가 바로 아래 컴포저와 시선을 다퉜다. iOS 레퍼런스의 첨부 칩처럼
     «테두리 없는 연회색 면»으로 바꿔 무게를 낮춘다. 칩 자체는 제품 진입점이라 없애지
     않는다. 대비 실측: 다크 13.63:1(AA 4.5 여유). 테두리는 0 이 아니라 transparent —
     굵기를 지우면 레이아웃이 1px 씩 움직인다. */
  border: 1px solid transparent;
  border-radius: 100px;
  background: var(--cg-hover-soft);
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 21px;
}

.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip .prompt-chip-icon {
  display: inline-flex;
  width: 20px;
  height: 20px;
  color: #8f8f8f;
}

.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip .prompt-chip-icon svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
}

.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip:hover {
  background: rgba(0, 0, 0, 0.04);
  border-color: transparent;
  color: var(--cg-text);
}

html[data-theme="dark"] .chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip {
    border-color: transparent;
    background: var(--cg-hover-soft);
  color: #ececec;
}

html[data-theme="dark"] .chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip .prompt-chip-icon {
  color: #b4b4b4;
}

html[data-theme="dark"] .chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: transparent;
  color: #ececec;
}

.chatgpt-reference-v1 .message.user .message-body {
  background: var(--cg-user-bubble-bg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .message-body code:not(pre code) {
  background: var(--cg-hover);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .message-body pre,
.chatgpt-reference-v1 .code-block {
  background: #0d0d0d;
  color: #ececec;
}

html[data-theme="dark"] .chatgpt-reference-v1 .message-body pre,
html[data-theme="dark"] .chatgpt-reference-v1 .code-block {
  background: #171717;
  color: #ececec;
}

.chatgpt-reference-v1 .chatgpt-composer-shell,
.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
  background: var(--cg-composer-bg);
  border-color: var(--cg-composer-border);
  color: var(--cg-text);
  box-shadow: var(--cg-shadow);
}

html[data-theme="dark"] body.chatgpt-reference-v1.service-product-v28 .composer-surface.chatgpt-composer-shell,
html[data-theme="dark"] body.chatgpt-reference-v1.premium-product-shell-v1 .composer-surface.chatgpt-composer-shell {
  background: var(--cg-composer-bg);
  border-color: var(--cg-composer-border);
  color: var(--cg-text);
  box-shadow: var(--cg-shadow);
}

html[data-chat-state="empty"] .chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
  box-shadow: var(--cg-shadow);
}

.chatgpt-reference-v1 .composer-surface textarea::placeholder {
  color: var(--cg-input-placeholder);
}

.chatgpt-reference-v1 .composer-mode-chip {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .composer-send-button,
.chatgpt-reference-v1 #sendButton {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

.chatgpt-reference-v1 .composer-send-button:hover,
.chatgpt-reference-v1 #sendButton:hover {
  background: var(--cg-send-bg);
}

.chatgpt-reference-v1 #sendButton:disabled {
  background: var(--cg-disabled-bg);
  color: var(--cg-send-fg);
}

.chatgpt-reference-v1 .recent-actions {
  background: linear-gradient(90deg, color-mix(in srgb, var(--cg-hover) 0%, transparent), var(--cg-hover) var(--chatgpt-recent-action-fade));
}

html[data-theme="dark"] .chatgpt-reference-v1 .recent-actions {
  background: linear-gradient(90deg, color-mix(in srgb, var(--cg-hover) 0%, transparent), var(--cg-hover) var(--chatgpt-recent-action-fade));
}

.chatgpt-reference-v1 .recent-select-box {
  background: var(--cg-surface);
  border-color: var(--cg-muted-2);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-recent-menu button:disabled {
  color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .evidence-card,
.chatgpt-reference-v1 .source-card,
.chatgpt-reference-v1 .tool-status-card,
.chatgpt-reference-v1 .answer-activity {
  background: var(--cg-menu-bg);
  border-color: var(--cg-menu-border);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .source-card-head strong,
.chatgpt-reference-v1 .source-card-head span,
.chatgpt-reference-v1 .evidence-card summary span {
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chat-pane {
  position: relative;
}

body.chatgpt-reference-v1 .chatgpt-conversation-actions {
  position: absolute;
  top: 8px;
  right: 22px;
  z-index: 40;
  display: inline-flex;
  align-items: flex-start;
  gap: 0;
}

body.chatgpt-reference-v1 .chatgpt-conversation-actions[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .chatgpt-conversation-health {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[hidden] {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-conversation-health:hover,
body.chatgpt-reference-v1 .chatgpt-conversation-health:focus-visible {
  background: var(--cg-hover);
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-conversation-health:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring);
  outline-offset: 1px;
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="attention"] {
  color: var(--cg-warning-fg);
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="approval"] {
  color: var(--ad-blue);
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="unavailable"] {
  color: var(--cg-danger-fg);
}
.chatgpt-conversation-health-icon,
.chatgpt-conversation-health-icon svg {
  width: 20px;
  height: 20px;
}
.chatgpt-conversation-health-badge {
  position: absolute;
  top: 1px;
  right: 1px;
  display: inline-grid;
  place-items: center;
  min-width: 14px;
  height: 14px;
  padding: 0 3px;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-text);
  color: var(--cg-surface);
  font-size: var(--ds-text-micro-11);
  font-weight: var(--wds-font-weight-semibold);
  line-height: 1;
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="attention"] .chatgpt-conversation-health-badge {
  background: var(--cg-warning-fg);
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="approval"] .chatgpt-conversation-health-badge {
  background: var(--ad-blue);
}
body.chatgpt-reference-v1 .chatgpt-conversation-health[data-status="unavailable"] .chatgpt-conversation-health-badge {
  background: var(--cg-danger-fg);
}

/* 20260710-conversation-actions-in-titlebar: on mobile the consolidated "..."
   lives in the top title bar, immediately left of the 새 채팅(compose) icon.
   z-index sits above the topbar row but below the sidebar drawer scrim (65),
   so opening the drawer covers it. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-conversation-actions {
    position: fixed;
    top: 8px;
    right: 52px;
    z-index: 64;
  }
}

body.chatgpt-reference-v1 .chatgpt-conversation-share,
body.chatgpt-reference-v1 .chatgpt-conversation-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-conversation-share {
  gap: 6px;
  width: 98px;
  padding: 0 12px;
  font-weight: 500;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-conversation-more {
  width: 36px;
  padding: 0;
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-conversation-share:hover,
body.chatgpt-reference-v1 .chatgpt-conversation-more:hover,
body.chatgpt-reference-v1 .chatgpt-conversation-more[aria-expanded="true"] {
  background: var(--cg-hover);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-conversation-share svg {
  width: 20px;
  height: 20px;
}

body.chatgpt-reference-v1 .chatgpt-conversation-more svg {
  width: 20px;
  height: 20px;
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu {
  position: absolute;
  top: 36px;
  right: 0;
  z-index: 45;
  display: grid;
  /* 20260710-menu-fit: size to the widest row (그룹 채팅 시작 + 준비 중 badge) so nothing
     wraps to a second line on desktop. Mobile bottom sheet overrides width below. */
  width: max-content;
  min-width: 186px;
  max-width: 260px;
  padding: 6px 0;
  border: 0;
  border-radius: 16px;
  background: var(--cg-menu-bg);
  color: var(--cg-text);
  box-shadow: var(--cg-menu-shadow);
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu button {
  display: flex;
  align-items: center;
  gap: 6px;
  box-sizing: border-box;
  width: auto;
  height: 36px;
  min-height: 36px;
  margin: 0 6px;
  padding: 6px 14px 6px 10px;
  border: 0;
  border-radius: var(--ds-radius-sm, 10px);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 400;
  line-height: 20px;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu button:hover {
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu button.danger {
  color: var(--cg-danger-fg);
}

/* 20260710-conversation-menu-consolidation: the group-chat item is an honest
   "준비 중" placeholder — muted, with a badge — until the workspace substrate lands. */
body.chatgpt-reference-v1 .chatgpt-conversation-menu button[aria-disabled="true"] {
  color: var(--cg-muted-2);
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu-badge {
  margin-left: auto;
  padding: 1px 6px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-hover-soft);
  color: var(--cg-muted-2);
  font-size: var(--ds-text-micro-11);
  font-weight: 500;
  line-height: 16px;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-conversation-menu svg {
  width: 20px;
  height: 20px;
}

body.chatgpt-reference-v1 .chatgpt-share-dialog {
  width: min(520px, calc(100vw - 32px));
  max-width: none;
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: var(--cg-menu-bg);
  color: var(--cg-text);
  opacity: 0;
  box-shadow: var(--cg-dialog-shadow);
  transform: translate3d(0, 12px, 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .chatgpt-share-dialog::backdrop {
  background: rgba(0, 0, 0, 0.28);
  opacity: 0;
  transition: opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

body.chatgpt-reference-v1 .chatgpt-share-dialog[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

body.chatgpt-reference-v1 .chatgpt-share-dialog[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(0, 12px, 0) scale(0.985);
}

body.chatgpt-reference-v1 .chatgpt-share-dialog[data-motion-state="open"]::backdrop {
  opacity: 1;
}

body.chatgpt-reference-v1 .chatgpt-share-dialog[data-motion-state="closing"]::backdrop {
  opacity: 0;
}

body.chatgpt-reference-v1 .chatgpt-share-shell {
  display: grid;
  gap: 0;
}

body.chatgpt-reference-v1 .chatgpt-share-head {
  display: flex;
  min-height: 56px;
  align-items: center;
  justify-content: space-between;
  padding: 10px 10px 10px 16px;
  border-bottom: 1px solid var(--cg-menu-border);
}

body.chatgpt-reference-v1 .chatgpt-share-head h2 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-title-18);
  font-weight: 400;
  line-height: 28px;
}

body.chatgpt-reference-v1 .chatgpt-share-close {
  display: inline-flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-share-close:hover {
  background: var(--cg-hover);
}

body.chatgpt-reference-v1 .chatgpt-share-body {
  display: grid;
  gap: 14px;
  padding: 16px;
}

body.chatgpt-reference-v1 .chatgpt-share-description,
body.chatgpt-reference-v1 .chatgpt-share-status {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
}

body.chatgpt-reference-v1 .chatgpt-share-link-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
}

body.chatgpt-reference-v1 .chatgpt-share-url {
  min-width: 0;
  height: 40px;
  padding: 0 12px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-sm, 10px);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
}

body.chatgpt-reference-v1 .chatgpt-share-url:focus,
body.chatgpt-reference-v1 .chatgpt-share-url:focus-visible {
  outline: none;
  border-color: var(--cg-menu-border);
  box-shadow: none;
}

body.chatgpt-reference-v1 .chatgpt-share-copy {
  height: 40px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 500;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-search-dialog[open] {
  position: fixed;
  inset: 0;
  width: min(680px, calc(100vw - 20px));
  height: min(442px, calc(100vh - 40px));
  max-height: calc(100vh - 40px);
  margin: auto;
  padding: 0;
  overflow: visible;
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: 16px;
  background: var(--cg-menu-bg, #ffffff);
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-16);
  line-height: 24px;
  box-shadow: 0 14px 62px rgba(0, 0, 0, 0.25);
  opacity: 0;
  transform: translate3d(0, 10px, 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .chatgpt-search-dialog[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

body.chatgpt-reference-v1 .chatgpt-search-dialog[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(0, 10px, 0) scale(0.985);
}

body.chatgpt-reference-v1 .chatgpt-search-dialog::backdrop {
  background: rgba(0, 0, 0, 0.50);
  opacity: 0;
  transition: opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

body.chatgpt-reference-v1 .chatgpt-search-dialog[data-motion-state="open"]::backdrop {
  opacity: 1;
}

body.chatgpt-reference-v1 .chatgpt-search-dialog[data-motion-state="closing"]::backdrop {
  opacity: 0;
}

html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-search-dialog::backdrop {
  background: rgba(0, 0, 0, 0.54);
}

body.chatgpt-reference-v1 .chatgpt-search-shell {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100%;
  max-height: inherit;
}

body.chatgpt-reference-v1 .chatgpt-search-input-row {
  display: flex;
  align-items: center;
  min-height: 64px;
  max-height: 64px;
  margin: 0 16px 0 12px;
  padding: 0;
  border-bottom: 0;
}

body.chatgpt-reference-v1 .chatgpt-search-divider {
  flex: 0 0 1px;
  width: 100%;
  height: 1px;
  margin: 0;
  overflow: hidden;
  border: 0;
  background: var(--cg-menu-border, rgba(0, 0, 0, 0.10));
}

body.chatgpt-reference-v1 .chatgpt-search-input-row input {
  width: 100%;
  height: 40px;
  min-height: 40px;
  min-width: 0;
  border: 0;
  border-radius: 0;
  outline: 0;
  background: transparent;
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: var(--ds-text-body-16);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 24px;
  padding: 8px 12px;
  box-shadow: none;
}

body.chatgpt-reference-v1 .chatgpt-search-input-row input::placeholder {
  color: var(--cg-input-placeholder, #8f8f8f);
}

body.chatgpt-reference-v1 .chatgpt-search-input-row input::-webkit-search-cancel-button,
body.chatgpt-reference-v1 .chatgpt-search-input-row input::-webkit-search-decoration {
  appearance: none;
  display: none;
}

body.chatgpt-reference-v1 .chatgpt-search-input-row input:focus,
body.chatgpt-reference-v1 .chatgpt-search-input-row input:focus-visible {
  border-color: transparent;
  box-shadow: none;
  outline: none;
}

body.chatgpt-reference-v1 .chatgpt-search-input-row .chatgpt-icon-button {
  display: flex;
  flex: 0 0 28px;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-left: 16px;
  padding: 4px;
  border-radius: var(--ds-radius-pill, 999px);
  color: var(--cg-text, #0d0d0d);
}

body.chatgpt-reference-v1 .chatgpt-search-input-row .chatgpt-icon-button svg {
  width: 20px;
  height: 20px;
  color: #8f8f8f;
}

body.chatgpt-reference-v1 .chatgpt-search-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 8px 0;
  scrollbar-gutter: stable;
}

body.chatgpt-reference-v1 .chatgpt-search-results {
  min-height: 0;
  overflow: visible;
  margin: 0;
  padding: 0;
}

body.chatgpt-reference-v1 .chatgpt-search-section {
  display: grid;
  gap: 0;
  min-width: 0;
}

body.chatgpt-reference-v1 .chatgpt-search-section h3 {
  width: calc(100% - 20px);
  margin: 8px 8px 8px;
  padding: 8px 16px 0;
  color: var(--cg-input-placeholder, #8f8f8f);
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 16px;
}

body.chatgpt-reference-v1 .chatgpt-search-row {
  display: flex;
  align-items: center;
  gap: 8px;
  /* 20260704-search-dialog-row-chatgpt-measured: Chrome ChatGPT row is 647px wide inside a 678px shell at 1920px viewport. */
  box-sizing: border-box;
  width: calc(100% - 20px);
  height: 44px;
  min-height: 44px;
  margin: 0 8px;
  padding: 12px 16px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: var(--ds-text-body-16);
  line-height: 24px;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-search-row:hover,
body.chatgpt-reference-v1 .chatgpt-search-row:focus-visible,
body.chatgpt-reference-v1 .chatgpt-search-row[data-chat-search-active="true"] {
  background: var(--cg-hover-soft, #f3f3f3);
}

body.chatgpt-reference-v1 .chatgpt-search-result-icon {
  display: flex;
  flex: 0 0 20px;
  align-items: center;
  justify-content: center;
  place-items: center;
  width: 20px;
  height: 20px;
  color: var(--cg-text, #0d0d0d);
}

body.chatgpt-reference-v1 .chatgpt-search-result-icon svg {
  width: 20px;
  height: 20px;
  stroke-width: var(--wds-icon-stroke, 1.7);
}

body.chatgpt-reference-v1 .chatgpt-search-result-copy {
  display: grid;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}

body.chatgpt-reference-v1 .chatgpt-search-result-copy strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--ds-text-body-16);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 24px;
}

body.chatgpt-reference-v1 .chatgpt-search-result.is-query-result {
  height: 64px;
  min-height: 64px;
  padding: 12px 16px;
}

body.chatgpt-reference-v1 .chatgpt-search-result.is-query-result .chatgpt-search-result-copy {
  gap: 2px;
}

body.chatgpt-reference-v1 .chatgpt-search-result.is-query-result .chatgpt-search-result-copy strong {
  font-size: var(--ds-text-body-16);
  line-height: 24px;
}

body.chatgpt-reference-v1 .chatgpt-search-result-preview {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-muted, #8a8a8a);
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 16px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-search-mark {
  padding: 0;
  border-radius: 2px;
  background: rgba(255, 214, 102, 0.42);
  color: inherit;
  font: inherit;
}

html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-search-mark {
  background: rgba(255, 214, 102, 0.30);
}

body.chatgpt-reference-v1 .chatgpt-search-empty {
  color: var(--cg-muted, #6b7280);
  font-size: var(--ds-text-body-16);
  font-weight: 400;
  letter-spacing: 0;
  line-height: 22px;
}

body.chatgpt-reference-v1 .chatgpt-search-empty {
  margin: 0;
  padding: 14px 34px 24px;
}

@media (max-width: 520px) {
  /* 20260708-search-dialog-mobile-fullscreen: the search dialog is a content panel, so
     on mobile it goes full-screen via the shared [data-mobile-fullscreen] rule (ChatGPT
     parity) instead of the old centered 420px card. Only inner layout lives here. */
  body.chatgpt-reference-v1 .chatgpt-search-input-row {
    min-height: 56px;
    max-height: 56px;
    margin: 0 10px 0 8px;
  }

  body.chatgpt-reference-v1 .chatgpt-search-body {
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    scroll-padding-block: 8px;
  }

  body.chatgpt-reference-v1 .chatgpt-search-row {
    width: calc(100% - 12px);
    margin: 0 6px;
    padding: 10px 12px;
  }

  body.chatgpt-reference-v1 .chatgpt-search-result.is-query-result {
    height: auto;
    min-height: 64px;
  }

  body.chatgpt-reference-v1 .chatgpt-search-result-preview {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    white-space: normal;
    overflow-wrap: anywhere;
  }
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[open] {
  width: min(448px, calc(100vw - 32px));
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 16px;
  background: var(--cg-menu-bg, #ffffff);
  color: var(--cg-text, #0d0d0d);
  box-shadow: var(--cg-dialog-shadow);
  font-size: var(--ds-text-body-16);
  line-height: 24px;
  opacity: 0;
  transform: translate3d(0, 12px, 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(0, 12px, 0) scale(0.985);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog::backdrop {
  background: rgba(0, 0, 0, 0.16);
  opacity: 0;
  transition: opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[data-motion-state="open"]::backdrop {
  opacity: 1;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[data-motion-state="closing"]::backdrop {
  opacity: 0;
}

html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog::backdrop {
  background: rgba(0, 0, 0, 0.52);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-shell {
  display: flex;
  flex-direction: column;
  width: 100%;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-head {
  display: flex;
  min-height: 52px;
  align-items: center;
  justify-content: space-between;
  padding: 10px 10px 10px 16px;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-head h2 {
  margin: 0;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-title-18);
  font-weight: 400;
  line-height: 28px;
  letter-spacing: 0;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-body {
  padding: 4px 16px 16px;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary {
  margin: 0;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-16);
  line-height: 24px;
  letter-spacing: 0;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary strong {
  font-weight: 600;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-memory-note {
  margin: 8px 0 0;
  color: var(--cg-muted, #8f8f8f);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
  letter-spacing: 0;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-memory-note button {
  border: 0;
  padding: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font: inherit;
  text-decoration: underline;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 16px;
  padding: 0;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-cancel,
body.chatgpt-reference-v1 .chatgpt-delete-confirm-danger,
body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary-action {
  min-width: 50px;
  height: 36px;
  padding: 0 12px;
  border-radius: var(--ds-radius-pill, 999px);
  font: inherit;
  font-size: var(--ds-text-body-14);
  font-weight: 500;
  line-height: 20px;
  cursor: pointer;
  transition:
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    border-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-cancel {
  border: 1px solid rgba(0, 0, 0, 0.15);
  background: #ffffff;
  color: var(--cg-text);
}

html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-delete-confirm-cancel {
  border-color: var(--cg-menu-border);
  background: var(--cg-menu-bg);
  color: var(--cg-text);
}

html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-settings-tabs button:hover,
html[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-settings-tabs button.is-active {
  background: var(--cg-hover);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-cancel:hover {
  background: var(--cg-hover-soft, #f4f4f4);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-danger {
  border: 1px solid transparent;
  background: var(--cg-danger-bg);
  color: #ffffff;
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-danger:hover {
  border-color: transparent;
  background: var(--cg-danger-bg-hover);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary-action {
  border: 1px solid transparent;
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary-action:hover {
  border-color: transparent;
  background: var(--cg-send-bg);
}

body.chatgpt-reference-v1 .chatgpt-delete-confirm-cancel:active,
body.chatgpt-reference-v1 .chatgpt-delete-confirm-danger:active,
body.chatgpt-reference-v1 .chatgpt-delete-confirm-primary-action:active {
  transform: scale(0.985);
}

body.chatgpt-reference-v1 .message-list {
  width: 100%;
  max-width: none;
  margin: 0;
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: max(24px, calc((100% - 768px) / 2));
  padding-left: max(24px, calc((100% - 768px) / 2));
  scrollbar-gutter: stable;
}

html[data-chat-state="active"] body.chatgpt-reference-v1 .message-list,
html[data-chat-state="loading"] body.chatgpt-reference-v1 .message-list {
  grid-row: 1;
  padding-top: 72px;
  padding-bottom: 24px;
}

body.chatgpt-reference-v1 .recent-item.is-active,
body.chatgpt-reference-v1 .recent-item.is-active:hover {
  background: var(--cg-sidebar-active-bg);
}

body.chatgpt-reference-v1 .recent-item.is-active .recent-primary {
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .recent-item.is-active .recent-actions {
  background: linear-gradient(90deg, color-mix(in srgb, var(--cg-sidebar-active-bg) 0%, transparent), var(--cg-sidebar-active-bg) var(--chatgpt-recent-action-fade));
}

html[data-theme="dark"] body.chatgpt-reference-v1 .recent-item.is-active .recent-actions {
  background: linear-gradient(90deg, color-mix(in srgb, var(--cg-sidebar-active-bg) 0%, transparent), var(--cg-sidebar-active-bg) var(--chatgpt-recent-action-fade));
}

body.chatgpt-reference-v1 .composer-surface textarea:focus,
body.chatgpt-reference-v1 .composer-surface textarea:focus-visible {
  border-color: transparent;
  box-shadow: none;
  outline: none;
}

body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:focus-within,
body.chatgpt-reference-v1 .chatgpt-composer-shell:focus-within {
  border-color: var(--cg-composer-border);
  box-shadow: var(--cg-shadow);
  outline: none;
}

body.chatgpt-reference-v1 .chatgpt-more-menu button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-account-menu button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-recent-menu button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-conversation-menu button:focus-visible,
body.chatgpt-reference-v1 .recent-action:focus-visible,
body.chatgpt-reference-v1 .composer-menu-item:focus-visible,
body.chatgpt-reference-v1 .reasoning-menu-item:focus-visible,
body.chatgpt-reference-v1 .chatgpt-settings-tabs button:focus-visible,
body.chatgpt-reference-v1 .settings-combobox:focus-visible,
body.chatgpt-reference-v1 .settings-switch:focus-visible,
body.chatgpt-reference-v1 .chatgpt-search-row:focus-visible,
body.chatgpt-reference-v1 .chatgpt-share-close:focus-visible {
  outline: 1px solid var(--cg-focus-visible-ring);
  outline-offset: -1px;
  background: var(--cg-focus-bg);
}

body.chatgpt-reference-v1 .chatgpt-share-copy:focus-visible {
  outline: 1px solid var(--cg-focus-visible-ring);
  outline-offset: 2px;
}

body.chatgpt-reference-v1 .chatgpt-settings-tabs button:focus:not(:focus-visible) {
  outline: none;
  outline-offset: 0;
}

body.chatgpt-reference-v1 .composer-popover,
body.chatgpt-reference-v1 .chatgpt-search-body,
body.chatgpt-reference-v1 .chatgpt-settings-tabs,
body.chatgpt-reference-v1 .chatgpt-settings-panel,
body.chatgpt-reference-v1 .message-list,
body.chatgpt-reference-v1 .recent-list {
  scrollbar-color: var(--cg-scrollbar-thumb) var(--cg-scrollbar-track);
  scrollbar-width: thin;
}

body.chatgpt-reference-v1 .composer-popover::-webkit-scrollbar,
body.chatgpt-reference-v1 .chatgpt-search-body::-webkit-scrollbar,
body.chatgpt-reference-v1 .chatgpt-settings-tabs::-webkit-scrollbar,
body.chatgpt-reference-v1 .chatgpt-settings-panel::-webkit-scrollbar,
body.chatgpt-reference-v1 .message-list::-webkit-scrollbar,
body.chatgpt-reference-v1 .recent-list::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

body.chatgpt-reference-v1 .composer-popover::-webkit-scrollbar-thumb,
body.chatgpt-reference-v1 .chatgpt-search-body::-webkit-scrollbar-thumb,
body.chatgpt-reference-v1 .chatgpt-settings-tabs::-webkit-scrollbar-thumb,
body.chatgpt-reference-v1 .chatgpt-settings-panel::-webkit-scrollbar-thumb,
body.chatgpt-reference-v1 .message-list::-webkit-scrollbar-thumb,
body.chatgpt-reference-v1 .recent-list::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-scrollbar-thumb);
  background-clip: content-box;
}

html[data-theme="dark"] .chatgpt-reference-v1 ::selection {
  background: #ffffff;
  color: #000000;
}

/* WIZON motion grammar layer: Apple-like continuity on top of WDS spring tokens. */
.chatgpt-reference-v1 {
  --wizon-motion-effect-fast: var(--wizon-ai-ease-enter, var(--wizon-ai-motion-effect-fast, var(--wds-spring-effect-fast, var(--wds-ease-out, cubic-bezier(0.16, 1, 0.3, 1)))));
  --wizon-motion-effect-ease: var(--wizon-ai-ease-move, var(--wizon-ai-motion-effect-ease, var(--wds-spring-effect-default, var(--wds-ease-out, cubic-bezier(0.16, 1, 0.3, 1)))));
  --wizon-motion-spatial-ease: var(--wizon-ai-ease-move, var(--wizon-ai-motion-spatial-ease, var(--wds-spring-spatial-default, var(--wds-ease-emphasized-decelerate, cubic-bezier(0.05, 0.7, 0.1, 1)))));
  --wizon-motion-micro-duration: var(--wizon-ai-transition-basic-duration, var(--wizon-ai-motion-micro-duration, var(--wds-spring-effect-fast-duration, 124ms)));
  --wizon-motion-surface-duration: var(--wizon-ai-motion-surface-duration, var(--wds-spring-effect-default-duration, 188ms));
  --wizon-motion-panel-duration: var(--wizon-ai-motion-panel-duration, var(--wds-spring-spatial-default-duration, 372ms));
  --wizon-message-enter-duration: var(--wizon-ai-message-enter-duration, 420ms);
  --wizon-message-action-delay: var(--wizon-ai-message-action-delay, 92ms);
}

@keyframes chatgpt-message-entrance {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0) scale(0.992);
    filter: blur(1.5px);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
    filter: blur(0);
  }
}

@keyframes chatgpt-pending-breathe {
  0%,
  100% {
    opacity: 0.46;
    transform: scale(0.92);
  }

  50% {
    opacity: 1;
    transform: scale(1.08);
  }
}

@keyframes chatgpt-action-rise {
  from {
    opacity: 0;
    transform: translate3d(0, 6px, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

body.chatgpt-reference-v1 .message {
  transform-origin: center bottom;
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .message[data-message-motion="enter"] {
  animation: chatgpt-message-entrance var(--wizon-message-enter-duration) var(--wizon-motion-spatial-ease) both;
}

body.chatgpt-reference-v1 .message.pending .thinking-inline {
  animation: chatgpt-pending-breathe 1180ms var(--wizon-motion-effect-ease) infinite;
  transform-origin: center;
}

body.chatgpt-reference-v1 .message[data-message-state="pending"] .answer-activity {
  transition:
    background-color var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    border-color var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
}

body.chatgpt-reference-v1 .message[data-message-state="complete"] .message-actions {
  animation: chatgpt-action-rise var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease) both;
  animation-delay: var(--wizon-message-action-delay);
}

body.chatgpt-reference-v1 .app-shell {
  transition: grid-template-columns var(--wizon-motion-panel-duration) var(--wizon-motion-spatial-ease);
}

body.chatgpt-reference-v1 .sidebar,
body.chatgpt-reference-v1 .chatgpt-sidebar-rail {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-panel-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .sidebar[data-motion-state="opening"],
body.chatgpt-reference-v1 .sidebar[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(-8px, 0, 0);
}

body.chatgpt-reference-v1 .sidebar[data-motion-state="open"],
body.chatgpt-reference-v1 .chatgpt-sidebar-rail[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

body.chatgpt-reference-v1 .chatgpt-sidebar-rail[data-motion-state="opening"],
body.chatgpt-reference-v1 .chatgpt-sidebar-rail[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(-4px, 0, 0) scale(0.985);
}

body.chatgpt-reference-v1[data-sidebar-transition="collapsing"] .sidebar,
body.chatgpt-reference-v1[data-sidebar-transition="expanding"] .sidebar {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 120;
  width: min(260px, calc(100vw - 52px));
  height: 100dvh;
  pointer-events: none;
}

body.chatgpt-reference-v1[data-sidebar-transition="collapsing"] .chatgpt-sidebar-rail,
body.chatgpt-reference-v1[data-sidebar-transition="expanding"] .chatgpt-sidebar-rail {
  display: flex;
}

body.chatgpt-reference-v1[data-sidebar-transition] .chatgpt-tooltip {
  display: none !important;
  opacity: 0 !important;
  visibility: hidden !important;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link,
.chatgpt-reference-v1 .new-chat-button,
.chatgpt-reference-v1 .theme-toggle,
.chatgpt-reference-v1 .nav-item,
.chatgpt-reference-v1 .chatgpt-icon-button,
.chatgpt-reference-v1 .chatgpt-rail-button,
.chatgpt-reference-v1 .chatgpt-account-button,
.chatgpt-reference-v1 .chatgpt-recent-header-action,
.chatgpt-reference-v1 .recent-action,
.chatgpt-reference-v1 .prompt-chip,
.chatgpt-reference-v1 .composer-icon-button,
.chatgpt-reference-v1 .composer-model-pill,
.chatgpt-reference-v1 .composer-send-button,
.chatgpt-reference-v1 #sendButton,
.chatgpt-reference-v1 .message-action-button,
body.chatgpt-reference-v1 .chatgpt-conversation-share,
body.chatgpt-reference-v1 .chatgpt-conversation-more {
  transition:
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    border-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    box-shadow var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
  will-change: transform;
}

.chatgpt-reference-v1 .chatgpt-sidebar-link:active,
.chatgpt-reference-v1 .new-chat-button:active,
.chatgpt-reference-v1 .theme-toggle:active,
.chatgpt-reference-v1 .nav-item:active,
.chatgpt-reference-v1 .chatgpt-icon-button:active,
.chatgpt-reference-v1 .chatgpt-rail-button:active,
.chatgpt-reference-v1 .chatgpt-account-button:active,
.chatgpt-reference-v1 .chatgpt-recent-header-action:active,
.chatgpt-reference-v1 .recent-action:active,
.chatgpt-reference-v1 .prompt-chip:active,
.chatgpt-reference-v1 .composer-icon-button:active,
.chatgpt-reference-v1 .composer-model-pill:active,
.chatgpt-reference-v1 .composer-send-button:active,
.chatgpt-reference-v1 #sendButton:active,
.chatgpt-reference-v1 .message-action-button:active,
body.chatgpt-reference-v1 .chatgpt-conversation-share:active,
body.chatgpt-reference-v1 .chatgpt-conversation-more:active {
  transform: scale(0.985);
}

.chatgpt-reference-v1 .chatgpt-more-menu,
.chatgpt-reference-v1 .chatgpt-account-menu,
.chatgpt-reference-v1 .chatgpt-recent-menu,
.chatgpt-reference-v1 .composer-popover,
.chatgpt-reference-v1 .reasoning-popover,
body.chatgpt-reference-v1 .chatgpt-conversation-menu {
  --wizon-popover-y: 6px;
  opacity: 0;
  pointer-events: none;
  transform: translate3d(0, var(--wizon-popover-y, 6px), 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

.chatgpt-reference-v1 .chatgpt-more-menu,
.chatgpt-reference-v1 .chatgpt-recent-menu,
body.chatgpt-reference-v1 .chatgpt-conversation-menu {
  transform-origin: right top;
}

.chatgpt-reference-v1 .chatgpt-account-menu {
  transform-origin: left bottom;
}

.chatgpt-reference-v1 .composer-popover {
  transform-origin: left bottom;
}

.chatgpt-reference-v1 .reasoning-popover {
  transform-origin: right bottom;
}

.chatgpt-reference-v1 .reasoning-model-menu {
  transform-origin: left bottom;
}

.chatgpt-reference-v1 .chatgpt-more-menu[data-motion-state="open"],
.chatgpt-reference-v1 .chatgpt-account-menu[data-motion-state="open"],
.chatgpt-reference-v1 .chatgpt-recent-menu[data-motion-state="open"],
.chatgpt-reference-v1 .composer-popover[data-motion-state="open"],
.chatgpt-reference-v1 .reasoning-popover[data-motion-state="open"],
body.chatgpt-reference-v1 .chatgpt-conversation-menu[data-motion-state="open"] {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(0, 0, 0) scale(1);
}

.chatgpt-reference-v1 .chatgpt-more-menu[data-motion-state="closing"],
.chatgpt-reference-v1 .chatgpt-account-menu[data-motion-state="closing"],
.chatgpt-reference-v1 .chatgpt-recent-menu[data-motion-state="closing"],
.chatgpt-reference-v1 .composer-popover[data-motion-state="closing"],
.chatgpt-reference-v1 .reasoning-popover[data-motion-state="closing"],
body.chatgpt-reference-v1 .chatgpt-conversation-menu[data-motion-state="closing"] {
  opacity: 0;
  pointer-events: none;
  transform: translate3d(0, var(--wizon-popover-y, 6px), 0) scale(0.985);
}

.chatgpt-reference-v1 .chatgpt-more-menu button,
.chatgpt-reference-v1 .chatgpt-account-menu button,
.chatgpt-reference-v1 .chatgpt-recent-menu button,
.chatgpt-reference-v1 .composer-menu-item,
.chatgpt-reference-v1 .reasoning-menu-item,
body.chatgpt-reference-v1 .chatgpt-conversation-menu button {
  transition:
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}

.chatgpt-reference-v1 .chatgpt-more-menu button:active,
.chatgpt-reference-v1 .chatgpt-account-menu button:active,
.chatgpt-reference-v1 .chatgpt-recent-menu button:active,
.chatgpt-reference-v1 .composer-menu-item:active,
.chatgpt-reference-v1 .reasoning-menu-item:active,
body.chatgpt-reference-v1 .chatgpt-conversation-menu button:active {
  transform: scale(0.99);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog[open] {
  opacity: 0;
  transform: translate3d(0, 12px, 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

.chatgpt-reference-v1 .chatgpt-settings-dialog[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(0, 12px, 0) scale(0.985);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog::backdrop {
  opacity: 0;
  transition: opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

.chatgpt-reference-v1 .chatgpt-settings-dialog[data-motion-state="open"]::backdrop {
  opacity: 1;
}

.chatgpt-reference-v1 .chatgpt-settings-dialog[data-motion-state="closing"]::backdrop {
  opacity: 0;
}

body.chatgpt-reference-v1 .context-pane {
  position: fixed;
  top: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 55;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  width: min(420px, calc(100vw - 32px));
  min-width: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-lg, 18px);
  background: var(--cg-menu-bg);
  color: var(--cg-text);
  box-shadow: 0 28px 80px rgba(0, 0, 0, 0.18), 0 8px 28px rgba(0, 0, 0, 0.10);
  opacity: 0;
  pointer-events: none;
  transform: translate3d(24px, 0, 0) scale(0.985);
  transform-origin: right center;
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-panel-duration) var(--wizon-motion-spatial-ease);
  will-change: opacity, transform;
}

body.chatgpt-reference-v1 .context-pane[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .context-pane[data-motion-state="open"] {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(0, 0, 0) scale(1);
}

body.chatgpt-reference-v1 .context-pane[data-motion-state="closing"] {
  opacity: 0;
  pointer-events: none;
  transform: translate3d(24px, 0, 0) scale(0.985);
}

body.side-panel-open.chatgpt-reference-v1 .chat-pane {
  transition: filter var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

body.chatgpt-reference-v1 .chatgpt-side-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--cg-menu-border);
}

body.chatgpt-reference-v1 .chatgpt-side-panel-head h2 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-title-18);
  font-weight: 600;
  line-height: 24px;
  letter-spacing: 0;
}

body.chatgpt-reference-v1 .chatgpt-side-panel-kicker {
  margin: 0 0 2px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  line-height: 16px;
  letter-spacing: 0;
}

body.chatgpt-reference-v1 .context-pane .tabs {
  display: flex;
  gap: 6px;
  padding: 10px 12px;
  overflow-x: auto;
  border-bottom: 1px solid var(--cg-menu-border);
  scrollbar-width: none;
}

body.chatgpt-reference-v1 .context-pane .tabs::-webkit-scrollbar {
  display: none;
}

body.chatgpt-reference-v1 .context-pane .tab-button {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: transparent;
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-13);
  font-weight: 500;
  line-height: 18px;
}

body.chatgpt-reference-v1 .context-pane .tab-button:hover,
body.chatgpt-reference-v1 .context-pane .tab-button.active {
  background: var(--cg-hover);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .context-pane .tab-content {
  min-height: 0;
  overflow-x: hidden;
  overflow-y: auto;
  padding: 16px;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}

body.chatgpt-reference-v1 .context-pane .panel-block {
  margin: 0 0 14px;
  border-color: var(--cg-menu-border);
  background: var(--cg-surface);
  color: var(--cg-text);
}

html[data-theme="dark"] body.chatgpt-reference-v1 .context-pane {
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.52), 0 8px 30px rgba(0, 0, 0, 0.36);
}

.chatgpt-reference-v1 .message-list[hidden],
.chatgpt-reference-v1 .chatgpt-composer-shell[hidden],
.chatgpt-reference-v1 .chatgpt-prompt-shelf[hidden] {
  display: none !important;
}

.chatgpt-reference-v1.portal-route-open .chat-pane {
  display: block;
  min-height: 100vh;
  overflow-y: auto;
}

/* 20260706-projects-route-no-home-composer-qa: ChatGPT route pages do not show the home chat prompt. */
.chatgpt-reference-v1.portal-route-open .message-list,
.chatgpt-reference-v1.portal-route-open .chatgpt-composer-shell,
.chatgpt-reference-v1.portal-route-open .composer-surface.chatgpt-composer-shell,
.chatgpt-reference-v1.portal-route-open .chatgpt-prompt-shelf,
/* #trustPanel is a .chatgpt-route-page too, but it is rendered as the LAST child of .chat-pane
   (after the composer) — NOT a preceding sibling of .message-list — so it never matches this
   thread-hide rule. Excluding it here with an ID would raise this rule's specificity and beat the
   docked-file-panel's message-list override, so we keep the selector ID-free. */
.chatgpt-reference-v1 .chatgpt-route-page:not([hidden]) ~ .message-list,
.chatgpt-reference-v1 .chatgpt-route-page:not([hidden]) ~ .chatgpt-composer-shell,
.chatgpt-reference-v1 .chatgpt-route-page:not([hidden]) ~ .composer-surface.chatgpt-composer-shell,
.chatgpt-reference-v1 .chatgpt-route-page:not([hidden]) ~ .chatgpt-prompt-shelf,
html[data-chat-state="route"] body.chatgpt-reference-v1 .message-list,
html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
html[data-chat-state="route"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell,
html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-prompt-shelf,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .message-list,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-prompt-shelf {
  display: none !important;
}

.chatgpt-reference-v1 .chatgpt-route-page[hidden] {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-route-page {
  --chatgpt-route-page-width: min(var(--wizon-ai-chat-max-width), calc(100% - (var(--wizon-ai-thread-gutter) * 6)));
  --chatgpt-route-page-top: calc(var(--wizon-ai-space-unit) * 28);
  --chatgpt-route-page-bottom: var(--ds-space-10, 64px);
  --chatgpt-route-gap-lg: var(--ds-space-8, 40px);
  --chatgpt-route-gap-md: var(--ds-space-6, 24px);
  --chatgpt-route-gap-sm: var(--ds-space-3, 12px);
  --chatgpt-route-gap-xs: var(--ds-space-2, 8px);
  --chatgpt-route-gap-2xs: calc(var(--wizon-ai-space-unit) * 1.5);
  --chatgpt-route-control-height: var(--wizon-ai-menu-row-height);
  --chatgpt-route-control-pad-x: calc(var(--wizon-ai-space-unit) * 3.5);
  --chatgpt-route-control-pad-y: var(--ds-space-2, 8px);
  --chatgpt-route-search-width: calc(var(--wizon-ai-space-unit) * 60);
  --chatgpt-route-search-icon-column: calc(var(--wizon-ai-space-unit) * 4.5);
  --chatgpt-route-search-font-size: var(--wds-font-size-body-2, 14px);
  --chatgpt-route-search-line-height: var(--wds-line-height-label, 20px);
  --chatgpt-route-row-height: calc(var(--wizon-ai-space-unit) * 16.5);
  --chatgpt-route-row-head-height: var(--wizon-ai-menu-row-height);
  --chatgpt-route-row-icon-size: var(--wizon-ai-action-target-sm);
  --chatgpt-route-radius-control: var(--wizon-ai-radius-control);
  --chatgpt-route-radius-lg: var(--wizon-ai-radius-popover);
  --chatgpt-route-radius-pill: var(--wizon-ai-radius-pill);
  --chatgpt-route-body-font-size: var(--wds-font-size-body-2);
  --chatgpt-route-body-line-height: var(--wds-line-height-label);
  --chatgpt-route-title-size: var(--wds-font-size-headline-m, 1.75rem);
  width: var(--chatgpt-route-page-width);
  margin: 0 auto;
  padding: var(--chatgpt-route-page-top) 0 var(--chatgpt-route-page-bottom);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-route-page-inner {
  display: grid;
  gap: var(--chatgpt-route-gap-lg);
}

/* The "새로 만들기" plus glyph only appears when the button collapses to an icon in the
   docked panel header; the full-width library page keeps the labelled "새로 만들기 v" pill. */
.chatgpt-reference-v1 .chatgpt-route-primary-plus {
  display: none;
}
.chatgpt-reference-v1 .chatgpt-route-primary-plus svg {
  width: 20px;
  height: 20px;
}

/* 20260710-conversation-files-desktop-dock: on desktop the chat-scoped file view (docs/153)
   docks as a right rail so the conversation stays visible on the left, instead of taking over
   the whole screen like mobile does. Body class is set only for fine pointers (see
   syncPortalRouteSurfaceVisibility), so mobile/tablet keep the full-screen route. The chat-pane
   gets a matching right padding; the route page is pinned absolutely into that reserved strip,
   so in-flow chat content and the rail never overlap. */
body.library-scope-docked.chatgpt-reference-v1 .chat-pane {
  position: relative;
  padding-right: clamp(360px, 38%, 520px);
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage.chatgpt-route-page {
  position: absolute;
  inset: 0 0 0 auto;
  width: clamp(360px, 38%, 520px);
  margin: 0;
  max-width: none;
  padding: 20px 20px calc(20px + var(--wizon-safe-bottom, 0px));
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--cg-menu-bg, var(--bg));
  border-left: 1px solid var(--line);
  box-shadow: -14px 0 34px rgba(0, 0, 0, 0.06);
  z-index: 40;
  /* the route head (title + fixed-width search + 새로 만들기) is built for a wide page;
     in the narrow rail let it wrap and the search go full-width. */
  --chatgpt-route-search-width: 100%;
}
/* Docked header matches the mobile pattern: title + "새로 만들기" collapse to a "+" icon
   (with hover tooltip) on row 1, and the search goes full-width on row 2. display:contents
   dissolves the actions wrapper so h1 / 새로 만들기 / search can be placed on the grid. */
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-page-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "title new"
    "search search";
  align-items: center;
  column-gap: 8px;
  row-gap: 12px;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-page-head > h1 {
  grid-area: title;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-page-actions {
  display: contents;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-search {
  grid-area: search;
  width: 100%;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-library-menu-anchor {
  grid-area: new;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-primary {
  width: 36px;
  height: 36px;
  min-width: 36px;
  padding: 0;
  gap: 0;
  justify-content: center;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-primary-plus {
  display: inline-flex;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-primary-label,
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-primary-caret {
  display: none;
}
/* keep the conversation "..." actions clear of the docked rail */
body.library-scope-docked.chatgpt-reference-v1 .chatgpt-conversation-actions {
  right: calc(clamp(360px, 38%, 520px) + 22px);
}

/* 20260710-dock-motion: the desktop chat-scoped file rail is NON-modal — the conversation stays
   fully visible, scrollable and interactive on the left (no dimming scrim). The rail slides in/out
   from the right with the same offcanvas motion as the left sidebar drawer. Clicking the empty
   chat background closes it (handleDockBackgroundClick); the closing class runs the exit slide. */
body.library-scope-docked.chatgpt-reference-v1 #portalPage.chatgpt-route-page {
  animation: wizon-dock-in var(--wds-spring-spatial-default-duration, 372ms)
    var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1));
}
body.library-dock-closing.chatgpt-reference-v1 #portalPage.chatgpt-route-page {
  animation: wizon-dock-out var(--wizon-sheet-exit-ms, 300ms)
    var(--wizon-sheet-exit-ease, cubic-bezier(0.33, 0, 0.2, 1)) forwards;
}
@keyframes wizon-dock-in {
  from { translate: 100% 0; }
  to { translate: 0 0; }
}
@keyframes wizon-dock-out {
  from { translate: 0 0; }
  to { translate: 100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  body.library-scope-docked.chatgpt-reference-v1 #portalPage.chatgpt-route-page,
  body.library-dock-closing.chatgpt-reference-v1 #portalPage.chatgpt-route-page {
    animation: none !important;
  }
}

/* 20260710-dock-chat-visible: the global "a route page is open → hide the home composer +
   message-list" rules (display:none !important) also blank the conversation in the docked file
   rail. In the docked view we WANT the chat visible + scrollable on the left, so a more-specific
   override (extra .library-scope-docked class → wins on specificity, not just source order)
   restores the message list and composer. The chat-pane already reserves the right strip
   (padding-right) so the two never overlap. */
html[data-portal-route-open="true"] body.library-scope-docked.chatgpt-reference-v1 .message-list {
  display: block !important;
}

/* 20260710-dock-card-redesign: the desktop chat-scoped file view is a FLOATING ROUNDED CARD on the
   right (over codex's flush full-height rail), matching the Codex/ChatGPT reference — margin on all
   sides, rounded corners, soft shadow. It reuses the mobile-collapsed route header and adds a
   leading "‹" back button (the desktop equivalent of the mobile topbar back). The chat stays
   visible on the left. These override codex's docked #portalPage rules (later source order). */
/* The card OVERLAYS the empty right gutter — it does NOT reserve space, so the centered
   conversation column keeps its exact position/width (no reflow). Override codex's reservation. */
body.library-scope-docked.chatgpt-reference-v1 .chat-pane {
  padding-right: 0;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage.chatgpt-route-page {
  inset: 12px 12px 12px auto;
  width: clamp(360px, 34%, 480px);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 16px 48px rgba(0, 0, 0, 0.16);
}
/* add a leading "back" column to codex's docked header grid (title | new / search) */
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-route-page-head {
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "back title new"
    "search search search";
}
.chatgpt-reference-v1 .chatgpt-library-dock-back {
  display: none;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-library-dock-back {
  grid-area: back;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-right: 2px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-library-dock-back:hover {
  background: var(--cg-hover-soft);
}
body.library-scope-docked.chatgpt-reference-v1 #portalPage .chatgpt-library-dock-back svg {
  width: 22px;
  height: 22px;
}

.chatgpt-reference-v1 .chatgpt-route-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-md);
}

.chatgpt-reference-v1 .chatgpt-route-page-head h1 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--chatgpt-route-title-size);
  font-weight: var(--wds-font-weight-regular);
  letter-spacing: 0;
  line-height: calc(var(--chatgpt-route-title-size) + (var(--wizon-ai-space-unit) * 2));
}

.chatgpt-reference-v1 .chatgpt-route-page-head p {
  margin: var(--chatgpt-route-gap-sm) 0 0;
  color: var(--cg-muted);
  font-size: var(--wds-font-size-body-1);
  line-height: calc(var(--wds-font-size-body-1) * 1.5);
}

.chatgpt-reference-v1 .chatgpt-route-page-actions {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-sm);
}

.chatgpt-reference-v1 .chatgpt-route-search {
  display: inline-grid;
  grid-template-columns: var(--chatgpt-route-search-icon-column) minmax(0, 1fr);
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  width: var(--chatgpt-route-search-width);
  min-height: var(--chatgpt-route-control-height);
  padding: 0 var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .chatgpt-route-search input {
  min-width: 0;
  min-height: 0;
  height: calc(var(--chatgpt-route-control-height) - 2px);
  padding: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--cg-text);
  box-shadow: none;
  font: inherit;
  font-size: var(--chatgpt-route-search-font-size);
  line-height: var(--chatgpt-route-search-line-height);
}

.chatgpt-reference-v1 .chatgpt-route-search input:focus,
.chatgpt-reference-v1 .chatgpt-route-search input:focus-visible {
  border-color: transparent;
  outline: none;
  box-shadow: none;
}

.chatgpt-reference-v1 .chatgpt-route-primary,
.chatgpt-reference-v1 .chatgpt-route-filter {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--chatgpt-route-gap-2xs);
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-control-pad-y) var(--chatgpt-route-control-pad-x);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-medium);
  letter-spacing: 0;
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-route-filter {
  border: 1px solid var(--cg-menu-border);
  background: var(--cg-surface);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-route-tabs {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
}

.chatgpt-reference-v1 .chatgpt-route-tabs button {
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-control-pad-y) var(--chatgpt-route-control-pad-x);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-route-tabs button.is-active {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-table {
  display: grid;
  gap: 0;
  margin-top: calc(var(--chatgpt-route-gap-2xs) * -1);
}

.chatgpt-reference-v1 .chatgpt-library-menu-anchor {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.chatgpt-reference-v1 .chatgpt-library-popover {
  position: absolute;
  z-index: 35;
  top: calc(100% + var(--chatgpt-route-gap-xs));
  right: 0;
  display: grid;
  min-width: calc(var(--wizon-ai-space-unit) * 50);
  padding: var(--chatgpt-route-gap-2xs);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-lg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-popover strong {
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm) var(--chatgpt-route-gap-2xs);
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-library-menu-item {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  width: 100%;
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-regular);
  line-height: var(--chatgpt-route-body-line-height);
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-library-menu-item.is-selected {
  color: var(--cg-text);
  font-weight: var(--wds-font-weight-medium);
}

.chatgpt-reference-v1 .chatgpt-library-menu-check {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-icon-size-md);
  height: var(--wizon-ai-icon-size-md);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-menu-item:hover,
.chatgpt-reference-v1 .chatgpt-library-menu-item:focus-visible {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-library-menu-item-danger {
  color: var(--cg-danger-fg);
}

.chatgpt-reference-v1 .chatgpt-library-menu-item-muted {
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-filter-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-md);
}

/* 20260710-conversation-files: scope bar for "채팅 내 파일 보기" (library route scoped to one chat). */
.chatgpt-reference-v1 .chatgpt-library-scope-bar {
  display: flex;
  margin: 4px 0 2px;
}

.chatgpt-reference-v1 .chatgpt-library-scope-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 6px 0 10px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: 500;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-scope-chip svg {
  width: 16px;
  height: 16px;
}

.chatgpt-reference-v1 .chatgpt-library-scope-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  background: transparent;
  color: var(--cg-muted-2);
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-library-scope-clear:hover {
  background: var(--cg-hover);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-scope-clear svg {
  width: 15px;
  height: 15px;
}

.chatgpt-reference-v1 .chatgpt-library-scope-note {
  margin: 8px 2px 0;
  font-size: var(--ds-text-caption-12);
  color: var(--cg-muted-2);
}

.chatgpt-reference-v1 .chatgpt-library-view-controls {
  display: inline-flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-view-control {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-view-control:hover,
.chatgpt-reference-v1 .chatgpt-library-view-control.is-active {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-view-control[aria-pressed="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-filter-count {
  position: absolute;
  right: calc(var(--chatgpt-route-gap-2xs) * -1);
  top: calc(var(--chatgpt-route-gap-2xs) * -1);
  display: inline-grid;
  place-items: center;
  min-width: calc(var(--wizon-ai-space-unit) * 4);
  height: calc(var(--wizon-ai-space-unit) * 4);
  padding: 0 var(--chatgpt-route-gap-2xs);
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  line-height: 1;
}

.chatgpt-reference-v1 .chatgpt-library-view-divider {
  width: 1px;
  height: var(--wizon-ai-action-target-sm);
  margin: 0 var(--chatgpt-route-gap-xs);
  background: var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-library-action-feedback {
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 [data-library-bulk-bar] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
}

.chatgpt-reference-v1 [data-library-bulk-bar] .chatgpt-library-create-submit {
  margin-left: auto;
}

.chatgpt-reference-v1 .chatgpt-library-row {
  display: grid;
  grid-template-columns: var(--ds-space-9, 48px) minmax(0, 1fr) calc(var(--wizon-ai-space-unit) * 40) calc(var(--wizon-ai-space-unit) * 28);
  align-items: center;
  width: 100%;
  min-height: var(--chatgpt-route-row-height);
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--cg-menu-border);
  background: transparent;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  font-family: inherit;
  line-height: var(--chatgpt-route-body-line-height);
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-library-row:not(.chatgpt-library-row--head),
.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger {
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-library-row:hover,
.chatgpt-reference-v1 .chatgpt-library-row:focus-visible {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-library-row:not(.chatgpt-library-row--head):active {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-row--head {
  min-height: var(--chatgpt-route-row-head-height);
  padding: 0;
  background: transparent;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-row-shell {
  position: relative;
}

.chatgpt-reference-v1 .chatgpt-library-file-copy {
  display: grid;
  min-width: 0;
  gap: 3px;
  padding: 8px 12px 8px 0;
}

/* 부제(수정일 · 크기 병합)는 폰 전용 슬롯이다. 데스크톱은 열이 충분해 표가 맞으므로 숨긴다 —
   숨김이라 스크린리더도 읽지 않아 date/size 열과 중복 낭독되지 않는다. 폰에서는 반대로
   date/size 를 숨기고 이 줄만 남긴다(20260802-library-mobile-native-list). */
.chatgpt-reference-v1 .chatgpt-library-row-meta {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-library-file-name {
  overflow: hidden;
  color: var(--cg-text);
  font-weight: var(--wds-font-weight-medium);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-search-snippet {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.35;
}

.chatgpt-reference-v1 .chatgpt-library-search-snippet > span {
  display: -webkit-box;
  min-width: 0;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.chatgpt-reference-v1 .chatgpt-library-search-snippet > small {
  flex: 0 0 auto;
  color: var(--cg-text);
  font: inherit;
  font-weight: var(--wds-font-weight-medium);
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-search-snippet mark {
  border-radius: var(--chatgpt-route-gap-2xs);
  background: color-mix(in srgb, var(--wds-brand-blue) 12%, transparent);
  color: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-search-status {
  min-height: 18px;
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

.chatgpt-reference-v1 .chatgpt-library-search-status.is-error {
  color: var(--cg-warning-fg);
}

.chatgpt-reference-v1 .chatgpt-library-processing-state {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-processing-state[data-state="failed"] {
  color: var(--cg-danger-fg);
}

.chatgpt-reference-v1 .chatgpt-library-processing-state[data-state="background"] {
  color: var(--ad-blue);
}

.chatgpt-reference-v1 .chatgpt-library-processing-state[data-state="degraded"] {
  color: var(--cg-warning-fg);
}

.chatgpt-reference-v1 .chatgpt-library-processing-progress {
  display: block;
  appearance: none;
  width: min(240px, 100%);
  height: 3px;
  overflow: hidden;
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-library-processing-progress::-webkit-progress-bar {
  background: var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-library-processing-progress::-webkit-progress-value,
.chatgpt-reference-v1 .chatgpt-library-processing-progress::-moz-progress-bar {
  border-radius: var(--ds-radius-pill);
  background: var(--ad-blue);
}

.chatgpt-reference-v1 .chatgpt-library-row.is-selected,
.chatgpt-reference-v1 .chatgpt-library-row-shell.is-selected .chatgpt-library-row {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-create-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--ds-space-6, 24px);
  background: rgba(0, 0, 0, 0.38);
}

.chatgpt-reference-v1 .chatgpt-library-create-form {
  display: grid;
  gap: var(--chatgpt-route-gap-md);
  width: min(calc(var(--wizon-ai-space-unit) * 112), calc(100vw - var(--ds-space-8, 40px)));
  padding: var(--ds-space-6, 24px);
  border: 1px solid var(--cg-menu-border);
  border-radius: calc(var(--chatgpt-route-radius-control) + var(--chatgpt-route-gap-xs));
  background: var(--cg-surface);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.22);
  color: var(--cg-text);
  font-family: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-create-form h2 {
  margin: 0;
  font-size: calc(var(--chatgpt-route-title-size) * 0.5);
  font-weight: 600;
  line-height: calc(var(--chatgpt-route-title-size) * 0.68);
  letter-spacing: 0;
}

.chatgpt-reference-v1 .chatgpt-library-create-field {
  display: grid;
  gap: var(--chatgpt-route-gap-xs);
  color: var(--cg-text);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-library-create-input {
  min-width: 0;
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-create-input:focus-visible {
  outline: 2px solid var(--cg-focus-ring, rgba(16, 163, 127, 0.45));
  outline-offset: 2px;
}

.chatgpt-reference-v1 .chatgpt-library-create-actions {
  display: inline-flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
}

.chatgpt-reference-v1 .chatgpt-library-create-submit,
.chatgpt-reference-v1 .chatgpt-library-create-cancel {
  display: inline-grid;
  place-items: center;
  min-width: calc(var(--wizon-ai-space-unit) * 16);
  min-height: var(--wizon-ai-action-target-sm);
  padding: 0 var(--chatgpt-route-gap-sm);
  border-radius: var(--chatgpt-route-radius-pill);
  font: inherit;
  font-weight: 600;
}

.chatgpt-reference-v1 .chatgpt-library-create-cancel {
  border: 1px solid var(--cg-menu-border);
  background: var(--cg-surface);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-create-submit {
  border: 1px solid var(--cg-text);
  background: var(--cg-text);
  color: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-library-create-submit:hover,
.chatgpt-reference-v1 .chatgpt-library-create-submit:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-create-cancel:hover,
.chatgpt-reference-v1 .chatgpt-library-create-cancel:focus-visible {
  filter: brightness(0.96);
}

.chatgpt-reference-v1 .chatgpt-library-rename-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--ds-space-6, 24px);
  background: rgba(0, 0, 0, 0.38);
}

.chatgpt-reference-v1 .chatgpt-library-rename-form {
  display: grid;
  gap: var(--chatgpt-route-gap-md);
  width: min(calc(var(--wizon-ai-space-unit) * 112), calc(100vw - var(--ds-space-8, 40px)));
  padding: var(--ds-space-6, 24px);
  border: 1px solid var(--cg-menu-border);
  border-radius: calc(var(--chatgpt-route-radius-control) + var(--chatgpt-route-gap-xs));
  background: var(--cg-surface);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.22);
  color: var(--cg-text);
  font-family: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-rename-form h2 {
  margin: 0;
  font-size: calc(var(--chatgpt-route-title-size) * 0.5);
  font-weight: 600;
  line-height: calc(var(--chatgpt-route-title-size) * 0.68);
  letter-spacing: 0;
}

.chatgpt-reference-v1 .chatgpt-library-rename-input {
  min-width: 0;
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-rename-input:focus-visible {
  outline: 2px solid var(--cg-focus-ring, rgba(16, 163, 127, 0.45));
  outline-offset: 2px;
}

.chatgpt-reference-v1 .chatgpt-library-rename-actions {
  display: inline-flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
}

.chatgpt-reference-v1 .chatgpt-library-rename-submit,
.chatgpt-reference-v1 .chatgpt-library-rename-cancel {
  display: inline-grid;
  place-items: center;
  min-width: calc(var(--wizon-ai-space-unit) * 16);
  min-height: var(--wizon-ai-action-target-sm);
  padding: 0 var(--chatgpt-route-gap-sm);
  border-radius: var(--chatgpt-route-radius-pill);
  font: inherit;
  font-weight: 600;
}

.chatgpt-reference-v1 .chatgpt-library-rename-cancel {
  border: 1px solid var(--cg-menu-border);
  background: var(--cg-surface);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-rename-submit {
  border: 1px solid var(--cg-text);
  background: var(--cg-text);
  color: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-library-rename-submit:hover,
.chatgpt-reference-v1 .chatgpt-library-rename-submit:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-rename-cancel:hover,
.chatgpt-reference-v1 .chatgpt-library-rename-cancel:focus-visible {
  filter: brightness(0.96);
}

.chatgpt-reference-v1 .chatgpt-library-move-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: var(--ds-space-6, 24px);
  background: rgba(0, 0, 0, 0.38);
}

.chatgpt-reference-v1 .chatgpt-library-move-dialog {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  width: min(calc(var(--wizon-ai-space-unit) * 218), calc(100vw - var(--ds-space-8, 40px)));
  height: min(calc(100svh - calc(var(--wizon-ai-space-unit) * 38)), calc(var(--wizon-ai-space-unit) * 157));
  min-height: calc(var(--wizon-ai-space-unit) * 96);
  overflow: hidden;
  border: 1px solid var(--cg-menu-border);
  border-radius: calc(var(--chatgpt-route-radius-control) + var(--chatgpt-route-gap-xs));
  background: var(--cg-surface);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.24);
  color: var(--cg-text);
  font-family: inherit;
}

.chatgpt-reference-v1 .chatgpt-library-move-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-width: 0;
  padding: var(--chatgpt-route-gap-lg) var(--chatgpt-route-gap-lg) var(--chatgpt-route-gap-sm);
}

.chatgpt-reference-v1 .chatgpt-library-move-dialog h2 {
  margin: 0;
  overflow: hidden;
  font-size: calc(var(--chatgpt-route-title-size) * 0.5);
  font-weight: 600;
  line-height: calc(var(--chatgpt-route-title-size) * 0.68);
  letter-spacing: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-move-close {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-move-close:hover,
.chatgpt-reference-v1 .chatgpt-library-move-close:focus-visible {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-move-breadcrumb {
  min-width: 0;
  padding: 0 var(--chatgpt-route-gap-lg) var(--chatgpt-route-gap-sm);
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-move-list {
  min-height: 0;
  margin: 0 var(--chatgpt-route-gap-lg);
  overflow: auto;
  border-top: 1px solid var(--cg-menu-border);
  border-bottom: 1px solid var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-library-move-entry {
  display: grid;
  grid-template-columns: var(--chatgpt-route-row-icon-size) minmax(0, 1fr);
  align-items: center;
  gap: var(--chatgpt-route-gap-sm);
  width: 100%;
  min-height: calc(var(--wizon-ai-space-unit) * 16);
  padding: 0 var(--chatgpt-route-gap-sm);
  border: 0;
  border-bottom: 1px solid var(--cg-menu-border);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-library-move-entry:last-child {
  border-bottom: 0;
}

.chatgpt-reference-v1 .chatgpt-library-move-entry:hover,
.chatgpt-reference-v1 .chatgpt-library-move-entry:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-move-entry.is-selected {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-library-move-entry.is-disabled {
  color: var(--cg-muted);
  cursor: default;
}

.chatgpt-reference-v1 .chatgpt-library-move-entry.is-empty {
  display: grid;
  place-items: center;
  min-height: calc(var(--wizon-ai-space-unit) * 24);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-move-entry-icon {
  display: inline-grid;
  place-items: center;
  width: var(--chatgpt-route-row-icon-size);
  height: var(--chatgpt-route-row-icon-size);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-move-footer {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-md) var(--chatgpt-route-gap-lg) var(--chatgpt-route-gap-lg);
}

.chatgpt-reference-v1 .chatgpt-library-move-footer-spacer {
  flex: 1 1 auto;
}

.chatgpt-reference-v1 .chatgpt-library-move-new-folder,
.chatgpt-reference-v1 .chatgpt-library-move-cancel,
.chatgpt-reference-v1 .chatgpt-library-move-submit {
  display: inline-grid;
  place-items: center;
  min-width: calc(var(--wizon-ai-space-unit) * 16);
  min-height: var(--wizon-ai-action-target-sm);
  padding: 0 var(--chatgpt-route-gap-sm);
  border-radius: var(--chatgpt-route-radius-pill);
  font: inherit;
  font-weight: 600;
}

.chatgpt-reference-v1 .chatgpt-library-move-new-folder,
.chatgpt-reference-v1 .chatgpt-library-move-cancel {
  border: 1px solid var(--cg-menu-border);
  background: var(--cg-surface);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-move-submit {
  border: 1px solid var(--cg-text);
  background: var(--cg-text);
  color: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-library-move-new-folder:hover,
.chatgpt-reference-v1 .chatgpt-library-move-new-folder:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-move-cancel:hover,
.chatgpt-reference-v1 .chatgpt-library-move-cancel:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-move-submit:hover,
.chatgpt-reference-v1 .chatgpt-library-move-submit:focus-visible {
  filter: brightness(0.96);
}

.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger {
  position: absolute;
  top: 50%;
  right: var(--chatgpt-route-gap-2xs);
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-muted);
  transform: translateY(-50%);
}

.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger:hover,
.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger[aria-expanded="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-file-menu {
  top: calc(100% - var(--chatgpt-route-gap-2xs));
  right: var(--chatgpt-route-gap-2xs);
}

.chatgpt-reference-v1 .chatgpt-library-file-icon {
  display: inline-grid;
  place-items: center;
  width: var(--chatgpt-route-row-icon-size);
  height: var(--chatgpt-route-row-icon-size);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view {
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--wizon-ai-space-unit) * 52), 1fr));
  gap: var(--chatgpt-route-gap-sm);
  margin-top: 0;
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-row--head {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-row-shell {
  min-height: calc(var(--wizon-ai-space-unit) * 28);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-row {
  grid-template-columns: var(--chatgpt-route-row-icon-size) minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  gap: var(--chatgpt-route-gap-2xs) var(--chatgpt-route-gap-sm);
  align-content: start;
  min-height: calc(var(--wizon-ai-space-unit) * 28);
  padding: var(--chatgpt-route-gap-md) calc(var(--wizon-ai-action-target-sm) + var(--chatgpt-route-gap-md)) var(--chatgpt-route-gap-md) var(--chatgpt-route-gap-md);
  border-bottom: 0;
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-file-copy {
  color: var(--cg-text);
  font-weight: var(--wds-font-weight-medium);
}

.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-row-date,
.chatgpt-reference-v1 .chatgpt-library-table.is-grid-view .chatgpt-library-row-size {
  grid-column: 2;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-library-empty {
  display: grid;
  justify-items: center;
  gap: var(--chatgpt-route-gap-sm);
  padding: calc(var(--wizon-ai-space-unit) * 12) var(--chatgpt-route-gap-md);
  color: var(--cg-text);
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-library-empty p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-library-preview-backdrop {
  position: fixed;
  inset: 0;
  z-index: 320;
  display: flex;
  background: var(--cg-surface);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-preview-dialog {
  display: grid;
  grid-template-rows: var(--chatgpt-header-height) minmax(0, 1fr) auto;
  width: 100%;
  min-width: 0;
  min-height: 100svh;
  background: var(--cg-surface);
  outline: none;
}

.chatgpt-reference-v1 .chatgpt-library-preview-topbar {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--chatgpt-route-gap-md);
  min-width: 0;
  padding: 0 var(--chatgpt-route-gap-lg);
  border-bottom: 1px solid var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-library-preview-breadcrumb {
  display: inline-flex;
  align-items: center;
  min-width: 0;
  gap: var(--chatgpt-route-gap-xs);
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-preview-breadcrumb strong {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-text);
  font-weight: var(--wds-font-weight-medium);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-library-preview-actions {
  display: inline-flex;
  align-items: center;
  justify-self: end;
  gap: var(--chatgpt-route-gap-2xs);
}

.chatgpt-reference-v1 .chatgpt-library-preview-icon-button,
.chatgpt-reference-v1 .chatgpt-library-preview-composer-button,
.chatgpt-reference-v1 .chatgpt-library-preview-submit {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-preview-icon-button:hover,
.chatgpt-reference-v1 .chatgpt-library-preview-icon-button:focus-visible,
.chatgpt-reference-v1 .chatgpt-library-preview-composer-button:hover,
.chatgpt-reference-v1 .chatgpt-library-preview-composer-button:focus-visible {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-library-preview-stage {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: var(--chatgpt-route-gap-lg);
  background: var(--cg-surface);
  overflow: auto;
}

.chatgpt-reference-v1 .chatgpt-library-preview-image {
  display: block;
  max-width: min(calc(var(--wizon-ai-space-unit) * 168), calc(100% - var(--chatgpt-route-gap-lg) * 2));
  max-height: min(68svh, calc(var(--wizon-ai-space-unit) * 150));
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  object-fit: contain;
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-pane {
  display: grid;
  justify-items: stretch;
  align-content: start;
  gap: var(--chatgpt-route-gap-sm);
  width: min(calc(var(--wizon-ai-space-unit) * 168), calc(100% - var(--chatgpt-route-gap-lg) * 2));
  max-width: min(calc(var(--wizon-ai-space-unit) * 168), calc(100% - var(--chatgpt-route-gap-lg) * 2));
  max-height: min(68svh, calc(var(--wizon-ai-space-unit) * 150));
  padding: 0;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: none;
  text-align: left;
  overflow: hidden;
}

.chatgpt-reference-v1 .chatgpt-library-preview-file-icon {
  display: inline-grid;
  place-items: center;
  width: var(--chatgpt-route-row-icon-size);
  height: var(--chatgpt-route-row-icon-size);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-title strong {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-word;
  color: var(--cg-text);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-title {
  display: flex;
  align-items: center;
  min-width: 0;
  gap: var(--chatgpt-route-gap-sm);
  padding: var(--chatgpt-route-gap-md) var(--chatgpt-route-gap-lg) 0;
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-title span:last-child {
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-body {
  min-height: calc(var(--wizon-ai-space-unit) * 44);
  max-height: min(54svh, calc(var(--wizon-ai-space-unit) * 120));
  margin: var(--chatgpt-route-gap-md) 0 0;
  padding: var(--chatgpt-route-gap-md) var(--chatgpt-route-gap-lg);
  border: 0;
  border-top: 1px solid var(--cg-menu-border);
  border-radius: 0;
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  line-height: var(--chatgpt-route-body-line-height);
  overflow: auto;
  white-space: pre-wrap;
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-body.is-empty {
  display: grid;
  place-items: center;
  color: var(--cg-muted);
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-library-preview-document-pane span:last-child {
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
}

.chatgpt-reference-v1 .chatgpt-library-preview-composer.chatgpt-composer-shell {
  position: relative;
  z-index: 1;
  width: min(calc(var(--cg-chat-max-width) - (var(--cg-thread-gutter) * 2)), calc(100% - (var(--cg-thread-gutter) * 3)));
  margin: 0 auto var(--chatgpt-route-gap-lg);
}

.chatgpt-reference-v1 .chatgpt-library-preview-composer .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto;
  grid-template-rows: 42px;
  grid-template-areas: "lead input actions";
  align-items: center;
  min-height: 42px;
  padding: 0;
}

.chatgpt-reference-v1 .chatgpt-library-preview-composer .composer-attachment-lane {
  display: none;
}

.chatgpt-reference-v1 .chatgpt-library-preview-composer .composer-textarea-scroll {
  align-self: center;
  display: flex;
  align-items: center;
  min-height: 26px;
  height: 26px;
  overflow-y: hidden;
}

.chatgpt-reference-v1 .chatgpt-library-preview-composer .composer-action-dock {
  align-self: center;
  display: inline-flex;
  flex-flow: row nowrap;
  align-items: center;
  justify-content: flex-end;
  width: auto;
  min-width: 0;
  min-height: 38px;
  gap: 6px;
}

.chatgpt-reference-v1 .chatgpt-library-preview-prompt-input {
  display: block;
  width: 100%;
  min-width: 0;
  min-height: 26px;
  height: 26px;
  max-height: 26px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--cg-text);
  box-shadow: none;
  font: inherit;
  font-size: var(--ds-text-body-16);
  line-height: 26px;
  outline: none;
  overflow: hidden;
  resize: none;
}

.chatgpt-reference-v1 .chatgpt-library-preview-prompt-input:focus,
.chatgpt-reference-v1 .chatgpt-library-preview-prompt-input:focus-visible,
body.chatgpt-reference-v1 .chatgpt-library-preview-composer .chatgpt-library-preview-prompt-input:focus,
body.chatgpt-reference-v1 .chatgpt-library-preview-composer .chatgpt-library-preview-prompt-input:focus-visible,
body.chatgpt-reference-v1 .chatgpt-library-preview-composer:focus-within {
  border-color: transparent;
  outline: none;
  box-shadow: none;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-prompt-input::placeholder {
  color: var(--cg-input-placeholder);
}

.chatgpt-reference-v1 .chatgpt-library-preview-submit {
  width: 38px;
  height: 38px;
  min-width: 38px;
  background: var(--cg-text);
  color: var(--cg-surface);
}

@media (max-width: 520px) {
  .chatgpt-reference-v1 .chatgpt-library-preview-composer .composer-action-dock {
    min-width: 0;
    gap: 4px;
  }
}

.chatgpt-reference-v1 .chatgpt-project-empty {
  display: grid;
  justify-items: center;
  gap: calc(var(--wizon-ai-space-unit) * 4.5);
  margin-top: calc(var(--wizon-ai-space-unit) * 13.5);
  color: var(--cg-text);
  font-size: var(--wds-font-size-body-1);
  font-weight: var(--wds-font-weight-regular);
  line-height: calc(var(--wds-font-size-body-1) * 1.5);
}

.chatgpt-reference-v1 .chatgpt-project-empty p {
  margin: 0;
  max-width: calc(var(--wizon-ai-space-unit) * 96);
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-project-action-feedback {
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--wizon-ai-space-unit) * 58), 1fr));
  gap: var(--chatgpt-route-gap-sm);
}

.chatgpt-reference-v1 .chatgpt-project-card {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-lg) minmax(0, 1fr);
  align-items: center;
  gap: var(--chatgpt-route-gap-sm);
  min-height: calc(var(--wizon-ai-space-unit) * 19);
  padding: var(--ds-space-4, 16px);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-project-card:hover,
.chatgpt-reference-v1 .chatgpt-project-card:focus-visible,
.chatgpt-reference-v1 .chatgpt-project-card.is-active {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-project-card-copy {
  display: grid;
  gap: var(--chatgpt-route-gap-2xs);
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-project-card-copy strong,
.chatgpt-reference-v1 .chatgpt-project-card-copy small {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-project-card-copy small {
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption);
}

/* 20260708-project-card-manage: per-project options menu (rename / delete) + inline
   rename input. The card is wrapped in a relatively-positioned shell so the ⋯ trigger
   can overlay the top-right without nesting an interactive control inside the card. */
.chatgpt-reference-v1 .chatgpt-project-card-shell {
  position: relative;
  display: flex;
}

.chatgpt-reference-v1 .chatgpt-project-card-shell .chatgpt-project-card {
  flex: 1;
  min-width: 0;
  padding-right: calc(var(--ds-space-4, 16px) + 28px);
}

.chatgpt-reference-v1 .chatgpt-project-card-shell.is-renaming {
  align-items: center;
  gap: var(--chatgpt-route-gap-sm);
  min-height: calc(var(--wizon-ai-space-unit) * 19);
  padding: var(--ds-space-4, 16px);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-project-rename-input {
  flex: 1;
  min-width: 0;
  min-height: 36px;
  padding: 0 10px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-sm, 10px);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
}

.chatgpt-reference-v1 .chatgpt-project-card-menu-anchor {
  position: absolute;
  top: 8px;
  right: 8px;
}

.chatgpt-reference-v1 .chatgpt-project-card-menu-trigger {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  color: var(--cg-muted);
  background: transparent;
}

.chatgpt-reference-v1 .chatgpt-project-card-menu-trigger:hover,
.chatgpt-reference-v1 .chatgpt-project-card-menu-trigger:focus-visible,
.chatgpt-reference-v1 .chatgpt-project-card-menu-trigger[aria-expanded="true"] {
  background: var(--cg-hover-soft, #f4f4f5);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-project-card-menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 30;
  display: flex;
  flex-direction: column;
  min-width: 148px;
  padding: 6px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 12px;
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow);
}

.chatgpt-reference-v1 .chatgpt-project-card-menu-danger {
  color: #b91c1c;
}

.chatgpt-reference-v1 .chatgpt-project-create-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: grid;
  place-items: center;
  padding: var(--ds-space-6, 24px);
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(1px);
}

.chatgpt-reference-v1 .chatgpt-project-create-dialog {
  display: grid;
  gap: var(--chatgpt-route-gap-md);
  width: min(calc(var(--wizon-ai-space-unit) * 118), calc(100vw - var(--ds-space-8, 40px)));
  padding: var(--ds-space-6, 24px);
  border: 1px solid var(--cg-menu-border);
  border-radius: calc(var(--chatgpt-route-radius-control) + var(--chatgpt-route-gap-xs));
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-xl);
  color: var(--cg-text);
  font-family: inherit;
}

.chatgpt-reference-v1 .chatgpt-project-create-head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--chatgpt-route-gap-xs);
  min-height: var(--wizon-ai-action-target-sm);
}

.chatgpt-reference-v1 .chatgpt-project-create-settings-anchor {
  position: relative;
  display: inline-grid;
  place-items: center;
}

.chatgpt-reference-v1 .chatgpt-project-create-settings,
.chatgpt-reference-v1 .chatgpt-project-create-close {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-project-create-settings:hover,
.chatgpt-reference-v1 .chatgpt-project-create-close:hover,
.chatgpt-reference-v1 .chatgpt-project-create-settings:focus-visible,
.chatgpt-reference-v1 .chatgpt-project-create-close:focus-visible,
.chatgpt-reference-v1 .chatgpt-project-create-settings[aria-expanded="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-project-create-settings-menu {
  position: absolute;
  top: calc(100% + var(--chatgpt-route-gap-xs));
  right: 0;
  z-index: 2;
  display: grid;
  gap: var(--chatgpt-route-gap-2xs);
  width: min(calc(var(--wizon-ai-space-unit) * 80), calc(100vw - var(--ds-space-8, 40px)));
  padding: var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-md);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-project-create-settings-menu > strong {
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-semibold, 600);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-project-create-settings-menu > small {
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption, 0.8125rem);
  line-height: calc(var(--wds-font-size-caption, 0.8125rem) * 1.4);
}

.chatgpt-reference-v1 .chatgpt-project-memory-option {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-xs) minmax(0, 1fr);
  gap: var(--chatgpt-route-gap-xs);
  align-items: start;
  min-height: calc(var(--wizon-ai-space-unit) * 15);
  padding: var(--chatgpt-route-gap-xs);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  text-align: left;
  font: inherit;
}

.chatgpt-reference-v1 .chatgpt-project-memory-option:hover,
.chatgpt-reference-v1 .chatgpt-project-memory-option:focus-visible,
.chatgpt-reference-v1 .chatgpt-project-memory-option[aria-checked="true"] {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .chatgpt-project-memory-option > span:first-child {
  display: inline-grid;
  place-items: center;
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-project-memory-option strong,
.chatgpt-reference-v1 .chatgpt-project-memory-option small {
  display: block;
}

.chatgpt-reference-v1 .chatgpt-project-memory-option strong {
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-semibold, 600);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-project-memory-option small {
  margin-top: var(--chatgpt-route-gap-2xs);
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption, 0.8125rem);
  line-height: calc(var(--wds-font-size-caption, 0.8125rem) * 1.4);
}

.chatgpt-reference-v1 .chatgpt-project-create-dialog h2 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--wds-font-size-title-l);
  font-weight: var(--wds-font-weight-semibold, 600);
  line-height: calc(var(--wds-font-size-title-l) * 1.35);
}

.chatgpt-reference-v1 .chatgpt-project-create-dialog p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: calc(var(--chatgpt-route-body-line-height) * 1.15);
}

.chatgpt-reference-v1 .chatgpt-project-create-field {
  display: grid;
  gap: var(--chatgpt-route-gap-xs);
  color: var(--cg-text);
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-medium);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-project-create-input {
  min-width: 0;
  min-height: calc(var(--wizon-ai-space-unit) * 11);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
}

.chatgpt-reference-v1 .chatgpt-project-create-input:focus-visible {
  outline: 2px solid var(--cg-focus-ring, rgba(16, 163, 127, 0.45));
  outline-offset: 2px;
}

.chatgpt-reference-v1 .chatgpt-project-create-submit {
  display: inline-grid;
  place-items: center;
  justify-self: end;
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-control-pad-y) var(--chatgpt-route-control-pad-x);
  border: 1px solid var(--cg-text);
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-text);
  color: var(--cg-surface);
  font: inherit;
  font-weight: var(--wds-font-weight-semibold, 600);
}

.chatgpt-reference-v1 .chatgpt-project-create-submit:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.chatgpt-reference-v1 .chatgpt-route-empty-icon {
  display: inline-grid;
  place-items: center;
  width: calc(var(--wizon-ai-space-unit) * 14);
  height: calc(var(--wizon-ai-space-unit) * 14);
  border-radius: var(--chatgpt-route-radius-lg);
  background: var(--cg-hover);
}

.chatgpt-reference-v1 .chatgpt-route-empty-icon svg {
  width: calc(var(--wizon-ai-space-unit) * 7);
  height: calc(var(--wizon-ai-space-unit) * 7);
}

.chatgpt-reference-v1 .chatgpt-scheduled-page {
  gap: var(--ds-space-7, 32px);
}

/* 20260708-scheduled-task-list: render actual scheduled tasks (previously the page
   only ever showed an empty state). */
.chatgpt-reference-v1 .chatgpt-scheduled-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--cg-menu-border, #ececec);
  border-radius: 16px;
  background: var(--cg-surface);
}

.chatgpt-reference-v1 .chatgpt-scheduled-item[data-scheduled-status="completed"] {
  opacity: 0.62;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--cg-hover-soft, #f4f4f5);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-title {
  font-size: var(--ds-text-body-15);
  font-weight: 600;
  color: var(--cg-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item[data-scheduled-status="completed"] .chatgpt-scheduled-item-title {
  text-decoration: line-through;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-scheduled-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: var(--ds-radius-pill, 999px);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}

.chatgpt-reference-v1 .chatgpt-scheduled-badge.is-active {
  background: rgba(22, 163, 74, 0.12);
  color: #15803d;
}

.chatgpt-reference-v1 .chatgpt-scheduled-badge.is-paused {
  background: rgba(217, 119, 6, 0.12);
  color: #b45309;
}

.chatgpt-reference-v1 .chatgpt-scheduled-badge.is-completed {
  background: rgba(107, 114, 128, 0.14);
  color: #4b5563;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-actions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-action {
  padding: 6px 12px;
  border: 1px solid var(--cg-menu-border, #ececec);
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-surface);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: 500;
  transition: background 150ms ease, border-color 150ms ease;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-action:hover,
.chatgpt-reference-v1 .chatgpt-scheduled-item-action:focus-visible {
  background: var(--cg-hover-soft, #f4f4f5);
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-action.is-danger {
  color: #b91c1c;
}

.chatgpt-reference-v1 .chatgpt-scheduled-item-action.is-danger:hover,
.chatgpt-reference-v1 .chatgpt-scheduled-item-action.is-danger:focus-visible {
  background: rgba(185, 28, 28, 0.08);
  border-color: rgba(185, 28, 28, 0.28);
}

@media (max-width: 520px) {
  .chatgpt-reference-v1 .chatgpt-scheduled-item {
    grid-template-columns: 36px minmax(0, 1fr);
    grid-template-areas:
      "icon body"
      "actions actions";
    row-gap: 10px;
  }
  .chatgpt-reference-v1 .chatgpt-scheduled-item-icon { grid-area: icon; }
  .chatgpt-reference-v1 .chatgpt-scheduled-item-body { grid-area: body; }
  .chatgpt-reference-v1 .chatgpt-scheduled-item-actions {
    grid-area: actions;
    justify-content: flex-end;
    flex-wrap: wrap;
  }
}

/* 축③ S4 — 워크플로우 합집합 뷰("진행 중"). 새 색상·반경·그림자 토큰을 만들지 않는다 —
   .chatgpt-scheduled-item 이 이미 쓰는 것과 같은 var() 집합만 재사용한다. */
.chatgpt-reference-v1 .workflow-inbox-page {
  gap: var(--ds-space-7, 32px);
}

.chatgpt-reference-v1 .workflow-inbox-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.chatgpt-reference-v1 .workflow-inbox-item {
  margin: 0;
  padding: 0;
}

.chatgpt-reference-v1 .workflow-inbox-item-open {
  display: grid;
  width: 100%;
  grid-template-columns: 40px minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
}

.chatgpt-reference-v1 .workflow-inbox-item-open:hover,
.chatgpt-reference-v1 .workflow-inbox-item-open:focus-visible {
  background: var(--cg-hover-soft);
}

.chatgpt-reference-v1 .workflow-inbox-item-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .workflow-inbox-item-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}

.chatgpt-reference-v1 .workflow-inbox-item-title {
  font-size: var(--ds-text-body-15);
  font-weight: 600;
  color: var(--cg-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .workflow-inbox-item-detail {
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .workflow-inbox-status {
  margin: 0;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .workflow-inbox-status.is-error {
  color: var(--cg-text);
}

.chatgpt-reference-v1 .workflow-inbox-truncated-note {
  margin: 0;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-scheduled-filter-anchor {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.chatgpt-reference-v1 .chatgpt-scheduled-filter-menu {
  position: absolute;
  z-index: 35;
  top: calc(100% + var(--chatgpt-route-gap-xs));
  right: 0;
  display: grid;
  min-width: calc(var(--wizon-ai-space-unit) * 42);
  padding: var(--chatgpt-route-gap-2xs);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-lg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-scheduled-filter-option {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  font-size: var(--chatgpt-route-body-font-size);
  font-weight: var(--wds-font-weight-medium);
  line-height: var(--chatgpt-route-body-line-height);
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-scheduled-filter-option:hover,
.chatgpt-reference-v1 .chatgpt-scheduled-filter-option:focus-visible {
  background: var(--cg-hover-soft);
  outline: none;
}

.chatgpt-reference-v1 .chatgpt-scheduled-filter-option[aria-checked="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer {
  display: grid;
  grid-template-columns: var(--ds-space-8, 40px) minmax(0, 1fr) var(--ds-space-8, 40px);
  align-items: center;
  gap: calc(var(--wizon-ai-space-unit) / 2);
  min-height: calc(var(--wizon-ai-space-unit) * 14.5);
  padding: var(--chatgpt-route-gap-xs) calc(var(--wizon-ai-space-unit) * 2.5);
  border: 1px solid var(--cg-menu-border);
  border-radius: calc(var(--wizon-ai-space-unit) * 7);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer input {
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--cg-text);
  font-size: var(--wds-font-size-body-1);
  line-height: calc(var(--wds-font-size-body-1) * 1.5);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-button {
  display: inline-grid;
  place-items: center;
  width: calc(var(--wizon-ai-space-unit) * 9);
  height: calc(var(--wizon-ai-space-unit) * 9);
  min-width: calc(var(--wizon-ai-space-unit) * 9);
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-text-soft);
  transition:
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-button svg {
  width: calc(var(--wizon-ai-space-unit) * 5);
  height: calc(var(--wizon-ai-space-unit) * 5);
  fill: none;
  stroke: currentColor;
  stroke-width: var(--wds-icon-stroke, 1.7);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-button:hover {
  background: var(--cg-hover);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-button:active {
  transform: scale(0.985);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-send {
  width: calc(var(--wizon-ai-space-unit) * 9.5);
  height: calc(var(--wizon-ai-space-unit) * 9.5);
  min-width: calc(var(--wizon-ai-space-unit) * 9.5);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

.chatgpt-reference-v1 .chatgpt-scheduled-composer .chatgpt-route-composer-send:hover {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-anchor {
  position: relative;
  display: inline-grid;
  place-items: center;
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-menu {
  position: absolute;
  left: 0;
  bottom: calc(100% + var(--chatgpt-route-gap-xs));
  z-index: 40;
  display: grid;
  gap: var(--chatgpt-route-gap-2xs);
  width: min(calc(var(--wizon-ai-space-unit) * 76), calc(100vw - var(--chatgpt-route-gap-lg) * 2));
  padding: var(--chatgpt-route-gap-xs);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-lg);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-xs) minmax(0, 1fr);
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  text-align: left;
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item:hover,
.chatgpt-reference-v1 .chatgpt-scheduled-add-item:focus-visible {
  background: var(--cg-hover-soft);
  outline: none;
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item svg {
  width: calc(var(--wizon-ai-space-unit) * 5);
  height: calc(var(--wizon-ai-space-unit) * 5);
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item span {
  display: grid;
  gap: calc(var(--wizon-ai-space-unit) / 2);
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item strong {
  overflow: hidden;
  color: var(--cg-text);
  font-weight: var(--wds-font-weight-medium);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-scheduled-add-item small {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--wds-font-size-caption);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-scheduled-empty {
  display: grid;
  justify-items: center;
  gap: var(--chatgpt-route-gap-sm);
  padding: calc(var(--wizon-ai-space-unit) * 8) var(--chatgpt-route-gap-md);
  color: var(--cg-text);
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-scheduled-empty p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-app-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(calc(var(--wizon-ai-space-unit) * 55), 1fr));
  gap: var(--chatgpt-route-gap-sm);
}

.chatgpt-reference-v1 .chatgpt-app-card {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr) var(--wizon-ai-action-target-xs);
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  min-height: calc(var(--wizon-ai-space-unit) * 18);
  padding: var(--ds-space-4, 16px);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-gap-sm);
  background: var(--cg-surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast),
    border-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}

.chatgpt-reference-v1 .chatgpt-app-card:hover {
  background: var(--cg-hover-soft);
  border-color: var(--cg-menu-border);
}

.chatgpt-reference-v1 .chatgpt-app-card-icon,
.chatgpt-reference-v1 .chatgpt-app-card-cta {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border-radius: var(--chatgpt-route-radius-control);
  color: var(--cg-text-soft);
}

.chatgpt-reference-v1 .chatgpt-app-card-icon {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

.chatgpt-reference-v1 .chatgpt-app-card-icon svg,
.chatgpt-reference-v1 .chatgpt-app-card-cta svg {
  width: calc(var(--wizon-ai-space-unit) * 5);
  height: calc(var(--wizon-ai-space-unit) * 5);
  fill: none;
  stroke: currentColor;
  stroke-width: var(--wds-icon-stroke, 1.7);
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chatgpt-reference-v1 .chatgpt-app-card-copy {
  display: grid;
  gap: var(--chatgpt-route-gap-2xs);
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-app-card-copy strong {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-text);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-app-card-copy p,
.chatgpt-reference-v1 .chatgpt-route-empty-copy {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

.chatgpt-reference-v1 .chatgpt-app-empty {
  display: grid;
  grid-column: 1 / -1;
  justify-items: center;
  gap: var(--chatgpt-route-gap-sm);
  padding: calc(var(--wizon-ai-space-unit) * 10) var(--chatgpt-route-gap-md);
  color: var(--cg-text);
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-app-empty p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--chatgpt-route-body-font-size);
  line-height: var(--chatgpt-route-body-line-height);
}

/* 20260704-composer-empty-optical-center-guard: keep the ChatGPT one-line prompt optically centered after new-chat, focus, and stale multiline transitions. */
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment),
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) {
  grid-template-rows: 42px !important;
  min-height: 52px !important;
  max-height: 52px !important;
  padding: 5px 8px !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto !important;
  grid-template-rows: 42px !important;
  grid-template-areas: "lead input actions" !important;
  align-items: center !important;
  min-height: 42px !important;
  height: 42px !important;
  padding: 0 !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-textarea-scroll,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-textarea-scroll {
  align-self: center !important;
  display: flex !important;
  align-items: center !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  overflow-y: hidden !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) textarea {
  align-self: center !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  padding: 0 !important;
  line-height: 26px !important;
  overflow-y: hidden !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-leading-action,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-action-dock,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-leading-action,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-action-dock {
  align-self: center !important;
}

/* 20260704-composer-hidden-attachment-center-guard: stale attachment classes must not keep an empty prompt in the tall multiline layout. */
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) {
  grid-template-rows: 42px !important;
  min-height: 52px !important;
  max-height: 52px !important;
  padding: 5px 8px !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto !important;
  grid-template-rows: 42px !important;
  grid-template-areas: "lead input actions" !important;
  align-items: center !important;
  min-height: 42px !important;
  height: 42px !important;
  padding: 0 !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll {
  align-self: center !important;
  display: flex !important;
  align-items: center !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  overflow-y: hidden !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea {
  align-self: center !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  padding: 0 !important;
  line-height: 26px !important;
  overflow-y: hidden !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-leading-action,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-action-dock,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-leading-action,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-action-dock {
  align-self: center !important;
}

/* 20260704-composer-single-line-baseline-guard: keep the one-line prompt on the same centerline as ChatGPT's placeholder. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea {
  transform: none;
}

/* 20260704-composer-direct-textarea-center-guard: support stale/deployed composer DOM without the textarea scroll wrapper. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:not(.is-multiline) .composer-prompt-body > textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body > textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body > textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body > textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body > textarea {
  grid-area: input !important;
  align-self: center !important;
  display: block !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  padding: 0 !important;
  line-height: 26px !important;
  overflow-y: hidden !important;
}

/* 20260704-composer-placeholder-state-reset-guard: placeholder state must always collapse stale multiline geometry back to ChatGPT's single-line rail. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) {
  grid-template-rows: 42px !important;
  min-height: 52px !important;
  height: 52px !important;
  max-height: 52px !important;
  padding: 5px 8px !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body {
  grid-template-columns: 36px minmax(0, 1fr) auto !important;
  grid-template-rows: 42px !important;
  grid-template-areas: "lead input actions" !important;
  align-items: center !important;
  min-height: 42px !important;
  height: 42px !important;
  max-height: 42px !important;
  margin: 0 !important;
  padding: 0 !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-textarea-scroll {
  grid-area: input !important;
  align-self: stretch !important;
  display: grid !important;
  align-items: center !important;
  min-height: 42px !important;
  height: 42px !important;
  max-height: 42px !important;
  overflow-y: hidden !important;
}

body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) textarea {
  align-self: center !important;
  min-height: 26px !important;
  height: 26px !important;
  max-height: 26px !important;
  padding: 0 !important;
  line-height: 26px !important;
  overflow-y: hidden !important;
  transform: none !important;
}

/* 20260704-composer-visible-attachment-expansion-guard: a visible attachment lane wins over stale empty-state height clamps. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])) {
  grid-template-rows: auto auto !important;
  min-height: 84px !important;
  height: auto !important;
  max-height: min(360px, calc(100dvh - 24px)) !important;
  padding: 5px 8px !important;
}

body.chatgpt-reference-v1 .composer-attachment-lane:not([hidden]) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-width: 0;
  overflow: visible;
}

/* 20260706-project-route-surface-v2: route pages must win after late empty composer clamps and cached CSS. */
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .message-list,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-prompt-shelf,
body.chatgpt-reference-v1.portal-route-open .message-list,
body.chatgpt-reference-v1.portal-route-open .chatgpt-composer-shell,
body.chatgpt-reference-v1.portal-route-open .composer-surface.chatgpt-composer-shell,
body.chatgpt-reference-v1.portal-route-open .chatgpt-prompt-shelf {
  display: none !important;
}

/* 20260707-library-preview-composer-route-restore: route pages hide the home composer, but the file preview prompt is part of the detail dialog. */
html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell,
html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell,
body.chatgpt-reference-v1.portal-route-open .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell {
  display: grid !important;
}

/* 20260707-library-preview-mobile-composer-reference: match Chrome-observed ChatGPT mobile composer geometry and beat global empty-composer clamps. */
@media (max-width: 520px) {
  html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]),
  html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]),
  body.chatgpt-reference-v1.portal-route-open .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]),
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) {
    width: calc(100% - 32px) !important;
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: 74px !important;
    min-height: 84px !important;
    height: 84px !important;
    max-height: 84px !important;
    margin: 0 auto var(--chatgpt-route-gap-lg) !important;
    padding: 5px 8px !important;
    border-radius: 28px !important;
    overflow: clip !important;
  }

  html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface.is-empty:has(textarea[data-library-preview-prompt-input]:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface.is-empty:has(textarea[data-library-preview-prompt-input]:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  body.chatgpt-reference-v1.portal-route-open .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface.is-empty:has(textarea[data-library-preview-prompt-input]:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface.is-empty:has(textarea[data-library-preview-prompt-input]:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) {
    grid-template-columns: minmax(0, 1fr) !important;
    grid-template-rows: 74px !important;
    min-height: 84px !important;
    height: 84px !important;
    max-height: 84px !important;
  }

  html[data-chat-state="route"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-prompt-body,
  html[data-portal-route-open="true"] body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-prompt-body,
  body.chatgpt-reference-v1.portal-route-open .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-prompt-body {
    grid-template-columns: 36px minmax(0, 1fr) auto !important;
    grid-template-rows: 38px 36px !important;
    grid-template-areas:
      "input input input"
      "lead spacer actions" !important;
    align-items: center !important;
    min-height: 74px !important;
    height: 74px !important;
    max-height: 74px !important;
    gap: 0 8px !important;
    padding: 0 !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-textarea-scroll {
    grid-area: input !important;
    align-self: stretch !important;
    display: grid !important;
    align-items: center !important;
    min-height: 38px !important;
    height: 38px !important;
    max-height: 38px !important;
    padding: 0 7px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .chatgpt-library-preview-prompt-input {
    align-self: center !important;
    min-height: 26px !important;
    height: 26px !important;
    max-height: 26px !important;
    padding: 0 !important;
    font-size: 16px !important;
    line-height: 26px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-leading-action {
    grid-area: lead !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-action-dock {
    grid-area: actions !important;
    align-self: center !important;
    display: inline-flex !important;
    flex-flow: row nowrap !important;
    align-items: center !important;
    justify-content: flex-end !important;
    min-width: 0 !important;
    min-height: 36px !important;
    height: 36px !important;
    gap: 4px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-model-pill,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-mic-button,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-leading-action,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .chatgpt-library-preview-submit {
    display: inline-grid !important;
    place-items: center !important;
    min-height: 36px !important;
    height: 36px !important;
    border-radius: 999px !important;
    background: rgba(0, 0, 0, 0.05);
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-leading-action,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-mic-button,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .chatgpt-library-preview-submit {
    width: 36px !important;
    min-width: 36px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-model-pill {
    display: inline-flex !important;
    flex: 0 0 auto !important;
    width: auto !important;
    min-width: 74px !important;
    padding: 0 14px !important;
    gap: 6px !important;
    color: rgb(143, 143, 143);
    font-size: 16px !important;
    line-height: 26px !important;
    white-space: nowrap !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-model-pill > span {
    flex: 0 0 auto !important;
    white-space: nowrap !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .composer-caret {
    width: 16px !important;
    min-width: 16px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog .chatgpt-library-preview-composer.chatgpt-composer-shell.composer-surface:has([data-library-preview-prompt-input]) .chatgpt-library-preview-submit {
    background: #000000;
    color: #ffffff;
  }
}

@media (max-width: 900px) {
  .chatgpt-reference-v1 .chatgpt-route-page {
    --chatgpt-route-page-mobile-width: min(100%, calc(100% - (var(--wizon-ai-thread-gutter) * 2)));
    /* the route title now lives in the top app bar (20260709-mobile-route-navbar),
       so the page no longer needs a large top gap for a big H1 — reclaim that space */
    --chatgpt-route-page-mobile-top: calc(var(--wizon-ai-space-unit) * 4);
    --chatgpt-route-page-mobile-bottom: var(--ds-space-8, 40px);
    /* --chatgpt-route-table-mobile-min 은 여기 있었다. 폰에서 라이브러리 표에 최소 폭을 줘 가로
       스크롤을 만들던 유일한 토큰이었고, 20260802-library-mobile-native-list 로 그 표 자체가
       리스트가 되면서 소비처가 0이 됐다. 정의만 남기면 죽은 토큰이라 함께 걷어낸다. */
    width: var(--chatgpt-route-page-mobile-width);
    padding: var(--chatgpt-route-page-mobile-top) 0 var(--chatgpt-route-page-mobile-bottom);
  }

  .chatgpt-reference-v1 .chatgpt-route-page-inner {
    gap: var(--chatgpt-route-gap-md);
  }

  .chatgpt-reference-v1 .chatgpt-route-page-head {
    flex-direction: column;
    align-items: stretch;
    gap: var(--ds-space-4, 16px);
  }

  /* the top app bar already shows the route title inline — drop the duplicate big
     H1 on mobile so the page isn't titled twice (NN/g: no redundant chrome). */
  body.portal-route-open.chatgpt-reference-v1 .chatgpt-route-page-head h1 {
    display: none;
  }

  /* 20260706-route-mobile-rail-v1 / 20260706-library-route-mobile-rail-guard: keep library controls inside the route rail while table rows scroll internally. */
  .chatgpt-reference-v1 .chatgpt-route-page-head,
  .chatgpt-reference-v1 .chatgpt-route-page-actions,
  .chatgpt-reference-v1 .chatgpt-library-filter-row,
  .chatgpt-reference-v1 .chatgpt-library-table {
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }

  .chatgpt-reference-v1 .chatgpt-route-page-actions {
    flex-wrap: wrap;
    align-items: stretch;
  }

  .chatgpt-reference-v1 .chatgpt-route-search {
    width: 100%;
  }

  .chatgpt-reference-v1 .chatgpt-route-tabs,
  .chatgpt-reference-v1 .chatgpt-library-table {
    overflow-x: auto;
    scrollbar-width: none;
  }

  .chatgpt-reference-v1 .chatgpt-library-filter-row {
    align-items: flex-start;
    gap: var(--chatgpt-route-gap-sm);
  }

  .chatgpt-reference-v1 .chatgpt-library-view-controls {
    flex: 0 0 auto;
  }

  .chatgpt-reference-v1 .chatgpt-route-tabs::-webkit-scrollbar,
  .chatgpt-reference-v1 .chatgpt-library-table::-webkit-scrollbar {
    display: none;
  }

  .chatgpt-reference-v1 .chatgpt-route-tabs button {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  /* 20260802-library-mobile-native-list (북극성 ③, doc 143 §3): 폰에서 라이브러리는 데이터 표가
     아니라 리스트다. 배포 0583703ab 를 iPhone 17 시뮬(실 WebKit)로 재니 4열이 그대로 남아 표가
     가로로 스크롤했고(폭 358px 에 scrollWidth 376), 정작 파일명은 5행 전부 말줄임이었다. 「크기」는
     5행 모두 값이 없었고 「수정됨」은 5행 모두 같은 값이라 둘이 폭만 먹었다. 아이콘 한 칸 + 제목
     (2줄까지) + 병합된 부제 한 줄로 접는다. 데스크톱(>=901px)은 무변경 — 거긴 표가 맞다. */
  .chatgpt-reference-v1 .chatgpt-library-table {
    min-width: 0;
    overflow-x: visible;
  }

  .chatgpt-reference-v1 .chatgpt-library-row--head {
    display: none;
  }

  .chatgpt-reference-v1 .chatgpt-library-row {
    grid-template-columns: 32px minmax(0, 1fr);
    grid-template-areas:
      "icon name"
      "icon meta";
    align-items: center;
    column-gap: 12px;
    row-gap: 3px;
    min-width: 0;
    /* 오른쪽 44px 은 .chatgpt-library-row-menu-trigger(⋯) 자리 — 제목이 그 밑으로 흐르지 않게. */
    padding: 12px 44px 12px 0;
  }

  .chatgpt-reference-v1 .chatgpt-library-file-icon {
    grid-area: icon;
  }

  .chatgpt-reference-v1 .chatgpt-library-file-copy {
    grid-area: name;
    padding: 0;
  }

  .chatgpt-reference-v1 .chatgpt-library-file-name {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    line-height: 1.35;
    white-space: normal;
  }

  .chatgpt-reference-v1 .chatgpt-library-row-date,
  .chatgpt-reference-v1 .chatgpt-library-row-size {
    display: none;
  }

  .chatgpt-reference-v1 .chatgpt-library-row-meta {
    grid-area: meta;
    display: block;
    justify-self: start;
    overflow: hidden;
    min-width: 0;
    color: var(--cg-muted);
    font-size: var(--ds-text-caption-13);
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* 20260707-library-preview-mobile-fullscreen-reference: ChatGPT mobile file detail covers the rail; no sidebar tab remains visible. */
  body.chatgpt-reference-v1.sidebar-collapsed .chatgpt-library-preview-backdrop,
  body.chatgpt-reference-v1 .chatgpt-library-preview-backdrop {
    left: 0 !important;
    right: 0 !important;
    width: 100vw !important;
  }

  body.chatgpt-reference-v1.sidebar-collapsed .chatgpt-library-preview-dialog,
  body.chatgpt-reference-v1 .chatgpt-library-preview-dialog {
    width: 100vw !important;
  }

  .chatgpt-reference-v1 .chatgpt-library-preview-topbar {
    grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr) auto;
    gap: var(--chatgpt-route-gap-xs);
    padding: 0 var(--chatgpt-route-gap-sm);
  }

  .chatgpt-reference-v1 .chatgpt-library-preview-stage {
    padding: var(--chatgpt-route-gap-md) var(--chatgpt-route-gap-sm);
  }

  .chatgpt-reference-v1 .chatgpt-library-preview-document-pane {
    width: 100%;
    max-width: 100%;
  }

  body.chatgpt-reference-v1 .context-pane {
    inset: auto 8px 8px 8px;
    width: auto;
    height: min(78vh, 720px);
    transform: translate3d(0, 24px, 0) scale(0.985);
    transform-origin: center bottom;
  }

  body.chatgpt-reference-v1 .context-pane[data-motion-state="closing"] {
    transform: translate3d(0, 24px, 0) scale(0.985);
  }
}


@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .app-shell,
  body.chatgpt-reference-v1 .sidebar,
  body.chatgpt-reference-v1 .chatgpt-sidebar-rail,
  body.chatgpt-reference-v1 .context-pane,
  body.chatgpt-reference-v1 .message[data-message-motion="enter"],
  body.chatgpt-reference-v1 .message.pending .thinking-inline,
  body.chatgpt-reference-v1 .message[data-message-state="complete"] .message-actions,
  .chatgpt-reference-v1 .chatgpt-more-menu,
  .chatgpt-reference-v1 .chatgpt-account-menu,
  .chatgpt-reference-v1 .chatgpt-recent-menu,
  .chatgpt-reference-v1 .composer-popover,
  .chatgpt-reference-v1 .reasoning-popover,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu,
  body.chatgpt-reference-v1 .chatgpt-share-dialog[open],
  body.chatgpt-reference-v1 .chatgpt-share-dialog::backdrop,
  body.chatgpt-reference-v1 .chatgpt-search-dialog[open],
  body.chatgpt-reference-v1 .chatgpt-search-dialog::backdrop,
  body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog[open],
  body.chatgpt-reference-v1 .chatgpt-delete-confirm-dialog::backdrop,
  .chatgpt-reference-v1 .chatgpt-settings-dialog[open],
  .chatgpt-reference-v1 .chatgpt-settings-dialog::backdrop {
    transition-duration: 1ms !important;
    transform: none !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* 20260707-mobile-shell-chatgpt-parity: match ChatGPT mobile — hide the rail, full-width content, hamburger topbar opens the sidebar as an overlay drawer. */
.chatgpt-reference-v1 .chatgpt-mobile-topbar {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  height: 54px;
  padding: 4px 8px;
}

.chatgpt-reference-v1 .chatgpt-mobile-topbar-button {
  width: 40px;
  height: 40px;
}

/* 20260729-touch-target-a2: 상단바 아이콘(40x40) 탭 타깃을 44px로 — 시각 박스는 그대로 두고
   투명 ::after로만 히트영역을 넓힌다(2026-07-10에 추가된 아트디렉션 P1-5 히트슬롭과 같은 기법이지만, 그 규칙은
   @media (pointer: coarse) 단독 조건이라 실기기/에뮬레이션에서 pointer가 정확히 coarse로
   보고되지 않으면 적용되지 않을 수 있다 — 여기서는 폭 기준을 별도로 추가해 390px 실측/자동화
   검증 모두에서 결정적으로 적용되게 한다. 기존 규칙은 .chatgpt-icon-button도 함께 묶어 전체
   다이얼로그 닫기 버튼 등 이 작업 범위 밖의 요소까지 건드리므로, 이번 작업은 범위를 좁혀
   .chatgpt-mobile-topbar-button만 별도 규칙으로 추가한다). 좌/중/우 세 슬롯은 gap 8px로
   서로 배타적으로만 노출되므로(syncPortalRouteSurfaceVisibility: 트레일 슬롯은 드라이브 메뉴/
   휴지통 비우기/새채팅 중 항상 하나만 visible) 슬롭이 다른 아이콘과 겹칠 자리가 없다(실측). */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar-button {
    position: relative;
  }
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar-button::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    min-width: 44px;
    min-height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* 20260725-mobile-topbar-workspace: three-slot nav bar (Material 3 / Apple HIG). The old
   layout was flat `space-between` children with an absolutely-positioned WIZON wordmark and a
   `flex: 1` title, so the title slid sideways whenever a trailing action appeared.
   20260725-mobile-topbar-grid (M1 title-centering fix): the leading/trailing slots used to share
   a flex-grow factor so free space split evenly BETWEEN them — which only keeps the middle
   optically centred while neither slot's min-content exceeds its equal share. A long title (less
   free space to split) or an asymmetric slot (more buttons on one side) can push a slot past that
   floor, and the middle drifts off-centre. `.chatgpt-mobile-topbar` is now `display: grid` with
   fixed-floor side columns (see the <=900px block below) — each side's width is a function of ITS
   OWN content only, independent of the title's length or the viewport width, so the centre column
   never wobbles. The slots keep `display: flex` for their OWN children's internal layout. */
.chatgpt-reference-v1 .chatgpt-mobile-topbar-slot {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.chatgpt-reference-v1 .chatgpt-mobile-topbar-trail {
  justify-content: flex-end;
}

.chatgpt-reference-v1 .chatgpt-mobile-topbar-center {
  justify-content: center;
}

/* Workspace (product mode) switcher — the middle slot's chat-surface state. It opens the very
   same #productModeMenu the sidebar head opens, which is already registered as a mobile
   top-layer sheet, so it escapes the drawer's stacking context with no new menu markup. */
.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
  max-width: 100%;
  min-height: 40px;
  padding: 0 6px 0 10px;
  border: 0;
  /* --ds-radius-sm resolves to --wds-radius-md = 10px; token rather than the literal so the
     anti-drift raw-border-radius ratchet stays at its current floor (net 0 for this change). */
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--cg-text);
  font-size: var(--cg-text-topbar-brand-size);
  font-weight: 600;
  line-height: 22px;
  letter-spacing: -0.2px;
  cursor: pointer;
}

.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger[aria-expanded="true"] {
  background: var(--cg-hover);
}

.chatgpt-reference-v1 .chatgpt-mobile-workspace-caret {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--cg-muted);
}

.chatgpt-reference-v1 .chatgpt-mobile-workspace-caret svg {
  width: 16px;
  height: 16px;
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .app-shell {
    grid-template-columns: minmax(0, 1fr);
  }

  body.chatgpt-reference-v1 .main-pane {
    grid-column: 1 / -1;
    min-width: 0;
  }

  body.chatgpt-reference-v1.sidebar-collapsed .chatgpt-sidebar-rail {
    display: none;
  }

  /* 20260725-mobile-topbar-grid (M1): three-column bar with the title in the middle.
     20260725-topbar-centre-equal-columns (audit fix): the first cut sized the side columns
     `minmax(36px, max-content)` — "each side is a function of ITS OWN content only". That is
     exactly what breaks centring when the two sides are asymmetric: on /library the trailing slot
     carries TWO buttons (새로 만들기 + 새 채팅 = 84px) against a 40px leading slot, so the middle
     column started 44px late and the title sat 22px left of the viewport centre (measured at
     390px: title mid − viewport mid = −22.0). Equal `1fr` side tracks put the centre column
     dead-centre no matter how many actions a surface exposes, which is what the approved mockup's
     `grid-template-columns: 36px 1fr 36px` does — and each `1fr` still floors at its own
     `grid-template-columns: 36px 1fr 36px` does. The centre track is `minmax(0, auto)` so a long
     title ellipsises inside its own share instead of pushing the sides apart, and the side tracks
     floor at `max-content` so that squeeze can never collapse the actions themselves: with a plain
     `1fr` floor a 50-character title drove both side slots to 0px wide at 375/390 (the ⋯ and 뒤로
     became untappable). With the max-content floor the tracks stay equal whenever there is room —
     the real case for every route title — and degrade to content width only when there is not.
     Regression pin: MobileTopbarTitleCentringTests. */
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar {
    display: grid;
    grid-template-columns: minmax(max-content, 1fr) minmax(0, auto) minmax(max-content, 1fr);
    position: relative;
  }

  /* 20260725-sidebar-wordmark-only: keyed to the SAME breakpoint that reveals the app bar above,
     so the workspace switcher is never absent — it simply moves from the drawer to the bar. */
  body.chatgpt-reference-v1 .chatgpt-product-mode-button {
    display: none;
  }

  body.chatgpt-reference-v1 .chatgpt-sidebar-wordmark {
    display: inline-flex;
  }

  /* 20260710-library-new-in-topbar: the library "새로 만들기" create action moves into the
     fixed topbar ("+" next to 새 채팅) on mobile so it stays visible while the file list
     scrolls. Hide the scrolling route-head trigger here (its popover anchor stays for the
     bottom sheet). Desktop keeps the labeled route-head button (no mobile topbar there). */
  body.chatgpt-reference-v1 .chatgpt-library-page .chatgpt-route-page-head .chatgpt-route-primary {
    display: none;
  }

  body.chatgpt-reference-v1 .sidebar {
    width: min(300px, calc(100vw - 48px));
  }

  body.chatgpt-reference-v1:not(.sidebar-collapsed) .chatgpt-sidebar-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 65;
    background: var(--wizon-scrim, rgba(0, 0, 0, 0.24));
  }
}

.chatgpt-reference-v1 .chatgpt-sidebar-scrim {
  display: none;
}

/* (Removed a redundant `@media (max-width: 520px) .chatgpt-settings-dialog { border-radius: 0 }`
   block — the settings dialog now opts into [data-mobile-fullscreen], and the shared
   mobile-dialog rule "20260708-mobile-dialog-fullscreen-system" already sets
   border-radius via --wizon-mobile-dialog-radius !important. Single source of truth.) */

/* 20260708-composer-mobile-two-row-v2: match ChatGPT mobile — reflow the home composer to two rows (textarea on top; [+] ... [pill][mic][voice] below) so every control fits at narrow widths instead of wrapping/overflowing. The single-line "placeholder-state-reset-guard" (styles.css:11858,11867) clamps the shell to 52px and the prompt-body to a single 42px row with (0,8,2) !important selectors; this block MIRRORS those exact selectors (plus the simpler empty-state ones) so equal specificity + later source order + !important wins. Geometry follows the library-preview mobile composer template (styles.css:11968). */
@media (max-width: 520px) {
  /* Release the fixed single-line height clamp on the shell so two rows can show,
     and give the shell symmetric inner padding so the bottom controls are not flush
     against the rounded edge. */
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))),
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty {
    /* 106 = 10 top pad + 40 input row + 6 row gap + 40 control row + 10 bottom pad */
    min-height: 106px !important;
    height: auto !important;
    max-height: none !important;
    padding: 10px 12px !important;
  }

  /* Two-row prompt-body: textarea spans the top row; +, pill, mic, voice sit on the
     bottom row. The input row is flexible (minmax(40px, auto)) so it grows with
     multi-line text while the controls row stays a fixed 40px pinned at the bottom
     (like the desktop composer). The extra `.chatgpt-composer-shell .composer-prompt-body`
     selector + !important also override the desktop multiline rule (styles.css:7046),
     which would otherwise win. Bottom row is 40px so the 38px voice button centers
     with room; the shell's 10px bottom padding keeps the controls off the edge. */
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
  body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(.has-attachment) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-empty:not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(textarea:placeholder-shown):not(:has(.composer-mode-slot:not([hidden]))):not(:has(.composer-attachment-lane:not([hidden]))) .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline.is-empty .composer-prompt-body,
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline:has(textarea:placeholder-shown) .composer-prompt-body {
    grid-template-columns: 36px minmax(0, 1fr) auto !important;
    grid-template-rows: minmax(40px, auto) 40px !important;
    grid-template-areas:
      "input input input"
      "lead spacer actions" !important;
    align-items: center !important;
    min-height: 86px !important;
    height: auto !important;
    max-height: none !important;
    gap: 6px 8px !important;
    padding: 0 !important;
  }

  /* Multi-line: the textarea grows then scrolls internally at max(30svh, 5rem) —
     matching ChatGPT mobile (`max-h-[max(30svh,5rem)]`, ~8 lines) — while the shell
     grows to fit. The broad shell selector + !important beat the desktop multiline
     shell clamp (styles.css:7042 max-height:300px, no !important). */
  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline,
  body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell.is-multiline {
    min-height: 0 !important;
    height: auto !important;
    max-height: none !important;
    padding: 10px 12px !important;
  }

  body.chatgpt-reference-v1 .chatgpt-composer-shell .composer-textarea-scroll,
  body.chatgpt-reference-v1 .chatgpt-composer-shell .composer-textarea-scroll textarea {
    max-height: max(30svh, 5rem) !important;
  }

  body.chatgpt-reference-v1 .chatgpt-composer-shell.is-multiline .composer-textarea-scroll {
    align-self: stretch !important;
    overflow-y: auto !important;
  }

  /* keep the action dock on a single horizontal row (wds-ai-portal-v1 forces column) and let the pill show its full label */
  body.chatgpt-reference-v1 .chatgpt-composer-shell .composer-action-dock {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    gap: 6px;
    justify-self: end;
  }

  body.chatgpt-reference-v1 .composer-model-pill {
    display: inline-flex;
    max-width: none;
  }

  body.chatgpt-reference-v1 .composer-model-pill > span:first-child {
    white-space: nowrap;
  }

  body.chatgpt-reference-v1 .composer-mic-button {
    display: inline-grid;
  }
}

/* 20260708-composer-mobile-bottom-pin: ChatGPT pins the composer to the BOTTOM of the
   mobile home instead of vertically centering the greeting/composer/chips block. Push
   the block down with a big top spacer and re-order the empty-home grid so the chips
   sit ABOVE the composer and the composer is last (bottom). Scoped to
   html[data-chat-state="empty"] so the active conversation view is untouched; the extra
   `body` in each selector beats the base empty-home rules (styles.css:7308-7336). */
@media (max-width: 520px) {
  /* Both empty AND active: the chat pane must fill the workbench (the area below the
     52px mobile topbar), never 100dvh (styles.css:8372) — otherwise the bottom-pinned
     composer, now 106px tall on mobile, overflows off-screen by the topbar height. */
  body.chatgpt-reference-v1 .chat-pane {
    height: 100% !important;
    min-height: 0 !important;
    max-height: 100% !important;
  }

  html[data-chat-state="empty"] body.chatgpt-reference-v1 .chat-pane {
    grid-template-rows: minmax(0, 1fr) auto auto auto !important;
    padding-bottom: 10px !important;
  }

  html[data-chat-state="empty"] body.chatgpt-reference-v1 .message-list {
    grid-row: 2 !important;
    margin: 0 auto 6px !important;
  }

  html[data-chat-state="empty"] body.chatgpt-reference-v1 .chatgpt-prompt-shelf {
    grid-row: 3 !important;
    margin: 0 auto 10px !important;
  }

  html[data-chat-state="empty"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
  html[data-chat-state="empty"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
    grid-row: 4 !important;
    margin: 0 auto !important;
  }

  /* Active conversation: trim the desktop 28px composer bottom margin to a mobile 10px
     so the composer sits near the bottom edge like ChatGPT (and matches the empty home). */
  html[data-chat-state="active"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
  html[data-chat-state="active"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell,
  html[data-chat-state="loading"] body.chatgpt-reference-v1 .chatgpt-composer-shell,
  html[data-chat-state="loading"] body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell {
    margin-bottom: 10px !important;
  }
}

/* 20260708-sidebar-shortcut-hints-mobile-hide: ChatGPT hides the keyboard-shortcut
   hints (⇧⌘O, ⌘K) in the sidebar on mobile, where there is no hardware keyboard. Hide
   them whenever the mobile drawer shell is active (<=900px, where the hamburger topbar
   replaces the rail). The Settings dialog's dedicated shortcut list (.settings-shortcut-*)
   is a separate surface and is intentionally left untouched. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-sidebar-shortcut {
    display: none !important;
  }
}

/* 20260708-mobile-dialog-fullscreen-system: WIZON mobile design RULE for modals.
   ANY overlay element that opts in with [data-mobile-fullscreen] becomes full-screen
   edge-to-edge on mobile (<=520px), matching ChatGPT's content-panel modals. Works for
   both native <dialog> (settings, search) and custom role="dialog" overlays rendered
   inside a backdrop (project create, …) — `position: fixed; inset: 0` pins either kind
   to the viewport. This is the single source of truth: opt-in dialogs no longer hardcode
   their own mobile size. It overrides the native <dialog> defaults (max-height:
   calc(100% - 38px); margin: auto) that otherwise leave a ~19px gap. Small confirmation
   alerts / pickers (delete, share, library-move) deliberately DO NOT opt in — ChatGPT
   keeps those compact and centered. Values come from the --wizon-mobile-dialog-* tokens
   (see "20260708-mobile-dialog-tokens" near the top of this file). */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 [data-mobile-fullscreen] {
    position: fixed !important;
    inset: 0 !important;
    /* Pin to the visual viewport (top offset + height) so an iOS keyboard scroll
       can't drag the dialog's sticky header off-screen. */
    top: var(--wizon-vv-offset-top, 0px) !important;
    bottom: auto !important;
    width: var(--wizon-mobile-dialog-inline-size, 100vw) !important;
    max-width: none !important;
    height: var(--wizon-mobile-dialog-block-size, 100dvh) !important;
    max-height: var(--wizon-mobile-dialog-block-size, 100dvh) !important;
    margin: var(--wizon-mobile-dialog-margin, 0) !important;
    border-radius: var(--wizon-mobile-dialog-radius, 0) !important;
  }

  /* A dialog whose card layout was a fixed-height grid must reflow when it goes
     full-screen: stack the content from the top and pin the primary action to the
     bottom, full-width (ChatGPT's new-project mobile page). */
  body.chatgpt-reference-v1 .chatgpt-project-create-dialog[data-mobile-fullscreen] {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 14px !important;
    padding: 16px 20px calc(20px + env(safe-area-inset-bottom, 0px)) !important;
    overflow-y: auto !important;
  }

  body.chatgpt-reference-v1 .chatgpt-project-create-dialog[data-mobile-fullscreen] .chatgpt-project-create-submit {
    margin-top: auto !important;
    width: 100% !important;
    align-self: stretch !important;
    justify-self: stretch !important;
  }
}

/* ===== Weather widget (WDS DataAnswerCard port) — immersive data-viz answer =============
   Sky gradients / glass tints / temp-range are intentional weather colors (real hex, no
   token dependency). Chrome spacing/radius/shadow use literals. Panel backgrounds are set
   inline by JS (WEATHER_PANEL_TINT) so CSS never fights them. */
.weather-widget,
.weather-mini,
.wcVerdict {
  container-type: inline-size;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 20px;
  margin-top: 4px;
  padding: 24px;
  border-radius: 20px;
  background: #0d285e;
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #ffffff 38%, transparent),
    inset 0 -1px 0 color-mix(in srgb, #0b1d3a 28%, transparent),
    0 24px 48px rgba(0, 0, 0, 0.16),
    0 18px 40px -12px color-mix(in srgb, #0b1d3a 30%, transparent);
  color: #ffffff;
}
.weather-widget::after,
.weather-mini::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(120% 80% at 50% 112%, color-mix(in srgb, #0b1d3a 36%, transparent), transparent 60%);
}
.weather-widget > *,
.weather-mini > * {
  position: relative;
  z-index: 1;
}

.weatherBg {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  overflow: hidden;
  pointer-events: none;
}
.weatherBg::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.weather-widget[data-cond="snow"] .weatherBg::before,
.weather-mini[data-cond="snow"] .weatherBg::before,
.weather-widget[data-cond="cloud"] .weatherBg::before,
.weather-mini[data-cond="cloud"] .weatherBg::before,
.weather-widget[data-cond="cloudnight"] .weatherBg::before,
.weather-mini[data-cond="cloudnight"] .weatherBg::before,
.weather-widget[data-cond="fog"] .weatherBg::before,
.weather-mini[data-cond="fog"] .weatherBg::before {
  background: linear-gradient(180deg, color-mix(in srgb, #0b1d3a 40%, transparent), transparent 38%);
}
.weather-widget[data-cond="sun"] .weatherBg,
.weather-mini[data-cond="sun"] .weatherBg {
  background:
    radial-gradient(120% 90% at 78% 10%, color-mix(in srgb, #fbbf24 28%, transparent), transparent 46%),
    radial-gradient(140% 120% at 12% -10%, color-mix(in srgb, #06b6d4 48%, transparent), transparent 56%),
    linear-gradient(168deg, #38bdf8, #3c8ffd 42%, #1252b2 92%, #0d285e);
}
.weather-widget[data-cond="cloudsun"] .weatherBg,
.weather-mini[data-cond="cloudsun"] .weatherBg {
  background:
    radial-gradient(120% 90% at 78% 10%, color-mix(in srgb, #fbbf24 26%, transparent), transparent 46%),
    radial-gradient(140% 120% at 12% -10%, color-mix(in srgb, #38bdf8 80%, transparent), transparent 55%),
    linear-gradient(168deg, #38bdf8, #3c8ffd 42%, #1252b2 92%, #0d285e);
}
.weather-widget[data-cond="cloud"] .weatherBg,
.weather-mini[data-cond="cloud"] .weatherBg {
  background: linear-gradient(168deg, color-mix(in srgb, #38bdf8 38%, #4b5563), #4b5563 48%, #0d285e);
}
.weather-widget[data-cond="rain"] .weatherBg,
.weather-mini[data-cond="rain"] .weatherBg {
  background:
    radial-gradient(140% 120% at 30% -10%, color-mix(in srgb, #1252b2 70%, #374151), transparent 60%),
    linear-gradient(172deg, color-mix(in srgb, #1252b2 55%, #374151), #0d285e 50%, #0b1d3a);
}
.weather-widget[data-cond="snow"] .weatherBg,
.weather-mini[data-cond="snow"] .weatherBg {
  background: linear-gradient(170deg, color-mix(in srgb, #38bdf8 45%, #4b5563), color-mix(in srgb, #3c8ffd 70%, #9ca3af) 45%, #1252b2);
}
.weather-widget[data-cond="night"] .weatherBg,
.weather-mini[data-cond="night"] .weatherBg {
  background:
    radial-gradient(120% 80% at 80% 8%, color-mix(in srgb, #1252b2 28%, transparent), transparent 50%),
    linear-gradient(168deg, #083344, #0b1d3a 55%, #111827);
}
.weather-widget[data-cond="thunder"] .weatherBg,
.weather-mini[data-cond="thunder"] .weatherBg {
  background:
    radial-gradient(130% 110% at 64% -8%, color-mix(in srgb, #1252b2 45%, #374151), transparent 58%),
    linear-gradient(176deg, color-mix(in srgb, #0b1d3a 78%, #374151), #0b1d3a 46%, #111827);
}
.weather-widget[data-cond="fog"] .weatherBg,
.weather-mini[data-cond="fog"] .weatherBg {
  background: linear-gradient(170deg, color-mix(in srgb, #38bdf8 22%, #4b5563), #4b5563 46%, #0d285e);
}
.weather-widget[data-cond="partlynight"] .weatherBg,
.weather-mini[data-cond="partlynight"] .weatherBg {
  background:
    radial-gradient(120% 80% at 82% 8%, color-mix(in srgb, #f2e4b0 12%, transparent), transparent 46%),
    linear-gradient(168deg, color-mix(in srgb, #38bdf8 10%, #0e2748), #0b1d3a 52%, #111827);
}
.weather-widget[data-cond="cloudnight"] .weatherBg,
.weather-mini[data-cond="cloudnight"] .weatherBg {
  background: linear-gradient(168deg, color-mix(in srgb, #38bdf8 14%, #1f2937), #1f2937 46%, #0b1d3a);
}

/* ---- 비교 답변: 애플 다지역형 미니 위젯 행 -------------------------------------------
 *
 * 큰 카드를 나란히 놓지 않는다. 채팅 열은 ~615px이고 모바일도 쓴다 — 반으로 쪼개면 시간별
 * 6칸과 5일 행이 무너진다. 애플·The Weather Channel도 다지역은 세로로 쌓은 납작한 행이다.
 *
 * ★새 색·새 치수를 만들지 않는다. 하늘(.weatherBg)·면·글자는 큰 카드의 선언을 **그대로
 *   공유하고**, 행 안의 글자는 큰 카드의 클래스(.loc/.cond/.bigTemp/.heroGlyph/.wNow)를
 *   그대로 쓴다. 처음엔 여기서 색과 크기를 손수 적었다가 anti-drift 래칫에 걸렸다 —
 *   래칫이 맞았다. 조건 10종 중 2종만 흉내 낸 색은 정의가 아니라 드리프트다.
 */
.weather-compare {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 4px;
}
.weather-mini {
  /* 큰 카드의 히어로는 clamp(36px…4.5rem)라 130px 행에서는 넘친다. 치수는 선언이 아니라
     변수로 둬서 anti-drift 스캐너가 세는 raw font-size를 늘리지 않는다. */
  --wx-mini-temp-size: 42px;
  --wx-mini-name-size: 19px;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: start;
  row-gap: 14px;
  gap: 14px;
  margin-top: 0;
  padding: 16px 20px;
  overflow: hidden;
}
/* 행 안에서는 큰 카드보다 한 단계 작게. 치수는 선언이 아니라 변수로 둔다. */
.weather-mini .bigTemp {
  font-size: var(--wx-mini-temp-size);
}
.weather-mini .heroGlyph {
  margin-top: 0;
}
.weather-mini .heroGlyph svg,
.weather-mini .heroGlyph .weather-icon {
  width: 34px;
  height: 34px;
}
.weather-mini .loc {
  font-size: var(--wx-mini-name-size);
}
.wmHead {
  min-width: 0;
}
.wmHead .cond {
  display: block;
  margin-top: 3px;
}
.wmCond {
  align-self: end;
}
.wmFoot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  align-self: end;
}
.wmRange {
  font-variant-numeric: tabular-nums;
}
/* 두 행 **모두** 칩을 갖는다. 따뜻한 쪽에만 달았더니 행 높이가 어긋나 한쪽이 더 중요해 보였다. */
.wmDelta {
  display: inline-flex;
  align-items: center;
  height: 21px;
  padding: 0 9px;
  border-radius: var(--ds-radius-pill);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.wmDelta[data-side="warm"] {
  background: var(--ds-badge-warn-bg);
  color: var(--ds-badge-warn-fg);
}
.wmDelta[data-side="cool"] {
  background: var(--ds-badge-info-bg);
  color: var(--ds-badge-info-fg);
}
/* 조회 실패한 행. 하늘을 낮추되 **이름은 남긴다** — 사라지면 물어본 지역이 어디 갔는지 모른다. */
.weather-mini[data-state="down"] .weatherBg {
  opacity: 0.3;
}
.wmDown {
  grid-column: 1 / -1;
  align-self: center;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
}
.wmDown svg {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--ds-badge-warn-bg);
}
/* 결론은 굵게 먼저, 근거는 흐리게 뒤에. 한 덩어리로 쓰면 위계가 없다.
   하늘(.weatherBg)을 두지 않아 평면으로 남는다 — 「여기는 또 다른 장소가 아니라 결론」. */
.wcVerdict {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 0;
  padding: 15px 18px;
}
.wcHead {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.wcHead svg {
  flex: none;
  width: 15px;
  height: 15px;
}
/* 근거의 소수점은 일부러 남긴다 — 행은 29°로 반올림하는데 결론은 1.5도라고 말하므로,
   둘을 잇는 값이 없으면 「숫자가 안 맞는다」로 보인다. */
.wcEvidence {
  margin: 0;
  padding-left: 24px;
  font-variant-numeric: tabular-nums;
}

.wHead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}
.wHeadText {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.loc {
  font-size: var(--ds-text-title-20);
  font-weight: 600;
  color: #ffffff;
}
.cond {
  font-size: var(--ds-text-caption-12);
  color: color-mix(in srgb, #ffffff 80%, transparent);
}
.wHeadTemp {
  flex: none;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
.bigTemp {
  font-size: clamp(36px, 6cqw + 1.5rem, 4.5rem);
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: -0.04em;
  color: #ffffff;
}
.deg {
  font-size: 0.42em;
  vertical-align: super;
}
.heroGlyph {
  display: inline-flex;
  margin-top: 8px;
  color: #ffffff;
  filter: drop-shadow(0 2px 8px color-mix(in srgb, #0b1d3a 45%, transparent));
}
.heroGlyph svg,
.heroGlyph .weather-icon {
  width: 56px;
  height: 56px;
}
.weather-widget[data-cond="sun"] .heroGlyph,
.weather-widget[data-cond="cloudsun"] .heroGlyph {
  color: #fbbf24;
}
.wNow {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  font-size: var(--ds-text-caption-12);
  color: color-mix(in srgb, #ffffff 80%, transparent);
}

.hourlyWrap {
  position: relative;
}
.slideBtn {
  position: absolute;
  top: 50%;
  z-index: 2;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  padding: 4px;
  border: none;
  background: transparent;
  color: #ffffff;
  cursor: pointer;
  opacity: 0;
  transition: opacity 150ms ease;
  filter: drop-shadow(0 1px 3px color-mix(in srgb, #0b1d3a 60%, transparent));
}
.slideBtn svg {
  width: 20px;
  height: 20px;
}
.hourlyWrap:hover .slideBtn {
  opacity: 1;
}
.slideLeft {
  left: -20px;
}
.slideRight {
  right: -20px;
}
.hourly {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  padding: 12px 16px;
  border-radius: var(--ds-radius-md, 14px);
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 color-mix(in srgb, #ffffff 26%, transparent),
    inset 0 0 0 1px color-mix(in srgb, #ffffff 9%, transparent);
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 16px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  cursor: grab;
  user-select: none;
  touch-action: pan-x;
}
.hourly::-webkit-scrollbar {
  display: none;
}
.hourly:active {
  cursor: grabbing;
}
.chip {
  flex: 0 0 calc((100cqw - 176px) / 10);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding-block: 8px;
  scroll-snap-align: start;
}
@container (max-width: 520px) {
  .chip {
    flex-basis: calc((100cqw - 96px) / 5);
  }
}
.chipTime {
  font-size: var(--ds-text-caption-12);
  white-space: nowrap;
  color: color-mix(in srgb, #ffffff 76%, transparent);
}
.chipGlyph {
  display: inline-flex;
  color: #ffffff;
  filter: drop-shadow(0 1px 2px color-mix(in srgb, #0b1d3a 40%, transparent));
}
.chipGlyph svg,
.dayGlyph svg,
.chipGlyph .weather-icon,
.dayGlyph .weather-icon {
  width: 34px;
  height: 34px;
}
.weather-icon {
  display: block;
  -webkit-user-select: none;
  user-select: none;
}
.chipGlyph[data-cond="sun"] {
  color: #fbbf24;
}
.chipPop {
  min-height: 1lh;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  color: #38bdf8;
}
.chipTemp {
  font-size: var(--ds-text-body-16);
  font-weight: 600;
  color: #ffffff;
}

.daily {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 16px;
  border-radius: var(--ds-radius-md, 14px);
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 color-mix(in srgb, #ffffff 26%, transparent),
    inset 0 0 0 1px color-mix(in srgb, #ffffff 9%, transparent);
}
.dailyHead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 8px;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  color: color-mix(in srgb, #ffffff 72%, transparent);
}
.dayRow {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-block: 4px;
}
.dayLabel {
  flex: none;
  width: 32px;
  font-size: var(--ds-text-body-14);
  font-weight: 500;
  color: #ffffff;
}
.dayCond {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 40px;
}
.dayGlyph {
  display: inline-flex;
  color: #ffffff;
}
.dayGlyph[data-cond="sun"] {
  color: #fbbf24;
}
.dayPop {
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  color: #38bdf8;
}
.dayMin {
  flex: none;
  width: 30px;
  text-align: right;
  font-size: var(--ds-text-body-14);
  color: color-mix(in srgb, #ffffff 66%, transparent);
}
.dayMax {
  flex: none;
  width: 30px;
  font-size: var(--ds-text-body-14);
  color: #ffffff;
}
/* 중기예보 오차 표시. 값보다 약하게 — 보조 정보이지 주인공이 아니다. */
.dayMargin {
  flex: none;
  margin-inline-start: 4px;
  font-size: var(--ds-text-caption-12);
  color: rgba(255, 255, 255, 0.55);
  font-variant-numeric: tabular-nums;
}
.dailyNote {
  margin-block-start: 8px;
  padding-block-start: 8px;
  border-block-start: 1px solid rgba(255, 255, 255, 0.12);
  font-size: var(--ds-text-caption-12);
  color: rgba(255, 255, 255, 0.6);
}
.track {
  position: relative;
  flex: 1;
  height: 6px;
  border-radius: 9999px;
  background: color-mix(in srgb, #ffffff 16%, transparent);
  box-shadow: inset 0 1px 2px color-mix(in srgb, #0b1d3a 35%, transparent);
}
.range {
  position: absolute;
  top: 0;
  height: 6px;
  border-radius: 9999px;
  background: linear-gradient(90deg, #66aaff, #fbbf24);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #ffffff 45%, transparent);
}
.nowDot {
  position: absolute;
  top: 50%;
  width: 9px;
  height: 9px;
  transform: translate(-50%, -50%);
  border-radius: 9999px;
  background: #ffffff;
  box-shadow:
    0 0 0 2px color-mix(in srgb, #1252b2 60%, transparent),
    0 1px 3px color-mix(in srgb, #0b1d3a 50%, transparent);
}
.weather-widget[data-cond="night"] .hourly,
.weather-widget[data-cond="night"] .daily {
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 color-mix(in srgb, #ffffff 34%, transparent),
    inset 0 0 0 1px color-mix(in srgb, #ffffff 14%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .slideBtn {
    transition: none;
  }
}

/* ===== Finance (stock) widget — Apple-Stocks-grade dark data slab ========================
   Background(direction halo + neutral dark slab)는 JS 인라인이 단독 소유(방향·강도 동적).
   방향색: 한국 관습 상승=빨강/하락=파랑(KRX), 해외 상장은 green/red — JS 토큰이 결정. */
.finance-widget {
  container-type: inline-size;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 4px;
  padding: 20px 22px;
  border-radius: 20px;
  color: #f4f6f8;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.09),
    inset 0 0 0 1px rgba(255, 255, 255, 0.06),
    0 18px 40px -14px rgba(0, 0, 0, 0.55);
}
.fin-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.fin-ident {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fin-name {
  font-size: 17px;
  font-weight: 600;
}
.fin-ticker {
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.55);
  font-variant-numeric: tabular-nums;
}
.fin-badge {
  flex: none;
  display: inline-flex;
  align-items: baseline;
  gap: 5px;
  padding: 5px 11px;
  border-radius: var(--ds-radius-pill, 999px);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fin-badge b {
  font-weight: 600;
}
.fin-badge-range {
  font-weight: 500;
  font-size: var(--ds-text-micro-11);
  opacity: 0.72;
}
.fin-price-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.fin-price {
  font-size: clamp(34px, 7cqw, 46px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.fin-currency {
  font-size: 0.42em;
  font-weight: 500;
  color: rgba(244, 246, 248, 0.6);
  margin-left: 3px;
}
.fin-asof {
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.45);
}
.fin-chart {
  margin-top: 4px;
}
/* Reserved readout band above the plot (WDS StockChart) — keeps height so scrub doesn't shift. */
.fin-readout {
  position: relative;
  width: 100%;
  height: 34px;
}
.fin-callout {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  white-space: nowrap;
  text-align: center;
  pointer-events: none;
}
.fin-callout[hidden] {
  display: none;
}
.fin-callout-time {
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.5);
}
.fin-callout-row {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}
.fin-callout-price {
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  color: #f4f6f8;
}
.fin-callout-change {
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.fin-plot {
  position: relative;
}
.fin-chart svg {
  display: block;
  width: 100%;
  height: 96px;
}
/* Draw-in reveal via clip-path on the line's wrapper group. Stroke-dash draw was
   dropped: with vector-effect="non-scaling-stroke" the dash is re-measured in device
   pixels, breaking pathLength normalization and leaving permanent gaps in the line. */
.fin-line-draw {
  animation: fin-line-draw 640ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes fin-line-draw {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
.fin-crosshair {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  transform: translateX(-50%);
  background: rgba(255, 255, 255, 0.28);
  pointer-events: none;
}
.fin-crosshair[hidden] {
  display: none;
}
.fin-dot {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: currentColor;
  box-shadow: 0 0 0 2px rgba(20, 22, 26, 0.9), 0 0 8px currentColor;
  pointer-events: none;
}
.fin-dot[hidden] {
  display: none;
}
@media (prefers-reduced-motion: reduce) {
  .fin-line-draw {
    animation: none;
    clip-path: none;
  }
}
.fin-chart-range {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.4);
  font-variant-numeric: tabular-nums;
}
.fin-segments {
  display: flex;
  gap: 4px;
  margin-top: 10px;
}
.fin-segment {
  flex: 1 1 0;
  padding: 6px 0;
  border: 0;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
  color: rgba(244, 246, 248, 0.6);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  cursor: pointer;
  transition: background var(--wds-duration-fast) ease, color var(--wds-duration-fast) ease;
}
.fin-segment:hover:not(:disabled):not(.is-active) {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(244, 246, 248, 0.85);
}
.fin-segment.is-active {
  background: rgba(255, 255, 255, 0.14);
  color: #f4f6f8;
}
.fin-segment:disabled {
  opacity: 0.32;
  cursor: default;
}
.fin-segment:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.55);
  outline-offset: 1px;
}
.fin-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px 16px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.045);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
.fin-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fin-stat-label {
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.5);
}
.fin-stat-value {
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fin-source {
  font-size: var(--ds-text-caption-12);
  color: rgba(244, 246, 248, 0.4);
}
@container (max-width: 480px) {
  .fin-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- News answer feed — magazine front page (2026-07-30) ------------------------------
   Figma "Free News & Magazine" (Design/desktop, frame 1920×5698) 어휘를 WIZON 토큰으로 옮긴 것.
   구조·비례만 가져오고 색은 하나도 가져오지 않는다:
     · top-tags      → 사진 깔린 주제 태그 (템플릿 필 ~118×40 → 레일 폭에 맞춰 106×40)
     · Slider        → 744×452 (1.65) + **밝은 프로스티드 인셋 밴드** + 화살표 + 알약 도트
     · popular-posts → 1512×459 gap 30 4열 → 컨테이너 폭에 따라 3/2/1열, 테두리·채움 없는 카드
     · 섹션 헤더      → 주제색 세로 바 + 제목 + 원형 이전/다음
   위젯감은 «면»이 아니라 사진 + 출처 행 + 넉넉한 간격에서 나온다. 그래서 카드에는 채움도
   테두리도 없다.

   ★원시 리터럴을 하나도 추가하지 않는다. 정적 UI 안티드리프트 래칫이 여섯 범주 전부
   여유 0이라(2026-07-30 실측: raw-color 1060/1060, raw-rgb 467/467, raw-border-radius
   206/206, raw-box-shadow 78/78, raw-font-size 72/72, inline-style 29/29) 색은 전부
   var(...)·color-mix(...)이고, 반경은 --ds-radius-* 또는 형태 백분율(50%)이며, 글자 크기는
   --ds-text-*, 그림자는 var()를 포함한 값만 쓴다. 주제 강조색도 새 팔레트를 만들지 않고
   --wds-chart-1..8(테마별로 따로 정의되어 있고 CVD 분리를 보존한다)을 슬롯으로 배정한다. */
.news-feed {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  /* ★리듬은 균일하지 않다. 목업은 18/20/26/26/24로 «헤더 근처는 조이고 큰 단락 사이는
     넓힌다». 균일 gap:18px은 그 리듬을 지웠으므로 gap을 0으로 두고 형제 규칙이 간격을
     만든다(아래 "수직 리듬" 블록). 실측(721px 컨텐츠 박스): 균일 18 → 18/20/26/26/24. */
  gap: 0;
  margin-top: 14px;
  /* 목업 24 / radius 22. 18/18은 위젯을 문서 블록처럼 납작하게 만들었다. */
  padding: 24px;
  border-radius: var(--ds-radius-xl);
  background: var(--cg-surface);
  /* 목업의 그림자는 셋이다: 인셋 헤어라인 + 근접 접지(2px) + 넓은 부양(20px). 앞의 하나만
     남기면 표면이 «떠 있는 위젯»이 아니라 «선으로 그린 상자»가 된다. 원시 리터럴은 쓰지
     않는다 — 두 그림자 모두 color-mix(var(--ds-black) …)라 raw-box-shadow/raw-rgb가 늘지 않는다. */
  box-shadow: inset 0 0 0 1px var(--cg-menu-border),
    0 2px 4px color-mix(in srgb, var(--ds-black) 3%, transparent),
    0 20px 40px -20px color-mix(in srgb, var(--ds-black) 22%, transparent);
  color: var(--cg-text);
}
/* ── 수직 리듬 ────────────────────────────────────────────────────────────────────────
   목업 실측: head→tags 18 · tags→stage 20 · stage→sec 26 · sec→sec 26 · foot 24(+구분선).
   형제 선택자라 어떤 블록이 없어도(주제 레일 없음, 히어로 없음) 남은 이웃이 올바른 간격을
   물려받는다 — 고정 margin을 각 블록에 박으면 «없을 때»가 어긋난다. */
.news-feed > * + * {
  margin-top: 18px;
}
.news-topics + .news-hero {
  margin-top: 20px;
}
.news-hero + .news-section,
.news-section + .news-section,
.news-topics + .news-section {
  margin-top: 26px;
}
.news-feed > .news-feed-foot {
  margin-top: 24px;
  padding-top: 14px;
  border-top: 1px solid var(--cg-menu-border);
}
/* 주제 강조색 슬롯. app.js의 newsTopicAccentSlot()이 주제명 해시로 1..8을 고르고 값은 여기서만
   산다 — 그래서 JS에도 CSS에도 새 색 리터럴이 없다. 0 = 주제 없음.
   ★0을 --cg-muted로 두면 «아무도 주제를 고르지 않은» 기본 상태 — 즉 모든 사용자가 처음 보는
   화면 — 에서 섹션 세로 바가 rgb(111,111,111) 회색으로 렌더된다(실측). 목업의 기본값은 회색이
   아니라 잉크다(`.fp-secname { --a: var(--cg-text) }`): 주제가 없을 때도 바는 «칠해진» 상태이고,
   주제를 고르면 그 주제색으로 «갈아탄다». 여기서도 같게 맞춘다 — 회색은 «비활성»으로 읽힌다. */
.news-feed [data-news-accent="0"] {
  --news-accent: var(--cg-text);
}
.news-feed [data-news-accent="1"] {
  --news-accent: var(--wds-chart-1);
}
.news-feed [data-news-accent="2"] {
  --news-accent: var(--wds-chart-2);
}
.news-feed [data-news-accent="3"] {
  --news-accent: var(--wds-chart-3);
}
.news-feed [data-news-accent="4"] {
  --news-accent: var(--wds-chart-4);
}
.news-feed [data-news-accent="5"] {
  --news-accent: var(--wds-chart-5);
}
.news-feed [data-news-accent="6"] {
  --news-accent: var(--wds-chart-6);
}
.news-feed [data-news-accent="7"] {
  --news-accent: var(--wds-chart-7);
}
.news-feed [data-news-accent="8"] {
  --news-accent: var(--wds-chart-8);
}
.news-feed-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 8px 14px;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--cg-muted, #8f8f8f);
}
/* ★스케일의 «꼭대기». 목업의 가장 큰 활자(23px "오늘의 주요 뉴스")가 통째로 빠져 있어서,
   이 위젯에서 가장 큰 글자가 히어로 제목이었고 그 히어로 제목마저 18.7px에 머물렀다 —
   즉 주변 채팅 본문(16px)과 사실상 같은 층이었다. 제목이 돌아오면서 22/18/15/12/11의
   단조 스케일이 성립한다(각 단계 ≥1.2배, 실측표는 test_news_magazine_front 참조).
   ★목업의 3분할 기간 컨트롤(24시간/48시간/7일)은 옮기지 않는다 — 포털에는 그 질의를 다시
   돌릴 경로가 없고, 아무것도 못 바꾸는 컨트롤은 없는 편이 낫다(이 파일의 기존 원칙).
   실제로 검색이 쓴 창은 이미 .news-facet-chip-window가 글자로 말한다. */
.news-feed-headline {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
/* ★★캐스케이드 접두사 `.chatgpt-reference-v1 .news-feed`가 «장식»이 아니다 — 없으면 이 규칙은
   통째로 죽는다. 이 위젯은 .message-body 안에 살고, 그 안의 h3/h4/p에는 전역 산문 규칙이
   이미 걸려 있다:
     · `.chatgpt-reference-v1 .message-body p` (0,2,0, 이 파일 뒤쪽) → font-size 16 / lh 1.7
     · `.message-body h3, h4, h5`             (0,1,1)               → margin 16px 0 9px / lh 1.25
     · `.message-body h3`                     (0,1,1)               → font-size title-20
   컴포넌트 클래스 하나(0,1,0)로는 셋 다 진다. 실측으로 두 번 물렸다:
     · 카드 요약이 16px/27.2px로 렌더돼 **자기 제목(14px)보다 컸다** — 위계가 뒤집혔다.
     · 섹션 헤더 블록이 20px 줄에 h4 마진 16+9가 붙어 45px가 됐다(목업 30).
   !important로 덮지 않는다. 접두사 두 개면 (0,3,0)이라 전역 산문 규칙보다 순서와 무관하게
   이긴다 — 다른 표면의 전역 규칙은 한 글자도 건드리지 않는다.
   ★이 접두사를 «간결하게» 벗기지 말 것. 벗기는 순간 위 세 규칙이 되살아난다. */
.chatgpt-reference-v1 .news-feed .news-feed-title {
  margin: 0;
  /* ★스케일의 «꼭대기». 상한이 --ds-text-heading-28인데 실제 채팅 폭에서는 그 아래에 선다:
     컨테이너 709px에서 3.7cqw = 26.23px(실측). 히어로 22px과 1.19배 벌어져 «위젯 이름»과
     «리드 기사»가 서로 다른 층으로 읽힌다.
     ★왜 목업의 23px이 아니라 26px인가 — 목업은 피드 제목 750 / 히어로 780으로 **웨이트**가
     둘을 갈랐다. 포털 타이포 계약(doc 160 T4)은 400/500/600만 허용하고 700은 모바일 워드마크
     1곳으로 래칫이 걸려 있어(test_static_contract.test_typography_contract) 그 채널이 닫혀
     있다. 닫힌 웨이트 채널의 몫을 크기 채널이 흡수한 값이 26px이다. */
  font-size: clamp(var(--ds-text-title-20), 3.7cqw, var(--ds-text-heading-28));
  font-weight: 600;
  line-height: var(--ds-leading-title, 1.32);
  letter-spacing: -0.024em;
  color: var(--cg-text);
}
/* <p>다 — 위 .news-feed-title 주석의 전역 산문 규칙에 같은 이유로 접두사가 필요하다. */
.chatgpt-reference-v1 .news-feed .news-feed-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: var(--ds-text-micro-11);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: normal;
}
/* ★«라이브» 점은 삭제했다(규칙도 @keyframes도). 두 가지 이유가 겹친다:
     ① 정직성 — 이 피드는 스트리밍이 아니라 «질의 시점에 고정된 스냅샷»이다. 맥동하는 라이브
        점은 갱신되지 않는 목록에 갱신을 약속한다. 신선도는 아래 as-of가 «글자로» 말한다.
     ② 실측 — 그 @keyframes의 70%/100% 프레임(`box-shadow: 0 0 0 7px transparent`,
        `0 0 0 0 transparent`)은 var()를 하나도 안 들고 있어서 정적 UI 안티드리프트의
        raw-box-shadow로 잡혔다. 이 규칙들이 들어오면서 그 범주가 천장을 넘겼다
        (2026-07-31 실측: ceiling 78 / actual 79 = RED). 삭제하면 79 → 77이 된다.
   ★두 규칙 다 마크업이 한 번도 없었다 — renderNewsFeed는 .news-live를 만든 적이 없고,
   `grep -rn "news-live\|newsLivePulse" apps/ai-portal`은 이 파일 안에서만 잡혔다. 즉 죽은
   규칙이라 지우는 데 표면 손실이 0이다. */
/* as-of는 «지금»이 아니라 «이 답변이 들고 있는 가장 신선한 기사의 시각»이다. 시각이 하나도
   없으면 아예 렌더되지 않는다 — 지어낸 기준 시각은 신선도에 대한 거짓말이다. */
.news-asof {
  color: var(--cg-muted);
  font-variant-numeric: tabular-nums;
}
/* Query facet chips (doc 337 A1) — the header says what the answer actually searched: the
   window the search really used, then the resolved topic, then the item count. These elements
   only exist when the gateway ships `news_query`, so a card without facets renders exactly as
   it did before. The chips carry text, never colour alone (WCAG SC 1.4.1): publisher identity
   already owns the colour channel on this surface, so the facets stay neutral. */
.news-facet-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
/* Hairline, no fill — measured live: --cg-surface resolves to the very colour the card itself
   uses (#ffffff light / dark equivalent), so a "filled" chip was invisible against its own
   background in both themes and only the border was ever doing the work. Follows the existing
   .chatgpt-topic-tag-badge precedent (hairline pill, no fill) for a quiet metadata row. */
.news-facet-chip {
  padding: 1px 6px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-xs, 6px);
  color: var(--cg-text-soft);
  font-weight: 500;
}
.news-facet-count {
  margin-inline-start: 2px;
  color: var(--cg-muted);
  font-weight: 500;
}
/* Publication time (doc 337 A2) — sits next to the publisher on the same byline (.news-by). The
   separator is a pseudo-element so it can never appear without a time beside it: an article
   with no usable timestamp renders no .news-time at all, and a stray "·" would read as a
   missing value rather than an absent one.
   ★색 토큰은 그대로 둔다. 2026-07-30 실측에서 이 라벨이 라이트 4.90:1로 이 표면에서 가장
   빠듯했다(test_news_card_a11y의 실측표). 사진 위 프로스티드 밴드에서만 --cg-text-soft로
   올려 쓴다 — 아래 .news-by-band 참조. */
.news-time {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  white-space: nowrap;
}
.news-time::before {
  content: "·";
  margin-inline: 6px;
}
/* ══ ① 사진 깔린 주제 태그 (템플릿 top-tags) ═══════════════════════════════════════════
   각 필의 배경은 그 주제의 «가장 신선한» 기사 사진이다 — 지어낸 그림이 아니라 그 주제가
   실제로 들고 있는 사진. 사진이 없거나 로드에 실패하면 강조색 틴트가 그대로 남고 스크림은
   그대로라, 라벨 대비가 두 경우 모두 동일하고 빈 자리가 생기지 않는다. */
.news-topics {
  position: relative;
}
.news-topics-rail {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-behavior: smooth;
  /* ★이 레일은 스크롤 컨테이너라 **자기 패딩 박스 밖을 잘라 낸다**. 바깥으로 그려지는 링은
     전부 여기서 죽는다. 실측(조상 overflow 검사): 첫 알약과 클리퍼 사이 여백이 가로 0px이라
     선택 링도 포커스 링도 왼쪽이 통째로 잘렸다 — 세로 4px도 선택 링(0 0 0 4px)에 여유가
     정확히 0이었다. 포커스 링은 6px까지 나가므로 6px로 올리고, 가로도 같은 6px을 준다.
     ★음수 마진으로 그 6px을 되돌린다 — 안 그러면 알약 열이 피드의 나머지 콘텐츠보다 6px
     안쪽으로 밀려 정렬이 깨진다. .news-topics에는 overflow가 없으므로 음수 마진은 잘리지 않는다.
     ★getComputedStyle은 이 결함을 **볼 수 없다**(outline 값은 정상으로 보고된다). 클리핑은
     계산값이 아니라 페인트라서, 계약 테스트가 아니라 조상 overflow 검사로만 잡힌다. */
  padding-block: 6px;
  padding-inline-start: 6px;
  margin-inline-start: -6px;
  padding-inline-end: 40px;
}
.news-topics-rail::-webkit-scrollbar {
  display: none;
}
.news-topic {
  --news-accent: var(--cg-muted);
  position: relative;
  overflow: hidden;
  flex: none;
  /* ★고정 106×40 → 최소값. 라벨은 rem으로 커지는데 알약이 px로 고정돼 있어서 텍스트 200%
     확대(WCAG SC 1.4.4)에서 라벨이 알약 밖으로 잘려 나갔다. 최소 크기만 남기고 실제 크기는
     라벨이 정하게 하면, 확대하면 알약도 같이 커진다. min-width는 «가지런한 레일»이라는
     원래 의도를 그대로 지킨다. */
  min-width: 106px;
  min-height: 40px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: color-mix(in srgb, var(--news-accent) 42%, var(--cg-hover));
  font: inherit;
  cursor: pointer;
  transition: transform var(--wds-duration-fast) var(--wds-ease-out),
    box-shadow var(--wds-duration-fast) ease;
}
.news-topic-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* 스크림. ★사진을 우리가 고르지 않으므로 라벨 대비를 사진에 맡길 수 없다. 순백 사진을
   최악으로 놓고 손으로 계산했다(자동 측정기는 그라데이션을 배경으로 읽지 못한다):
   검정 56%→78%면 라벨이 놓이는 중앙부(≈67%)에서 #fff 대비가 약 7:1, 글자 상단(≈61%)에서도
   약 4.95:1로 4.5:1 하한을 넘는다. 템플릿의 48%→74%는 상단에서 4.74까지 내려간다. */
.news-topic::after {
  content: "";
  position: absolute;
  inset: 0;
  /* ★스크림은 사진 «위»에 있어야 한다. .news-topic-img가 함께 다는 .news-thumb가 z-index:1을
     들고 있어서, 이걸 auto로 두면 ::after가 사진 아래로 깔린다 — 실브라우저에서 순백 사진
     타일이 흰 글자를 그대로 삼켰다(1280×1000, 라이트, 첫 타일 라벨이 통째로 사라짐).
     계산으로 정한 대비는 스크림이 위에 있을 때만 성립한다. */
  z-index: 2;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--ds-black) 56%, transparent),
    color-mix(in srgb, var(--ds-black) 78%, transparent)
  );
}
/* 분야별 기사 수 (doc 343 §3.4). 라벨 옆에 붙되 라벨을 밀어내지 않는다 —
   8개 탭이면 어느 탭이 알찬지 보이지 않아 사용자가 빈 탭을 누르게 된다.
   ★색은 새로 만들지 않는다. 라벨과 같은 토큰을 쓰고 불투명도로만 뒤로 물린다 —
   이 리포의 원시값 드리프트 래칫은 여유가 0이다. */
.news-topic-count {
  /* 라벨 안에 살므로 z-index·position이 따로 필요 없다 — 간격은 라벨의 column-gap이 준다. */
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1.4;
  color: var(--ds-white);
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
}
.news-topic-label {
  position: relative;
  z-index: 3; /* 사진(1) < 스크림(2) < 라벨 */
  display: grid;
  /* ★라벨과 건수 배지를 **한 줄에** 놓는다. 기본(row)이면 배지가 다음 줄로 떨어져 탭
     높이가 37px → 64px가 된다(실브라우저 실측). */
  grid-auto-flow: column;
  column-gap: 4px;
  place-items: center;
  /* height:100% + overflow:hidden이 알약을 «넘치면 자른다»로 만들고 있었다. 확대되면 라벨이
     알약을 밀어 키우도록 세로 패딩으로 바꾼다(잘림 → 성장). */
  padding: 10px 12px;
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.005em;
  color: var(--ds-white);
}
/* 선택은 색만으로 말하지 않는다: 강조색 링 + 스크림이 걷히며 사진이 드러나고, 보조기술에는
   aria-pressed가 간다(SC 1.4.1). */
.news-topic[aria-selected="true"] {
  box-shadow: 0 0 0 2px var(--cg-surface), 0 0 0 4px var(--news-accent);
}
.news-topic[aria-selected="true"]::after {
  opacity: 0.78;
}
/* 포커스 링은 이 블록 맨 끝의 «뉴스 포커스 링» 규칙 하나가 전담한다 — 여기 있던 개별
   :focus-visible 규칙은 (0,2,0)이라 전역 기본 링(0,3,3)에 져서 한 번도 그려진 적이 없다. */
.news-topics-more {
  position: absolute;
  inset-inline-end: 0;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  /* 목업 32 (30이었다). */
  width: 32px;
  height: 32px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 50%;
  background: var(--cg-surface);
  color: var(--cg-text-soft);
  cursor: pointer;
  /* 레일 끝을 표면색으로 덮어 «더 있다»는 잘림 신호를 만든다. */
  box-shadow: -12px 0 14px 8px var(--cg-surface);
}
.news-topics-more:hover {
  border-color: var(--cg-text-soft);
  color: var(--cg-text);
}
.news-topics-more .wds-inline-icon {
  width: 16px;
  height: 16px;
}

/* ══ ② 히어로 캐러셀 (템플릿 Slider 744×452 · 1.65) ═════════════════════════════════════ */
.news-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--ds-radius-md);
}
.news-hero-track {
  display: flex;
  transition: transform 460ms var(--wds-ease-out);
}
/* 오프셋은 인라인 style이 아니라 여기서 산다 — 전환·감속·reduced-motion과 같은 자리. */
.news-hero-track[data-news-hero-index="1"] {
  transform: translateX(-100%);
}
.news-hero-track[data-news-hero-index="2"] {
  transform: translateX(-200%);
}
.news-lead {
  position: relative;
  flex: 0 0 100%;
  display: block;
  box-sizing: border-box;
  overflow: hidden;
  aspect-ratio: 744 / 452;
  border-radius: var(--ds-radius-md);
  /* Real border (not inset box-shadow): overflow:hidden clips the photo to the inner radius,
     so a loaded image can never paint over the top/side frame the way it did with an inset
     shadow. It also gives a near-white photo an edge to sit against. */
  border: 1px solid var(--cg-menu-border);
  background: var(--cg-hover);
  text-decoration: none;
  color: inherit;
}
/* 포커스 링 → 블록 끝의 «뉴스 포커스 링» 참조(여기 있던 (0,2,0) 규칙은 죽은 코드였다). */
.news-lead-shot {
  position: absolute;
  inset: 0;
}
/* ★사진 없는 리드 = 텍스트 리드. 사진 자리를 비워 두는 대신 밴드가 슬라이드 «전체»가 된다.
   1.65 상자를 유지하면 커다란 빈 사각형 아래에 밴드만 놓인 모양이 되고, 그건 설계된 부재가
   아니라 고장으로 읽힌다(실브라우저 확인 — 레거시 페이로드에서 정확히 그랬다).
   흐릴 배경이 없으므로 프로스티드 처리도 걷는다. */
.news-lead[data-news-textonly] {
  aspect-ratio: auto;
  background: var(--cg-hover-soft);
}
.news-lead[data-news-textonly] .news-lead-band {
  position: static;
  padding: 16px 18px;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
/* 도트가 커커·발행처 줄 위로 겹치지 않도록 그만큼만 비워 둔다(알약 22 + 점 2개 + 간격 + 인셋). */
.news-lead[data-news-textonly] .news-lead-bandtop {
  padding-inline-end: 70px;
}
/* Real source thumbnail (20260709-news-thumb) — a failed load takes its whole slot with it
   (bindNewsPhotoFallbacks), so the surface never shows an empty box where a photo was
   promised. Subtle hover zoom gives the feed the same "alive" feel as the other widgets. */
.news-thumb {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* No opacity fade: an opacity transition here froze at currentTime 0 (the img is created
     and revealed in the same frame), leaving thumbnails invisible over the cover. The image
     just appears on load — the token background shows through until then. */
  transition: transform 420ms var(--wds-ease-out);
}
/* ★템플릿의 핵심 처리 — 가장자리에서 띄운 **밝은** 프로스티드 카드. 어두운 그라데이션이 아니다.
   투명도는 취향이 아니라 계산이다. 사진을 우리가 고르지 않으므로 최악(순백/순흑)을 가정한다:
     라이트(surface #ffffff) · 순흑 사진 → 밴드 rgb(224) → --cg-text 대비 ≈13:1
     다크 (surface #000000) · 순백 사진 → 밴드 rgb(31)  → --cg-text 대비 ≈13:1
   ★밴드 위 보조 텍스트는 --cg-muted가 아니라 --cg-text-soft를 쓴다. --cg-muted(#6f6f6f)는
   라이트 최악 밴드에서 3.46:1로 미달한다(카드 위에서는 5.02:1로 통과한다 — 배경이 다르다).
   backdrop-filter가 없는 브라우저에서는 86%로 더 불투명하게 떨어뜨려 같은 하한을 지킨다
   (라이트·순흑 사진 최악에서 밴드 rgb(219) → --cg-text 대비 약 13.2:1). */
.news-lead-band {
  position: absolute;
  z-index: 2;
  /* ★13이지 14가 아니다. .news-lead에는 1px 실테두리가 있고 이 밴드는 **패딩 박스** 기준으로
     자리를 잡는다. 14를 적으면 보이는 가장자리에서 15px 떨어져 보인다(실측 15). 13 + 테두리
     1 = 목업의 14px. */
  inset-inline: 13px;
  bottom: 13px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 16px 18px;
  border-radius: var(--ds-radius-md);
  background: color-mix(in srgb, var(--cg-surface) 86%, transparent);
  box-shadow: inset 0 0 0 1px var(--cg-menu-border);
}
@supports (backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px)) {
  .news-lead-band {
    /* ★88% → 78%(목업값). 88%는 «프로스티드 오버레이»가 아니라 «불투명한 판»으로 읽혔다.
       투명도는 취향이 아니라 계산이므로 낮추면서 하한을 다시 유도했다. 사진을 우리가 고르지
       않으므로 최악(순백/순흑)을 가정한다 — 78%의 최악 밴드는:
         라이트(surface #fff) · 순흑 사진 → 밴드 rgb(199) → --cg-text(#0d0d0d) 대비 11.49:1
         다크 (surface #000) · 순백 사진 → 밴드 rgb(56)  → --cg-text 대비는 아래 실측표 참조
       보조 텍스트(--cg-text-soft)도 라이트 최악에서 6.22:1로 4.5:1을 넘는다. 즉 하한(4.5:1)은
       88%가 아니라 «밴드가 만드는 대비»가 지키는 것이고, 78%도 그 하한 안쪽이다.
       ★핀을 «88 이상»이 아니라 «계산된 대비 하한»으로 바꿔 두었다
       (test_news_magazine_front.LiveMeasuredCssInvariantTest) — 프록시가 아니라 불변식을 잰다. */
    background: color-mix(in srgb, var(--cg-surface) 78%, transparent);
    -webkit-backdrop-filter: blur(22px) saturate(150%);
    backdrop-filter: blur(22px) saturate(150%);
  }
}
.news-lead-bandtop {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
}
/* 커커. ★강조색은 «점»이 나르고 주제 이름은 «글자»가 나른다. 강조색을 라벨 글자에 쓰면 사진
   위 밴드에서 대비를 보장할 수 없다 — 차트 토큰 일부는 라이트 최악 밴드에서 2.5:1까지
   떨어진다. 점은 바로 옆 글자가 같은 말을 하므로 장식이고, 글자는 --cg-text라 항상 안전하다. */
.news-kicker {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--cg-text);
}
.news-kicker::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--news-accent, var(--cg-muted));
}
.news-lead-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* ★상한 22px은 «승인된 크기»인데 2.6cqw로는 **닿지 않는 죽은 팔**이었다. 실측: 컨테이너
     709px에서 2.6cqw = 18.43px — 승인값보다 16.2% 작고, 주변 채팅 본문 16px의 1.15배라
     사실상 같은 층이었다. 중간 팔을 3.2cqw로 올리면 컨테이너 687.5px부터 상한에 닿는다.
     실제 채팅 폭(709px 실측)에서 3.2cqw = 22.69px → clamp 상한 22px로 고정된다.
     ★하한 body-16은 **1280만 재던 값**이었다. 390 실측(피드 컨테이너 283px): 3.2cqw = 9.06px
     이라 하한 16px에 눌리는데, 섹션 이름은 고정 18px이라 **리드 제목이 섹션 헤더보다 작았다**
     (16 : 18 = 0.889배). 1280에서 고친 것과 같은 종류의 위계 역전이 390에서 그대로 살아 있었다.
     하한을 title-18로 올린다 — 1280에서는 상한 22px에 걸려 있으므로 한 픽셀도 바뀌지 않고
     (3.2cqw × 709 = 22.69 > 22), 좁은 폭에서만 18px 바닥이 드러난다. 아래 .news-section-name /
     .news-card-link도 같은 이유로 유동화해서 사다리 전체가 **순서를 지킨 채** 함께 내려온다.
     웨이트는 위 .news-feed-title 주석과 같은 이유로 600이 상한이다. */
  font-size: clamp(var(--ds-text-title-18), 3.2cqw, var(--ds-text-title-22));
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.022em;
  text-wrap: pretty;
  color: var(--cg-text);
}
.news-lead:hover .news-lead-title {
  text-decoration: underline;
  text-underline-offset: 4px;
}
.news-lead-excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--ds-text-caption-12);
  line-height: 1.55;
  color: var(--cg-text-soft);
}
.news-hero-nav {
  position: absolute;
  z-index: 3;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  /* 목업 38 (36이었다). */
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--cg-surface) 84%, transparent);
  color: var(--cg-text);
  cursor: pointer;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--ds-black) 24%, transparent);
  transition: opacity var(--wds-duration-fast) ease, transform var(--wds-duration-fast) ease;
}
/* 자동 넘김 재생/정지 (doc 343 §4.1, WCAG 2.2.1) — 화살표와 같은 원형 컨트롤이되
   좌우가 아니라 왼쪽 아래에 앉는다(화살표·도트와 겹치지 않는 자리).
   ★글리프를 CSS로 그린다. WDS 아이콘셋(shared/wds/wds-icons.js)에 pause/play가 없고 그
   파일은 이 작업의 범위 밖이다. app.js 폴백 맵에만 넣으면 «앱에는 있는데 WDS에는 없는»
   파리티 드리프트가 생긴다 — 이 리포가 반복해 겪은 문제라 만들지 않는다.
   아이콘셋에 pause/play가 들어오면 이 규칙을 renderIcon 호출로 바꿀 것. */
.news-hero-autoplay {
  position: absolute;
  z-index: 3;
  inset-inline-start: 10px;
  bottom: 10px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, var(--cg-surface) 84%, transparent);
  color: var(--cg-text);
  cursor: pointer;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--ds-black) 24%, transparent);
}
.news-hero-autoplay::before,
.news-hero-autoplay::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 3px;
  height: 11px;
  /* ★라운딩 없음. 3px 막대에 1px 라운딩은 눈에 띄지도 않는데 원시값 드리프트 래칫을
     넘긴다(여유 0). 천장을 올려 통과시키지 않는다 — 그게 래칫의 존재 이유다. */
  background: currentColor;
  transform: translateY(-50%);
}
.news-hero-autoplay::before { inset-inline-start: calc(50% - 4px); }
.news-hero-autoplay::after { inset-inline-start: calc(50% + 1px); }
/* 멈춘 상태 = 다음 동작이 «재생»이므로 삼각형을 보인다. */
.news-hero-autoplay[aria-pressed="false"]::before {
  inset-inline-start: calc(50% - 3px);
  width: 0;
  height: 0;
  background: none;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-inline-start: 9px solid currentColor;
}
.news-hero-autoplay[aria-pressed="false"]::after { content: none; }

.news-hero-nav-prev {
  inset-inline-start: 10px;
}
.news-hero-nav-next {
  inset-inline-end: 10px;
}
.news-hero-nav .wds-inline-icon {
  width: 18px;
  height: 18px;
}
/* 화살표는 hover 가능한 포인터에서만 숨는다. 터치에서 숨기면 캐러셀을 넘길 방법이 도트뿐이 된다. */
@media (hover: hover) and (pointer: fine) {
  .news-hero-nav {
    opacity: 0;
  }
  .news-hero:hover .news-hero-nav,
  .news-hero-nav:focus-visible {
    opacity: 1;
  }
  .news-hero-nav:hover {
    transform: translateY(-50%) scale(1.06);
  }
}
/* ★★도트는 **자기 스크림 위에** 앉는다. 도트는 이 캐러셀의 유일한 상시 위치 표시기인데,
   사진 위에 바로 놓여 있던 동안 흰 도트 대 «흰 사진»이 실측 1.00:1이었다(라이트/다크,
   활성/비활성 네 경우 모두). 사진은 우리가 고르지 않으므로 배경에 기댈 수 없다.
   ★목업을 그대로 베끼지 않는다 — 목업의 처리는 1.26:1로 더 나쁘다.
   불투명도는 계산값이다. 순백 사진 최악에서 스크림 = 검정 70% → rgb(76.5):
     · 활성 도트(순백 #fff)  대 스크림 → 8.51:1
     · 비활성 도트(흰색 62%) 대 스크림 → 4.44:1   (둘 다 SC 1.4.11의 3:1을 통과)
   활성/비활성 구분은 색이 아니라 **너비**(24 대 10)가 나른다 — SC 1.4.1. */
.news-dots {
  position: absolute;
  z-index: 3;
  inset-inline-end: 13px;
  top: 13px;
  display: flex;
  align-items: center;
  /* 14px 간격은 장식이 아니라 SC 2.5.8 계산이다 — 아래 .news-dot::after 주석 참조. */
  gap: 14px;
  padding: 6px 10px;
  border-radius: var(--ds-radius-pill);
  background: color-mix(in srgb, var(--ds-black) 70%, transparent);
}
.news-dot {
  position: relative;
  /* 7 → 10. 히트 영역만 키우면 SC 2.5.8은 통과해도 **보이는** 표시기가 여전히 7px이라
     읽히지 않는다. */
  width: 10px;
  height: 10px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: color-mix(in srgb, var(--ds-white) 62%, transparent);
  cursor: pointer;
  transition: width 280ms var(--wds-ease-out),
    background var(--wds-duration-fast) ease;
}
/* ★SC 2.5.8(Target Size Minimum, AA) 계산. 이전 값(inset -9px -4px)은 7px 도트에 15×25
   히트 영역을 줬다 — 가로 15 < 24라 최소 크기도 미달이고, 중심 간격이 13px / 20.5px라
   «간격 예외»(24px 원이 겹치지 않을 것)도 동시에 미달이었다.
   지금: 도트 10 + inset 7 양쪽 = 24×24로 최소 크기를 정면 통과하고, gap 14px이라 비활성끼리
   중심 간격이 10+14 = 24px라 히트 영역이 서로 «닿기만» 하고 겹치지 않는다. */
.news-dot::after {
  content: "";
  position: absolute;
  inset: -7px;
}
.news-dot[aria-current="true"] {
  width: 24px;
  background: var(--ds-white);
}

/* ══ ③ 섹션 헤더 (템플릿: 세로 바 + 제목 + 우측 원형 화살표) ═══════════════════════════ */
.news-section {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.news-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
/* <h4>다 — 접두사가 없으면 `.message-body h4`(0,1,1)의 `margin: 16px 0 9px`가 이겨서 20px짜리
   글줄이 45px 블록이 된다(실측). 접두사로 (0,3,0)을 만들면 마진 0이 실제로 적용돼 30px가 된다.
   크기도 body-16 → title-18: 16px은 주변 채팅 본문과 **같은 값**이라 «섹션 이름»이라는 역할이
   활자로는 하나도 표시되지 않았다. 18px이면 카드 제목 15px과 1.20배로 갈라진다.
   ★고정 18px은 1280에서만 옳았다. 390(컨테이너 283px)에서는 히어로 제목이 하한으로 눌려
   내려오는데 이것만 18px에 못 박혀 있어서 **섹션 이름이 리드 제목보다 커졌다**(실측 18 : 16).
   유동화한다: 2.6cqw는 컨테이너 692.3px부터 상한 18px에 닿으므로 실채팅 폭 709px에서는
   18.43 → 18px로 **1280 값이 그대로 유지**되고(실측), 좁은 폭에서만 하한 body-16이 드러난다.
   하한을 14가 아니라 16으로 두는 이유는 아래 .news-card-link(하한 14)와 1.14배를 유지하기
   위해서다 — 사다리의 각 칸은 좁은 폭에서도 최소 한 단계(토큰 사다리의 이웃 눈금)를 벌린다. */
.chatgpt-reference-v1 .news-feed .news-section-name {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  font-size: clamp(var(--ds-text-body-16), 2.6cqw, var(--ds-text-title-18));
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--cg-text);
}
.news-section-bar {
  flex: none;
  width: 3px;
  height: 17px;
  border-radius: var(--ds-radius-2xs);
  background: var(--news-accent, var(--cg-text));
}
.news-section-arrows {
  display: flex;
  gap: 7px;
}
.news-arrow {
  display: grid;
  place-items: center;
  /* 목업 32 (30이었다). */
  width: 32px;
  height: 32px;
  border: 1px solid var(--cg-menu-border);
  border-radius: 50%;
  background: transparent;
  color: var(--cg-text-soft);
  cursor: pointer;
  transition: border-color var(--wds-duration-fast) ease, color var(--wds-duration-fast) ease,
    background var(--wds-duration-fast) ease;
}
.news-arrow:hover {
  border-color: var(--cg-text-soft);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}
.news-arrow .wds-inline-icon {
  width: 16px;
  height: 16px;
}

/* ══ ③b 2단 — 톱과 카드 트랙 사이 두 칸 (doc 344 §10) ══════════════════════════════════
   ★사진이 없다. 1면의 위계는 사진 크기가 아니라 활자와 밀도로 만든다 — 톱(사진 위 밴드) →
   2단(제목 + 요약 1줄) → 카드(썸네일 + 요약 2줄). 2단에 사진을 주면 톱과 같은 층이 되어
   1면이 «큰 사진 세 덩이»가 된다.
   ★카드 트랙과 달리 여기는 **평범한 2열 격자**다. 두 칸뿐이라 페이징할 것이 없고, 트랙으로
   만들면 스냅·페이저·2줄 기하가 두 벌이 된다. */
/* 구획 전체(라벨 + 격자). hidden은 여기가 든다 — 격자만 숨기면 라벨이 홀로 남는다. */
.news-second-tier {
  display: block;
  margin-top: 16px;
  padding-top: 14px;
  /* ★--cg-border는 **정의되지 않은 토큰**이다(NoPhantomCgBorderTokenTest가 잡는다). 이 표면의
     구분선은 --cg-menu-border를 쓴다 — 바로 위 .news-topics + .news-hero가 같은 값이다. */
  border-top: 1px solid var(--cg-menu-border);
}
/* ★`[hidden]`은 (0,0,1)이라 바로 위 `display: block` (0,1,0)에 진다 — .news-card[hidden]에서
   같은 것을 실브라우저로 확인했다. 없으면 기사가 적은 분야에서 빈 구획이 선만 남기고 보인다. */
.news-second-tier[hidden] {
  display: none;
}
.news-second-tier > .news-section-head {
  margin-bottom: 10px;
}
.news-second {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
/* ★셀은 2열 격자다: 왼쪽에 제목·요약, 오른쪽에 64px 썸네일, 발행처 행은 아래를 가로지른다.
   flex 세로 쌓기로는 썸네일을 «제목 옆»에 둘 수 없다. */
.news-second-cell {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-rows: auto auto auto;
  column-gap: 12px;
  row-gap: 4px;
  align-items: start;
  min-width: 0;
}
.news-second-cell > .news-second-link {
  grid-column: 1;
  grid-row: 1;
}
.news-second-cell > .news-second-excerpt {
  grid-column: 1;
  grid-row: 2;
}
.news-second-cell > .news-second-shot {
  grid-column: 2;
  grid-row: 1 / span 2;
}
.news-second-cell > .news-second-foot {
  grid-column: 1 / -1;
  grid-row: 3;
}
/* 카드와 같은 «늘린 링크» 구조. 제목은 카드(15)와 톱 사이 층이라 16이다. */
.news-second-link {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: clamp(var(--ds-text-body-15), 2.4cqw, var(--ds-text-body-16));
  font-weight: 600;
  line-height: 1.36;
  letter-spacing: -0.014em;
  text-wrap: pretty;
  text-decoration: none;
  color: var(--cg-text);
}
.news-second-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--ds-radius-sm);
}
.news-second-link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* ★<p>다 — 접두사 없이는 `.chatgpt-reference-v1 .message-body p` (0,2,0)가 이겨서 요약이
   16px로 렌더되고 **자기 제목보다 커진다**. .news-card-excerpt가 정확히 그렇게 깨져 있었다.
   접두사 두 개 = (0,3,0)이라 파일 순서와 무관하게 이긴다(CascadeOverrideTest가 소유한다). */
.chatgpt-reference-v1 .news-feed .news-second-excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  line-height: 1.55;
  color: var(--cg-muted);
}
.news-second-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 6px;
}
/* ★★썸네일 두 함정 — 둘 다 라이브 DOM에 후보를 주입해서 잡았다(T6c). 합성 하네스에는
   전역 `.news-thumb` 규칙이 없어 **둘 다 안 보인다**.
   ① `.news-thumb`는 `position: absolute`다. 감싸개가 relative가 아니면 이미지가 셀 원점으로
      튀어 제목 위에 겹친다(.news-card-shot이 relative인 이유가 이것이다).
   ② `.news-second-shot img` (0,1,1)는 전역 `.news-thumb`에 **진다**. 접두사 두 개로
      (0,3,1)을 만들어야 64px가 실제로 먹는다 — 안 그러면 이미지가 346px로 퍼진다(실측). */
.chatgpt-reference-v1 .news-feed .news-second-shot {
  position: relative;
  flex: none;
  width: 64px;
  height: 64px;
  overflow: hidden;
  border-radius: var(--ds-radius-sm);
  background: var(--cg-hover);
}
.chatgpt-reference-v1 .news-feed .news-second-shot .news-second-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ══ ④ 카드 (템플릿 popular-posts) ═════════════════════════════════════════════════════
   채움도 테두리도 없다. 사진과 출처 행이 카드를 만든다. */
/* align-items는 stretch(기본)로 둔다. 사진 없는 기사가 섞이면 start에서는 그 카드만 위로
   붙어 행이 들쭉날쭉해 보인다(실브라우저 확인) — stretch면 카드 높이가 같아지고
   .news-card-foot의 margin-top:auto가 모든 출처 행을 같은 바닥선에 정렬한다. */
/* ★세로 2줄 고정 · 가로 흐름. 예전에는 3열 세로 격자여서 지면 높이가 기사 수를 그대로
   따라갔다 — 24건이면 7줄, 카드 구간만 2000px을 넘었다. 이제 줄은 2로 고정이고 남는 기사는
   오른쪽으로 흘러 페이지 단위로 넘어간다.
   ★열 수가 아니라 **줄 수**를 고정한 이유: 열 수는 컨테이너 폭에 따라 3→2→1로 접히는데,
   카드를 6개씩 «페이지»로 묶어 두면 좁은 폭에서 한 페이지가 3줄·6줄이 되어 «2줄» 약속이
   깨진다. 줄을 고정하고 열을 흐르게 두면 어떤 폭에서도 2줄이고, JS는 개수를 세지 않는다.
   ★grid-auto-columns가 한 «페이지»의 열 수를 정한다. 100%를 열 수로 나눈 값이라 한 화면에
   정확히 그 수만큼 들어가고, scrollBy(clientWidth)가 곧 한 페이지가 된다. */
.news-cards {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(2, minmax(0, auto));
  grid-auto-columns: calc((100% - 32px) / 3);
  gap: 16px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* 스크롤 컨테이너가 카드의 focus-visible 링을 잘라 먹지 않게 한다. */
  padding-block: 2px;
}
.news-cards::-webkit-scrollbar {
  display: none;
}

/* ══ 한 페이지에 다 들어가면 «행»으로 채운다 (2026-08-04, 사용자 지적) ═══════════════
   격자는 `grid-auto-flow: column` + 2행이라 **아래로 먼저** 채운다. 기사가 12·23건인
   분야에서는 그래야 페이지가 꽉 차지만, 문화처럼 **2건**뿐이면 한 열에 세로로 쌓이고
   오른쪽 2/3가 빈다 — 사용자가 화면에서 지적한 모양이 이것이다.

   ★임계는 **4개**다. 가장 좁은 페이지(620px, 2열×2행)가 4개이므로, 4개 이하이면 어느
     폭에서도 스크롤이 필요 없다. 그래서 컨테이너 쿼리는 **열 폭만** 바꾸면 되고
     (`test_every_width_keeps_exactly_two_rows`의 약속), 줄 수를 건드릴 일이 없다.
   ★5개부터는 원래의 열 흐름·좌우 페이징 그대로다. 넘치는 분야까지 행 흐름으로 두면
     컨테이너가 세로로 자라 캐러셀이 사라진다(페이저는 scrollWidth/clientWidth로 센다).

   라이브 DOM 주입 실측(3열): 2개 → 1행 나란히 · 4개 → 첫 줄 3개+1개 · 5개↑ → 열 흐름 복귀. */
.news-cards:not(:has(> .news-card:nth-child(5))) {
  grid-auto-flow: row;
  grid-template-rows: none;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  justify-content: start;
}
.news-cards > .news-card {
  scroll-snap-align: start;
}
.news-page-count {
  /* 화살표만으로는 «얼마나 더 있는지»를 알 수 없다. 이 표시가 없으면 끝을 확인하려고
     끝까지 눌러 보는 수밖에 없다. aria-hidden인 이유: 같은 사실을 피드의 aria-label과
     라이브 리전이 이미 문장으로 말한다. */
  align-self: center;
  margin-inline-end: 3px;
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  font-variant-numeric: tabular-nums;
}
.news-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
/* ★없으면 주제 필터가 화면에서 아무 일도 하지 않는다. selectNewsTopic이 card.hidden = true를
   놓아도, 사용자 에이전트 기본 규칙 `[hidden] { display: none }`은 특이도 (0,0,1)이라
   바로 위 `.news-card { display: flex }` (0,1,0)에 진다. 실브라우저에서 실측했다:
   aria-pressed="true"에 hidden 속성까지 붙은 카드가 display:flex로 그대로 보였다.
   DOM 스텁은 hidden을 «속성이 있으니 숨겨졌다»로 읽어 이 결함을 통과시킨다. */
.news-card[hidden] {
  display: none;
}
.news-card-shot {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  border-radius: var(--ds-radius-sm);
  background: var(--cg-hover);
}

/* ══ 사진 없는 기사의 «채워진» 자리 (2026-08-04, 사용자 지적) ══════════════════════════
   사진이 없다고 칸을 통째로 빼면 카드마다 제목 시작점이 달라져 격자가 들쭉날쭉해 보인다.
   `align-items: stretch`가 **발**은 맞춰 주지만 **머리**는 못 맞춘다.

   ★예전 결정(«빈 상자를 남기지 않는다»)과 모순이 아니다. 그때 문제는 **아무것도 없는**
     사각형이었다. 여기서는 «사진 없음»으로 채운다 — 헤어라인 테두리와 글리프가 있으면
     로딩 스켈레톤이나 깨진 이미지가 아니라 **의도된 부재**로 읽힌다.
   ★리드(히어로)는 제외다. 1.65 상자를 이렇게 채우면 커다란 슬래브가 되고, 그 모양은
     실브라우저에서 이미 기각됐다(.news-lead[data-news-textonly] 참조). */
.news-card-shot[data-news-photo="empty"],
.chatgpt-reference-v1 .news-feed .news-second-shot[data-news-photo="empty"] {
  display: grid;
  place-items: center;
  background: var(--cg-hover-soft, var(--cg-hover));
  box-shadow: inset 0 0 0 1px var(--wizon-ai-popover-border);
}
.news-shot-empty {
  display: grid;
  place-items: center;
  color: var(--cg-muted);
  opacity: 0.34;
}
.news-shot-empty svg {
  /* 카드는 넉넉히, 64px 2단 칸은 작게 — 칸 폭을 따라간다. */
  inline-size: clamp(18px, 22%, 34px);
  block-size: auto;
}
/* 카드 전체가 링크지만 <a> 안에 버튼을 넣지 않는다(무효 HTML이자 키보드 함정). 늘린 링크가
   카드를 덮고, 북마크 버튼만 그 위로 올라온다. */
.news-card-link {
  margin-top: 5px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* 14 → 15. 카드 제목은 요약(12)보다 위, 섹션 이름(18)보다 아래여야 한다. 14px이면
     요약과 1.17배밖에 안 벌어지고, 15px이면 1.25배다.
     ★고정 15px이면 좁은 폭에서 사다리가 «위만» 내려오고 여기서 멈춰 칸 간격이 무너진다.
     2.2cqw는 컨테이너 681.8px부터 상한 15px에 닿으므로 실채팅 폭 709px에서는 15.6 → 15px로
     **1280 값이 그대로 유지**되고(실측), 390(283px)에서만 하한 body-14가 드러나 요약 12px과
     1.17배를 지킨다. 하한을 13으로 더 낮추지 않는 이유가 그것이다 — 13이면 1.08배로 요약과
     사실상 같은 층이 된다. */
  font-size: clamp(var(--ds-text-body-14), 2.2cqw, var(--ds-text-body-15));
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.014em;
  text-wrap: pretty;
  text-decoration: none;
  color: var(--cg-text);
}
.news-card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--ds-radius-sm);
}
.news-card-link:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* 포커스 링 → 블록 끝의 «뉴스 포커스 링» 참조(여기 있던 (0,2,0) 규칙은 죽은 코드였다). */
/* ★★이 위젯에서 유일한 <p>다. 접두사가 없던 동안 `.chatgpt-reference-v1 .message-body p`
   (0,2,0)가 이겨서 요약이 **16px/27.2px**로 렌더됐다 — 자기 카드 제목(14px)보다 크다.
   모든 카드에서 위계가 뒤집혀 있었다(실측). 접두사 두 개 = (0,3,0)이라 순서와 무관하게 이긴다.
   위 .news-feed-title 주석에 이 캐스케이드 사고의 전모가 있다. */
.chatgpt-reference-v1 .news-feed .news-card-excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
  font-size: var(--ds-text-caption-12);
  font-weight: 400;
  line-height: 1.55;
  color: var(--cg-muted);
}
.news-card-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  padding-top: 8px;
}
/* 출처 행 = 템플릿의 «아바타 + 작성자 + 날짜». 우리는 작성자가 없고 언론사가 있다. */
.news-by {
  display: flex;
  align-items: center;
  min-width: 0;
}
.news-by-band .news-time {
  /* 프로스티드 밴드 위에서만 한 단계 올린다 — 위 .news-lead-band 주석의 계산 참조. */
  color: var(--cg-text-soft);
}
.news-bookmark {
  /* 늘린 카드 링크(.news-card-link::after) 위로 올라와야 눌린다. */
  position: relative;
  z-index: 1;
  flex: none;
  margin-inline-start: auto;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
  transition: color var(--wds-duration-fast) ease, background var(--wds-duration-fast) ease;
}
.news-bookmark:hover {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}
.news-bookmark .wds-inline-icon {
  width: 16px;
  height: 16px;
}
/* 눌림은 색과 «형태»를 함께 바꾼다 — 외곽선 북마크가 채워진 북마크가 된다(SC 1.4.1). */
.news-bookmark[aria-pressed="true"] {
  color: var(--news-accent, var(--cg-text));
}
.news-bookmark[aria-pressed="true"] .wds-inline-icon {
  fill: currentColor;
}
@media (hover: hover) and (pointer: fine) {
  .news-topic:hover {
    transform: translateY(-2px);
  }
  .news-card:hover .news-card-img {
    transform: scale(1.05);
  }
  .news-lead:hover .news-lead-img {
    transform: scale(1.04);
  }
}
.news-fav {
  position: relative;
  overflow: hidden;
  flex: none;
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border-radius: 4px;
  font-size: 10px;
  font-weight: 600;
  color: #ffffff;
}
/* Branded letter fallback — sits under the favicon and shows when the favicon fails to load
   (removed in mountNewsFeeds). */
.news-fav-letter {
  line-height: 1;
}
/* Real site favicon layered over the letter box. White fill keeps transparent logos crisp;
   object-fit contain avoids cropping the mark. */
.news-fav-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #ffffff;
}
.news-feed-foot {
  font-size: var(--ds-text-caption-12);
  color: var(--cg-muted, #8f8f8f);
}

/* ══ 뉴스 포커스 링 ═══════════════════════════════════════════════════════════════════════
   ★이 표면에 흩어져 있던 네 개의 :focus-visible 규칙은 **한 번도 그려진 적이 없다**. 전역
   기본 링
     `.chatgpt-reference-v1 :focus-visible:not(input):not(textarea):not(select):not([contenteditable="true"])`
   이 (0,3,3)이라 컴포넌트 규칙 (0,2,0)을 전부 눌렀다. 실측(포커스 후 getComputedStyle):
   여덟 컨트롤 전부 outline-color가 전역값 rgba(13,13,13,0.16) — 배경 대비 **1.42:1**
   (다크는 rgba(255,255,255,0.18) = 1.55:1). SC 1.4.11의 3:1에 한참 못 미치고, 사진 위에서는
   배경이 무엇이든 될 수 있으니 더 나쁘다.
   ★해결은 !important도, 전역 규칙 약화도 아니다. `:is()`는 인자 중 «가장 센 것»의 특이도를
   가지므로 이 선택자는 (0,4,0) — 클래스 자리가 4 > 3이라 **순서와 무관하게** 전역을 이긴다.
   다른 표면의 전역 링은 한 글자도 바뀌지 않는다.
   ★두 색 링(안쪽 흰색 3px + 바깥 검정 3px)인 이유: 사진 위에서는 배경 대비를 보장할 수
   없으므로 **링끼리** 대비를 갖게 한다(#fff 대 #000 = 21:1). 어떤 배경에서도 둘 중 하나는
   3:1을 넘는다 — 실측: 흰 배경에서 검정 링 21:1, 검은 사진에서 흰 링 21:1, 중간 회색(128)
   에서 흰 3.95:1 / 검정 5.32:1.
   ★★그리고 이 규칙은 @media (pointer: coarse) 안의 전역 `outline: none`(같은 (0,3,3))도
   이긴다 — 그래서 터치스크린 노트북·키보드 붙인 태블릿에서 뉴스 컨트롤 26개의 포커스가
   «사라지지» 않는다. 그 전역 억제는 그대로 두었다(다른 표면은 종전과 동일). */
.chatgpt-reference-v1
  .news-feed
  :is(
    .news-lead,
    .news-second-link,
    .news-card-link,
    .news-topic,
    .news-topics-more,
    .news-hero-nav,
    .news-hero-autoplay,
    .news-arrow,
    .news-dot,
    .news-bookmark,
    .news-subscribe-btn):focus-visible {
  outline: 3px solid var(--ds-white);
  outline-offset: 0;
  box-shadow: 0 0 0 6px var(--ds-black);
}
/* 선택된 주제 탭은 강조색 링으로 «선택»을 말한다. 포커스 링이 그 자리를 덮어쓰지 않도록
   바깥에 한 겹 더 얹는다 — 포커스와 선택이 동시에 보인다.
   ★aria-pressed → aria-selected. 탭은 «눌림»이 아니라 «선택»이다(doc 343 §4.3). 선택자를
   같이 안 바꾸면 이 규칙이 조용히 아무 요소에도 안 걸린다. */
.chatgpt-reference-v1 .news-feed .news-topic[aria-selected="true"]:focus-visible {
  box-shadow: 0 0 0 6px var(--ds-black), 0 0 0 8px var(--news-accent);
}
/* ★★히어로 슬라이드만 예외다. .news-hero는 overflow:hidden이고 슬라이드가 그 상자를 «꽉»
   채우므로(실측: 클리퍼와의 여백이 사방 0px) 바깥으로 그리는 링은 통째로 잘린다 — 실제로
   포커스 스크린샷에서 링이 한 픽셀도 보이지 않았다. 레일과 달리 여기엔 패딩을 줄 자리가
   없다(패딩을 주면 캐러셀 트랙 계산이 어긋난다). 그래서 이 컨트롤만 링을 **안쪽**에 그린다.
   ★box-shadow: inset은 배경 레이어라 사진(.news-thumb, z-index:1) 아래로 깔려 보이지 않는다.
   그래서 의사요소에 얹고 z-index를 사진·밴드보다 위로 올린다.
   ★두 겹의 순서: 목록 뒤쪽 그림자가 «뒤»에 깔린다. 흰색 0..3px이 위, 검정 0..6px이 아래라
   화면에는 흰 3px(안) + 검정 3px(밖)으로 보인다 — 바깥 두 규칙과 같은 21:1 쌍이다.
   ★outline을 끄는 건 «포커스를 지우는 것»이 아니라 같은 요소에서 더 잘 보이는 표시로
   **교체**하는 것이다. 아래 ::after가 없으면 이 규칙은 접근성 후퇴다 — 함께 지울 것. */
.chatgpt-reference-v1 .news-feed .news-lead:focus-visible {
  outline: none;
  box-shadow: none;
}
.chatgpt-reference-v1 .news-feed .news-lead:focus-visible::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 4; /* 사진(1) < 밴드(2) < 화살표·도트(3) < 포커스 링 */
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 3px var(--ds-white), inset 0 0 0 6px var(--ds-black);
}

/* ---- Generated file download card (doc 171 P2 / batch D3) -----------------------------
   Server-generated file (e.g. xlsx) sits below the answer body as a single download
   affordance. Tone matches .md-table-copy (small outline button on --cg-* surface tokens);
   layout matches .news-feed (bordered card, container query for narrow reflow). */
.generated-file-card {
  container-type: inline-size;
  display: flex;
  /* wrap lives here, not in the @container block below: a container query styles a container's
     descendants, never the container element itself, so the narrow-width rule cannot flip the
     card's own flex-wrap. Without it the button's flex-basis: 100% overflows instead of wrapping. */
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  padding: 14px 16px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-menu-radius);
  background: var(--cg-surface);
  color: var(--cg-text);
}
.generated-file-icon {
  display: grid;
  flex: none;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: var(--wizon-ai-radius-control);
  color: var(--cg-text-soft, var(--muted));
}
/* The attachment artwork carries its own colour and its own paper shape, so the grey tile
   the old inline glyph needed would only box it in. Kept for the svg branch in case a card
   ever falls back to a line icon. */
.generated-file-icon svg,
.generated-file-icon .wds-inline-icon {
  width: 18px;
  height: 18px;
  background: var(--cg-hover-soft, var(--surface-2));
  border-radius: var(--wizon-ai-radius-control);
}
.generated-file-icon .composer-attachment-art {
  width: 32px;
  height: 32px;
  object-fit: contain;
}
.generated-file-body {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.generated-file-name {
  overflow: hidden;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.generated-file-meta {
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft, var(--muted));
}
/* doc 171 S2c — the actions beside a generated file. Shaped from .generated-file-download
   below rather than from a design-system class name: the portal stylesheet has no ds-button,
   and borrowing one that does not exist is how the save button ended up as wrapped text in a
   34px box on 2026-08-10. */
.generated-file-action {
  display: inline-flex;
  flex: none;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-control);
  background: var(--cg-text, var(--text));
  color: var(--cg-surface);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}

.generated-file-more {
  position: relative;
  flex: none;
}

.generated-file-more-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  padding: 6px 8px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text, var(--text));
  font: inherit;
  line-height: 1;
  cursor: pointer;
}

.generated-file-more-menu {
  position: absolute;
  right: 0;
  z-index: 20;
  display: grid;
  min-width: 168px;
  margin-top: 4px;
  padding: 4px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-menu-row);
  background: var(--cg-surface);
  box-shadow: var(--ds-shadow-md);
}

.generated-file-more-menu[hidden] {
  display: none;
}

.generated-file-more-menu button {
  padding: 8px 10px;
  border: 0;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
}

.generated-file-more-menu button:hover,
.generated-file-more-menu button:focus-visible {
  background: color-mix(in srgb, var(--cg-text) 6%, transparent);
}

.generated-file-download {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-control);
  background: var(--cg-surface, #fff);
  color: var(--cg-text, var(--text));
  font: inherit;
  font-size: var(--ds-text-caption-12);
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, opacity 120ms ease;
}
.generated-file-download:hover {
  background: var(--cg-hover-soft, var(--surface-2));
}
.generated-file-download:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, #0d0d0d);
  outline-offset: 2px;
}
.generated-file-download:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}
.generated-file-download.is-copied {
  color: var(--accent, #2f6bff);
}
.generated-file-download.is-expired {
  color: var(--cg-text-soft, var(--muted));
}
.generated-file-download-icon {
  display: inline-flex;
}
.generated-file-download-icon svg,
.generated-file-download-icon .wds-inline-icon {
  width: 13px;
  height: 13px;
}
.generated-file-card.is-expired .generated-file-icon {
  opacity: 0.6;
}
.generated-file-card.is-expired .generated-file-meta {
  color: var(--cg-text-soft, var(--muted));
}
@container (max-width: 520px) {
  /* .generated-file-body deliberately keeps its base flex: 1 1 auto here (no flex-basis: 100%
     override) so it shares the first row with the icon instead of forcing the icon to sit alone
     on a mostly-empty line. Only the download button drops to its own full-width row below. */
  .generated-file-download {
    flex-basis: 100%;
    justify-content: center;
  }
}
@media (prefers-reduced-motion: reduce) {
  .generated-file-download {
    transition: none;
  }
}

/* ---- Document summary insight card (D2, docs/53 §7.1 · specs/2026-06-03) ------------------
   Evidence-backed insight surface for attached-document answers: enterprise-dense, subdued,
   ≤8px radius, no decorative gradients, tone via border/text (never color-only — WCAG AA). Sits
   below the prose answer (attach). Container query reflows the fact tiles, not a breakpoint.
   Tokens only (no raw hex — anti-drift ratchet); tone accents reuse the semantic danger/success/
   accent tokens (no warning token exists, so warning shares the accent emphasis). */
/* 2026-08-26 공용 위젯 카드 셸로 이관(차별화 축① 1차 슬라이스).
   컨테이너·표면·실선·모서리·여백·본문색은 이제 .wiz-card[data-wiz-density="compact"]
   가 소유한다(wizon-widget-card-shell.css). 여기 남아 있던 같은 선언은 지웠다 —
   두 시트가 같은 속성을 걸면 «나중에 로드된 쪽»만 이기고, 지는 선언은 화면에 한 번도
   닿지 않으면서 읽는 사람만 헷갈리게 한다(이 시트 14600행대에 같은 사고 기록 있음).
   raw 14px/16px 도 함께 사라진다 — 스케일 밖 값이 토큰으로 흡수된 자리다. */
.doc-summary-head {
  margin-bottom: 0;
}
/* 배지와 상태 칩을 한 덩어리로 묶는 eyebrow 슬롯. 셸의 __headings 안에서 제목 위에
   선다 — 이전에는 셋(배지·상태·문서명)이 한 줄에 나란했지만, 문서명은 «출처/시각»
   이라 셸의 __meta 로 갈라졌다. */
.doc-summary-eyebrow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wiz-card-gap-tight);
}
.doc-summary-badge {
  padding: 2px 8px;
  border-radius: var(--ds-radius-xs);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.doc-summary-status {
  padding: 2px 8px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill);
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
}
.doc-summary-status[data-status="completed"] {
  border-color: color-mix(in oklab, var(--accent) 40%, transparent);
  color: var(--accent);
}
.doc-summary-doc {
  margin-left: auto;
  overflow: hidden;
  max-width: 100%;
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 제목과 개요의 여백·크기·굵기·색은 셸의 .wiz-card__title / .wiz-card__subtitle 이
   소유한다. 세로 리듬은 이제 margin-bottom 이 아니라 __headings 의 gap 이 만든다.
   ★한 가지 «의도한» 변화: 개요가 본문색(--cg-text)에서 보조색(ink-soft)으로 내려간다.
   제목 아래 딸린 문장이 제목과 같은 농도로 서 있으면 위계가 안 생기고, 옆 카드
   (commerce)의 부제는 이미 --wizon-ai-text-secondary 였다. 두 카드가 «부제가 무슨
   색인가»에 서로 다른 답을 갖고 있던 걸 하나로 맞춘 자리다. */
/* (규칙 없음 — 셸이 전부 소유한다. 여기에 같은 속성을 한 줄이라도 남기면 «지는
   선언»이 되어 읽는 사람만 속인다.) */
.doc-summary-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 10px;
}
.doc-summary-fact {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-sm);
  background: var(--cg-hover-soft);
  min-width: 0;
}
/* ★경고와 위험은 다른 단계다. 두 tone이 한 선택자에 묶여 --cg-danger-fg 하나를 쓴 탓에
   화면에서 같은 빨강으로 뭉개졌다 — fact 타일의 tone 신호는 이 테두리 하나뿐이라
   (app.js의 타일은 label/value에 tone별 스타일이 없다) 두 단계를 구분할 방법이 없었다.
   .doc-summary-notice가 이미 warning/danger를 나눠 쓰는 것과 같은 형태로 맞춘다.
   실브라우저 실측(color-mix 55% 통과 후 캔버스로 되읽은 합성 픽셀, 타일 배경
   --cg-hover-soft 대비): 라이트 #b45309→#d19c73 2.19:1, 다크 #f59e0b→#956514 3.18:1.
   다크는 이 자리에 있던 빨강(2.61:1)보다 오히려 나아진다. 옛 규칙을 되살려 같은
   엔진에서 잰 BEFORE는 두 tone 거리가 0.0 — 말 그대로 같은 색이었다(AFTER 11.3/21.2).
   ★믹스 강도 55%→80%→85%(family 단위 단일 값. tone별로 다르게 두지 않는다). 55%로는
   여섯 경우 중 넷이 SC 1.4.11의 3:1에 미달했다: 라이트 warning 2.19 / danger 2.59 /
   positive 2.18, 다크 danger 2.61. 이 테두리가 심각도를 나르는 유일한 신호라 여기서
   색은 장식이 아니라 정보다. 3:1을 처음 넘기는 값은 tone·테마별로 라이트 75/63/75%,
   다크 53/63/50%(warning/danger/positive)라 라이트 warning·positive가 family 전체를
   묶는 제약이다. 최저 통과값 75%는 3.01:1로 여유가 없어 토큰이 조금만 움직여도
   되돌아간다.

   80%(최저 3.27:1)에서 85%로 한 번 더 올린 근거는 «배경 대비»가 아니라 «중립 대비»다.
   타일이 톤을 가졌다는 걸 읽히려면 톤 없는 이웃 타일과 구별돼야 하는데, 그 거리가
   80%에서 다크 danger 2.70까지 내려간다. 85%면 배경 대비 최저 3.52:1, 중립 대비도
   라이트 3.02 / 다크 2.97로 두 축이 함께 ~3에 선다. 중립 대비는 1.4.11의 요구사항이
   «아니다»(인접색이 아니라 옆 타일이고, 색상차가 휘도비로 안 잡히는 몫을 메운다) —
   요구가 아니라 «이 테두리가 유일한 신호»라는 전제를 끝까지 민 결과다. 형제
   .doc-summary-notice가 같은 토큰을 믹스 없이 100%로 쓰므로 85%도 여전히 옅은 쪽이다.

   강도를 var()로 빼지 않은 건 이 시트에 color-mix 퍼센트를 var로 넣은 선례가 없어서다
   (검증 안 된 패턴을 새로 들이는 것보다 기존 형태 유지가 낫다). 중립 테두리
   (--cg-menu-border, 라이트 1.17:1 / 다크 1.53:1)는 일부러 그대로 둔다: 메뉴·팝오버까지
   쓰는 앱 전역 토큰이라 여기서 결정할 값이 아니고, 1.4.11이 겨냥하는 건 '상태'를
   나르는 tone 테두리이며, 무엇보다 중립을 올리면 위의 중립 대비 거리가 «줄어» 신호가
   죽는다. 별도 관측: 타일 배경 대 카드 배경은 라이트 1.10 / 다크 1.30이다.

   측정은 실브라우저 합성 픽셀 캔버스 되읽기. 하네스 body class에 chatgpt-reference-v1
   필수 — --cg-*는 :root가 아니라 이 클래스에 스코프되어, 빠뜨리면 전 토큰이 조용히 빈
   값이 되고(테두리가 rgb(13,13,13), 타일 배경이 투명으로 떨어진다) 측정이 통째로
   거짓이 된다. 가정이 아니라 클래스를 떼서 실제로 그렇게 되는 걸 확인했다. */
.doc-summary-fact[data-tone="warning"] {
  border-color: color-mix(in oklab, var(--cg-warning-fg) 85%, transparent);
}
.doc-summary-fact[data-tone="danger"] {
  border-color: color-mix(in oklab, var(--cg-danger-fg) 85%, transparent);
}
.doc-summary-fact[data-tone="positive"] {
  border-color: color-mix(in oklab, var(--cg-success) 85%, transparent);
}
.doc-summary-fact-label {
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
}
.doc-summary-fact-value {
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  overflow-wrap: anywhere;
}
.doc-summary-fact-unit {
  margin-left: 2px;
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  color: var(--cg-text-soft);
}
.doc-summary-chip {
  align-self: flex-start;
  margin-top: 2px;
  padding: 1px 6px;
  border-radius: var(--ds-radius-xs);
  background: var(--cg-surface);
  border: 1px solid var(--cg-menu-border);
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
}
.doc-summary-rows {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 0 0 10px;
  border-top: 1px solid var(--cg-menu-border);
}
.doc-summary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  padding: 7px 0;
  border-bottom: 1px solid var(--cg-menu-border);
}
.doc-summary-row-label {
  flex: 0 0 auto;
  min-width: 96px;
  margin: 0;
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
}
.doc-summary-row-value {
  flex: 1 1 60%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: var(--ds-text-caption-13);
  overflow-wrap: anywhere;
}
/* doc 234 W6 — 아티팩트 고위험 고지가 같은 레이아웃을 쓴다. 값을 복제하지 않고
   선택자만 얹는다: 성격이 같은 고지가 두 모양으로 보이면 사용자는 둘을 다른 것으로
   읽는다. 항목 색은 아래 .doc-summary-notice[data-tone] 규칙이 그대로 정한다. */
.doc-summary-notices,
.artifact-notices {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}
/* 문서요약은 본문 위, 아티팩트 고지는 표 뒤에 붙으므로 위쪽 간격이 필요하다. */
.artifact-notices {
  margin-top: 8px;
}

/* doc 234 v5 — 2줄 셀의 보조줄. 부속 열이 왼쪽 이웃 안으로 접혀 들어온 자리다.
   ★주값과 같은 무게로 보이면 접은 의미가 없다. 한 단계 작고 흐리게 두어 «이 값의
   속성»으로 읽히게 한다. 색은 기존 토큰만 쓴다(새 리터럴 없음 — raw-color 래칫). */
/* kpi.trend — 추세 요약 띠. 정렬 기준 캡션과 같은 자리(스크롤 영역 밖, 카드 안쪽 맨 위)에
   앉아 표 전체에 대한 한 줄 요약으로 읽힌다. */
/* ★접두사 필요 — `.md-table-tile-label` 주석 참조. 이 띠도 <p>다: 접두사 없이는 전역
   산문 규칙의 margin 10px가 이겨 표와의 간격이 6px가 아니게 된다. */
.message-body .md-table-wrap .md-table-trend {
  display: flex;
  align-items: center;
  gap: var(--ds-space-2);
  margin: 0 0 var(--ds-space-1);
  padding: 0 2px;
}
.md-table-trend svg {
  flex: none;
  overflow: visible;
}
/* ★선만 그린다. 면(area)으로 채우면 0 기준처럼 보이는데 이 선은 min~max 정규화라
   기준선이 0이 아니다 — 채우면 그림이 거짓말을 시작한다. */
.md-table-trend polyline {
  fill: none;
  /* ★데이터 마크는 «차트 계열색»을 쓴다. 원래 `var(--cg-focus-ring, var(--accent))` 였는데
     포커스 링은 테두리 장식용 토큰이라 대비 예산이 다르다 — 2026-08-07 라이브 실측에서
     이 선의 실효 대비가 흰 배경 대비 1.43:1 이었다(WCAG 2.2 SC 1.4.11 기준 3:1 미달).
     의도했던 `var(--accent)` 폴백은 `--cg-focus-ring` 이 정의돼 있어 한 번도 발화하지
     않았다 — 폴백이 죽은 토큰 선택을 가려 준 셈이다.
     ★같은 답변 안의 인라인 차트 선과 **같은 토큰**을 쓴다. 한 답변 안에서 추세를 말하는
     그림 둘이 다른 색 언어를 쓸 이유가 없다. */
  stroke: var(--ds-chart-slot-1);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.md-table-trend-caption {
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}
/* ★레일은 «한 번도 그려진 적이 없다» (2026-08-08 라이브 실측으로 확정).
   규칙이 `td` 로만 걸려 있었는데, 렌더러는 첫 열을 `<th scope="row">` 로 낸다(접근성
   결정). 레일이 붙는 시간 열은 대개 첫 열이므로 선택자가 **한 번도 매칭되지 않았다**.
   증거: 일정 표 5행 전부 `matchesTdSelector=false`·`matchesThVariant=true`,
   `padding-left` 가 규칙의 22px 이 아니라 12px, `::before`/`::after` 가 `content: none`.
   ★판정기는 통과하고 클래스도 붙어 있었다 — 「적용됐다」와 「그려졌다」는 다른 말이다. */
/* schedule.timeline — 시간 열의 레일. 점과 잇는 선으로 «순서»를 보여 준다.
   ★크기를 말하지 않는다. 이미 표에 적힌 날짜의 순서를 확인해 잇는 것뿐이라, 고위험
   도메인(마감·제출기한)에서도 그린다. */
.md-table th.md-table-timeline,
.md-table td.md-table-timeline {
  position: relative;
  padding-left: 22px;
  white-space: nowrap;
}
.md-table th.md-table-timeline::before,
.md-table td.md-table-timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--cg-menu-border, var(--line));
}
.md-table th.md-table-timeline.is-first::before,
.md-table td.md-table-timeline.is-first::before {
  top: 50%;
}
.md-table th.md-table-timeline.is-last::before,
.md-table td.md-table-timeline.is-last::before {
  bottom: 50%;
}
.md-table th.md-table-timeline::after,
.md-table td.md-table-timeline::after {
  content: "";
  position: absolute;
  left: 2px;
  top: 50%;
  width: 7px;
  height: 7px;
  margin-top: -3px;
  border-radius: var(--ds-radius-pill, 999px);
  /* ★폴백 원시값을 쓰지 않는다 — 드리프트 래칫이 잡았다(1050 → 1051). 점 안쪽은
     카드 표면색이어야 레일 선이 점을 관통하지 않는다. */
  background: var(--cg-surface);
  box-shadow: inset 0 0 0 1.5px var(--cg-focus-ring, var(--accent));
}
/* 수치 열의 데이터 바 (doc 234 v5). 셀 뒤에 값에 비례하는 띠를 깔아 숫자 열을 읽지 않고도
   대소가 보이게 한다. 막대는 이미 셀에 있는 숫자를 다시 그릴 뿐이라 새 주장을 얹지 않는다.
   ★scaleX로 늘린다 — width 애니메이션은 레이아웃을 다시 계산시키고, 여기선 정적이어도
   같은 이유로 합성 가능한 속성을 쓴다. 원점을 왼쪽에 두어야 0에서 자란다. */
/* v7 — 지표 타일. 규범이 「a handful of headline numbers」에 지정한 형태다(차트가 아니다).
   ★깊이: 카드는 그림자로 «뜨고» 이 띠는 inset으로 «눌린다». 두 층이 생기면 표가 세 번째
   층으로 자연히 뒤로 물러난다 — 카드 안이 한 층뿐이라 평평했던 것을 여기서 푼다. */
/* ── 등장 모션 (⑤, doc 234) ──
   ★목적이 있는 모션만 넣는다(조사: 「모든 애니메이션에 목적이 있어야 한다」).
   띠는 먼저 떠올라 «여기가 요약»이라는 읽기 순서를 세우고, 자는 오른쪽 기준점에서 자라며
   크기 부호화를 «재어 보이게» 한다. 장식이 아니라 위계와 인코딩을 말한다.
   ★★기본 상태는 «최종 상태»다. scaleX(0)·opacity 0을 기본으로 두면 reduced-motion
   사용자에게 막대가 통째로 사라진다 — 애니메이션은 항상 없어도 되는 것이어야 한다. */
@keyframes md-table-tiles-in {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ── 첫 열 고정 (v10-2) ──
   ★히트맵의 전제조건이다. 3열 이상 표는 가로 스크롤인데 행 식별자가 같이 밀려 사라지면
   색만 남고 이름이 없어진다 — 「이 진한 셀이 어느 행이었지」가 되어 히트맵이 아무 말도
   못 한다. 자(bar)는 값이 셀 안에 함께 있어 덜 치명적이었지만, 히트맵은 값과 이름이 갈린다.
   Mobbin 실측: Stake·Formula 1·theScore가 전부 이 방식이다 — 가로 스크롤 표의 관례다.
   ★배경은 «불투명»이어야 한다. 없거나 반투명이면 스크롤한 셀이 밑으로 비쳐 글자가 겹친다.
   ★z-index가 필요하다 — 히트맵 셀에도 배경이 있어 문서 순서로는 뒤에 깔린다. */
.md-table-scroll .md-table th:first-child,
.md-table-scroll .md-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 2;
  background: var(--cg-surface, var(--ds-color-surface));
  box-shadow: 1px 0 0 var(--cg-menu-border, var(--line)),
    6px 0 12px -8px color-mix(in srgb, var(--ds-black) 18%, transparent);
}
.md-table-scroll .md-table thead th:first-child {
  z-index: 3;
  /* ★v7 — 머리글 밴드를 이 모서리 칸까지 잇는다. 위 고정열 규칙이 `--cg-surface`(흰 면)를
     주는데, 머리글 행이 밴드가 된 뒤로는 이 한 칸만 흰색으로 남아 밴드가 끊겨 보인다.
     불투명 배경이어야 한다는 고정열의 전제는 그대로 지킨다(밴드도 불투명 토큰이다). */
  background: var(--cg-hover-soft);
}
/* ★고정 열은 자기 배경을 가지므로 행 hover 배경을 상속받지 못한다 —
   이 규칙이 없으면 마우스를 올렸을 때 첫 칸만 색이 안 바뀐다. */
@media (hover: hover) {
  .md-table-scroll .md-table tbody tr:hover th:first-child,
  .md-table-scroll .md-table tbody tr:hover td:first-child {
    background: var(--cg-hover-soft, var(--ds-color-surface-muted));
  }
}


/* 행 끝의 추이 열 (W2).
   ★Uniswap·Pinterest Trends가 쓰는 관용구다 — 숫자 넉 줄을 읽어야 알던 «올랐는가»를
   한 번에 보여준다. 표를 문서에서 위젯으로 바꾸는 가장 큰 한 걸음이다.
   ★선은 요약이지 대체가 아니다. 값은 셀에 그대로 남고, 계획이 없는 행은 빈 칸이다 —
   없는 추세를 그리느니 비워 둔다.
   ★색은 «추이» 종류 색을 쓴다. 히트맵 램프와 같은 계열이라 카드 안에서 따로 놀지 않는다. */
/* ★추이 열은 오른쪽에 고정한다 — 첫 열 고정의 **거울상**이다.
   2026-08-02 실측: 추이 열을 붙이자 표가 83px 넘쳤고 그 넘침이 정확히 추이 열을 잘라
   SVG 64px 중 15px만 남았다. 선의 77%가 화면 밖이었다. 계산값만 보면 정상이라
   확대 스크린샷이 아니었으면 놓쳤다.
   ★업계 표준이 이 경우를 다룬다 — 「맨 왼쪽 열을 고정하고, 때로는 합계 같은 **요약을
   담는 맨 오른쪽 열도** 고정한다」(Pencil & Paper). 추이 열이 그 «요약»이다.
   ★그림자는 방향만 뒤집는다. 같은 방향이면 표 밖으로 나가 층으로 안 읽힌다. */
.md-table-sparkline-head,
.md-table-sparkline-cell {
  position: sticky;
  right: 0;
  z-index: 2;
  background: var(--cg-surface, var(--ds-color-surface));
  box-shadow: -1px 0 0 var(--cg-menu-border, var(--line)),
    -6px 0 12px -8px color-mix(in srgb, var(--ds-black) 18%, transparent);
}
.md-table-sparkline-head {
  /* 머리글은 다른 열과 같은 규칙을 따른다 — 여기서만 다르면 줄이 어긋나 보인다. */
  text-align: center;
  /* ★교차 지점에서 본문 위에 선다. 첫 열 머리글이 3인 것과 같은 이유다. */
  z-index: 3;
}
.md-table-sparkline-cell {
  width: 1%; /* 내용만큼만 — 데이터 열의 폭을 뺏지 않는다 */
  text-align: center;
  vertical-align: middle;
}
/* ★고정 열은 자기 배경을 가지므로 행 hover 배경을 상속받지 못한다 — 첫 열과 같은 처리.
   토큰도 첫 열이 쓰는 것을 그대로 쓴다. 다르면 두 고정 열의 hover 색이 갈린다. */
@media (hover: hover) {
  .md-table tbody tr:hover .md-table-sparkline-cell {
    background: var(--cg-hover-soft, var(--ds-color-surface-muted));
  }
}
.md-table-sparkline {
  display: block;
  width: 64px;
  height: 16px;
  margin: 0 auto;
  overflow: visible;
}
.md-table-sparkline-line {
  fill: none;
  stroke: var(--ds-kind-trend-mark, currentColor);
  stroke-width: 1.5;
  /* 꺾이는 지점이 뾰족하면 작은 크기에서 점처럼 튄다. */
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

@media (prefers-reduced-motion: no-preference) {
  /* 선이 왼쪽에서 자라난다 — 시간 방향과 같아 «읽는 방향»을 강화한다.
     ★`stroke-dashoffset`은 컴포지터에 남지 않지만 요소가 64×16으로 작고 행당 하나뿐이라
     비용이 무시할 수준이다. 레이아웃은 건드리지 않는다.
     ★`--ds-motion-default`는 **지속시간+이징을 함께** 담는다(`220ms cubic-bezier(...)`).
     뒤에 이징을 또 붙이면 단축 속성이 무효가 된다 — 실제로 그렇게 썼다가 애니메이션이
     통째로 드롭됐다. */
  .md-table-sparkline-line {
    animation: md-table-sparkline-draw var(--ds-motion-default) forwards;
  }
}

/* ★대시는 키프레임 «안»에만 둔다. 기본 규칙에 두면 애니메이션이 어떤 이유로든 안 돌 때
   `stroke-dashoffset`만 남아 **선이 통째로 사라진다** — 2026-08-02 실화면에서 정확히 그
   상태였다(선 길이 61에 오프셋 120). 모션은 실패해도 콘텐츠는 보여야 한다. */
@keyframes md-table-sparkline-draw {
  from {
    stroke-dasharray: 120;
    stroke-dashoffset: 120;
  }
  to {
    stroke-dasharray: 120;
    stroke-dashoffset: 0;
  }
}


/* 히트맵 범례 (W1-3).
   ★조사한 히트맵 화면은 예외 없이 범례를 갖고 있었는데(Klaviyo·Vanta·Gorgias) 우리만
   없었다. 5단계로 칠하면서 무엇이 높고 낮은지 안 말하면 색각 이상 사용자에게는 아무
   정보도 아니다.
   ★더 중요한 것은 «축»이다. 같은 색이 어떤 표에서는 이 행 안에서 크고 다른 표에서는
   이 열 안에서 크다 — 안 알려주면 표 전체에서 큰 값으로 오독된다.
   ★견본 색은 셀 규칙에 **선택자를 덧붙여** 선언을 공유한다. 따로 쓰면 팔레트를 바꿀 때
   한쪽만 바뀌어 범례가 다른 표를 설명하게 된다. */

@media (max-width: 520px) {

}

/* ── 종류 chip (④, doc 234 v9) ──
   ★색은 «종류»를 말하고 «평가»를 말하지 않는다. 빨강·초록은 이 제품에서 이미
   danger/success를 뜻해 범주형 팔레트에서 영구 배제했다(--ds-kind-* 생성기 참조).
   ★이 트랙은 색각이상 «분리도»를 일부러 포기하고 대비 균일성을 샀다 — 카드당 종류가
   하나만 뜨고 chip에 늘 글자가 함께 가므로 색이 안 보여도 잃는 정보가 0이다.
   그래서 chip은 절대 아이콘·점만으로 서지 않는다(애플 HIG: 색에만 의존하지 말라). */
.md-table-kind-chip {
  /* ★v7-1 — `flex-start` → `center`. 옛 툴바는 `align-items: flex-start` 에 제목이
     두 줄(이름 + "N열 × M행")이라 칩이 첫 줄에 맞으려면 위로 붙어야 했다. v7에서 부제가
     sr-only 가 되며 툴바를 `center` 로 바꿨는데 이 칩만 따라오지 않아, 실측 결과 칩
     중심이 제목 중심보다 **9.8px 위**에 떠 있었다. 툴바가 가로 정렬을 소유하므로
     여기서는 교차축을 거스르지 않는다. */
  /* ★v11 — 채움을 뺐다. 툴바 한 줄에서 색이 채워진 유일한 요소가 «누를 수 없는» 이 칩이고
     정작 선택된 세그먼트는 흰색이라, 사용자가 「추이가 선택됨」으로 읽었다(실측). 색은
     여전히 «종류»를 말하지만 글자 위에서 말한다 — 이 파일의 원래 계약대로 라벨이 정보를
     온전히 지므로, 채움을 빼도 잃는 정보는 0이다.
     ★`margin-left: auto` 도 뺐다. 이제 제목 무리 안이라 밀어낼 것이 없다. */
  flex: none;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--ds-weight-semibold);
  white-space: nowrap;
}
.md-table-kind-chip[data-kind="compare"] {
  color: var(--ds-kind-compare-ink);
}
.md-table-kind-chip[data-kind="trend"] {
  color: var(--ds-kind-trend-ink);
}
.md-table-kind-chip[data-kind="schedule"] {
  color: var(--ds-kind-schedule-ink);
}
.md-table-kind-chip[data-kind="rank"] {
  color: var(--ds-kind-rank-ink);
}
/* ── 근거 표기 (④) ──
   ★색을 주지 않는다. 「문서 근거」에 색을 얹으면 「모델 지식보다 낫다」는 평가가 되고,
   그건 색이 하면 안 되는 일이다. 구분은 글자가 한다.
   ★<p>라서 접두사가 필요하다 — 없으면 전역 산문 규칙(0,2,1)에 져서 본문 크기로 렌더된다. */
.message-body .md-table-wrap .md-table-provenance {
  margin: var(--ds-space-3) 0 0;
  padding-top: var(--ds-space-3);
  border-top: 1px solid var(--cg-menu-border, var(--line));
  font-size: var(--ds-text-caption-12);
  color: var(--cg-muted);
}
/* ── v7-1 아트디렉션 정합 (2026-08-07, 사용자 지적) ──
   ★지적: 「사각형인데 비해 상단의 요약 표는 둥근 사각형」·「간격/여백 아트디렉션도 안 맞는다」.
   실측으로 확인된 어긋남 둘:
     ① 모서리 — 타일 14px vs 표 프레임 0px. 같은 색(#f4f4f4) 밴드가 나란히 있는데
        모서리 언어만 달라 «둘이 다른 것»으로 읽힌다.
     ② 들여쓰기 — 표 계열은 제목·머리글·행이름이 **모두 산문 대비 12px** 로 통일돼
        있는데 타일만 16px 이라 혼자 4px 더 들어가 왼쪽 정렬선이 깨졌다.
   ★이 값들은 카드 시절의 유물이다. 14px 은 카드의 22px 아래 «중첩된» 반경이었고,
   16px 여백은 카드의 24px 여백 안에서 잡은 리듬이었다. 카드가 사라졌으므로 기준을
   표 계열로 옮긴다 — 새 언어를 만들지 않고 이미 있는 리듬에 합류시킨다.
   ★inset 그림자도 뺀다. 「카드는 그림자로 뜨고 이 띠는 inset 으로 눌린다」는 2층 모델의
   아래층인데, 위층(카드 리프트)이 없어져 혼자서는 아무 것도 말하지 않는다. */
/* ★타일 셋은 «각각의 상자»가 아니라 **하나의 격자**다 (2026-08-08).
   flex 였을 때는 라벨이 2줄이 되면 그 타일의 값·부제만 내려가 기준선이 깨졌다 —
   실측 375px·430px 에서 **20px 어긋남**(라벨 높이 20/20/40). 셋 중 하나만 어긋나 눈에 띈다.
   ★라벨 길이는 우리가 못 정한다. 「2025-Q1 대비 2025-Q4」는 **표에서 읽어 온 이름**이라
   줄바꿈을 없앨 수 없다 — 자르면 무엇 대비 무엇인지가 사라진다. 그래서 줄바꿈을 허용한
   채로 기준선을 지킨다: 행을 여기서 정의하고 타일이 `subgrid` 로 **상속**한다.
   ★행이 짧을 땐 아무 대가도 없다. 라벨이 한 줄인 표에서 띠 높이는 그대로다(실측 89px),
   실제로 2줄이 될 때만 109px 로 커진다 — `min-height` 로 늘 2줄을 예약하지 않는 이유다. */
.md-table-tiles {
  display: grid;
  grid-auto-flow: column;
  /* ★`1fr` 만으로는 부족하다 — 자동 최소 크기가 내용 폭이라 긴 값이 자기 열을 넓혀
     타일 폭이 갈린다. 종전 flex 의 `flex: 1 1 0` + `min-width: 0` 이 하던 일이다. */
  grid-auto-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto;
  margin: 0 0 var(--ds-space-3);
  animation: md-table-tiles-in var(--ds-motion-default) both;
  overflow: hidden;
  background: var(--cg-hover-soft, var(--surface-2));
}

/* ★전정기관 민감성. 조사: reduced-motion은 킬 스위치가 아니라 «장식은 빼고 기능은 남긴다».
   여기서는 최종 상태가 곧 기능이므로 애니메이션만 제거하면 끝이다 — 기본 상태가 이미
   최종 상태라서(opacity 0을 기본으로 두지 않았다) 띠는 그대로 보인다.
   ★2026-08-08 — 이 블록은 자(bar)와 띠를 함께 다뤘고, A안에서 자 규칙을 걷어낼 때
   블록이 통째로 사라졌다(게이트가 잡았다). 남은 소비자 하나로 다시 세운다. */
@media (prefers-reduced-motion: reduce) {
  .md-table-tiles {
    animation: none;
  }
}

.md-table-tile {
  position: relative;
  /* ★띠의 행을 **상속**한다 — 자기 행을 만들지 않는다. 그래야 라벨이 2줄이 될 때 세
     타일의 라벨 행이 «함께» 2줄이 되고 값은 같은 줄에 남는다(위 `.md-table-tiles` 주석).
     ★`span 3` 과 짝이다. 하나만 있으면 아무 일도 안 한다 — `subgrid` 만 있으면 한 행만
     상속해 값·부제가 한 칸에 뭉치고, `span` 만 있으면 자기 행을 만들어 형제와 어긋난다.
     ★상자를 `display: contents` 로 녹이지 않는다 — `position: relative` 와 아래
     `::before` 구분선, 패딩이 이 상자에 걸려 있다. */
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  min-width: 0;
  /* 좌우 12px = 표 셀·제목과 같은 들여쓰기. 세로는 라벨+값 두 줄이라 셀(8px)보다 넉넉히. */
  padding: var(--ds-space-3);
}

/* ★타일 값이 잘렸다(실기기 iPhone 402pt: 「139,822」가 「139,…」). 타일은 폭을 균등하게
   나눠 가지는데 값은 nowrap+ellipsis라, 안쪽 폭이 모자라면 헤드라인 숫자가 잘린다 —
   잘린 숫자는 안 보여 주는 것만 못하다. 「33,03…」은 33,033.3 이 아니라 **틀린 수**다.
   실측: 22px에서 「139,822」는 80.5px. 안쪽 폭이 패딩 16일 때 75.3pt로 모자라고
   패딩 8이면 91.3pt로 들어간다.
   ★★2026-08-08 — 「글자를 줄이는 대신 패딩을 줄여 헤드라인 크기를 지킨다」던 종전 결정을
   **실측이 뒤집었다.** 패딩만으로는 모자란다(폭별 최소 여유 · 넘치는 값 개수):

       값 크기   320          360         375          430      520
       22px     -19.3 (10)   -6.3 (4)    -1.3 (1)     +16.7    +46.7
       18px      +0.7 (0)   +13.7 (0)   +18.7 (0)     +36.7    +66.7

   22px는 **375px 폰에서도** 넘친다(안전해지는 것은 ~390px부터). 범인은 원 단위 열의
   평균(「33,033.3원」, 9자)으로, 요금제·단가 표에서 늘 나오는 모양이다. 헤드라인 크기를
   지키려다 헤드라인 «숫자»를 틀리게 만드는 것은 거래가 안 된다 — 한 단계 내린다.
   여전히 만능은 아니다: 320px에서 여유가 0.7px라 더 긴 값은 잘린다.
   ★★이 블록은 기본 규칙 «뒤»에 있어야 한다. @media는 특이도를 올리지 않으므로 앞에 두면
   뒤의 기본 규칙이 이겨 override가 통째로 무효가 된다 — 실제로 그렇게 배포했다가
   시뮬레이터에서 잘림이 그대로인 것을 보고 잡았다(reduced-motion에서도 같은 실수를 했다). */
@media (max-width: 520px) {
  .md-table-tile {
    padding: var(--ds-space-2);
  }
}
/* 타일 사이는 선으로 가른다 — 박스를 각각 그리면 카드 안에 카드가 겹친다. */
.md-table-tile + .md-table-tile::before {
  content: "";
  position: absolute;
  left: 0;
  top: 14px;
  bottom: 14px;
  width: 1px;
  background: var(--cg-menu-border, var(--line));
}
/* ★★접두사 `.message-body .md-table-wrap`이 «장식»이 아니다 — 카드가 만드는 <p>는 접두사를
   벗기는 순간 전역 산문 규칙에 진다. 실측으로 물렸다: 라벨이 12px/600/muted 대신
   **16px/400/ink**로 렌더돼 자기 값과 같은 크기·같은 검정이 됐고, 지표 띠의 위계가
   통째로 사라졌다. 토큰은 멀쩡했다 — 진 것은 캐스케이드다.
     .message-body p                            (0,1,1)  margin 10px
     .premium-product-shell-v1 .message-body p  (0,2,1)  font-size 15
     .chatgpt-reference-v1 .message-body p      (0,2,1)  color → ink
     .chatgpt-reference-v1 .message-body p      (0,2,1)  font-size 16 · weight 400
   컴포넌트 클래스 하나(0,1,0)로는 넷 다 진다. 클래스 셋(0,3,0)이면 파일 순서와 무관하게
   이기고, 셸 클래스를 안 쓰므로 어느 셸에서도 같다. !important로 덮지 않는다 —
   다른 표면의 전역 산문 규칙까지 같이 망가진다.
   ★이 접두사를 «간결하게» 벗기지 말 것. `test_table_card_prose_specificity.py`가 막는다. */
.message-body .md-table-wrap .md-table-tile-label {
  margin: 0 0 var(--ds-space-1);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  color: var(--cg-muted);
}
.md-table-tile-value {
  /* ★규범: 큰 독립 숫자는 비례 숫자. tabular은 121을 헐렁하게 만들고, 세로로 정렬할
     이유도 없다 — 그건 표 열에서만 필요하다. */
  font-size: var(--ds-text-title-22);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-variant-numeric: proportional-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* ★폰에서 한 단계 내린다 — 사유와 실측표는 위 `@media (max-width: 520px)` 패딩 블록 주석에.
   ★★이 블록은 기본 규칙 «바로 뒤»에 있어야 한다. @media 는 특이도를 올리지 않으므로
   패딩 블록(위쪽)에 함께 넣으면 뒤따르는 기본 규칙 `font-size: …title-22` 가 이겨
   **선언이 통째로 죽는다.** 실제로 그렇게 짰다가 검사에 잡혔다 — 같은 파일이 같은 함정을
   두 번 기록하고 있는데도 그랬다. 중단점 값은 패딩 블록과 **같은 520px** 이다. */
@media (max-width: 520px) {
  .md-table-tile-value {
    font-size: var(--ds-text-title-18);
  }
}
/* ★접두사 필요 — 위 `.md-table-tile-label` 주석 참조. */
.message-body .md-table-wrap .md-table-tile-sub {
  margin: var(--ds-space-1) 0 0;
  font-size: var(--ds-text-caption-12);
  color: var(--cg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}.md-table-cell-secondary {
  display: block;
  margin-top: 2px;
  color: var(--cg-text-soft);
  font-size: var(--ds-text-caption-12);
  line-height: 1.45;
}

/* A안 «안전 프레임» (2026-07-30 승인). 고지가 표 카드 **안**으로 들어오면 카드 밖에
   있을 때 필요했던 바깥 여백이 오히려 카드를 벌린다. 카드 내부에서는 안쪽 여백을
   쓰고, 위험도 엣지가 카드 전체 높이를 관통해 표와 고지를 한 덩어리로 묶는다 —
   배포 화면에서 표·고지·모델 꼬리문단이 세 개의 남남으로 읽힌 것이 이 안의 출발점이다.
   색은 이미 있는 시맨틱 토큰을 그대로 쓴다(새 색 리터럴 없음). */
.md-table-wrap > .artifact-notices {
  margin: 0;
  padding: var(--ds-space-2) var(--ds-space-3);
}
/* ★v10 — 헤어라인도 중립색이다. v7-1 에서 여기에 등급색을 물렸는데, 나머지 표면이
   전부 채도 0% 인 잉크라 채도 90% 짜리 선 하나가 «마크다운이 아닌 무언가»로 튀었다
   (사용자 지적). 등급은 아래 텍스트 라벨이 진다. */
.md-table-wrap > .artifact-notices:first-child {
  border-bottom: 1px solid var(--cg-menu-border);
}
.md-table-wrap > .artifact-notices:last-child {
  border-top: 1px solid var(--cg-menu-border);
}
/* ── v7-1 (2026-08-07) — 관통 엣지를 걷어낸다 ──
   ★이 엣지는 «카드»를 전제로 만들어졌다: 카드 전체 높이를 관통해 표와 고지를 한
   덩어리로 묶고, 카드의 반경 22px을 좌측만 0으로 취소했다. v7에서 카드를 걷어내자
   그 전제가 통째로 깨졌고, 배포 화면에서 두 가지가 실측됐다.
     ① 제목의 액센트 바(4px)와 이 엣지(3px)가 **간격 0으로 맞붙었다.** 공교롭게도
        바로 아래 주석이 경고하는 «이중 신호»와 같은 결함이다 — 그때는 카드 엣지와
        고지 레일이었고, 이번엔 카드 엣지와 제목 바다.
     ② 래퍼의 3px 테두리가 표를 산문보다 3px 안쪽으로 밀어, 인라인 정렬이 이 경우에만
        어긋났다. 카드 시절엔 24px 여백에 묻혀 보이지 않던 값이다.
   ★엣지를 지워도 등급 신호는 잃지 않는다 — 아래 밴드 tint가 이미 tone별로 갈린다
   (그 자체가 «레일을 빼고 배경으로 옮긴» 앞선 결정의 결과다). 여기서는 남은 중복
   채널 하나를 마저 걷어내고, tone 은 밴드 헤어라인으로 물려준다.
   ★선택자는 살려 둔다. 계약이 존재를 핀할 뿐 아니라, tone → 색 대응이 사라지면
   밴드 경계가 등급을 잃는다. */
/* ── v10 (2026-08-07) — 등급을 «색»에서 «말»로 옮긴다 ──
   ★사용자 지적: 「빨간색 마크다운 방식이 좀 안 어울린다」. 실측하니 답변 표면이 전부
   채도 0% 인데(머리글 밴드 0%·제목 액센트 바 0%) 고지만 헤어라인 채도 90.5%·밴드 70.7%
   였고, 밴드 면적이 표 본체의 41% 였다. 잉크 규율(doc 345)과 정면으로 부딪힌다.
   ★색을 빼도 등급을 잃지 않는다 — 오히려 접근성이 는다. doc 231 A5 는 «필수 역할을
   color 채널에만 배정 금지»(SC 1.4.1)를 요구하는데, 지금까지 danger/warning 을 가르는
   가시 채널은 색뿐이었다(위치는 있었지만 색이 주였다). 등급을 **글자**로 옮기면 색각·
   흑백 인쇄·저대비 환경에서도 살아남는다.
   ★래퍼의 `[data-risk-tone]` 은 색을 안 쓰게 되어 CSS 로는 할 일이 없다. 속성 자체는
   JS 가 계속 세운다(고지 마운트 표식) — 죽은 선언을 남기지 않고 규칙만 걷어낸다. */
/* ★실브라우저에서 발견: 카드 엣지와 고지 항목의 좌측 레일이 같은 색으로 나란히
   그려졌다(측정: 카드 x=856, 고지 x=904, 둘 다 rgb(186,38,35)). 「한 덩어리로 묶는다」고
   만든 엣지가 신호를 이중으로 만든 것이다 — 소스로는 안 보이고 픽셀을 재야 나온다.
   카드 안에서는 레일을 빼되, 지금 두 밴드의 배경이 **같은 회색**이라 레일이 tone을
   구분하는 유일한 채널이므로 등급을 배경으로 옮긴다. 카드 밖(표 없는 답변)의 고지는
   기존 레일을 그대로 쓴다 — 거기엔 카드 엣지가 없다. */
/* 반경은 일부러 재선언하지 않는다 — 배경이 투명하고 레일이 없으면 칠할 것이 없어
   시각적으로 무의미한데, 원시 border-radius 값은 반드시 anti-drift 래칫에 잡힌다
   (206 → 207로 RED가 났다). 안 쓰는 선언으로 천장을 깎지 않는다. */
.md-table-wrap > .artifact-notices .doc-summary-notice {
  border-left: 0;
  background: transparent;
}
/* ★밴드는 등급과 무관하게 중립 회색이다 — 머리글 밴드와 같은 톤이라 답변 안에서
   «같은 언어의 형제»로 읽힌다. 등급은 아래 라벨이 진다. */
.md-table-wrap > .artifact-notices {
  background: var(--cg-hover-soft);
}
/* ── 등급 라벨 (v10) ──
   ★색 대신 말. 「중요」(danger) · 「주의」(warning) · 「참고」(info).
   ★CSS `content` 로 넣는 이유: 이 문구는 정책이 정한 «고지 본문»이 아니라 UI 라벨이다.
   본문에 섞으면 복사·내보내기한 원문이 오염되고, 정책 YAML 이 문구의 유일한 출처라는
   계약(«모델도 렌더러도 고지를 짓지 않는다»)이 흐려진다. */
/* ★v10-1 — 카드 «밖» 고지도 같이 중립화한다.
   실브라우저 검수에서 잡았다: 표가 없는 답변은 고지가 `.md-table-wrap` 밖에 붙어
   v10 의 중립화가 안 닿았고, **채도 90.5% 짜리 주황 레일이 그대로** 남아 있었다
   (사용자가 지적한 바로 그 색). 등급을 «말»로 옮긴 이상 레일도 중립이어야 한다.
   ★`.doc-summary-notice` 기본 규칙은 손대지 않는다 — 그 클래스는 문서요약 위젯도 쓰고,
   거기서는 등급 레일이 여전히 유효한 신호다. 위험 고지 컨테이너(`.artifact-notices`)
   안에서만 덮는다. */
/* ★★특이도를 한 칸 올린다 — `[data-tone]` 을 붙여 (0,2,0) → (0,3,0).
   실브라우저에서 잡았다: (0,2,0) 으로 썼더니 라벨은 나오는데 **레일만 주황 그대로**였다.
   기존 `.doc-summary-notice[data-tone="warning"]`(클래스1+속성1 = 0,2,0)와 동률인데
   그쪽이 파일 뒤에 있어 이긴다. 동률은 «나중 선언»이 가져간다. */
.artifact-notices .doc-summary-notice[data-tone] {
  border-left-color: var(--cg-menu-border);
}
.artifact-notices .doc-summary-notice::before {
  margin-right: var(--ds-space-1);
  color: var(--cg-text);
  font-weight: var(--ds-weight-semibold);
}
.artifact-notices .doc-summary-notice[data-tone="danger"]::before {
  content: "중요";
}
.artifact-notices .doc-summary-notice[data-tone="warning"]::before {
  content: "주의";
}
.artifact-notices .doc-summary-notice[data-tone="info"]::before {
  content: "참고";}
.doc-summary-notice {
  margin: 0;
  padding: 8px 10px;
  border-radius: var(--ds-radius-xs);
  border-left: 3px solid var(--cg-menu-border);
  background: var(--cg-hover-soft);
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text);
}
/* ★위험 수준을 개인 설정으로 렌더하지 않는다. 여기가 --accent였던 탓에 파란 accent를
   고른 사용자에게는 «투자 자문이 아닙니다»가 파란 막대로 나왔다 — 실브라우저 실측에서
   발견. 기본 accent가 우연히 먹빛이라 눈에 띄지 않았을 뿐이다. */
.doc-summary-notice[data-tone="warning"] {
  border-left-color: var(--cg-warning-fg);
}
.doc-summary-notice[data-tone="danger"] {
  border-left-color: var(--cg-danger-fg);
}
.doc-summary-evidence {
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft);
}
.doc-summary-evidence summary {
  cursor: pointer;
  padding: 4px 0;
  color: var(--cg-text-soft);
}
.doc-summary-evidence ul {
  margin: 4px 0 0;
  padding-left: 18px;
}
.doc-summary-evidence li {
  margin: 2px 0;
  overflow-wrap: anywhere;
}
@container (max-width: 520px) {
  .doc-summary-facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- Visual answer card v1 --------------------------------------------------------------
   Generic web answers with 1–5 entity-approved HTTPS source images stay text-first:
   answer/price table → source controls → optional media. Zero images use the plain answer path
   and reserve no height. Compact reflow is owned by the card container. */
.visual-answer-card {
  container-name: visual-answer;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  inline-size: 100%;
  max-inline-size: 100%;
  min-width: 0;
  margin-top: var(--wds-space-1);
  overflow: hidden;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  box-shadow: var(--wizon-ai-popover-shadow);
}

.visual-answer-mosaic {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  min-width: 0;
  max-width: 100%;
  gap: var(--wds-space-1);
  padding: var(--wds-space-1);
  background: var(--wizon-ai-surface);
}

.visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="1"] > .visual-answer-mosaic {
  grid-template-columns: minmax(0, 1fr);
}

.visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="2"] > .visual-answer-mosaic {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="3"] > .visual-answer-mosaic {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="4"] > .visual-answer-mosaic {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="5"] > .visual-answer-mosaic {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.visual-answer-item {
  display: grid;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
}

.visual-answer-media {
  position: relative;
  min-width: 0;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  color: inherit;
  font: inherit;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}

.visual-answer-media:first-child:nth-last-child(3) {
  grid-row: span 2;
}

.visual-answer-item .visual-answer-media {
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 0;
}

.visual-answer-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--wizon-ai-motion-surface-duration) var(--wizon-ai-motion-effect-ease);
}

.visual-answer-media:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: -2px;
}

.visual-answer-caption {
  min-width: 0;
  padding: var(--wds-space-2) var(--wds-space-3);
  border-top: 1px solid var(--wizon-ai-popover-border);
  font-size: var(--ds-text-caption-12);
  line-height: 1.4;
}

.visual-answer-source-link {
  display: block;
  overflow: hidden;
  color: var(--wizon-ai-text-secondary);
  text-decoration: none;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.visual-answer-source-link:hover,
.visual-answer-source-link:focus-visible {
  color: var(--wizon-ai-text-primary);
  text-decoration: underline;
}

@media (hover: hover) {
  .visual-answer-media:hover img {
    transform: scale(1.035);
  }
}

.visual-answer-content {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-width: 100%;
  gap: var(--wds-space-3);
  padding: var(--wds-space-5) var(--wds-space-5) var(--wds-space-4);
}

.visual-answer-content > :first-child {
  margin-top: 0;
}

.visual-answer-content > :last-child {
  margin-bottom: 0;
}

.visual-answer-content .list-line,
.visual-answer-content .answer-table-line {
  margin: 0;
  padding-block: var(--wds-space-2);
  border-top: 1px solid var(--wizon-ai-popover-border);
  line-height: 1.65;
}

.visual-answer-content h3,
.visual-answer-content h4,
.visual-answer-content h5 {
  margin: var(--wds-space-3) 0 0;
  text-wrap: pretty;
}

.visual-answer-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  min-width: 0;
  max-width: 100%;
  gap: var(--wds-space-2);
  padding: var(--wds-space-3) var(--wds-space-5) var(--wds-space-4);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.visual-answer-foot .source-pill-row,
.visual-answer-foot .trust-chips {
  margin-top: 0;
}

.visual-answer-content .md-table-wrap {
  max-width: 100%;
}

/* Broken fenced output stays readable as escaped source instead of becoming a partial code card.
   Korean keeps word boundaries where possible; an unbroken URL/token may still wrap before it can
   widen a 390px page. */
.md-plain-fallback {
  max-width: 100%;
  word-break: keep-all;
  overflow-wrap: anywhere;
}

/* A zero-count payload never enters the card. If remote loading later leaves zero tiles,
   remove the shell and keep the same Markdown/source controls as the standard answer path. */
.visual-answer-card.is-image-fallback {
  overflow: visible;
  border: 0;
  background: transparent;
  box-shadow: none;
}

.visual-answer-card.is-image-fallback .visual-answer-mosaic {
  display: none;
}

.visual-answer-card.is-image-fallback .visual-answer-content,
.visual-answer-card.is-image-fallback .visual-answer-foot {
  padding-inline: 0;
}

.visual-answer-card.is-image-fallback .visual-answer-content {
  padding-top: 0;
}

.visual-answer-card.is-image-fallback .visual-answer-foot {
  border-top: 0;
}

@container visual-answer (max-width: 520px) {
  .visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="4"] > .visual-answer-mosaic,
  .visual-answer-card:not(.travel-itinerary-card)[data-visual-image-count="5"] > .visual-answer-mosaic {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .visual-answer-content {
    padding: var(--wds-space-4);
  }

  .visual-answer-foot {
    padding: var(--wds-space-3) var(--wds-space-4) var(--wds-space-4);
  }
}

/* ---- Travel itinerary widget v2 -------------------------------------------------------
   The travel card stays inside the visual-answer shell, but adds evidence-aware day tabs,
   synchronized stops and a coordinate-backed route overview. All colors, spacing and motion
   come from the existing WIZON/WDS contract; unavailable map data degrades to a route list. */
.travel-itinerary-lede {
  margin: 0 0 var(--wds-space-3);
  line-height: 1.65;
  text-wrap: pretty;
}

.travel-itinerary-card {
  container-name: travel-itinerary;
}

.travel-itinerary-hero {
  grid-auto-rows: clamp(144px, 22vw, 180px);
  min-height: 0;
  background: var(--wizon-ai-surface);
}

.travel-itinerary-hero:has(.travel-itinerary-hero-media:only-child) {
  grid-template-columns: minmax(0, 1fr);
}

.travel-itinerary-hero-media {
  border-radius: calc(var(--wizon-ai-radius-control) - var(--wds-space-1));
}

.travel-itinerary-body {
  gap: var(--wds-space-3);
  padding-top: var(--wds-space-4);
}

.travel-itinerary-heading {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-itinerary-heading > span {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: var(--wds-space-1);
}

.travel-itinerary-heading h3 {
  margin: 0;
  font-size: var(--wds-font-size-title-l);
  line-height: calc(var(--wds-font-size-title-l) * 1.35);
}

.travel-itinerary-heading.has-long-days {
  align-items: stretch;
  flex-direction: column;
}

.travel-itinerary-evidence {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.travel-itinerary-day-nav,
.travel-itinerary-tabs {
  display: flex;
  align-items: center;
  min-width: 0;
}

.travel-itinerary-day-nav {
  flex: 0 1 auto;
  gap: var(--wds-space-2);
}

.travel-itinerary-day-nav.is-long {
  width: 100%;
}

.travel-itinerary-tabs {
  flex: 1 1 auto;
  gap: var(--wds-space-1);
  max-width: 100%;
  padding: var(--wds-space-1);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-canvas);
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline proximity;
  scrollbar-width: none;
}

.travel-itinerary-tabs::-webkit-scrollbar {
  display: none;
}

.travel-itinerary-tabs button {
  flex: 0 0 auto;
  min-width: 52px;
  min-height: 44px;
  padding: 0 var(--wds-space-3);
  border: 0;
  border-radius: var(--wizon-ai-radius-pill);
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  cursor: pointer;
  scroll-snap-align: center;
}

.travel-itinerary-tabs button[aria-selected="true"] {
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  box-shadow: var(--wizon-ai-popover-shadow);
}

.travel-itinerary-day-step {
  display: grid;
  flex: 0 0 44px;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  cursor: pointer;
}

.travel-itinerary-day-step:disabled {
  color: var(--wizon-ai-text-muted);
  cursor: default;
  opacity: 0.45;
}

.travel-itinerary-day-step svg {
  width: 18px;
  height: 18px;
}

.travel-itinerary-day-position {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: baseline;
  gap: var(--wds-space-1);
  min-width: 54px;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.travel-itinerary-day-position strong {
  color: var(--wizon-ai-text-primary);
}

.travel-itinerary-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(220px, 0.92fr);
  align-items: stretch;
  gap: var(--wds-space-4);
}

.travel-itinerary-days {
  min-width: 0;
}

.travel-itinerary-day ol {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-itinerary-stop {
  position: relative;
  display: grid;
  grid-template-columns: var(--wds-space-3) minmax(48px, auto) minmax(0, 1fr);
  column-gap: var(--wds-space-2);
  min-width: 0;
  font-size: var(--wds-font-size-caption);
  line-height: 1.4;
}

.travel-itinerary-stop:not(:last-child)::after {
  content: "";
  position: absolute;
  top: var(--wds-space-3);
  bottom: calc(var(--wds-space-1) * -1);
  left: calc(var(--wds-space-3) / 2 - 0.5px);
  width: 1px;
  background: var(--wizon-ai-popover-border);
}

.travel-itinerary-stop-marker {
  position: relative;
  width: var(--wds-space-2);
  height: var(--wds-space-2);
  margin: calc(var(--wds-space-1) + 1px) auto 0;
  border: 1px solid var(--wizon-ai-text-secondary);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
}

.travel-itinerary-stop.is-selected .travel-itinerary-stop-marker {
  border-color: var(--wizon-ai-text-primary);
  background: var(--wizon-ai-text-primary);
}

.travel-itinerary-stop-time {
  color: var(--wizon-ai-text-secondary);
  font-variant-numeric: tabular-nums;
}

.travel-itinerary-stop-copy,
.travel-itinerary-stop-head {
  display: flex;
  min-width: 0;
}

.travel-itinerary-stop-copy {
  width: 100%;
  min-height: 44px;
  padding: var(--wds-space-2) var(--wds-space-3);
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
}

.travel-itinerary-stop-control {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 0;
  min-height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  gap: var(--wds-space-1);
  cursor: pointer;
}

.travel-itinerary-stop.is-selected .travel-itinerary-stop-copy {
  background: var(--wizon-ai-canvas);
}

.travel-itinerary-stop.is-featured .travel-itinerary-stop-copy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(108px, 132px);
  column-gap: var(--wds-space-3);
}

.travel-itinerary-stop.is-featured .travel-itinerary-stop-head,
.travel-itinerary-stop.is-featured .travel-itinerary-stop-detail,
.travel-itinerary-stop.is-featured .travel-itinerary-stop-control {
  grid-column: 1;
}

.travel-itinerary-stop.is-featured .travel-itinerary-stop-media {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: start;
  margin-top: 0;
}

.travel-itinerary-stop-head {
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--wds-space-1) var(--wds-space-3);
}

.travel-itinerary-stop-head strong {
  font-weight: var(--wds-font-weight-semibold);
  color: var(--wizon-ai-text-primary);
}

.travel-itinerary-stop-head span,
.travel-itinerary-stop-note,
.travel-itinerary-stop-facts {
  color: var(--wizon-ai-text-secondary);
}

.travel-itinerary-stop-detail {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transition:
    max-height var(--wizon-ai-motion-micro-duration) var(--wizon-ai-ease-move),
    opacity var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast);
}

.travel-itinerary-stop.is-selected .travel-itinerary-stop-detail {
  max-height: 160px;
  opacity: 1;
}

.travel-itinerary-stop-facts {
  margin-top: var(--wds-space-1);
  font-size: var(--wds-font-size-caption);
}

.travel-itinerary-stop-media {
  width: min(132px, 100%);
  aspect-ratio: 16 / 9;
  margin-top: var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-control);
}

.travel-itinerary-route-preview {
  min-width: 0;
  min-height: 100%;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  overflow: hidden;
}

.travel-itinerary-route-panel {
  height: 100%;
  padding: var(--wds-space-4);
}

.travel-itinerary-route-panel > header {
  display: flex;
  flex-direction: column;
  gap: var(--wds-space-1);
  margin-bottom: var(--wds-space-3);
}

.travel-itinerary-route-panel > header strong {
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-label);
}

.travel-itinerary-route-panel > header span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-label);
}

.travel-itinerary-route-list {
  display: flex;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-itinerary-route-row {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  gap: var(--wds-space-2);
  padding: var(--wds-space-2);
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--wizon-ai-text-primary);
  text-align: left;
  cursor: pointer;
}

.travel-itinerary-route-row.is-selected {
  background: var(--wizon-ai-surface);
}

.travel-itinerary-route-row > span {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-text-primary);
  color: var(--wizon-ai-surface);
  font-size: var(--wds-font-size-caption);
}

.travel-itinerary-route-row strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--wds-font-size-caption);
}

.travel-itinerary-map {
  position: relative;
  min-height: 214px;
  border-radius: var(--wizon-ai-radius-control);
  background:
    linear-gradient(var(--wizon-ai-popover-border) 1px, transparent 1px),
    linear-gradient(90deg, var(--wizon-ai-popover-border) 1px, transparent 1px),
    var(--wizon-ai-surface);
  background-size: var(--wds-space-8) var(--wds-space-8);
  overflow: hidden;
}

.travel-itinerary-map svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.travel-itinerary-map polyline {
  fill: none;
  stroke: var(--wizon-ai-text-primary);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}

.travel-itinerary-map-marker {
  position: absolute;
  left: var(--travel-map-x);
  top: var(--travel-map-y);
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 2px solid var(--wizon-ai-surface);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-text-secondary);
  color: var(--wizon-ai-surface);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
  transform: translate(-50%, -50%);
  cursor: pointer;
  box-shadow: var(--wizon-ai-popover-shadow);
  transition:
    transform var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-spatial-ease),
    background var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast);
}

.travel-itinerary-map-marker.is-selected {
  background: var(--wizon-ai-text-primary);
  transform: translate(-50%, -50%) scale(1.12);
}

.travel-itinerary-map-selection {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-2);
  min-height: 44px;
  padding-top: var(--wds-space-2);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
}

.travel-itinerary-map-selection a {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-1);
  min-height: 44px;
  color: var(--wizon-ai-text-secondary);
  text-decoration: none;
}

.travel-itinerary-map-selection svg,
.travel-itinerary-actions svg {
  width: 18px;
  height: 18px;
}

.travel-itinerary-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wds-space-2);
  padding-top: var(--wds-space-2);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-itinerary-actions button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wds-space-1);
  min-height: 44px;
  padding: 0 var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  cursor: pointer;
}

.travel-itinerary-adjust {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wds-space-1);
}

.travel-itinerary-adjust[hidden] {
  display: none;
}

.travel-itinerary-adjust > span,
.travel-itinerary-adjust-status,
.travel-itinerary-caveat {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-itinerary-adjust button {
  min-width: 44px;
  padding-inline: var(--wds-space-2);
}

.travel-itinerary-caveat {
  margin: 0;
  line-height: 1.5;
}

.travel-feature-degradation {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--wds-space-2) var(--wds-space-3);
  padding: var(--wds-space-3);
  border-radius: var(--wizon-ai-radius-control);
  /* No literal fallbacks here: both tokens come from stylesheets index.html always loads,
     and --wizon-ai-surface is theme-dependent (#ffffff light / #000000 dark) -- a #ffffff
     fallback would paint a white panel in dark mode on the one occasion it fired. */
  background: color-mix(in srgb, var(--wds-blue-500) 8%, var(--wizon-ai-surface));
  color: var(--wizon-ai-text-primary);
}

.travel-feature-degradation-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--wds-blue-500);
}

.travel-feature-degradation-icon svg {
  width: 18px;
  height: 18px;
}

.travel-feature-degradation-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.travel-feature-degradation-copy strong {
  font-size: var(--wds-font-size-body-2);
}

.travel-feature-degradation-copy > span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: 1.45;
}

.travel-itinerary-note {
  padding-top: var(--wds-space-3);
  border-top: 1px solid var(--wizon-ai-popover-border);
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-itinerary-note > :first-child,
.travel-itinerary-note > :last-child {
  margin-block: 0;
}

.travel-itinerary-foot {
  justify-content: space-between;
}

/* ---- Travel guidebook widget G5-5 ---------------------------------------------------
   G5-4 timing and route facts remain authoritative. The card exposes partial states,
   interleaves stops and legs, and renders location markers without inferred route lines. */
.travel-guidebook-card {
  inline-size: 100%;
  max-inline-size: 100%;
  min-width: 0;
  margin-top: 0;
  overflow: visible;
  border: 0;
  border-radius: initial;
  background: transparent;
  box-shadow: none;
}

.travel-guidebook-card > .visual-answer-content.travel-itinerary-body {
  padding: 0;
}

.travel-guidebook-card > .visual-answer-foot.travel-itinerary-foot {
  padding-inline: 0;
  border-top: 0;
}

.travel-guidebook-card .travel-itinerary-body {
  gap: var(--wds-space-4);
}

.travel-guidebook-heading {
  align-items: flex-start;
}

.travel-guidebook-heading > span {
  gap: var(--wds-space-2);
}

.travel-guidebook-heading p {
  max-width: var(--wizon-ai-chat-max-width);
  margin: 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-normal);
  text-wrap: pretty;
}

.travel-guidebook-revalidation {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  min-height: var(--wizon-ai-action-target-touch);
  gap: var(--wds-space-2);
  padding: 0 var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  cursor: pointer;
}

.travel-guidebook-revalidation svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-snapshot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wds-space-1) var(--wds-space-3);
  padding: var(--wds-space-2) 0;
  border-block: 1px solid var(--wizon-ai-popover-border);
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-snapshot span {
  display: inline-flex;
  align-items: center;
  min-height: var(--wds-space-8);
  white-space: nowrap;
}

.travel-guidebook-personalization {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--wizon-adaptive-right-panel-width)), 1fr));
  gap: var(--wds-space-2);
}

.travel-guidebook-personalization-panel {
  display: grid;
  align-content: start;
  gap: var(--wds-space-2);
  min-width: 0;
  padding: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
}

.travel-guidebook-personalization-panel h4,
.travel-guidebook-personalization-panel p,
.travel-guidebook-personalization-chips,
.travel-guidebook-alternatives {
  margin: 0;
}

.travel-guidebook-personalization-panel h4 {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-personalization-panel p,
.travel-guidebook-alternatives span,
.travel-guidebook-alternatives em {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-personalization-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wds-space-1);
  padding: 0;
  list-style: none;
}

.travel-guidebook-personalization-chips li {
  padding: var(--wds-space-1) var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-hover-soft-bg);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-label-s);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-personalization-check {
  padding-top: var(--wds-space-2);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-guidebook-theme-fit,
.travel-guidebook-personalization-facts {
  display: grid;
  gap: var(--wds-space-1);
  margin: 0;
  padding: 0;
}

.travel-guidebook-theme-fit {
  list-style: none;
}

.travel-guidebook-theme-fit li,
.travel-guidebook-personalization-facts > div {
  display: grid;
  gap: var(--wds-space-1);
  padding-top: var(--wds-space-2);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-guidebook-theme-fit strong,
.travel-guidebook-personalization-facts dt {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-theme-fit span,
.travel-guidebook-personalization-facts dd,
.travel-guidebook-personalization-state {
  margin: 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-label-s);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-personalization-state {
  color: var(--wds-color-warning-text);
  font-style: normal;
  font-weight: var(--wds-font-weight-medium);
}

.travel-guidebook-alternatives {
  display: grid;
  gap: var(--wds-space-2);
  padding: 0;
  list-style: none;
}

.travel-guidebook-alternatives li {
  display: grid;
  gap: var(--wds-space-1);
}

.travel-guidebook-alternatives strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-alternatives em {
  color: var(--wds-color-warning-text);
  font-style: normal;
  font-weight: var(--wds-font-weight-medium);
}

/* G5-7O: the lower guide stays single-column, but each decision surface behaves like a
   compact widget rather than a document section. */
.travel-guidebook-story-flow {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--wds-space-3);
}

.travel-guidebook-prep,
.travel-guidebook-rain-strip {
  display: grid;
  align-content: start;
  gap: var(--wds-space-3);
  min-width: 0;
  padding: var(--wds-space-4);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-surface);
  box-shadow: var(--wizon-ai-popover-shadow);
}

.travel-guidebook-prep header,
.travel-guidebook-prep header > span,
.travel-guidebook-rain-strip header,
.travel-guidebook-rain-strip header > span,
.travel-guidebook-readiness,
.travel-guidebook-rain-controls {
  display: flex;
}

.travel-guidebook-prep header,
.travel-guidebook-rain-strip header {
  align-items: baseline;
  justify-content: space-between;
  gap: var(--wds-space-2);
}

.travel-guidebook-rain-strip header > span {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-prep header > span:first-child {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-readiness,
.travel-guidebook-rain-controls {
  align-items: center;
  flex: 0 0 auto;
  gap: var(--wds-space-1);
}

.travel-guidebook-rain-strip header > .travel-guidebook-rain-controls {
  flex-direction: row;
}

.travel-guidebook-readiness progress {
  appearance: none;
  width: var(--wds-space-24);
  height: var(--wds-space-2);
  overflow: hidden;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-canvas);
  accent-color: var(--wds-color-info);
}

.travel-guidebook-readiness progress::-webkit-progress-bar {
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-canvas);
}

.travel-guidebook-readiness progress::-webkit-progress-value {
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wds-color-info);
}

.travel-guidebook-readiness progress::-moz-progress-bar {
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wds-color-info);
}

.travel-guidebook-readiness b,
.travel-guidebook-rain-controls > span {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-rain-controls button {
  display: grid;
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-primary);
  cursor: pointer;
}

.travel-guidebook-rain-controls button:disabled {
  color: var(--wizon-ai-text-muted);
  cursor: default;
}

.travel-guidebook-rain-controls button svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-prep header strong,
.travel-guidebook-rain-strip header strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-prep header span,
.travel-guidebook-rain-strip header span,
.travel-guidebook-rain-strip > p {
  margin: 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-prep ol {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  list-style: none;
}

.travel-guidebook-prep li {
  display: grid;
  grid-template-columns: var(--wds-space-10) minmax(0, 1fr);
  align-items: center;
  gap: var(--wds-space-3);
  min-height: var(--wizon-ai-action-target-touch);
  padding: var(--wds-space-3);
}

.travel-guidebook-prep li + li {
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-guidebook-prep-icon {
  display: grid;
  place-items: center;
  width: var(--wds-space-10);
  height: var(--wds-space-10);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-hover-soft-bg);
  color: var(--wds-color-info-text);
}

.travel-guidebook-prep-icon svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-prep-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-prep-copy strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-prep-copy > span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

/* G5-7P: one contextual fact is visible at a time.  This preserves the guidebook's
   single-column reading rhythm while giving live data an interactive widget surface. */
.travel-guidebook-context-stack {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-3);
}

.travel-guidebook-live-context {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-2);
  padding: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
}

.travel-guidebook-live-context > header,
.travel-guidebook-live-context > header > span,
.travel-guidebook-live-controls,
.travel-guidebook-live-context [data-travel-live-rail],
.travel-guidebook-live-context li,
.travel-guidebook-live-copy {
  display: flex;
}

.travel-guidebook-live-context > header {
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-guidebook-live-context > header > span:first-child,
.travel-guidebook-live-copy {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-live-context > header strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-live-context > header > span:first-child > span,
.travel-guidebook-live-copy > span,
.travel-guidebook-live-copy small,
.travel-guidebook-live-controls > span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-live-controls {
  align-items: center;
  flex: 0 0 auto;
  gap: 0;
}

.travel-guidebook-live-controls > span {
  padding-inline-end: var(--wds-space-1);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-live-controls button {
  display: grid;
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  cursor: pointer;
}

.travel-guidebook-live-controls button:disabled {
  color: var(--wizon-ai-text-muted);
  cursor: default;
}

.travel-guidebook-live-controls svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-guidebook-live-context [data-travel-live-rail] {
  min-width: 0;
  gap: var(--wds-space-2);
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scroll-snap-stop: always;
  scrollbar-width: none;
  list-style: none;
  touch-action: pan-x;
}

.travel-guidebook-live-context li {
  align-items: center;
  flex: 0 0 100%;
  min-width: 0;
  min-height: calc(var(--wizon-ai-action-target-touch) * 2);
  gap: var(--wds-space-3);
  padding: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  opacity: 0.72;
  scroll-snap-align: start;
  transition:
    border-color var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    background var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    opacity var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast);
}

.travel-guidebook-live-context li[aria-current="true"] {
  border-color: var(--wds-color-info);
  background: var(--wizon-ai-hover-soft-bg);
  opacity: 1;
}

.travel-guidebook-live-icon {
  display: grid;
  flex: 0 0 var(--wds-space-10);
  place-items: center;
  width: var(--wds-space-10);
  height: var(--wds-space-10);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
  color: var(--wds-color-info-text);
}

.travel-guidebook-live-icon svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-live-copy {
  flex: 1 1 auto;
}

.travel-guidebook-live-copy strong {
  overflow: hidden;
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-normal);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.travel-guidebook-live-context .travel-guidebook-status {
  flex: 0 0 auto;
}

/* G5-7S: weather is its own whole-card surface. It no longer sits inside the
   neutral live-context card, so one horizontal gesture always has one owner. */
.travel-guidebook-weather-mini {
  position: relative;
  gap: var(--wds-space-2);
  margin: 0;
  min-height: 156px;
  padding: var(--wds-space-4);
  overflow: hidden;
  border-radius: var(--wizon-ai-radius-control);
  color: var(--wds-white);
}

.travel-guidebook-weather-controls {
  display: flex;
}

.travel-guidebook-weather-copy > span,
.travel-guidebook-weather-copy > small,
.travel-guidebook-weather-temperatures small,
.travel-guidebook-weather-controls > span,
.travel-guidebook-weather-meta {
  color: color-mix(in srgb, var(--wds-white) 78%, transparent);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-weather-hero {
  display: grid;
  grid-column: 1;
  grid-row: 1 / span 2;
  place-items: center;
  width: var(--wds-space-10);
  height: var(--wds-space-10);
}

.travel-guidebook-weather-hero .weather-icon { width: var(--wds-space-10); height: var(--wds-space-10); }

.travel-guidebook-weather-controls {
  position: absolute;
  top: var(--wds-space-2);
  right: var(--wds-space-2);
  align-items: center;
}
.travel-guidebook-weather-controls > span { white-space: nowrap; }
.travel-guidebook-weather-controls button {
  display: grid;
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wds-white);
  cursor: pointer;
}
.travel-guidebook-weather-controls button:disabled { opacity: 0.45; cursor: default; }
.travel-guidebook-weather-controls svg { width: var(--wds-space-4); height: var(--wds-space-4); }

.travel-guidebook-weather-days {
  display: flex;
  gap: var(--wds-space-2);
  width: 100%;
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scrollbar-width: none;
  list-style: none;
  touch-action: pan-x;
}

.travel-guidebook-weather-mini .travel-guidebook-weather-day {
  display: grid;
  grid-template-columns: var(--wds-space-10) minmax(0, 1fr) auto;
  grid-template-rows: auto 1fr;
  align-items: center;
  flex: 0 0 100%;
  gap: var(--wds-space-1) var(--wds-space-3);
  min-width: 0;
  min-height: 92px;
  padding: 0;
  border: 0;
  border-radius: initial;
  background: transparent;
  color: var(--wds-white);
  box-shadow: none;
  opacity: 1;
  scroll-snap-align: start;
  text-align: left;
}
.travel-guidebook-weather-mini .travel-guidebook-weather-day[aria-current="true"] {
  border: 0;
  background: transparent;
  box-shadow: none;
}
.travel-guidebook-weather-copy {
  display: grid;
  grid-column: 2;
  grid-row: 1 / span 2;
  gap: 2px;
  min-width: 0;
}
.travel-guidebook-weather-copy strong {
  overflow: hidden;
  color: var(--wds-white);
  font-size: var(--wds-font-size-body-1, 1rem);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.travel-guidebook-weather-temperatures {
  display: flex;
  grid-column: 3;
  grid-row: 2;
  align-self: end;
  justify-self: end;
  gap: var(--wds-space-4);
  padding-inline-end: var(--wds-space-1);
}
.travel-guidebook-weather-temperatures > span {
  display: flex;
  align-items: baseline;
  gap: var(--wds-space-1);
}
.travel-guidebook-weather-temperatures strong {
  color: var(--wds-white);
  font-size: var(--wds-font-size-title-l);
}
.travel-guidebook-weather-days:focus-visible { outline: none; }
.travel-guidebook-weather-mini:has(.travel-guidebook-weather-days:focus-visible) {
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--wds-white) 72%, transparent);
}
.travel-guidebook-weather-day:focus-visible,
.travel-guidebook-weather-controls button:focus-visible { outline: 2px solid var(--wds-white); outline-offset: 2px; }
.travel-guidebook-weather-pending { margin: var(--wds-space-10) 0 var(--wds-space-4); color: color-mix(in srgb, var(--wds-white) 82%, transparent); font-size: var(--wds-font-size-caption); }
.travel-guidebook-weather-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--wds-space-2);
}
.travel-guidebook-weather-meta span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.travel-guidebook-weather-meta strong {
  flex: none;
  color: var(--wds-white);
  font-weight: var(--wds-font-weight-semibold);
}

/* The assistant message typography layer is intentionally strong. Keep the
   immersive weather card's foreground on its sky palette inside that layer. */
body.chatgpt-reference-v1 .travel-guidebook-weather-mini :is(
  .travel-guidebook-weather-day,
  .travel-guidebook-weather-copy strong,
  .travel-guidebook-weather-temperatures strong,
  .travel-guidebook-weather-meta strong
) {
  color: var(--wds-white);
}

@media (max-width: 520px) {
  .travel-guidebook-weather-mini { min-height: 156px; }
  .travel-guidebook-weather-mini .travel-guidebook-weather-day {
    grid-template-columns: var(--wds-space-10) minmax(0, 1fr);
  }
  .travel-guidebook-weather-copy {
    grid-row: 1;
    padding-inline-end: calc(var(--wizon-ai-action-target-touch) * 2 + var(--wds-space-3));
  }
  .travel-guidebook-weather-temperatures {
    grid-column: 2;
    grid-row: 2;
    justify-self: start;
    padding-inline-end: 0;
  }
}

.travel-guidebook-rain-strip .travel-guidebook-alternatives {
  display: flex;
  gap: var(--wds-space-2);
  margin: 0;
  padding: 0;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scrollbar-width: none;
  list-style: none;
}

.travel-guidebook-rain-strip .travel-guidebook-alternatives li {
  display: grid;
  grid-template-columns: var(--wds-space-12) minmax(0, 1fr) auto;
  align-items: center;
  flex: 0 0 100%;
  gap: var(--wds-space-3);
  min-width: 0;
  min-height: 132px;
  padding: var(--wds-space-4);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  opacity: 0.78;
  scroll-snap-align: start;
  transition:
    border-color var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    background var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    opacity var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast);
}

.travel-guidebook-rain-strip .travel-guidebook-alternatives li[aria-current="true"] {
  border-color: var(--wds-color-info);
  background: var(--wizon-ai-hover-soft-bg);
  opacity: 1;
}

.travel-guidebook-rain-icon {
  display: grid;
  place-items: center;
  width: var(--wds-space-12);
  height: var(--wds-space-12);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
  color: var(--wds-color-info-text);
}

.travel-guidebook-rain-icon svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-rain-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-rain-copy > span:first-child,
.travel-guidebook-rain-copy > span,
.travel-guidebook-rain-copy small {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-rain-copy strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
}

.travel-guidebook-rain-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wds-space-2);
}

.travel-guidebook-rain-actions button {
  min-height: var(--wizon-ai-action-target-touch);
  padding-inline: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  font: inherit;
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
  cursor: pointer;
}

.travel-guidebook-rain-actions [data-travel-rain-apply] {
  border-color: var(--wds-color-info);
  background: var(--wds-color-info);
  color: var(--wds-color-text-on-primary);
}

.travel-guidebook-rain-actions button:disabled {
  border-color: var(--wizon-ai-popover-border);
  background: var(--wizon-ai-canvas);
  color: var(--wizon-ai-text-muted);
  cursor: default;
}

.travel-guidebook-rain-actions [data-travel-rain-apply-status] {
  flex: 1 1 100%;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

/* G5-7C: the media contract stays ordered and untruncated. One horizontal snap rail is
   reused at every container size; touch scroll, visible controls, and keyboard movement
   are equivalent paths to the same items. */
.travel-media-presentation {
  display: grid;
  min-width: 0;
  max-width: 100%;
  gap: var(--wds-space-2);
}

[data-travel-photo-rail] {
  min-width: 0;
}

.travel-media-heading,
.travel-media-heading > span,
.travel-media-controls,
.travel-media-fallback,
.travel-media-fallback > span:last-child {
  display: flex;
}

.travel-media-heading {
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-media-heading > span:first-child {
  min-width: 0;
  align-items: baseline;
  gap: var(--wds-space-2);
}

.travel-media-heading strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
}

.travel-media-heading [data-travel-media-position] {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-media-controls {
  flex: 0 0 auto;
  gap: 0;
}

.travel-media-controls button {
  display: grid;
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  cursor: pointer;
}

.travel-media-controls button:disabled {
  color: var(--wizon-ai-text-muted);
  cursor: default;
}

.travel-media-controls svg,
.travel-media-fallback svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-media-viewport {
  display: flex;
  min-width: 0;
  max-width: 100%;
  gap: var(--wds-space-3);
  padding-block: var(--wds-space-1);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scroll-snap-stop: always;
  scroll-padding-inline: var(--wds-space-1);
  scrollbar-width: thin;
  touch-action: pan-x;
}

.travel-media-card.visual-answer-media,
[data-travel-photo-rail] .travel-media-card,
[data-travel-photo-rail] > :is(button, a, li, article) {
  display: grid;
  flex: 0 0 min(100%, var(--wizon-adaptive-right-panel-width));
  scroll-snap-align: start;
  border: 1px solid var(--wizon-ai-popover-border);
  background: var(--wizon-ai-surface);
  transform-origin: center;
  transition:
    border-color var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    box-shadow var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    opacity var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    transform var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-spatial-ease);
}

.travel-media-card.visual-answer-media[aria-current="true"],
.travel-media-card.visual-answer-media:is([aria-current="true"], .is-selected, [data-selected="true"]),
[data-travel-photo-rail] > :is(button, a, li, article):is([aria-current="true"], .is-selected, [data-selected="true"]) {
  border-color: var(--wds-color-info);
  box-shadow: inset 0 0 0 1px var(--wds-color-info);
  transform: none;
}

.travel-media-card.visual-answer-media img {
  aspect-ratio: 16 / 9;
  height: auto;
}

.travel-media-card-copy {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-1);
  padding: var(--wds-space-3);
}

.travel-media-card-copy strong {
  overflow: hidden;
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  line-height: var(--wds-line-height-normal);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.travel-media-card-copy > span {
  overflow: hidden;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.travel-media-card-copy .travel-media-card-scope {
  color: var(--wds-color-info-text);
  font-weight: var(--wds-font-weight-semibold);
}

.travel-media-fallback {
  align-items: center;
  gap: var(--wds-space-3);
  min-height: calc(var(--wizon-ai-action-target-touch) * 2);
  padding: var(--wds-space-4);
  border: 1px dashed var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  color: var(--wizon-ai-text-secondary);
}

.travel-media-fallback[hidden] {
  display: none;
}

.travel-media-fallback > span:first-child {
  display: grid;
  flex: 0 0 var(--wizon-ai-action-target-touch);
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-hover-soft-bg);
}

.travel-media-fallback > span:last-child {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-media-fallback strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-media-fallback span span {
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-media-controls button:focus-visible,
.travel-media-viewport:focus-visible,
.travel-media-card:focus-visible,
.travel-course-option:focus-visible,
.travel-itinerary-stop-control:focus-visible,
.travel-itinerary-day-step:focus-visible,
.travel-itinerary-tabs button:focus-visible,
.travel-guidebook-course-controls button:focus-visible,
.travel-guidebook-course-viewport:focus-visible,
.travel-guidebook-course-card:focus-visible,
[data-travel-photo-rail]:focus-visible,
[data-travel-course-rail]:focus-visible {
  outline: 0;
  box-shadow: 0 0 0 var(--wds-space-1) var(--wizon-ai-focus-visible-ring);
}

/* G5-7K: the rendering layer can add the semantic hero marker without coupling this
   presentation rule to a single payload version. Selection state drives a short, readable
   crossfade while the image remains the leading guidebook surface. */
:is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]) {
  position: relative;
  min-width: 0;
  aspect-ratio: 16 / 7;
  overflow: hidden;
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  isolation: isolate;
}

/* A source-backed photo keeps the cinematic ratio above. When TourAPI has no usable
   image, the honest text fallback must collapse to its content instead of reserving a
   large blank photographic canvas. */
.travel-guidebook-hero-fallback[data-travel-guidebook-fallback] {
  aspect-ratio: auto;
  overflow: visible;
  background: transparent;
  isolation: auto;
}

:is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]) :is(img, [data-travel-hero-image], .travel-hero-media) {
  width: 100%;
  min-height: 100%;
  object-fit: cover;
  transform: scale(1.01);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
}

:is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]):is(.is-transitioning, [data-travel-selection-state="enter"], [data-travel-selection-state="swap"]) :is(img, [data-travel-hero-image], .travel-hero-media),
:is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]):is(.is-transitioning, [data-travel-selection-state="enter"], [data-travel-selection-state="swap"]) :is(.travel-hero-copy, [data-travel-hero-copy]) {
  animation: travel-guidebook-hero-in var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease) both;
}

[data-travel-guidebook-experience]:is([data-travel-selection-state="enter"], [data-travel-selection-state="swap"], [data-travel-selection-state="changing"]) [data-travel-guidebook-hero] :is(img, [data-travel-hero-image], .travel-hero-media),
[data-travel-guidebook-experience]:is([data-travel-selection-state="enter"], [data-travel-selection-state="swap"], [data-travel-selection-state="changing"]) [data-travel-guidebook-hero] :is(.travel-hero-copy, [data-travel-hero-copy], .travel-guidebook-hero-overlay) {
  animation: travel-guidebook-hero-in var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease) both;
}

@keyframes travel-guidebook-hero-in {
  from {
    opacity: 0;
    transform: translate3d(0, var(--wds-space-3), 0) scale(1.01);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

.travel-itinerary-day:not([hidden]),
.travel-itinerary-route-panel:not([hidden]),
.travel-guidebook-detail:not([hidden]),
[data-travel-detail-panel]:not([hidden]),
[data-travel-location-panel]:not([hidden]) {
  animation: travel-guidebook-panel-in var(--wizon-ai-motion-panel-duration) var(--wizon-ai-motion-spatial-ease) both;
}

@keyframes travel-guidebook-panel-in {
  from {
    opacity: 0;
    transform: translate3d(0, var(--wds-space-2), 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* The hero and curated-course rail are supplied only when source-backed media exists.
   A text fallback uses the same semantic hero marker, keeping the state honest without
   manufacturing a photographic surface. */
.travel-guidebook-hero.has-media {
  display: grid;
  min-height: 0;
  color: var(--wds-color-text-on-primary);
}

.travel-guidebook-hero-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: zoom-in;
}

.travel-guidebook-hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, color-mix(in srgb, var(--wizon-ai-text-primary) 68%, transparent), transparent);
  pointer-events: none;
}

.travel-guidebook-rain-visual-fallback,
.travel-guidebook-rain-place-fallback,
.travel-guidebook-rain-map-fallback {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--wds-space-2);
  min-height: 100%;
  padding: var(--wds-space-4);
  background: var(--wizon-ai-hover-soft-bg);
  color: var(--wizon-ai-text-secondary);
  text-align: center;
}

.travel-guidebook-rain-visual-fallback[hidden],
.travel-guidebook-rain-place-fallback[hidden],
.travel-guidebook-rain-map-fallback[hidden] {
  display: none;
}

.travel-guidebook-rain-visual-fallback {
  position: absolute;
  inset: 0;
}

.travel-guidebook-rain-visual-fallback strong,
.travel-guidebook-rain-place-fallback > span:last-child,
.travel-guidebook-rain-map-fallback > span {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-rain-visual-fallback > span:last-child {
  max-width: var(--wizon-adaptive-right-panel-width);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-rain-visual-fallback svg,
.travel-guidebook-rain-place-fallback svg,
.travel-guidebook-rain-map-fallback svg {
  width: var(--wds-space-6);
  height: var(--wds-space-6);
  color: var(--wds-color-info-text);
}

.travel-guidebook-rain-place-fallback {
  align-self: stretch;
  min-height: var(--wds-space-24);
  border-radius: calc(var(--wizon-ai-radius-control) - var(--wds-space-1));
}

.travel-guidebook-rain-map-fallback {
  min-height: var(--wds-space-24);
  margin: var(--wds-space-3);
  border: 1px dashed var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
}

.travel-guidebook-hero-overlay {
  position: relative;
  align-self: end;
  max-width: var(--wizon-ai-chat-max-width);
  padding: var(--wds-space-5);
  pointer-events: none;
}

.travel-guidebook-hero-overlay h3,
.travel-guidebook-hero-overlay p,
.travel-guidebook-hero-kicker,
.travel-guidebook-hero-status,
.travel-guidebook-hero-credit {
  color: var(--wds-color-text-on-primary);
}

.travel-guidebook-hero-overlay h3,
.travel-guidebook-hero-overlay p {
  margin: 0;
}

.travel-guidebook-hero-overlay h3 {
  margin-top: var(--wds-space-1);
  font-size: var(--wds-font-size-title-l);
}

.travel-guidebook-hero-overlay p {
  max-width: var(--wizon-adaptive-right-panel-width);
  margin-top: var(--wds-space-2);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-hero-kicker,
.travel-guidebook-hero-status,
.travel-guidebook-hero-credit {
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-hero-action {
  position: absolute;
  inset-block-start: var(--wds-space-3);
  inset-inline-end: var(--wds-space-3);
}

.travel-guidebook-hero-credit {
  position: absolute;
  inset-block-end: var(--wds-space-2);
  inset-inline-end: var(--wds-space-3);
  max-width: var(--wizon-adaptive-right-panel-width);
  margin: 0;
  text-align: end;
}

.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-hero-overlay h3,
.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-hero-overlay p,
.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-hero-kicker,
.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-hero-status,
.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-hero-credit {
  color: var(--wds-color-text-on-primary);
}

.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-snapshot {
  gap: var(--wds-space-1);
  padding: 0;
  border: 0;
  color: var(--wds-color-text-on-primary);
}

.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-snapshot span {
  min-height: var(--wds-space-6);
  padding-inline: var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-pill);
  background: color-mix(in srgb, var(--wizon-ai-text-primary) 44%, transparent);
  color: var(--wds-color-text-on-primary);
}

.chatgpt-reference-v1 [data-travel-guidebook-hero] .travel-guidebook-status {
  color: var(--wds-color-text-on-primary);
}

/* The no-photo hero is an editorial text header on the page canvas. Do not inherit
   the white-on-photo metadata treatment from the source-backed hero. */
.chatgpt-reference-v1 .travel-guidebook-hero-fallback[data-travel-guidebook-fallback] {
  color: var(--wizon-ai-text-primary);
}

.chatgpt-reference-v1 .travel-guidebook-hero-fallback[data-travel-guidebook-fallback] :is(
    .travel-guidebook-hero-kicker,
    .travel-guidebook-hero-status,
    .travel-guidebook-status
  ) {
  color: var(--wizon-ai-text-secondary);
}

.chatgpt-reference-v1 .travel-itinerary-card:not(.travel-guidebook-card) [data-travel-guidebook-hero] .travel-guidebook-hero-overlay h3 {
  font-size: var(--wds-font-size-headline-m);
}

.travel-guidebook-hero.has-media {
  aspect-ratio: 21 / 5;
}

.travel-guidebook-hero-overlay {
  align-self: center;
  display: grid;
  width: min(58%, var(--wizon-ai-chat-max-width));
  justify-items: start;
  gap: var(--wds-space-1);
  padding-block: var(--wds-space-5);
}

.travel-guidebook-hero-overlay h3,
.travel-guidebook-hero-overlay p {
  margin-block: 0;
}

.travel-guidebook-hero-overlay .travel-guidebook-snapshot {
  padding-block: var(--wds-space-1);
}

.travel-guidebook-hero-weather {
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-medium);
  word-break: keep-all;
}

.travel-guidebook-hero-credit {
  max-width: 46%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.travel-media-card-selected {
  position: absolute;
  inset-block-start: var(--wds-space-2);
  inset-inline-start: var(--wds-space-2);
  display: none;
  place-items: center;
  width: var(--wds-space-8);
  height: var(--wds-space-8);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wds-color-info);
  color: var(--wds-color-text-on-primary);
}

.travel-media-card:is([aria-pressed="true"], .is-selected) .travel-media-card-selected {
  display: grid;
}

.travel-media-card-selected svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-media-card.visual-answer-media {
  min-height: var(--wds-space-32);
}

.travel-media-card.visual-answer-media img {
  position: absolute;
  inset: 0;
  height: 100%;
  aspect-ratio: auto;
}

.travel-media-card-copy {
  position: relative;
  align-self: end;
  background: linear-gradient(transparent, color-mix(in srgb, var(--wizon-ai-text-primary) 82%, transparent));
}

.chatgpt-reference-v1 .travel-media-card-copy strong,
.chatgpt-reference-v1 .travel-media-card-copy > span,
.chatgpt-reference-v1 .travel-media-card-copy .travel-media-card-scope {
  color: var(--wds-color-text-on-primary);
}

@container travel-itinerary (min-width: 521px) {
  .travel-media-card.visual-answer-media,
  [data-travel-photo-rail] .travel-media-card,
  [data-travel-photo-rail] > :is(button, a, li, article) {
    flex-basis: min(24%, var(--wizon-adaptive-right-panel-width));
  }

  .travel-guidebook-course-card,
  [data-travel-course-rail] > :is(button, a, li, article) {
    flex-basis: min(38%, var(--wizon-adaptive-right-panel-width));
  }
}

[data-travel-course-rail] {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-2);
}

.travel-guidebook-rail-heading,
.travel-guidebook-rail-heading > span,
.travel-guidebook-course-controls {
  display: flex;
  align-items: center;
}

.travel-guidebook-rail-heading {
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-guidebook-rail-heading > span:first-child {
  min-width: 0;
  gap: var(--wds-space-2);
}

.travel-guidebook-rail-heading strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
}

.travel-guidebook-rail-heading [data-travel-course-position] {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-course-controls {
  flex: 0 0 auto;
  gap: 0;
}

.travel-guidebook-course-controls button {
  display: grid;
  place-items: center;
  width: var(--wizon-ai-action-target-touch);
  height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  cursor: pointer;
}

.travel-guidebook-course-controls svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-guidebook-course-controls button:disabled {
  color: var(--wizon-ai-text-muted);
  cursor: default;
}

.travel-guidebook-course-viewport {
  display: flex;
  min-width: 0;
  gap: var(--wds-space-3);
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scroll-snap-stop: always;
  scrollbar-width: thin;
  touch-action: pan-x;
}

.travel-guidebook-course-card {
  display: grid;
  grid-template-columns: minmax(var(--wds-space-24), 2fr) minmax(0, 3fr);
  flex: 0 0 min(100%, var(--wizon-adaptive-right-panel-width));
  min-width: 0;
  padding: var(--wds-space-2);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  color: var(--wizon-ai-text-primary);
  text-align: left;
  scroll-snap-align: start;
  transform-origin: center;
  cursor: pointer;
  transition:
    border-color var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    box-shadow var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    transform var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-spatial-ease);
}

.travel-guidebook-course-card:is(.is-selected, [aria-pressed="true"]) {
  border-color: var(--wds-color-info);
  background: var(--wizon-ai-hover-soft-bg);
  box-shadow: inset 0 0 0 1px var(--wds-color-info);
  transform: none;
}

.travel-guidebook-course-visual,
.travel-guidebook-course-visual img {
  width: 100%;
  height: 100%;
}

.travel-guidebook-course-visual {
  align-self: start;
  aspect-ratio: 4 / 3;
  height: auto;
  min-height: var(--wds-space-20);
  overflow: hidden;
  border-radius: calc(var(--wizon-ai-radius-control) - var(--wds-space-1));
}

.travel-guidebook-course-visual img {
  object-fit: cover;
}

.travel-guidebook-course-copy,
.travel-guidebook-course-badges {
  display: flex;
  min-width: 0;
}

.travel-guidebook-course-copy {
  flex-direction: column;
  gap: var(--wds-space-1);
  padding-inline-start: var(--wds-space-2);
}

.travel-guidebook-course-label {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-course-copy strong {
  overflow: hidden;
  font-size: var(--wds-font-size-body-2);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.travel-guidebook-course-badges {
  flex-wrap: wrap;
  gap: var(--wds-space-1);
}

.travel-guidebook-course-badges span {
  display: inline-flex;
  align-items: center;
  min-height: var(--wds-space-6);
  padding-inline: var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-canvas);
  color: var(--wds-color-info-text);
  font-size: var(--wds-font-size-label-s);
}

.travel-guidebook-plan {
  display: grid;
  min-width: 0;
  gap: var(--wds-space-4);
  padding: var(--wds-space-4);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-surface);
  box-shadow: none;
}

.travel-guidebook-plan-heading,
.travel-guidebook-plan-heading > span {
  display: flex;
}

.travel-guidebook-plan-heading {
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-guidebook-plan-heading > span:first-child {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-guidebook-plan-heading strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
}

.travel-guidebook-plan-heading > span:first-child > span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-plan-heading .travel-itinerary-day-nav,
.travel-guidebook-plan-heading .travel-itinerary-tabs {
  flex: 0 0 auto;
  gap: 0;
}

.travel-guidebook-plan-heading .travel-itinerary-tabs {
  width: auto;
  padding: 0;
  border-radius: initial;
  background: transparent;
}

.travel-guidebook-plan-heading .travel-itinerary-tabs button {
  min-width: auto;
  padding-inline: var(--wds-space-3);
  border-radius: initial;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-body-1);
}

.travel-guidebook-plan-heading .travel-itinerary-tabs button[aria-selected="true"] {
  background: transparent;
  color: var(--wizon-ai-text-primary);
  font-weight: var(--wds-font-weight-semibold);
  box-shadow: none;
  transform: none;
}

.travel-guidebook-selection-layout {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--wds-space-4);
}

.travel-guidebook-place-detail {
  display: grid;
  grid-template-columns: minmax(200px, 240px) minmax(0, 1fr);
  align-items: center;
  min-width: 0;
  gap: var(--wds-space-3);
  margin-top: var(--wds-space-3);
  padding-top: var(--wds-space-3);
  border-top: 1px solid var(--wizon-ai-popover-border);
  animation: travel-guidebook-panel-in var(--wizon-ai-motion-panel-duration) var(--wizon-ai-motion-spatial-ease) both;
}

.travel-guidebook-place-detail[hidden] {
  display: none;
}

.travel-guidebook-place-visual {
  align-self: start;
  overflow: hidden;
  border-radius: calc(var(--wizon-ai-radius-control) - var(--wds-space-1));
}

.travel-guidebook-place-visual img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.travel-guidebook-location-disclosure {
  min-width: 0;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-canvas);
  overflow: hidden;
}

.travel-guidebook-location-disclosure > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--wizon-ai-action-target-touch);
  gap: var(--wds-space-3);
  padding: var(--wds-space-2) var(--wds-space-3);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-semibold);
  cursor: pointer;
  list-style: none;
}

.travel-guidebook-location-disclosure > summary::-webkit-details-marker {
  display: none;
}

.travel-guidebook-location-disclosure > summary > span:first-child {
  display: flex;
  align-items: center;
  gap: var(--wds-space-2);
}

.travel-guidebook-location-disclosure > summary > span:first-child svg,
.travel-guidebook-location-chevron svg {
  width: var(--wds-space-5);
  height: var(--wds-space-5);
}

.travel-guidebook-location-chevron {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  color: var(--wizon-ai-text-secondary);
  transition: transform var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-spatial-ease);
}

.travel-guidebook-location-disclosure[open] .travel-guidebook-location-chevron {
  transform: rotate(180deg);
}

.travel-guidebook-location-disclosure .travel-itinerary-route-preview {
  min-height: 0;
  margin: 0 var(--wds-space-3) var(--wds-space-3);
}

.travel-guidebook-place-copy {
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--wds-space-1);
}

.travel-guidebook-place-copy [hidden] {
  display: none;
}

.travel-guidebook-place-copy h4,
.travel-guidebook-place-copy p {
  margin: 0;
}

.travel-guidebook-place-copy > span:first-child,
.travel-guidebook-place-copy p,
.travel-guidebook-place-copy small {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-place-copy h4 {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-place-copy small {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.travel-guidebook-place-timing,
[data-travel-place-timing],
[data-travel-place-route] {
  color: var(--wds-color-info-text);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-course-decision {
  display: grid;
  gap: var(--wds-space-3);
  padding: var(--wds-space-4);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-surface);
}

.travel-course-decision-heading,
.travel-course-decision-heading > span,
.travel-course-option header,
.travel-course-option header > span,
.travel-course-rationale header {
  display: flex;
}

.travel-course-decision-heading,
.travel-course-option header,
.travel-course-rationale header {
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--wds-space-3);
}

.travel-course-decision-heading > span,
.travel-course-option header > span {
  min-width: 0;
  flex-direction: column;
  gap: var(--wds-space-1);
}

.travel-course-decision h4,
.travel-course-decision p,
.travel-course-decision dl,
.travel-course-decision dd {
  margin: 0;
}

.travel-course-decision h4 {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
  line-height: var(--wds-line-height-normal);
}

.travel-course-decision-heading p,
.travel-course-decision-heading > span:last-child,
.travel-course-option header span span,
.travel-course-option p,
.travel-course-rationale > p,
.travel-course-rationale header > span,
.travel-course-rejected li span {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-course-decision-heading > span:last-child {
  flex: 0 0 auto;
  white-space: nowrap;
}

.travel-course-options {
  display: flex;
  min-width: 0;
  gap: var(--wds-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scroll-behavior: smooth;
  scroll-snap-type: inline mandatory;
  scroll-snap-stop: always;
  scrollbar-width: thin;
  touch-action: pan-x;
}

.travel-course-option,
[data-travel-course-rail] > :is(button, a, li, article) {
  display: grid;
  flex: 0 0 min(100%, var(--wizon-adaptive-right-panel-width));
  align-content: start;
  gap: var(--wds-space-2);
  min-width: 0;
  padding: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-surface);
  scroll-snap-align: start;
  transform-origin: center;
  transition:
    border-color var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    box-shadow var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-effect-fast),
    transform var(--wizon-ai-motion-micro-duration) var(--wizon-ai-motion-spatial-ease);
}

.travel-course-option:is(.is-primary, .is-selected, [aria-current="true"], [data-selected="true"]),
[data-travel-course-rail] > :is(button, a, li, article):is(.is-primary, .is-selected, [aria-current="true"], [data-selected="true"]) {
  border-color: var(--wds-color-info);
  background: var(--wizon-ai-hover-soft-bg);
  box-shadow: inset 0 0 0 1px var(--wds-color-info);
  transform: none;
}

.travel-course-option header strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
}

.travel-course-option header b {
  flex: 0 0 auto;
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-h3);
  font-variant-numeric: tabular-nums;
}

.travel-course-rationale {
  display: grid;
  gap: var(--wds-space-3);
  padding-top: var(--wds-space-3);
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-course-rationale dl {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--wds-space-2);
}

.travel-course-rationale dl > div {
  display: grid;
  gap: var(--wds-space-1);
  min-width: 0;
  padding: var(--wds-space-3);
  border-radius: var(--wizon-ai-radius-control);
  background: var(--wizon-ai-hover-soft-bg);
}

.travel-course-rationale dt {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-label-s);
}

.travel-course-rationale dd {
  display: grid;
  gap: var(--wds-space-1);
}

.travel-course-rationale dd strong {
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-1);
  font-variant-numeric: tabular-nums;
}

.travel-course-rationale dd span,
.travel-course-check {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-label-s);
  line-height: var(--wds-line-height-normal);
}

.travel-course-rejected {
  border-top: 1px solid var(--wizon-ai-popover-border);
}

.travel-course-rejected summary {
  display: flex;
  align-items: center;
  min-height: var(--wizon-ai-action-target-touch);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
  cursor: pointer;
}

.travel-course-rejected ul {
  display: grid;
  gap: var(--wds-space-2);
  margin: 0;
  padding: 0 0 var(--wds-space-2);
  list-style: none;
}

.travel-course-rejected li {
  display: grid;
  grid-template-columns: minmax(var(--wds-space-16), auto) minmax(0, 1fr);
  gap: var(--wds-space-3);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-day-head,
.travel-guidebook-day-head > span,
.travel-guidebook-day-meta {
  display: flex;
}

.travel-guidebook-day-head {
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--wds-space-3);
  padding-bottom: var(--wds-space-2);
}

.travel-guidebook-day-head > span {
  flex-direction: column;
  min-width: 0;
  gap: var(--wds-space-1);
}

.travel-guidebook-day-head strong {
  font-size: var(--wds-font-size-body-2);
}

.travel-guidebook-day-head > span > span,
.travel-guidebook-day-meta {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-day-meta {
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--wds-space-2);
  margin-bottom: var(--wds-space-3);
  padding: 0;
  border: 0;
}

.travel-guidebook-day-meta > span {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-1);
  min-height: var(--wds-space-8);
  padding-inline: var(--wds-space-3);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-canvas);
}

.travel-guidebook-day-meta svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-itinerary-stop.travel-guidebook-stop {
  grid-template-columns: var(--wds-space-8) minmax(0, 1fr);
  gap: var(--wds-space-2);
}

.travel-guidebook-stop .travel-itinerary-stop-marker {
  display: grid;
  place-items: center;
  width: var(--wds-space-8);
  height: var(--wds-space-8);
  margin: 0;
  border: 0;
  background: var(--wds-color-info);
  color: var(--wds-color-text-on-primary);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
}

.travel-guidebook-stop.is-selected .travel-itinerary-stop-marker {
  background: var(--wizon-ai-text-primary);
}

.travel-guidebook-stop.travel-itinerary-stop:not(:last-child)::after {
  top: var(--wds-space-8);
  left: calc(var(--wds-space-8) / 2);
}

.travel-guidebook-stop .travel-itinerary-stop-copy {
  flex-direction: column;
  min-height: var(--wizon-ai-action-target-touch);
  padding: var(--wds-space-3);
  border: 1px solid transparent;
}

.travel-guidebook-stop .travel-itinerary-stop-copy > .travel-itinerary-stop-control {
  width: 100%;
  min-height: var(--wizon-ai-action-target-touch);
}

.travel-guidebook-stop.is-selected .travel-itinerary-stop-copy {
  border-color: var(--wds-color-info);
  background: var(--wizon-ai-hover-soft-bg);
  box-shadow: none;
  transform: none;
}

.travel-guidebook-stop .travel-itinerary-stop-head {
  justify-content: flex-start;
}

.travel-guidebook-stop .travel-itinerary-stop-head > span {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: var(--wds-space-2);
}

.travel-guidebook-stop .travel-itinerary-stop-time {
  flex: 0 0 auto;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-stop .travel-itinerary-stop-detail {
  display: none;
}

.travel-guidebook-stop-timing {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-stop.is-selected .travel-guidebook-stop-timing {
  display: none;
}

.travel-guidebook-leg,
.travel-guidebook-remaining {
  display: grid;
  grid-template-columns: var(--wds-space-8) minmax(0, 1fr);
  align-items: center;
  gap: var(--wds-space-2);
  min-height: var(--wizon-ai-action-target-touch);
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-leg-marker {
  display: grid;
  place-items: center;
  width: var(--wds-space-8);
  height: var(--wds-space-8);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-surface);
}

.travel-guidebook-leg-marker svg {
  width: var(--wds-space-4);
  height: var(--wds-space-4);
}

.travel-guidebook-leg-times {
  color: var(--wizon-ai-text-secondary);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-leg-copy,
.travel-guidebook-remaining > span:last-child {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--wds-space-1) var(--wds-space-2);
}

.travel-guidebook-leg-copy strong,
.travel-guidebook-remaining strong {
  color: var(--wizon-ai-text-primary);
}

.travel-guidebook-leg-evidence {
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-label-s);
  font-variant-numeric: tabular-nums;
}

.travel-guidebook-remaining > span:first-child {
  width: var(--wds-space-3);
  height: var(--wds-space-3);
  margin-inline: auto;
  border: 1px dashed var(--wizon-ai-text-muted);
  border-radius: var(--wizon-ai-radius-pill);
}

.travel-guidebook-remaining > span:last-child {
  justify-content: space-between;
  min-width: 0;
}

.travel-guidebook-status {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-1);
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-label-s);
  font-weight: var(--wds-font-weight-medium);
  white-space: nowrap;
}

.travel-guidebook-status > span {
  width: var(--wds-space-2);
  height: var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-text-muted);
}

.travel-guidebook-status[data-status="passed"] {
  color: var(--wds-color-success-text);
}

.travel-guidebook-status[data-status="passed"] > span {
  background: var(--wds-color-success);
}

.travel-guidebook-status[data-status="needs_refresh"] {
  color: var(--wds-color-warning-text);
}

.travel-guidebook-status[data-status="needs_refresh"] > span {
  background: var(--wds-color-warning);
}

.travel-guidebook-status[data-status="not_checked"] {
  color: var(--wds-color-info-text);
}

.travel-guidebook-status[data-status="not_checked"] > span {
  background: var(--wds-color-info);
}

.travel-guidebook-status[data-status="failed"] {
  color: var(--wds-color-error-text);
}

.travel-guidebook-status[data-status="failed"] > span {
  background: var(--wds-color-error);
}

.travel-guidebook-map-note {
  margin: var(--wds-space-2) 0 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  line-height: var(--wds-line-height-normal);
}

.travel-guidebook-evidence {
  border-block: 1px solid var(--wizon-ai-popover-border);
}

.travel-guidebook-evidence > [data-travel-evidence-toggle] {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--wizon-ai-action-target-touch);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-primary);
  font-family: inherit;
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-semibold);
  text-align: start;
  cursor: pointer;
}

.travel-guidebook-evidence-list {
  display: grid;
  gap: var(--wds-space-2);
  padding-bottom: var(--wds-space-3);
}

.travel-guidebook-evidence-list p {
  display: grid;
  grid-template-columns: minmax(var(--wds-space-16), auto) minmax(0, 1fr);
  align-items: baseline;
  gap: var(--wds-space-3);
  margin: 0;
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.travel-guidebook-status-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wds-space-2) var(--wds-space-4);
  padding: var(--wds-space-3) 0;
  border-top: 1px solid var(--wizon-ai-popover-border);
}

@container travel-itinerary (max-width: 520px) {
  :is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]) {
    aspect-ratio: 7 / 3;
  }

  .travel-guidebook-hero.has-media {
    aspect-ratio: 7 / 3;
  }

  .travel-guidebook-hero-overlay {
    width: 76%;
    padding: var(--wds-space-3);
  }

  .chatgpt-reference-v1 .travel-itinerary-card:not(.travel-guidebook-card) [data-travel-guidebook-hero] .travel-guidebook-hero-overlay h3 {
    font-size: var(--wds-font-size-title-l);
  }

  .travel-guidebook-hero-overlay > p:not(.travel-guidebook-hero-weather),
  .travel-guidebook-hero-overlay .travel-guidebook-snapshot {
    display: none;
  }

  .travel-guidebook-hero-credit {
    display: none;
  }

  .travel-itinerary-hero {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: clamp(92px, 29vw, 128px);
    padding: var(--wds-space-1);
  }

  .travel-itinerary-body {
    gap: var(--wds-space-3);
    padding: var(--wds-space-4);
  }

  .travel-itinerary-heading {
    align-items: stretch;
    flex-direction: column;
  }

  .travel-itinerary-tabs {
    width: 100%;
  }

  .travel-itinerary-day-nav {
    width: 100%;
  }

  .travel-itinerary-day-nav.is-long {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) auto 44px;
    gap: var(--wds-space-1);
  }

  .travel-itinerary-day-nav.is-long .travel-itinerary-tabs {
    padding-inline: var(--wds-space-1);
  }

  .travel-itinerary-day-position {
    min-width: 48px;
    justify-content: center;
  }

  .travel-itinerary-layout {
    display: flex;
    flex-direction: column;
    gap: var(--wds-space-5);
  }

  .travel-itinerary-route-preview {
    order: -1;
    width: 100%;
  }

  .travel-itinerary-route-panel {
    padding: var(--wds-space-3);
  }

  .travel-itinerary-map {
    min-height: 180px;
  }

  .travel-guidebook-card .travel-itinerary-map-marker {
    width: var(--wizon-ai-action-target-touch);
    height: var(--wizon-ai-action-target-touch);
  }

  .travel-itinerary-stop {
    grid-template-columns: var(--wds-space-3) 42px minmax(0, 1fr);
  }

  .travel-itinerary-stop-media {
    width: 100%;
    max-height: 112px;
  }

  .travel-itinerary-stop.is-featured .travel-itinerary-stop-copy {
    display: flex;
  }

  .travel-itinerary-stop.is-featured .travel-itinerary-stop-media {
    margin-top: var(--wds-space-2);
  }

  .travel-itinerary-actions,
  .travel-itinerary-adjust {
    align-items: stretch;
    flex-direction: column;
  }

  .travel-itinerary-actions > button,
  .travel-itinerary-adjust,
  .travel-itinerary-adjust button {
    width: 100%;
  }

  .travel-guidebook-card .travel-itinerary-route-preview {
    order: initial;
    min-height: 0;
  }

  .travel-guidebook-card .travel-itinerary-route-panel {
    height: auto;
  }

  .travel-guidebook-plan-heading {
    align-items: stretch;
    flex-direction: column;
  }

  .travel-guidebook-plan,
  .travel-guidebook-prep,
  .travel-guidebook-rain-strip {
    padding: var(--wds-space-3);
    box-shadow: none;
  }

  .travel-guidebook-plan-heading .travel-itinerary-day-nav,
  .travel-guidebook-plan-heading .travel-itinerary-tabs {
    width: auto;
    align-self: flex-start;
  }

  .travel-guidebook-place-detail {
    grid-template-columns: minmax(0, 1fr);
  }

  .travel-guidebook-rain-strip .travel-guidebook-alternatives li {
    grid-template-columns: var(--wds-space-10) minmax(0, 1fr);
    min-height: 156px;
    padding: var(--wds-space-3);
  }

  .travel-guidebook-rain-strip .travel-guidebook-status {
    grid-column: 2;
  }

  .travel-guidebook-rain-icon {
    width: var(--wds-space-10);
    height: var(--wds-space-10);
  }

  .travel-guidebook-readiness progress {
    width: var(--wds-space-16);
  }

  .travel-guidebook-place-visual img {
    aspect-ratio: 16 / 9;
  }

  .travel-guidebook-revalidation {
    width: 100%;
  }

  .travel-guidebook-hero-action {
    width: auto;
    gap: var(--wds-space-1);
    padding-inline: var(--wds-space-2);
    font-size: var(--wds-font-size-label-s);
  }

  .travel-media-heading,
  .travel-media-heading > span:first-child {
    gap: var(--wds-space-1);
  }

  .travel-media-heading strong {
    font-size: var(--wds-font-size-body-2);
  }

  .travel-guidebook-snapshot {
    gap: var(--wds-space-1) var(--wds-space-2);
  }

  .travel-media-card.visual-answer-media {
    flex-basis: calc(100% - var(--wds-space-8));
  }

  .travel-course-decision {
    padding: var(--wds-space-3);
  }

  .travel-course-decision-heading {
    align-items: flex-start;
  }

  .travel-course-options,
  .travel-course-rationale dl {
    grid-template-columns: minmax(0, 1fr);
  }

  .travel-course-option,
  .travel-guidebook-course-card,
  [data-travel-course-rail] > :is(button, a, li, article) {
    flex-basis: calc(100% - var(--wds-space-8));
  }

  .travel-course-rejected li {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--wds-space-1);
  }

  .travel-itinerary-stop.travel-guidebook-stop,
  .travel-guidebook-leg,
  .travel-guidebook-remaining {
    grid-template-columns: var(--wds-space-8) minmax(0, 1fr);
  }

  .travel-guidebook-stop .travel-itinerary-stop-copy {
    padding: var(--wds-space-2);
  }

  .travel-guidebook-evidence-list p {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--wds-space-1);
  }

  .travel-guidebook-status-legend {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (prefers-reduced-motion: reduce) {
  .visual-answer-media img,
  .travel-media-viewport,
  [data-travel-photo-rail],
  [data-travel-course-rail],
  .travel-media-card.visual-answer-media,
  .travel-course-option,
  .travel-guidebook-course-viewport,
  .travel-guidebook-course-card,
  .travel-guidebook-live-context [data-travel-live-rail],
  .travel-guidebook-weather-days,
  .travel-guidebook-weather-mini,
  .travel-guidebook-live-context li,
  .travel-itinerary-tabs,
  .travel-itinerary-tabs button,
  .travel-itinerary-stop-copy,
  .travel-itinerary-stop-detail,
  .travel-itinerary-map-marker,
  .travel-itinerary-day,
  .travel-itinerary-route-panel,
  .travel-guidebook-place-detail,
  .travel-guidebook-detail,
  [data-travel-detail-panel],
  [data-travel-location-panel],
  :is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]),
  :is(.travel-guidebook-hero, .travel-hero, [data-travel-guidebook-hero]) :is(img, [data-travel-hero-image], .travel-hero-media) {
    transition: none;
    animation: none;
    transform: none;
    scroll-behavior: auto;
  }
}

@media (hover: hover) and (pointer: fine) {
  .travel-media-controls button:not(:disabled):hover,
  .travel-guidebook-course-controls button:not(:disabled):hover,
  .travel-guidebook-live-controls button:not(:disabled):hover {
    color: var(--wizon-ai-text-primary);
  }

  .travel-media-card.visual-answer-media:not([aria-current="true"]):hover,
  [data-travel-photo-rail] > :is(button, a, li, article):not([aria-current="true"]):not(.is-selected):hover,
  .travel-course-option:not(.is-primary):hover,
  .travel-guidebook-course-card:not(.is-selected):hover,
  [data-travel-course-rail] > :is(button, a, li, article):not([aria-current="true"]):not(.is-selected):hover {
    transform: scale(1.01);
  }

  .travel-itinerary-day-step:not(:disabled):hover,
  .travel-itinerary-tabs button:hover {
    background: var(--wizon-ai-hover-soft-bg);
  }
}

/* Image tiles open a focused preview. Source-list navigation stays exclusively on the source
   pill below the answer, avoiding two controls that perform the same provenance action. */
.image-preview-dialog[open] {
  position: fixed;
  inset: 0;
  display: block;
  width: min(
    calc(var(--wizon-ai-chat-max-width) + var(--wizon-adaptive-right-panel-width)),
    calc(100vw - var(--wds-space-8))
  );
  height: min(calc(100dvh - var(--wds-space-8)), calc(var(--wizon-ai-chat-max-width) + var(--wds-space-16)));
  max-width: none;
  max-height: none;
  margin: auto;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-popover-bg);
  color: var(--wizon-ai-text-primary);
  box-shadow: var(--wizon-ai-dialog-shadow);
  opacity: 0;
  transform: translate3d(0, var(--wds-space-3), 0) scale(0.985);
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    transform var(--wizon-motion-surface-duration) var(--wizon-motion-spatial-ease);
}

.image-preview-dialog::backdrop {
  background: color-mix(in srgb, var(--wds-black) 16%, transparent);
  opacity: 0;
  transition: opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease);
}

.image-preview-dialog[data-motion-state="open"] {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
}

.image-preview-dialog[data-motion-state="open"]::backdrop {
  opacity: 1;
}

.image-preview-dialog[data-motion-state="closing"] {
  opacity: 0;
  transform: translate3d(0, var(--wds-space-3), 0) scale(0.985);
}

.image-preview-dialog[data-motion-state="closing"]::backdrop {
  opacity: 0;
}

html[data-theme="dark"] .image-preview-dialog::backdrop {
  background: color-mix(in srgb, var(--wds-black) 52%, transparent);
}

.image-preview-dialog:focus {
  outline: none;
}

.image-preview-shell {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  height: 100%;
  min-height: 0;
}

.image-preview-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: var(--wds-space-3);
  min-height: var(--wizon-ai-action-target-touch);
  padding: var(--wds-space-3) var(--wds-space-4);
  border-bottom: 1px solid var(--wizon-ai-popover-border);
}

.image-preview-head-actions {
  grid-column: 3;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--wds-space-2);
}

.image-preview-stage {
  position: relative;
  display: flex;
  min-width: 0;
  min-height: 0;
  padding: var(--wds-space-5) var(--wds-space-4);
  overflow: hidden;
  background: var(--wizon-ai-hover-soft-bg);
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
}

.image-preview-stage.is-dragging {
  cursor: grabbing;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-stage {
  background: color-mix(in srgb, var(--wizon-ai-text-primary) 86%, var(--wizon-ai-popover-bg));
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-carousel-card img {
  object-fit: contain;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-carousel-card.is-current {
  border: 0;
  border-radius: initial;
  background: transparent;
  box-shadow: none;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-counter,
.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-source-link {
  display: none;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head {
  grid-template-columns: minmax(0, auto) auto minmax(0, 1fr);
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-caption-copy {
  grid-column: 1;
  justify-self: start;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-title-line {
  justify-content: flex-start;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-title {
  flex: 0 1 auto;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head-actions {
  grid-column: 2;
  justify-self: start;
}

html:not([data-wizon-viewport="compact"]) .image-preview-dialog[data-image-preview-scope="travel-place"][open] {
  width: min(760px, 100vw);
  height: min(540px, calc(100dvh - var(--wds-space-8)));
}

.image-preview-header-count {
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
  white-space: nowrap;
}

.image-preview-stage-control {
  position: absolute;
  z-index: var(--wizon-layer-sticky, 1);
  top: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 44px;
  block-size: 44px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--wizon-ai-surface);
  cursor: pointer;
  transform: translateY(-50%);
}

.image-preview-stage-control[hidden],
.image-preview-carousel-card[hidden] {
  display: none;
}

.image-preview-stage-control--previous {
  inset-inline-start: var(--wds-space-4);
}

.image-preview-stage-control--next {
  inset-inline-end: var(--wds-space-4);
}

.image-preview-stage-control:focus-visible {
  outline: 2px solid var(--wds-color-focus-ring);
  outline-offset: 2px;
}

.image-preview-disclosure-slot:empty {
  display: none;
}

.image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-disclosure-slot {
  box-sizing: border-box;
  min-block-size: 48px;
  border-top: 1px solid var(--wizon-ai-popover-border);
  background: var(--wizon-ai-popover-bg);
}

.image-preview-place-source-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-3);
  box-sizing: border-box;
  min-block-size: 48px;
  padding-inline: var(--wds-space-4);
  color: var(--wizon-ai-text-secondary);
  font-size: var(--wds-font-size-caption);
}

.image-preview-place-source-row > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-preview-place-source-row a {
  display: inline-flex;
  align-items: center;
  gap: var(--wds-space-1);
  color: var(--wds-color-primary);
  font-weight: var(--wds-font-weight-semibold);
  text-decoration: none;
  white-space: nowrap;
}

.image-preview-disclosure {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1.4fr) auto;
  align-items: center;
  gap: var(--wds-space-4);
  padding: var(--wds-space-3) var(--wds-space-4);
  border-top: 1px solid var(--wizon-ai-popover-border);
  background: var(--wizon-ai-popover-bg);
}

.image-preview-disclosure-heading,
.image-preview-disclosure-list,
.image-preview-disclosure-list > div {
  min-width: 0;
}

.image-preview-disclosure-heading {
  display: grid;
  gap: var(--wds-space-1);
}

.image-preview-disclosure-heading > span,
.image-preview-disclosure-list dt,
.image-preview-disclosure > p {
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-caption);
}

.image-preview-disclosure-heading strong,
.image-preview-disclosure-list dd {
  overflow: hidden;
  color: var(--wizon-ai-text-primary);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-preview-disclosure-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--wds-space-3);
  margin: 0;
}

.image-preview-disclosure-list > div {
  display: grid;
  gap: var(--wds-space-1);
}

.image-preview-disclosure-list dd {
  margin: 0;
  font-size: var(--wds-font-size-body-2);
}

.image-preview-disclosure-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--wds-space-1);
  min-height: var(--wizon-ai-action-target-touch);
  padding-inline: var(--wds-space-3);
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-control);
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-semibold);
  text-decoration: none;
}

.image-preview-disclosure-link svg {
  width: var(--wizon-ai-icon-size-md);
  height: var(--wizon-ai-icon-size-md);
}

.image-preview-disclosure > p {
  grid-column: 1 / -1;
  margin: calc(0px - var(--wds-space-2)) 0 0;
}

.image-preview-disclosure-link:focus-visible {
  outline: 2px solid var(--wizon-ai-text-primary);
  outline-offset: 2px;
}

.image-preview-pagination {
  position: absolute;
  right: 0;
  left: 0;
  top: calc(50% + min(39%, calc(var(--wizon-ai-chat-max-width) * 0.34)) + var(--wds-space-3));
  display: grid;
  place-items: center;
  min-height: var(--wds-space-5);
  pointer-events: none;
}

.image-preview-counter {
  padding: var(--wds-space-1) var(--wds-space-2);
  border-radius: var(--wizon-ai-radius-pill);
  background: color-mix(in srgb, var(--wds-black) 48%, transparent);
  color: var(--wizon-ai-surface);
  font-size: var(--wds-font-size-caption);
  font-weight: var(--wds-font-weight-semibold);
}

.image-preview-page-dots {
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}

.image-preview-page-dot {
  display: grid;
  place-items: center;
  width: var(--wds-space-5);
  height: var(--wds-space-5);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.image-preview-page-dot::before {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--wizon-ai-text-muted) 18%, transparent);
  content: "";
  transition:
    width var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease),
    height var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease),
    background-color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease);
}

.image-preview-page-dot.is-current::before {
  width: 8px;
  height: 8px;
  background: var(--wizon-ai-text-primary);
}

.image-preview-carousel {
  position: relative;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
}

.image-preview-carousel-card {
  position: absolute;
  top: 50%;
  left: var(--image-preview-rest-left, 50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--image-preview-rest-width, 22%);
  height: min(78%, calc(var(--wizon-ai-chat-max-width) * 0.68));
  min-width: 0;
  min-height: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--wizon-ai-popover-border);
  border-radius: var(--wizon-ai-radius-popover);
  background: var(--wizon-ai-popover-bg);
  box-shadow: none;
  cursor: pointer;
  opacity: var(--image-preview-rest-opacity, 0);
  pointer-events: none;
  transform: translate3d(-50%, -50%, 0) scale(var(--image-preview-rest-scale, 1));
  will-change: transform, opacity;
  transition:
    opacity var(--wizon-motion-surface-duration) var(--wizon-motion-effect-ease),
    width calc(var(--wizon-motion-panel-duration) + var(--wizon-motion-surface-duration)) var(--wds-ease-standard),
    left calc(var(--wizon-motion-panel-duration) + var(--wizon-motion-surface-duration)) var(--wds-ease-standard),
    transform calc(var(--wizon-motion-panel-duration) + var(--wizon-motion-surface-duration)) var(--wds-ease-standard),
    box-shadow calc(var(--wizon-motion-panel-duration) + var(--wizon-motion-surface-duration)) var(--wds-ease-standard);
}

.image-preview-carousel-card.is-visible {
  pointer-events: auto;
}

.image-preview-carousel-card.is-current {
  z-index: var(--wizon-layer-sticky, 1);
  pointer-events: auto;
  box-shadow: var(--wizon-ai-dialog-shadow);
}

.image-preview-carousel-card.is-wrap-jump {
  opacity: 0;
  transition: none;
}

.image-preview-carousel-card img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  object-fit: cover;
  border-radius: inherit;
  background: transparent;
  pointer-events: none;
}

.image-preview-stage.is-dragging .image-preview-carousel-card.is-current {
  left: var(--image-preview-live-left, 50%);
  width: var(--image-preview-live-width, 66%);
  opacity: var(--image-preview-live-opacity, 1);
  transform: translate3d(-50%, -50%, 0) scale(var(--image-preview-live-scale, 1));
}

.image-preview-stage.is-dragging .image-preview-carousel-card {
  left: var(--image-preview-live-left, 50%);
  width: var(--image-preview-live-width, 22%);
  opacity: var(--image-preview-live-opacity, 0);
  transform: translate3d(-50%, -50%, 0) scale(var(--image-preview-live-scale, 1));
  transition: none;
}

.image-preview-caption-copy {
  grid-column: 2;
  justify-self: center;
  display: grid;
  justify-items: center;
  gap: var(--wds-space-1);
  max-width: min(46vw, var(--wizon-ai-chat-max-width));
  min-width: 0;
  text-align: center;
}

.image-preview-title-line {
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: var(--wds-space-2);
  min-width: 0;
}

.image-preview-title {
  flex: 1 1 auto;
  margin: 0;
  overflow: hidden;
  color: var(--wizon-ai-text-primary);
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-semibold);
  line-height: var(--wds-line-height-normal);
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-preview-icon-button,
.image-preview-source-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--wizon-ai-action-target-touch);
  min-height: var(--wizon-ai-action-target-touch);
  border: 0;
  background: transparent;
  color: var(--wizon-ai-text-primary);
  opacity: 0.72;
  transition: opacity var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease);
}

.image-preview-icon-button {
  padding: 0;
  border-radius: var(--wizon-ai-radius-control);
  cursor: pointer;
}

.image-preview-mobile-back {
  display: none;
}

.image-preview-icon-button svg,
.image-preview-source-link svg {
  width: var(--wizon-ai-icon-size-md);
  height: var(--wizon-ai-icon-size-md);
}

.image-preview-source-link {
  flex: none;
  width: var(--wizon-ai-action-target-touch);
  padding: 0;
  border-radius: var(--wizon-ai-radius-control);
  text-decoration: none;
}

.chatgpt-reference-v1 .chatgpt-tooltip-host[data-tooltip-placement="bottom"] > .chatgpt-tooltip {
  top: calc(100% + var(--wds-space-2));
  left: 50%;
  transform: translateX(-50%) translateY(calc(0px - var(--wds-space-1)));
}

.chatgpt-reference-v1 .chatgpt-tooltip-host[data-tooltip-placement="bottom"][data-tooltip-open="true"] > .chatgpt-tooltip {
  transform: translateX(-50%) translateY(0);
}

.image-preview-icon-button:focus-visible,
.image-preview-source-link:focus-visible,
.image-preview-carousel-card:focus-visible,
.image-preview-page-dot:focus-visible {
  outline: 2px solid var(--wizon-ai-text-primary);
  outline-offset: 2px;
}

@media (hover: hover) {
  .image-preview-icon-button:hover,
  .image-preview-source-link:hover {
    opacity: 1;
  }

  .image-preview-carousel-card.is-before:hover {
    opacity: 0.94;
    transform: translate3d(-50%, -50%, 0) scale(0.97);
  }

  .image-preview-carousel-card.is-after:hover {
    opacity: 0.94;
    transform: translate3d(-50%, -50%, 0) scale(0.97);
  }

  .image-preview-carousel-card.is-current:hover {
    transform: translate3d(-50%, -50%, 0) scale(1.01);
  }

  .image-preview-page-dot:not(.is-current):hover::before {
    background: color-mix(in srgb, var(--wizon-ai-text-muted) 42%, transparent);
  }
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] {
  border: 0;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"][open] {
  background: color-mix(in srgb, var(--wizon-ai-text-primary) 86%, var(--wizon-ai-popover-bg));
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head {
  grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr) auto;
  padding-top: env(safe-area-inset-top, 0px);
  border-bottom-color: color-mix(in srgb, var(--wizon-ai-surface) 16%, transparent);
  background: color-mix(in srgb, var(--wizon-ai-text-primary) 86%, var(--wizon-ai-popover-bg));
  color: var(--wizon-ai-surface);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-caption-copy {
  grid-column: 2;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head-actions {
  grid-column: 3;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] :is(.image-preview-title, .image-preview-header-count, .image-preview-icon-button) {
  color: var(--wizon-ai-surface);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-source-link {
  display: none;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-stage {
  padding-inline: 0;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-pagination {
  top: auto;
  bottom: var(--wds-space-2);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-page-dot::before {
  background: color-mix(in srgb, var(--wizon-ai-surface) 32%, transparent);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-page-dot.is-current::before {
  background: var(--wizon-ai-surface);
}

html[data-wizon-viewport="compact"] .image-preview-head {
  grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr) auto;
  height: var(--wds-space-16);
  gap: var(--wds-space-4);
  min-height: var(--wds-space-16);
  padding: 0 var(--wds-space-4);
}

html[data-wizon-viewport="compact"] .image-preview-mobile-back {
  grid-column: 1;
  align-self: center;
  display: inline-flex;
}

html[data-wizon-viewport="compact"] .image-preview-caption-copy {
  grid-column: 2;
  align-self: stretch;
  justify-self: stretch;
  display: flex;
  align-items: center;
  justify-items: start;
  max-width: none;
  text-align: left;
}

html[data-wizon-viewport="compact"] .image-preview-title-line {
  justify-content: flex-start;
  align-items: center;
  width: 100%;
}

html[data-wizon-viewport="compact"] .image-preview-title {
  font-size: var(--wds-font-size-body-2);
  font-weight: 600;
  line-height: var(--wds-line-height-label, 20px);
}

html[data-wizon-viewport="compact"] .image-preview-head-actions {
  grid-column: 3;
  align-self: center;
}

html[data-wizon-viewport="compact"] .image-preview-desktop-close {
  display: none;
}

html[data-wizon-viewport="compact"] .image-preview-mobile-back,
html[data-wizon-viewport="compact"] .image-preview-source-link {
  width: var(--wizon-ai-action-target-sm);
  min-width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  min-height: var(--wizon-ai-action-target-sm);
}

html[data-wizon-viewport="compact"] .image-preview-stage {
  padding: var(--wds-space-3);
}

html[data-wizon-viewport="compact"] .image-preview-stage-control--previous {
  inset-inline-start: var(--wds-space-3);
}

html[data-wizon-viewport="compact"] .image-preview-stage-control--next {
  inset-inline-end: var(--wds-space-3);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-disclosure-slot {
  padding-bottom: env(safe-area-inset-bottom, 0px);
  border-top-color: color-mix(in srgb, var(--wizon-ai-surface) 16%, transparent);
  background: color-mix(in srgb, var(--wizon-ai-text-primary) 86%, var(--wizon-ai-popover-bg));
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-place-source-row {
  color: color-mix(in srgb, var(--wizon-ai-surface) 68%, transparent);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head {
  box-sizing: border-box;
  min-block-size: calc(56px + env(safe-area-inset-top, 0px));
  height: calc(56px + env(safe-area-inset-top, 0px));
  padding: env(safe-area-inset-top, 0px) var(--wds-space-4) 0;
}

html[data-wizon-viewport="compact"] .image-preview-disclosure {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--wds-space-2) var(--wds-space-3);
  padding: var(--wds-space-3) var(--wds-space-4) var(--wds-space-4);
}

html[data-wizon-viewport="compact"] .image-preview-disclosure-heading,
html[data-wizon-viewport="compact"] .image-preview-disclosure-list {
  grid-column: 1 / -1;
}

html[data-wizon-viewport="compact"] .image-preview-disclosure-link {
  grid-column: 2;
  grid-row: 3 / span 2;
  align-self: end;
}

html[data-wizon-viewport="compact"] .image-preview-disclosure > p {
  grid-column: 1;
  margin: 0;
}

html[data-wizon-viewport="compact"] .image-preview-pagination {
  top: calc(50% + min(20vw, 120px) + var(--wds-space-3));
}

html[data-wizon-viewport="compact"] .image-preview-carousel-card {
  height: min(40vw, 240px);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-carousel-card.is-current {
  height: min(64vw, 360px);
}

html[data-wizon-viewport="compact"] .image-preview-source-link {
  align-self: center;
}

@media (prefers-reduced-motion: reduce) {
  .image-preview-dialog[open],
  .image-preview-dialog::backdrop,
  .image-preview-carousel-card,
  .image-preview-page-dot::before {
    transition: none;
  }
}

/* RC22 · Common Media Viewer
   One full-screen media surface is shared by travel-place and generic visual answers.
   Controls float above the media so the image remains the first visual layer. */
.image-preview-dialog[open] {
  inset: 0;
  width: 100vw;
  height: 100dvh;
  margin: 0;
  border-radius: 0;
  background: #08090b;
  color: #fff;
  box-shadow: none;
  transform: none;
}

html:not([data-wizon-viewport="compact"]) .image-preview-dialog[data-image-preview-scope="travel-place"][open] {
  width: 100vw;
  height: 100dvh;
}

.image-preview-dialog::backdrop,
html[data-theme="dark"] .image-preview-dialog::backdrop {
  background: rgb(0 0 0 / 78%);
}

.image-preview-dialog[data-motion-state="open"],
.image-preview-dialog[data-motion-state="closing"] {
  transform: none;
}

.image-preview-shell {
  display: block;
  background: #08090b;
}

.image-preview-dialog[open] .image-preview-head {
  position: absolute;
  z-index: 4;
  inset: 0 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  min-height: 72px;
  padding: 16px 16px 16px 28px;
  border: 0;
  background: linear-gradient(180deg, rgb(8 9 11 / 92%) 0%, rgb(8 9 11 / 0%) 100%);
  color: #fff;
  pointer-events: none;
}

.image-preview-dialog[open] .image-preview-caption-copy {
  grid-column: 1;
  justify-self: start;
  align-self: start;
  max-width: min(60vw, 720px);
  color: #fff;
  text-align: left;
  pointer-events: auto;
}

.image-preview-dialog[open] .image-preview-title-line {
  justify-content: flex-start;
  align-items: center;
  min-height: 48px;
}

.image-preview-dialog[open] .image-preview-title {
  color: #fff;
  font-size: var(--wds-font-size-body-2);
  font-weight: var(--wds-font-weight-semibold);
}

.image-preview-dialog[open] .image-preview-header-count {
  color: rgb(255 255 255 / 68%);
}

.image-preview-dialog[open] .image-preview-head-actions {
  grid-column: 2;
  justify-self: end;
  align-self: start;
  gap: 8px;
  pointer-events: auto;
}

.image-preview-dialog[open] .image-preview-icon-button {
  width: 48px;
  min-width: 48px;
  height: 48px;
  min-height: 48px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #fff;
  opacity: 0.88;
  backdrop-filter: none;
}

.image-preview-dialog[open] .image-preview-mobile-back {
  display: none;
}

.image-preview-dialog[open] .image-preview-stage {
  position: absolute;
  inset: 0;
  display: block;
  padding: 84px 92px 72px;
  overflow: hidden;
  background: #08090b;
  cursor: zoom-in;
  touch-action: none;
}

.image-preview-dialog[data-image-preview-zoomed="true"] .image-preview-stage {
  cursor: grab;
}

.image-preview-dialog[data-image-preview-zoomed="true"] .image-preview-stage.is-panning {
  cursor: grabbing;
}

.image-preview-dialog[open] .image-preview-carousel {
  width: 100%;
  height: 100%;
}

.image-preview-dialog[open] .image-preview-carousel-card,
.image-preview-dialog[open] .image-preview-carousel-card.is-current,
.image-preview-dialog[open][data-image-preview-scope="travel-place"] .image-preview-carousel-card.is-current {
  position: absolute;
  inset: 0;
  display: none;
  width: 100%;
  height: 100%;
  padding: 0;
  overflow: visible;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  opacity: 0;
  pointer-events: none;
  transform: none;
  transition: none;
}

.image-preview-dialog[open] .image-preview-carousel-card.is-current,
.image-preview-dialog[open][data-image-preview-scope="travel-place"] .image-preview-carousel-card.is-current {
  display: flex;
  opacity: 1;
  pointer-events: auto;
}

.image-preview-dialog[open] .image-preview-media {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  border: 0;
  border-radius: 0;
  background: transparent;
  object-fit: contain;
  pointer-events: auto;
  transform:
    translate3d(var(--image-preview-pan-x, 0), var(--image-preview-pan-y, 0), 0)
    scale(var(--image-preview-scale, 1));
  transform-origin: center;
  transition: transform 120ms var(--wizon-motion-effect-ease);
  user-select: none;
  will-change: transform;
}

.image-preview-dialog[open] .image-preview-media--video {
  min-width: min(920px, 72vw);
  background: #000;
}

.image-preview-dialog[open] .image-preview-stage.is-panning .image-preview-media,
.image-preview-dialog[open] .image-preview-stage.is-dragging .image-preview-media {
  transition: none;
}

.image-preview-dialog[open] .image-preview-pagination {
  display: none;
}

.image-preview-dialog[open] .image-preview-stage-control {
  z-index: 3;
  width: 52px;
  height: 52px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #fff;
  opacity: 0.88;
  backdrop-filter: none;
  transition: opacity var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease);
}

.image-preview-dialog[open] .image-preview-stage-control--previous {
  inset-inline-start: 24px;
}

.image-preview-dialog[open] .image-preview-stage-control--next {
  inset-inline-end: 24px;
}

.image-preview-zoom-controls {
  position: absolute;
  z-index: 4;
  right: 24px;
  bottom: 72px;
  display: grid;
  width: 52px;
  overflow: hidden;
  border: 1px solid rgb(255 255 255 / 12%);
  border-radius: 26px;
  background: rgb(16 18 22 / 76%);
  color: #fff;
  backdrop-filter: blur(12px);
}

.image-preview-zoom-button {
  display: inline-grid;
  place-items: center;
  width: 52px;
  min-height: 52px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.image-preview-zoom-value {
  display: grid;
  place-items: center;
  width: 52px;
  min-height: 36px;
  border-block: 1px solid rgb(255 255 255 / 10%);
  color: rgb(255 255 255 / 72%);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  pointer-events: none;
}

.image-preview-zoom-button svg {
  width: 20px;
  height: 20px;
}

.image-preview-zoom-button:disabled {
  color: rgb(255 255 255 / 28%);
  cursor: default;
}

.image-preview-dialog[data-image-preview-media-type="video"] .image-preview-zoom-controls {
  display: none;
}

.image-preview-dialog[open] .image-preview-disclosure-slot {
  position: absolute;
  z-index: 4;
  top: var(--image-preview-source-top, 0);
  right: auto;
  bottom: auto;
  left: var(--image-preview-source-left, 0);
  display: block;
  width: var(--image-preview-source-width, 0);
  max-width: none;
  min-height: 40px;
  padding: 0;
  border: 0;
  background: transparent;
  color: rgb(255 255 255 / 66%);
  pointer-events: auto;
  visibility: hidden;
}

.image-preview-dialog[open] .image-preview-disclosure-slot[data-image-preview-source-positioned="true"] {
  visibility: visible;
}

.image-preview-dialog[open] .image-preview-source-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-3);
  width: 100%;
  min-height: 40px;
  padding: var(--wds-space-2) 0;
  border: 0;
  background: transparent;
  font-size: var(--wds-font-size-caption);
  line-height: 1.4;
}

.image-preview-dialog[open] .image-preview-source-link-text {
  display: flex;
  align-items: center;
  align-self: stretch;
  min-width: 0;
  color: rgb(255 255 255 / 66%);
  text-decoration: none;
  transition: color var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease);
}

.image-preview-dialog[open] .image-preview-source-link-text--static {
  cursor: default;
}

.image-preview-dialog[open] .image-preview-source-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.image-preview-dialog[open] .image-preview-source-share {
  display: inline-grid;
  flex: none;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: #fff;
  cursor: pointer;
  opacity: 0.88;
  transition: opacity var(--wizon-motion-micro-duration) var(--wizon-motion-effect-ease);
}

.image-preview-dialog[open] .image-preview-source-share svg {
  width: 18px;
  height: 18px;
}

.image-preview-gesture-hint {
  display: none;
}

.image-preview-dialog[open] :is(
  .image-preview-icon-button,
  .image-preview-stage-control,
  .image-preview-zoom-button,
  .image-preview-source-link-text,
  .image-preview-source-share
):focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

@media (hover: hover) {
  .image-preview-dialog[open] :is(
    .image-preview-icon-button,
    .image-preview-stage-control,
    .image-preview-source-share
  ):hover {
    opacity: 1;
  }

  .image-preview-dialog[open] .image-preview-source-link-text:hover {
    color: #fff;
  }

  .image-preview-dialog[open] .image-preview-zoom-button:not(:disabled):hover {
    background: rgb(36 39 46 / 72%);
  }

  .image-preview-dialog[open] .image-preview-carousel-card.is-current:hover {
    transform: none;
  }
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open],
html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"][open] {
  width: 100vw;
  height: 100dvh;
  background: #08090b;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-head,
html[data-wizon-viewport="compact"] .image-preview-dialog[data-image-preview-scope="travel-place"] .image-preview-head {
  grid-template-columns: 44px minmax(0, 1fr) auto;
  box-sizing: border-box;
  height: calc(100px + env(safe-area-inset-top, 0px));
  min-height: calc(100px + env(safe-area-inset-top, 0px));
  padding: calc(44px + env(safe-area-inset-top, 0px)) 8px 0;
  border: 0;
  background: linear-gradient(180deg, rgb(8 9 11 / 96%) 0%, rgb(8 9 11 / 0%) 100%);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-mobile-back {
  grid-column: 1;
  display: inline-flex;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-caption-copy {
  grid-column: 2;
  align-self: start;
  padding-inline: 8px;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-head-actions {
  grid-column: 3;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-desktop-close {
  display: inline-flex;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] :is(
  .image-preview-icon-button
) {
  width: 44px;
  min-width: 44px;
  height: 44px;
  min-height: 44px;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-stage {
  padding: calc(112px + env(safe-area-inset-top, 0px)) 0 calc(130px + env(safe-area-inset-bottom, 0px));
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-stage-control {
  display: none;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-media {
  max-width: 100%;
  max-height: 100%;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open][data-image-preview-scope="travel-place"] .image-preview-carousel-card.is-current {
  width: 100%;
  height: 100%;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-media--video {
  min-width: 100%;
}

html[data-wizon-viewport="compact"] .image-preview-zoom-controls {
  right: 12px;
  bottom: calc(150px + env(safe-area-inset-bottom, 0px));
  width: 48px;
  border-radius: 24px;
}

html[data-wizon-viewport="compact"] .image-preview-zoom-button {
  width: 48px;
  min-height: 48px;
}

html[data-wizon-viewport="compact"] .image-preview-zoom-value {
  width: 48px;
  min-height: 36px;
  font-size: 10px;
}

html[data-wizon-viewport="compact"] .image-preview-gesture-hint {
  position: absolute;
  z-index: 3;
  bottom: calc(104px + env(safe-area-inset-bottom, 0px));
  left: 50%;
  display: block;
  min-width: 172px;
  margin: 0;
  padding: 9px 14px;
  border-radius: var(--ds-radius-pill, 999px);
  background: rgb(16 18 22 / 72%);
  color: rgb(255 255 255 / 88%);
  font-size: 12px;
  font-weight: var(--wds-font-weight-medium);
  text-align: center;
  transform: translateX(-50%);
  pointer-events: none;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-disclosure-slot {
  min-height: 44px;
  padding-bottom: 0;
  border: 0;
  background: transparent;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-source-row {
  min-height: 44px;
  padding: 0;
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-source-link-text {
  padding-inline-start: var(--wds-space-4);
}

html[data-wizon-viewport="compact"] .image-preview-dialog[open] .image-preview-source-share {
  width: 44px;
  height: 44px;
}

@media (prefers-reduced-motion: reduce) {
  .image-preview-dialog[open] .image-preview-media {
    transition: none;
  }
}


/* ---- Sources pill + drawer (20260709) ----
   접힌 요약(파비콘 클러스터+출처 N) → 드로어 근거(카드 리스트) → 원문 링크 세부, doc 82의
   요약→근거→세부 순서. 데스크톱=우측 슬라이드 오버, 모바일=2-detent 바텀시트(ChatGPT 패리티). */
.source-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 7px;
  border: 1px solid var(--cg-menu-border, rgba(13, 13, 13, 0.08));
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-bg, #ffffff);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  color: var(--cg-text-soft, #5d5d5d);
  cursor: pointer;
  transition: background var(--wds-duration-fast) ease, border-color var(--wds-duration-fast) ease;
}
.source-pill:hover {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.04));
  border-color: var(--cg-menu-border, rgba(13, 13, 13, 0.14));
}
.source-pill:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, #0d0d0d);
  outline-offset: 2px;
}
.travel-guidebook-card .source-pill {
  min-height: 44px;
}
.source-pill-favs {
  display: inline-flex;
  align-items: center;
}
/* Overlapping favicon cluster — circular, ring-separated (Perplexity/ChatGPT pattern). */
.source-pill-favs .news-fav {
  border-radius: var(--ds-radius-pill, 999px);
  box-shadow: 0 0 0 2px var(--cg-bg, #ffffff);
}
.source-pill-favs .news-fav + .news-fav {
  margin-left: -5px;
}
/* "+N" overflow — a solid ink pill (not the old low-contrast gray that read as barely legible),
   set apart from the favicons rather than overlapping them so the number is clear. */
.source-pill-more {
  display: grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  margin-left: 5px;
  padding: 0 5px;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-text, #0d0d0d);
  font-size: 10px;
  font-weight: 600;
  color: var(--cg-bg, #ffffff);
}
.source-pill-label {
  font-weight: 500;
}
.source-pill-row {
  margin-top: 10px;
}
.memory-use-rationale-shadow {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 10px;
  padding: 9px 11px;
  border: 1px solid color-mix(in srgb, var(--ad-blue) 20%, transparent);
  border-radius: var(--ds-radius-md, 10px);
  background: color-mix(in srgb, var(--ad-blue) 5%, transparent);
  color: var(--cg-text);
  font-size: var(--cg-text-meta-size);
  line-height: 1.45;
}
.memory-use-rationale-shadow__icon,
.memory-use-rationale-shadow__icon .wds-inline-icon {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  color: var(--ad-blue);
}
.memory-use-rationale-shadow__copy {
  display: grid;
  gap: 1px;
  min-width: 0;
}
.memory-use-rationale-shadow__copy strong {
  font-size: var(--cg-text-meta-size);
  font-weight: var(--cg-text-label-active-weight);
}
.memory-use-rationale-shadow__copy > span {
  color: var(--cg-text-soft);
}
.memory-use-rationale-shadow__version {
  flex: 0 0 auto;
  margin-left: auto;
  color: var(--cg-text-soft);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
@media (max-width: 520px) {
  .memory-use-rationale-shadow {
    align-items: flex-start;
  }
  .memory-use-rationale-shadow__version {
    display: none;
  }
}
/* Doc-source avatars (Phase 4 RAG): a document glyph stands in for the favicon on the pill,
   drawer card, and inline citation chip. */
.source-pill-doc {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--cg-text-soft, #5d5d5d);
}
.source-pill-doc .wds-inline-icon {
  width: 15px;
  height: 15px;
}
.citation-ref-doc {
  display: inline-flex;
}
.citation-ref-doc .wds-inline-icon {
  width: 12px;
  height: 12px;
}
/* Inline citation chip — a source-colored number + that source's favicon (user request: color-
   code the number, show the favicon instead of a raw URL). Deep-links to the drawer card. */
.citation-ref {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 17px;
  margin: 0 2px;
  padding: 0 5px 0 4px;
  vertical-align: baseline;
  transform: translateY(-1px);
  border: 1px solid color-mix(in srgb, var(--cite-color, #5d5d5d) 30%, transparent);
  border-radius: var(--ds-radius-pill, 999px);
  background: color-mix(in srgb, var(--cite-color, #5d5d5d) 10%, transparent);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background var(--wds-duration-fast) ease, border-color var(--wds-duration-fast) ease;
}
.citation-ref-num {
  color: var(--cite-color, #5d5d5d);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
}
.citation-ref-fav {
  width: 12px;
  height: 12px;
  border-radius: var(--ds-radius-2xs, 3px);
  object-fit: contain;
}
.citation-ref:hover {
  background: color-mix(in srgb, var(--cite-color, #5d5d5d) 20%, transparent);
  border-color: color-mix(in srgb, var(--cite-color, #5d5d5d) 55%, transparent);
}
.citation-ref:focus-visible {
  outline: 2px solid var(--cite-color, var(--cg-focus-visible-ring, #0d0d0d));
  outline-offset: 1px;
}
/* Paragraph-end source tag (doc 161 P2-1): ChatGPT-style neutral pill at the end of a
   paragraph/list item — favicon(s) or doc glyph + source name (+N). Replaces the inline
   numbered chips of that block; table cells keep the compact chips. */
.citation-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 20px;
  margin: 0 0 0 6px;
  padding: 0 8px 0 4px;
  /* The tag (20px) is taller than the body text, so a tall inline box needs an explicit vertical
     anchor. vertical-align:middle centers it on the parent's x-height (baseline + x-height/2).
     The nudge is NOT eyeballed: it's the measured gap between the font's Korean-ink optical center
     and that x-height midpoint — (5.64px − 4.24px) / 16px ≈ 0.088em for Pretendard. Being a font
     metric (em, not px), it holds for every sentence and every text size (verified: <0.02px off,
     <0.01px drift across content/size). doc 164 §후속4. */
  vertical-align: middle;
  transform: translateY(-0.088em);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-hover-soft, var(--surface-2));
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background var(--wds-duration-fast) ease, border-color var(--wds-duration-fast) ease;
}
.citation-tag:hover {
  background: var(--cg-hover, var(--surface-2));
  border-color: var(--cg-muted, var(--muted));
}
/* doc 161 §7 B3: document source tags read as blue-tint pills everywhere (Blue = 문서 축);
   web tags stay neutral + colored favicon. Unifies the small-tag radius/color language. */
.citation-tag[data-kind="doc"] {
  border-color: color-mix(in srgb, var(--ad-blue) 16%, transparent);
  background: var(--ad-blue-tint);
}
.citation-tag[data-kind="doc"] .citation-tag-name {
  color: var(--ad-blue);
}
.citation-tag[data-kind="doc"] .citation-tag-doc {
  color: var(--ad-blue);
}
.citation-tag[data-kind="doc"]:hover {
  background: var(--ad-blue-tint);
  border-color: color-mix(in srgb, var(--ad-blue) 38%, transparent);
}
.citation-tag:focus-visible {
  /* Strong solid ring — the faint --cg-focus-ring (16% alpha) fails 3:1 and would be a
     downgrade from the saturated ring of the .citation-ref chips this tag replaces. */
  outline: 2px solid var(--cg-text, #0d0d0d);
  outline-offset: 1px;
}
.citation-tag-favs {
  display: inline-flex;
  align-items: center;
}
.citation-tag-favs > * + * {
  margin-left: -4px;
}
.citation-tag-fav {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  box-shadow: 0 0 0 1.5px var(--cg-surface, #fff);
}
.citation-tag-doc {
  display: inline-flex;
  color: var(--cg-text-soft, var(--muted));
}
.citation-tag-doc .wds-inline-icon {
  width: 13px;
  height: 13px;
}
.citation-tag-name {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
}
.citation-tag-more {
  color: var(--cg-text-soft, var(--muted));
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}
/* Citation drift is attached only to the rendered claim block that owns the affected source.
   The comparison itself stays server-side; this surface carries status + safe source indices only. */
.has-citation-drift {
  border-radius: var(--ds-radius-sm, 8px);
  background: color-mix(in srgb, var(--cg-warning-fg) 8%, transparent);
  box-shadow: inset 3px 0 0 color-mix(in srgb, var(--cg-warning-fg) 78%, transparent);
}
.has-citation-drift--missing {
  background: color-mix(in srgb, var(--cg-danger-fg) 7%, transparent);
  box-shadow: inset 3px 0 0 color-mix(in srgb, var(--cg-danger-fg) 78%, transparent);
}
.citation-drift-notice {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-left: 6px;
  vertical-align: middle;
  color: var(--cg-warning-fg);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
}
.citation-drift-notice[data-tone="danger"] {
  color: var(--cg-danger-fg);
}
.citation-drift-label {
  white-space: nowrap;
}
.citation-drift-regenerate {
  min-height: 24px;
  padding: 2px 7px;
  border: 1px solid currentColor;
  border-radius: var(--ds-radius-pill, 999px);
  background: var(--cg-surface, var(--surface));
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.citation-drift-regenerate:hover:not(:disabled) {
  background: color-mix(in srgb, currentColor 9%, var(--cg-surface, var(--surface)));
}
.citation-drift-regenerate:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}
.citation-drift-regenerate:disabled {
  cursor: progress;
  opacity: 0.68;
}
.citation-drift-notice.is-reviewed {
  color: var(--cg-success);
}
.citation-revision-applied {
  display: grid;
  gap: var(--wds-space-1);
  margin: var(--wds-space-2) 0;
  padding: var(--wds-space-3) var(--wds-space-4);
  border-left: 3px solid var(--cg-success);
  border-radius: var(--ds-radius-sm);
  background: var(--ad-green-tint);
}
.citation-revision-applied > strong {
  color: var(--cg-success);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-semibold);
}
.citation-revision-applied > p {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  line-height: var(--wds-line-height-normal);
  overflow-wrap: anywhere;
}
.citation-health-focus {
  box-shadow: inset 0 0 0 2px var(--cg-focus-visible-ring);
}

/* Conversation-level evidence health reuses the trust dock. It contains only answer text and
   safe ordinals; document/version references remain in JS state and the authorized API lane. */
.citation-health-summary {
  display: grid;
  gap: var(--wds-space-4);
  padding: var(--wds-space-5);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-lg);
  background: var(--ad-blue-tint);
}
.citation-health-summary[data-status="attention"] {
  background: var(--ad-amber-tint);
}
.citation-health-summary[data-status="approval"] {
  border-color: var(--ad-blue);
  background: var(--ad-blue-tint);
}
.citation-health-summary[data-status="reviewed"] {
  background: var(--ad-green-tint);
}
.citation-health-summary[data-status="unavailable"] {
  border-color: var(--cg-danger-fg);
  background: var(--cg-hover-soft);
}
.citation-health-summary-copy {
  display: grid;
  gap: var(--wds-space-1);
}
.citation-health-summary-copy > span {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-medium);
}
.citation-health-summary-copy > strong {
  color: var(--cg-text);
  font-size: var(--ds-text-title-18);
  font-weight: var(--wds-font-weight-semibold);
}
.citation-health-summary-copy > p,
.citation-health-result {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: var(--wds-line-height-normal);
}
.citation-health-counts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--wds-space-2);
}
.citation-health-counts > span {
  display: grid;
  gap: var(--wds-space-1);
  padding: var(--wds-space-3);
  border-radius: var(--ds-radius-sm);
  background: var(--cg-surface);
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
  text-align: center;
}
.citation-health-counts strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
}
.citation-health-actions,
.citation-health-claim-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--wds-space-2);
}
.citation-health-actions button,
.citation-health-claim-actions button {
  min-height: var(--wizon-ai-action-target-sm);
  padding: var(--wds-space-2) var(--wds-space-3);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-medium);
  cursor: pointer;
}
.citation-health-actions button:hover:not(:disabled),
.citation-health-claim-actions button:hover:not(:disabled) {
  background: var(--cg-hover);
}
.citation-health-actions button:focus-visible,
.citation-health-claim-actions button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring);
  outline-offset: 2px;
}
.citation-health-actions button:disabled,
.citation-health-claim-actions button:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}
.citation-health-actions .citation-health-primary {
  border-color: var(--cg-send-bg);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}
.citation-health-list {
  display: grid;
  gap: var(--wds-space-3);
}

.citation-recovery-steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--wds-space-2);
  margin: var(--wds-space-3) 0;
  padding: 0;
  list-style: none;
}

.citation-recovery-steps li {
  display: grid;
  justify-items: center;
  gap: var(--wds-space-1);
  min-width: 0;
  padding: var(--wds-space-3) var(--wds-space-2);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-md);
  background: var(--cg-surface);
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
  text-align: center;
}

.citation-recovery-steps li > span {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-hover-soft);
  font-weight: var(--wds-font-weight-semibold);
}

.citation-recovery-steps li[data-status="current"] {
  border-color: var(--ad-blue);
  color: var(--ad-blue);
  background: var(--ad-blue-tint);
}

.citation-recovery-steps li[data-status="complete"] {
  color: var(--cg-success);
  background: var(--ad-green-tint);
}

.citation-impact-review-list {
  display: grid;
  gap: 10px;
  margin-top: 12px;
}

.citation-impact-review-item {
  display: grid;
  gap: 12px;
  padding: 14px;
  border: 1px solid color-mix(in srgb, currentColor 12%, transparent);
  border-radius: var(--wizon-ai-menu-radius);
  background: color-mix(in srgb, var(--ad-amber) 5%, transparent);
}

.citation-impact-review-item__copy {
  min-width: 0;
  display: grid;
  gap: 4px;
}

.citation-impact-review-item__copy strong {
  overflow: hidden;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  line-height: 20px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.citation-impact-review-item__copy small,
.citation-impact-review-item__copy p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: 18px;
}

.citation-impact-review-item__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.citation-impact-review-item__actions button {
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid color-mix(in srgb, currentColor 16%, transparent);
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}

.citation-impact-review-item__actions button:disabled {
  cursor: default;
  opacity: 0.5;
}
.citation-health-claim {
  display: grid;
  gap: var(--wds-space-3);
  padding: var(--wds-space-4);
  border: 1px solid var(--cg-menu-border);
  border-left-color: var(--cg-warning-fg);
  border-radius: var(--ds-radius-md);
  background: var(--cg-surface);
}
.citation-health-claim[data-status="missing"] {
  border-left-color: var(--cg-danger-fg);
}
.citation-health-claim[data-status="approval"] {
  border-left-color: var(--ad-blue);
}
.citation-health-claim.is-reviewed {
  border-left-color: var(--cg-success);
}
.citation-health-claim > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-2);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
.citation-health-claim > header strong {
  color: var(--cg-warning-fg);
  font-weight: var(--wds-font-weight-semibold);
}
.citation-health-claim[data-status="missing"] > header strong {
  color: var(--cg-danger-fg);
}
.citation-health-claim[data-status="approval"] > header strong {
  color: var(--ad-blue);
}
.citation-health-claim.is-reviewed > header strong {
  color: var(--cg-success);
}
.citation-health-claim > p {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  line-height: var(--wds-line-height-normal);
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
.citation-health-empty {
  display: grid;
  justify-items: center;
  gap: var(--wds-space-2);
  padding: var(--wds-space-8) var(--wds-space-4);
  color: var(--cg-muted);
  text-align: center;
}
.citation-health-empty > span,
.citation-health-empty > span svg {
  width: 28px;
  height: 28px;
}
.citation-health-empty > strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
}
.citation-health-empty > p {
  margin: 0;
  font-size: var(--ds-text-caption-12);
}
.citation-revision-head {
  display: grid;
  gap: var(--wds-space-2);
  padding: var(--wds-space-4);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-md);
  background: var(--ad-blue-tint);
}
.citation-revision-head > span,
.citation-revision-head > p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: var(--wds-line-height-normal);
}
.citation-revision-head > strong {
  color: var(--ad-blue);
  font-size: var(--ds-text-title-18);
  font-weight: var(--wds-font-weight-semibold);
}
.citation-revision-head[data-status="accepted"] {
  background: var(--ad-green-tint);
}
.citation-revision-head[data-status="accepted"] > strong {
  color: var(--cg-success);
}
.citation-revision-head[data-status="rejected"] {
  background: var(--cg-hover-soft);
}
.citation-revision-head[data-status="rejected"] > strong {
  color: var(--cg-muted);
}
.citation-revision-compare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--wds-space-3);
  margin-top: var(--wds-space-4);
}
.citation-revision-compare > section {
  display: grid;
  align-content: start;
  gap: var(--wds-space-3);
  min-width: 0;
  padding: var(--wds-space-4);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-md);
  background: var(--cg-surface);
}
.citation-revision-compare > .citation-revision-candidate {
  border-color: var(--ad-blue);
  background: var(--ad-blue-tint);
}
.citation-revision-compare header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--wds-space-2);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-semibold);
}
.citation-revision-compare header small {
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
  font-weight: var(--wds-font-weight-regular);
}
.citation-revision-compare p {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  line-height: var(--wds-line-height-normal);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.citation-revision-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--wds-space-2);
  margin-top: var(--wds-space-4);
}
.citation-revision-actions button {
  min-height: var(--wizon-ai-action-target-sm);
  padding: var(--wds-space-2) var(--wds-space-4);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-medium);
  cursor: pointer;
}
.citation-revision-actions button:hover:not(:disabled) {
  background: var(--cg-hover);
}
.citation-revision-actions button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring);
  outline-offset: 2px;
}
.citation-revision-actions button:disabled {
  cursor: wait;
  opacity: 0.6;
}
.citation-revision-actions .citation-health-primary {
  border-color: var(--cg-send-bg);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}
.citation-revision-decision {
  margin: var(--wds-space-4) 0 0;
  padding: var(--wds-space-3) var(--wds-space-4);
  border-radius: var(--ds-radius-sm);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  line-height: var(--wds-line-height-normal);
}
@media (max-width: 520px) {
  .citation-drift-notice {
    margin: 6px 0 0;
  }
  .citation-health-counts {
    grid-template-columns: 1fr;
  }
  .citation-health-actions,
  .citation-health-claim-actions,
  .citation-revision-actions {
    display: grid;
  }
  .citation-health-actions button,
  .citation-health-claim-actions button,
  .citation-revision-actions button {
    width: 100%;
  }
  .citation-revision-compare {
    grid-template-columns: 1fr;
  }
  .citation-recovery-steps {
    grid-template-columns: 1fr;
  }
}
/* Citation hover preview (Phase 3, desktop) — a pointer-transparent floating card that peeks
   the source on hover/focus without opening the drawer. Positioned in JS; fixed to the
   viewport. Touch devices never trigger it (fine-pointer + hover gated in JS). */
.citation-preview {
  position: fixed;
  z-index: 210;
  width: min(320px, calc(100vw - 24px));
  padding: 8px;
  border: 1px solid var(--cg-menu-border, rgba(13, 13, 13, 0.1));
  border-radius: var(--ds-radius-md, 14px);
  background: var(--cg-surface);
  color: var(--cg-text);
  box-shadow: 0 14px 40px rgba(13, 13, 13, 0.18);
  /* doc 161 §7 B4: the preview is now interactive (← → pager) — clickable, kept open while
     hovered via a hide grace period. Touch never triggers it (fine-pointer gated in JS). */
  pointer-events: auto;
}
.citation-preview[hidden] {
  display: none;
}
/* Card body reuses .source-card-v2 (same anatomy as drawer/panel). Strip its own shadow here —
   the preview frame supplies the surround. */
.citation-preview .citation-preview-card {
  padding: 8px 6px 6px;
  box-shadow: none;
}
.citation-preview .citation-preview-card:hover {
  box-shadow: none;
}
/* ← → n/m pager: only when a tag covers multiple sources. */
.citation-preview-pager {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px 6px;
}
.citation-preview-nav {
  display: inline-grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--cg-text-soft, var(--muted));
  cursor: pointer;
}
.citation-preview-nav:hover {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.06));
}
.citation-preview-nav:focus-visible {
  outline: 2px solid var(--cg-focus-ring, var(--accent));
  outline-offset: 1px;
}
.citation-preview-nav .wds-inline-icon {
  width: 16px;
  height: 16px;
}
.citation-preview-count {
  margin-left: auto;
  color: var(--cg-muted, var(--muted));
  font-size: var(--ds-text-micro-11);
  font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) {
  .source-pill {
    transition: none;
  }
}
/* 템플릿은 1512폭에 4열이다. 답변 안의 카드는 그만큼 넓을 수 없으므로 3 → 2 → 1열로 접는다.
   기준은 뷰포트가 아니라 컨테이너 쿼리, 즉 피드 «자신의» 폭이다 — 같은 화면에서도 사이드
   패널이 열리면 폭이 달라지고 카드가 따라 접혀야 한다. 그래서 정본 폭 분기점(520/521/900/901)
   래칫의 대상이 아니다. ★이 주석에 뷰포트 앳룰 이름을 글자 그대로 적지 말 것:
   test_design_system_contract의 스캐너는 주석을 걷어내지 않고 `@med` + `[^{]*` 로 훑기 때문에
   주석 안의 그 단어가 아래 컨테이너 쿼리까지 삼켜 620을 «비정본 분기점»으로 오검출한다. */
@container (max-width: 620px) {
  .news-cards {
    grid-auto-columns: calc((100% - 16px) / 2);
  }
  /* 행 흐름일 때의 열 수도 폭을 따라간다. ★줄 수는 건드리지 않는다. */
  .news-cards:not(:has(> .news-card:nth-child(5))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* ★여기 있던 `.news-card:last-child:nth-child(odd) { grid-column: span 2 }`는 사라졌다.
   그 예외는 «3의 배수가 2열에서는 홀수일 수 있다»는, 세로 격자에서만 생기던 문제를 메우던
   규칙이다. 이제 줄 수가 폭과 무관하게 2로 고정이라 pickNewsHeroCount의 짝수 역산 하나로
   모든 폭에서 마지막 열이 채워지고, 메울 구멍 자체가 없다. */
@container (max-width: 380px) {
  .news-cards {
    grid-auto-columns: 100%;
    gap: 18px;
  }
  .news-cards:not(:has(> .news-card:nth-child(5))) {
    grid-template-columns: minmax(0, 1fr);
  }
  /* ★두 칸을 380px에 나란히 두면 칸당 ~180px이라 제목이 2줄 상한을 넘어 잘린다. 카드가
     1열로 접히는 것과 같은 폭에서 2단도 한 줄로 쌓는다. */
  .news-second {
    grid-template-columns: 1fr;
  }
  .news-lead {
    aspect-ratio: 4 / 3;
  }
  .news-lead-band {
    inset-inline: 10px;
    bottom: 10px;
    padding: 12px 13px;
  }
}
/* ★모션은 정보를 나르지 않는다 — 전부 꺼도 캐러셀은 «즉시» 그 슬라이드로 간다(위치는
   data-news-hero-index가 이미 정한다). 확대·부양은 장식이라 그대로 사라진다. */
@media (prefers-reduced-motion: reduce) {
  .news-hero-track,
  .news-hero-nav,
  .news-topic,
  .news-arrow,
  .news-bookmark,
  .news-dot,
  .news-thumb {
    transition: none;
  }
  .news-topics-rail {
    scroll-behavior: auto;
  }
  .news-topic:hover {
    transform: none;
  }
  /* none이 아니라 기본값으로 되돌린다 — 이 버튼의 transform은 «수직 중앙»이라는 레이아웃이지
     모션이 아니다. none으로 지우면 화살표가 아래로 반쯤 내려간다. */
  .news-hero-nav:hover {
    transform: translateY(-50%);
  }
  .news-card:hover .news-card-img,
  .news-lead:hover .news-lead-img {
    transform: none;
  }
}

/* 20260709-mobile-keyboard-fix: validated on the iOS Simulator (real WebKit + soft
   keyboard). Pin the shell to the visual viewport so the topbar stays fixed and the
   composer rides just above the keyboard instead of the page scrolling up. The
   offsetTop compensation (--wizon-vv-offset-top, written by syncMobileViewportMetrics
   in app.js) is essential on iOS: when the keyboard opens iOS scrolls the layout
   viewport, so a fixed shell must translate down by offsetTop to stay aligned with the
   visible area — without it the composer flies to the top of the screen. Both vars fall
   back to 100dvh before the first visualViewport event. Scoped to <=900px so desktop
   keeps the global 100dvh chain (styles.css:8707) untouched. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .app-shell {
    position: fixed;
    left: 0;
    top: var(--wizon-vv-offset-top, 0px);
    width: 100%;
    /* 20260803-shell-height-clamp — **믿지 말고 조인다.**
     *
     * ★실기기 실측(2026-08-03): 가로에서 컴포저 기본 액션이 잘리고 스크롤로도 닿지 않았다.
     *   셸이 뷰포트(292)보다 크게 잡히는데 overflow: hidden이라 넘친 아래가 사라진다.
     *   데스크톱 브라우저에서는 --wizon-vvh가 888로 낡은 것을 실제로 봤다.
     *
     * ★JS 값이 «언제 정착하는가»에 기대는 설계가 애초에 약했다. orientationchange 재동기화를
     *   먼저 넣어 봤지만 실기기에서 증상이 그대로였다 — 이벤트 타이밍을 맞추는 방향으로는
     *   닫히지 않는다. 그래서 «값을 못 믿어도 안전한» 모양으로 바꾼다.
     *
     * ★svh는 **브라우저 크롬을 뺀 보장 가시 높이**다(업계 권고: 레이아웃은 svh 기본, dvh는
     *   근거 있을 때만). min()으로 조이면 세 경우가 모두 옳다:
     *     · 값이 신선하고 더 작다(키보드 열림) → 그 값을 쓴다. 기존 키보드 대응 유지.
     *     · 값이 낡아 더 크다                  → svh로 잘려 화면 밖으로 못 나간다.
     *     · JS가 아직/전혀 안 돌았다           → 100svh 폴백.
     *
     * ★레퍼런스 대조: 같은 기기 가로에서 chatgpt.com은 컴포저가 온전히 보이고 그 아래까지
     *   스크롤로 닿는다 — 셸을 뷰포트 높이에 잠그지 않는다. 우리는 앱 셸 성격을 유지하되
     *   «잠그는 높이»를 보장 가시 높이로 바꾼다.
     */
    height: min(var(--wizon-vvh, 100svh), 100svh);
  }

  body.chatgpt-reference-v1 .main-pane,
  body.chatgpt-reference-v1 .workbench,
  body.chatgpt-reference-v1 .chat-pane {
    height: 100%;
  }
}

/* 20260803-dock-row-range — doc 143 항목 E. **이것이 가로 결함의 진짜 원인이었다.**
 *
 * 두 규칙의 미디어 범위가 어긋나 있었다:
 *
 *     styles.css L8256   .wds-ai-portal-v1 .composer-action-dock { flex-direction: column }
 *                        └ @media (max-width: 900px)        ← 가로(874px)에서 **적용됨**
 *     styles.css L17310  이를 되돌리는 flex-direction: row !important
 *                        └ @media (max-width: 520px)        ← 가로에서 **적용 안 됨**
 *
 * body에는 `wds-ai-portal-v1`과 `chatgpt-reference-v1`이 **둘 다** 붙는다. 그래서 폭이
 * 521~900px인 구간(= 폰 가로)에서만 dock이 세로로 쌓이고(실측 76×126), 기본 액션이 컴포저
 * 아래로 밀려 화면 밖으로 잘렸다. 세로(402px)는 두 규칙이 모두 적용돼 되돌리는 쪽이 이기므로
 * 멀쩡했다 — 결함이 «가로에서만» 나던 이유가 이것이다.
 *
 * ★높이는 처음부터 원인이 아니었다. 뷰포트 높이·안전영역·회전 재동기화를 차례로 의심했고
 *   전부 빗나갔다. 원인은 **폭 구간의 빈틈**이었다.
 *
 * ★고치는 방법은 «되돌리는 규칙을 자기가 되돌리려는 규칙과 같은 범위로» 맞추는 것이다.
 *   L17310의 520px 블록은 그대로 두고(세로에서 이미 옳다), 그 사이 구간만 여기서 덮는다.
 */
@media (min-width: 521px) and (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-composer-shell .composer-action-dock {
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    gap: 6px;
    justify-self: end;
  }
}

/* 20260803-short-viewport-scroll — doc 143 항목 E.
 *
 * ★증상(실기기 실측): iPhone 17을 가로로 돌리면 컴포저 기본 액션이 화면 아래로 잘리고
 *   **스크롤로도 닿을 수 없다.** 라이트·다크 양쪽에서 재현.
 *
 *       가로 뷰포트   874×292        (Safari 크롬이 110pt를 먹는다)
 *       셸            height: var(--wizon-vvh, 100dvh) + overflow: hidden
 *       문서 스크롤   없음            (scrollHeight == clientHeight)
 *
 * ★가설 셋을 세워 **셋 다 기각**했다(같은 길을 다시 파지 않도록 남긴다):
 *     · 컴포저 그리드가 2행으로 떨어진다 → 진짜 마크업 프로브가 292px에서 35px 여유.
 *     · 좌우 안전영역 미배선            → --wizon-safe-left/right는 이미 env()에 연결·7곳 사용.
 *     · 회전 시 뷰포트 값이 낡는다      → resize가 6ms 안에 2회, inner == visual == 292.
 *   남은 원인은 **홈 세로 스택이 292px에 안 들어가는 것**이다. 배관이 아니라 예산 문제다.
 *
 * ★고르지 않은 길: 인사말·칩을 접는 안. 그 둘은 이 표면의 정체성이라 지우면 잃는 게 크고,
 *   짧은 뷰포트는 예외 상황이다. 그래서 «그때만 스크롤을 연다».
 *
 * ★트리거가 max-height인 이유: 키보드를 올린 세로도 같은 부족이다. orientation으로 잡으면
 *   그 경우를 통째로 놓친다. 460px은 가로 실측(292) 위, 세로 실측(약 700) 아래다.
 *
 * ★여는 것은 **본문**이지 셸이 아니다. 셸까지 열면 주소창이 오르내려 «앱처럼 보이는»
 *   성질이 깨지고 상단바·컴포저 고정이 함께 무너진다. 셸 체인의 잠금은 그대로 둔다.
 */
@media (max-width: 900px) and (max-height: 460px) {
  body.chatgpt-reference-v1 .chat-pane {
    overflow-y: auto;
    /* 이 리포는 .message-list에서 같은 문제를 이미 이렇게 닫았다 — 스크롤 체이닝으로
       뒤 표면이 딸려 움직이는 것을 막는다. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
}

/* ---- User-message hover actions + inline editor (20260709-user-edit, ChatGPT parity) ---- */
/* Stack the bubble and its actions in a right-aligned column so copy/edit sit cleanly BELOW
   the bubble (not inside it). Overrides the grid layout for user turns. */
.chatgpt-reference-v1 .message.user {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.message.user .user-actions {
  display: flex;
  gap: 2px;
  justify-content: flex-end;
  margin-top: 2px;
  padding-right: 6px;
  opacity: 0;
  transition: opacity 120ms ease;
}
.message.user:hover .user-actions,
.message.user:focus-within .user-actions {
  opacity: 1;
}
/* Touch: no hover, so the inline actions are hidden and a long-press context menu (below)
   provides 복사/편집 instead — the ChatGPT mobile pattern. Suppress the iOS text-selection
   callout so the long-press lifts the menu rather than the native magnifier. */
@media (hover: none) {
  .message.user .user-actions {
    display: none;
  }
  .chatgpt-reference-v1 .message.user .message-body {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
}
/* Long-press context menu: dimmed backdrop + a lifted clone of the pressed bubble (kept bright
   above the scrim) + a popover of actions. */
.user-msg-scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(0, 0, 0, 0.44);
}
.user-msg-scrim[hidden] {
  display: none;
}
.user-msg-lift {
  position: fixed;
  z-index: 195;
  margin: 0 !important;
  pointer-events: none;
}
.user-msg-lift .message-body {
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.3);
  transform: scale(1.02);
  transform-origin: top right;
}
.user-msg-lift .user-actions {
  display: none !important;
}
.user-msg-menu {
  position: fixed;
  z-index: 200;
  min-width: 184px;
  padding: 6px;
  border: 1px solid var(--cg-menu-border, rgba(13, 13, 13, 0.1));
  border-radius: 16px;
  background: var(--cg-menu-bg, #ffffff);
  box-shadow: 0 18px 50px rgba(13, 13, 13, 0.22);
}
.user-msg-menu[hidden] {
  display: none;
}
.user-msg-menu-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border: none;
  border-radius: 11px;
  background: transparent;
  font: inherit;
  font-size: var(--ds-text-body-15);
  color: var(--cg-text, #0d0d0d);
  cursor: pointer;
}
.user-msg-menu-item:active {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.06));
}
.user-msg-menu-item .wds-inline-icon {
  width: 19px;
  height: 19px;
}

/* 20260709-recent-longpress (doc 144 follow-up): touch has no hover, so a long-press on a
   recent conversation lifts a snippet preview above a dimmed backdrop and opens a bottom
   action sheet — the ChatGPT mobile pattern. All three live on <body> (not the fixed
   sidebar), so a real tap-capturing scrim is safe here. */
@media (hover: none) {
  .chatgpt-reference-v1 .recent-item {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
  .chatgpt-reference-v1 .recent-item input {
    -webkit-user-select: text;
    user-select: text;
  }
}
/* While the long-press sheet is open the finger is still down over the sheet, so lock the
   whole document unselectable (JS also drops any range iOS already made) — per-element
   user-select:none does not stop a selection the long-press gesture already armed. */
body.recent-longpress-open,
body.recent-longpress-open * {
  -webkit-touch-callout: none !important;
  -webkit-user-select: none !important;
  user-select: none !important;
}
.recent-longpress-scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: rgba(0, 0, 0, 0.44);
}
.recent-longpress-scrim[hidden] {
  display: none;
}
.recent-longpress-lift {
  position: fixed;
  z-index: 195;
  left: 8px;
  right: 8px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border-radius: var(--ds-radius-md, 14px);
  background: var(--cg-menu-bg, #ffffff);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}
.recent-longpress-title {
  overflow: hidden;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-body-15);
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.recent-longpress-preview {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--cg-muted-2);
  font-size: var(--ds-text-caption-13);
  line-height: 18px;
}
.recent-longpress-menu {
  position: fixed;
  z-index: 200;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 8px calc(12px + var(--wizon-safe-bottom));
  border-radius: 18px 18px 0 0;
  background: var(--cg-menu-bg, #ffffff);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.22);
  animation: wizon-sheet-up var(--wizon-motion-base) var(--wds-ease-out) both;
  /* The finger is still pressing when the sheet opens under it — suppress the native text
     selection / callout so the label ("공유하기" etc.) is not selected at the same time. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.recent-longpress-menu[hidden] {
  display: none;
}
.recent-longpress-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 13px 14px;
  border: none;
  border-radius: 12px;
  background: transparent;
  font: inherit;
  font-size: var(--ds-text-body-16);
  color: var(--cg-text, #0d0d0d);
  text-align: left;
  cursor: pointer;
}
.recent-longpress-item:active {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.06));
}
.recent-longpress-item.is-danger {
  color: #e02e2a;
}
.recent-longpress-item .wds-inline-icon {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
}
.recent-longpress-divider {
  height: 1px;
  margin: 6px 10px;
  background: var(--cg-menu-border, rgba(13, 13, 13, 0.1));
}
@media (prefers-reduced-motion: reduce) {
  .recent-longpress-menu {
    animation: none;
  }
}

/* While editing, the bubble yields to a full-width inline editor. */
.chatgpt-reference-v1 .message.user .message-body:has(.user-edit) {
  max-width: 100%;
  width: 100%;
  padding: 0;
  background: transparent;
}
.user-edit {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(620px, 100%);
  margin-left: auto;
}
.user-edit-input {
  width: 100%;
  resize: none;
  border-radius: var(--ds-radius-lg, 18px);
  padding: 12px 16px;
  border: 1px solid var(--cg-menu-border, rgba(13, 13, 13, 0.14));
  background: var(--cg-surface, #ffffff);
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  line-height: 1.5;
}
.user-edit-input:focus {
  outline: none;
  border-color: var(--cg-text, #0d0d0d);
  box-shadow: none;
}
.user-edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.user-edit-cancel,
.user-edit-save {
  padding: 8px 16px;
  border: 0;
  border-radius: var(--ds-radius-pill, 999px);
  cursor: pointer;
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  transition: background 120ms ease, opacity 120ms ease;
}
.user-edit-cancel {
  background: transparent;
  color: var(--cg-muted, #8f8f8f);
}
.user-edit-cancel:hover {
  background: var(--cg-hover-soft, rgba(13, 13, 13, 0.04));
  color: var(--cg-text, #0d0d0d);
}
.user-edit-save {
  background: var(--cg-send-bg, #0d0d0d);
  color: var(--cg-send-fg, #ffffff);
}
.user-edit-save:hover {
  opacity: 0.9;
}

/* 20260709-mobile-route-navbar: standard single top app bar (Material 3 / Apple HIG).
   On a route page (library/projects/…) the LEADING slot swaps hamburger→back and an
   inline route title appears; the TRAILING new-chat action stays put (like ChatGPT's
   Library). There is exactly ONE title — the route page's big H1 is hidden on mobile
   (see the route-page block) so the title isn't duplicated (NN/g: no redundant chrome). */
@media (max-width: 900px) {
  /* hide the hidden-attr controls even though .chatgpt-icon-button sets display */
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-portal-route-back][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-mobile-route-title][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-mobile-workspace-trigger][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-mobile-library-new][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-drive-mobile-menu-trigger][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-mobile-trash-empty][hidden],
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-rail-new-chat][hidden] {
    display: none !important;
  }

  /* route open: back replaces the hamburger; new-chat stays on the right. The title
     fills the middle so new-chat is pushed to the trailing edge. */
  body.portal-route-open.chatgpt-reference-v1 .chatgpt-mobile-topbar [data-sidebar-open] {
    display: none;
  }
  /* The title sits in the CENTER slot (20260725-mobile-topbar-workspace), so it no longer
     needs to grow to push the trailing action out — the equal-basis side slots already do
     that. `flex: 0 1 auto` lets it shrink-with-ellipsis instead of claiming the whole bar,
     which is what kept it pinned left before. */
  body.portal-route-open.chatgpt-reference-v1 .chatgpt-mobile-topbar .chatgpt-mobile-route-title {
    flex: 0 1 auto;
    text-align: center;
    margin-inline: 2px;
  }

  body.chatgpt-reference-v1 .chatgpt-mobile-route-title {
    font-size: 17px;
    font-weight: 600;
    color: var(--cg-text, #0d0d0d);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
}

/* 20260709-mobile-safe-area (doc 143 item A): honor device safe areas now that
   viewport-fit=cover lets env() resolve. The app-shell is position:fixed at the
   very top (top:offsetTop), so the topbar pads its content below the notch, the
   composer clears the home indicator, and the drawer / content inset their edges
   (matters in landscape where the notch is on the side). Scoped <=900px. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar {
    height: calc(54px + var(--wizon-safe-top));
    padding-top: calc(4px + var(--wizon-safe-top));
    padding-left: calc(8px + var(--wizon-safe-left));
    padding-right: calc(8px + var(--wizon-safe-right));
    box-sizing: border-box;
  }

  /* composer clears the home indicator; collapse the inset while the keyboard is
     up (indicator hidden and the shell already sits on the keyboard). */
  body.chatgpt-reference-v1 .chat-pane {
    padding-bottom: var(--wizon-safe-bottom);
  }
  html.is-keyboard-open body.chatgpt-reference-v1 .chat-pane {
    padding-bottom: 0;
  }

  /* drawer clears the notch top and the side inset in landscape */
  body.chatgpt-reference-v1 .sidebar {
    padding-top: var(--wizon-safe-top);
    padding-left: var(--wizon-safe-left);
  }

  /* keep route/chat content clear of a side notch in landscape */
  body.chatgpt-reference-v1 .workbench {
    padding-left: var(--wizon-safe-left);
    padding-right: var(--wizon-safe-right);
  }
}

/* 20260709-mobile-bottom-sheet (doc 143 item C): on phones the composer "+" menu
   and the model/mode selector present as bottom sheets (slide up from the bottom,
   full-width, rounded top, dimming scrim + drag handle) instead of tiny dropdowns —
   the standard mobile menu affordance (Material bottom sheet / iOS action sheet).
   Overrides the JS dropdown positioning while the menu is open (:not([hidden])). */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 .composer-popover:not([hidden]),
  body.chatgpt-reference-v1 .reasoning-popover:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-more-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-account-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-recent-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-library-popover,
  /* 20260818-settings-choice-sheet (doc 143 항목 C 잔여): 설정의 선택 팝오버만
     아직 220px 우측 드롭다운이었다. 규칙을 새로 만들지 않고 이 목록에 더한다 —
     사본을 만들면 두 시트가 서로 다르게 늙는다. 이 팝오버는 transform·will-change 를
     가진 설정 다이얼로그 «안»에 있지만, 그 다이얼로그가 [data-mobile-fullscreen] 로
     inset:0 이라 컨테이닝 블록이 곧 뷰포트다 — 하단이 화면 하단과 같다. */
  body.chatgpt-reference-v1 .settings-choice-popover {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    top: auto !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: none !important;
    /* Height fits the content — the sheet is only as tall as its rows, and scrolls
       (never stretches) once it would exceed the cap. `align-content: start` is critical:
       these menus are display:grid, and grid's default align-content (normal→stretch)
       was inflating each row (36px → 80px) to fill the capped box, spreading the items. */
    height: auto !important;
    max-height: min(70vh, calc(var(--wizon-vvh, 100dvh) - 96px)) !important;
    align-content: start !important;
    overflow-y: auto !important;
    margin: 0 !important;
    padding: 8px 8px calc(12px + var(--wizon-safe-bottom)) !important;
    border-radius: var(--wizon-ai-radius-sheet, 18px) var(--wizon-ai-radius-sheet, 18px) 0 0 !important;
    /* Interim dimming via a paint-only huge spread shadow (restored). The tap-capturing
       scrim element was reverted because a body-level z-indexed scrim is rendered ABOVE
       sidebar-embedded sheets (account/more/recent are trapped in the fixed sidebar's
       stacking context) — it dimmed and disabled those sheets. The robust fix is the
       native top layer (dialog/popover), tracked separately. */
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.22), 0 0 0 100vmax var(--wizon-scrim, rgba(0, 0, 0, 0.24)) !important;
    transform: none !important;
    /* 20260709-motion-m0 (doc 146 §1): motion rides the individual `translate` property, so the
       `transform: none !important` above (which blocks inherited desktop transforms) never touches
       it. `backwards` fill (not `both`): after the entrance settles, the base `translate: 0 0`
       governs — so the M1 exit transition takes over cleanly instead of fighting a forwards fill.
       Curve = WDS `effect-default` spring: an APPLE-style critically-damped `linear()` curve
       that decelerates to rest WITHOUT positional overshoot. The `spatial-default` spring was
       tried first but overshoots to 1.015 (translate -1.5%), which on a bottom-anchored sheet
       lifts it ~6px past rest and reveals a gap below before it settles (the reported
       "하단쪽 살짝 떴다가 다시 붙음"). effect-default never exceeds 1 → no lift, no gap. */
    translate: 0 0;
    z-index: 200 !important;
    animation: wizon-sheet-up var(--wds-spring-spatial-default-duration, 372ms) var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1)) backwards;
  }

  /* 20260818-sheet-handle-dedupe: 여기 있던 `::after` 잡이를 걷었다.
     배치 4(`b20c576fa`)가 「이 블록은 핸들을 한 번도 그리지 않았다(hasHandle=false)」
     고 보고 `::before` 로 다시 그렸는데, 그 판단이 틀렸다 — `::after` 는 그리고
     있었고 결과적으로 **막대가 두 개**가 됐다. 2026-08-18 실측(375px 라이브):
     시트 8종 전부 ::before(+2px, 227 불투명)와 ::after(+8px, 138 50%)가 2px 간격을
     두고 «따로» 보인다. 정본은 배치 4 의 ::before 다(Mobbin 시트 6/6 근거).
     계약: apps/ai-portal/tests/test_mobile_sheet_handle_single.py */

  /* 20260710-conversation-menu-consolidation: in the full-width bottom sheet the
     conversation menu rows stretch edge-to-edge (the 174px desktop-popover width is a
     dropdown holdover) so labels like "그룹 채팅 시작" + the "준비 중" badge stay on one line. */
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:not([hidden]) button {
    width: auto;
  }

  body.chatgpt-reference-v1 .chatgpt-conversation-menu:not([hidden]) button > span:not([class]) {
    white-space: nowrap;
  }
}

@keyframes wizon-sheet-up {
  from { translate: 0 100%; }
  to { translate: 0 0; }
}
@keyframes wizon-scrim-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
/* Exit as a keyframe animation (not a transition) — Safari paints animations, not transitions,
   on top-layer popovers. See the 20260709-motion-m1 block. */
@keyframes wizon-sheet-down {
  from { translate: 0 0; }
  to { translate: 0 100%; }
}
@keyframes wizon-scrim-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
/* Library sheet exit (20260710-library-sheet-motion): the new/filter menus re-render as fresh
   HTML (no persistent node for setAnimatedDisclosure's exit), so their close is animated via a
   cloned inert ghost that slides down AND fades — the fade also carries the paint-only dim
   (box-shadow inherits element opacity) out with it, matching the ::backdrop fade of the other
   sheets without needing the top layer. */
@keyframes wizon-library-sheet-out {
  from { translate: 0 0; opacity: 1; }
  to { translate: 0 100%; opacity: 0; }
}
/* Mobile drawer offcanvas slide (M2, doc 146 §3). `translate` (not transform) so it coexists
   with the escape rule's `transform: none !important`; keyframe animation (not transition) with
   no forwards fill on entry so no residual translate re-traps the child sheets (doc 144). */
@keyframes wizon-drawer-in {
  from { translate: -100% 0; }
  to { translate: 0 0; }
}
@keyframes wizon-drawer-out {
  from { translate: 0 0; }
  to { translate: -100% 0; }
}

/* 20260710-motion-m3 (doc 146 §4): mobile route transition via the View Transitions API.
   The JS wraps the route render in document.startViewTransition (Safari 18+/Baseline; gated to
   mobile + feature-detected + reduced-motion). The new page cross-slides in from the right, the
   old slides slightly left and fades — a subtle iOS-style page transition. */
@keyframes wizon-route-in {
  from { opacity: 0; transform: translateX(16px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes wizon-route-out {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(-12px); }
}
@media (max-width: 900px) {
  ::view-transition-old(root) {
    animation: wizon-route-out 160ms var(--wizon-sheet-exit-ease, cubic-bezier(0.4, 0, 1, 1)) both;
  }
  ::view-transition-new(root) {
    animation: wizon-route-in 240ms var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1)) both;
  }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}

/* 20260710-motion-m4 (doc 146 §5, revised): touch tap feedback via a JS-toggled `.wds-pressed`
   class, NOT CSS `:active`. iOS Safari applies `:active` unreliably on tap (and not at all on the
   non-<button> prompt chips); a pointerdown/up class toggle (see handleTapPressStart in app.js) is
   identical on iOS + Android + every touch device — and is testable. Individual `scale` property so
   it never fights any `transform`; base `transition: scale` eases both press and release. Bounded
   whitelist of interactive chrome — never a global `*`.
   ★2026-08-02 (북극성 ③): 이 목록은 일곱이었고, 라이브 390px 실측이 그 경계가 빠뜨린 것을 보였다
   — 드로어 49개 중 31개(63%), 라이브러리 31개 중 28개(90%), 대화 화면 30개 중 25개(83%)가 눌러도
   반응이 없었다. 형제끼리 갈린 게 신호였다: .prompt-chip 은 반응하고 .followup-chip 은 아니며,
   .chatgpt-sidebar-link 는 반응하고 바로 한 줄 아래 .recent-item 은 아니었다.
   경계가 잘못이 아니라 «크롬»을 기준으로 그어진 게 잘못이었다 — 모바일 표면은 대부분 내용 행과
   칩이다. 경계는 그대로 두되(전역 `*` 금지) 두 갈래로 나눈다: 폭 358px 짜리 행이 통째로 줄어들면
   화면이 움직여 어색하고, iOS 목록 행의 규범은 축소가 아니라 «채움»이다. 그래서 행은
   .wds-pressed-fill(면), 작은 것은 .wds-pressed(축소). 행 안의 작은 컨트롤은 closest() 가 더
   깊은 것을 고르므로 자기 형태를 그대로 지킨다.
   ★면은 계산 스타일로 검증할 수 없다 — transition: background-color 때문에 페인트하지 않는
   브라우저 패널에서 시작값(투명)에 얼어붙는다(같은 파일 상단바 눌림 배경 주석의 실측). 판정은
   시뮬레이터 픽셀로. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .chatgpt-icon-button,
  body.chatgpt-reference-v1 .chatgpt-rail-button,
  body.chatgpt-reference-v1 .chatgpt-mobile-topbar-button,
  body.chatgpt-reference-v1 .chatgpt-sidebar-link,
  body.chatgpt-reference-v1 .composer-icon-button,
  body.chatgpt-reference-v1 .prompt-chip,
  body.chatgpt-reference-v1 [role="menuitem"],
  body.chatgpt-reference-v1 [role="tab"],
  body.chatgpt-reference-v1 .followup-chip,
  body.chatgpt-reference-v1 .message-action-button,
  body.chatgpt-reference-v1 .chatgpt-route-empty-action,
  body.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger,
  body.chatgpt-reference-v1 .recent-action,
  body.chatgpt-reference-v1 .chatgpt-recent-header-action,
  body.chatgpt-reference-v1 .chatgpt-recent-title,
  body.chatgpt-reference-v1 .chatgpt-library-view-control,
  body.chatgpt-reference-v1 .composer-model-pill,
  body.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger,
  body.chatgpt-reference-v1 .chatgpt-conversation-more,
  body.chatgpt-reference-v1 .chatgpt-conversation-health,
  body.chatgpt-reference-v1 .chatgpt-account-button,
  body.chatgpt-reference-v1 .citation-health-actions button,
  body.chatgpt-reference-v1 .citation-health-claim-actions button,
  body.chatgpt-reference-v1 .citation-revision-actions button,
  body.chatgpt-reference-v1 .trust-chip,
  body.chatgpt-reference-v1 .citation-tag,
  body.chatgpt-reference-v1 .md-table-copy,
  body.chatgpt-reference-v1 .scroll-to-bottom {
    transition: scale var(--wizon-motion-fast, 140ms) ease-out;
  }
  body.chatgpt-reference-v1 .wds-pressed {
    scale: 0.96;
  }
  /* 행은 줄이지 않고 채운다. 상단바 눌림 배경과 같은 토큰을 써서 «눌림 = 이 면»이라는 한 가지
     언어로 통일한다. */
  body.chatgpt-reference-v1 .recent-item,
  body.chatgpt-reference-v1 .chatgpt-library-row {
    transition: background-color var(--wizon-motion-fast, 140ms) ease-out;
  }
  body.chatgpt-reference-v1 .wds-pressed-fill {
    background: var(--cg-hover-soft);
  }
}

/* 20260728-composer-attachment-preview-v3: keep ordered attachment context on its own compact shelf.
   Inline-size containment lets the rail scroll internally without widening the mobile document. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])) {
  grid-template-rows: auto auto !important;
  min-height: 106px !important;
  height: auto !important;
  padding: 7px 8px 5px !important;
}

body.chatgpt-reference-v1 .composer-attachment-lane:not([hidden]) {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  box-sizing: border-box;
  contain: inline-size paint;
  gap: 7px;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  padding: 1px 2px 8px;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

body.chatgpt-reference-v1 .composer-attachment-lane::-webkit-scrollbar {
  display: none;
}

/* 20260802-composer-attachment-navigation: fine pointers get explicit horizontal
   navigation and grab-to-scroll. Touch keeps the native swipe lane with no chrome. */
body.chatgpt-reference-v1 .composer-attachment-rail:not([hidden]) {
  display: flex;
  align-items: center;
  gap: 4px;
  width: 100%;
  min-width: 0;
}

body.chatgpt-reference-v1 .composer-attachment-rail .composer-attachment-lane:not([hidden]) {
  flex: 1 1 auto;
  width: auto;
  cursor: grab;
  overscroll-behavior-inline: contain;
  scroll-snap-type: inline proximity;
}

body.chatgpt-reference-v1 .composer-attachment-rail .composer-attachment-lane.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
  user-select: none;
}

body.chatgpt-reference-v1 .composer-attachment-card,
body.chatgpt-reference-v1 .composer-attachment-manage {
  scroll-snap-align: start;
}

body.chatgpt-reference-v1 .composer-attachment-nav {
  display: none;
  flex: 0 0 32px;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--cg-text) 10%, transparent);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-text);
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-nav:disabled {
  opacity: 0.32;
  cursor: default;
}

body.chatgpt-reference-v1 .composer-attachment-manage {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
  border-radius: var(--wizon-ai-menu-radius);
  background: color-mix(in srgb, var(--cg-text) 3%, var(--cg-surface));
  color: var(--cg-text);
  font: inherit;
  font-size: var(--wizon-ai-font-size-label);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-card[data-question-active="false"] {
  opacity: 0.56;
}

@media (pointer: fine) {
  body.chatgpt-reference-v1 .composer-attachment-rail.has-overflow .composer-attachment-nav:not([hidden]) {
    display: grid;
  }

  body.chatgpt-reference-v1 .composer-attachment-nav:not(:disabled):hover,
  body.chatgpt-reference-v1 .composer-attachment-manage:hover {
    background: var(--cg-hover-soft);
  }
}

body.chatgpt-reference-v1 .composer-attachment-dialog {
  width: min(520px, calc(100vw - 32px));
  max-height: min(680px, calc(100dvh - 48px));
  padding: 0;
  border: 0;
  border-radius: var(--wizon-ai-radius-sheet);
  background: var(--cg-surface);
  color: var(--cg-text);
  box-shadow: var(--wizon-ai-dialog-shadow);
  overflow: hidden;
}

body.chatgpt-reference-v1 .composer-attachment-dialog::backdrop {
  background: var(--wds-modal-scrim);
  backdrop-filter: blur(2px);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-shell {
  display: flex;
  flex-direction: column;
  max-height: inherit;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 16px;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-head h2,
body.chatgpt-reference-v1 .composer-attachment-dialog-head p {
  margin: 0;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-head h2 {
  font-size: var(--wizon-ai-font-size-title);
  line-height: 1.35;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-head p {
  margin-top: 4px;
  color: var(--cg-muted);
  font-size: var(--wizon-ai-font-size-caption);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-close,
body.chatgpt-reference-v1 .composer-attachment-dialog-remove,
body.chatgpt-reference-v1 .composer-attachment-dialog-toggle {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: var(--wizon-ai-radius-pill);
  background: transparent;
  color: inherit;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-scope {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  margin: 0 16px 12px;
  padding: 4px;
  border-radius: var(--wizon-ai-menu-radius);
  background: color-mix(in srgb, var(--cg-text) 6%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-scope button {
  min-height: 36px;
  padding: 0 12px;
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-scope button.is-active {
  background: var(--cg-surface);
  color: var(--cg-text);
  box-shadow: var(--ds-shadow-xs);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  padding: 0 12px 16px;
  overflow-y: auto;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-item {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) 36px;
  align-items: center;
  min-height: 56px;
  border-radius: var(--wizon-ai-menu-radius);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-item.is-active {
  background: color-mix(in srgb, var(--wds-brand-blue) 7%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-main {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  min-height: 56px;
  padding: 4px 8px;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-check {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 28%, transparent);
  border-radius: var(--ds-radius-xs);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-toggle[aria-checked="true"] .composer-attachment-dialog-check {
  border-color: var(--wds-brand-blue);
  background: var(--wds-brand-blue);
  color: var(--wds-color-on-primary);
}

body.chatgpt-reference-v1 .composer-attachment-dialog-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-copy strong,
body.chatgpt-reference-v1 .composer-attachment-dialog-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-dialog-copy small {
  margin-top: 2px;
  color: var(--cg-muted);
  font-size: var(--wizon-ai-font-size-caption);
}

@media (pointer: fine) {
  body.chatgpt-reference-v1 .composer-attachment-dialog-item:hover,
  body.chatgpt-reference-v1 .composer-attachment-dialog-close:hover,
  body.chatgpt-reference-v1 .composer-attachment-dialog-remove:hover {
    background: var(--cg-hover-soft);
  }
}

@media (max-width: 520px), (pointer: coarse) {
  body.chatgpt-reference-v1 .composer-attachment-rail {
    gap: 0;
  }

  body.chatgpt-reference-v1 .composer-attachment-nav {
    display: none !important;
  }

  body.chatgpt-reference-v1 .composer-attachment-rail .composer-attachment-lane:not([hidden]) {
    cursor: auto;
    padding-inline: 2px;
    -webkit-overflow-scrolling: touch;
  }

  body.chatgpt-reference-v1 .composer-attachment-dialog {
    width: 100%;
    max-width: none;
    max-height: min(78dvh, 680px);
    margin: auto 0 0;
    border-radius: var(--wizon-ai-radius-sheet) var(--wizon-ai-radius-sheet) 0 0;
  }

  body.chatgpt-reference-v1 .composer-attachment-dialog-list {
    scrollbar-width: none;
    padding-bottom: calc(16px + env(safe-area-inset-bottom));
  }

  body.chatgpt-reference-v1 .composer-attachment-dialog-list::-webkit-scrollbar {
    display: none;
  }
}

body.chatgpt-reference-v1 .chatgpt-composer-shell.has-attachment .composer-prompt-body {
  padding-top: 4px;
  border-top: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 8%, transparent);
}

body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-card {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0;
  width: auto;
  max-width: min(240px, calc(100vw - 80px));
  min-height: 44px;
  padding: 0 4px 0 6px;
  border: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 11%, transparent);
  border-radius: 13px;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 4%, #fff);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.035);
}

body.chatgpt-reference-v1 .composer-attachment-open {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 8px;
  min-width: 0;
  height: 42px;
  padding: 0 7px 0 0;
  border: 0;
  border-radius: 11px 0 0 11px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-open:focus-visible {
  outline: 2px solid var(--wds-brand-blue, #155eef);
  outline-offset: 1px;
}

body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-policy-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 1px 31px;
  grid-template-rows: auto auto;
  width: min(430px, calc(100vw - 80px));
  max-width: min(430px, calc(100vw - 80px));
  padding: 5px 4px 5px 6px;
}

body.chatgpt-reference-v1 .composer-attachment-policy-copy {
  grid-row: 1;
  grid-column: 1;
  height: auto;
  min-height: 42px;
  cursor: default;
}

body.chatgpt-reference-v1 .composer-attachment-policy-card .composer-attachment-index-state {
  max-width: 330px;
  white-space: normal;
}

body.chatgpt-reference-v1 .composer-attachment-policy-actions {
  display: flex;
  grid-row: 2;
  grid-column: 1 / -1;
  gap: 6px;
  padding: 3px 2px 0 38px;
}

body.chatgpt-reference-v1 .composer-attachment-policy-actions button {
  min-height: 30px;
  padding: 0 9px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 13%, transparent);
  border-radius: var(--ds-radius-sm, 8px);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--cg-text-meta-size);
  font-weight: var(--cg-text-label-active-weight);
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-policy-actions button:hover,
body.chatgpt-reference-v1 .composer-attachment-policy-actions button:focus-visible {
  border-color: color-mix(in srgb, var(--ad-blue) 38%, transparent);
  background: color-mix(in srgb, var(--ad-blue) 9%, transparent);
  outline: 2px solid var(--ad-blue);
  outline-offset: 1px;
}

body.chatgpt-reference-v1 .composer-attachment-policy-card .composer-attachment-separator {
  grid-row: 1;
  grid-column: 2;
}

body.chatgpt-reference-v1 .composer-attachment-policy-card .composer-chip-remove {
  grid-row: 1;
  grid-column: 3;
}

body.chatgpt-reference-v1 .composer-range-context-copy {
  cursor: default;
}

body.chatgpt-reference-v1 .composer-range-quick-action {
  display: grid;
  flex: 0 0 auto;
  min-width: var(--wds-control-height-md);
  height: var(--wds-control-height-md);
  padding: 0 var(--ds-space-2);
  place-items: center;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--wds-color-text);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  font-weight: var(--ds-weight-medium);
  cursor: pointer;
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .composer-range-quick-action:hover {
    background: color-mix(in srgb, var(--wds-color-text) 8%, transparent);
  }
}

body.chatgpt-reference-v1 .composer-range-quick-action:focus-visible {
  outline: 2px solid var(--wds-color-focus-ring);
  outline-offset: -2px;
}

body.chatgpt-reference-v1 .composer-range-quick-action:disabled {
  color: var(--wds-color-text-muted);
  cursor: default;
  opacity: 0.55;
}

@media (pointer: coarse) {
  .artifact-titlebar-button[data-artifact-range-ask] {
    width: 44px;
    height: 44px;
  }
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-attachment-file-icon {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--cg-menu-border);
}

/* The canonical 200x241 artwork paints its extension badge to y=240.  Filling the
   30x30 host therefore puts that ink under the host's radius-9 clip even though
   object-fit:contain reports a healthy image.  Keep the shared host mask, but give
   attachment artwork a real two-pixel safe area on every side. */
body.chatgpt-reference-v1 .composer-attachment-card
  .composer-attachment-file-icon > .wizon-file-type-icon--attachment {
  width: 26px;
  height: 26px;
  margin: 2px;
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-attachment-file-icon svg {
  width: 18px;
  height: 18px;
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-attachment-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-attachment-type {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-chip-label {
  display: block;
  overflow: hidden;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-caption-13, 13px);
  font-weight: 500;
  line-height: 18px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-index-state {
  display: flex;
  align-items: center;
  gap: 4px;
  color: var(--cg-muted);
  font-size: smaller;
  line-height: 14px;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-index-state::before {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ad-blue);
  content: "";
}

body.chatgpt-reference-v1 .composer-attachment-index-state[data-state="failed"] {
  color: var(--cg-danger-fg);
}

body.chatgpt-reference-v1 .composer-attachment-index-state[data-state="failed"]::before {
  background: currentColor;
}

body.chatgpt-reference-v1 .composer-attachment-index-state[data-state="background"] {
  color: var(--ad-blue);
}

body.chatgpt-reference-v1 .composer-attachment-index-state[data-state="degraded"] {
  color: var(--cg-warning-fg);
}

body.chatgpt-reference-v1 .composer-attachment-index-state[data-state="degraded"]::before {
  background: currentColor;
}

body.chatgpt-reference-v1 .composer-attachment-progress {
  position: relative;
  display: block;
  appearance: none;
  width: 100%;
  height: 2px;
  margin-top: 2px;
  overflow: hidden;
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-menu-border);
}

body.chatgpt-reference-v1 .composer-attachment-progress::-webkit-progress-bar {
  background: var(--cg-menu-border);
}

body.chatgpt-reference-v1 .composer-attachment-progress::-webkit-progress-value,
body.chatgpt-reference-v1 .composer-attachment-progress::-moz-progress-bar {
  border-radius: var(--ds-radius-pill);
  background: var(--ad-blue);
}

body.chatgpt-reference-v1 .composer-attachment-separator {
  flex: 0 0 1px;
  width: 1px;
  height: 22px;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 11%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-retry {
  display: grid;
  flex: 0 0 auto;
  width: 30px;
  height: 38px;
  padding: 0;
  place-items: center;
  border: 0;
  border-radius: var(--ds-radius-sm);
  background: transparent;
  color: var(--cg-warning-fg);
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-attachment-retry:hover,
body.chatgpt-reference-v1 .composer-attachment-retry:focus-visible {
  background: color-mix(in srgb, var(--cg-warning-fg) 10%, transparent);
  outline: none;
}

body.chatgpt-reference-v1 .composer-attachment-retry svg {
  width: 16px;
  height: 16px;
}

body.chatgpt-reference-v1 .composer-attachment-retry:disabled {
  color: var(--cg-muted);
  cursor: progress;
  opacity: 0.72;
}

body.chatgpt-reference-v1 .composer-attachment-card .composer-chip-remove {
  width: 31px;
  height: 38px;
  margin-left: 2px;
  color: var(--cg-muted, #6f6f6f);
}

body.chatgpt-reference-v1 .composer-attachment-card:hover,
body.chatgpt-reference-v1 .composer-attachment-card:focus-within {
  border-color: color-mix(in srgb, var(--cg-text, #0d0d0d) 17%, transparent);
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 7%, #fff);
  color: var(--cg-text, #0d0d0d);
}

/* Success is announced once through the existing polite live region, but does not become a
   persistent green instruction above the prompt. Progress and error remain visible in place. */
body.chatgpt-reference-v1 .composer-attachment-status[data-tone="success"] {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  margin: -1px !important;
  overflow: hidden !important;
  clip: rect(0, 0, 0, 0) !important;
  white-space: nowrap !important;
  border: 0 !important;
}

body.chatgpt-reference-v1 .composer-attachment-preview {
  position: fixed;
  z-index: 1250;
  width: min(352px, calc(100vw - 24px));
  padding: 14px;
  border: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 12%, transparent);
  border-radius: var(--ds-radius-lg, 18px);
  background: var(--cg-surface, #fff);
  color: var(--cg-text, #0d0d0d);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.16), 0 2px 8px rgba(0, 0, 0, 0.08);
}

body.chatgpt-reference-v1 .composer-attachment-preview[hidden],
body.chatgpt-reference-v1 .composer-attachment-preview-host[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-preview-host[open] {
  position: fixed;
  inset: 0;
  width: 100vw;
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 0;
  background: transparent;
}

body.chatgpt-reference-v1 .composer-attachment-preview-host::backdrop {
  background: transparent;
}

body.chatgpt-reference-v1 .composer-attachment-preview-header {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

body.chatgpt-reference-v1 .composer-attachment-preview-icon {
  display: inline-grid;
  flex: 0 0 auto;
  place-items: center;
  width: 42px;
  height: 42px;
  overflow: hidden;
  border-radius: 11px;
  background: var(--cg-surface);
  color: var(--ad-blue, var(--wds-brand-blue, #155eef));
  box-shadow: inset 0 0 0 1px var(--cg-menu-border);
}

body.chatgpt-reference-v1 .composer-attachment-preview-icon svg {
  width: 19px;
  height: 19px;
}

body.chatgpt-reference-v1 .composer-attachment-preview-heading {
  display: grid;
  min-width: 0;
  gap: 2px;
}

body.chatgpt-reference-v1 .composer-attachment-preview-heading strong {
  overflow: hidden;
  font-size: var(--ds-text-body-14, 14px);
  font-weight: 600;
  line-height: 20px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-preview-heading > span {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow: hidden;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
  line-height: 16px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-preview-heading i {
  color: color-mix(in srgb, var(--cg-muted, #6f6f6f) 55%, transparent);
  font-style: normal;
}

body.chatgpt-reference-v1 .composer-attachment-preview-content {
  margin-top: 12px;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 9%, transparent);
  border-radius: 13px;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 2.5%, #fff);
}

body.chatgpt-reference-v1 .composer-attachment-preview-kicker {
  display: block;
  padding: 10px 12px 0;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
  font-weight: 500;
  line-height: 16px;
}

body.chatgpt-reference-v1 .composer-attachment-preview-image {
  display: block;
  width: 100%;
  height: 172px;
  margin-top: 8px;
  object-fit: cover;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 5%, #fff);
}

body.chatgpt-reference-v1 .composer-attachment-preview-text,
body.chatgpt-reference-v1 .composer-attachment-preview-empty {
  display: -webkit-box;
  overflow: hidden;
  margin: 7px 12px 12px;
  color: var(--cg-text, #0d0d0d);
  font-size: var(--ds-text-caption-13, 13px);
  line-height: 20px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 7;
}

body.chatgpt-reference-v1 .composer-attachment-preview-empty {
  color: var(--cg-muted, #6f6f6f);
}

body.chatgpt-reference-v1 .composer-attachment-preview-hint {
  display: block;
  margin-top: 10px;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
  line-height: 16px;
}

body.chatgpt-reference-v1 .composer-document-preview-surface {
  box-sizing: border-box;
  min-width: 0;
  color: var(--cg-text, #0d0d0d);
}

body.chatgpt-reference-v1 .composer-document-preview-quality {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-height: 18px;
  width: fit-content;
  margin-top: 3px;
  padding: 1px 6px;
  border: 1px solid color-mix(in srgb, var(--wds-brand-blue, #155eef) 20%, transparent);
  border-radius: var(--ds-radius-pill, 999px);
  background: color-mix(in srgb, var(--wds-brand-blue, #155eef) 8%, transparent);
  color: color-mix(in srgb, var(--wds-brand-blue, #155eef) 82%, var(--cg-text, #0d0d0d));
  font-size: 10px;
  font-weight: 600;
  line-height: 14px;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-document-preview-quality.is-pending {
  visibility: hidden;
}

body.chatgpt-reference-v1 .composer-document-preview-quality[data-preview-quality="converted"],
body.chatgpt-reference-v1 .composer-document-preview-quality[data-preview-quality="limited"] {
  border-color: color-mix(in srgb, #f79009 25%, transparent);
  background: color-mix(in srgb, #f79009 10%, transparent);
  color: #9a4e00;
}

body.chatgpt-reference-v1 .composer-document-preview-quality[data-preview-quality="unavailable"] {
  border-color: color-mix(in srgb, var(--cg-muted, #6f6f6f) 24%, transparent);
  background: color-mix(in srgb, var(--cg-muted, #6f6f6f) 10%, transparent);
  color: var(--cg-muted, #6f6f6f);
}

body.chatgpt-reference-v1 .composer-attachment-preview .composer-document-preview-surface {
  height: 226px;
  max-height: 226px;
  margin-top: 7px;
  overflow: auto;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-loading,
body.chatgpt-reference-v1 .composer-document-preview-surface.is-state {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 9px;
  min-height: 92px;
  padding: 14px 12px;
  color: var(--cg-muted, #6f6f6f);
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-loading p,
body.chatgpt-reference-v1 .composer-document-preview-surface.is-state p {
  margin: 0;
  font-size: var(--ds-text-caption-13, 13px);
  line-height: 20px;
}

body.chatgpt-reference-v1 .composer-document-preview-state-copy {
  display: grid;
  grid-column: 1 / -1;
  gap: 12px;
}

body.chatgpt-reference-v1 .composer-document-preview-state-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

body.chatgpt-reference-v1 .composer-document-preview-state-actions button {
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid color-mix(in srgb, currentColor 28%, transparent);
  border-radius: var(--ds-radius-sm, 8px);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--ds-text-caption-13, 13px);
  font-weight: 600;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-document-preview-state-actions button:hover,
body.chatgpt-reference-v1 .composer-document-preview-state-actions button:focus-visible {
  background: color-mix(in srgb, currentColor 10%, transparent);
}

body.chatgpt-reference-v1 .composer-document-preview-spinner {
  width: 16px;
  height: 16px;
  border: 2px solid color-mix(in srgb, var(--cg-muted, #6f6f6f) 22%, transparent);
  border-top-color: var(--wds-brand-blue, #155eef);
  border-radius: 50%;
  animation: composer-document-preview-spin 700ms linear infinite;
}

@keyframes composer-document-preview-spin {
  to { transform: rotate(360deg); }
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-visual {
  display: grid;
  place-items: center;
  overflow: hidden;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 4%, #fff);
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-visual img {
  display: block;
  width: 100%;
  max-height: 226px;
  object-fit: contain;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-text pre {
  box-sizing: border-box;
  min-height: 92px;
  margin: 0;
  padding: 12px;
  overflow: auto;
  color: var(--cg-text, #0d0d0d);
  font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  tab-size: 2;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

body.chatgpt-reference-v1 .composer-document-preview-note {
  margin: 0;
  padding: 8px 12px;
  border-top: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 8%, transparent);
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
  line-height: 16px;
}

body.chatgpt-reference-v1 .composer-document-preview-sheet-tabs {
  display: flex;
  gap: 4px;
  padding: 8px 8px 0;
  overflow-x: auto;
}

body.chatgpt-reference-v1 .composer-document-preview-sheet-tabs button {
  flex: 0 0 auto;
  min-height: 30px;
  padding: 4px 9px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-muted, #6f6f6f);
  font: inherit;
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .composer-document-preview-sheet-tabs button[aria-selected="true"] {
  border-color: color-mix(in srgb, var(--cg-text, #0d0d0d) 10%, transparent);
  background: var(--cg-surface, #fff);
  color: var(--cg-text, #0d0d0d);
}

body.chatgpt-reference-v1 .composer-document-preview-table-wrap {
  overflow: auto;
}

body.chatgpt-reference-v1 .composer-document-preview-table-wrap table {
  width: max-content;
  min-width: 100%;
  border-spacing: 0;
  border-collapse: separate;
  font-size: var(--ds-text-caption-12, 12px);
  line-height: 18px;
}

body.chatgpt-reference-v1 .composer-document-preview-table-wrap th,
body.chatgpt-reference-v1 .composer-document-preview-table-wrap td {
  max-width: 240px;
  padding: 6px 9px;
  overflow: hidden;
  border-right: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 7%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--cg-text, #0d0d0d) 7%, transparent);
  text-align: left;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-document-preview-table-wrap th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 5%, var(--cg-surface, #fff));
  font-weight: 600;
}

body.chatgpt-reference-v1 .composer-document-preview-table-wrap .is-search-target {
  position: relative;
  z-index: 2;
  background: color-mix(in srgb, var(--ds-color-accent) 14%, var(--cg-surface));
  box-shadow: inset 0 0 0 2px var(--ds-color-accent);
}

body.chatgpt-reference-v1 .composer-document-preview-surface mark[data-document-preview-search-target] {
  padding: 1px 2px;
  border-radius: var(--ds-radius-xs);
  background: color-mix(in srgb, var(--ds-color-accent) 18%, var(--cg-surface));
  color: inherit;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane {
  width: min(1120px, calc(100% - var(--chatgpt-route-gap-lg) * 2));
  max-width: min(1120px, calc(100% - var(--chatgpt-route-gap-lg) * 2));
  max-height: min(72svh, 920px);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface {
  min-height: min(58svh, 720px);
  margin-top: var(--chatgpt-route-gap-md);
  overflow: auto;
  border-top: 1px solid var(--cg-menu-border);
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 3%, var(--cg-surface, #fff));
}

body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface.is-loading,
body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface.is-state {
  place-content: center;
  grid-template-columns: auto minmax(0, 340px);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface.is-visual img {
  width: auto;
  max-width: 100%;
  max-height: min(62svh, 800px);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface.is-text pre {
  min-height: min(58svh, 720px);
  padding: 24px 28px;
  background: var(--cg-surface, #fff);
  font-size: 14px;
  line-height: 1.65;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-pdf {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  overflow: hidden !important;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-pdf.has-external-toolbar {
  grid-template-rows: auto minmax(0, 1fr);
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-pdf.has-external-toolbar > .document-viewer-find {
  grid-row: 1;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-pdf.has-external-toolbar > .document-viewer-layout {
  grid-row: 2;
}

/* doc 171 S2c — the live workbook. Same three-band grid as the PDF viewer (toolbar, notice,
   stage) so both full-viewer surfaces share one chrome rhythm. The stage must get a real
   height: Univer measures its container to lay out the canvas, and an auto-height parent
   collapses it to nothing. */
body.chatgpt-reference-v1 .composer-document-preview-surface.is-workbook {
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  overflow: hidden !important;
}

body.chatgpt-reference-v1 .composer-document-preview-workbook {
  min-height: 320px;
  height: 100%;
}

/* Deliberately NOT .composer-document-preview-toolbar: that one sizes every button to a
   34x34 icon box, which turned this text label into wrapped characters spilling across the
   sheet (2026-08-10 live defect). */
body.chatgpt-reference-v1 .composer-document-preview-workbook-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid color-mix(in srgb, var(--cg-text) 8%, transparent);
  background: var(--cg-surface);
}

body.chatgpt-reference-v1 .composer-document-preview-workbook-save {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-text);
  color: var(--cg-surface);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-document-preview-workbook-save:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* P3 sheet -> CPQ proposal bridge. A distinct outline treatment (not a solid fill like
   Save) on purpose: this action creates a §13.4 PROPOSAL, not a saved version -- the
   weight of the button should not imply it commits anything by itself. */
body.chatgpt-reference-v1 .composer-document-preview-workbook-cpq-proposal {
  flex: 0 0 auto;
  min-height: 32px;
  padding: 0 14px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 24%, transparent);
  border-radius: var(--ds-radius-pill);
  background: transparent;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}

body.chatgpt-reference-v1 .composer-document-preview-workbook-cpq-proposal:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

body.chatgpt-reference-v1 .workbook-cpq-proposal-preview {
  display: grid;
  gap: 8px;
  margin-top: 8px;
  padding: 8px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
  border-radius: var(--ds-radius-md);
}

body.chatgpt-reference-v1 .workbook-cpq-proposal-preview p {
  margin: 0;
}

body.chatgpt-reference-v1 .composer-document-preview-workbook-status {
  min-width: 0;
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12, 12px);
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-document-preview-note.is-risk {
  display: grid;
  gap: 4px;
  border-top: 1px solid color-mix(in srgb, var(--cg-warning-fg) 32%, transparent);
  background: color-mix(in srgb, var(--cg-warning-fg) 8%, transparent);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .composer-document-preview-note.is-risk label {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

body.chatgpt-reference-v1 .workbook-version-comparison {
  display: grid;
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
}

body.chatgpt-reference-v1 .workbook-version-comparison p,
body.chatgpt-reference-v1 .workbook-version-comparison ul {
  margin: 0;
}

body.chatgpt-reference-v1 .workbook-version-comparison-sheet {
  display: grid;
  gap: 6px;
  min-width: 0;
  margin: 0;
  padding: 8px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
  border-radius: var(--ds-radius-md);
}

body.chatgpt-reference-v1 .workbook-version-comparison-sheet ul {
  display: grid;
  gap: 4px;
  padding-left: 18px;
}

body.chatgpt-reference-v1 .workbook-version-comparison-sheet li label {
  align-items: flex-start;
}

body.chatgpt-reference-v1 .workbook-version-comparison-sheet li span {
  min-width: 0;
  overflow-wrap: anywhere;
}

body.chatgpt-reference-v1 .workbook-version-comparison-sheet small {
  display: block;
  margin-left: 24px;
  color: var(--cg-muted);
}

body.chatgpt-reference-v1 .workbook-version-structure-warning {
  display: grid;
  gap: 4px;
  padding: 8px;
  border-radius: var(--ds-radius-md);
  background: color-mix(in srgb, var(--cg-warning-fg) 10%, transparent);
}

body.chatgpt-reference-v1 .workbook-version-comparison-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body.chatgpt-reference-v1 .workbook-ai-delta-preview {
  display: grid;
  gap: 8px;
  margin-top: 8px;
  padding: 8px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 12%, transparent);
  border-radius: var(--ds-radius-md);
}

body.chatgpt-reference-v1 .workbook-ai-delta-preview p {
  margin: 0;
}

body.chatgpt-reference-v1 .workbook-ai-delta-preview ul {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Same emphasis token .workbook-version-structure-warning already uses for
   "review before you commit" -- an AI-proposed cell change is exactly that. */
body.chatgpt-reference-v1 .workbook-ai-delta-preview-cell {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px 8px;
  border-radius: var(--ds-radius-md);
  background: color-mix(in srgb, var(--cg-warning-fg) 10%, transparent);
}

body.chatgpt-reference-v1 .workbook-ai-delta-preview-cell span {
  min-width: 0;
  overflow-wrap: anywhere;
  color: var(--cg-muted);
}

body.chatgpt-reference-v1 .workbook-ai-delta-preview-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body.chatgpt-reference-v1 [data-workbook-history] button {
  min-height: 28px;
  padding: 3px 9px;
  border: 1px solid color-mix(in srgb, var(--cg-text) 14%, transparent);
  border-radius: var(--ds-radius-pill);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  cursor: pointer;
}

body.chatgpt-reference-v1 [data-workbook-history] button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--cg-menu-border);
  background: color-mix(in srgb, var(--cg-surface, #fff) 94%, transparent);
  backdrop-filter: blur(12px);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar button {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: 18px;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar button:hover,
body.chatgpt-reference-v1 .composer-document-preview-toolbar button:focus-visible {
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar [data-pdf-sidebar][aria-pressed="true"] {
  /* 눌림은 «상태»이므로 파랑을 유지한다(doc 345 §6 — 토글 ON 과 같은 근거).
     줄이는 것은 «종»뿐: --wds-color-primary-text 는 WDS 기본 #1252b2 라 포털의 정보
     파랑 --ad-blue(#155eef)와 다른 파랑이 하나 더 생긴다. A 로 흡수한다. */
  background: var(--wds-color-primary-container);
  color: var(--ad-blue);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar button svg {
  width: 18px;
  height: 18px;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar > span:not(.composer-document-preview-toolbar-spacer) {
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-13, 13px);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar output {
  min-width: 42px;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar [data-pdf-viewer-status] {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  min-width: 1px !important;
  padding: 0 !important;
  overflow: hidden !important;
  clip-path: inset(50%) !important;
  white-space: nowrap !important;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar-divider {
  width: 1px;
  height: 22px;
  background: color-mix(in srgb, currentColor 16%, transparent);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar select,
body.chatgpt-reference-v1 .document-viewer-page-form input,
body.chatgpt-reference-v1 .document-viewer-find input {
  min-height: 32px;
  border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--cg-surface, #fff) 92%, transparent);
  color: inherit;
  font: inherit;
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar select {
  max-width: 112px;
  padding: 0 28px 0 9px;
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .document-viewer-scale-control {
  display: inline-flex;
  min-width: 0;
}

body.chatgpt-reference-v1 .document-viewer-page-form {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--cg-muted, #6f6f6f);
}

body.chatgpt-reference-v1 .document-viewer-page-form input {
  width: 48px;
  padding: 0 6px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

body.chatgpt-reference-v1 .document-viewer-find {
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--cg-menu-border);
  background: color-mix(in srgb, var(--cg-surface, #fff) 96%, transparent);
}

body.chatgpt-reference-v1 .document-viewer-find[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .document-viewer-find input {
  flex: 0 1 320px;
  min-width: 140px;
  padding: 0 10px;
}

body.chatgpt-reference-v1 .document-viewer-find button {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: inherit;
}

body.chatgpt-reference-v1 .document-viewer-find button:hover,
body.chatgpt-reference-v1 .document-viewer-find button:focus-visible {
  background: color-mix(in srgb, currentColor 10%, transparent);
}

body.chatgpt-reference-v1 .document-viewer-find button svg {
  width: 17px;
  height: 17px;
}

body.chatgpt-reference-v1 .document-viewer-find output {
  flex: 1 1 auto;
  min-width: 96px;
  color: var(--cg-muted, #6f6f6f);
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .composer-document-preview-toolbar-spacer {
  flex: 1 1 auto;
}

body.chatgpt-reference-v1 .document-viewer-layout {
  display: grid;
  grid-template-columns: 196px minmax(0, 1fr);
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-sidebar-collapsed .document-viewer-layout {
  grid-template-columns: 0 minmax(0, 1fr);
}

body.chatgpt-reference-v1 .document-viewer-sidebar {
  min-width: 0;
  overflow: auto;
  border-right: 1px solid color-mix(in srgb, currentColor 13%, transparent);
  background: color-mix(in srgb, var(--cg-text, #0d0d0d) 5%, var(--cg-surface, #fff));
  transition: opacity 140ms ease;
}

body.chatgpt-reference-v1 .is-sidebar-collapsed .document-viewer-sidebar {
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

body.chatgpt-reference-v1 .document-viewer-thumbnails {
  display: grid;
  gap: 12px;
  justify-items: center;
  padding: 14px 10px 24px;
}

body.chatgpt-reference-v1 .document-viewer-thumbnail {
  display: grid;
  justify-items: center;
  gap: 6px;
  width: 164px;
  padding: 8px;
  border: 2px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .document-viewer-thumbnail:hover,
body.chatgpt-reference-v1 .document-viewer-thumbnail:focus-visible {
  background: color-mix(in srgb, currentColor 8%, transparent);
}

body.chatgpt-reference-v1 .document-viewer-thumbnail.is-active {
  border-color: var(--wds-brand-blue, #155eef);
  background: color-mix(in srgb, var(--wds-brand-blue, #155eef) 10%, transparent);
}

body.chatgpt-reference-v1 .document-viewer-thumbnail canvas {
  display: block;
  max-width: 144px;
  min-height: 90px;
  background: #fff;
  box-shadow: 0 3px 14px rgba(15, 23, 42, 0.18);
}

body.chatgpt-reference-v1 .document-viewer-main {
  position: relative;
  min-width: 0;
  min-height: 0;
}

body.chatgpt-reference-v1 .document-viewer-stage {
  position: absolute;
  inset: 0;
  overflow: auto;
  background: #25282e;
  outline: none;
}

body.chatgpt-reference-v1 .document-viewer-stage:focus-visible {
  box-shadow: inset 0 0 0 2px var(--wds-brand-blue, #155eef);
}

body.chatgpt-reference-v1 .document-viewer-stage > .pdfViewer {
  position: relative;
  min-height: 100%;
  padding: 18px 0 44px;
  --page-border: 1px solid rgba(0, 0, 0, 0.14);
}

body.chatgpt-reference-v1 .document-viewer-stage .pdfViewer .page {
  margin: 0 auto 14px;
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.28);
}

body.chatgpt-reference-v1 .composer-document-preview-canvas-wrap {
  min-height: 0;
  padding: 20px 12px 36px;
  overflow: auto;
  text-align: center;
}

body.chatgpt-reference-v1 .composer-document-preview-canvas-wrap canvas {
  display: inline-block;
  max-width: none;
  background: #fff;
  box-shadow: 0 10px 32px rgba(15, 23, 42, 0.16);
}

body.chatgpt-reference-v1 .composer-document-preview-surface.is-hwp {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden !important;
}

body.chatgpt-reference-v1 .composer-document-preview-hwp-wrap {
  display: grid;
  grid-template-columns: auto minmax(0, auto);
  place-content: center;
  align-items: center;
  gap: 9px;
  min-height: 0;
  padding: 16px;
  overflow: auto;
  color: var(--cg-muted, #6f6f6f);
  text-align: center;
}

body.chatgpt-reference-v1 .composer-document-preview-hwp-wrap > p {
  margin: 0;
  font-size: var(--ds-text-caption-13, 13px);
  line-height: 20px;
}

body.chatgpt-reference-v1 .composer-document-preview-hwp-wrap > img {
  display: block;
  grid-column: 1 / -1;
  max-width: none;
  height: auto;
  margin: auto;
  background: #fff;
  box-shadow: 0 10px 32px rgba(15, 23, 42, 0.16);
}

body.chatgpt-reference-v1 .composer-attachment-preview .composer-document-preview-surface.is-hwp {
  display: block;
}

body.chatgpt-reference-v1 .composer-attachment-preview .composer-document-preview-hwp-wrap {
  width: 100%;
  height: 226px;
  padding: 0;
  overflow: hidden;
}

body.chatgpt-reference-v1 .composer-attachment-preview .composer-document-preview-hwp-wrap > img {
  width: 100% !important;
  max-width: 100%;
  max-height: 226px;
  object-fit: contain;
  box-shadow: none;
}

/* Composer attachment full preview reuses the common media viewer's shell/head/stage/icon
   primitives and dark canvas. Its content state stays separate because the image viewer's
   carousel/pan state machine cannot represent PDF pages, sheets, or selectable text. */
body.chatgpt-reference-v1 .composer-attachment-media-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1250;
  display: grid;
  background: rgb(8 9 11 / 88%);
  color: #fff;
}

body.chatgpt-reference-v1 .composer-attachment-media-dialog {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: 100vw;
  height: 100dvh;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  background: transparent;
  outline: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-head {
  position: relative;
  z-index: 3;
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(520px, auto) auto;
  align-items: center;
  gap: 18px;
  min-height: 68px;
  padding: 8px 18px 8px 24px;
  border-bottom: 1px solid color-mix(in srgb, var(--wds-color-inverse-on-surface) 10%, transparent);
  background: color-mix(in srgb, var(--wds-neutral-tonal-t6) 96%, transparent);
  box-shadow: var(--cg-dialog-shadow);
}

body.chatgpt-reference-v1 .composer-attachment-media-file,
body.chatgpt-reference-v1 .composer-attachment-media-actions {
  display: flex;
  align-items: center;
  min-width: 0;
  gap: 10px;
}

body.chatgpt-reference-v1 .composer-attachment-media-actions.image-preview-head-actions {
  grid-column: 3;
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools {
  display: flex;
  min-width: 0;
  justify-content: center;
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools:empty {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar {
  position: static;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  overflow: visible;
  border: 0;
  background: transparent;
  color: var(--wds-color-inverse-on-surface);
  backdrop-filter: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar button {
  color: var(--wds-color-inverse-on-surface);
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar button:hover,
body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar button:focus-visible {
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 10%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar [data-pdf-sidebar][aria-pressed="true"] {
  background: color-mix(in srgb, var(--wds-color-inverse-primary) 22%, transparent);
  color: var(--wds-color-inverse-primary);
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar > span:not(.composer-document-preview-toolbar-spacer),
body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar output {
  color: color-mix(in srgb, var(--wds-color-inverse-on-surface) 68%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar select,
body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .document-viewer-page-form input {
  border-color: color-mix(in srgb, var(--wds-color-inverse-on-surface) 18%, transparent);
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 8%, transparent);
  color: var(--wds-color-inverse-on-surface);
}

body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar-spacer {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-dialog .composer-attachment-preview-heading strong {
  color: #fff;
}

body.chatgpt-reference-v1 .composer-attachment-media-dialog .composer-attachment-preview-heading > span {
  color: rgba(255, 255, 255, 0.62);
}

body.chatgpt-reference-v1 .composer-attachment-media-icon-button {
  width: 48px;
  height: 48px;
  color: #fff;
}

body.chatgpt-reference-v1 .composer-attachment-media-icon-button svg {
  width: 20px;
  height: 20px;
}

body.chatgpt-reference-v1 .composer-attachment-media-icon-button:disabled {
  cursor: wait;
  opacity: 0.38;
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu {
  position: absolute;
  z-index: 8;
  top: calc(100% + 8px);
  right: 58px;
  display: grid;
  width: min(248px, calc(100vw - 24px));
  padding: 6px;
  border: 1px solid color-mix(in srgb, var(--wds-color-inverse-on-surface) 14%, transparent);
  border-radius: var(--ds-radius-sm);
  background: var(--wds-color-inverse-surface);
  color: var(--wds-color-inverse-on-surface);
  box-shadow: var(--cg-dialog-shadow);
  backdrop-filter: blur(18px);
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu[hidden],
body.chatgpt-reference-v1 .composer-attachment-media-utility-panel[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  min-height: 42px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button:hover,
body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button:focus-visible {
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 10%, transparent);
  outline: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button.is-danger {
  color: var(--wds-color-error-text);
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button.is-danger:hover,
body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button.is-danger:focus-visible {
  background: color-mix(in srgb, var(--wds-color-error) 14%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button svg {
  width: 18px;
  height: 18px;
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu > button kbd {
  color: color-mix(in srgb, var(--wds-color-inverse-on-surface) 58%, transparent);
  font: inherit;
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .composer-attachment-media-more-menu .is-mobile-only {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel {
  position: absolute;
  z-index: 7;
  top: 76px;
  right: 24px;
  width: min(360px, calc(100vw - 48px));
  padding: 14px;
  border: 1px solid color-mix(in srgb, var(--wds-color-inverse-on-surface) 14%, transparent);
  border-radius: var(--ds-radius-md);
  background: var(--wds-color-inverse-surface);
  color: var(--wds-color-inverse-on-surface);
  box-shadow: var(--cg-dialog-shadow);
  backdrop-filter: blur(18px);
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 36px;
  padding-bottom: 10px;
  border-bottom: 1px solid color-mix(in srgb, var(--wds-color-inverse-on-surface) 10%, transparent);
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header > div {
  display: flex;
  align-items: center;
  gap: 9px;
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header svg {
  width: 18px;
  height: 18px;
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header button {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--wds-color-inverse-on-surface);
}

body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header button:hover,
body.chatgpt-reference-v1 .composer-attachment-media-utility-panel > header button:focus-visible {
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 10%, transparent);
  outline: none;
}

body.chatgpt-reference-v1 :is(.composer-attachment-shortcut-list, .composer-attachment-file-info) {
  display: grid;
  gap: 0;
  margin: 8px 0 0;
}

body.chatgpt-reference-v1 :is(.composer-attachment-shortcut-list, .composer-attachment-file-info) > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  min-height: 38px;
}

body.chatgpt-reference-v1 :is(.composer-attachment-shortcut-list, .composer-attachment-file-info) :is(dt, dd) {
  min-width: 0;
  margin: 0;
}

body.chatgpt-reference-v1 :is(.composer-attachment-shortcut-list, .composer-attachment-file-info) dt {
  color: color-mix(in srgb, var(--wds-color-inverse-on-surface) 68%, transparent);
  font-size: var(--ds-text-caption-13, 13px);
}

body.chatgpt-reference-v1 .composer-attachment-shortcut-list kbd {
  display: inline-flex;
  min-width: 58px;
  justify-content: center;
  padding: 4px 8px;
  border: 1px solid color-mix(in srgb, var(--wds-color-inverse-on-surface) 18%, transparent);
  border-radius: var(--ds-radius-xs);
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 8%, transparent);
  color: var(--wds-color-inverse-on-surface);
  font: inherit;
  font-size: var(--ds-text-caption-12, 12px);
}

body.chatgpt-reference-v1 .composer-attachment-file-info > div {
  grid-template-columns: 92px minmax(0, 1fr);
  align-items: start;
  padding-block: 8px;
}

body.chatgpt-reference-v1 .composer-attachment-file-info dd {
  overflow-wrap: anywhere;
  font-size: var(--ds-text-caption-13, 13px);
  line-height: 1.45;
}

.composer-document-print-root {
  position: fixed;
  top: 0;
  left: -100000px;
  width: max-content;
  background: var(--ds-color-surface-solid);
  pointer-events: none;
}

.composer-document-print-page {
  width: var(--composer-print-page-width);
  height: var(--composer-print-page-height);
  overflow: hidden;
  background: var(--ds-color-surface-solid);
  break-after: page;
  page-break-after: always;
}

.composer-document-print-page:last-child {
  break-after: auto;
  page-break-after: auto;
}

.composer-document-print-page canvas {
  display: block;
  width: 100%;
  height: 100%;
}

@media print {
  @page {
    margin: 0;
  }

  body > *:not(.composer-document-print-root) {
    display: none !important;
  }

  .composer-document-print-root {
    position: static;
    display: block !important;
    width: auto;
    background: var(--ds-color-surface-solid);
  }

  .composer-document-print-page {
    margin: 0 auto;
    box-shadow: none;
  }
}

body.chatgpt-reference-v1 .composer-attachment-media-stage {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  padding: 16px 24px 24px;
  overflow: hidden;
  background: transparent;
  cursor: default;
  touch-action: pan-x pan-y;
  user-select: auto;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target {
  position: absolute;
  z-index: 8;
  top: 28px;
  left: 50%;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: min(520px, calc(100% - 64px));
  min-height: 34px;
  padding: 7px 12px;
  border: 1px solid color-mix(in srgb, var(--ds-color-accent) 22%, transparent);
  border-radius: var(--ds-radius-pill);
  background: color-mix(in srgb, var(--cg-surface) 94%, transparent);
  color: var(--cg-text);
  box-shadow: var(--ds-shadow-md);
  font-size: var(--ds-text-caption-12, 12px);
  line-height: 18px;
  transform: translateX(-50%);
  backdrop-filter: blur(12px);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target svg {
  width: 15px;
  height: 15px;
  flex: 0 0 auto;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > button {
  display: inline-grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: transparent;
  color: inherit;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > button:hover:not(:disabled) {
  background: var(--cg-hover-soft, var(--ds-color-accent-soft));
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > button:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: 1px;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > .chatgpt-library-preview-target-ask {
  width: auto;
  padding-inline: 9px;
  background: var(--cg-text);
  color: var(--cg-surface);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > .chatgpt-library-preview-version-toggle {
  width: auto;
  padding-inline: 9px;
  border: 1px solid color-mix(in srgb, var(--ds-color-accent) 30%, transparent);
  color: var(--ds-color-accent);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target > .chatgpt-library-preview-target-ask:hover:not(:disabled) {
  background: color-mix(in srgb, var(--cg-text) 84%, transparent);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-copy {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-copy > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-copy small {
  flex: 0 0 auto;
  color: var(--cg-muted);
  font: inherit;
  font-variant-numeric: tabular-nums;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  display: grid;
  gap: 4px;
  width: min(460px, calc(100vw - 48px));
  max-height: min(420px, 56vh);
  padding: 6px;
  overflow-y: auto;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--wizon-ai-radius-popover, 16px);
  background: var(--cg-menu-bg);
  box-shadow: var(--cg-menu-shadow, var(--ds-shadow-lg));
  color: var(--cg-text, #0d0d0d);
  transform: translateX(-50%);
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list > button {
  display: grid;
  gap: 5px;
  width: 100%;
  min-height: 54px;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--wizon-ai-radius-menu-row, 10px);
  background: transparent;
  color: inherit;
  text-align: left;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list > button:hover,
body.chatgpt-reference-v1 .chatgpt-library-preview-target-list > button[aria-selected="true"] {
  background: var(--cg-hover-soft, var(--ds-color-accent-soft));
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list > button:focus-visible {
  outline: 2px solid var(--wizon-ai-focus-visible-ring);
  outline-offset: -2px;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list-head strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list-head small {
  flex: 0 0 auto;
  color: var(--cg-muted);
  font: inherit;
  font-variant-numeric: tabular-nums;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list-snippet {
  display: -webkit-box;
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12, 12px);
  font-weight: 400;
  line-height: 1.45;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

body.chatgpt-reference-v1 .chatgpt-library-preview-target-list-snippet mark {
  border-radius: var(--chatgpt-route-gap-2xs);
  background: color-mix(in srgb, var(--wds-brand-blue) 12%, transparent);
  color: inherit;
}

@media (pointer: coarse) {
  body.chatgpt-reference-v1 .chatgpt-library-preview-target {
    min-height: 44px;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-target > button {
    width: 44px;
    height: 44px;
    margin-block: -7px;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-target > .chatgpt-library-preview-target-ask {
    width: auto;
    padding-inline: 12px;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-target > .chatgpt-library-preview-version-toggle {
    width: auto;
    padding-inline: 10px;
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-target-list {
    width: min(460px, calc(100vw - 24px));
  }

  body.chatgpt-reference-v1 .chatgpt-library-preview-target-list > button {
    min-height: 58px;
  }
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface {
  width: min(1600px, 100%);
  height: 100%;
  max-height: 100%;
  overflow: auto;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--ds-radius-sm);
  background: #14161a;
  color: #f4f4f4;
  box-shadow: 0 20px 64px rgba(0, 0, 0, 0.42);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-loading,
body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-state {
  place-content: center;
  grid-template-columns: auto minmax(0, 360px);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-visual {
  border: 0;
  background: transparent;
  box-shadow: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-visual img {
  width: auto;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-text {
  width: min(920px, 100%);
  background: #f8f8f6;
  color: #171717;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-text pre {
  min-height: 100%;
  padding: 28px 32px;
  color: #171717;
  font-size: 14px;
  line-height: 1.65;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface.is-spreadsheet {
  background: #f8f8f6;
  color: #171717;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .composer-document-preview-toolbar {
  color: #f4f4f4;
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(20, 22, 26, 0.94);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .composer-document-preview-toolbar button {
  color: #fff;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .composer-document-preview-toolbar > span:not(.composer-document-preview-toolbar-spacer) {
  color: rgba(255, 255, 255, 0.68);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .composer-document-preview-toolbar output {
  color: rgba(255, 255, 255, 0.68);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .document-viewer-find {
  border-color: rgba(255, 255, 255, 0.12);
  background: rgba(20, 22, 26, 0.96);
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .document-viewer-find input,
body.chatgpt-reference-v1 .composer-attachment-media-stage .composer-document-preview-toolbar select,
body.chatgpt-reference-v1 .composer-attachment-media-stage .document-viewer-page-form input {
  border-color: rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

body.chatgpt-reference-v1 .composer-attachment-media-stage .document-viewer-sidebar {
  border-color: rgba(255, 255, 255, 0.12);
  background: #1b1e23;
}

@media (max-width: 1200px) {
  body.chatgpt-reference-v1 .composer-attachment-media-head {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "file actions"
      "tools tools";
    gap: 4px 12px;
    padding-block: 8px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-file {
    grid-area: file;
    overflow: hidden;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-actions.image-preview-head-actions {
    grid-area: actions;
    grid-column: auto;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools {
    grid-area: tools;
    justify-content: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools::-webkit-scrollbar {
    display: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-viewer-tools .composer-document-preview-toolbar {
    flex: 0 0 max-content;
    width: max-content;
  }
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .document-viewer-layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 126px minmax(0, 1fr);
  }

  body.chatgpt-reference-v1 .document-viewer-sidebar {
    overflow-x: auto;
    overflow-y: hidden;
    border-right: 0;
    border-bottom: 1px solid color-mix(in srgb, currentColor 13%, transparent);
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }

  body.chatgpt-reference-v1 .document-viewer-sidebar::-webkit-scrollbar,
  body.chatgpt-reference-v1 .document-viewer-stage::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
  }

  body.chatgpt-reference-v1 .document-viewer-stage {
    scrollbar-width: none;
    -ms-overflow-style: none;
  }

  body.chatgpt-reference-v1 .document-viewer-thumbnails {
    display: flex;
    width: max-content;
    height: 100%;
    gap: 8px;
    padding: 8px 12px;
  }

  body.chatgpt-reference-v1 .document-viewer-thumbnail {
    flex: 0 0 98px;
    width: 98px;
    padding: 5px;
    scroll-snap-align: center;
  }

  body.chatgpt-reference-v1 .document-viewer-thumbnail canvas {
    max-width: 84px;
    min-height: 64px;
  }

  body.chatgpt-reference-v1 .composer-document-preview-toolbar {
    flex-wrap: nowrap;
  }

  body.chatgpt-reference-v1 .composer-document-preview-toolbar [data-pdf-sidebar] {
    display: none;
  }

  body.chatgpt-reference-v1 .composer-document-preview-toolbar-spacer {
    display: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-stage {
    padding-inline: 10px;
  }
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-button {
  min-height: 44px;
  padding: 10px 16px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--ds-radius-xl, 22px);
  background: rgba(24, 27, 32, 0.9);
  color: #fff;
  font: inherit;
  font-weight: 600;
  backdrop-filter: blur(12px);
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-button.is-header-action {
  flex: 0 0 auto;
  min-height: 40px;
  padding: 8px 14px;
  border-color: color-mix(in srgb, var(--wds-color-inverse-on-surface) 18%, transparent);
  border-radius: var(--ds-radius-sm);
  background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 8%, transparent);
  white-space: nowrap;
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-label-short {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-drawer {
  position: absolute;
  z-index: 5;
  top: 76px;
  right: 24px;
  bottom: auto;
  width: min(520px, calc(100vw - 48px));
  padding: 10px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 20px;
  background: rgba(24, 27, 32, 0.96);
  box-shadow: 0 20px 56px rgba(0, 0, 0, 0.46);
  backdrop-filter: blur(18px);
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-drawer[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-drawer .chatgpt-library-preview-composer.chatgpt-composer-shell {
  width: 100%;
  margin: 0;
}

body.chatgpt-reference-v1 .composer-attachment-media-ask-drawer .composer-prompt-body {
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "input actions";
}

/* Composer library document-version lineage. */
body.chatgpt-reference-v1 .chatgpt-library-version-badge {
  display: inline-flex;
  align-items: center;
  margin-inline-start: 8px;
  padding: 1px 6px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--ds-radius-pill);
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
  font-weight: 600;
  line-height: 18px;
  vertical-align: middle;
}

body.chatgpt-reference-v1 .chatgpt-library-version-backdrop {
  z-index: 24;
}

body.chatgpt-reference-v1 .chatgpt-library-version-dialog {
  width: min(640px, calc(100vw - 32px));
  max-height: min(720px, calc(100dvh - 48px));
  overflow: hidden;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--wizon-ai-radius-sheet);
  background: var(--cg-surface);
  box-shadow: var(--cg-dialog-shadow);
}

body.chatgpt-reference-v1 .chatgpt-library-version-header,
body.chatgpt-reference-v1 .chatgpt-library-version-toolbar,
body.chatgpt-reference-v1 .chatgpt-library-version-row {
  display: flex;
  align-items: center;
  gap: 16px;
}

body.chatgpt-reference-v1 .chatgpt-library-version-header {
  justify-content: space-between;
  padding: 20px 22px 14px;
}

body.chatgpt-reference-v1 .chatgpt-library-version-header h2,
body.chatgpt-reference-v1 .chatgpt-library-version-header p,
body.chatgpt-reference-v1 .chatgpt-library-version-toolbar p {
  margin: 0;
}

body.chatgpt-reference-v1 .chatgpt-library-version-header p,
body.chatgpt-reference-v1 .chatgpt-library-version-toolbar p,
body.chatgpt-reference-v1 .chatgpt-library-version-copy span {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
}

body.chatgpt-reference-v1 .chatgpt-library-version-toolbar {
  justify-content: space-between;
  padding: 0 22px 16px;
  border-bottom: 1px solid var(--cg-menu-border);
}

body.chatgpt-reference-v1 .chatgpt-library-version-list {
  min-height: 120px;
  overflow-y: auto;
  padding: 8px 22px 20px;
}

body.chatgpt-reference-v1 .chatgpt-library-version-row {
  justify-content: space-between;
  padding: 14px 0;
  border-bottom: 1px solid var(--cg-menu-border);
}

body.chatgpt-reference-v1 .chatgpt-library-version-row.is-current strong {
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-library-version-copy {
  display: grid;
  gap: 3px;
  min-width: 0;
}

body.chatgpt-reference-v1 .chatgpt-library-version-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
}

body.chatgpt-reference-v1 .chatgpt-library-version-actions button,
body.chatgpt-reference-v1 .chatgpt-library-version-actions a {
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  padding: 7px 9px;
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-12);
  text-decoration: none;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-library-version-actions button:hover,
body.chatgpt-reference-v1 .chatgpt-library-version-actions button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-library-version-actions a:hover,
body.chatgpt-reference-v1 .chatgpt-library-version-actions a:focus-visible {
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .chatgpt-library-version-actions .is-primary {
  background: var(--cg-text);
  color: var(--cg-surface);
}

body.chatgpt-reference-v1 .chatgpt-library-version-actions button:disabled,
body.chatgpt-reference-v1 .chatgpt-library-version-actions a[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
  cursor: default;
}

body.chatgpt-reference-v1 .chatgpt-library-version-empty {
  padding: 32px 0;
  color: var(--cg-muted);
  text-align: center;
}

@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-library-version-dialog {
    width: 100%;
    max-height: 88dvh;
    margin-top: auto;
    border-radius: var(--wizon-ai-radius-sheet) var(--wizon-ai-radius-sheet) 0 0;
  }

  body.chatgpt-reference-v1 .chatgpt-library-version-toolbar,
  body.chatgpt-reference-v1 .chatgpt-library-version-row {
    align-items: flex-start;
    flex-direction: column;
  }

  body.chatgpt-reference-v1 .chatgpt-library-version-actions {
    justify-content: flex-start;
  }
}

body.chatgpt-reference-v1 .composer-attachment-media-dialog :is(
  .composer-attachment-media-icon-button,
  .composer-attachment-media-ask-button
):focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .composer-attachment-media-icon-button:hover {
    background: rgba(255, 255, 255, 0.1);
    opacity: 1;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-ask-button:hover {
    background: color-mix(in srgb, var(--wds-color-inverse-on-surface) 14%, transparent);
  }
}

[data-theme="dark"] body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-card,
body[data-theme="dark"].chatgpt-reference-v1 .composer-chip-removable.composer-attachment-card,
[data-theme="dark"] body.chatgpt-reference-v1 .composer-attachment-preview-content,
[data-theme="dark"] body.chatgpt-reference-v1 .composer-document-preview-surface.is-visual,
[data-theme="dark"] body.chatgpt-reference-v1 .chatgpt-library-preview-document-pane > .composer-document-preview-surface {
  background: color-mix(in srgb, var(--cg-text, #f4f4f4) 8%, var(--cg-surface, #212121));
}

@media (hover: none), (pointer: coarse) {
  body.chatgpt-reference-v1 .composer-attachment-preview {
    display: none !important;
  }
}

@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])),
  body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(.composer-attachment-lane:not([hidden])) {
    min-height: 112px !important;
  }

  body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-card {
    max-width: min(220px, calc(100vw - 64px));
  }

  body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-policy-card {
    width: calc(100vw - 64px);
    max-width: calc(100vw - 64px);
  }
}

@media (max-width: 520px), (pointer: coarse) {
  body.chatgpt-reference-v1 .composer-attachment-lane:not([hidden]) {
    display: flex;
    flex-wrap: nowrap;
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: 2px;
    overscroll-behavior-inline: contain;
    /* Native horizontal swipe stays available without trapping a vertical page gesture
       that happened to start on the attachment shelf. */
    touch-action: pan-x pan-y;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
  }

  body.chatgpt-reference-v1 .composer-chip-removable.composer-attachment-card {
    flex: none;
    scroll-snap-align: start;
    scroll-snap-stop: normal;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-backdrop {
    position: fixed;
    inset: 0;
    z-index: var(--wizon-layer-scrim, 190);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    background: var(--ds-modal-overlay, rgba(15, 23, 42, 0.3));
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet {
    display: flex;
    flex-direction: column;
    box-sizing: border-box;
    width: 100%;
    min-height: min(48vh, 406px);
    max-height: min(78vh, calc(var(--wizon-vvh, 100dvh) - 32px));
    padding: 8px 16px calc(16px + var(--wizon-safe-bottom));
    overflow: hidden;
    border: 1px solid var(--ds-modal-border, rgba(15, 23, 42, 0.12));
    border-bottom: 0;
    border-radius: var(--wizon-ai-radius-sheet, var(--ds-modal-radius)) var(--wizon-ai-radius-sheet, var(--ds-modal-radius)) 0 0;
    background: var(--ds-modal-surface, #fff);
    color: var(--cg-text);
    box-shadow: var(--ds-modal-shadow, 0 -12px 36px rgba(15, 23, 42, 0.12));
    transform: translateY(var(--composer-attachment-sheet-drag-y, 0));
    transition: transform var(--wizon-motion-fast, 140ms) var(--wizon-motion-spatial-ease);
    will-change: transform;
    animation: wizon-sheet-up var(--wizon-motion-panel-duration) var(--wizon-motion-spatial-ease) backwards;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet.is-dragging {
    transition: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-grabber {
    display: grid;
    flex: none;
    place-items: center;
    width: 100%;
    min-height: 28px;
    margin-top: -4px;
    cursor: grab;
    touch-action: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet.is-dragging .composer-attachment-sheet-grabber {
    cursor: grabbing;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-handle {
    flex: none;
    align-self: center;
    width: 36px;
    height: 4px;
    border-radius: var(--wizon-ai-radius-pill, var(--ds-radius-pill));
    background: var(--wizon-ai-text-muted-2);
    opacity: 0.5;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-header {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 10px;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-close {
    display: inline-grid;
    place-items: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--ds-radius-md);
    background: transparent;
    color: var(--cg-text);
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-close:focus-visible {
    outline: 2px solid var(--wizon-ai-focus-ring, #155eef);
    outline-offset: 1px;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-close svg {
    width: 20px;
    height: 20px;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-content {
    flex: 1 1 auto;
    min-height: 0;
    margin-top: 12px;
    overflow-x: hidden;
    overflow-y: auto;
    border: 1px solid var(--ds-modal-border, rgba(15, 23, 42, 0.1));
    border-radius: var(--ds-radius-md, 12px);
    background: var(--cg-surface, #fff);
    overscroll-behavior: contain;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-image {
    display: block;
    width: 100%;
    max-height: 48vh;
    margin-top: 8px;
    object-fit: contain;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-preview {
    margin: 8px 12px 14px;
    color: var(--cg-text);
    font-size: var(--ds-text-body-14);
    line-height: 1.55;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-preview.is-empty {
    color: var(--cg-muted);
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-content .composer-document-preview-surface {
    min-height: 220px;
    max-height: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-content .composer-document-preview-surface.is-visual img {
    max-height: 48vh;
  }

  body.chatgpt-reference-v1 .composer-attachment-sheet-full {
    flex: none;
    min-height: 44px;
    margin-top: 12px;
    border: 0;
    border-radius: var(--wds-radius-md);
    background: var(--cg-text, #0d0d0d);
    color: var(--cg-surface, #fff);
    font: inherit;
    font-weight: 600;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-head {
    min-height: calc(112px + env(safe-area-inset-top, 0px));
    padding: calc(6px + env(safe-area-inset-top, 0px)) 8px 6px 12px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-file {
    gap: 8px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-file .composer-attachment-preview-icon {
    width: 36px;
    height: 36px;
    border-radius: 9px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-actions {
    gap: 0;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-ask-button.is-header-action {
    min-height: 40px;
    padding-inline: 10px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-ask-label {
    display: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-ask-label-short {
    display: inline;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-icon-button {
    width: 44px;
    height: 44px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-print-button {
    display: none;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-more-menu {
    top: calc(100% + 4px);
    right: 44px;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-more-menu .is-mobile-only {
    display: grid;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-utility-panel {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px));
    border-width: 1px 0 0;
    border-radius: var(--ds-radius-lg) var(--ds-radius-lg) 0 0;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-stage {
    padding: 8px 0 calc(8px + env(safe-area-inset-bottom, 0px));
  }

  body.chatgpt-reference-v1 .composer-attachment-media-stage > .composer-document-preview-surface {
    width: 100%;
    height: 100%;
    border-inline: 0;
    border-radius: 0;
  }

  body.chatgpt-reference-v1 .composer-attachment-media-ask-drawer {
    top: auto;
    right: 0;
    bottom: 0;
    left: 0;
    width: auto;
    padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px));
    border-width: 1px 0 0;
    border-radius: 20px 20px 0 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .composer-attachment-sheet,
  body.chatgpt-reference-v1 .composer-document-preview-spinner {
    animation: none;
  }
}

/* Server-backed archive and trash routes. Rows remain table-like on desktop and
   turn their actions into a wrapped second line on narrow touch screens. */
body.chatgpt-reference-v1 .chatgpt-route-action,
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs);
  background: var(--cg-surface, #fff);
  color: var(--cg-text, #0d0d0d);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-route-action svg,
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button svg { width: 16px; height: 16px; }

body.chatgpt-reference-v1 .chatgpt-route-action:hover,
body.chatgpt-reference-v1 .chatgpt-route-action:focus-visible,
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button:hover,
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button:focus-visible { background: var(--cg-hover, #f5f5f5); outline: none; }

body.chatgpt-reference-v1 .chatgpt-route-action.is-danger,
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button.is-danger,
body.chatgpt-reference-v1 .chatgpt-lifecycle-empty.is-error { color: #b42318; }

body.chatgpt-reference-v1 .chatgpt-lifecycle-list { border-top: 1px solid var(--ds-color-line); }

body.chatgpt-reference-v1 .chatgpt-lifecycle-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 76px;
  padding: 12px 2px;
  border-bottom: 1px solid var(--ds-color-line);
}

body.chatgpt-reference-v1 .chatgpt-lifecycle-row-icon { display: inline-grid; place-items: center; color: var(--cg-muted, #737373); }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-icon svg { width: 19px; height: 19px; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-copy { min-width: 0; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-title { display: flex; align-items: center; min-width: 0; gap: 7px; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-title strong { overflow: hidden; min-width: 0; color: var(--cg-text, #0d0d0d); font-size: var(--ds-text-body-14); font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-copy p { overflow: hidden; margin: 4px 0 0; color: var(--cg-muted, #737373); font-size: var(--ds-text-caption-12); line-height: 18px; text-overflow: ellipsis; white-space: nowrap; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-retention { flex: 0 0 auto; color: var(--cg-muted, #737373); font-size: var(--ds-text-caption-12); }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-meta { display: flex; flex-wrap: wrap; gap: 5px 8px; margin-top: 4px; font-size: var(--ds-text-caption-12); line-height: 18px; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-purge { color: var(--cg-muted, #737373); font-weight: 500; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-purge.is-warning { color: #b54708; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions { display: flex; align-items: center; gap: 7px; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-empty { display: grid; justify-items: center; gap: 8px; padding: 72px 16px; color: var(--cg-muted, #737373); text-align: center; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-empty strong { color: var(--cg-text, #0d0d0d); font-size: var(--ds-text-body-15); font-weight: 500; }
body.chatgpt-reference-v1 .chatgpt-lifecycle-empty span { font-size: var(--ds-text-caption-13); }

@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row { grid-template-columns: 24px minmax(0, 1fr); align-items: start; }
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions { grid-column: 2; flex-wrap: wrap; }
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button { flex: 1 1 auto; }
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-title { flex-wrap: wrap; }
}

/* 20260802-lifecycle-row-mobile-title (북극성 ③ 배치 3): 폰에서 휴지통/아카이브 행 제목이
   한 줄로 강제돼 잘렸다. 라이브 /trash 390px 실측: 제목 열이 316px 인데 내용은 401~766px 라
   최대 450px(대략 2/3)가 말줄임으로 사라졌고, 사라지는 쪽이 하필 두 대화를 구별해 주는
   뒷부분이었다(「2026년 7월 18일부터 제주 2일 가족 자동차 여행 사진 …」). 데스크톱은 폭이
   충분해 한 줄 그대로 두고(공유 규칙의 nowrap 은 계약이 함께 핀한다), 폰에서만 2줄까지 감싼다.
   미리보기 <p> 도 같은 이유로 함께 푼다 — 제목과 같은 문장이면 렌더러가 아예 안 그린다. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-title strong,
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-copy > p {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    line-height: 1.35;
    white-space: normal;
  }
}

/* 20260726-trash-mobile-topbar (T3b): mobile decluttering for the archive/trash route.
   (1) the subtitle under the H1 explains server behaviour that doesn't need a whole line on a
   small screen — the fixed top app bar already shows the route title, so the subtitle is pure
   restatement there. Scoped to .chatgpt-lifecycle-page only (NOT the shared .chatgpt-route-page
   -head selector) because /scheduled renders its own unrelated <p> subtitle inside the very same
   header shape and must stay untouched.
   (2) the desktop "대화 휴지통 비우기" text button now has a same-purpose icon twin in the fixed
   topbar (see .chatgpt-mobile-topbar [data-mobile-trash-empty] wiring in
   syncPortalRouteSurfaceVisibility) — mirrors the established library precedent just above
   (20260710-library-new-in-topbar hides .chatgpt-route-primary in the route head once its own
   topbar "+" twin exists), so the redundant full-text copy is hidden here rather than duplicated
   under one sticky header. Desktop is untouched — this whole block is <=900px only. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-lifecycle-page .chatgpt-route-page-head p {
    display: none;
  }
  body.chatgpt-reference-v1 .chatgpt-lifecycle-page .chatgpt-route-page-actions {
    display: none;
  }
}

/* 20260729-touch-target-a2 (WCAG 2.5.5 / Apple HIG 44pt): 휴지통·아카이브 행 액션(복원/영구
   삭제)과 워크스페이스 칩(전체/채팅/업무/코딩)이 390px 실측에서 각각 142x36 / 167x36 / 73x40 —
   너비는 이미 44 이상이라 세로만 44로 올린다. 가로 padding은 그대로 둔다: 복원↔영구 삭제
   사이 가로 간격이 7px뿐이라(파괴적 액션이 바로 옆) 가로로 넓히면 오탭 위험이 커진다. 세로는
   행 높이 168px 중 132px가 여유라 겹침 없이 들어간다(실측). 44px는 이 파일 전역에 이미 40곳
   넘게 리터럴로 쓰인 기존 관례(예: .btn--lg, line 7291)를 따른 것 — 이 값에 맞는 --ds-* 스케일
   토큰이 없어(스페이싱 스케일 최댓값 --ds-space-10=64px) 새 토큰을 만들지 않고 그 관례를 그대로
   따른다. 칩은 .chatgpt-trash-category-tabs로만 스코프해 다른 라우트의 .chatgpt-route-tabs
   (예: /projects)는 건드리지 않는다. 데스크톱은 마우스라 44px가 불필요하고 지금 밀도가 의도된
   디자인이므로 <=900px only. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button {
    min-height: 44px;
  }
  body.chatgpt-reference-v1 .chatgpt-trash-category-tabs button {
    min-height: 44px;
  }
}

/* Title row + workspace chips pin below the fixed topbar, only the row list scrolls below them —
   mirrors .chatgpt-drive-mobile-stickyhead above verbatim. `display: contents` dissolves the
   wrapper on desktop so `.chatgpt-route-page-inner`'s existing layout is byte-for-byte unchanged
   there; the <=900px override is the only visible change. */
body.chatgpt-reference-v1 .chatgpt-lifecycle-mobile-stickyhead {
  display: contents;
}
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-lifecycle-mobile-stickyhead {
    display: flex;
    flex-direction: column;
    gap: var(--chatgpt-route-gap-xs);
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--cg-bg);
    padding-bottom: var(--chatgpt-route-gap-xs);
  }
}

/* T2 unified trash (docs/product/215): 전체/대화/드라이브 category chips reuse
   .chatgpt-route-tabs verbatim (same markup/behaviour as the projects page's own filter tabs) —
   only the count badge and the row-level category badge/original-path are new here. No new
   color tokens: --cg-muted, --cg-hover-soft, --ds-badge-info-bg, --ds-badge-info-fg,
   --ds-radius-pill, --ds-radius-md and --ds-text-caption-12 all already exist and are referenced
   WITHOUT a literal hex/rgb fallback. (No glob-star before a slash inside a CSS comment — that
   sequence closes the comment early and silently drops the next rule; this file has been burned
   by it three times in this track.)
   The anti-drift ratchet has zero headroom on raw-color/raw-rgb (measured: 2608/2608 and
   658/658), but that only bars new HEX/RGB LITERALS — `background`/`color` are not scanned
   properties at all, so a token-expressed distinction is free. See
   tests/test_design_system_contract.py:70-73 for the scanned pattern set. */
body.chatgpt-reference-v1 .chatgpt-route-tabs-count {
  margin-left: 4px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-trash-category-badge {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--ds-radius-pill);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-trash-category-badge svg { width: 13px; height: 13px; }

/* The two badges were byte-identical grey (measured: both rgb(244,244,244)/rgb(111,111,111)),
   which left a mixed list with no colour signal at all — the badge WORD was the only cue, at
   caption size. "Zero ratchet headroom" only forbids new raw hex/rgb: `background`/`color` are
   not scanned properties, and --ds-badge-info-* is an existing Tier-3 token pair defined for
   both themes (shared/design-tokens/component.css), so this distinction costs the ratchet
   nothing. Drive = the foreign source being merged in, so it takes the accent; conversation
   stays neutral as the page's native content. */
body.chatgpt-reference-v1 .chatgpt-trash-category-badge--drive {
  background: var(--ds-badge-info-bg);
  color: var(--ds-badge-info-fg);
}

/* doc 228 P3 — conversation topic tag pill (trash/archive rows). Same pill geometry as
   .chatgpt-trash-category-badge just above (radius/padding/caption size) so the two read as one
   family, but deliberately NOT filled and NOT iconed: the category badge answers "what KIND of
   row is this" (대화/드라이브) — an axis already visible one level up in the workspace filter chips
   — while this pill answers "what is this conversation ABOUT", brand-new information the reader
   has never seen elsewhere on this screen. Giving it the same filled weight as the category badge
   would make two different kinds of fact compete for the same attention; a hairline outline with
   no icon keeps the family resemblance (still a pill, still caption-sized) while reading as
   lighter, secondary, descriptive rather than classificatory.
   Border token: NOT --cg-border — that name looks like this file's other generic tokens but is
   never actually defined at :root (verified: only ever consumed with a literal fallback wherever
   it appears elsewhere in this file, so it silently renders as no border at all wherever no
   fallback is given — confirmed live, this rule rendered with zero border before the fix, using
   that name). --ds-color-line is the real, already-defined Tier-2 semantic border token
   (shared/design-tokens/semantic.css, light+dark) already used without a fallback dozens of times
   elsewhere in this exact file (e.g. line 1471), so this adds no new color and needs none. */
body.chatgpt-reference-v1 .chatgpt-topic-tag-badge {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 500;
  white-space: nowrap;
}

/* Partial-failure banner: one source is missing, the rest of the list below is real. Deliberately
   NOT .is-error styling — an alert-red block over a working list would read as "this list is
   broken" when it is merely incomplete. */
body.chatgpt-reference-v1 .chatgpt-lifecycle-notice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
  padding: 10px 14px;
  border-radius: var(--ds-radius-md, 12px);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-trash-original-path {
  flex: 0 0 auto;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

/* Restore is disabled (not hidden) for a viewer-role drive row — the row itself already carries
   a title= explaining why, this is only the visual half. */
body.chatgpt-reference-v1 .chatgpt-lifecycle-row-actions button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

body.chatgpt-reference-v1 .chatgpt-trash-load-more {
  margin-top: 12px;
}

/* docs/product/215-wizon-drive-design.md DR-1b explorer page. Rows/empty/toolbar
   all reuse .chatgpt-route-page-* and .chatgpt-lifecycle-* above as-is (no new rules
   needed for those) — only the breadcrumb, the folder-name-as-button reset, the
   inline feedback line, and the new-folder dialog are new here. */
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-history-controls,
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-trail {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
body.chatgpt-reference-v1 .chatgpt-drive-history-controls {
  flex: 0 0 auto;
  padding-right: 4px;
  border-right: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-history-button {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-history-button svg { width: 16px; height: 16px; }
body.chatgpt-reference-v1 .chatgpt-drive-history-button:hover { background: var(--cg-hover); }
body.chatgpt-reference-v1 .chatgpt-drive-history-button:disabled { color: var(--cg-muted); opacity: 0.45; cursor: default; }
body.chatgpt-reference-v1 .chatgpt-drive-history-button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 7px;
  border: none;
  border-radius: var(--ds-radius-xs);
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item svg { width: 14px; height: 14px; }
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item:hover,
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item:focus-visible { background: var(--cg-hover); }
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-item.is-current { color: var(--cg-text); font-weight: 500; }
body.chatgpt-reference-v1 .chatgpt-drive-breadcrumb-sep { color: var(--cg-muted); }

body.chatgpt-reference-v1 .chatgpt-drive-row-open {
  display: block;
  min-width: 0;
  border: none;
  background: transparent;
  padding: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-row-open:hover strong,
body.chatgpt-reference-v1 .chatgpt-drive-row-open:focus-visible strong { text-decoration: underline; }

body.chatgpt-reference-v1 .chatgpt-drive-feedback,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt {
  margin: 0;
  padding: 8px 12px;
  border-radius: var(--ds-radius-xs);
  background: var(--cg-hover-soft, var(--cg-hover));
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
body.chatgpt-reference-v1 .chatgpt-drive-feedback button,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt button {
  min-width: 44px;
  min-height: 44px;
  border: none;
  border-radius: var(--ds-radius-xs);
  padding: 4px 10px;
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-feedback button:hover,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt button:hover {
  background: var(--cg-hover);
}
body.chatgpt-reference-v1 .chatgpt-drive-feedback button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt button:focus-visible {
  background: var(--cg-hover);
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-feedback button:disabled,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt button:disabled {
  color: var(--cg-muted);
  cursor: wait;
}

/* A destructive operation remains a local, readable receipt while it is pending and after an
   error; this is intentionally a compact Drive surface rather than a global toast. */
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt {
  display: flex;
  align-items: center;
  min-height: 40px;
  margin: 0;
  padding: 8px 12px;
  border-left: 3px solid var(--cg-focus-ring);
  background: var(--cg-hover-soft, var(--cg-hover));
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt > span {
  min-width: 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt.is-pending {
  color: var(--cg-muted);
}

body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt.is-error,
body.chatgpt-reference-v1 .chatgpt-drive-operation-receipt.is-partial {
  border-left-color: var(--cg-danger-fg);
  color: var(--cg-danger-fg);
}

body.chatgpt-reference-v1 .chatgpt-drive-new-folder-dialog form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
}
body.chatgpt-reference-v1 .chatgpt-drive-new-folder-dialog label {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions button {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 6px 12px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions button[type="submit"] {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  border-color: transparent;
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions button:hover { outline: none; }
}
body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-dialog-actions button[data-drive-action="permissions-save"] {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
  border-color: transparent;
}

/* DR-2 permission-grant dialog (docs/product/215-wizon-drive-design.md §9). Reuses
   .chatgpt-library-popover/.chatgpt-drive-dialog-actions/.ds-input/.ds-chip as-is —
   only the list/row/add-row layout below is new (no raw color/radius/shadow/font-size,
   anti-drift net-zero: every declaration here is spacing/layout, or points at a
   --cg-* and --ds-* token already used by the sibling DR-1b dialog above). */
body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog {
  position: fixed;
  z-index: var(--wds-z-modal);
  top: 50%;
  left: 50%;
  right: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 12px;
  width: min(560px, calc(100vw - (var(--wizon-ai-thread-gutter) * 2)));
  min-width: 520px;
  max-width: 560px;
  max-height: min(80vh, 760px);
  transform: translate(-50%, -50%);
  box-shadow: var(--cg-shadow-float-lg), 0 0 0 100vmax var(--wizon-scrim);
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-head h2 {
  margin: 0;
  font-size: var(--ds-text-body-15);
  font-weight: 600;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 220px;
  overflow-y: auto;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-scroll {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-md);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-xs);
  padding-bottom: var(--chatgpt-route-gap-md);
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section:last-child {
  border-bottom: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section-head > span:first-child {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section-head strong {
  padding: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-section-head small,
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row-copy span,
body.chatgpt-reference-v1 .chatgpt-drive-share-list small {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--ds-radius-xs);
  background: var(--cg-hover-soft, var(--cg-hover));
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row.is-inherited {
  border: 1px dashed var(--cg-menu-border, var(--line));
  background: transparent;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row-copy {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  gap: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row-copy strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row select.ds-input {
  flex: 0 0 auto;
  width: auto;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-owner-note {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-empty {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  padding: 8px 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-add-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-add-row select.ds-input {
  flex: 1 1 140px;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-empty-hint {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  margin: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-inheritance-chain {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-inheritance-chain li {
  display: inline-flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  min-height: var(--chatgpt-route-control-height);
  padding: 0 var(--chatgpt-route-gap-xs);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-inheritance-chain li.is-boundary {
  border-color: var(--cg-focus-visible-ring, var(--cg-focus-ring));
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-inheritance-chain svg {
  width: 14px;
  height: 14px;
}
body.chatgpt-reference-v1 .chatgpt-drive-share-create,
body.chatgpt-reference-v1 .chatgpt-drive-share-created {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--chatgpt-route-gap-xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-share-create select.ds-input {
  flex: 1 1 120px;
}
body.chatgpt-reference-v1 .chatgpt-drive-share-created label {
  display: flex;
  flex: 1 1 280px;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-share-created input {
  width: 100%;
}
body.chatgpt-reference-v1 .chatgpt-drive-share-list {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-share-list li {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  min-height: var(--chatgpt-route-control-height);
  padding: var(--chatgpt-route-gap-xs);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-share-list li > span:first-child {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-share-list button,
body.chatgpt-reference-v1 .chatgpt-drive-permissions-row > button {
  min-height: var(--chatgpt-route-control-height);
  padding: 0 var(--chatgpt-route-gap-xs);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-permissions-error {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-12);
}

/* DR-3 administrator review queue and audit log. */
body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog {
  position: fixed;
  z-index: var(--wds-z-modal);
  top: 50%;
  left: 50%;
  right: auto;
  display: flex;
  flex-direction: column;
  width: min(720px, calc(100vw - (var(--wizon-ai-thread-gutter) * 2)));
  min-width: 640px;
  max-width: 720px;
  max-height: min(84vh, 820px);
  gap: var(--chatgpt-route-gap-sm);
  padding: var(--chatgpt-route-gap-md);
  transform: translate(-50%, -50%);
  box-shadow: var(--cg-shadow-float-lg), 0 0 0 100vmax var(--wizon-scrim);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-head,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case > header,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-head > span,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case header > span:first-child,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case li > span:first-child,
body.chatgpt-reference-v1 .chatgpt-drive-handover-create > span:first-child {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: var(--chatgpt-route-gap-2xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-head h2 {
  margin: 0;
  font-size: var(--ds-text-title-20);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-head small,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case small,
body.chatgpt-reference-v1 .chatgpt-drive-handover-create small {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-head button,
body.chatgpt-reference-v1 .chatgpt-drive-governance-tabs button,
body.chatgpt-reference-v1 .chatgpt-drive-handover-case button,
body.chatgpt-reference-v1 .chatgpt-drive-governance-error button {
  min-height: var(--chatgpt-route-control-height);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-tabs,
body.chatgpt-reference-v1 .chatgpt-drive-inspector-tabs {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-tabs button,
body.chatgpt-reference-v1 .chatgpt-drive-inspector-tabs button {
  min-height: var(--chatgpt-route-control-height);
  padding: 0 var(--chatgpt-route-gap-sm);
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-tabs button[aria-selected="true"],
body.chatgpt-reference-v1 .chatgpt-drive-inspector-tabs button[aria-selected="true"] {
  border-bottom-color: var(--cg-focus-visible-ring, var(--cg-focus-ring));
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-inspector-tabs button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog button:disabled,
body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog button:disabled {
  opacity: 0.45;
  cursor: default;
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-body {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-sm);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
body.chatgpt-reference-v1 .chatgpt-drive-handover-create {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(180px, 0.8fr) auto;
  align-items: end;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-lg);
}
body.chatgpt-reference-v1 .chatgpt-drive-handover-case {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-lg);
}
body.chatgpt-reference-v1 .chatgpt-drive-handover-case ul {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-handover-case li {
  padding: var(--chatgpt-route-gap-xs);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-handover-case select {
  min-width: 160px;
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-error {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-xs);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-governance-loading {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-rag-governance,
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-copy,
body.chatgpt-reference-v1 .chatgpt-drive-rag-governance > header > span {
  display: flex;
  min-width: 0;
  flex-direction: column;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-governance {
  gap: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-governance > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-governance > header > span,
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-copy {
  gap: var(--chatgpt-route-gap-2xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-governance small,
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-copy small {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-filters {
  display: flex;
  gap: var(--chatgpt-route-gap-2xs);
  overflow-x: auto;
  scrollbar-width: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-filter {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  min-height: var(--chatgpt-route-control-height);
  padding: 0 var(--chatgpt-route-gap-xs);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-filter.is-selected {
  border-color: var(--cg-text);
  background: var(--cg-text);
  color: var(--cg-surface);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-list {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-row {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-xs);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-control);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-icon .wizon-file-type-icon {
  width: 32px;
  height: 32px;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-index-copy strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-status {
  display: inline-flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-status i,
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-status[data-status="ready"] i,
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-state[data-status="ready"] .chatgpt-drive-ai-index-dot {
  background: var(--ad-green);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-status[data-status="failed"] i,
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-state.is-error .chatgpt-drive-ai-index-dot {
  background: var(--cg-danger-fg);
}
body.chatgpt-reference-v1 .chatgpt-drive-rag-status[data-status="processing"] i,
body.chatgpt-reference-v1 .chatgpt-drive-rag-status[data-status="queued"] i {
  background: var(--ad-amber);
}

body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-dialog {
  position: fixed;
  z-index: var(--wds-z-modal);
  top: 50%;
  left: 50%;
  right: auto;
  display: flex;
  flex-direction: column;
  width: min(560px, calc(100vw - (var(--wizon-ai-thread-gutter) * 2)));
  min-width: 440px;
  max-width: 560px;
  max-height: min(80vh, 760px);
  gap: var(--chatgpt-route-gap-sm);
  padding: var(--chatgpt-route-gap-md);
  overflow: hidden;
  transform: translate(-50%, -50%);
  box-shadow: var(--cg-shadow-float-lg), 0 0 0 100vmax var(--wizon-scrim);
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head > span {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head h2 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-title-20);
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head small {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head button {
  display: inline-grid;
  place-items: center;
  min-width: 44px;
  min-height: 44px;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-head button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-body button:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: 2px;
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-body {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* 20260812-drive-permissions-mobile-targets: production 390x844 QA measured
   the native selects/actions at 31–36px. Keep the compact desktop dialog,
   while making every direct permission action a non-overlapping 44px target
   on touch layouts. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog,
  body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-dialog {
    min-width: 0;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog select.ds-input,
  body.chatgpt-reference-v1 .chatgpt-drive-permissions-dialog button,
  body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog select.ds-input,
  body.chatgpt-reference-v1 .chatgpt-drive-governance-dialog button,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-activity-dialog button {
    min-width: 44px;
    min-height: 44px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-permissions-row {
    align-items: stretch;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-handover-create {
    grid-template-columns: 1fr;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-handover-case li {
    align-items: stretch;
    flex-direction: column;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-rag-index-row {
    grid-template-columns: 36px minmax(0, 1fr);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-rag-index-row > .chatgpt-route-action {
    grid-column: 1 / -1;
    justify-content: center;
  }
}

/* ============================================================================
 * E1 2패널 탐색기(docs/product/215-wizon-drive-design.md) — 브레드크럼은 하단 경로 바로
 * 이동. 라우트 자체는 중앙정렬 document 컨테이너를 풀고 전체폭으로 전환한다(아래 첫 블록,
 * #artifactPanel의 ID+attribute 조합으로 베이스 .chatgpt-route-page보다 특이도를 높이는
 * 패턴을 그대로 미러). 색/반경은 전부 기존 --cg-* 와 --chatgpt-route-* 토큰 재사용 — 이 블록의
 * raw 리터럴은 없다(anti-drift 순증 0).
 *
 * 20260724-drive-shellfit (docs/product/215, 셸 정합 재구성): 위즈온 앱 셸이 이미 왼쪽에
 * 260px 앱 사이드바(.app-shell)를 갖고 있어, E1이 그 옆에 또 240px 폴더 트리 레일을 두면
 * "이중 사이드바"로 보였다 — 그 좌측 트리 패널(옛 .chatgpt-drive-tree*)을 데스크톱에서도
 * 완전히 없애고, 목록은 전체폭 브라우즈로, 그 오른쪽을 선택 상태 기반 인스펙터 패널로
 * 대체했다. 트리 렌더 CSS는 지금 실제 DOM 어디에도 쓰이지 않아 통째로 제거한다(JS의
 * renderDriveTreePane/renderDriveTreeNode 자체는 남아 있지만 renderDrivePage가 더 이상
 * 호출하지 않는다 — 트리 캐시(state.drive.tree.childrenByParentId)는 Miller 뷰 조상 컬럼이
 * 계속 쓰므로 그대로 둔다).
 * ========================================================================== */
html[data-portal-route="/drive"] #portalPage.chatgpt-route-page {
  /* 20260725-drive-redesign R1: 800px 중앙문서 캡을 풀되 전체폭이 아니라 파인더식
     넓은 중앙 콘텐츠(1000px)로 재중앙정렬한다 — 죽은 우측 여백 제거. 인스펙터는 더 이상
     이 흐름 안 320px 컬럼이 아니라 아티팩트 패널과 동일한 position:fixed 오버레이(아래). */
  --chatgpt-drive-content-max-width: 1000px;
  width: 100%;
  max-width: var(--chatgpt-drive-content-max-width);
  margin: 0 auto;
  padding: var(--chatgpt-route-page-top) var(--wizon-ai-thread-gutter) var(--chatgpt-route-page-bottom);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
html[data-portal-route="/drive"] #portalPage .chatgpt-route-page-inner {
  flex: 1;
  min-height: 0;
}

/* 20260724-drive-shellfit: [전체폭 브라우즈][320px 인스펙터] — 옛 [240px 트리][1fr 목록]을
   대체. 인스펙터가 닫히면 .chatgpt-drive-explorer--inspector-closed가 붙어 1열로 접힌다
   (renderDriveInspectorPane이 닫힘 상태에서 마크업 자체를 만들지 않으므로, 빈 grid 트랙이
   생기지 않도록 트랙 정의도 같이 접어야 한다). */
/* 20260725-drive-redesign R1: 인스펙터가 흐름 밖 position:fixed 오버레이로 빠졌으므로
   explorer는 인스펙터 열림/닫힘과 무관하게 항상 단일 컬럼(중앙 콘텐츠 전체폭). 옛 [1fr 320px]
   2컬럼 트랙은 제거 — 인스펙터가 목록을 밀지 않고 그 위에 얹힌다(아티팩트 패널과 동일 계열). */
body.chatgpt-reference-v1 .chatgpt-drive-explorer {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--chatgpt-route-gap-md);
  min-height: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--inspector-closed {
  grid-template-columns: minmax(0, 1fr);
}

/* 우측 컬럼 목록(선택/이름/크기/수정일). 헤더와 행이 같은 컬럼 폭을 공유해 정렬을
   맞추고, 행에만 마지막에 컨텍스트 메뉴("⋮") 트랙을 더한다(헤더는 그 트랙을 비워 둔다 —
   두 selector가 동일 폭을 쓰므로 정렬은 깨지지 않는다).
   20260724-drive-explorer-e2b: 맨 앞에 다중 선택 체크박스 컬럼을 추가하고, 기존에 각 행마다
   따로 있던 다운로드/삭제/권한 관리 버튼은 컨텍스트 메뉴로 통합되어 마지막 트랙이 "⋮" 트리거
   하나로 줄었다(그만큼 폭도 줄여 min-width로 보정).
   20260725-drive-row-r2b: 유형 트랙(96px)을 통째로 제거 — 유형/권한 정보는 이제 이름 셀
   안의 subline(둘째 줄)으로 옮겨 갔다(renderDriveColumnRow 참고). 남는 폭은 이름의
   minmax(0, 1fr) 트랙이 그대로 흡수한다. min-width도 지워진 트랙+그 간격만큼(96px + 8px
   gap) 그대로 줄여, 이름 트랙이 실제로 확보하던 최소 폭(옛 600px 기준 약 172px)을 그대로
   보존한다. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-pane {
  min-width: 0;
  overflow-x: auto;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-head,
body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 96px 128px 40px;
  align-items: center;
  gap: 8px;
  min-width: 496px;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-cell-select {
  display: flex;
  align-items: center;
  justify-content: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-select-checkbox {
  width: 16px;
  height: 16px;
  margin: 0;
  cursor: pointer;
  /* 20260725-drive-redesign R2: 체크 표시를 네이티브 파랑이 아니라 잉크로 — 파랑은 계정 아바타
     전용(모노 규칙). 토큰 구동이라 다크에서는 밝은 잉크로 flip. */
  accent-color: var(--cg-text);
}
/* 20260725-drive-redesign R2: 미세 포인터(데스크톱)에서는 체크박스를 호버/선택/포커스에서만
   드러내 평소 행을 조용하게 유지 — 터치(호버 없음)에서는 항상 보여 선택 가능성을 지킨다(doc147). */
@media (hover: hover) and (pointer: fine) {
  body.chatgpt-reference-v1 .chatgpt-drive-select-checkbox {
    opacity: 0;
    transition: opacity 0.12s ease;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row:hover .chatgpt-drive-select-checkbox,
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-selected .chatgpt-drive-select-checkbox,
  body.chatgpt-reference-v1 .chatgpt-drive-select-checkbox:focus-visible,
  body.chatgpt-reference-v1 .chatgpt-drive-select-checkbox:checked {
    opacity: 1;
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-selected {
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-row:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-search-result:focus-visible {
  outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
  outline-offset: -2px;
}
/* 20260725-drive-redesign R2: 선택 = 표면 상승 + 좌측 잉크 바(색 하이라이트 없이 명도/위치로만). */
body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-selected::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--cg-text);
}
/* 좌측 잉크 바는 리스트/밀러 같은 각진 행의 스파인 어포던스다. 라운드 카드(그리드·갤러리
   뷰, border-radius control)에서는 직각 바가 모서리를 삐져나오므로 끄고, 카드 선택은 이미
   있는 표면 상승(is-selected 배경)으로만 표시한다 — 4뷰 공유 행 마크업의 뷰별 분기. */
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row.is-selected::before,
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row.is-selected::before {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-head {
  padding: 8px 12px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  text-transform: uppercase;
  /* 20260725-drive-redesign R2: 헤더 라벨 트래킹을 넓혀 "설계된" 캡션 톤(정렬은 행과 동일 패딩). */
  letter-spacing: 0.06em;
}
/* 20260725-drive-redesign R2: 30px 아이콘 칩과 함께 행 높이가 ~46px로 올라가 리듬이 생긴다.
   position:relative는 선택 좌측 잉크 바(::before)의 앵커. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
  position: relative;
  padding: 8px 12px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row:hover {
    background: var(--cg-hover-soft);
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-cell {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  /* 20260725-drive-redesign R2: 크기/수정일 숫자를 tabular-nums로 우측 정렬 시 자리수 맞춤(질서). */
  font-variant-numeric: tabular-nums;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-cell-name {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-cell-name strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: block;
  min-width: 0;
  color: var(--cg-text);
  font-weight: 500;
  /* 20260725-drive-redesign R2: 파일명에 살짝의 마이너스 자간 — 프리미엄 리스트의 "설계된" 톤. */
  letter-spacing: -0.01em;
}
/* 20260725-drive-row-r2b: 이름(strong) + subline(둘째 줄)을 세로로 쌓는 래퍼 — 파일 행은
   .chatgpt-drive-columns-cell-name의 바로 아래 자식, 폴더 행은 .chatgpt-drive-row-open
   버튼 안쪽 자식이라 depth가 다르지만 이 규칙은 depth와 무관하게 둘 다 잡는다. min-width:0은
   부모(cell-name, 폴더는 그 위에 .chatgpt-drive-row-open까지)가 flex 아이템일 때 이 래퍼가
   내용 크기로 안 늘어나고 정상적으로 줄어들도록(그래야 strong/subline의 ellipsis가 먹는다). */
body.chatgpt-reference-v1 .chatgpt-drive-columns-name-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 2px;
}
/* subline = 파일 유형(driveFileTypeMeta 라벨) 또는 폴더 내 권한(driveRoleLabel), 실제
   컬럼에서 옮겨온 값 — 톤은 헤더 캡션과 같은 --ds-text-caption-12 + --cg-muted. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-subline {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
/* File-type assets already own their complete silhouette. Keep this wrapper geometry-only so
   the transparent SVG never gains a second tile, border, or clipped corner around it. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-icon {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  overflow: hidden;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-icon .wizon-file-type-icon {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
}
/* 폴더 칩은 잉크 글리프로 위계 강조(색상 구분이 아니라 명도 — 모노 규칙 준수). */
body.chatgpt-reference-v1 .chatgpt-drive-columns-row[data-drive-folder-row-id] .chatgpt-drive-columns-icon {
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns-icon svg { width: 16px; height: 16px; }
/* 모노 잉크(색상 구분 금지) — 파일 유형 아이콘은 색이 아니라 glyph로만 구분한다. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  flex-wrap: wrap;
}

/* M3 스와이프 삭제(우→좌) — 모바일 전용 기능이지만, 래퍼 자체(overflow:hidden 앵커 + 행의
   touch-action)는 뷰포트와 무관하게 항상 필요하다(행이 그 안에서만 좌우로 움직여야 페이지가
   안 밀린다) — 그래서 이 블록은 미디어쿼리 밖에 둔다. 실제 액션 패널(.chatgpt-drive-swipe-actions)의
   기본값은 display:none이고, 화면에 드러내는 규칙은 아래 <=900px 블록 "안에서만" 켠다 — M2에서
   겪은 함정(칩 스타일을 미디어쿼리 안에만 둬서 그 밖의 기본 규칙이 없어 1280px 데스크톱에
   스타일 없는 요소가 그대로 샌 결함)을 반복하지 않기 위해 기본값을 항상 명시적으로 밖에 둔다.
   1280px에서 렌더되는지 실측 결과는 작업 보고에 기록한다. */
body.chatgpt-reference-v1 .chatgpt-drive-swipe-row {
  position: relative;
  overflow: hidden;
}
body.chatgpt-reference-v1 .chatgpt-drive-swipe-row .chatgpt-drive-columns-row {
  /* 컴포지터 전용 속성(transform)만 애니메이션한다 — left/margin 금지. transform 값 자체는
     bindDriveRowSwipe가 인라인 스타일로 쓰고, 여기서는 그 값이 바뀔 때의 전환 채널만 연다. */
  transition: transform var(--wizon-motion-micro-duration, 150ms) var(--wizon-motion-effect-fast, ease);
  touch-action: pan-y; /* 세로 스크롤은 브라우저에 맡기고 가로만 JS가 가져간다(preventDefault) */
}
@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-row .chatgpt-drive-columns-row {
    transition: none;
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-swipe-actions {
  display: none;
}
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-actions {
    display: flex;
    position: absolute;
    inset: 0 0 0 auto;
    align-items: stretch;
    /* 닫혀 있을 때는 시각적으로도, 포커스/탭 순서에서도 존재하지 않는다 — visibility:hidden은
       display:none과 달리 레이아웃 폭 계산(actionWidth 측정)은 유지하면서 상호작용만 끈다. */
    visibility: hidden;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-row.is-drive-swipe-active .chatgpt-drive-swipe-actions {
    visibility: visible;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-delete-btn {
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ds-space-2);
    padding: 0 var(--ds-space-6);
    min-width: var(--ds-space-9);
    border: none;
    background: var(--ds-button-danger-bg);
    color: var(--ds-button-danger-fg);
    font-size: var(--ds-text-body-14);
    font-weight: 500;
    cursor: pointer;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-delete-btn:hover,
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-delete-btn:focus-visible {
    background: var(--ds-button-danger-bg-hover);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-swipe-delete-btn svg {
    width: 16px;
    height: 16px;
  }
}

/* R3a Finder-style inline folder creation (docs/product/215): the draft row (renderDriveDraftRow)
   reuses the SAME row/cell classes as a real row (select/name/size/modified/actions) so list and
   grid stay visually consistent — only the name cell differs (a live input instead of the
   open-folder button). The select/size/modified/actions cells render empty; the row itself is a
   <form> (data-drive-draft-form) so its geometry needs no override beyond the folder-ink icon
   color a real folder row already gets via the data-drive-folder-row-id selector above (the
   draft has no such attribute since it isn't a real row yet).
   R3b Finder-style inline rename reuses this SAME .chatgpt-drive-draft-input/-columns-subline
   pair verbatim (renderDriveRenameNameCell) so create and rename look identical — a folder being
   renamed IS a real row, so it already carries data-drive-folder-row-id and needs no icon-color
   override of its own. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-row--draft .chatgpt-drive-columns-icon {
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-draft-input {
  width: 100%;
  min-width: 0;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-body-14);
  padding: 4px 8px;
  outline: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-draft-input:focus-visible {
  border-color: var(--cg-focus-ring);
  box-shadow: 0 0 0 2px var(--cg-focus-ring);
}
body.chatgpt-reference-v1 .chatgpt-drive-draft-input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
/* Error subline reuses the SAME danger token every other drive error surface already uses
   (move dialog, delete confirm) — never a raw color. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-subline.is-error {
  color: var(--cg-danger-fg);
}

/* 20260724-drive-explorer-e2b: 행 "⋮" 트리거 — 컨텍스트 메뉴의 주경로(항상 보임, 터치/키보드
   접근 가능). border-radius는 토큰만 사용, 신규 :hover는 hover 가능 기기에서만. */
body.chatgpt-reference-v1 .chatgpt-drive-context-trigger {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-context-trigger:hover {
    background: var(--cg-hover-soft);
    color: var(--cg-text);
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-context-trigger:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-context-trigger[aria-expanded="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}
/* 20260729-touch-target-a2: ⋮ 트리거(32x32) 탭 타깃을 44px로 — 시각 크기는 그대로 두고 투명
   ::after로 히트영역만 6px/변 확장. 실측(390px, 3행 스택): 행 높이 62px, 트리거는 행 안에서
   top 14.49~bottom 46.49로 위아래 여백이 각각 14~15px — 6px 확장 후에도 다음 행 트리거까지
   ~18px 여유가 남아 겹치지 않는다. 가로도 트리거가 행 우측 끝(뷰포트 기준 -12px)에 있어 6px
   확장이 뷰포트를 벗어나지 않는다. 이 확장은 행 자체 탭(모바일 선택모드에서 행 전체가 선택
   토글, handlePortalRouteClick 상단부)과 아이콘 겹침이 생기지만 — ::after는 버튼의 생성 콘텐츠라
   클릭 시 event.target은 여전히 버튼 자신이고, 선택모드 핸들러는 event.target.closest(
   "[data-drive-context-menu-trigger]")로 이 버튼을 먼저 걸러 제외하므로(app.js) 동작은
   변하지 않는다 — 다만 트리거 주변 6px 띠에서는 "행 열기/선택" 대신 "메뉴 열기"가 되므로 의도된
   변화다(실브라우저로 행 탭이 여전히 항목을 여는지 확인 완료, 아래 보고 참고). */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-context-trigger {
    position: relative;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-context-trigger::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    min-width: 44px;
    min-height: 44px;
    transform: translate(-50%, -50%);
  }
}
/* R3b: the ⋮ trigger goes inert (native `disabled`) on the one row currently being renamed —
   same dimmed/not-allowed treatment .chatgpt-drive-draft-input:disabled already uses (토큰만,
   raw 리터럴 없음) so both "off while editing" cues read as one visual language. */
body.chatgpt-reference-v1 .chatgpt-drive-context-trigger:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* 컨텍스트 메뉴 — openUserMsgMenu의 스크림+플로팅 메뉴 구조를 재사용하되(같은 190/200
   z-index 계열, 다른 fixed 최상위 오버레이와 공유), 리프트할 요소가 없는 단순 메뉴이므로
   스크림은 어둡게 칠하지 않고 바깥 클릭만 잡는 투명 캐처로 둔다. 항목 마크업은
   .chatgpt-library-menu-item/.chatgpt-library-popover 그대로 재사용. 좌표는 JS
   (positionDriveContextMenu)가 뷰포트 안으로 clamp한다. */
.chatgpt-drive-context-scrim {
  position: fixed;
  inset: 0;
  z-index: 190;
  background: transparent;
}
body.chatgpt-reference-v1 .chatgpt-drive-context-menu {
  position: fixed;
  z-index: 200;
  box-sizing: border-box;
  inline-size: min(288px, calc(100vw - 16px));
  max-inline-size: calc(100vw - 16px);
  min-inline-size: min(calc(var(--wizon-ai-space-unit) * 50), calc(100vw - 16px));
  padding: var(--chatgpt-route-gap-2xs);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  box-shadow: var(--cg-shadow-float-lg);
  color: var(--cg-text);
}
/* R3c: separator above 삭제 — mirrors .recent-longpress-divider's own shape (non-interactive
   div, role="separator", a 1px --cg-menu-border line inset from the popover edge) rather than
   inventing a new visual language for "danger item below a line". */
body.chatgpt-reference-v1 .chatgpt-drive-context-menu-divider {
  height: 1px;
  margin: var(--chatgpt-route-gap-2xs) var(--chatgpt-route-gap-xs);
  background: var(--cg-menu-border);
}

/* drive-toolbar-unify: 행1 "새로 만들기 ▾" 팝오버 — 트리거(.chatgpt-route-primary)와 팝오버
   (.chatgpt-library-popover)/항목(.chatgpt-library-menu-item)을 라이브러리 새로 만들기 메뉴와
   100% 동일하게 재사용하므로 여기 신규 규칙은 없다(진짜 통일 — 룩얼라이크가 아니다). */

/* drive-toolbar-unify 행2(.chatgpt-drive-filter-row) — 뼈대는 .chatgpt-library-filter-row를
   그대로 재사용(flex space-between, 반응형 규칙 포함)한다. 여기서는 LEFT 슬롯 두 콘텐츠
   (컨텍스트 라벨/일괄 작업 바)가 그 슬롯에 맞물리도록 하는 배치만 추가 — 색/반경/그림자는
   전부 기존 --cg-* 와 --ds-* 토큰 재사용, raw 리터럴 없음(anti-drift 순증 0). */
body.chatgpt-reference-v1 .chatgpt-drive-filter-context {
  margin: 0;
  min-width: 0;
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  line-height: var(--chatgpt-route-control-height);
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 행2 트랙의 버튼 라벨은 절대 줄바꿈되지 않는다 — .chatgpt-route-action 베이스는 white-space를
   지정하지 않아(normal) 슬롯이 좁아지면 "다운로 드"/"새로고 침"처럼 라벨이 두 줄로 깨지고 행
   높이가 들쭉날쭉해진다(실렌더 계측으로 확인). 드라이브 행2 스코프로만 한정해 다른 라우트의
   .chatgpt-route-action 동작은 그대로 둔다. */
body.chatgpt-reference-v1 .chatgpt-drive-filter-row .chatgpt-route-action,
body.chatgpt-reference-v1 .chatgpt-drive-bulk-bar .chatgpt-route-action {
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-filter-trigger {
  position: relative;
}

/* 정렬 메뉴 — 방향 표시자만 신규(트리거/팝오버 자체는 .chatgpt-library-menu-anchor/-popover 재사용). */
body.chatgpt-reference-v1 .chatgpt-drive-sort-direction svg {
  width: 13px;
  height: 13px;
  transition: transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}
body.chatgpt-reference-v1 .chatgpt-drive-sort-direction.is-asc svg {
  transform: rotate(180deg);
}

/* 일괄 작업 바 — 선택 시에만 노출. 버튼은 기존 .chatgpt-route-action 그대로 재사용.
   drive-toolbar-unify: 이제 헤더 아래 독립 블록이 아니라 행2 LEFT 슬롯에 인라인으로 얹히므로
   margin-bottom은 더 이상 필요 없고(형제가 flex 갭으로 이미 분리) min-width:0으로 좁은 화면에서
   버튼 트랙이 슬롯 폭을 넘지 않게 한다. */
body.chatgpt-reference-v1 .chatgpt-drive-bulk-bar {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-sm);
  min-width: 0;
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-bulk-bar-count {
  font-weight: var(--wds-font-weight-medium);
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-bulk-bar-spacer {
  flex: 1 1 auto;
}

/* doc147 규칙4 — 컨텍스트/롱프레스 시트가 열려 있는 동안 문서 전체 선택 잠금(요소별
   user-select:none만으로는 이미 armed된 네이티브 선택을 못 막는다). M2의 선택모드 롱프레스도
   같은 클래스를 재사용한다(enterDriveMobileSelectMode/exitDriveMobileSelectMode) — 켜져 있는
   "시트"가 팝업 메뉴 대신 선택모드 세션 그 자체일 뿐, 손가락이 눌린 채로 480ms를 넘긴 시점에
   반응한다는 타이밍은 동일하다. */
body.drive-longpress-open,
body.drive-longpress-open * {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

/* 위 body 클래스는 480ms 타이머가 "발동한 뒤"에야 붙는다 — 손 누르고 있는 480ms 동안은 아직
   아무 잠금도 없다는 뜻. .recent-item(20260709-recent-longpress)이 이미 쓰는 좁은 상시 가드를
   그대로 옮겨 온다: 터치 기기에서 드라이브 행 자체는 항상 콜아웃/선택이 꺼져 있어, 타이머가
   돌아가는 동안에도(선택모드든 ⋮ 컨텍스트 메뉴든) iOS의 선택 핸들·돋보기 콜아웃이 뜨지 않는다.
   문서 전체가 아니라 행 하나로 좁힌 가드라 다른 곳(검색창 등)의 텍스트 선택은 그대로 된다. */
@media (hover: none) {
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
  }
}

@media (max-width: 900px) {
  /* 20260724-drive-shellfit: 모바일은 인스펙터도 데스크톱 전용 — state.drive.inspectorOpen이
     true여도(트리처럼) 항상 숨기고 브라우즈 목록만 전체폭 1컬럼으로. 오버플로는 목록 자체의
     overflow-x(위)가 흡수하므로 페이지 가로 스크롤은 생기지 않는다. */
  body.chatgpt-reference-v1 .chatgpt-drive-explorer {
    grid-template-columns: minmax(0, 1fr);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-inspector {
    display: none;
  }
}

/* 하단 경로 바(브레드크럼은 renderDriveBreadcrumb 그대로, 배치만 하단으로 이동). */
body.chatgpt-reference-v1 .chatgpt-drive-pathbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: var(--chatgpt-route-gap-xs);
  border-top: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-pathbar-label {
  flex: 0 0 auto;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
body.chatgpt-reference-v1 .chatgpt-drive-pathbar .chatgpt-drive-breadcrumb {
  margin-top: 0;
}

/* ============================================================================
   20260725-drive-mobile-shell (M1, docs handoff): mobile-only drive route shell.
   Desktop (901px+) is untouched by everything in this block — the base (non-media) rules only
   neutralize the EXTRA breadcrumb copy renderDrivePage now emits (display:contents dissolves the
   wrapper so it doesn't disturb `.chatgpt-route-page-inner`'s grid on desktop; see the same
   pattern already used for the library-scope-docked actions wrapper above), and every visible
   change lives inside `@media (max-width: 900px)`.
   ============================================================================ */
/* renderDrivePage wraps the breadcrumb + row-1 header together so mobile can pin both below the
   fixed topbar as one sticky unit — see the <=900px override below. `display: contents` makes the
   wrapper invisible to `.chatgpt-route-page-inner`'s grid on desktop, so `<header>` still lays out
   exactly as it did before (a direct grid item); the extra breadcrumb copy is simply hidden
   there — desktop keeps its one existing bottom breadcrumb (`.chatgpt-drive-pathbar` above),
   unchanged. */
body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead {
  display: contents;
}
body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead > .chatgpt-drive-breadcrumb {
  display: none;
}
/* 크기·수정일은 데스크톱에서 전용 컬럼(-cell--size / -cell--modified)이 담당하므로 이름 아래
   모바일 사본은 기본적으로 접혀 있다. 아래 <=900px 블록이 유일한 노출 지점이다 — 어느 폭에서든
   정확히 한쪽만 보인다. 이 규칙은 반드시 그 블록보다 '앞'에 있어야 한다(같은 특이도라 뒤에 두면
   미디어쿼리 안의 display:block을 소스 순서로 덮어버린다). */
body.chatgpt-reference-v1 .chatgpt-drive-columns-mobilemeta {
  display: none;
}

@media (max-width: 900px) {
  /* R4 고정 헤더: 경로(breadcrumb) + 검색바까지 상단 고정, 목록만 스크롤. `.chat-pane`가 실제
     스크롤 컨테이너(`.portal-route-open .chat-pane { overflow-y:auto }`, 위쪽 참고)이므로
     `position: sticky; top: 0` 은 고정 상단바 바로 아래에서 정확히 붙는다. 큰 타이틀(h1)은 이미
     시스템 규칙으로 숨겨져 있어 여기서 다시 숨기지 않는다. */
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead {
    display: flex;
    flex-direction: column;
    gap: var(--chatgpt-route-gap-xs);
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--cg-bg);
    padding-bottom: var(--chatgpt-route-gap-xs);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead > .chatgpt-drive-breadcrumb {
    display: flex;
  }
  /* 마지막 조각을 굵게 — 데스크톱 하단 경로 바의 기존 .is-current(500)는 그대로 두고, 이 모바일
     사본에만 적용(선택자가 .chatgpt-drive-mobile-stickyhead로 스코프돼 있어 데스크톱 무회귀). */
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead .chatgpt-drive-breadcrumb-item.is-current {
    font-weight: 700;
  }
  /* 상단에 고정 사본이 생겼으니 목록 맨 아래 원래 경로 바는 중복 — 모바일에서만 숨긴다. */
  body.chatgpt-reference-v1 .chatgpt-drive-pathbar {
    display: none;
  }

  /* 20260725-drive-mobile-topgap (M1 audit fix): 고정 헤더가 상단바 '바로 아래'에 붙어야
     목업 화면 1이 되는데, 실측 390px에서 경로 바가 166px에서 시작했다 — 상단바 아래로 112px가
     빈 채였다(844px 화면의 13%). 원인은 위 `20260724-drive-shellfit` 블록의
     `padding: var(--chatgpt-route-page-top) …`(=112px)가 모바일 전용 토큰
     `--chatgpt-route-page-mobile-top`(=16px)을 적용하는 <=900px 규칙보다 뒤에 와서 폭에
     상관없이 덮어버리는 것. 드라이브 라우트에만, <=900px에서만 되돌린다(큰 H1은 이미 숨겨져
     있어 이 여백이 받쳐줄 대상도 없다). 회귀 핀: DriveMobileTopGapTests. */
  html[data-portal-route="/drive"] #portalPage.chatgpt-route-page {
    padding-top: var(--chatgpt-route-page-mobile-top);
  }

  /* ── 20260725-drive-mobile-consolidation (M1 audit fix) ──────────────────────────────
     M1은 ⋯ 시트를 "새로 만들기/정렬/보기전환/새로고침의 모바일 통합"으로 추가했지만, 정작
     통합 대상인 데스크톱 툴바를 숨기지 않아 같은 액션이 두 곳에 남았다(승인 목업 화면 1에는
     이 컨트롤들이 없다). 실측 390px: 「새로 만들기」 필(131.6x39.8)이 고정 헤더 안에 박히고,
     그 아래 정렬+뷰토글(컬럼 포함)+새로고침 행이 38px를 더 먹어 목록 시작이 388px로 밀렸다.
     시트가 일부러 제외한 컬럼(Miller) 뷰도 이 툴바로는 그대로 열 수 있었다.
     회귀 핀: DriveMobileToolbarConsolidationTests. */
  body.chatgpt-reference-v1 .chatgpt-drive-page .chatgpt-route-page-actions [data-drive-new-trigger],
  body.chatgpt-reference-v1 .chatgpt-drive-page .chatgpt-library-view-controls {
    display: none;
  }

  /* 목록 헤더 행(선택 전체 + 이름/크기/수정일 정렬 헤더)도 모바일에는 없다 — 정렬은 시트가
     갖고, 선택 모드는 M2 범위다. 목업 화면 1·5 모두 헤더 없는 순수 행 목록이다. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-head {
    display: none;
  }

  /* M2: renderDriveBulkBar(행2 왼쪽 슬롯, 다운로드/삭제/선택 해제 필)는 M1 당시 모바일에서
     선택할 방법 자체가 없어(체크박스 숨김) driveSelectedCount() > 0이 될 수 없는 죽은 코드
     경로였다 — 그래서 이 행을 따로 숨길 필요가 없었다. M2가 롱프레스로 진짜 선택을 도입하면서
     이 조건이 처음으로 참이 될 수 있게 됐고, 그 순간 데스크톱용 이 필이 하단 플로팅 그룹칩과
     동시에 화면에 뜬다(같은 화면에 "선택 작업" UI가 두 벌 — 실측: 390px에서 "1개 선택됨" 필이
     고정 헤더 바로 아래에 뜨고, 그 아래 플로팅 칩까지 이중으로 보였다). 모바일의 유일한 선택
     작업 표면은 이제 아래 .chatgpt-drive-mobile-select-chips뿐이다. */
  body.chatgpt-reference-v1 .chatgpt-drive-bulk-bar {
    display: none;
  }

  /* ── 행을 화면 폭에 맞춘다 ────────────────────────────────────────────────────────────
     `.chatgpt-drive-columns-row`의 `min-width: 496px`(28+1fr+96+128+40 트랙) 때문에 390px
     화면에서 행이 496px로 넘쳐 `.chat-pane`이 가로 스크롤(scrollWidth 421 > clientWidth 390)
     되고, 행 ⋯가 화면 밖 오른쪽 110px에 놓여 elementFromPoint가 아무것도 잡지 못했다 —
     즉 목업이 요구하는 "행마다 ⋯"가 실제로는 누를 수 없었다. 모바일에서는 크기/수정일 컬럼과
     선택 셀을 접고 [이름][⋯] 2트랙으로 만든다. 접힌 두 값은 이름 아래
     `.chatgpt-drive-columns-mobilemeta`로 그대로 보인다(renderDriveColumnRow 참고).
     회귀 핀: DriveMobileRowFitsViewportTests. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
    grid-template-columns: minmax(0, 1fr) 40px;
    min-width: 0;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row .chatgpt-drive-columns-cell-select,
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row .chatgpt-drive-columns-cell--size,
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row .chatgpt-drive-columns-cell--modified {
    display: none;
  }
  /* 아이콘 칩 + 이름 셀은 남은 1fr을 전부 쓰고, 긴 이름은 말줄임으로 접힌다. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row .chatgpt-drive-columns-cell-name {
    min-width: 0;
  }
  /* 목업 화면 1의 행은 정확히 2줄이다. 파일 행에서는 유형 라벨까지 합친 이 한 줄이 원래
     subline을 '대체'한다 — 둘을 함께 보이면 이름/유형/크기·날짜 3줄이 되어 행 높이가 62->86px로
     불어난다(실측). 폴더 행에는 mobilemeta가 없으므로 subline("편집 가능")이 그대로 남는다. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-mobilemeta {
    display: block;
    color: var(--cg-muted);
    font-size: var(--ds-text-caption-12);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-columns-name-text:has(> .chatgpt-drive-columns-mobilemeta) > .chatgpt-drive-columns-subline {
    display: none;
  }

  /* M2 (모바일 선택모드): 길게 눌러 선택모드에 들어가면 위 [이름][⋮] 2트랙 위에 체크박스 트랙을
     다시 얹는다 — renderDriveColumnList가 붙이는 .chatgpt-drive-columns--select-mode 컨테이너
     한정이라, 평소(선택모드 아님)의 2트랙/숨김 체크박스 규칙은 그대로 살아있다(더 구체적인
     선택자라 순서와 무관하게 이 규칙이 이긴다). 체크박스 자체 크기·색은 기존
     .chatgpt-drive-select-checkbox를 그대로 쓴다 — 새 시각 언어를 만들지 않는다. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns--select-mode .chatgpt-drive-columns-row {
    grid-template-columns: 28px minmax(0, 1fr) 40px;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-columns--select-mode .chatgpt-drive-columns-cell-select {
    display: flex;
  }
  /* 위 desktop 전용 규칙 `@media (hover: hover) and (pointer: fine) { .chatgpt-drive-select-
     checkbox { opacity: 0 } }`은 미세 포인터 장치에서 체크박스를 평소엔 숨긴다 — 실기기라면
     터치는 hover:none이라 상관없지만, 데스크톱 창을 그냥 900px 이하로 좁히기만 한 채(터치
     에뮬레이션 없이) 확인하면 마우스/트랙패드는 여전히 pointer:fine이라 이 규칙이 그대로
     적용돼 선택 중이 아닌 행의 체크박스가 전부 투명해진다(실측: Electron 데스크톱 브라우저를
     375px로 리사이즈만 했을 때 unchecked 체크박스 opacity 0, rect 16x42 — DOM엔 있지만 안
     보임). 선택모드 자체가 "체크박스가 보여야 하는" 유일한 조건이므로, 포인터 종류와 무관하게
     여기서 명시적으로 1로 고정한다(선택자가 한 클래스 더 많아 hover 규칙보다 항상 이긴다). */
  body.chatgpt-reference-v1 .chatgpt-drive-columns--select-mode .chatgpt-drive-select-checkbox {
    opacity: 1;
  }
}

/* 20260725-drive-mobile-menu (M1): the fixed topbar's drive-only "..." trigger opens this as a
   bottom sheet. Reuses `.chatgpt-library-popover`'s card look (border/background/menu-item
   spacing) as-is — only POSITION is overridden below. Unlike the composer/library/etc popovers
   gated at max-width:520px (they still fall back to an anchored desktop dropdown above that),
   this trigger only ever exists <=900px (`.chatgpt-mobile-topbar` itself is display:none above
   that) and its popover renders inside the SCROLLING route body while its trigger lives in the
   separate FIXED topbar — the two are not DOM-adjacent, so the 520px list's anchored-dropdown
   fallback would float wrong if it ever applied here. One always-fixed rule across the full
   900px shelf avoids that instead of sharing the 520px-gated list.
   20260725-drive-sheet-desktop-guard (audit fix): "the trigger only exists <=900px" makes the
   sheet unreachable at desktop widths, but it does NOT make it un-RENDERED. Nothing closes
   state.drive.mobileMenuOpen on resize (handleViewportReflow does not, and renderDrivePage keeps
   emitting the markup), so widening the window with the sheet open left an orphan popover styled
   by `.chatgpt-library-popover`'s desktop base rules — measured at 1280px: position absolute,
   bottom -276px, width 200px, i.e. a stray 268px-tall dropdown hanging off the route page. The
   base `display: none` below is the same shape of safety net the tab bar uses, for the same
   reason. Regression pin: DriveMobileSheetDesktopGuardTests. */
body.chatgpt-reference-v1 .chatgpt-drive-mobile-menu,
body.chatgpt-reference-v1 .chatgpt-drive-mobile-submenu {
  display: none;
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-menu,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-submenu {
    display: grid;
    position: fixed;
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    width: 100%;
    max-width: none;
    height: auto;
    max-height: min(70vh, calc(var(--wizon-vvh, 100dvh) - 96px));
    align-content: start;
    overflow-y: auto;
    margin: 0;
    padding: 8px 8px calc(12px + var(--wizon-safe-bottom));
    border-radius: var(--wizon-ai-radius-sheet, 18px) var(--wizon-ai-radius-sheet, 18px) 0 0;
    box-shadow: var(--cg-shadow-float-lg);
    z-index: 200;
    animation: wizon-sheet-up var(--wds-spring-spatial-default-duration, 372ms) var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1)) backwards;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-menu::after,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-submenu::after {
    content: "";
    position: absolute;
    top: 8px;
    left: 50%;
    width: 36px;
    height: 4px;
    border-radius: var(--wizon-ai-radius-pill, 999px);
    background: var(--wizon-ai-text-muted-2);
    opacity: 0.5;
    transform: translateX(-50%);
  }
}

/* 20260725-drive-mobile-tabbar (M1): drive-route-only bottom tab bar (프로젝트/드라이브/산출물/
   일정 — index.html의 기존 목적지 재사용, 사이드바는 건드리지 않음). position:fixed라 DOM
   위치와 무관하게 뷰포트 바닥에 붙는다(바텀시트와 동일 기법). `.chat-pane`에 같은 높이만큼
   하단 패딩을 더해, 스크롤되는 목록 마지막 행이 탭바 밑에 가려지지 않게 한다.
   Unlike the topbar's drive-only trigger (safely nested inside `.chatgpt-mobile-topbar`, which is
   itself `display: none` on desktop — an ancestor's display:none hides descendants regardless of
   their own JS `hidden` state), this tab bar is a standalone <nav> with no such ancestor. Its
   visibility is JS-driven (`hidden` attribute, see syncPortalRouteSurfaceVisibility) but resizing
   across the 900px breakpoint does NOT re-run that sync — so a bare `<nav>` UA default of
   `display: block` would show it, unstyled, at desktop widths if `hidden` was ever cleared while
   narrow. This explicit `display: none` base rule is the safety net (mirrors
   `.chatgpt-mobile-topbar`'s own base rule for the identical reason) — the <=900px block below is
   the only place it becomes visible, independent of the `hidden` attribute's timing.
   20260725-drive-tabbar-hidden-gate (audit fix): the <=900px rule below MUST carry
   `:not([hidden])`. An author-sheet `display: grid` outranks the UA sheet's `[hidden] {
   display: none }`, so without the guard the `hidden` attribute syncPortalRouteSurfaceVisibility
   sets is silently defeated and this drive-only bar renders on EVERY mobile route (library /
   projects / scheduled) and over the chat home's composer. Measured before the fix at 390px:
   `hidden === true` yet `getComputedStyle().display === "grid"`, height 67.4px, on all four
   surfaces. Regression pin: DriveTabbarHiddenAttributeGateTests. */
body.chatgpt-reference-v1 .chatgpt-mobile-drive-tabbar {
  display: none;
}

/* 20260728-select-chips-desktop-leak (audit fix): 칩 행도 탭바와 똑같이 기본값을 숨김으로 둔다.
   M2의 나머지 칩 스타일은 전부 아래 <=900px 블록 안에 있었지만 이 기본 규칙이 없어서, 데스크톱에서
   선택모드 상태가 되면 스타일 없는 칩 행이 그대로 렌더됐다 — 1280px 실측: `display: block`,
   너비 968px, 높이 32px로 보이고 데스크톱 자체 벌크바와 겹쳤다.

   진입 자체는 isMobileSheetViewport()(max-width: 900px)로 막혀 있으므로 데스크톱에서 새로
   선택모드에 들어갈 수는 없다. 문제는 그 다음이다: 폭 검사는 롱프레스 '시점'에 한 번만 하고
   state.drive.mobileSelectMode는 그 뒤 창 크기와 무관하게 남는다. 그래서 모바일 폭에서
   선택모드에 들어간 뒤 창을 넓히거나 기기를 가로로 돌리면 이 상태가 그대로 데스크톱 레이아웃에
   들어온다. 회귀 핀: DesktopDoesNotShowTheMobileSelectChipsTests. */
body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chips {
  display: none;
}

@media (max-width: 900px) {
  /* One authoritative height for the bar, consumed BOTH by the bar itself and by the scroll
     reserve below, so the two can never drift apart. */
  body.chatgpt-reference-v1 .chatgpt-mobile-drive-tabbar:not([hidden]) {
    --wizon-drive-tabbar-block: 68px;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    min-height: var(--wizon-drive-tabbar-block);
    background: var(--cg-bg);
    border-top: 1px solid var(--cg-menu-border);
    padding: 6px calc(var(--wizon-safe-right, 0px)) calc(6px + var(--wizon-safe-bottom)) calc(var(--wizon-safe-left, 0px));
  }
  body.chatgpt-reference-v1 .chatgpt-mobile-drive-tab {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    border: 0;
    background: transparent;
    color: var(--cg-muted);
    font-size: var(--wds-font-size-caption);
    text-decoration: none;
    cursor: pointer;
    position: relative;
  }
  body.chatgpt-reference-v1 .chatgpt-mobile-drive-tab svg {
    width: 22px;
    height: 22px;
  }
  body.chatgpt-reference-v1 .chatgpt-mobile-drive-tab.is-active {
    color: var(--cg-text);
  }
  /* 승인 목업 화면 1·6의 `.tab.on::before` — 활성 탭 상단 2px 인디케이터(24px 너비). 색만
     바꾸면 활성 탭이 "조금 진한 회색"으로만 읽혀 목업의 신호 강도에 못 미친다. */
  body.chatgpt-reference-v1 .chatgpt-mobile-drive-tab.is-active::before {
    content: "";
    position: absolute;
    top: -6px;
    width: 24px;
    height: 2px;
    border-radius: var(--wizon-ai-radius-pill, 999px);
    background: var(--cg-text);
  }
  /* 키보드가 올라오면 하단 네비게이션은 숨긴다(iOS·Android 공통 관행). position:fixed bottom:0은
     Android처럼 레이아웃 뷰포트가 줄어드는 환경에서 키보드 위에 떠 검색 입력과 목록을 동시에
     좁히고, iOS에서는 키보드 아래에 깔려 아무 값도 못 낸다. 함께 스크롤 예약도 회수한다. */
  html.is-keyboard-open body.chatgpt-reference-v1 .chatgpt-mobile-drive-tabbar {
    display: none;
  }
  /* 스크롤 예약은 `.chat-pane`이 아니라 드라이브 라우트 페이지에 얹는다. `.chat-pane`에는
     `@media (max-width: 520px)`의 `html[data-chat-state="empty"] … { padding-bottom: 10px
     !important }`(위쪽 참고)가 있어, 대화가 없는 상태(로그인 직후 드라이브로 바로 들어오는
     기본 경로)에서는 예약이 조용히 무효화된다 — 실측 결과 390px/empty에서 예약이 10px로
     덮여 홈 인디케이터가 있는 실기기에서는 마지막 행이 탭바에 가려진다. 라우트 페이지에는
     경쟁하는 !important가 없다. 회귀 핀: DriveTabbarScrollReserveTests. */
  html[data-portal-route="/drive"] body.chatgpt-reference-v1.portal-route-open .chatgpt-drive-page {
    /* 68px tab bar + 56px FAB + 20px air + safe area. This keeps the final
       Finder row fully visible instead of letting the fixed FAB cover it. */
    padding-bottom: calc(68px + 76px + var(--wizon-safe-bottom) + 8px);
  }
  /* 키보드가 올라오면 탭바를 숨기므로 예약도 회수한다. 선택자는 위 예약 규칙보다 반드시 더
     구체적이어야 한다 — `html.is-keyboard-open body… .chatgpt-drive-page`(클래스 3)로는 예약
     규칙(속성 1 + 클래스 3)에 밀려 조용히 무시된다(실측: 76px 그대로 유지). */
  html.is-keyboard-open[data-portal-route="/drive"] body.chatgpt-reference-v1.portal-route-open .chatgpt-drive-page {
    padding-bottom: 0;
  }

  /* M2: 선택모드 그룹칩이 탭바 위에 position:fixed로 떠 있는 동안에는 목록 마지막 행이 그
     칩에 가려질 수 있다 — 위 탭바 전용 예약(68px)과 같은 계열로, 칩 높이(44px 버튼 + 위아래
     여백)만큼 더 얹는다. `:has()`로 렌더된 칩 유무를 직접 읽으므로 selectMode용 body 클래스를
     따로 만들 필요가 없다(선택자 자체가 이미 .chatgpt-drive-page보다 더 구체적이라 순서 무관하게
     이 규칙이 이긴다). 키보드가 뜨면 위 리셋 규칙(html.is-keyboard-open… 접두사가 하나 더 붙어
     더 구체적이다)이 그대로 이겨 0으로 되돌아간다 — 칩은 선택모드 중 검색창을 누르는 극히 드문
     경우를 빼면 키보드와 동시에 뜨지 않는다. */
  html[data-portal-route="/drive"] body.chatgpt-reference-v1.portal-route-open .chatgpt-drive-page:has(.chatgpt-drive-mobile-select-chips) {
    padding-bottom: calc(68px + 76px + 56px + var(--wizon-safe-bottom) + 8px);
  }
}

/* M2 (모바일 선택모드) 그룹칩 — 탭바 바로 위에 뜨는 4개의 독립된 floating 버튼. 제품 결정:
   컨테이너 자체는 경계선/막대/배경을 두지 않는다("리스트 상위 레이어" 개념 — 나중에 리스트
   위에 버튼만 떠 있어야 한다) — 그래서 아래 .chatgpt-drive-mobile-select-chips 규칙은 순수하게
   레이아웃(위치·간격·가로 스크롤)만 맡고 background/border/box-shadow가 전혀 없다. 개별 버튼
   (.chatgpt-drive-mobile-select-chip)만 자기 몫의 표면(배경+그림자)을 갖는다 — 안 그러면 목록
   위에 텍스트만 둥둥 떠 가독성이 없다. .chatgpt-drive-view-toggle-btn.is-active가 이미 쓰는
   "border:0 + background:var(--cg-surface) + box-shadow:var(--cg-shadow-float-xs)" 조합과 같은
   무경계 표면 패턴을 재사용한다(새 시각 언어 아님). */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chips {
    position: fixed;
    left: 0;
    right: 0;
    /* 68px = 탭바 자체 높이(--wizon-drive-tabbar-block과 같은 값 — 커스텀 프로퍼티는 형제
       요소로 상속되지 않아 여기서 재선언할 수 없으므로, 탭바 쪽 값이 바뀌면 이 숫자도 같이
       바꿔야 한다. 탭바의 스크롤 예약(위 DriveTabbarScrollReserveTests 규칙)도 같은 이유로
       이미 68을 하드코딩하고 있다). */
    bottom: calc(68px + var(--wizon-safe-bottom) + 10px);
    z-index: 21;
    display: flex;
    gap: 8px;
    padding: 0 calc(12px + var(--wizon-safe-right)) 0 calc(12px + var(--wizon-safe-left));
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chips::-webkit-scrollbar {
    display: none;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chip {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 44px;
    padding: 0 16px;
    border: 0;
    border-radius: var(--wizon-ai-radius-pill, 999px);
    background: var(--cg-surface);
    color: var(--cg-text);
    font: inherit;
    font-size: var(--ds-text-caption-13);
    font-weight: var(--wds-font-weight-medium);
    box-shadow: var(--cg-shadow-float-lg);
    cursor: pointer;
    white-space: nowrap;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chip svg {
    width: 16px;
    height: 16px;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chip.is-danger {
    color: var(--cg-danger-fg);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chip:disabled {
    opacity: 0.4;
    cursor: default;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-select-chip:active {
    background: var(--cg-hover-soft);
  }
}

/* ============================================================================
   20260724-drive-shellfit: 우측 인스펙터 패널(docs/product/215, 셸 정합 재구성). 선택 없음
   (현재 폴더 요약)/단일 선택(세부 정보+작업 버튼)/다중 선택(합계+일괄 작업) 3가지 콘텐츠를
   전부 같은 레이아웃 클래스로 담는다 — 콘텐츠는 renderDriveInspectorPane이 고르고, 여기서는
   배치만. 버튼은 새 클래스가 아니라 기존 .chatgpt-route-action을 재사용(패널 폭에 맞춰 전체
   너비로만 재배치). 전부 기존 --cg-*·--chatgpt-route-*·--ds-*·--wizon-ai-* 토큰, raw 색상·
   반경/!important 신규 없음(anti-drift 순증 0).
   ============================================================================ */
/* 20260725-drive-redesign R1: 인스펙터 = 아티팩트 패널(#artifactPanel)과 동일한 데스크톱
   오버레이 문법 그대로 — position:fixed · inset 12 · radius popover(16) · 보더 + 그림자 ·
   z-index 200 계열. 목록을 밀지 않고 우측에 카드로 도킹되어 열릴 때 슬라이드 인 한다
   (driveInspectorIn, --entering 모디파이어가 붙은 렌더에서만 재생 → 매 재렌더 재애니 방지).
   모바일(<=900px)은 위 셸핏 블록에서 이미 display:none 이라 이 데스크톱 규칙과 상호배타. */
@media (min-width: 901px) {
  body.chatgpt-reference-v1 .chatgpt-drive-inspector {
    position: fixed;
    inset: 12px 12px 12px auto;
    width: clamp(320px, 32%, 400px);
    margin: 0;
    padding: var(--chatgpt-route-gap-md);
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    border: 1px solid var(--cg-menu-border, var(--line));
    border-radius: var(--wizon-ai-radius-popover, 16px);
    background: var(--cg-menu-bg, var(--bg));
    box-shadow: var(--wizon-ai-overlay-panel-shadow);
    z-index: 200;
  }
  body.chatgpt-reference-v1 .chatgpt-drive-inspector.chatgpt-drive-inspector--entering {
    animation: driveInspectorIn 0.26s cubic-bezier(0.16, 1, 0.3, 1);
  }
}
@keyframes driveInspectorIn {
  from { transform: translateX(calc(100% + 24px)); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .chatgpt-drive-inspector.chatgpt-drive-inspector--entering {
    animation: none;
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 auto;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-sm) var(--chatgpt-route-gap-md);
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-head h2 {
  margin: 0;
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--wds-font-weight-medium);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-toggle {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-toggle svg {
  width: 16px;
  height: 16px;
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-inspector-toggle:hover {
    background: var(--cg-hover-soft);
    color: var(--cg-text);
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-toggle:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-inspector-toggle[aria-pressed="true"] {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--chatgpt-route-gap-md);
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-list {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-item {
  display: grid;
  grid-template-columns: var(--wizon-ai-action-target-sm) minmax(0, 1fr);
  align-items: start;
  gap: var(--chatgpt-route-gap-xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-marker {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-marker svg {
  width: 16px;
  height: 16px;
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-copy {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-copy strong {
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--wds-font-weight-medium);
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-copy span,
body.chatgpt-reference-v1 .chatgpt-drive-activity-copy small {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-activity-more {
  width: 100%;
  margin-top: var(--chatgpt-route-gap-md);
  justify-content: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding-bottom: var(--chatgpt-route-gap-md);
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  text-align: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-icon {
  display: inline-grid;
  place-items: center;
  width: calc(var(--wizon-ai-space-unit) * 18);
  height: calc(var(--wizon-ai-space-unit) * 18);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-lg);
  background: var(--cg-hover-soft);
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-icon:has(> .wizon-file-type-icon) {
  border: 0;
  border-radius: 0;
  background: transparent;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-icon.chatgpt-drive-inspector-hero-icon--multi {
  border-style: dashed;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-icon svg {
  width: calc(var(--wizon-ai-space-unit) * 9);
  height: calc(var(--wizon-ai-space-unit) * 9);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-name {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
  font-weight: var(--wds-font-weight-medium);
  word-break: break-all;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-hero-sub {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

/* R3d-1 (docs/product/215 승인 목업, 2026-07-25): 단일 선택 전용 미리보기 카드 + 제목/부제.
   폴더 요약·다중 선택은 위 .chatgpt-drive-inspector-hero를 그대로 쓰고(콘텐츠 불변), 여기 제목
   (--title)·부제(--subtitle)는 hero-name와 hero-sub가 쓰는 것과 같은 --ds-text-body-15 그리고
   --ds-text-caption-12 토큰을 그대로 재사용해 세 상태의 타이포 리듬이 갈라지지 않게 맞춘다.
   미리보기 자체는 실제 썸네일 백엔드가 없어 확장자로 고른 순수 CSS 자리표시자 — 신규 raw 색상
   없음, 전부 기존 --cg-*, --wizon-ai-*, --chatgpt-route-* 토큰.
   AI "이 파일에 대해 질문하기" 슬롯은 드라이브→문서 브리지가 없어 이 자리에 넣지 않는다
   (app.js의 renderDriveInspectorPreview 위 주석 참고). */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-md);
  margin-bottom: var(--chatgpt-route-gap-md);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-lg);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: calc(var(--wizon-ai-space-unit) * 22);
  overflow: hidden;
}
/* File-type SVGs are portrait-shaped source art. Give the inspector a bounded
   portrait owner instead of stretching the asset to the full preview stage. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-stage .wizon-file-type-icon--preview {
  width: min(68px, 100%);
  height: min(82px, 100%);
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-type {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* document — 문서, PDF, 프레젠테이션: 폭이 들쭉날쭉한 텍스트 줄 4개. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-lines {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7px;
  width: 76%;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-line {
  height: 7px;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-hover);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-line:nth-child(1) { width: 92%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-line:nth-child(2) { width: 100%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-line:nth-child(3) { width: 70%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-line:nth-child(4) { width: 55%; }
/* spreadsheet — 스프레드시트: 3x3 셀 그리드. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  width: 62%;
  aspect-ratio: 1 / 1;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-cell {
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-micro);
  background: var(--cg-hover);
}
/* image — 이미지: 톤온톤 그라디언트 타일 위에 옅은 워터마크 아이콘(실제 사진 아님). */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-tone {
  display: inline-grid;
  place-items: center;
  width: 78%;
  aspect-ratio: 4 / 3;
  border-radius: var(--chatgpt-route-radius-control);
  background: linear-gradient(135deg, var(--cg-hover-soft), var(--cg-hover));
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-tone svg {
  width: calc(var(--wizon-ai-space-unit) * 7);
  height: calc(var(--wizon-ai-space-unit) * 7);
  opacity: 0.55;
}
/* audio/video — 오디오, 동영상: 막대 파형 모티프. 동영상만 재생 배지를 덧얹어 구분한다. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview--video .chatgpt-drive-inspector-preview-stage {
  position: relative;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bars {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: calc(var(--wizon-ai-space-unit) * 10);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar {
  width: 5px;
  height: 30%;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(1) { height: 42%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(2) { height: 70%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(3) { height: 100%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(4) { height: 58%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(5) { height: 85%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(6) { height: 46%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-bar:nth-child(7) { height: 66%; }
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-play {
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(var(--wizon-ai-space-unit) * 7);
  height: calc(var(--wizon-ai-space-unit) * 7);
  /* 정사각이므로 pill 토큰이 50%와 동일한 원을 만든다 — raw 리터럴 대신 토큰 사용. */
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-send-bg);
  opacity: 0.85;
  transform: translate(-50%, -50%);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 55%;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 6px 0 6px 9px;
  border-color: transparent transparent transparent var(--cg-send-fg);
  transform: translate(-50%, -50%);
}
/* folder/unknown — 큰 유형 글리프. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-glyph {
  display: inline-grid;
  place-items: center;
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview-glyph svg {
  width: calc(var(--wizon-ai-space-unit) * 11);
  height: calc(var(--wizon-ai-space-unit) * 11);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-heading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding-bottom: var(--chatgpt-route-gap-md);
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  text-align: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-title {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
  font-weight: var(--wds-font-weight-medium);
  word-break: break-all;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-subtitle {
  overflow: hidden;
  max-width: 100%;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-inspector-section {
  padding: var(--chatgpt-route-gap-md) 0;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-section:last-child {
  border-bottom: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-section h3 {
  margin: 0 0 var(--chatgpt-route-gap-xs);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-meta-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-xs);
  padding: 4px 0;
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-meta-k {
  flex: 0 0 auto;
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-meta-v {
  overflow: hidden;
  min-width: 0;
  color: var(--cg-text);
  font-variant-numeric: tabular-nums;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-actions {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-2xs);
  padding-top: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-actions .chatgpt-route-action {
  width: 100%;
  justify-content: flex-start;
}
/* R3d-1: 순서상 첫 작업(폴더=열기, 파일=미리보기)만 잉크 필 1차 버튼 — 나머지는 기존 2차
   스타일 그대로. .chatgpt-route-action의 border/background를 --cg-send-bg·--cg-send-fg로
   덮어써 컴포저 전송 버튼과 같은 잉크 필 토큰을 재사용한다(신규 색상 없음). */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-actions .chatgpt-route-action.is-primary {
  justify-content: center;
  border-color: var(--cg-send-bg);
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-inspector-actions .chatgpt-route-action.is-primary:hover {
    background: var(--cg-send-bg);
    opacity: 0.92;
  }
}

/* R3d-2a: 파일 전용 "이 파일을 AI가 참고하도록 허용" 토글 행 — 매니저 이상만 렌더된다(app.js
   driveRoleAtLeast 게이트, 서버가 authoritative). 새 색상을 만들지 않는다: on 상태는 위
   1차 버튼과 같은 잉크 필 토큰(--cg-send-bg 와 --cg-send-fg)을, off 상태는 --cg-hover를
   재사용한다. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--chatgpt-route-gap-xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-state {
  display: flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-xs);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
  color: var(--cg-text);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-state > span:last-child {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-state small {
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-dot {
  flex: 0 0 auto;
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-dot.is-loading {
  animation: cgPulse 1s ease-in-out infinite;
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-summary {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--chatgpt-route-gap-2xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-summary > span {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  padding: var(--chatgpt-route-gap-xs);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-summary strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-summary small {
  color: var(--cg-muted);
  font-size: var(--ds-text-micro-11);
}
body.chatgpt-reference-v1 .chatgpt-drive-ai-index-summary .has-failure strong {
  color: var(--cg-danger-fg);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-label {
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-toggle {
  position: relative;
  flex: 0 0 auto;
  width: 32px;
  height: 20px;
  padding: 2px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-hover);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-toggle[aria-checked="true"] {
  border-color: var(--cg-send-bg);
  background: var(--cg-send-bg);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-toggle::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-surface);
  transition: transform 0.12s ease;
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-toggle[aria-checked="true"]::after {
  transform: translateX(12px);
}
body.chatgpt-reference-v1 .chatgpt-drive-inspector-ai-toggle.is-pending {
  cursor: default;
  opacity: 0.6;
}

/* 20260724-drive-shellfit: 트리 레일 제거로 브라우즈 목록이 전체폭을 쓰게 되어, 진짜 빈 폴더
   (권한 0인 계정에서 자주 보임)가 더는 좁은 박스로 보이지 않는다 — 폭을 한 번 더 제한해
   중앙에 정돈하고 아이콘 칩을 키운다. 다른 라우트가 쓰는 공유 .chatgpt-lifecycle-empty
   자체는 건드리지 않는다(두 클래스 조합 선택자라 특이도가 자연히 더 높다, !important 없음). */
body.chatgpt-reference-v1 .chatgpt-drive-empty {
  max-width: 420px;
  margin: 0 auto;
  padding: 96px 20px;
}
body.chatgpt-reference-v1 .chatgpt-drive-empty .chatgpt-route-empty-icon {
  width: calc(var(--wizon-ai-space-unit) * 16);
  height: calc(var(--wizon-ai-space-unit) * 16);
}
body.chatgpt-reference-v1 .chatgpt-drive-empty .chatgpt-route-empty-icon svg {
  width: calc(var(--wizon-ai-space-unit) * 8);
  height: calc(var(--wizon-ai-space-unit) * 8);
}

/* ============================================================================
   20260724-drive-explorer-e2b: 뷰 토글(목록/아이콘/컬럼/갤러리) + 컬럼(Miller)/갤러리 뷰 +
   드래그로 이동. 정렬·다중선택·컨텍스트 메뉴·행 마크업(renderDriveColumnRow)은 4뷰가 전부
   그대로 재사용하므로 여기서는 렌더러별 배치만 다르다. 전부 기존 --cg-*·--chatgpt-route-*·
   --ds-*·--wizon-ai-* 토큰 재사용, raw 색상·반경·!important 신규 없음(anti-drift 순증 0).
   ============================================================================ */

/* 뷰 토글 — .chatgpt-route-action과 같은 툴바 트랙에 얹는 세그먼트 컨트롤. */
body.chatgpt-reference-v1 .chatgpt-drive-view-toggle {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-view-toggle-btn {
  display: inline-grid;
  place-items: center;
  width: var(--wizon-ai-action-target-sm);
  height: var(--wizon-ai-action-target-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-view-toggle-btn svg {
  width: 15px;
  height: 15px;
}
body.chatgpt-reference-v1 .chatgpt-drive-view-toggle-btn.is-active {
  background: var(--cg-surface);
  color: var(--cg-text);
  box-shadow: var(--cg-shadow-float-xs);
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-view-toggle-btn:hover {
    color: var(--cg-text);
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-view-toggle-btn:focus-visible {
  color: var(--cg-text);
  outline: none;
}

/* 아이콘 뷰는 Finder처럼 고정 리듬의 타일을 왼쪽부터 채운다. 목록의 5개 셀을 단순히
   늘려 카드로 보이게 하지 않고, body가 타일 그리드를 소유하며 각 행은 아이콘과 이름을
   중심으로 다시 배치한다. 남는 폭으로 타일을 억지로 늘리지 않는 것이 핵심이다. */
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view {
  display: block;
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-head {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(calc(var(--wizon-ai-space-unit) * 34), calc(var(--wizon-ai-space-unit) * 38)));
  grid-auto-rows: calc(var(--wizon-ai-space-unit) * 36);
  align-content: start;
  justify-content: start;
  gap: var(--chatgpt-route-gap-xs);
  min-width: 0;
  padding: var(--chatgpt-route-gap-sm);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  align-items: stretch;
  align-content: stretch;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  padding: 10px 8px;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell-select {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row > .chatgpt-drive-columns-actions {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 2;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell-name {
  grid-column: 1;
  grid-row: 1;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 8px;
  min-width: 0;
  padding: 2px 0 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-cell-name .chatgpt-drive-columns-icon {
  width: calc(var(--wizon-ai-space-unit) * 11);
  height: calc(var(--wizon-ai-space-unit) * 11);
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-cell-name .chatgpt-drive-columns-icon svg {
  width: 24px;
  height: 24px;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-row-open,
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-name-text {
  width: 100%;
  align-items: center;
  text-align: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-cell-name strong {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  max-width: 100%;
  line-height: 1.3;
  white-space: normal;
  overflow-wrap: anywhere;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-subline {
  max-width: 100%;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell--size {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell--modified {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row.is-selected {
  background: color-mix(in srgb, var(--cg-focus-ring) 12%, var(--cg-surface));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cg-focus-ring) 40%, var(--cg-menu-border));
}
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row--draft .chatgpt-drive-draft-input {
  width: 100%;
  text-align: center;
}
@media (hover: hover) and (pointer: fine) {
  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-actions {
    opacity: 0;
    transition: opacity var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row:hover .chatgpt-drive-columns-actions,
  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-row:focus-within .chatgpt-drive-columns-actions {
    opacity: 1;
  }
}

/* 컬럼(Miller) 뷰 — 좌→우 컬럼 체인. 마지막 컬럼(--current)만 renderDriveColumnRow 그대로라
   격자(6트랙)를 유지하고, 그 앞의 탐색 전용 컬럼들은 단순 버튼 목록이다. */
body.chatgpt-reference-v1 .chatgpt-drive-miller {
  display: flex;
  align-items: stretch;
  gap: 0;
  min-width: 0;
  height: 100%;
  overflow-x: auto;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-control);
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-column {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  width: calc(var(--wizon-ai-space-unit) * 56);
  min-width: calc(var(--wizon-ai-space-unit) * 56);
  padding: 4px;
  overflow-y: auto;
  border-right: 1px solid var(--cg-menu-border, var(--line));
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-column:last-child {
  border-right: 0;
}
/* 마지막 컬럼의 각 행(.chatgpt-drive-columns-row)은 이미 자기 자신의 6트랙 grid-template을
   기본 규칙에서 가져오므로(위 "우측 컬럼 목록" 블록), 여기서는 그 폭(min-width:600px)을 담을
   수 있도록 컬럼 컨테이너 자체 폭만 넉넉히 넓힌다 — 행 내부 레이아웃을 다시 정의하지 않는다. */
body.chatgpt-reference-v1 .chatgpt-drive-miller-column--current {
  width: auto;
  min-width: max(600px, calc(var(--wizon-ai-space-unit) * 90));
  gap: 1px;
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 5px 6px;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-row.is-active {
  background: var(--cg-hover-soft);
}
@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-miller-row:hover {
    background: var(--cg-hover-soft);
  }
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-row-label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  font-size: var(--ds-text-caption-13);
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-row-chevron {
  flex: 0 0 auto;
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-row-chevron svg {
  width: 13px;
  height: 13px;
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  padding: var(--chatgpt-route-gap-md);
  text-align: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-miller-preview-meta {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

/* 갤러리 뷰 — 큰 미리보기(스테이지) + 하단 필름스트립. 백엔드 썸네일이 없으므로 실제 이미지가
   아니라 유형 아이콘을 "미리보기"로 쓴다(정직성 — 날조된 사진 미리보기 없음). */
body.chatgpt-reference-v1 .chatgpt-drive-gallery {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-md);
  min-width: 0;
  min-height: 0;
  height: 100%;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--chatgpt-route-gap-xs);
  flex: 1 1 auto;
  min-height: calc(var(--wizon-ai-space-unit) * 70);
  padding: var(--chatgpt-route-gap-lg);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-lg);
  background: var(--cg-surface);
  text-align: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage.is-empty {
  color: var(--cg-muted);
  justify-content: center;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage-icon {
  display: inline-grid;
  place-items: center;
  color: var(--cg-muted);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage-icon svg {
  width: calc(var(--wizon-ai-space-unit) * 14);
  height: calc(var(--wizon-ai-space-unit) * 14);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage-name {
  color: var(--cg-text);
  font-size: var(--ds-text-body-16);
  font-weight: var(--wds-font-weight-medium);
  word-break: break-word;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage-meta {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage-actions {
  display: flex;
  gap: var(--chatgpt-route-gap-xs);
  margin-top: var(--chatgpt-route-gap-xs);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip.chatgpt-drive-columns.is-gallery-view {
  flex: 0 0 auto;
  display: block;
  overflow-x: auto;
  overflow-y: hidden;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-body {
  display: flex;
  gap: var(--chatgpt-route-gap-xs);
  min-width: 0;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-content: start;
  gap: 4px;
  flex: 0 0 auto;
  width: calc(var(--wizon-ai-space-unit) * 30);
  min-height: calc(var(--wizon-ai-space-unit) * 26);
  padding: var(--chatgpt-route-gap-xs);
  border: 1px solid var(--cg-menu-border);
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row.is-gallery-active {
  border-color: var(--cg-text);
  background: var(--cg-hover-soft);
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell-select {
  grid-column: 1;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row > .chatgpt-drive-columns-actions {
  grid-column: 3;
  justify-self: end;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell-name {
  grid-column: 1 / -1;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
/* 20260725-drive-row-r2b: 필름스트립은 30 space-unit(~240px) 폭이라 subline까지 넣으면
   빽빽해진다 — 예전에도 이 자리(수정일+유형 칸)를 통째로 숨겼으니(구 nth-child(4),(5)
   display:none) subline도 같은 이유로 계속 숨긴다. 필름스트립은 "지금 보는 파일 고르기"
   용도라 이름만으로 충분하다. */
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-cell-name .chatgpt-drive-columns-subline {
  display: none;
}
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell--size,
body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row > .chatgpt-drive-columns-cell--modified {
  display: none;
}

/* 드래그로 이동 — 데스크톱 전용(driveDragEnabled). 소스/드롭 타깃 시각 효과는 renderPortalPage를
   거치지 않고 classList로 직접 토글되므로(handleDriveRowDragStart/Over/Leave/End 자체 주석 참고)
   여기 선택자들은 애니메이션 없이 즉시 상태만 반영한다. */
body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-drive-dragging,
body.chatgpt-reference-v1 .chatgpt-drive-miller-row.is-drive-dragging {
  opacity: 0.5;
}
body.chatgpt-reference-v1 .is-drive-drop-target,
body.chatgpt-reference-v1 .is-drive-file-drop-target {
  outline: 2px solid var(--cg-text);
  outline-offset: -2px;
  background: var(--cg-hover-soft);
}

/* 바깥에서 파일을 끌고 들어오면 목록 전체가 목적지임을 보인다 — 폴더 행이 아니라 빈 곳에
   떨궈도 지금 보고 있는 폴더로 들어가기 때문에, 강조가 행에만 붙으면 「여기 놔도 되나」를
   알 수 없다. */
body.chatgpt-reference-v1.is-drive-file-dragging .chatgpt-drive-page {
  outline: 2px dashed var(--cg-text);
  outline-offset: -6px;
  border-radius: var(--wizon-ai-radius-lg, 12px);
}

@media (max-width: 900px) {
  /* 컬럼/갤러리도 900px 이하에서는 오버플로 없이 세로로 눌러 담는다(가로 스크롤은 각 트랙
     자체의 overflow-x가 흡수). */
  body.chatgpt-reference-v1 .chatgpt-drive-miller-column {
    width: calc(var(--wizon-ai-space-unit) * 44);
    min-width: calc(var(--wizon-ai-space-unit) * 44);
  }
  /* --current는 위 기본 규칙의 min-width: max(600px, ...)를 그대로 유지한다 — 마지막 컬럼의
     행(.chatgpt-drive-columns-row) 자체가 이미 min-width:600px를 요구하므로, 900px 이하에서
     좁히려 해도 행 쪽이 바닥을 정한다. .chatgpt-drive-miller의 overflow-x:auto가 그 폭을
     가로 스크롤로 흡수해 페이지 레벨 오버플로 없이 담아낸다(붕괴 금지 요구사항 충족). */
  body.chatgpt-reference-v1 .chatgpt-drive-gallery-stage {
    min-height: calc(var(--wizon-ai-space-unit) * 50);
    padding: var(--chatgpt-route-gap-md);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-gallery-filmstrip .chatgpt-drive-columns-row {
    width: calc(var(--wizon-ai-space-unit) * 24);
  }
}

@media (pointer: coarse) and (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .wds-pressed {
    scale: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .composer-popover:not([hidden]),
  body.chatgpt-reference-v1 .reasoning-popover:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-more-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-account-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-recent-menu:not([hidden]),
  body.chatgpt-reference-v1 .chatgpt-library-popover,
  body.chatgpt-reference-v1 .settings-choice-popover {
    animation: none !important;
  }
}

/* 20260709-mobile-sheet-top-layer (doc 144 §5, §7 rollout): these mobile bottom-sheet
   menus are promoted to the native top layer via the Popover API on touch viewports so
   they escape the fixed sidebar's stacking context (the root cause — doc 144 §1). The
   layout still comes from the shared bottom-sheet block above (matched via :not([hidden]),
   which holds while the popover is open). Here we swap the interim paint-only scrim for a
   real ::backdrop dim. NOTE: the ::backdrop is VISUAL ONLY — every UA stylesheet forces
   pointer-events:none on it, so it cannot block taps; pass-through is stopped by the JS
   capture guard (handleTopLayerOutsidePointerDown in app.js). The library popover is NOT
   here — it re-renders outside setAnimatedDisclosure and keeps the interim box-shadow. */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-account-menu:popover-open,
  body.chatgpt-reference-v1 .chatgpt-more-menu:popover-open,
  body.chatgpt-reference-v1 .chatgpt-recent-menu:popover-open,
  body.chatgpt-reference-v1 .composer-popover:popover-open,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:popover-open,
  body.chatgpt-reference-v1 .reasoning-popover:popover-open {
    /* Drop the 0 0 0 100vmax scrim (it let taps fall through); keep only the lift shadow. */
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.22) !important;
  }

  body.chatgpt-reference-v1 .chatgpt-account-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-more-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-recent-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .composer-popover:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .reasoning-popover:popover-open::backdrop {
    background: var(--wizon-scrim, rgba(0, 0, 0, 0.24));
    /* `backwards` (not `both`) so the resting opacity:1 governs post-entrance and the exit
       transition below can fade it out (mirrors the sheet translate approach). */
    opacity: 1;
    animation: wizon-scrim-in var(--wizon-motion-base) var(--wds-ease-out) backwards;
  }
}

/* 20260709-motion-m1 (doc 146 §2, revised after VIDEO verification): EXIT — sheet slides back
   down + scrim fades out while closing.
   ★ CRITICAL: the exit MUST be a keyframe `animation`, NOT a `transition`. Safari does not paint
   a CSS `transition` on a top-layer popover/::backdrop — the layout box moves (getBoundingClientRect
   sees it) but the rendered pixels just vanish, so the sheet appeared to "just close". A keyframe
   `animation` IS composited in the top layer (same as the working entrance). Verified frame-by-frame
   on the iOS simulator. Only the six stateful sheets reach this (library re-renders outside
   setAnimatedDisclosure → no state). */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-account-menu[data-motion-state="closing"],
  body.chatgpt-reference-v1 .chatgpt-more-menu[data-motion-state="closing"],
  body.chatgpt-reference-v1 .chatgpt-recent-menu[data-motion-state="closing"],
  body.chatgpt-reference-v1 .composer-popover[data-motion-state="closing"],
  body.chatgpt-reference-v1 .chatgpt-conversation-menu[data-motion-state="closing"],
  body.chatgpt-reference-v1 .reasoning-popover[data-motion-state="closing"] {
    animation: wizon-sheet-down var(--wizon-sheet-exit-ms, 300ms) var(--wizon-sheet-exit-ease, cubic-bezier(0.33, 0, 0.2, 1)) forwards;
  }

  body.chatgpt-reference-v1 .chatgpt-account-menu[data-motion-state="closing"]:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-more-menu[data-motion-state="closing"]:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-recent-menu[data-motion-state="closing"]:popover-open::backdrop,
  body.chatgpt-reference-v1 .composer-popover[data-motion-state="closing"]:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu[data-motion-state="closing"]:popover-open::backdrop,
  body.chatgpt-reference-v1 .reasoning-popover[data-motion-state="closing"]:popover-open::backdrop {
    animation: wizon-scrim-out var(--wizon-sheet-exit-ms, 300ms) linear forwards;
  }
}

/* 20260712-question-card-bottom-sheet (doc 166; fallback symmetry doc 167 §4.4): on touch the
   question card rides the same top-layer bottom-sheet system as the menus — a popup separate from
   the thread, so it slides up over everything with a ::backdrop dim instead of an inline dock that
   stacked over the message actions/meta (the reported overlap). Gated on (pointer: coarse), NOT on
   [popover]: a coarse device whose browser lacks the Popover API still gets the fixed bottom-sheet
   layout + the paint-only 100vmax scrim (same degraded mode as the sibling menus), while a NARROW
   DESKTOP window (fine pointer) keeps the inline dock — [popover] gating gave that browser no sheet
   treatment at all. The card's own surface is flattened — the dock provides the sheet chrome.
   Sizing differs from the sibling menu sheets ON PURPOSE (85vh/-40px vs 70vh/-96px, 20/14 vs 8/8
   padding): this is a form (text field + keyboard + submit), not a row menu — it needs the extra
   height headroom and breathing room around inputs (doc 167 §4.4). */
@media (max-width: 520px) and (pointer: coarse) {
  body.chatgpt-reference-v1 .orchestration-dock:not([hidden]) {
    position: fixed !important;
    left: 0 !important;
    right: 0 !important;
    top: auto !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: none !important;
    height: auto !important;
    max-height: min(85vh, calc(var(--wizon-vvh, 100dvh) - 40px)) !important;
    overflow-y: auto !important;
    margin: 0 !important;
    padding: 20px 14px calc(16px + var(--wizon-safe-bottom)) !important;
    background: var(--cg-menu-bg, var(--surface, #fff)) !important;
    border-radius: var(--wizon-ai-radius-sheet, 18px) var(--wizon-ai-radius-sheet, 18px) 0 0 !important;
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.22), 0 0 0 100vmax var(--wizon-scrim, rgba(0, 0, 0, 0.24)) !important;
    transform: none !important;
    translate: 0 0;
    z-index: 200 !important;
    animation: wizon-sheet-up var(--wds-spring-spatial-default-duration, 372ms)
      var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1)) backwards;
  }

  /* grab handle — same ::after recipe as the sibling sheets (doc 167 §4.4 DRY); declared here
     because the sibling rule lives in a media block without the coarse-pointer condition. */
  body.chatgpt-reference-v1 .orchestration-dock:not([hidden])::after {
    content: "";
    position: absolute;
    top: 8px;
    left: 50%;
    width: 36px;
    height: 4px;
    border-radius: var(--wizon-ai-radius-pill, 999px);
    background: var(--wizon-ai-text-muted-2, #8a8a8a);
    opacity: 0.5;
    transform: translateX(-50%);
  }

  /* Flatten the card — the dock now IS the sheet surface (bg, rounding, handle). */
  body.chatgpt-reference-v1 .orchestration-dock:not([hidden]) .orchestration-card {
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    padding: 0;
  }

  /* Top layer active: swap the paint-only scrim for the real ::backdrop (mirrors the sibling
     sheets' :popover-open shadow swap). */
  body.chatgpt-reference-v1 .orchestration-dock:popover-open {
    box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.22) !important;
  }

  /* Real ::backdrop dim (VISUAL only — the JS capture guard blocks the tap-through). */
  body.chatgpt-reference-v1 .orchestration-dock:popover-open::backdrop {
    background: var(--wizon-scrim, rgba(0, 0, 0, 0.24));
    opacity: 1;
    animation: wizon-scrim-in var(--wizon-motion-base)
      var(--wds-ease-out) backwards;
  }

  /* Exit — slide down + scrim fade (keyframe animation, not transition; Safari top-layer paints
     only animations — see the 20260709-motion-m1 note above). */
  body.chatgpt-reference-v1 .orchestration-dock[data-motion-state="closing"] {
    animation: wizon-sheet-down var(--wizon-sheet-exit-ms, 300ms)
      var(--wizon-sheet-exit-ease, cubic-bezier(0.33, 0, 0.2, 1)) forwards;
  }
  body.chatgpt-reference-v1 .orchestration-dock[data-motion-state="closing"]:popover-open::backdrop {
    animation: wizon-scrim-out var(--wizon-sheet-exit-ms, 300ms) linear forwards;
  }
}

/* 20260710-library-sheet-motion: the library new/filter menus re-render as fresh HTML inside
   renderPortalPage, so the setAnimatedDisclosure exit above can never reach them. EXIT is animated
   by cloning the closing sheet to <body> as an inert ghost (JS spawnLibrarySheetGhost) — the ghost
   suppresses the entrance and slides+fades out. An in-place update while the menu stays open (e.g.
   a filter tap re-rendering the popover) would otherwise replay the entrance slide every tap; the
   [data-library-sheet-static] attribute suppresses that so only a genuine open animates. */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-library-popover[data-library-sheet-static] {
    animation: none !important;
  }
  body.chatgpt-reference-v1 .chatgpt-library-popover[data-library-sheet-ghost] {
    pointer-events: none;
    animation: none;
  }
  body.chatgpt-reference-v1 .chatgpt-library-popover[data-library-sheet-ghost][data-motion-state="closing"] {
    animation: wizon-library-sheet-out var(--wizon-sheet-exit-ms, 300ms)
      var(--wizon-sheet-exit-ease, cubic-bezier(0.33, 0, 0.2, 1)) forwards;
  }
}

@media (max-width: 520px) and (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 [data-motion-state="closing"],
  body.chatgpt-reference-v1 [data-motion-state="closing"]:popover-open::backdrop {
    transition: none !important;
    translate: none !important;
  }
}

@media (max-width: 520px) and (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .chatgpt-account-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-more-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-recent-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .composer-popover:popover-open::backdrop,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:popover-open::backdrop,
  body.chatgpt-reference-v1 .reasoning-popover:popover-open::backdrop {
    animation: none !important;
  }
}

/* 20260709-mobile-sheet-escape (doc 143 item C fix): the sidebar carries
   transform: translate3d(0,0,0) + will-change: transform, each of which makes it the
   containing block for its position:fixed descendants — so a bottom-sheet menu inside
   the drawer (account / more / recent) was clipped to the drawer width instead of
   spanning the viewport. While such a sheet is open, drop those properties so the
   fixed sheet escapes to the full screen. :has() is supported on the target Safari. */
@media (max-width: 900px) {
  body.chatgpt-reference-v1 .sidebar:not([data-motion-state="opening"]):not([data-motion-state="closing"]) {
    transform: none !important;
    will-change: auto !important;
  }
}

/* 20260710-motion-m2 (doc 146 §3): mobile drawer offcanvas slide. The sidebar is a plain
   <aside> (NOT top-layer), animated by keyframe `animation` on the individual `translate`
   property. `opening` parks it off-canvas for one frame; `open` slides it in; `closing` slides
   it out. The escape rule above owns `transform` at rest — we only touch `translate`/`opacity`,
   so the child bottom-sheets still escape. Verified frame-by-frame on the iOS simulator (R2). */
@media (max-width: 900px) {
  /* Pin the mobile drawer's box while animating. The DESKTOP collapse-transition rule
     `body[data-sidebar-transition] .sidebar` (styles.css:10139) sets width:260px + absolute +
     pointer-events:none during the transition — which our M2 change now triggers on mobile too,
     making the drawer stretch 260→300px at the end (the reported "왼쪽이 튕기며 늘어남"). Same
     specificity, later source order → this wins and keeps the drawer at its open box throughout. */
  body.chatgpt-reference-v1 .sidebar[data-motion-state] {
    position: fixed;
    width: min(300px, calc(100vw - 48px));
    z-index: 70;
    pointer-events: auto;
  }
  body.chatgpt-reference-v1 .sidebar[data-motion-state="opening"] {
    translate: -100% 0;
    opacity: 1;
    transform: none;
  }
  body.chatgpt-reference-v1 .sidebar[data-motion-state="open"] {
    opacity: 1;
    transform: none;
    animation: wizon-drawer-in var(--wds-spring-spatial-default-duration, 372ms) var(--wds-spring-effect-default, cubic-bezier(0.16, 1, 0.3, 1));
  }
  body.chatgpt-reference-v1 .sidebar[data-motion-state="closing"] {
    opacity: 1;
    transform: none;
    animation: wizon-drawer-out var(--wizon-sheet-exit-ms, 300ms) var(--wizon-sheet-exit-ease, cubic-bezier(0.33, 0, 0.2, 1)) forwards;
  }

  /* Scrim present during open + closing so it fades OUT with the drawer (the base
     `:not(.sidebar-collapsed)` rule hides it the instant `closing` adds the collapsed class). */
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="opening"]) .chatgpt-sidebar-scrim,
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="open"]) .chatgpt-sidebar-scrim,
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="closing"]) .chatgpt-sidebar-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 65;
    background: var(--wizon-scrim, rgba(0, 0, 0, 0.24));
  }
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="opening"]) .chatgpt-sidebar-scrim {
    opacity: 0;
  }
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="open"]) .chatgpt-sidebar-scrim {
    animation: wizon-scrim-in var(--wds-spring-spatial-default-duration, 372ms) linear backwards;
  }
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state="closing"]) .chatgpt-sidebar-scrim {
    animation: wizon-scrim-out var(--wizon-sheet-exit-ms, 300ms) linear forwards;
  }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .sidebar[data-motion-state],
  body.chatgpt-reference-v1:has(.sidebar[data-motion-state]) .chatgpt-sidebar-scrim {
    animation: none !important;
    translate: none !important;
  }
}

/* 20260709-mobile-input-zoom (doc 143): iOS Safari zooms the page IN when a text field with
   computed font-size < 16px receives focus, and keeps that zoom afterwards — so logging in
   (14px fields) left the whole app zoomed-in on first entry, and focusing the 15px composer
   did the same. Forcing >= 16px on text fields for coarse-pointer devices stops the auto-zoom
   entirely (16px is also the iOS-recommended readable minimum). !important is needed to beat
   the component rules that set the smaller token sizes. (ref: WebKit text-field zoom rule.) */
@media (pointer: coarse) {
  input:where([type="text"], [type="email"], [type="password"], [type="search"], [type="url"], [type="tel"], [type="number"]),
  input:not([type]),
  textarea {
    font-size: 16px !important;
  }
}

/* 20260709-mobile-focus-rings (doc 143): on touch devices a focus ring only ever appears
   from a tap (no keyboard in use) and reads as a stuck highlight. Per-component
   :focus-visible guards are not enough because iOS Safari mis-reports :focus-visible after a
   tap (the ring still paints). So on coarse-pointer devices suppress the ring globally for
   interactive controls. Text fields are intentionally excluded — they keep their focus
   styling and caret. Desktop / fine-pointer users are unaffected and keep keyboard focus
   rings. (ref: MDN :focus-visible; user-reported sidebar/settings focus-ring cleanup.) */
@media (pointer: coarse) {
  .chatgpt-reference-v1 button:focus,
  .chatgpt-reference-v1 a:focus,
  .chatgpt-reference-v1 [role="button"]:focus,
  .chatgpt-reference-v1 [role="switch"]:focus,
  .chatgpt-reference-v1 [role="menuitem"]:focus,
  .chatgpt-reference-v1 [role="menuitemradio"]:focus,
  .chatgpt-reference-v1 [role="option"]:focus,
  .chatgpt-reference-v1 [role="tab"]:focus,
  .chatgpt-reference-v1 summary:focus {
    outline: none;
  }
}

/* 20260710-composer-mode-slot-expansion (doc 150 P0): a visible mode pill (이미지 만들기 등)
   lives in the same .composer-textarea-scroll as the input, so the empty-state rules squeezed
   the pill and placeholder onto one line (overlap). The empty-state clamps are now guarded
   against .composer-mode-slot (so they skip the mode case); this block supplies the matching
   two-row expansion — mirroring the attachment-lane expansion — so the pill stacks ABOVE the
   input. Placed last so source order beats the @media(520) mobile composer block. */
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])),
body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) {
  grid-template-rows: auto !important;
  min-height: 84px !important;
  height: auto !important;
  max-height: min(360px, calc(100dvh - 24px)) !important;
  padding: 5px 8px !important;
}
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) .composer-prompt-body {
  grid-template-rows: auto !important;
  align-items: start !important;
  min-height: 0 !important;
  height: auto !important;
  max-height: none !important;
}
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) .composer-textarea-scroll {
  display: block !important;
  align-self: start !important;
  min-height: 0 !important;
  height: auto !important;
  max-height: max(30svh, 5rem) !important;
  overflow-y: auto !important;
}
body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) textarea {
  align-self: start !important;
  min-height: 26px !important;
  height: auto !important;
  max-height: none !important;
}


/* 20260710-starter-chip-hidden-guard (docs/product/150 §6 결정1): [hidden]으로 표시한
   스타터 칩/컴포저 메뉴 아이템(이미지 만들기 = P2까지 비노출)이 실제로 숨도록 강제.
   `.prompt-chip.chatgpt-action-chip { display: flex }`의 명시적 display가 UA
   `[hidden] { display: none }`(낮은 특정성)을 이겨 hidden이 무력화되던 문제를 차단. */
.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip[hidden],
.chatgpt-reference-v1 .composer-menu-item[hidden] {
  display: none !important;
}


/* 20260710-starter-shelf-chipgroup (실기기 피드백): 스타터 칩 셸프를 WDS ChipGroup 패턴으로 —
   고정 크기 칩 + 좌우 가로 스크롤. 칩이 트랙에 맞으면 중앙, 넘치면 시작 정렬+스크롤(P2 이미지 등
   추가 대비). safe center = 맞을 때 중앙 / 넘칠 때 start(클리핑 방지). */
html[data-chat-state="empty"] .chatgpt-reference-v1 .chatgpt-prompt-shelf {
  flex-wrap: nowrap !important;
  justify-content: safe center;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  padding-inline: 4px;
}
html[data-chat-state="empty"] .chatgpt-reference-v1 .chatgpt-prompt-shelf::-webkit-scrollbar {
  display: none;
}
.chatgpt-reference-v1 .chatgpt-prompt-shelf .prompt-chip.chatgpt-action-chip {
  flex: 0 0 auto;
  scroll-snap-align: start;
}


/* 20260710-composer-focus-wake (실기기 인터랙션 요청): 칩/모드 선택으로 키보드가 올라올 때
   컴포저에 1회 글로우 펄스를 줘 "여기 입력하세요"를 명확히 신호. 캐럿도 진한 텍스트색으로 강조.
   모노크롬 브랜드에 맞춰 텍스트색 링, compositor-친화(opacity/transform), reduced-motion 시 펄스 생략. */
body.chatgpt-reference-v1 .composer-surface textarea,
body.chatgpt-reference-v1 .chatgpt-composer-shell textarea {
  caret-color: var(--cg-text, var(--wizon-ai-text-primary, #0d0d0d));
}
body.chatgpt-reference-v1 .chatgpt-composer-shell.composer-focus-wake::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 2px var(--cg-text, #0d0d0d);
  opacity: 0;
  pointer-events: none;
  z-index: 1;
  animation: composer-focus-wake 520ms cubic-bezier(0.16, 1, 0.3, 1) 1;
}
@keyframes composer-focus-wake {
  0% { opacity: 0; transform: scale(0.992); }
  28% { opacity: 0.34; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.016); }
}
@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .chatgpt-composer-shell.composer-focus-wake::after { animation: none; opacity: 0; }
}


/* 20260710-composer-mode-slot-web-inline (실기기 피드백): 웹(≥521px)은 모바일처럼 pill을 윗줄에
   쌓을 필요 없음 — ChatGPT처럼 태그+입력을 한 줄로. P0 2행 확장(20260710-composer-mode-slot-expansion)을
   넓은 화면에서만 인라인 flex 행으로 되돌린다. 모바일(≤520px)은 2행 유지. */
@media (min-width: 521px) {
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])),
  body.chatgpt-reference-v1 .composer-surface.chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) {
    min-height: 52px !important;
  }
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) .composer-prompt-body {
    align-items: center !important;
  }
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) .composer-textarea-scroll {
    display: flex !important;
    align-items: center !important;
    align-self: center !important;
    gap: 8px;
  }
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) .composer-mode-slot {
    margin: 0 !important;
    flex: 0 0 auto;
    align-self: center !important;
  }
  body.chatgpt-reference-v1 .chatgpt-composer-shell:has(.composer-mode-slot:not([hidden])) textarea {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    align-self: center !important;
  }
}


/* 20260710-branch-switcher (docs/product/156 §5): ‹ n/m › active-branch switcher in a message
   action row. Hidden entirely when a turn has a single branch (renderBranchSwitcher returns ""). */
.chatgpt-reference-v1 .branch-switcher {
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
.chatgpt-reference-v1 .branch-switcher-count {
  font-size: var(--ds-text-caption-12);
  color: #8f8f8f;
  min-width: 2.4em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
.chatgpt-reference-v1 .branch-switch[disabled] {
  opacity: 0.35;
  pointer-events: none;
}


/* 20260710-icon-vertical-centering (아트디렉션 규칙): 아이콘을 어디서나 수직 중앙정렬로 기본값화.
   그동안 정렬은 컴포넌트마다 개별 처리(예: sidebar/menu는 [data-icon]에 inline-grid+place-items)라,
   정렬을 명시 안 한 아이콘 래퍼(라이브러리 검색바·"이 채팅의 파일" 칩 등)는 SVG가 inline baseline에
   걸려 아래로 처졌다 = 간헐적 어긋남의 원인. 아래 두 규칙이 그 기본값을 전역으로 세운다:
   ① [data-icon] 래퍼는 grid로 자식 SVG를 중앙에 둔다(기존 정상 컴포넌트와 동일 값 → tie여도 무회귀,
      :not([hidden])로 숨김 아이콘 미노출). ② 래퍼 없이 텍스트와 인라인으로 놓인 아이콘은
      vertical-align:middle로 텍스트 중앙에 맞춘다(grid/flex 자식에선 무시되어 무해). */
.chatgpt-reference-v1 [data-icon]:not([hidden]) {
  display: inline-grid;
  place-items: center;
}
.chatgpt-reference-v1 .wds-inline-icon {
  vertical-align: middle;
}


/* 20260710-reduced-motion-floor (아트디렉션 P0-2): 모션 감소 전역 하한. 그동안 reduced-motion은
   블록별 opt-in(17곳)이라 thinking-dot·streaming-cursor 같은 무한루프가 미커버로 새고 있었다.
   이 블랭킷이 기본값(모든 애니·전환 즉시 종료)이고, 기존 17개 블록은 세부 조정으로 유지.
   0.01ms(0 아님)라 animationend/transitionend는 정상 발화 = JS 대기 로직 무해. doc 143 하한선의 전역판. */
@media (prefers-reduced-motion: reduce) {
  .chatgpt-reference-v1 *,
  .chatgpt-reference-v1 *::before,
  .chatgpt-reference-v1 *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* 20260710-focus-visible-base (아트디렉션 P0-3): 키보드 포커스 링 단일 기본값. 그동안 outline:none
   리셋(32곳)+제각각 재구현(링 8종 혼재)이라 빠뜨린 컨트롤은 키보드 포커스가 안 보였다. 이 기본이
   구멍을 메우고, 컴포넌트의 의도적 오버라이드(더 높은 특정성)는 그대로 이긴다.
   input/textarea/select/contenteditable 제외 — 텍스트 입력은 UA가 클릭 포커스에도 :focus-visible을
   매칭해 컴포저/검색창에 원치 않는 링이 생기므로 컴포넌트 스타일(웨이크 링 등)에 맡긴다. */
.chatgpt-reference-v1 :focus-visible:not(input):not(textarea):not(select):not([contenteditable="true"]) {
  outline: 2px solid var(--cg-focus-visible-ring, #0d0d0d);
  outline-offset: 2px;
}
/* 20260710-focus-visible-base-coarse-guard: 위 P0-3 기본 링은 fine 포인터(키보드)용이다.
   coarse(터치)에서는 iOS Safari가 탭 후에도 :focus-visible을 오매칭해 링이 고착으로 보인다
   (doc 143/147, L15549 :focus 억제와 동일 취지). P0-3 기본 링이 (0,3,3)로 그 :focus 억제보다
   세서 되살아나므로, 같은 셀렉터를 coarse에서 후순위로 억제해 링을 끈다. 실기기 검증 대상. */
@media (pointer: coarse) {
  .chatgpt-reference-v1 :focus-visible:not(input):not(textarea):not(select):not([contenteditable="true"]) {
    outline: none;
  }
}

/* 20260710-icon-size-tokens: 기본 md 외 크기는 래퍼 모디파이어로 (개별 px 하드코딩 대신). */
.chatgpt-reference-v1 [data-icon-size="sm"] .wds-inline-icon {
  width: var(--wds-icon-size-sm, 16px);
  height: var(--wds-icon-size-sm, 16px);
}
.chatgpt-reference-v1 [data-icon-size="lg"] .wds-inline-icon {
  width: var(--wds-icon-size-lg, 24px);
  height: var(--wds-icon-size-lg, 24px);
}

/* 20260710-truncate-util (아트디렉션 P1-7): 한 줄 말줄임 표준 유틸. 그동안 overflow/nowrap/ellipsis를
   사이트마다 손으로 복붙(32곳)했는데, flex/grid 자식에서 필수인 min-width:0을 빠뜨리면 말줄임이
   "간헐적으로 안 먹는" 버그(아이콘 정렬과 동류의 기본값 누락)가 났다. 신규 말줄임은 이 클래스로 통일. */
.chatgpt-reference-v1 .wds-truncate {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  min-width: 0;
}

/* 20260711-typography-contract (doc 160, 사용자 승인 D1+D2): 타이포그래피 시맨틱 토큰 계약.
   실측(GPT/Claude/WIZON) × 코드감사 × 벤치마킹(Apple HIG·KRDS·WCAG) 교차 결과:
   본문 15px+strong 700(GPT는 16px+600)이 "굵고 답답"의 체감 원인, 모바일은 업스케일 부재.
   4종 시맨틱(body/label/meta/title)로 계약하고, 기존 파운데이션 토큰(--wds-font-size-body-2 70+곳,
   --wds-font-size-caption 12곳)을 body 스코프에서 시맨틱으로 승계해 소비처 일괄 편입.
   웨이트 팔레트 400/500/600 — 본문 강조 700 금지(strong→600). letter-spacing은 본문·UI 0 고정.
   font-synthesis-weight:none = 미로드 웨이트의 faux-bold 합성 차단(상속). */
body.chatgpt-reference-v1 {
  --cg-text-body-size: 16px;
  --cg-text-body-weight: 400;
  --cg-text-body-leading: 1.7;
  --cg-text-strong-weight: 600;
  --cg-text-label-size: 14px;
  --cg-text-label-weight: 400;
  --cg-text-label-leading: 1.45;
  --cg-text-label-active-weight: 500;
  --cg-text-meta-size: 12px;
  --cg-text-meta-weight: 500;
  --cg-text-title-size: 18px;
  --cg-text-title-weight: 600;
  --cg-text-title-leading: 1.35;
  /* anti-drift reconcile: dedicated token for the mobile top app bar's primary label.
     Introduced for .chatgpt-mobile-topbar-brand; that wordmark was replaced by the
     workspace switcher in 20260725-mobile-topbar-workspace, which inherits the token so
     the bar's headline size stays one value. NOT aliased to --cg-text-label-size — that
     variable is only repointed to 17px inside the narrower max-width:520px block, so
     aliasing here would silently shrink the label to 14px across the 521-900px range.
     Value unchanged (17px), just named. */
  --cg-text-topbar-brand-size: 17px;
  /* 파운데이션 승계: 기존 소비처(사이드바 route/recent/account/menu 별칭 체인)가 계약을 따라오게 */
  --wds-font-size-body-2: var(--cg-text-label-size);
  --wds-font-size-caption: var(--cg-text-meta-size);
  /* 공유 토큰은 불가침이므로 포털 스코프에서만 bold를 계약 상한(600)으로 승계 */
  --ds-weight-bold: var(--cg-text-strong-weight);
  font-synthesis-weight: none;
}

/* 본문(답변·유저버블): 15→16px, 행간 1.7. pre/code는 자체 규칙(12px mono) 유지. */
.chatgpt-reference-v1 .message-body,
.chatgpt-reference-v1 .message-body p {
  font-size: var(--cg-text-body-size);
  line-height: var(--cg-text-body-leading);
  font-weight: var(--cg-text-body-weight);
}
/* 본문 강조: UA bolder(→700)를 계약 600으로. 전역 기본이며 컴포넌트 명시 규칙이 이긴다. */
.chatgpt-reference-v1 strong,
.chatgpt-reference-v1 b {
  font-weight: var(--cg-text-strong-weight);
}
/* 라벨 표면(사이드바·컴포저/추론 메뉴): 시맨틱 토큰 소비 — 모바일 15px 승격이 여기로 전파 */
.chatgpt-reference-v1 .chatgpt-sidebar-link,
.chatgpt-reference-v1 .composer-menu-item,
.chatgpt-reference-v1 .reasoning-menu-item {
  font-size: var(--cg-text-label-size);
}
/* "최근" 섹션 헤더: 600 볼드 → meta 500 (볼드 대신 크기·색으로 위계 — 차분함 계약) */
.chatgpt-reference-v1 .chatgpt-recent-title {
  font-weight: var(--cg-text-meta-weight);
}
/* 다이얼로그 타이틀 3종 통합: 18/400 → 18/600 (GPT 실측 패리티) */
.chatgpt-reference-v1 .chatgpt-settings-head h2,
.chatgpt-reference-v1 .chatgpt-share-head h2,
.chatgpt-reference-v1 .chatgpt-delete-confirm-head h2 {
  font-size: var(--cg-text-title-size);
  font-weight: var(--cg-text-title-weight);
  line-height: var(--cg-text-title-leading);
}

/* T3 모바일 업스케일 (doc 160 R3, GPT 모바일 실측 정합): 데스크톱 px가 폰에 1:1로 실려 "작게"
   느껴지던 갭. GPT 모바일 드로어를 시뮬 3x 스크린샷 픽셀 계측한 결과 — 한글 글리프 45px=15.0pt
   (폰트 ≈17px, Apple HIG body 17과 일치), 행 피치 150px=50pt. 이에 맞춰 라벨 17px + 사이드바
   행높이 48px(피치 ~50pt). 시맨틱 토큰 재정의 한 곳으로 사이드바·메뉴·recent·account 일괄 전파. */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 {
    --cg-text-label-size: 17px;
    --cg-text-meta-size: 13px;
    --cg-sidebar-item-height: 48px;
  }
  /* 17px 폰트에 고정 20px 행간은 타이트 — 라벨 leading 토큰으로 보정
     (recent line-height 별칭은 .recent-list 컴포넌트 스코프라 소비처에서 직접). */
  body.chatgpt-reference-v1 .chatgpt-sidebar-link,
  body.chatgpt-reference-v1 .recent-item,
  body.chatgpt-reference-v1 .recent-primary,
  body.chatgpt-reference-v1 .composer-menu-item,
  body.chatgpt-reference-v1 .reasoning-menu-item {
    line-height: var(--cg-text-label-leading);
  }
}

/* 터치 입력에서만 적용한다 — 화면 폭이 아니라 «손가락이냐 마우스냐»가 기준이라
   max-width 가 아니라 pointer: coarse 다(이 파일의 기존 관례, 25159행과 같은 근거).
   ㉮ 컴포저 + 메뉴 항목이 36px 였다. 메뉴 자체는 이미 하단 시트(fixed·폭 100%·반경 18px)로
      잘 떠 있는데 항목만 작아, 시트까지 가서 오조작하는 구조였다. iOS HIG 최소 44pt 로 올린다.
      ★상단바 버튼은 ::after 로 44px 를 이미 보장하고 있었는데(아래 블록) 메뉴 항목엔 없었다.
      여기선 실제 행 높이를 키운다 — 시트 안이라 이웃과 겹칠 여지가 없다.
   ㉯ 모바일 상단바 버튼 반경 8px → 원형. ChatGPT iOS 관례이고 결함은 아니다.
   ★실측(2026-08-02, 라이브 390px 에 선언을 주입해 실물 요소로 확인):
     메뉴 항목 36px→44px(44 미만 9개→0), 상단바 반경 8px→999px. 데스크톱은 pointer: fine
     이라 이 블록이 매치되지 않아 무변화다. */
@media (pointer: coarse) {
  .chatgpt-reference-v1 .composer-menu-item {
    min-height: 44px;
  }
  .chatgpt-reference-v1 .chatgpt-mobile-topbar-button {
    border-radius: var(--ds-radius-pill);
  }
  /* 눌림 배경. ★이게 없으면 위 반경은 «보이지 않는 변경»이다 — 배경이 rgba(0,0,0,0)
     이라 칠할 픽셀이 없어서, 시뮬레이터 확대에서 아이콘 두 획만 보였다(2026-08-02 실측).
     :active 가 아니라 .wds-pressed 를 쓰는 이유는 app.js 주석이 이미 적어 뒀다 —
     iOS Safari 는 tap 에서 :active 를 불안정하게 발화한다. 이 버튼은 이미
     TAP_FEEDBACK_SELECTOR 에 있어 pointerdown 에 클래스가 붙고 scale 0.96 을 받는다.
     여기선 «면»을 하나 더해 눌린 것이 보이게 하고, 그 김에 반경도 드러나게 한다. */
  .chatgpt-reference-v1 .chatgpt-mobile-topbar-button.wds-pressed {
    background: var(--cg-hover-soft);
  }
}

/* 20260710-touch-target-hitslop (아트디렉션 P1-5): coarse(터치)에서 standalone 소형 아이콘버튼의
   탭 타깃을 44px로 확장(WCAG 2.5.5 / Apple HIG 44pt). 시각 박스는 그대로 두고 투명 ::after로만
   히트영역을 넓힌다(박스 팽창=밀도 붕괴를 피함). dense 행은 탭존 겹침=오탭이라 의도적으로 제외:
   composer-toolbar(gap 6px)·recent 액션·메뉴 항목. 대상은 여백이 확보된 두 곳 —
   모바일 상단바 버튼(40px, gap 8px→겹침 없음)과 헤더/다이얼로그 아이콘버튼(34px, 고립 배치).
   두 버튼 모두 overflow·기존 ::after 없음(슬롭 미클립·무충돌). 실기기 검증 대상. */
@media (pointer: coarse) {
  .chatgpt-reference-v1 .chatgpt-mobile-topbar-button,
  .chatgpt-reference-v1 .chatgpt-icon-button {
    position: relative;
  }
  .chatgpt-reference-v1 .chatgpt-mobile-topbar-button::after,
  .chatgpt-reference-v1 .chatgpt-icon-button::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    height: 100%;
    min-width: 44px;
    min-height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* 20260802-answer-footer-mobile-stack (북극성 ③, 배치 2): 폰에서 답변 하단은 «대각선»이 아니라
   왼쪽으로 정렬된 한 덩어리여야 한다. 배포 0583703ab 실측(390px): .feedback-row.message-actions
   는 액션 버튼 5개(합 160px)와 .answer-meta-cluster(199px)를 한 flex 행에 담는데 가용 폭이
   342px 뿐이라 17px 모자라 wrap 하고, 클러스터의 margin-left:auto 가 «줄바꿈된 줄»에서도 우측
   끝으로 밀어붙인다. 결과가 액션은 좌하단·메타는 우하단으로 갈라진 대각선이었다.
   한 줄로 압축하는 안은 실측 후 기각했다 — 폰트·아이콘·간격을 함께 줄여도 354px 로 여전히
   12px 초과라, 더 줄이면 설계가 아니라 욱여넣기가 된다.
   그래서 클러스터를 버튼 «위»로 올리고(order:-1) 둘 다 같은 좌측 시작선에 둔다. 메타는 이
   답변에 대한 설명이라 답변에 붙고, 액션은 사용자 행동이라 컴포저 쪽으로 모인다.
   데스크톱(>=901px)은 폭이 충분해 기존 «한 줄 우측 정렬» 그대로다. */
@media (max-width: 900px) {
  /* ★배치 4(아래 20260802-sheet-grab-handle 과 같은 배포)가 이 스택을 대체했다. 모델칩의
     「자동 · 」 접두를 빼서 클러스터가 198 → 169px 이 되자 버튼 160 + 169 = 329 ≤ 342 로
     «한 줄»에 들어간다 — 줄바꿈이 사라졌으니 두 줄을 정렬하던 규칙은 할 일이 없다.
     order/width/margin 을 되돌려 데스크톱과 같은 한 줄 우측 정렬로 둔다(공유 규칙의
     margin-left:auto 가 다시 일한다). row-gap 은 남긴다: 폰트 배율을 키운 기기에서 다시
     wrap 하면 그때는 두 줄 간격이 필요하다. */
  .chatgpt-reference-v1 .feedback-row.message-actions {
    row-gap: 4px;
  }
}

/* 20260802-sheet-grab-handle (북극성 ③ 배치 4): 바텀시트에 잡이(grab handle)를 그린다.
   위 20260709-mobile-bottom-sheet 주석은 「dimming scrim + drag handle」을 이미 약속해 놓고
   핸들을 한 번도 그리지 않았다(라이브 컴포저 시트 실측 hasHandle=false). Mobbin 에서 표본으로
   본 iOS 시트는 Obsidian·ChatGPT·Character AI·Fabric·Savee·pliability **6/6 전부** 이 잡이를
   갖는다 — 「이건 아래로 내려 닫는 판이다」를 말해 주는 표준 신호다.
   ::before 로 그리는 이유: DOM 을 늘리지 않아 메뉴에 엉뚱한 포커스 대상이 생기지 않고,
   등록된 시트 전부가 한 규칙으로 동시에 얻는다. 이 메뉴들은 display:grid 라 생성 상자가
   첫 행이 되고, 시트 블록의 align-content:start 덕에 맨 위에 앉는다. */
@media (max-width: 520px) {
  body.chatgpt-reference-v1 .composer-popover:not([hidden])::before,
  body.chatgpt-reference-v1 .reasoning-popover:not([hidden])::before,
  body.chatgpt-reference-v1 .chatgpt-more-menu:not([hidden])::before,
  body.chatgpt-reference-v1 .chatgpt-account-menu:not([hidden])::before,
  body.chatgpt-reference-v1 .chatgpt-conversation-menu:not([hidden])::before,
  body.chatgpt-reference-v1 .chatgpt-recent-menu:not([hidden])::before,
  body.chatgpt-reference-v1 .chatgpt-library-popover::before,
  body.chatgpt-reference-v1 .settings-choice-popover::before {
    content: "";
    justify-self: center;
    width: 36px;
    height: 4px;
    margin: 2px 0 10px;
    border-radius: var(--ds-radius-pill);
    background: var(--cg-menu-border);
  }

  /* 컴포저 「+」 시트는 여섯 항목이 한 줄기로 늘어서 있는데 성격은 셋이다 —
     첨부(사진·파일·최근 파일) / 만들기 / 연결 앱. 동적 목록 다음에 오는 항목이 정확히 그
     경계라, 그 자리에만 선을 넣어 새 개념 없이 이미 있는 묶음을 드러낸다. */
  body.chatgpt-reference-v1 .composer-menu-dynamic + .composer-menu-item {
    margin-top: 6px;
    padding-top: 10px;
    border-top: 1px solid var(--cg-menu-border);
  }
}

/* 20260802-empty-state-standard (북극성 ③): 라우트 빈 상태를 하나의 규격으로 모은다.
   390px 실측에서 셋이 서로 달랐고 둘은 제 위계가 뒤집혀 있었다 —
     /projects   제목 16px · 설명 17px · 제목 left 136 / 설명 left 16
     /scheduled  제목 15px · 설명 17px
     /drive      제목 15px (설명 없음)          ← 공유 블록. 이것만 옳았다.
   원인은 명확하다. 공유 .chatgpt-lifecycle-empty 는 제목과 설명 크기를 «각각» 선언하는데
   project/scheduled 는 컨테이너에만 font-size 를 걸어 제목이 그걸 상속하고, 설명은 자기
   라우트 본문 크기(17px)를 따로 선언했다. 그래서 설명이 자기가 설명하는 제목보다 커졌다.
   ★클래스와 기존 규칙은 그대로 둔다 — test_static_contract 가 그 선택자의 존재와 CSS 안
   위치를 구간 앵커로 쓴다. 여기서는 선언만 덮어 규격을 맞춘다. */
.chatgpt-reference-v1 .chatgpt-project-empty,
.chatgpt-reference-v1 .chatgpt-scheduled-empty {
  text-align: center;
}

.chatgpt-reference-v1 .chatgpt-project-empty strong,
.chatgpt-reference-v1 .chatgpt-scheduled-empty strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-15);
  font-weight: 500;
}

.chatgpt-reference-v1 .chatgpt-project-empty p,
.chatgpt-reference-v1 .chatgpt-scheduled-empty p {
  max-width: calc(var(--wizon-ai-space-unit) * 70);
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
  line-height: 1.5;
}

/* 빈 상태의 1차 액션. 에러 변형이 이미 쓰는 .chatgpt-route-action 과 같은 자리를 노리되,
   여기서는 «시작하게 하는» 버튼이라 주액션 톤을 쓴다. Mobbin iOS 표본 6/6(Coursera·
   Skyscanner·Ubank·Greenlight·Woolworths·Swiggy)이 전부 이 버튼을 갖는다. */
.chatgpt-reference-v1 .chatgpt-route-empty-action {
  margin-top: var(--wizon-ai-space-unit);
  min-height: var(--wizon-ai-action-target-sm);
  padding: 0 var(--ds-space-4, 16px);
  border: 0;
  border-radius: var(--ds-radius-pill);
  background: var(--wizon-ai-action-primary-bg);
  color: var(--wizon-ai-action-primary-fg);
  font-size: var(--ds-text-body-14);
  font-weight: 600;
  cursor: pointer;
}

/* ★모음 자체가 비었을 때만 크롬을 접는다. 검색·필터가 0건을 돌려준 것은 «다른 상태»이고
   거기서는 그 컨트롤을 고쳐야 하므로 절대 접으면 안 된다 — 그래서 이 규칙은 렌더러가
   routeCollectionIsEmpty() 로 계산해 붙이는 속성에만 걸린다. 필터 결과가 짧다고 걸리지 않는다. */
.chatgpt-reference-v1 .chatgpt-route-page-inner[data-route-empty="true"] .chatgpt-route-search,
.chatgpt-reference-v1 .chatgpt-route-page-inner[data-route-empty="true"] .chatgpt-route-tabs,
.chatgpt-reference-v1 .chatgpt-route-page-inner[data-route-empty="true"] .chatgpt-route-primary {
  display: none;
}

/* 20260803-touch-target-44 (doc 143 항목 B, 북극성 ③): 남아 있던 44pt 미만 탭 타깃을 닫는다.
   ★해법을 발명하지 않았다 — 위 20260710-touch-target-hitslop 이 이미 쓰는 «투명 ::after 로
   히트영역만 넓히고 시각 박스는 그대로» 를 그대로 재사용한다. 게이트도 그 관례대로 폭이
   아니라 pointer: coarse 다(손가락이냐 마우스냐가 기준).
   그 블록은 대상을 .chatgpt-icon-button / .chatgpt-mobile-topbar-button 둘로 한정했고, 아래
   다섯은 그 클래스를 하나도 갖지 않아 한 번도 덮인 적이 없다. 대신 다섯 전부 20260802 탭
   피드백의 scale 그룹에는 들어 있다 — 그래서 «눌리는 티는 나는데 누르기는 어렵다» 였다.

   라이브 390x844 실측(115957d0f, coarse/hover:none 미디어블록 19개·규칙 73개를 래퍼 없이
   재주입한 상태). 같은 하네스에서 .chatgpt-icon-button 이 시각 34x34 / ::after 44x44 로
   나오는 것을 대조군으로 먼저 확인했으므로, 「슬롭이 없다」는 관측의 사각이 아니라 실제 부재다.

   처방이 셋으로 갈리는 이유는 크기가 아니라 «옆에 남은 자리» 다:
   - 폭은 이미 44 이상이고 높이만 32 인 둘(.composer-model-pill 105.9x32,
     .chatgpt-recent-title 223x32) → 세로로만 넓힌다. 위아래 이웃이 16px·12px 떨어져 있어
     44 높이가 아무것도 건드리지 않는다. 가로까지 넓히면 얻는 것 없이 이웃 자리만 뺏는다.
   - .chatgpt-library-row-menu-trigger(행당 1개, 20개) → 행 안에 가로 이웃이 아예 없고 다음
     행까지 18.6px. 44x44 를 통째로 준다. ★이미 position: absolute 라 relative 를 다시
     선언하지 않는다 — 선언하면 흐름으로 되돌아가 ⋯ 버튼이 실제로 움직인다.
   - .chatgpt-library-view-control(3개, 형제 간격 6px)·.chatgpt-recent-header-action(2개,
     형제 간격 2px·타이틀과는 0px) → 44 폭으로 벌리면 형제의 탭존을 파고들어 «어느 쪽이
     먹느냐» 가 페인트 순서에 달린다. 그건 사용자가 내린 결정이 아니다. 그래서 가로는
     중간선까지만 간다: 보기 컨트롤은 calc(100% + 6px)=38px 로 두 슬롭이 정확히 맞닿고
     넘지 않으며, 헤더 액션은 왼쪽 중간선이 곧 제 경계라 가져올 가로 자리가 없어 높이만 받는다.

   실측 검증(후보 CSS 를 라이브 DOM 에 주입, elementFromPoint 로 네 변): 다섯 전부 슬롭
   가장자리에서 자기 자신이 잡히고, 6px 간격의 형제 경계에서는 중간선을 기준으로 갈렸다.
   ⚠️.recent-action(드로어 대화 행)은 여기 없다 — 계정에 대화가 0건이라 실측을 못 했고,
   터치에서는 opacity:0 + 롱프레스 시트(20260709-recent-longpress)가 따로 있어 «터치에서
   눌러야 하는 컨트롤인가» 부터 재야 한다. 재기 전에는 넣지 않는다. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .composer-model-pill,
  body.chatgpt-reference-v1 .chatgpt-recent-title,
  body.chatgpt-reference-v1 .chatgpt-recent-header-action,
  body.chatgpt-reference-v1 .chatgpt-library-view-control {
    position: relative;
  }

  body.chatgpt-reference-v1 .composer-model-pill::after,
  body.chatgpt-reference-v1 .chatgpt-recent-title::after,
  body.chatgpt-reference-v1 .chatgpt-recent-header-action::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }

  body.chatgpt-reference-v1 .chatgpt-library-view-control::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(100% + 6px);
    height: 44px;
    transform: translate(-50%, -50%);
  }

  body.chatgpt-reference-v1 .chatgpt-library-row-menu-trigger::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* 20260803-touch-target-44-sweep (doc 143 항목 B, 배치 2): 손으로 고른 여섯이 아니라 «전수»로
   찾은 나머지. 배포본 b6d12c7a4 를 390x844 에서, coarse/hover:none 미디어블록을 래퍼 없이
   재주입한 상태로 홈·드로어·라이브러리·아카이브·휴지통·컴포저 시트·설정을 훑어 보이는
   인터랙티브 요소 전부의 실제 히트영역(= 테두리 상자와 ::after 상자의 축별 최댓값)을 쟀다.
   ★아카이브·휴지통·컴포저 시트는 0건이었다 — 배치 3 과 20260729 touch-targets-a2 가 이미 닫았다.

   남은 것이 «왜 작은가»로 갈리고, 그 갈림이 이 블록의 요점이다.
   - .chatgpt-mobile-workspace-trigger 65x40, 좌우 여유 114.5px → 슬롭이 아무 대가도 치르지 않는다.
   - .composer-icon-button 36x36 / 36x36 / 38x38, 형제 간격 6px. 위 20260710 주석이 컴포저
     툴바를 제외한 이유가 바로 «6px 간격에서 44 슬롭은 겹친다» 였다. 배치 1 에서 합의한
     중간선 규칙이 그 사유를 없앤다 — calc(100% + 6px) 은 한쪽에 3px 씩만 가져가 형제 슬롭과
     정확히 맞닿고 넘지 않는다. 실측 42x44 / 42x44 / 44x44, 네 변 모두 자기 자신이 잡힌다.
     ★position: relative 를 여기서 «선언»한다. 세 버튼이 라이브에서 relative 로 나오긴 하지만
     styles.css 어디에도 .composer-icon-button 자체에 position 을 주는 규칙이 없다 — 변형
     클래스에서 흘러온 것이다. 남의 규칙의 부수효과에 절대배치를 얹으면, 그 변형이 손질되는
     날 슬롭이 조용히 엉뚱한 조상으로 탈출한다.
   - .chatgpt-route-tabs button 57.4~72.1x39.8 → ★이건 슬롭이 아니다. 레일이 <=900px 에서
     overflow-x: auto 인 가로 스크롤러이고 높이가 버튼에 딱 맞아, overflow 가 패딩 박스에서
     자르는 탓에 더 큰 ::after 는 절대 빠져나오지 못한다(패딩+음수마진으로 열어 봤더니 이번엔
     3px 밀렸다). 이 모양에 대한 답은 리포에 이미 있다 — .chatgpt-trash-category-tabs button 의
     min-height: 44px (<=900px, 배포됨). 아카이브·휴지통 탭이 44 이고 라이브러리 탭만 39.8 인
     이유가 그것이다. 기제를 새로 만들지 않고 그 결정을 공유 레일로 넓힌다. 실측: 39.8 → 44,
     아래 목록이 4.2px 내려가고, 가로 오버플로 없음, 레일은 여전히 스크롤 없이 들어간다.
     게이트가 coarse 가 아니라 <=900px 인 것도 선례 그대로다 — 보이는 상자를 바꾸는 변경이고
     데스크톱 밀도는 의도된 것이라서다.

   ⚠️.prompt-chip(96~112x40)은 일부러 뺐다. computed min-height 가 40px 로 핀돼 있어
   body.chatgpt-reference-v1 오버라이드가 못 이기고, 레일은 위와 같은 이유로 자르며, 패딩+음수
   마진으로 열면 칩이 3px 위로 밀린다(레일이 하단 앵커 그리드의 아이템이고 그 마진이 더 높은
   특이도 규칙에 핀돼 있다). 홈 히어로 행을 키우는 건 아트디렉션 결정이지 기계적 슬롭이 아니다.
   ⚠️텍스트 필드(컴포저 342x26 · 라이브러리 검색 306x34 · 설정 306x27.5)도 뺐다 — <input> 은
   ::after 가 생성되지 않아 유일한 처방이 보이는 상자를 키우는 것이다. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger,
  body.chatgpt-reference-v1 .composer-icon-button {
    position: relative;
  }

  body.chatgpt-reference-v1 .chatgpt-mobile-workspace-trigger::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }

  body.chatgpt-reference-v1 .composer-icon-button::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(100% + 6px);
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-route-tabs button {
    min-height: 44px;
  }
}

/* 20260803-touch-target-44-answer (doc 143 항목 B, 배치 3): 대화가 있어야 존재하는 두 표면.
   배치 1·2는 이 둘을 아예 못 쟀다 — 계정 대화가 0건이라(/api/portal/conversations counts.all=0)
   답변 화면도 드로어 최근 행도 렌더되지 않았다. 대화를 하나 만들고 나서 390x844,
   coarse/hover:none 재주입 상태로 배치 2와 같은 방법으로 쟀다.

   - .message-action-button 32x38, 5개(복사·좋아요·싫어요·소리로 듣기·다시 생성), 형제 간격
     **0px**. 중간선이 곧 제 경계라 가로로 가져올 자리가 없다 → 높이만 44. 위아래 여유 16px.
   - .chatgpt-conversation-more 36x36(상단바), 이웃과 4px. ★그 이웃이
     .chatgpt-mobile-topbar-button 이고 20260710 슬롭이 이미 그 4px 중 2px 을 먹고 있다.
     calc(100% + 4px) 로 남은 2px 씩만 가져가 두 슬롭이 정확히 맞닿는다 → 40x44.
     elementFromPoint 실측: 네 변 모두 자기 자신.
   - .recent-action 28x28, 행당 2개, 서로 **0px**(293x48 행 안에서 x = -65 · -37) → 높이만 44.
     ★기하를 적어 둔다. .recent-item 이 overflow: hidden 이라 클립이 문제가 될 수 있는데,
     버튼은 행(553~601) 안에서 563~591 로 «세로 중앙»이라 위아래 10px 씩 남고, 44 슬롭은
     555~599 를 차지해 행의 클립 상자 안에 2px 여유로 들어간다. 배포 전 네 변 프로브는 못
     돌렸다 — 프로브 중에 드로어가 계속 오프캔버스 위치로 돌아갔다. 그래서 이 하나는 위
     기하와, 같은 드로어의 같은 28x28 컨트롤인 .chatgpt-recent-header-action 이 배치 1에서
     28x44 로 네 변 전부 검증된 사실에 기댄다. 배포 후 라이브에서 확인한다.

   ⚠️.trust-chip 91.5x20 은 뺐다 — 이 표면 전체에서 가장 작고 WCAG 2.5.8 의 24px 하한에도
   못 미친다. 그런데 부모 .trust-chips 가 overflow: auto 라 .prompt-chip·라우트 탭과 똑같이
   더 큰 ::after 가 잘린다. z-index 를 올려도 그대로였는데, 그게 «페인트 순서»가 아니라
   «클립»이라는 서명이다. 라우트 탭과 달리 따라갈 배포된 선례도 없고, 20px 인라인 칩을 44px
   로 키우는 건 답변이 읽히는 방식을 바꾼다. 아트디렉션 결정이 먼저다. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .message-action-button,
  body.chatgpt-reference-v1 .chatgpt-conversation-more,
  body.chatgpt-reference-v1 .recent-action {
    position: relative;
  }

  body.chatgpt-reference-v1 .message-action-button::after,
  body.chatgpt-reference-v1 .recent-action::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }

  body.chatgpt-reference-v1 .chatgpt-conversation-more::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(100% + 4px);
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* 20260803-touch-target-44-cards (doc 143 항목 B, 배치 4): 답변 «카드» 표면.
   ★배치 2 는 「모든 모바일 표면을 훑었다」고 했고 §1.6 도 그렇게 고쳐 썼는데, 둘 다 같은
   방식으로 틀렸다 — 답변 카드는 «그 카드를 만든 대화 안에서만» 렌더된다. 그때 계정 대화가
   0건이라 스윕이 볼 수가 없었고, 뉴스 카드가 든 대화를 열자 44pt 미만이 47개 더 나왔다.
   교훈: 스윕은 «도달할 수 있었던 상태»만큼만 완전하다. 「전부 쟀다」는 「내가 만들어 낼 수
   있는 상태를 전부 만들어 놓고 쟀다」여야 한다.

   배포본 390x844, coarse 재주입, ★각 요소를 scrollIntoView 한 뒤 프로브했다(앞선 시도가
   네 변 모두 null 로 나온 건 결함이 아니라 요소가 뷰포트 밖이었기 때문이다).

   - .news-bookmark 28x28 (22개) → 44x44. 오른쪽 변만 카드 경계(.news-feed)에 닿는데 컨트롤이
     아니고, 나머지 세 변은 자기 자신이 잡힌다.
   - .news-hero-autoplay 32x32 → 44x44.
   - .citation-tag 123.8~128.7x**20** (5개) → 높이 44. .trust-chip 과 높이가 같은데 이쪽은
     overflow: auto 레일 «안에 있지 않아» 슬롭이 안 잘린다 — 하나는 여기서 닫히고 다른 하나는
     아직 아트디렉션 결정을 기다리는 이유가 그 차이다.
   - .source-pill 216.3x32.4 · .news-subscribe-btn 60.5x26.4 → 높이 44.
   - .news-arrow 32x32, 서로 7px → calc(100% + 7px) 로 중간선.
   - .news-dot 24x10 · 10x10(높이가 10px 다), 서로 14px → calc(100% + 14px).
   - .news-topic 106x40 (10개) 은 .news-topics-rail 이 overflow: auto 라 더 큰 ::after 가
     잘린다 — 라우트 탭과 같은 모양이므로 같은 배포된 답을 쓴다: <=900px 에서 min-height: 44px.
     실측 토픽 40 → 44, 레일 52 → 56, 페이지 가로 오버플로 없음, 레일 스크롤 불변.

   ★정정(배치 5, 같은 날): 이 자리에 «.news-hero-nav 둘이 세로로 간격 0 으로 포개졌다»고
   적어 제외했는데 **틀렸다.** 그 좌표 (58,-587)·(38,-549) 는 y 가 음수인 데서 보이듯 요소가
   뷰포트 밖이었고, 리렌더 도중 `position` 이 잠깐 `relative` 로 읽힌 과도기 값이었다.
   **연속 3회 안정 측정**은 둘 다 `position: absolute` 로 히어로 좌·우 끝(x 58 · 294, 간격
   198px)에 나란히 있고 44x44 슬롭이 네 변 모두 자기 자신으로 잡힌다. 그래서 아래 44x44
   묶음에 합류시켰다(이미 absolute 라 position: relative 는 주지 않는다).
   교훈: **캐러셀처럼 상태가 도는 표면은 한 번 재서 판정하지 말고 같은 값이 연속으로 나오는지
   를 봐라.** 한 번의 스냅샷으로 「구조가 막는다」를 선언했다가 배포까지 갔다.

   ⚠️하나는 여전히 못 닫았고 사유는 실측이다.
   - .news-topics-more 32x32 는 44x44 로 하면 위 변이 .news-topic 버튼 «안»에 들어간다
     (T 가 CTL:news-topic-label — 그 버튼 안의 span). 토픽 레일이 x 가 겹친 채 바로 위에
     있어 위쪽 중간선이 0 이다. 오탭을 다른 오탭과 바꾸는 셈이라 뺐다. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .news-bookmark,
  body.chatgpt-reference-v1 .news-hero-autoplay,
  body.chatgpt-reference-v1 .citation-tag,
  body.chatgpt-reference-v1 .source-pill,
  body.chatgpt-reference-v1 .news-subscribe-btn,
  body.chatgpt-reference-v1 .news-arrow,
  body.chatgpt-reference-v1 .news-dot {
    position: relative;
  }

  body.chatgpt-reference-v1 .news-bookmark::after,
  body.chatgpt-reference-v1 .news-hero-nav::after,
  body.chatgpt-reference-v1 .news-hero-autoplay::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }

  body.chatgpt-reference-v1 .citation-tag::after,
  body.chatgpt-reference-v1 .source-pill::after,
  body.chatgpt-reference-v1 .news-subscribe-btn::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }

  body.chatgpt-reference-v1 .news-arrow::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(100% + 7px);
    height: 44px;
    transform: translate(-50%, -50%);
  }

  body.chatgpt-reference-v1 .news-dot::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: calc(100% + 14px);
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .news-topic {
    min-height: 44px;
  }
}

/* 20260803-touch-target-44-trust-chip (doc 143 항목 B, 배치 6): .trust-chip 은 아트디렉션
   결정이 아니었다 — 배치 3·4 의 두 번째 자기정정.

   배치 3·4 는 이 칩(91.5x20, 이 표면에서 가장 작고 WCAG 2.5.8 의 24px 하한에도 미달)을
   «레일 .trust-chips 가 overflow: auto 라 더 큰 ::after 를 자른다 → 보이는 칩을 키우는 수밖에
   없다 → 아트디렉션» 으로 뺐다. **클립은 사실이었지만 결론이 틀렸다.**
   overflow 는 «패딩 박스»에서 자르므로, 레일을 padding-block 으로 열고 같은 만큼 음수 마진으로
   되갚으면 레이아웃을 건드리지 않고 클립만 넓힐 수 있다.
   ★그 레시피를 .prompt-chip(칩이 3px 밀림)과 .chatgpt-route-tabs(통했지만 배포된 min-height
   선례가 있어 그걸 씀)에서 시험해 놓고, **이 레일엔 시험하지 않은 채 일반화**했다.
   두 레일은 같지 않다 — .prompt-chip-row 는 하단 앵커 그리드의 아이템이고 마진이 더 높은
   특이도 규칙에 핀돼 있는 반면, .trust-chips 는 .message-body 의 평범한 블록 흐름 안에 있다.

   배포본 390x844 실측(padding-block: 12px; margin-block: -10px):
     칩 상단 238.4 → 238.4 · message-body 하단 322.4 → 322.4 · 다음 콘텐츠 280.4 → 280.4
     · 레일 높이 22 → 44.  **모든 기준점 이동 0**, 연속 3회 89.5x44 에 네 변 모두 자기 자신.
   보이는 칩은 그대로다.

   ⚠️.prompt-chip 은 제외를 유지한다. 같은 레시피가 거기서는 칩 2px·히어로 제목 4px 을 위로
   밀고, 어떤 마진 조합으로도 상쇄되지 않는다(이기는 마진 규칙이 body.chatgpt-reference-v1
   오버라이드보다 특이도가 높다). 40px 은 이미 WCAG 2.5.8 을 넘고, Apple 44 까지 남은 4px 은
   홈 히어로를 조용히 밀 게 아니라 결정을 받을 일이다. */
@media (pointer: coarse) {
  body.chatgpt-reference-v1 .trust-chips {
    padding-block: 12px;
    margin-block: -10px;
  }

  body.chatgpt-reference-v1 .trust-chip {
    position: relative;
  }

  body.chatgpt-reference-v1 .trust-chip::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: 44px;
    transform: translateY(-50%);
  }
}

/* 20260803-touch-target-44-final (doc 143 항목 B, 배치 7 — 마지막 둘):
   ★하나는 크기 문제가 아니었다.

   ① .prompt-chip — 배치 4~6 은 「computed min-height 가 40px 로 핀돼 body.chatgpt-reference-v1
   오버라이드가 못 이긴다」로 막혔다고 적었다. **그 규칙을 한 번도 찾아보지 않았다.**
   실제 규칙은 `.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip { height: 40px }` 이고
   특이도가 (0,3,0) 인데 내가 쓴 오버라이드는 (0,2,1) 이었다. 리포가 막은 게 아니라 선택자가
   진 것이다. (0,3,1) 로 다시 재니 390x844 에서:
     칩 높이 40 → 44 · 제목↔칩 간격 14 → **14** · 칩↔컴포저 간격 10 → **10** · 컴포저 728 → **728**
   **간격이 하나도 안 바뀐다.** 「제목+칩」 덩어리가 4px 위로 갈 뿐이고, 그 4px 은 홈이 이미
   비워 두고 있는 568px(셸의 67%)에서 나간다. 선례는 .chatgpt-trash-category-tabs button 과
   .chatgpt-route-tabs button — 둘 다 <=900px min-height: 44px 로 배포돼 있다. 보이는 상자를
   바꾸므로 게이트도 그 선례대로 폭(<=900px)이지 coarse 가 아니다.

   ② .news-topics-more — 「44 상자가 .news-topic 과 겹친다」고 보고했는데 증상의 절반이었다.
   **이 버튼은 지금 아무 탭도 못 받는다.** 가역 A/B(중앙 + 네 변):
     현재 → 전부 .news-topic-label · z-index:4 만 → 전부 버튼(32x32) ·
     z-index:4 + 슬롭 → 전부 버튼(44x44) · 주입 제거 → 다시 .news-topic-label
   원인은 이웃 칩 «안»에 있다: .news-topic-label 이 z-index: 3, .news-topic-img 가 z-index: 1
   인데 .news-topics-more 는 z-index: auto 다. DOM 상 나중 형제여도 이웃의 자식이 스스로를
   올려 버리면 소용없다.
   ★그래서 이건 터치 어포던스가 아니라 결함이고, **1280px 데스크톱에서도 동일하게 재현된다.**
   z-index 규칙에 미디어 게이트를 걸지 않는 이유가 그것이다. 44 슬롭만 coarse 로 건다.
   ★죽은 버튼보다 나쁘다 — 탭이 삼켜지는 게 아니라 «아래 깔린 분야 칩»에 꽂힌다. 사용자가
   「더 보기」를 눌렀는데 고르지도 않은 분야가 조용히 선택된다. */
body.chatgpt-reference-v1 .news-topics-more {
  z-index: 4;
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .prompt-chip.chatgpt-action-chip {
    height: 44px;
    min-height: 44px;
  }
}

@media (pointer: coarse) {
  body.chatgpt-reference-v1 .news-topics-more::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* ── 업무 드라이브 전송 진행 창 ─────────────────────────────────────────────
   ★2026-08-11. 파일을 드래그해 올렸는데 화면에 아무 변화가 없어 사용자가 새로고침을
   하고서야 올라간 걸 알았다. 진행 표시가 가던 곳(workspaceStatus)은 이 화면에서
   렌더 크기가 0×0 이었다. 그래서 이 창은 body 직속으로 «스스로» 선다. */
body.chatgpt-reference-v1 .wizon-drive-transfer {
  position: fixed;
  right: calc(var(--wizon-ai-space-unit) * 6);
  bottom: calc(var(--wizon-ai-space-unit) * 6);
  /* 업데이트 알림(.client-update-notice)과 같은 토스트 층. 같은 층에서는 DOM 순서가
     이기는데 이 창은 body 끝에 붙으므로 위로 온다. 임의의 큰 숫자를 박으면 스케일
     (overlay 1200 · modal 1300 · toast 1400 · tooltip 1500)이 무너진다. */
  z-index: var(--wds-z-toast, 1400);
  width: min(360px, calc(100vw - var(--wizon-ai-space-unit) * 8));
  padding: calc(var(--wizon-ai-space-unit) * 4);
  display: grid;
  gap: calc(var(--wizon-ai-space-unit) * 2);
  background: var(--cg-surface);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--ds-radius-md);
  box-shadow: var(--cg-menu-shadow);
  color: var(--cg-text, var(--text));
}

body.chatgpt-reference-v1 .wizon-drive-transfer[hidden] {
  display: none;
}

body.chatgpt-reference-v1 .wizon-drive-transfer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--wizon-ai-space-unit) * 2);
}

body.chatgpt-reference-v1 .wizon-drive-transfer-title {
  font-size: var(--ds-text-body-15);
  font-weight: 600;
  letter-spacing: -0.01em;
}

body.chatgpt-reference-v1 .wizon-drive-transfer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}

body.chatgpt-reference-v1 .wizon-drive-transfer-close:hover,
body.chatgpt-reference-v1 .wizon-drive-transfer-close:focus-visible {
  background: var(--cg-hover-soft);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .wizon-drive-transfer-track {
  height: 6px;
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--cg-hover-soft);
  overflow: hidden;
}

body.chatgpt-reference-v1 .wizon-drive-transfer-fill {
  display: block;
  height: 100%;
  width: 0%;
  border-radius: inherit;
  background: var(--cg-text, var(--text));
  /* 레이아웃 속성이 아니라 transform 만 쓰고 싶지만, 진행률 막대는 width 가 의미 자체다.
     6px 높이 한 줄이라 리플로 비용이 사실상 없다. */
  transition: width 180ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .wizon-drive-transfer-fill {
    transition: none;
  }
}

body.chatgpt-reference-v1 .wizon-drive-transfer-detail {
  margin: 0;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
  /* 파일명이 길어도 창을 밀어내면 안 된다. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .wizon-drive-transfer-failures {
  margin: 0;
  padding-left: calc(var(--wizon-ai-space-unit) * 4);
  max-height: 120px;
  overflow-y: auto;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
}

body.chatgpt-reference-v1 .wizon-drive-transfer-failures li {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 완료·실패는 색이 아니라 «막대의 상태»로도 읽혀야 한다 — 흑백잉크 테마라 색만으로
   구분하면 아무것도 구분되지 않는다. */
body.chatgpt-reference-v1 .wizon-drive-transfer[data-phase="done"] .wizon-drive-transfer-track {
  opacity: 0.45;
}

body.chatgpt-reference-v1 .wizon-drive-transfer[data-phase="error"] .wizon-drive-transfer-fill {
  background: repeating-linear-gradient(
    45deg,
    var(--cg-text, var(--text)) 0 4px,
    transparent 4px 8px
  );
}

@media (max-width: 520px) {
  body.chatgpt-reference-v1 .wizon-drive-transfer {
    right: calc(var(--wizon-ai-space-unit) * 3);
    left: calc(var(--wizon-ai-space-unit) * 3);
    bottom: calc(var(--wizon-ai-space-unit) * 3);
    width: auto;
  }
}

/* ── 같은 이름 파일 확인 다이얼로그 ─────────────────────────────────────────
   .chatgpt-delete-confirm-dialog 의 [open] 게이트를 그대로 물려받는다 — 닫힌 <dialog>가
   화면에 그려지는 사고를 막는 가드가 거기 붙어 있고, 다이얼로그마다 따로 다시 다는 구조라
   잊히기 쉽다. */
body.chatgpt-reference-v1 .chatgpt-drive-conflict-list {
  margin: 0 0 var(--chatgpt-route-gap-sm);
  padding-left: calc(var(--wizon-ai-space-unit) * 4);
  max-height: 168px;
  overflow-y: auto;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
}

body.chatgpt-reference-v1 .chatgpt-drive-conflict-list li {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-conflict-list li.is-more {
  list-style: none;
  margin-left: calc(var(--wizon-ai-space-unit) * -4);
  opacity: 0.75;
}

body.chatgpt-reference-v1 .chatgpt-drive-conflict-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: calc(var(--wizon-ai-space-unit) * 2);
}

/* 「업로드 취소」는 세 선택지와 같은 무게로 보이면 안 된다 — 되돌리는 문이지 선택지가 아니다. */
body.chatgpt-reference-v1 .chatgpt-drive-conflict-cancel {
  display: block;
  margin: calc(var(--wizon-ai-space-unit) * 3) 0 0 auto;
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
  text-decoration: underline;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-conflict-cancel:hover,
body.chatgpt-reference-v1 .chatgpt-drive-conflict-cancel:focus-visible {
  color: var(--cg-text, var(--text));
}

@media (max-width: 520px) {
  body.chatgpt-reference-v1 .chatgpt-drive-conflict-actions button {
    flex: 1 1 auto;
  }
}

/* ── 버전 기록 다이얼로그 ────────────────────────────────────────────────── */
body.chatgpt-reference-v1 .chatgpt-drive-version-name {
  margin: calc(var(--wizon-ai-space-unit) * 1) 0 0;
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-status {
  margin: 0 0 var(--chatgpt-route-gap-sm);
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
}

body.chatgpt-reference-v1 .chatgpt-drive-version-list {
  margin: 0 0 var(--chatgpt-route-gap-sm);
  padding: 0;
  list-style: none;
  max-height: 280px;
  overflow-y: auto;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--wizon-ai-space-unit) * 2);
  padding: calc(var(--wizon-ai-space-unit) * 2) 0;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}

body.chatgpt-reference-v1 .chatgpt-drive-version-list li:last-child {
  border-bottom: 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-meta {
  display: flex;
  align-items: baseline;
  gap: calc(var(--wizon-ai-space-unit) * 2);
  font-size: var(--ds-text-caption-13);
  color: var(--cg-muted, var(--muted));
  min-width: 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-meta strong {
  font-size: var(--ds-text-body-14);
  color: var(--cg-text, var(--text));
}

/* 「현재」는 색이 아니라 테두리로도 읽혀야 한다 — 흑백잉크 테마다. */
body.chatgpt-reference-v1 .chatgpt-drive-version-current {
  padding: 1px calc(var(--wizon-ai-space-unit) * 1.5);
  border: 1px solid var(--cg-text, var(--text));
  border-radius: var(--wizon-ai-radius-pill);
  font-size: var(--ds-text-micro-11);
  color: var(--cg-text, var(--text));
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-restore {
  flex: 0 0 auto;
  padding: calc(var(--wizon-ai-space-unit) * 1.5) calc(var(--wizon-ai-space-unit) * 3);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-control);
  background: transparent;
  color: var(--cg-text, var(--text));
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-version-restore:hover,
body.chatgpt-reference-v1 .chatgpt-drive-version-restore:focus-visible {
  background: var(--cg-hover-soft);
}

/* 「업로드는 폴더 안에서」 안내. 메뉴 항목처럼 생겼지만 누를 수 없는 설명이라, 눌리는
   항목과 시각적으로 구분되어야 한다 — 안 그러면 죽은 버튼이 된다. */
body.chatgpt-reference-v1 .chatgpt-drive-new-menu-hint {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--wizon-ai-space-unit) * 2);
  cursor: default;
  color: var(--cg-muted, var(--muted));
  font-size: var(--ds-text-caption-13);
  line-height: 1.45;
  white-space: normal;
  max-width: calc(var(--wizon-ai-space-unit) * 56);
}

body.chatgpt-reference-v1 .chatgpt-drive-new-menu-hint:hover {
  background: transparent;
}

/* ==========================================================================
   20260811 Drive workspace: Explorer/Finder-style docked layout.
   The app shell remains the global navigation. Inside the route, the folder tree,
   file list, and contextual preview are one continuous working surface.
   ========================================================================== */
html[data-portal-route="/drive"] #portalPage.chatgpt-route-page {
  --chatgpt-drive-content-max-width: none;
  --chatgpt-route-page-top: var(--chatgpt-route-gap-sm);
  --chatgpt-route-page-bottom: var(--chatgpt-route-gap-sm);
  width: 100%;
  height: 100%;
  max-width: none;
  margin: 0;
  padding-inline: clamp(16px, 2vw, 32px);
  overflow: hidden;
}

body.chatgpt-reference-v1 .chatgpt-drive-page {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  gap: 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead {
  display: flex;
  flex-direction: column;
  gap: var(--chatgpt-route-gap-xs);
}

body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead > .chatgpt-drive-breadcrumb {
  display: flex;
  margin: 0 0 var(--chatgpt-route-gap-sm);
}

body.chatgpt-reference-v1 .chatgpt-drive-filter-row {
  margin-bottom: 0;
  padding: var(--chatgpt-route-gap-sm) 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-explorer {
  display: grid;
  grid-template-columns: 220px minmax(520px, 1fr) minmax(292px, 330px);
  flex: 1 1 auto;
  gap: 0;
  height: auto;
  min-height: 0;
  overflow: hidden;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--wizon-ai-radius-popover, 16px);
  background: var(--cg-surface, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--tree-closed {
  grid-template-columns: minmax(520px, 1fr) minmax(292px, 330px);
}

body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--inspector-closed {
  grid-template-columns: 220px minmax(520px, 1fr);
}

body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--tree-closed.chatgpt-drive-explorer--inspector-closed {
  grid-template-columns: minmax(0, 1fr);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  padding: 10px;
  border-right: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-bg, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 38px;
  padding: 0 4px 0 10px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-medium);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-root,
body.chatgpt-reference-v1 .chatgpt-drive-tree-row {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 38px;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-root {
  gap: 9px;
  padding: 0 10px;
  font: inherit;
  font-size: var(--ds-text-body-14);
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-root svg,
body.chatgpt-reference-v1 .chatgpt-drive-tree-icon svg {
  width: 17px;
  height: 17px;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-root.is-active,
body.chatgpt-reference-v1 .chatgpt-drive-tree-row.is-active {
  background: color-mix(in srgb, var(--cg-focus-ring) 12%, var(--cg-surface));
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-panel {
  right: 0;
  left: auto;
  width: min(360px, calc(100vw - 32px));
  max-height: min(620px, calc(100vh - 180px));
  padding: 14px;
  overflow: auto;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-panel section {
  display: grid;
  gap: 8px;
  padding: 10px 0;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-panel section:first-child {
  padding-top: 0;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-panel section > strong {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-semibold);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-chip {
  min-height: 34px;
  padding: 0 11px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-surface, var(--bg));
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-chip.is-selected {
  border-color: color-mix(in srgb, var(--cg-focus-ring) 58%, var(--cg-menu-border));
  background: color-mix(in srgb, var(--cg-focus-ring) 12%, var(--cg-surface));
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-chip:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-types {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-filter-reset {
  width: 100%;
  margin-top: 12px;
  justify-content: center;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  background: var(--cg-surface, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 58px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-head > span:first-child {
  display: grid;
  gap: 2px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-summary {
  grid-template-columns: 20px minmax(0, 1fr);
  align-items: center;
  gap: 10px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-summary > span {
  display: grid;
  gap: 2px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-head strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-head small,
body.chatgpt-reference-v1 .chatgpt-drive-search-scope {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-scope {
  padding: 5px 9px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-results-list {
  min-height: 0;
  overflow: auto;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 92px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--cg-menu-border, var(--line));
  position: relative;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result.is-selected {
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result.is-selected::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-main {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 5px;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-icon .wizon-file-type-icon {
  width: 40px;
  height: 40px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-copy {
  display: grid;
  min-width: 0;
  gap: 3px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-title {
  overflow: hidden;
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: var(--wds-font-weight-semibold);
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-title mark,
body.chatgpt-reference-v1 .chatgpt-drive-search-result-snippet mark {
  border-radius: var(--ds-radius-2xs, 3px);
  background: color-mix(in srgb, var(--cg-focus-ring) 22%, transparent);
  color: inherit;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-path,
body.chatgpt-reference-v1 .chatgpt-drive-search-result-meta {
  overflow: hidden;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-snippet {
  display: -webkit-box;
  overflow: hidden;
  color: color-mix(in srgb, var(--cg-text) 82%, var(--cg-muted));
  font-size: var(--ds-text-caption-13);
  line-height: 1.45;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-side {
  display: grid;
  justify-items: end;
  gap: 8px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-result-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-match-badge {
  color: var(--cg-focus-ring);
  font-size: var(--ds-text-caption-12);
  font-weight: var(--wds-font-weight-semibold);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-state {
  display: grid;
  place-items: center;
  align-content: center;
  gap: 8px;
  min-height: 280px;
  padding: 32px;
  color: var(--cg-muted);
  text-align: center;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-state > svg {
  width: 26px;
  height: 26px;
}

body.chatgpt-reference-v1 .chatgpt-drive-search-state strong {
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .chatgpt-drive-search-spinner {
  width: 24px;
  height: 24px;
  border: 2px solid color-mix(in srgb, var(--cg-muted) 28%, transparent);
  border-top-color: var(--cg-focus-ring);
  border-radius: 50%;
  animation: chatgpt-drive-search-spin 700ms linear infinite;
}

@keyframes chatgpt-drive-search-spin {
  to { transform: rotate(360deg); }
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-search-result:hover {
    background: var(--cg-hover-soft);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-result:hover .chatgpt-drive-select-checkbox,
  body.chatgpt-reference-v1 .chatgpt-drive-search-result.is-selected .chatgpt-drive-select-checkbox,
  body.chatgpt-reference-v1 .chatgpt-drive-search-results-summary .chatgpt-drive-select-checkbox {
    opacity: 1;
  }
}

body.chatgpt-reference-v1 .chatgpt-drive-tree {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 2px;
}

/* D2: quota belongs to the Drive hierarchy rail, never the global WIZON navigation or the
   selection inspector. Until an API receipt proves a same-workspace current value, the rail
   deliberately exposes only this non-actionable unavailable state — no guessed meter/count. */
body.chatgpt-reference-v1 .chatgpt-drive-tree-quota {
  display: grid;
  flex: 0 0 auto;
  gap: 5px;
  margin: 10px -10px -10px;
  padding: 12px 14px max(12px, var(--chatgpt-route-gap-sm));
  border-top: 1px solid var(--cg-menu-border, var(--line));
  background: var(--cg-bg, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-kicker,
body.chatgpt-reference-v1 .chatgpt-drive-tree-quota p,
body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-manage {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota strong {
  color: var(--cg-text);
  font-size: var(--ds-text-caption-13);
  font-weight: var(--wds-font-weight-semibold);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-meter {
  display: block;
  width: 100%;
  height: 4px;
  overflow: hidden;
  appearance: none;
  border: 0;
  padding: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-meter::-webkit-progress-bar {
  background: var(--cg-hover-soft);
  border-radius: inherit;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-meter::-webkit-progress-value {
  background: var(--cg-focus-ring);
  border-radius: inherit;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-meter::-moz-progress-bar {
  background: var(--cg-focus-ring);
  border-radius: inherit;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-manage {
  width: fit-content;
  color: var(--cg-focus-ring);
  font-weight: var(--wds-font-weight-medium);
  text-decoration: none;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-manage:hover,
body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-manage:focus-visible {
  text-decoration: underline;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-quota-manage:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 2px;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-row {
  padding-right: 4px;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-twist {
  display: grid;
  place-items: center;
  flex: 0 0 28px;
  width: 28px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-twist svg {
  width: 14px;
  height: 14px;
  transition: transform var(--wizon-motion-micro-duration) var(--wizon-motion-effect-fast);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-twist.is-expanded svg {
  transform: rotate(90deg);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-open {
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 32px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--ds-text-caption-13);
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-status {
  margin: 6px 10px 6px 30px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-status.is-error {
  color: var(--cg-danger-fg);
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-tree-root:hover,
  body.chatgpt-reference-v1 .chatgpt-drive-tree-row:hover,
  body.chatgpt-reference-v1 .chatgpt-drive-tree-twist:hover {
    background: var(--cg-hover-soft);
  }
}

body.chatgpt-reference-v1 .chatgpt-drive-tree-root:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-tree-open:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-tree-twist:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-preview-open:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-row-open:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: -2px;
}

body.chatgpt-reference-v1 .chatgpt-drive-columns-pane {
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: auto;
  background: var(--cg-surface, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-columns-head {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--cg-surface, var(--bg));
}

body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-selected {
  background: color-mix(in srgb, var(--cg-focus-ring) 12%, var(--cg-surface));
}

body.chatgpt-reference-v1 .chatgpt-drive-columns-row.is-selected::before {
  width: 3px;
  background: var(--cg-focus-ring);
}

body.chatgpt-reference-v1 .chatgpt-drive-row-open {
  width: 100%;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-selection-dock {
  position: sticky;
  left: 0;
  bottom: 0;
  z-index: 4;
  padding: 10px 12px;
  border-top: 1px solid var(--cg-menu-border, var(--line));
  background: color-mix(in srgb, var(--cg-surface) 94%, transparent);
  backdrop-filter: blur(12px);
}

body.chatgpt-reference-v1 .chatgpt-drive-selection-dock .chatgpt-drive-bulk-bar {
  border: 0;
  padding: 0;
  background: transparent;
}

@media (min-width: 901px) {
  body.chatgpt-reference-v1 .chatgpt-drive-inspector {
    position: static;
    inset: auto;
    width: auto;
    height: 100%;
    margin: 0;
    padding: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-width: 0;
    border: 0;
    border-left: 1px solid var(--cg-menu-border, var(--line));
    border-radius: 0;
    background: var(--cg-bg, var(--bg));
    box-shadow: none;
    z-index: auto;
  }
}

body.chatgpt-reference-v1 .chatgpt-drive-inspector-head {
  min-height: 52px;
  padding: 0 12px 0 16px;
}

body.chatgpt-reference-v1 .chatgpt-drive-inspector-head h2 {
  font-size: var(--ds-text-body-14);
  font-weight: 600;
}

body.chatgpt-reference-v1 .chatgpt-drive-inspector-body {
  padding: 16px;
}

body.chatgpt-reference-v1 .chatgpt-drive-preview-open {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  min-height: 38px;
  margin: -8px 0 14px;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-control);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-preview-open svg {
  width: 16px;
  height: 16px;
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 250px;
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-lg);
  background: var(--cg-hover-soft);
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview iframe,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview img,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview video {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 250px;
  border: 0;
  object-fit: contain;
  background: var(--cg-surface);
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview audio {
  width: calc(100% - 28px);
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview--text {
  display: block;
  padding: 14px;
  text-align: left;
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview--text pre {
  max-height: 360px;
  margin: 0;
  overflow: auto;
  color: var(--cg-text);
  font: 12px/1.6 var(--wds-font-family-mono, monospace);
  white-space: pre-wrap;
  word-break: break-word;
}

body.chatgpt-reference-v1 .chatgpt-drive-preview-note {
  margin: 12px 0 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-loading {
  align-content: center;
  justify-items: stretch;
  gap: 10px;
  padding: 28px;
}

body.chatgpt-reference-v1 .chatgpt-drive-preview-skeleton {
  display: block;
  width: 72%;
  height: 9px;
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-hover);
}

body.chatgpt-reference-v1 .chatgpt-drive-preview-skeleton.is-wide { width: 94%; }
body.chatgpt-reference-v1 .chatgpt-drive-preview-skeleton.is-short { width: 48%; }

body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-error,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-sheet,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-unsupported {
  align-content: center;
  gap: 8px;
  padding: 24px;
  color: var(--cg-text);
  text-align: center;
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-error > span svg,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-sheet > span svg,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-unsupported > span svg {
  width: 28px;
  height: 28px;
  color: var(--cg-muted);
}

/* The shared live-preview media rule intentionally expands document/image content to the
   whole stage. A registry icon is a type cue, not document content, so keep it intrinsic;
   otherwise the unsupported-state copy is pushed below the fixed preview viewport. */
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-sheet > span .wizon-file-type-icon--preview,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-unsupported > span .wizon-file-type-icon--preview {
  width: clamp(64px, 18vw, 96px);
  height: clamp(64px, 18vw, 96px);
  min-height: 0;
  background: transparent;
}

/* The 1024px inspector is deliberately narrower than the full-screen preview.
   Keep the existing registry artwork proportional so metadata remains visible
   in the same panel instead of letting the badge dominate it. */
body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-sheet > span .wizon-file-type-icon--preview,
body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-unsupported > span .wizon-file-type-icon--preview {
  width: 64px;
  height: 77px;
  max-width: 100%;
  max-height: 100%;
}

body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-error p,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-sheet p,
body.chatgpt-reference-v1 .chatgpt-drive-live-preview.is-unsupported p {
  margin: 0;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
}

body.chatgpt-reference-v1 .chatgpt-drive-mobile-fab,
body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview {
  display: none;
}

/* Desktop full-screen preview reuses the authenticated in-page renderer instead of opening a
   new tab. The overlay exists only after an explicit inspector action, so the docked preview
   remains the default Finder workflow. */
@media (min-width: 901px) {
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview {
    position: fixed;
    inset: 0;
    z-index: 420;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    width: 100%;
    min-height: 100dvh;
    background: var(--cg-bg, var(--bg));
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-head {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr) 48px;
    align-items: center;
    min-height: 64px;
    padding: 8px 16px;
    border-bottom: 1px solid var(--cg-menu-border, var(--line));
    background: var(--cg-surface);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-head h2 {
    overflow: hidden;
    margin: 0;
    color: var(--cg-text);
    font-size: var(--ds-text-body-15);
    font-weight: var(--wds-font-weight-medium);
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-icon {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--chatgpt-route-radius-control);
    background: transparent;
    color: var(--cg-text);
    cursor: pointer;
  }

  @media (hover: hover) {
    body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-icon:hover {
      background: var(--cg-hover-soft);
    }
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage {
    min-height: 0;
    overflow: auto;
    padding: 24px clamp(24px, 5vw, 80px);
    background: var(--cg-hover-soft);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview {
    width: min(100%, 1180px);
    min-height: calc(100dvh - 190px);
    margin: 0 auto;
    border-radius: var(--chatgpt-route-radius-lg);
    box-shadow: var(--cg-shadow-float-lg);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview iframe,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview img,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview video {
    min-height: calc(100dvh - 190px);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions {
    display: flex;
    justify-content: center;
    gap: var(--chatgpt-route-gap-xs);
    padding: 10px 16px;
    border-top: 1px solid var(--cg-menu-border, var(--line));
    background: var(--cg-surface);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 112px;
    min-height: 40px;
    padding: 8px 14px;
    border: 1px solid var(--cg-menu-border, var(--line));
    border-radius: var(--chatgpt-route-radius-control);
    background: var(--cg-surface);
    color: var(--cg-text);
    font: inherit;
    font-size: var(--ds-text-caption-13);
    cursor: pointer;
  }

  @media (hover: hover) {
    body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions button:hover {
      background: var(--cg-hover-soft);
    }
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-icon:focus-visible,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions button:focus-visible {
    outline: 2px solid var(--cg-focus-visible-ring, var(--cg-focus-ring));
    outline-offset: 2px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions svg {
    width: 18px;
    height: 18px;
  }
}

@media (min-width: 901px) and (any-pointer: coarse) {
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions button {
    min-height: var(--wizon-ai-action-target-touch);
  }
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-dock {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  flex: 0 0 auto;
  gap: var(--chatgpt-route-gap-xs);
  min-height: calc(var(--wizon-ai-space-unit) * 16);
  margin-top: var(--chatgpt-route-gap-sm);
  padding: var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-sm);
  border: 1px solid var(--cg-menu-border, var(--line));
  border-radius: var(--chatgpt-route-radius-pill);
  background: var(--cg-surface, var(--bg));
  box-shadow: var(--cg-shadow-float-xs);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-dock[aria-busy="true"] {
  opacity: 0.72;
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-status {
  grid-column: 1 / -1;
  margin: 0;
  padding: 0 var(--chatgpt-route-gap-xs) var(--chatgpt-route-gap-2xs);
  color: var(--cg-danger-text, var(--cg-text));
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-input-wrap {
  display: flex;
  align-items: center;
  min-width: 0;
  min-height: calc(var(--wizon-ai-space-unit) * 10);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-input {
  width: 100%;
  min-width: 0;
  min-height: calc(var(--wizon-ai-space-unit) * 6.5);
  max-height: calc(var(--wizon-ai-space-unit) * 6.5);
  padding: 0;
  overflow: hidden;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--cg-text);
  box-shadow: none;
  font: inherit;
  font-size: var(--ds-text-body-16);
  line-height: calc(var(--wizon-ai-space-unit) * 6.5);
  resize: none;
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-input::placeholder {
  color: var(--cg-input-placeholder);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-input:focus,
body.chatgpt-reference-v1 .chatgpt-drive-chat-input:focus-visible {
  border: 0;
  outline: 0;
  box-shadow: none;
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-icon-button,
body.chatgpt-reference-v1 .chatgpt-drive-chat-submit {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: calc(var(--wizon-ai-space-unit) * 10);
  height: calc(var(--wizon-ai-space-unit) * 10);
  padding: 0;
  border: 0;
  border-radius: var(--chatgpt-route-radius-pill);
  background: transparent;
  color: var(--cg-text);
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-icon-button svg,
body.chatgpt-reference-v1 .chatgpt-drive-chat-submit svg {
  width: calc(var(--wizon-ai-space-unit) * 5);
  height: calc(var(--wizon-ai-space-unit) * 5);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-model {
  display: inline-flex;
  align-items: center;
  gap: var(--chatgpt-route-gap-2xs);
  min-height: calc(var(--wizon-ai-space-unit) * 10);
  padding: 0 var(--chatgpt-route-gap-sm);
  border: 0;
  border-radius: var(--chatgpt-route-radius-control);
  background: transparent;
  color: var(--cg-muted);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  white-space: nowrap;
  cursor: pointer;
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-model svg {
  width: calc(var(--wizon-ai-space-unit) * 4);
  height: calc(var(--wizon-ai-space-unit) * 4);
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-submit {
  background: var(--cg-send-bg);
  color: var(--cg-send-fg);
}

@media (hover: hover) {
  body.chatgpt-reference-v1 .chatgpt-drive-chat-icon-button:hover,
  body.chatgpt-reference-v1 .chatgpt-drive-chat-model:hover {
    background: var(--cg-hover-soft);
    color: var(--cg-text);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-chat-submit:hover {
    background: var(--cg-send-bg-hover, var(--cg-send-bg));
  }
}

body.chatgpt-reference-v1 .chatgpt-drive-chat-icon-button:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-chat-model:focus-visible,
body.chatgpt-reference-v1 .chatgpt-drive-chat-submit:focus-visible {
  outline: 2px solid var(--cg-focus-ring);
  outline-offset: 2px;
}

@media (min-width: 901px) and (max-width: 1200px) {
  /* Reuse the existing canonical medium-shell band for the compact inspector.
     The prior 1100px-only split violated the shared breakpoint ratchet and
     left 1101–1200px with less metadata room for no product reason. */
  body.chatgpt-reference-v1 .chatgpt-drive-inspector-preview {
    margin-bottom: var(--chatgpt-route-gap-sm);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-sheet,
  body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-unsupported {
    box-sizing: border-box;
    height: calc(var(--wizon-ai-space-unit) * 53);
    min-height: calc(var(--wizon-ai-space-unit) * 53);
    gap: var(--chatgpt-route-gap-2xs);
    padding: var(--chatgpt-route-gap-sm);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-sheet > span .wizon-file-type-icon--preview,
  body.chatgpt-reference-v1 .chatgpt-drive-inspector .chatgpt-drive-live-preview.is-unsupported > span .wizon-file-type-icon--preview {
    width: calc(var(--wizon-ai-space-unit) * 13);
    height: calc(var(--wizon-ai-space-unit) * 16);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-explorer {
    grid-template-columns: 180px minmax(496px, 1fr) minmax(250px, 280px);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--tree-closed {
    grid-template-columns: minmax(0, 1fr) minmax(260px, 292px);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--inspector-closed {
    grid-template-columns: 180px minmax(496px, 1fr);
  }
  body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--tree-closed.chatgpt-drive-explorer--inspector-closed {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Medium shells have less horizontal room than the desktop grid's 520px +
     292px minimum. Let the list track shrink while keeping a bounded inspector;
     otherwise the Explorer's overflow guard crops the inspector at 1024px. */
  body.chatgpt-reference-v1 .chatgpt-drive-inspector,
  body.chatgpt-reference-v1 .chatgpt-drive-inspector-body {
    min-width: 0;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-inspector-meta-row {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    justify-content: normal;
  }

  /* Preserve every desktop column while allowing the list to share the medium
     shell with the inspector. The wide desktop widths remain unchanged. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-head,
  body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
    grid-template-columns: 28px minmax(0, 1fr) 72px 96px 40px;
    gap: 6px;
    min-width: 0;
  }

  /* D2 shell-fit: this band keeps the hierarchy plus a >=496px list. The selection dock
     therefore has to reflow its complete command set inside the list instead of widening the
     scroll container; hiding the horizontal overflow is a backstop, not the primary layout. */
  body.chatgpt-reference-v1 .chatgpt-drive-columns-pane {
    overflow-x: hidden;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-selection-dock {
    min-width: 0;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-selection-dock .chatgpt-drive-bulk-bar {
    flex-wrap: wrap;
    inline-size: 100%;
    box-sizing: border-box;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-selection-dock .chatgpt-drive-bulk-bar-count {
    flex: 1 0 100%;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-selection-dock .chatgpt-drive-bulk-bar-spacer {
    display: none;
  }
}

@media (max-width: 900px) {
  html[data-portal-route="/drive"] #portalPage.chatgpt-route-page {
    --chatgpt-route-page-top: var(--chatgpt-route-page-mobile-top);
    --chatgpt-route-page-bottom: var(--chatgpt-route-page-mobile-bottom);
    height: auto;
    padding-inline: 0;
    overflow: visible;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-page {
    display: grid;
    height: auto;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead {
    padding: 10px 14px 12px;
    border-bottom: 1px solid var(--cg-menu-border, var(--line));
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead > .chatgpt-drive-breadcrumb {
    order: -1;
    margin: 0;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-page .chatgpt-route-search {
    width: 100%;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-page .chatgpt-route-search input {
    width: 100%;
    min-height: 48px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-filter-row {
    padding: 10px 14px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-explorer,
  body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--tree-closed,
  body.chatgpt-reference-v1 .chatgpt-drive-explorer.chatgpt-drive-explorer--inspector-closed {
    display: block;
    height: auto;
    min-height: 0;
    overflow: visible;
    border: 0;
    border-radius: 0;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-tree-pane,
  body.chatgpt-reference-v1 .chatgpt-drive-inspector,
  body.chatgpt-reference-v1 .chatgpt-drive-selection-dock,
  body.chatgpt-reference-v1 .chatgpt-drive-chat-dock {
    display: none;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns-pane {
    overflow: visible;
  }

  /* Keep the Miller scroller inside the mobile route: its own horizontal
     scrolling remains available without widening the page past 390px. */
  body.chatgpt-reference-v1 .chatgpt-drive-explorer--columns,
  body.chatgpt-reference-v1 .chatgpt-drive-explorer--columns .chatgpt-drive-columns-pane,
  body.chatgpt-reference-v1 .chatgpt-drive-explorer--columns .chatgpt-drive-miller {
    width: 100%;
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-explorer--columns .chatgpt-drive-columns-pane {
    overflow: hidden;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns-row {
    min-height: 72px;
    padding: 11px 14px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns-icon {
    width: 42px;
    height: 42px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns-icon svg {
    width: 20px;
    height: 20px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-filter-panel.chatgpt-drive-mobile-submenu {
    width: 100%;
    max-height: min(72vh, 620px);
    padding: 18px 16px calc(18px + var(--wizon-safe-bottom));
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-results {
    min-height: 58vh;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-results-head {
    min-height: 54px;
    padding: 9px 14px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-result {
    grid-template-columns: 20px minmax(0, 1fr);
    gap: 6px;
    padding: 11px 10px 10px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-result-main {
    grid-template-columns: 48px minmax(0, 1fr);
    gap: 10px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-result-side {
    display: flex;
    align-items: center;
    justify-content: space-between;
    grid-column: 2;
    padding-left: 58px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-search-result-side .chatgpt-route-action {
    min-height: 34px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-fab {
    position: fixed;
    right: calc(20px + var(--wizon-safe-right));
    bottom: calc(84px + var(--wizon-safe-bottom));
    z-index: 20;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border: 0;
    border-radius: var(--chatgpt-route-radius-pill);
    background: var(--cg-send-bg);
    color: var(--cg-send-fg);
    box-shadow: var(--cg-shadow-float-lg);
    cursor: pointer;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-fab svg {
    width: 24px;
    height: 24px;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview {
    position: fixed;
    inset: 0;
    z-index: 420;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr) auto;
    width: 100%;
    min-height: 100dvh;
    background: var(--cg-bg, var(--bg));
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-head {
    display: grid;
    grid-template-columns: 48px minmax(0, 1fr) 48px;
    align-items: center;
    min-height: 64px;
    padding: max(4px, var(--wizon-safe-top)) 8px 4px;
    border-bottom: 1px solid var(--cg-menu-border, var(--line));
    background: var(--cg-surface);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-head h2 {
    overflow: hidden;
    margin: 0;
    color: var(--cg-text);
    font-size: var(--ds-text-body-15);
    font-weight: var(--wds-font-weight-medium);
    text-align: center;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-icon {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: var(--chatgpt-route-radius-control);
    background: transparent;
    color: var(--cg-text);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage {
    min-height: 0;
    overflow: auto;
    display: grid;
    align-items: stretch;
    padding: clamp(16px, 5vw, 24px) 18px;
    background: var(--cg-hover-soft);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview {
    width: 100%;
    min-height: 0;
    height: 100%;
    margin: 0;
    border-radius: var(--chatgpt-route-radius-control);
    box-shadow: var(--cg-shadow-float-lg);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview iframe,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview img,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-stage .chatgpt-drive-live-preview video {
    width: 100%;
    min-height: 100%;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions {
    display: flex;
    justify-content: space-around;
    gap: 6px;
    padding: 10px 12px calc(10px + var(--wizon-safe-bottom));
    border-top: 1px solid var(--cg-menu-border, var(--line));
    background: var(--cg-surface);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions button {
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-width: 0;
    min-height: 52px;
    padding: 4px;
    border: 0;
    border-radius: var(--chatgpt-route-radius-control);
    background: transparent;
    color: var(--cg-text);
    font: inherit;
    font-size: var(--ds-text-caption-12);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-preview-actions svg {
    width: 20px;
    height: 20px;
  }
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-body {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: calc(var(--wizon-ai-space-unit) * 36);
    gap: var(--chatgpt-route-gap-xs);
    padding: var(--chatgpt-route-gap-sm);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-mobilemeta {
    display: none;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-columns-name-text:has(> .chatgpt-drive-columns-mobilemeta) > .chatgpt-drive-columns-subline {
    display: block;
  }
}

/* 20260812-drive-mobile-touch-qa: production QA at a CSS 390x844 viewport exposed three
   interaction gaps that geometry-only snapshots did not catch.

   1. In icon view the 44px document/folder artwork sits outside `.chatgpt-drive-row-open`, so
      tapping the most prominent part of a card does nothing. A transparent pseudo-element owned
      by the existing open button covers the card while the checkbox and context trigger retain
      their z-index:2 priority. This changes no markup, paint, selection, or menu wiring.
   2. Mobile breadcrumb buttons are visually compact (28px) but need a 44px vertical hit area.
      There is enough measured clearance above and below, so transparent hit slop preserves the
      approved compact header instead of making it 16px taller.
   3. Drive and row-action bottom-sheet items were 39.8px tall and directly adjacent, which means
      transparent slop would overlap the next command. Grow those visible rows to 44px instead. */
body.chatgpt-reference-v1 .chatgpt-drive-columns.is-grid-view .chatgpt-drive-row-open::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

@media (max-width: 900px) {
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead .chatgpt-drive-breadcrumb-item {
    position: relative;
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-stickyhead .chatgpt-drive-breadcrumb-item::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 100%;
    min-height: 44px;
    transform: translate(-50%, -50%);
  }

  body.chatgpt-reference-v1 .chatgpt-drive-mobile-menu .chatgpt-library-menu-item,
  body.chatgpt-reference-v1 .chatgpt-drive-mobile-submenu .chatgpt-library-menu-item,
  body.chatgpt-reference-v1 .chatgpt-drive-context-menu .chatgpt-library-menu-item {
    min-height: 44px;
  }
}

@media (prefers-reduced-motion: reduce) {
  body.chatgpt-reference-v1 .chatgpt-drive-tree-twist svg,
}
.wizon-file-type-icon {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
}

/* Generated-file cards use the same transparent SVG artwork as attachments. Keep the variant
   explicitly registered in CSS so it cannot silently fall back to an unstyled wrapper contract. */
.wizon-file-type-icon--attachment {
  object-position: center;
}

.chatgpt-drive-columns-icon .wizon-file-type-icon,
.chatgpt-library-file-icon .wizon-file-type-icon,
.chatgpt-library-move-entry-icon .wizon-file-type-icon,
.generated-file-icon .wizon-file-type-icon {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
}

/* ═══════════════════════════════════════════════════════════════════════════
   CPQ 견적 위젯 대시보드 (doc 400 §13.4 — 오너 승인 목업 v3, 2026-08-15)
   v2 반려 사유: 「위젯 틀은 맞는데 안이 텍스트라 문서로 읽힌다」. Mobbin 재조사에서
   뽑은 규칙 하나를 전면 적용했다 — **모든 카드가 안에 차트를 품는다**
   (Apple Health 행별 인라인 막대 · Chase 당월 강조 월별 막대 · Glassdoor/Commons
   도넛+값·비중 범례 · Airwallex 커넥터 타임라인 · Remote HR 승인 카드).
   깊이 = 틴트 «캔버스» 위에 그림자로 떠 있는 카드. v2 의 흰 배경+헤어라인을 버렸다.
   위계 = 히어로 title-xl ↔ 캡션 label-s 의 크기 대비(웨이트는 팔레트 상한 600 고정).
   ═══════════════════════════════════════════════════════════════════════════ */
.cpq-dash {
  --cpqd-canvas: var(--wds-color-surface-muted);
  --cpqd-card: var(--wds-color-surface);
  --cpqd-ink: var(--wds-color-text);
  --cpqd-ink-2: var(--wds-color-text-muted);
  --cpqd-muted: var(--wds-color-text-subtle);
  --cpqd-hair: var(--wds-color-border-subtle);
  --cpqd-accent: var(--wds-color-primary-text);
  --cpqd-hw-fg: var(--wds-color-info-text);
  --cpqd-hw-bg: var(--wds-color-info-container);
  --cpqd-sw-fg: var(--wds-color-tag-teal-text);
  --cpqd-sw-bg: var(--wds-color-tag-teal-bg);
  --cpqd-ok-fg: var(--wds-color-success-text);
  --cpqd-ok-bg: var(--wds-color-success-container);
  --cpqd-gone-fg: var(--wds-badge-neutral-fg);
  --cpqd-gone-bg: var(--wds-badge-neutral-bg);
  --cpqd-sup-fg: var(--wds-color-tag-violet-text);
  --cpqd-sup-bg: var(--wds-color-tag-violet-bg);
  --cpqd-pend-fg: var(--wds-color-warning-text);
  --cpqd-pend-bg: var(--wds-color-warning-container);
  --cpqd-up: var(--wds-color-error-text);
  --cpqd-down: var(--wds-color-success-text);
  --cpqd-shadow: var(--ds-shadow-xs);
  /* 막대의 «바닥»색. ★border-subtle 을 쓰면 다크에서 카드 배경과 대비 1.00 이라
     추이 막대가 통째로 사라진다(2026-08-15 렌더 실측) — 차트가 「그 달엔 없었다」고
     거짓말하는 상태다. border-strong 이 라이트 1.47 / 다크 1.94 로 뮤트를 유지하면서
     보이는 유일한 값이었다. 후보 절반(divider·surface-sunken·neutral-*)은 아예 없는
     토큰이라 transparent 로 계산됐다 — 이름이 그럴듯하다고 쓰지 말 것. */
  --cpqd-bar: var(--wds-color-border-strong);
  display: block; background: var(--cpqd-canvas); border-radius: var(--wizon-ai-radius-sheet);
  padding: 12px; color: var(--cpqd-ink); font-size: var(--wds-font-size-body-s); line-height: 1.45;
  container-type: inline-size;
}
.cpq-dash .cpq-dash-widget { background: var(--cpqd-card); border-radius: var(--wizon-ai-radius-popover);
  box-shadow: var(--cpqd-shadow); margin-bottom: 12px; overflow: hidden; }
.cpq-dash-grid { display: grid; grid-template-columns: 1.55fr 1fr; gap: 12px; }
.cpq-dash-grid .cpq-dash-widget { margin-bottom: 12px; }
@container (max-width: 560px) { .cpq-dash-grid { grid-template-columns: 1fr; } }
@media (max-width: 520px) { .cpq-dash-grid { grid-template-columns: 1fr; } }

.cpq-dash-w-head { display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px 0; gap: 10px; }
.cpq-dash-w-label { font-size: var(--wds-font-size-caption); font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; }
.cpq-dash-w-label::before { content: ""; width: 7px; height: 7px; border-radius: var(--wizon-ai-radius-pill);
  background: currentColor; display: inline-block; }
.cpq-dash-w-label--main { color: var(--cpqd-hw-fg); }
.cpq-dash-w-label--sup { color: var(--cpqd-sup-fg); }
.cpq-dash-w-label--pend { color: var(--cpqd-pend-fg); }
.cpq-dash-w-label--cat { color: var(--cpqd-ok-fg); }
.cpq-dash-w-more { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); }
.cpq-dash-w-more--link { background: none; border: 0; color: var(--cpqd-accent); cursor: pointer;
  font-weight: 600; padding: 0; font-family: inherit; }

/* ── 히어로: 큰 수 + 델타 배지 + 6개월 추이 막대 ── */
.cpq-dash-hero { padding: 8px 16px 16px; }
.cpq-dash-big { font-size: var(--wds-font-size-h1); font-weight: 600; letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums; line-height: 1.1; }
.cpq-dash-unit { font-size: var(--wds-font-size-body-s); font-weight: 600; color: var(--cpqd-ink-2);
  margin-left: 4px; letter-spacing: 0; }
.cpq-dash-delta { display: inline-flex; align-items: center; gap: 4px; font-size: var(--wds-font-size-label-s);
  font-weight: 600; padding: 3px 8px; border-radius: var(--wizon-ai-radius-pill); margin-left: 8px;
  vertical-align: middle; }
.cpq-dash-delta--up { background: var(--cpqd-ok-bg); color: var(--cpqd-ok-fg); }
.cpq-dash-delta--down { background: var(--cpqd-gone-bg); color: var(--cpqd-gone-fg); }
.cpq-dash-big-sub { font-size: var(--wds-font-size-caption); color: var(--cpqd-ink-2); margin-top: 6px; }
.cpq-dash-big-sub em { font-style: normal; color: var(--cpqd-pend-fg); font-weight: 600; }
.cpq-dash-spark { margin-top: 14px; }
.cpq-dash-spark-svg { display: block; width: 100%; height: 46px; }
.cpq-dash-sbar { fill: var(--cpqd-bar); }
.cpq-dash-sbar-on { fill: var(--cpqd-hw-fg); }
.cpq-dash-spark-labels { display: flex; margin-top: 5px; }
.cpq-dash-sb { flex: 1; text-align: center; font-size: var(--wds-font-size-label-s);
  color: var(--cpqd-muted); text-decoration: none; font-variant-numeric: tabular-nums; }
.cpq-dash-sb-on { color: var(--cpqd-ink); font-weight: 600; }

/* ── 상태 구성 도넛 + 범례 ── */
.cpq-dash-donutwrap { display: flex; align-items: center; gap: 14px; padding: 10px 16px 16px; }
.cpq-dash-donut { position: relative; width: 104px; height: 104px; flex: 0 0 104px; display: block; }
.cpq-dash-donut svg { transform: rotate(-90deg); }
.cpq-dash-arc { fill: none; stroke-width: 13; cursor: pointer;
  transition: stroke-width 180ms ease, opacity 180ms ease; }
.cpq-dash-arc:hover { stroke-width: 16; }
.cpq-dash-arc--ok { stroke: var(--cpqd-ok-fg); }
.cpq-dash-arc--sup { stroke: var(--cpqd-sup-fg); }
.cpq-dash-arc--gone { stroke: var(--cpqd-gone-fg); }
.cpq-dash-dim { opacity: 0.3; }
.cpq-dash-donut-mid { position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; pointer-events: none; }
.cpq-dash-donut-mid b { font-size: var(--wds-font-size-h2); font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.cpq-dash-donut-mid u { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted);
  text-decoration: none; margin-top: 1px; }
.cpq-dash-legend { flex: 1; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cpq-dash-lg { display: flex; align-items: center; gap: 8px; font-size: var(--wds-font-size-caption);
  cursor: pointer; border: 0; background: none; font-family: inherit; color: inherit;
  border-radius: var(--wizon-ai-radius-control); padding: 4px 6px; text-align: left;
  transition: background 150ms ease, opacity 180ms ease; }
.cpq-dash-lg:hover { background: var(--cpqd-canvas); }
.cpq-dash-lg span { flex: 1; color: var(--cpqd-ink-2); }
.cpq-dash-lg b { font-weight: 600; font-variant-numeric: tabular-nums; }
.cpq-dash-lg em { font-style: normal; color: var(--cpqd-muted); font-size: var(--wds-font-size-label-s);
  margin-left: 5px; font-variant-numeric: tabular-nums; }
.cpq-dash-sw { width: 8px; height: 8px; border-radius: var(--wizon-ai-radius-control); flex: 0 0 8px; text-decoration: none;
  display: inline-block; }
.cpq-dash-sw--ok { background: var(--cpqd-ok-fg); }
.cpq-dash-sw--sup { background: var(--cpqd-sup-fg); }
.cpq-dash-sw--gone { background: var(--cpqd-gone-fg); }
.cpq-dash-sw--p1 { background: var(--cpqd-hw-fg); }
.cpq-dash-sw--p2 { background: var(--cpqd-sup-fg); }
.cpq-dash-sw--p3 { background: var(--cpqd-ok-fg); }
.cpq-dash-sw--p4 { background: var(--cpqd-bar); }

/* ── 세그먼트 ── */
.cpq-dash-seg { display: flex; gap: 5px; padding: 4px; background: var(--cpqd-card);
  border-radius: var(--wizon-ai-radius-pill); box-shadow: var(--cpqd-shadow);
  margin-bottom: 12px; width: fit-content; }
.cpq-dash-seg button { border: 0; background: none; font-family: inherit;
  font-size: var(--wds-font-size-caption); font-weight: 600; color: var(--cpqd-ink-2);
  padding: 6px 13px; border-radius: var(--wizon-ai-radius-pill); cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; transition: background 180ms ease, color 180ms ease; }
.cpq-dash-seg button:hover { color: var(--cpqd-ink); }
.cpq-dash-seg .cpq-dash-seg-on { background: var(--cpqd-ink); color: var(--cpqd-card); }
.cpq-dash-seg-n { font-size: var(--wds-font-size-label-s); opacity: 0.65; font-variant-numeric: tabular-nums; }

/* ── 견적 행 (금액 인라인 막대) ── */
.cpq-dash-rows { padding: 8px; }
/* 행은 button 이다(키보드 접근). 브라우저 기본 스타일을 지우고 초점 링을 명시한다 —
   outline: none 만 두면 키보드 사용자가 «어디에 있는지» 알 수 없다. */
.cpq-dash-row { display: grid; grid-template-columns: 34px 1fr auto; gap: 11px; align-items: center;
  padding: 9px 8px; border-radius: var(--wizon-ai-radius-menu-row); cursor: pointer;
  transition: background 150ms ease; width: 100%; border: 0; background: none;
  font: inherit; color: inherit; text-align: left; }
.cpq-dash-row:hover, .cpq-dash-row--open { background: var(--cpqd-canvas); }
.cpq-dash-row:focus-visible { outline: 2px solid var(--cpqd-accent); outline-offset: 2px; }
.cpq-dash-row[aria-disabled="true"] { cursor: default; }
.cpq-dash-icon { width: 34px; height: 34px; border-radius: var(--wizon-ai-radius-menu-row);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--wds-font-size-label-s); font-weight: 600; letter-spacing: 0.02em; }
.cpq-dash-icon--hw { background: var(--cpqd-hw-bg); color: var(--cpqd-hw-fg); }
.cpq-dash-icon--sw { background: var(--cpqd-sw-bg); color: var(--cpqd-sw-fg); }
.cpq-dash-icon--cat { background: var(--cpqd-pend-bg); color: var(--cpqd-pend-fg); }
.cpq-dash-icon--lab { background: var(--cpqd-ok-bg); color: var(--cpqd-ok-fg); }
.cpq-dash-mid { min-width: 0; display: block; }
.cpq-dash-no { font-size: var(--wds-font-size-caption); font-weight: 600; letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums; display: block; }
.cpq-dash-sub { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); margin-top: 1px;
  display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cpq-dash-amtbar { display: block; height: 4px; margin-top: 5px; max-width: 230px; width: 100%; }
.cpq-dash-amtbar-track { fill: var(--cpqd-bar); }
.cpq-dash-amtbar-fill { fill: var(--cpqd-hw-fg); }
.cpq-dash-row[data-cpq-status="gone"] .cpq-dash-amtbar-fill { fill: var(--cpqd-gone-fg); }
.cpq-dash-row[data-cpq-status="sup"] .cpq-dash-amtbar-fill { fill: var(--cpqd-sup-fg); }
.cpq-dash-end { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.cpq-dash-amt { font-size: var(--wds-font-size-body-s); font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.cpq-dash-amt--unk { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); font-weight: 400; }
.cpq-dash-pill { font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 2px 8px;
  border-radius: var(--wizon-ai-radius-pill); display: inline-flex; align-items: center; gap: 4px; }
.cpq-dash-pill--ok { background: var(--cpqd-ok-bg); color: var(--cpqd-ok-fg); }
.cpq-dash-pill--gone { background: var(--cpqd-gone-bg); color: var(--cpqd-gone-fg); }
.cpq-dash-pill--sup { background: var(--cpqd-sup-bg); color: var(--cpqd-sup-fg); }
.cpq-dash-trunc { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted);
  padding: 8px 16px 12px; border-top: 1px solid var(--cpqd-hair); margin: 4px 8px 0; }
.cpq-dash-mini-empty { font-size: var(--wds-font-size-caption); color: var(--cpqd-muted); padding: 14px 8px; }

/* ── 확장 이력: 세로 커넥터 타임라인 ── */
.cpq-dash-expand { display: none; }
.cpq-dash-row--open + .cpq-dash-expand { display: block; }
.cpq-dash-ex-inner { background: var(--cpqd-canvas); border-radius: var(--wizon-ai-radius-popover);
  padding: 13px 14px; margin: 2px 0 8px; }
.cpq-dash-ex-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.cpq-dash-cap { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqd-muted);
  letter-spacing: 0.04em; }
.cpq-dash-pin { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted);
  background: var(--cpqd-card); padding: 3px 8px; border-radius: var(--wizon-ai-radius-pill); }
.cpq-dash-tl { list-style: none; margin: 0; padding: 0 0 0 18px; position: relative; }
.cpq-dash-tl::before { content: ""; position: absolute; left: 4px; top: 6px; bottom: 10px; width: 2px;
  background: var(--cpqd-hair); border-radius: var(--wizon-ai-radius-pill); }
.cpq-dash-tl li { position: relative; padding-bottom: 11px; }
.cpq-dash-tl li:last-child { padding-bottom: 2px; }
.cpq-dash-dot { position: absolute; left: -18px; top: 4px; width: 10px; height: 10px;
  border-radius: var(--wizon-ai-radius-pill); background: var(--cpqd-card);
  border: 2px solid var(--cpqd-gone-fg); }
.cpq-dash-tl-ok .cpq-dash-dot { border-color: var(--cpqd-ok-fg); }
.cpq-dash-tl-sup .cpq-dash-dot { border-color: var(--cpqd-sup-fg); }
.cpq-dash-tl-t1 { font-size: var(--wds-font-size-caption); font-weight: 600; }
.cpq-dash-tl-t2 { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); margin-top: 1px;
  font-variant-numeric: tabular-nums; }
.cpq-dash-note { display: inline-block; font-size: var(--wds-font-size-label-s); color: var(--cpqd-ink-2);
  background: var(--cpqd-card); padding: 3px 9px; border-radius: var(--wizon-ai-radius-control); margin-top: 5px; }
.cpq-dash-callout { display: flex; align-items: center; justify-content: space-between; width: 100%;
  margin-top: 10px; background: var(--cpqd-sup-bg); border: 0; border-radius: var(--wizon-ai-radius-control);
  padding: 9px 12px; font-family: inherit; font-size: var(--wds-font-size-caption); font-weight: 600;
  color: var(--cpqd-sup-fg); cursor: pointer; }

/* ── 제안: 변화폭 트랙 ── */
.cpq-dash-sec-cap { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqd-muted);
  letter-spacing: 0.04em; padding: 10px 16px 2px; }
.cpq-dash-prow { display: grid; grid-template-columns: 34px 1fr auto; gap: 11px; align-items: center;
  padding: 10px 16px; }
.cpq-dash-deltabar { display: flex; align-items: center; gap: 7px; margin-top: 6px; max-width: 250px; }
.cpq-dash-track { flex: 1; height: 6px; display: block; }
.cpq-dash-track-bed { fill: var(--cpqd-bar); }
.cpq-dash-track-base { fill: var(--cpqd-muted); }
.cpq-dash-track--up { fill: var(--cpqd-pend-fg); }
.cpq-dash-track--down { fill: var(--cpqd-down); }
.cpq-dash-pct { font-style: normal; font-size: var(--wds-font-size-label-s); font-weight: 600;
  font-variant-numeric: tabular-nums; }
.cpq-dash-pct--up { color: var(--cpqd-pend-fg); }
.cpq-dash-pct--down { color: var(--cpqd-down); }
.cpq-dash-money { font-size: var(--wds-font-size-caption); font-variant-numeric: tabular-nums;
  color: var(--cpqd-muted); white-space: nowrap; }
.cpq-dash-money b { color: var(--cpqd-ink); font-weight: 600; }
.cpq-dash-acts { display: inline-flex; gap: 6px; margin-top: 6px; }
.cpq-dash-b-ok, .cpq-dash-b-no { border-radius: var(--wizon-ai-radius-pill);
  font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 6px 13px; cursor: pointer;
  border: 0; font-family: inherit; }
.cpq-dash-b-ok { background: var(--cpqd-ink); color: var(--cpqd-card); }
.cpq-dash-b-no { background: var(--cpqd-canvas); color: var(--cpqd-ink-2); }
.cpq-dash-done { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); }

/* ── 승인/반려 낙관적 UI: 처리 중 · 롤백 사유 (§13.4 위 얹는 개선) ── */
.cpq-dash-b-ok:disabled, .cpq-dash-b-no:disabled { cursor: default; opacity: .7; }
.cpq-dash-b-spin { display: inline-block; width: 9px; height: 9px; margin-right: 5px;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor; border-radius: var(--wizon-ai-radius-pill);
  vertical-align: -1px; animation: cpq-dash-b-spin 700ms linear infinite; }
@keyframes cpq-dash-b-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .cpq-dash-b-spin { animation: none; }
}
.cpq-dash-fail-reason { display: block; margin-top: 6px; max-width: 250px;
  font-size: var(--wds-font-size-label-s); color: var(--wds-color-error-text); text-align: right; }

/* ── 카탈로그: 비중 스택바 ── */
.cpq-dash-cat-body { padding: 8px 16px 16px; }
.cpq-dash-cat-num { display: flex; align-items: baseline; gap: 6px; }
.cpq-dash-cat-n { font-size: var(--wds-font-size-h2); font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.cpq-dash-cat-s { font-size: var(--wds-font-size-label-s); color: var(--cpqd-muted); }
.cpq-dash-stack { display: block; width: 100%; height: 9px; margin: 10px 0 9px; }
.cpq-dash-stack-1 { fill: var(--cpqd-hw-fg); }
.cpq-dash-stack-2 { fill: var(--cpqd-sup-fg); }
.cpq-dash-stack-3 { fill: var(--cpqd-ok-fg); }
.cpq-dash-stack-4 { fill: var(--cpqd-bar); }

/* §11.29 수주율 카드 — 분할 비중 바. 결정(수주|실주)은 채움, 미결은 윤곽선만:
   분모(won+lost) 밖이라는 사실을 채움 여부가 말한다. */
.cpq-dash-w-label--win { color: var(--cpqd-ok-fg); }
.cpq-dash-win-body { padding: 2px 2px 0; }
.cpq-dash-winbar { display: block; width: 100%; height: 12px; margin: 10px 0 8px; }
.cpq-dash-winbar-won { fill: var(--cpqd-ok-fg); }
.cpq-dash-winbar-lost { fill: var(--cpqd-gone-fg); }
.cpq-dash-winbar-open { fill: none; stroke: var(--cpqd-hair); stroke-width: 1; }
.cpq-dash-win-legend { display: flex; gap: 14px; flex-wrap: wrap; }
.cpq-dash-win-lg { display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--wds-font-size-caption); color: var(--cpqd-ink-2); }
.cpq-dash-win-lg b { color: var(--cpqd-ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.cpq-dash-win-lg .cpq-dash-sw--open { background: transparent; border: 1px solid var(--cpqd-hair); }
.cpq-dash-sw--won { background: var(--cpqd-ok-fg); }
.cpq-dash-sw--lost { background: var(--cpqd-gone-fg); }
.cpq-dash-cat-chips { display: flex; gap: 10px 16px; flex-wrap: wrap; }
.cpq-dash-cat-chip { display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--wds-font-size-label-s); color: var(--cpqd-ink-2); }

/* --- Composer paste-preview (Phase 1): 붙여넣기 압축 칩 + 원문 다이얼로그 ---- */
.composer-link-preview-thumb {
  width: 44px;
  height: 26px;
  border-radius: var(--ds-radius-xs);
  object-fit: cover;
  flex-shrink: 0;
}

.composer-link-preview-copy {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.composer-paste-dialog-content {
  margin: 0;
  padding: 12px 14px;
  max-height: min(48vh, 420px);
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: inherit;
  font-size: var(--wds-font-size-body-2);
  line-height: 1.5;
  color: var(--wizon-ai-text-primary);
  background: var(--wizon-ai-hover-soft-bg);
  border: 1px solid var(--wizon-ai-composer-border);
  border-radius: var(--wizon-ai-menu-radius);
}

.composer-paste-dialog-foot {
  display: flex;
  justify-content: flex-end;
  padding-top: 10px;
}

.composer-paste-dialog-restore {
  border: 1px solid var(--wizon-ai-composer-border);
  border-radius: var(--wizon-ai-radius-pill);
  padding: 6px 14px;
  background: transparent;
  color: var(--wizon-ai-text-primary);
  cursor: pointer;
}

.composer-paste-dialog-restore:hover {
  background: var(--wizon-ai-hover-bg);
}

.composer-paste-dialog-restore:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

/* --- Phase 3: 붙여넣기 구조 카드 ------------------------------------------ */
/* 구조 차트 색. 셸 토큰(shared/wds)은 이 트랙 범위 밖이라 여기서 파생시킨다 —
   전부 기존 텍스트/표면 토큰에서 끌어와 새 색을 발명하지 않는다. */
.composer-structure-card {
  --wizon-ai-structure-prose: var(--wizon-ai-text-primary);
  --wizon-ai-structure-code: var(--wizon-ai-text-muted);
  --wizon-ai-structure-table: var(--wizon-ai-text-muted-2);
  --wizon-ai-structure-list: var(--wizon-ai-hover-bg);
  /* ★--wds-color-warning-fg 는 «존재하지 않는» 토큰이었다. 폴백이 조용히 먹어
     경고색 = 본문 검정이 되고, 컨텍스트 초과가 시각적으로 경고가 아니었다.
     정본은 --ds-feedback-warn-fg (semantic.css, 라이트 amber-700 / 다크 amber-400).
     폴백을 두지 않는다 — 폴백이 죽은 토큰을 숨긴다. */
  --wizon-ai-structure-warn: var(--ds-feedback-warn-fg);
  flex: 0 0 auto;
  width: min(420px, 100%);
  background: var(--wizon-ai-surface);
  border: 1px solid var(--wizon-ai-composer-border);
  border-radius: var(--wizon-ai-menu-radius);
  overflow: hidden;
  text-align: left;
}

.composer-structure-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 13px;
}

.composer-structure-icon {
  width: 30px;
  height: 30px;
  border-radius: var(--ds-radius-xs);
  background: var(--wizon-ai-hover-soft-bg);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--wizon-ai-text-muted);
}

.composer-structure-title {
  flex: 1;
  min-width: 0;
}

.composer-structure-title strong {
  display: block;
  font-size: var(--wds-font-size-body-2);
  font-weight: 600;
  color: var(--wizon-ai-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.composer-structure-meta {
  display: block;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
}

.composer-structure-actions {
  display: flex;
  gap: 2px;
  flex-shrink: 0;
}

.composer-structure-icon-button {
  width: 26px;
  height: 26px;
  border: 0;
  background: transparent;
  border-radius: var(--ds-radius-xs);
  color: var(--wizon-ai-text-muted);
  cursor: pointer;
  display: grid;
  place-items: center;
}

.composer-structure-icon-button:hover {
  background: var(--wizon-ai-hover-bg);
  color: var(--wizon-ai-text-primary);
}

.composer-structure-icon-button:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

.composer-structure-section {
  padding: 12px 13px;
  border-top: 1px solid var(--wizon-ai-composer-border);
}

.composer-structure-label {
  margin: 0 0 8px;
  font-size: var(--wds-font-size-label-s);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wizon-ai-text-muted-2);
}

.composer-structure-composition-bar {
  display: block;
  width: 100%;
  height: 8px;
}

.composer-structure-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 8px;
}

.composer-structure-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
}

.composer-structure-legend-item b {
  color: var(--wizon-ai-text-primary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.composer-structure-swatch {
  width: 8px;
  height: 8px;
  border-radius: var(--ds-radius-2xs);
  flex-shrink: 0;
}

.composer-structure-swatch[data-kind="prose"] { background: var(--wizon-ai-structure-prose); }
.composer-structure-swatch[data-kind="code"] { background: var(--wizon-ai-structure-code); }
.composer-structure-swatch[data-kind="table"] { background: var(--wizon-ai-structure-table); }
.composer-structure-swatch[data-kind="list"] { background: var(--wizon-ai-structure-list); }

.composer-structure-row {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr) 88px 46px;
  align-items: center;
  gap: 8px;
  padding: 5px 4px;
  border-radius: var(--ds-radius-2xs);
  cursor: pointer;
  /* 브라우저 기본 삼각형 마커를 지운다 — 남기면 캐럿이 둘로 보인다. */
  list-style: none;
}

.composer-structure-row::-webkit-details-marker {
  display: none;
}

.composer-structure-row:hover {
  background: var(--wizon-ai-hover-soft-bg);
}

.composer-structure-row:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

.composer-structure-caret {
  color: var(--wizon-ai-text-muted-2);
  display: grid;
  place-items: center;
  transition: transform var(--wds-duration-fast, 150ms) ease;
}

.composer-structure-row-group[open] > .composer-structure-row .composer-structure-caret {
  transform: rotate(90deg);
}

.composer-structure-row-body {
  margin: 0;
  padding: 2px 4px 8px 22px;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
  overflow-wrap: anywhere;
}

.composer-structure-row-name {
  font-size: var(--wds-font-size-body-2);
  color: var(--wizon-ai-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.composer-structure-section-bar {
  display: block;
  width: 88px;
  height: 6px;
}

.composer-structure-row-count {
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.composer-structure-more {
  margin: 6px 0 0;
  padding-left: 22px;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
}

.composer-structure-budget-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.composer-structure-budget-key,
.composer-structure-budget-value {
  font-size: var(--wds-font-size-label-s);
  white-space: nowrap;
}

.composer-structure-budget-key { color: var(--wizon-ai-text-muted); }

.composer-structure-budget-value {
  color: var(--wizon-ai-text-primary);
  font-variant-numeric: tabular-nums;
}

.composer-structure-budget-bar {
  display: block;
  width: 100%;
  height: 6px;
}

.composer-structure-card[data-over-budget="true"] .composer-structure-budget-value {
  color: var(--wizon-ai-structure-warn);
  font-weight: 600;
}

.composer-structure-warning {
  margin: 8px 0 0;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-structure-warn);
}

.composer-structure-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 11px 13px 12px;
  border-top: 1px solid var(--wizon-ai-composer-border);
}

.composer-structure-chip {
  font-size: var(--wds-font-size-label-s);
  padding: 5px 11px;
  border-radius: var(--wizon-ai-radius-pill);
  border: 1px solid var(--wizon-ai-composer-border);
  background: transparent;
  color: var(--wizon-ai-text-secondary);
  cursor: pointer;
}

.composer-structure-chip:hover { background: var(--wizon-ai-hover-bg); }

.composer-structure-chip:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

.composer-structure-chip.is-primary {
  background: var(--wizon-ai-text-primary);
  color: var(--wizon-ai-surface);
  border-color: var(--wizon-ai-text-primary);
}

/* 모바일: 88px 인라인 바가 들어갈 폭이 없다 — 단어 수 숫자만으로 같은 판단이 된다. */
@media (max-width: 520px) {
  .composer-structure-card {
    width: 100%;
  }

  .composer-structure-section-bar {
    display: none;
  }

  .composer-structure-row {
    grid-template-columns: 14px minmax(0, 1fr) 46px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .composer-structure-caret {
    transition: none;
  }
}

/* --- Phase 4: 전송 후 버블 압축 + [§N] 앵커 -------------------------------- */
/* 붙여넣은 벽이 대화에 그대로 남지 않게 카드로 접는다. 새 색을 발명하지 않고
   기존 텍스트/표면 토큰만 쓴다. */
.composer-sent-paste-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.composer-sent-paste-typed {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.composer-sent-paste-card {
  border: 1px solid var(--wizon-ai-composer-border);
  border-radius: var(--ds-radius-sm);
  background: var(--wizon-ai-surface);
  overflow: hidden;
}

.composer-sent-paste-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
}

.composer-sent-paste-icon {
  width: 26px;
  height: 26px;
  border-radius: var(--ds-radius-xs);
  background: var(--wizon-ai-hover-soft-bg);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  color: var(--wizon-ai-text-muted);
}

.composer-sent-paste-title {
  min-width: 0;
}

.composer-sent-paste-title strong {
  display: block;
  font-size: var(--wds-font-size-body-2);
  font-weight: 600;
  color: var(--wizon-ai-text-primary);
}

.composer-sent-paste-meta {
  display: block;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
  font-variant-numeric: tabular-nums;
}

.composer-sent-paste-tabs {
  display: flex;
  gap: 14px;
  padding: 0 12px;
  border-top: 1px solid var(--wizon-ai-composer-border);
}

.composer-sent-paste-tab {
  border: 0;
  background: transparent;
  padding: 8px 0;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
  cursor: pointer;
}

.composer-sent-paste-tab:hover {
  color: var(--wizon-ai-text-primary);
}

.composer-sent-paste-tab:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

.composer-sent-paste-tab.is-active {
  color: var(--wizon-ai-text-primary);
  font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--wizon-ai-text-primary);
}

.composer-sent-paste-outline {
  margin: 0;
  padding: 8px 12px 12px;
  list-style: none;
  border-top: 1px solid var(--wizon-ai-composer-border);
}

.composer-sent-paste-row {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) 46px;
  align-items: center;
  gap: 8px;
  padding: 4px 4px;
  border-radius: var(--ds-radius-2xs);
  scroll-margin-block: 80px;
}

.composer-sent-paste-row[data-sent-highlight="true"] {
  background: var(--wizon-ai-hover-bg);
}

.composer-sent-paste-row-index {
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted-2);
  font-variant-numeric: tabular-nums;
}

.composer-sent-paste-row-name {
  font-size: var(--wds-font-size-body-2);
  color: var(--wizon-ai-text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.composer-sent-paste-row-count {
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-muted);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.composer-sent-paste-source {
  margin: 0;
  padding: 10px 12px 12px;
  max-height: 260px;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font: inherit;
  font-size: var(--wds-font-size-label-s);
  color: var(--wizon-ai-text-secondary);
  border-top: 1px solid var(--wizon-ai-composer-border);
}

/* 답변 속 출처 앵커. 인라인 텍스트 흐름을 깨지 않게 baseline 에 얹는다. */
.composer-sent-anchor {
  display: inline;
  border: 1px solid var(--wizon-ai-composer-border);
  border-radius: var(--wizon-ai-radius-pill);
  background: var(--wizon-ai-hover-soft-bg);
  color: var(--wizon-ai-text-muted);
  font-size: var(--wds-font-size-label-s);
  padding: 1px 7px;
  margin: 0 2px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}

.composer-sent-anchor:hover {
  background: var(--wizon-ai-hover-bg);
  color: var(--wizon-ai-text-primary);
}

.composer-sent-anchor:focus-visible {
  outline: none;
  box-shadow: var(--wizon-ai-focus-visible-ring);
}

@media (max-width: 520px) {
  .composer-sent-paste-row {
    grid-template-columns: 26px minmax(0, 1fr) 40px;
  }

  .composer-sent-paste-source {
    max-height: 200px;
  }
}

/* ── 유튜브 답변 카드 (doc 482 혼합안 1단계) ─────────────────────────────
   raw 색 0 — 전부 실존 토큰. 축 강조는 --cg-danger-fg 재사용(정본에 붉은 강조가
   그것뿐이다). 새 토큰·새 리터럴을 만들면 anti-drift 래칫이 빨개진다. */
/* 2026-08-27 공용 위젯 카드 셸로 이관(차별화 축① 잔여 슬라이스).
   테두리·배경은 이제 .wiz-card 가 소유한다 — 실측으로 확인한 완전 동일 값이라
   지웠다: border-color 는 --cg-menu-border(→--wizon-ai-popover-border, #e3e3e3)가
   셸의 --wiz-card-hairline 과 같은 정의, background 는 --cg-surface(→--wizon-ai-
   surface, #fff)가 셸의 --wiz-card-surface 와 같은 정의다(둘 다 라이트/다크 전부
   일치 — 별칭 체인이 같은 원색을 가리킨다). 그림자는 원래도 없었고 compact
   밀도의 --wiz-card-elevation: none 이 그대로다.
   ★두 줄은 «정당하게 남는» 위젯 보정이다(셸은 기본값, 위젯이 이긴다):
     - border-radius: 셸의 corner(comfortable 16px / compact 10px) 어느 쪽도
       기존 18px과 다르다. 화면을 그대로 두려고 명시로 고정했다.
     - margin-top: 셸은 카드 자신에 --wiz-card-detach(16px) 상단 여백을 준다.
       이 카드는 지금까지 자기 여백이 0이었고, 위 간격은 항상 앞 문단의
       `.assistant .message-body > p { margin-bottom: var(--ds-space-5) }`가
       내고 있었다(정적 스캔 확인 — 이 시트에 .wizon-yt-card 자신의 margin-top
       선언이 없었다). 셸의 detach를 그대로 받으면 문단 하단 여백 위에 16px가
       «더해져» 간격이 실측 20px→36px로 벌어진다(로컬 하네스 getComputedStyle
       대조, 토큰 체인 전부 로드 상태). 0으로 고정해 지금 간격을 지킨다. */
.wizon-yt-card { border-radius: var(--ds-radius-lg); margin-top: 0;
  padding: 16px; display: flex; flex-direction: column; gap: 12px; max-width: 560px; }
.wizon-yt-meta { display: flex; gap: 12px; align-items: flex-start; }
.wizon-yt-meta h3 { margin: 0; font-size: var(--wds-font-size-body-2); line-height: 1.35; }
.wizon-yt-meta h3 a { color: inherit; text-decoration: none; }
.wizon-yt-meta p { margin: 2px 0 0; font-size: var(--wds-font-size-caption); color: var(--cg-muted);
  font-variant-numeric: tabular-nums; }
.wizon-yt-thumb { border-radius: var(--ds-radius-xs); flex-shrink: 0; object-fit: cover; }
.wizon-yt-tldr { margin: 0; font-weight: 500; border-left: 3px solid var(--cg-danger-fg);
  padding-left: 10px; }
.wizon-yt-axis svg { display: block; width: 100%; height: 14px; }
.wizon-yt-base { fill: var(--cg-menu-border); }
.wizon-yt-seg { fill: var(--cg-danger-fg); opacity: 0.78; }
.wizon-yt-seg--alt { opacity: 0.45; }
.wizon-yt-ticks { display: flex; justify-content: space-between;
  font-size: var(--wds-font-size-caption); color: var(--cg-muted);
  font-variant-numeric: tabular-nums; }
.wizon-yt-secs { border-top: 1px solid var(--cg-menu-border); }
.wizon-yt-sec { display: flex; gap: 10px; align-items: baseline; padding: 8px 0;
  border-bottom: 1px solid var(--cg-menu-border); }
.wizon-yt-ts { font-size: var(--wds-font-size-caption); flex-shrink: 0;
  color: var(--cg-danger-fg); font-variant-numeric: tabular-nums; }
.wizon-yt-sec-body b { display: block; font-size: var(--wds-font-size-body-2); }
.wizon-yt-sec-body span { display: block; font-size: var(--wds-font-size-caption);
  color: var(--cg-muted); }
.wizon-yt-warn { margin: 0; font-size: var(--wds-font-size-caption);
  color: var(--ds-feedback-warn-fg); }
.wizon-yt-disc { margin: 0; font-size: var(--wds-font-size-caption); color: var(--cg-muted); }
.wizon-yt-open { font-size: var(--wds-font-size-caption); }

/* ══ 권한 오류 표면 — doc 496 §3 ═══════════════════════════════════════════════
   세 표면 모두 새 색·새 간격을 만들지 않는다. 값은 전부 라이브 토큰에서 온다
   (--cg-*, --ds-*, --wds-z-toast) 이고, 전면 표면은 기존 .chatgpt-lifecycle-empty
   규격 위에 아이콘·계정 줄·액션 행만 얹은 것이다.

   ★상태 카드는 키보드만으로 도달하는 경우가 많다. :focus-visible 링을 반드시 준다. */
body.chatgpt-reference-v1 .permission-state-icon {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-bottom: 2px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-pill, 999px);
  color: var(--cg-muted);
}

body.chatgpt-reference-v1 .permission-state-icon svg { width: 20px; height: 20px; }

body.chatgpt-reference-v1 .permission-full span:not(.permission-state-icon):not(.permission-full-account) {
  max-width: 44ch;
}

body.chatgpt-reference-v1 .permission-full-account {
  margin-top: 2px;
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-12);
}

body.chatgpt-reference-v1 .permission-state-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin-top: 10px;
}

body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-primary {
  border-color: var(--cg-text);
  background: var(--cg-text);
  color: var(--cg-surface);
}

body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-primary:hover,
body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-primary:focus-visible {
  background: var(--cg-text);
  opacity: 0.86;
}

/* 「다른 계정으로 로그인」은 조용한 3차 액션이다 — 로그인 경로를 없애지 않되
   1차로 올리지 않는다. 1차로 올리면 지금 고치는 그 오해가 그대로 돌아온다. */
body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-quiet {
  border-color: transparent;
  background: none;
  color: var(--cg-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}

body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-quiet:hover,
body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action.is-quiet:focus-visible {
  background: var(--cg-hover);
  color: var(--cg-text);
}

body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action:focus-visible,
body.chatgpt-reference-v1 .permission-inline .chatgpt-route-action:focus-visible,
body.chatgpt-reference-v1 .permission-toast button:focus-visible {
  outline: 2px solid var(--cg-text);
  outline-offset: 2px;
}

/* ── 표면 B · 인라인 ── 뒤의 목록을 지우지 않는다. 배너만 얹는다. */
body.chatgpt-reference-v1 .permission-inline {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 14px;
  padding: 12px 14px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-sm, 10px);
  background: var(--cg-hover);
}

body.chatgpt-reference-v1 .permission-inline .permission-state-icon {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  margin-bottom: 0;
  border-color: transparent;
}

body.chatgpt-reference-v1 .permission-inline .permission-state-icon svg { width: 18px; height: 18px; }

body.chatgpt-reference-v1 .permission-inline-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}

body.chatgpt-reference-v1 .permission-inline-copy strong {
  color: var(--cg-text);
  font-size: var(--ds-text-body-14);
  font-weight: 500;
}

body.chatgpt-reference-v1 .permission-inline-copy span {
  color: var(--cg-muted);
  font-size: var(--ds-text-caption-13);
}

body.chatgpt-reference-v1 .permission-inline .chatgpt-route-action { flex: 0 0 auto; }

/* ── 표면 C · 토스트 ── 한 문장 + 액션 하나. 계정·2차 액션은 넣지 않는다. */
.permission-toast-host {
  position: fixed;
  right: 16px;
  bottom: 16px;
  left: auto;
  display: grid;
  justify-items: end;
  pointer-events: none;
  z-index: var(--wds-z-toast, 1400);
}

.permission-toast {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(92vw, 460px);
  padding: 11px 14px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-sm, 10px);
  background: var(--cg-surface);
  color: var(--cg-text);
  box-shadow: var(--cg-shadow-float-lg);
  font-size: var(--ds-text-caption-13);
  pointer-events: auto;
}

.permission-toast button {
  flex: 0 0 auto;
  min-height: 34px;
  padding: 6px 10px;
  border: 1px solid var(--ds-color-line);
  border-radius: var(--ds-radius-xs, 8px);
  background: var(--cg-surface);
  color: var(--cg-text);
  font: inherit;
  font-size: var(--ds-text-caption-13);
  cursor: pointer;
}

.permission-toast button:hover { background: var(--cg-hover); }

/* 좁은 화면에서는 토스트가 가로를 채우고, 액션이 아래로 내려간다. 44px 터치 슬롭은
   기존 20260803-touch-target-44 규칙을 그대로 탄다. */
@media (max-width: 520px) {
  .permission-toast-host { right: 12px; left: 12px; justify-items: stretch; }
  .permission-toast { flex-wrap: wrap; max-width: none; }
  .permission-toast button { flex: 1 1 auto; }
  body.chatgpt-reference-v1 .permission-inline { flex-wrap: wrap; }
  body.chatgpt-reference-v1 .permission-inline .chatgpt-route-action { flex: 1 1 auto; }
  body.chatgpt-reference-v1 .permission-state-actions .chatgpt-route-action { flex: 1 1 auto; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CPQ 공수 기준표 관리 «화면» (doc 505 C 트랙) — cpq-dash 위젯과 같은 시각 언어:
   틴트 캔버스 위에 그림자로 뜬 카드, --wds 시맨틱 토큰 별칭(--cpqp-*), tabular-nums,
   히어로 title ↔ 캡션 label 의 크기 대비. 상태(대기/승인/반려)는 색으로 한눈에 읽힌다.
   ═══════════════════════════════════════════════════════════════════════════ */
.cpq-page {
  --cpqp-canvas: var(--wds-color-surface-muted);
  --cpqp-card: var(--wds-color-surface);
  --cpqp-ink: var(--wds-color-text);
  --cpqp-ink-2: var(--wds-color-text-muted);
  --cpqp-muted: var(--wds-color-text-subtle);
  --cpqp-hair: var(--wds-color-border-subtle);
  --cpqp-line: var(--wds-color-border);
  --cpqp-accent: var(--wds-color-primary);
  --cpqp-accent-ink: var(--wds-color-primary-text);
  --cpqp-on-accent: var(--wds-color-on-primary);
  --cpqp-ok-fg: var(--wds-color-success-text);
  --cpqp-ok-bg: var(--wds-color-success-container);
  --cpqp-warn-fg: var(--wds-color-warning-text);
  --cpqp-warn-bg: var(--wds-color-warning-container);
  --cpqp-err-fg: var(--wds-color-error-text);
  --cpqp-err-bg: var(--wds-color-error-container);
  --cpqp-gone-fg: var(--wds-color-text-subtle);
  --cpqp-gone-bg: var(--wds-color-surface-muted);
  /* 견적 이력의 «개정»과 «복원»은 성공도 경고도 아니다 — 정보/태그 축을 따로 빌린다.
     색만 다른 게 아니라 뜻이 다르므로 ok/warn 을 재사용하지 않는다. */
  --cpqp-info-fg: var(--wds-color-info-text);
  --cpqp-info-bg: var(--wds-color-info-container);
  --cpqp-back-fg: var(--wds-color-tag-violet-text);
  --cpqp-back-bg: var(--wds-color-tag-violet-bg);
  --cpqp-shadow: var(--ds-shadow-xs);
  display: block; background: var(--cpqp-canvas); color: var(--cpqp-ink);
  border-radius: var(--wizon-ai-radius-sheet); padding: clamp(16px, 2vw, 28px);
  font-size: var(--wds-font-size-body-s); line-height: 1.5; container-type: inline-size;
}
.cpq-page-head { display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 22px; }
.cpq-page-head-text { max-width: 62ch; }
.cpq-eyebrow { font-size: var(--wds-font-size-label-s); font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--cpqp-accent-ink); }
.cpq-title { font-size: var(--wds-font-size-h1); font-weight: 600; letter-spacing: -0.02em;
  line-height: 1.1; margin: 6px 0 8px; color: var(--cpqp-ink); }
.cpq-lead { font-size: var(--wds-font-size-body-s); color: var(--cpqp-ink-2); margin: 0; }
.cpq-rolechip { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px;
  font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 4px 10px;
  border-radius: var(--wizon-ai-radius-pill); color: var(--cpqp-muted);
  background: var(--cpqp-card); box-shadow: inset 0 0 0 1px var(--cpqp-line); }
.cpq-page-acts { display: flex; gap: 10px; flex-wrap: wrap; }

/* ── 버튼: 채운 accent / 고스트 / 승인·반려 ── */
.cpq-btn { font-family: inherit; font-size: var(--wds-font-size-body-s); font-weight: 600;
  border: 0; border-radius: var(--wizon-ai-radius-control); padding: 9px 16px; cursor: pointer;
  transition: transform 120ms ease, box-shadow 160ms ease, background 160ms ease, opacity 160ms ease; }
.cpq-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.cpq-btn:not(:disabled):active { transform: translateY(1px); }
.cpq-btn:focus-visible { outline: 2px solid var(--cpqp-accent); outline-offset: 2px; }
.cpq-btn--primary { background: var(--cpqp-accent); color: var(--cpqp-on-accent);
  box-shadow: var(--cpqp-shadow); }
.cpq-btn--primary:not(:disabled):hover { box-shadow: 0 4px 14px -4px var(--cpqp-accent); }
.cpq-btn--ghost { background: var(--cpqp-card); color: var(--cpqp-ink);
  box-shadow: inset 0 0 0 1px var(--cpqp-line); }
.cpq-btn--ghost:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--cpqp-accent);
  color: var(--cpqp-accent-ink); }
.cpq-btn--approve { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-btn--approve:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--cpqp-ok-fg); }
.cpq-btn--reject { background: var(--cpqp-card); color: var(--cpqp-err-fg);
  box-shadow: inset 0 0 0 1px var(--cpqp-line); }
.cpq-btn--reject:not(:disabled):hover { box-shadow: inset 0 0 0 1px var(--cpqp-err-fg); }

/* ── 알림 배너 ── */
.cpq-banner { border-radius: var(--wizon-ai-radius-control); padding: 12px 16px; margin-bottom: 16px;
  font-size: var(--wds-font-size-body-s); font-weight: 500; }
.cpq-banner--ok { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-banner--err { background: var(--cpqp-err-bg); color: var(--cpqp-err-fg); }

/* ── 제안 폼 (카드) ── */
.cpq-form { background: var(--cpqp-card); border-radius: var(--wizon-ai-radius-popover);
  box-shadow: var(--cpqp-shadow); padding: 20px; margin-bottom: 22px; }
.cpq-form-head { margin-bottom: 16px; }
.cpq-form-title { font-size: var(--wds-font-size-body-2); font-weight: 600; margin: 0 0 4px; }
.cpq-form-sub { font-size: var(--wds-font-size-caption); color: var(--cpqp-ink-2); margin: 0; }
.cpq-form-hint { font-size: var(--wds-font-size-caption); color: var(--cpqp-warn-fg); margin: 0 0 12px; }
.cpq-form-err { font-size: var(--wds-font-size-caption); color: var(--cpqp-err-fg); font-weight: 600;
  margin: 4px 0 0; }
.cpq-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
@container (max-width: 560px) { .cpq-form-grid { grid-template-columns: 1fr; } }
.cpq-field { display: flex; flex-direction: column; gap: 6px; }
.cpq-field--full { margin-top: 14px; }
.cpq-field--preview { justify-content: flex-start; }
.cpq-label { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqp-ink-2); }
.cpq-input { font-family: inherit; font-size: var(--wds-font-size-body-s); color: var(--cpqp-ink);
  background: var(--cpqp-canvas); border: 0; box-shadow: inset 0 0 0 1px var(--cpqp-line);
  border-radius: var(--wizon-ai-radius-control); padding: 9px 12px; }
.cpq-input:focus-visible { outline: 0; box-shadow: inset 0 0 0 2px var(--cpqp-accent); }
.cpq-textarea { resize: vertical; min-height: 44px; }
.cpq-current { font-size: var(--wds-font-size-body-s); color: var(--cpqp-ink-2);
  font-variant-numeric: tabular-nums; padding: 9px 0; align-self: flex-start; }
.cpq-form-acts { display: flex; gap: 10px; margin-top: 18px; }

/* ── 섹션 ── */
.cpq-section { margin-bottom: 26px; }
.cpq-section-title { font-size: var(--wds-font-size-body-2); font-weight: 600; margin: 0 0 12px;
  display: flex; align-items: center; gap: 8px; }
.cpq-count { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqp-warn-fg);
  background: var(--cpqp-warn-bg); border-radius: var(--wizon-ai-radius-pill);
  padding: 2px 9px; font-variant-numeric: tabular-nums; }

/* ── 제안 카드 (좌측 상태 스트립으로 색을 한눈에) ── */
.cpq-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
.cpq-card { position: relative; background: var(--cpqp-card); border-radius: var(--wizon-ai-radius-popover);
  box-shadow: var(--cpqp-shadow); padding: 16px 18px 16px 20px; overflow: hidden; }
.cpq-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--cpqp-line); }
.cpq-card--pending::before { background: var(--cpqp-warn-fg); }
.cpq-card--ok::before { background: var(--cpqp-ok-fg); }
.cpq-card--gone::before { background: var(--cpqp-gone-fg); }
.cpq-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cpq-cardid { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqp-muted);
  font-variant-numeric: tabular-nums; }
.cpq-chip { font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 3px 10px;
  border-radius: var(--wizon-ai-radius-pill); }
.cpq-chip--pending { background: var(--cpqp-warn-bg); color: var(--cpqp-warn-fg); }
.cpq-chip--ok { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-chip--gone { background: var(--cpqp-gone-bg); color: var(--cpqp-gone-fg); }
.cpq-card-cell { font-size: var(--wds-font-size-body-s); font-weight: 600; margin: 12px 0 8px;
  color: var(--cpqp-ink); }
.cpq-card-change { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-variant-numeric: tabular-nums; }
.cpq-md { font-size: var(--wds-font-size-body-s); }
.cpq-md--old { color: var(--cpqp-muted); }
.cpq-md--new { font-weight: 600; color: var(--cpqp-ink); font-size: var(--wds-font-size-body-2); }
.cpq-arrow { color: var(--cpqp-muted); }
.cpq-delta { font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 2px 8px;
  border-radius: var(--wizon-ai-radius-pill); }
.cpq-delta--up { background: var(--cpqp-err-bg); color: var(--cpqp-err-fg); }
.cpq-delta--down { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-delta--flat { background: var(--cpqp-gone-bg); color: var(--cpqp-gone-fg); }
.cpq-card-meta { font-size: var(--wds-font-size-caption); color: var(--cpqp-muted); margin-top: 10px;
  font-variant-numeric: tabular-nums; }
.cpq-note { font-size: var(--wds-font-size-caption); color: var(--cpqp-ink-2); margin: 8px 0 0;
  padding-left: 10px; box-shadow: inset 2px 0 0 var(--cpqp-hair); }
.cpq-card-acts { display: flex; gap: 8px; margin-top: 14px; }
.cpq-await, .cpq-applied { display: inline-block; margin-top: 14px; font-size: var(--wds-font-size-label-s);
  font-weight: 600; color: var(--cpqp-muted); }
.cpq-applied { color: var(--cpqp-ok-fg); }

/* ── 현재 기준표 그리드 (가로 스크롤은 자기 안에서) ── */
.cpq-grid-wrap { overflow-x: auto; background: var(--cpqp-card); border-radius: var(--wizon-ai-radius-popover);
  box-shadow: var(--cpqp-shadow); padding: 6px; }
.cpq-grid { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
.cpq-grid-cap { caption-side: bottom; text-align: left; font-size: var(--wds-font-size-caption);
  color: var(--cpqp-muted); padding: 10px 12px; }
.cpq-grid th, .cpq-grid td { padding: 4px; text-align: center; }
.cpq-grid thead th { font-size: var(--wds-font-size-label-s); font-weight: 600; color: var(--cpqp-ink-2);
  padding: 10px 8px; }
.cpq-grid tbody th[scope="row"] { text-align: left; font-size: var(--wds-font-size-caption);
  font-weight: 600; color: var(--cpqp-ink); padding: 4px 12px 4px 8px; white-space: nowrap; }
.cpq-cell { display: block; width: 100%; min-width: 56px; font-family: inherit;
  font-size: var(--wds-font-size-body-s); color: var(--cpqp-ink); background: var(--cpqp-canvas);
  border: 0; border-radius: var(--wizon-ai-radius-control); padding: 10px 6px; cursor: pointer;
  transition: box-shadow 140ms ease, color 140ms ease; }
.cpq-cell:hover { box-shadow: inset 0 0 0 1px var(--cpqp-accent); color: var(--cpqp-accent-ink); }
.cpq-cell:focus-visible { outline: 2px solid var(--cpqp-accent); outline-offset: 1px; }
.cpq-cell--static { cursor: default; background: transparent; }
.cpq-cell--static:hover { box-shadow: none; color: var(--cpqp-ink); }

/* ── 빈/로딩 상태 ── */
.cpq-empty { background: var(--cpqp-card); border-radius: var(--wizon-ai-radius-popover);
  box-shadow: var(--cpqp-shadow); padding: 22px; text-align: center; color: var(--cpqp-muted);
  font-size: var(--wds-font-size-body-s); }
.cpq-empty--soft { box-shadow: inset 0 0 0 1px var(--cpqp-hair); background: transparent; }
.cpq-skeleton { display: grid; gap: 14px; }
.cpq-skeleton span { display: block; height: 92px; border-radius: var(--wizon-ai-radius-popover);
  background: linear-gradient(100deg, var(--cpqp-card) 30%, var(--cpqp-canvas) 50%, var(--cpqp-card) 70%);
  background-size: 200% 100%; animation: cpq-shimmer 1.3s ease-in-out infinite; }
@keyframes cpq-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .cpq-skeleton span { animation: none; } }
/* ── 견적서 목록·조회 (doc 505 C 트랙) ──
   같은 시각 언어를 그대로 잇는다: 틴트 캔버스 위의 카드, 왼쪽 4px 상태 레일,
   tabular-nums. ★상태를 «색으로만» 말하지 않는다 — 레일(형태) + 칩(글자) + 배지가
   같은 사실을 세 번 겹쳐 말하므로 색을 못 보는 사용자도 읽는다. */
.cpq-band { font-size: var(--wds-font-size-body-2); font-weight: 600; color: var(--cpqp-ink);
  margin: 34px 0 14px; padding-top: 18px; box-shadow: inset 0 1px 0 var(--cpqp-hair); }
.cpq-section--quotes { margin-bottom: 8px; }

.cpq-qbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.cpq-qseg { display: flex; gap: 4px; padding: 4px; background: var(--cpqp-card);
  border-radius: var(--wizon-ai-radius-pill); box-shadow: inset 0 0 0 1px var(--cpqp-hair); }
.cpq-qseg-btn { font-family: inherit; font-size: var(--wds-font-size-label-s); font-weight: 600;
  display: inline-flex; align-items: center; gap: 5px; border: 0; cursor: pointer;
  background: none; color: var(--cpqp-ink-2); padding: 5px 13px;
  border-radius: var(--wizon-ai-radius-pill); transition: background 120ms ease, color 120ms ease; }
.cpq-qseg-btn:hover { color: var(--cpqp-ink); }
.cpq-qseg-btn:focus-visible { outline: 2px solid var(--cpqp-accent); outline-offset: 2px; }
.cpq-qseg-btn--on { background: var(--cpqp-ink); color: var(--cpqp-card); }
.cpq-qseg-n { font-style: normal; font-size: var(--wds-font-size-label-s); opacity: 0.65;
  font-variant-numeric: tabular-nums; }
.cpq-qperiod { font-size: var(--wds-font-size-label-s); color: var(--cpqp-muted);
  font-variant-numeric: tabular-nums; margin-right: auto; }

.cpq-qlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.cpq-qitem { position: relative; background: var(--cpqp-card); overflow: hidden;
  border-radius: var(--wizon-ai-radius-popover); box-shadow: var(--cpqp-shadow); }
.cpq-qitem::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--cpqp-line); }
.cpq-qitem:has(.cpq-qchip--gone)::before { background: var(--cpqp-gone-fg); }
.cpq-qitem:has(.cpq-qchip--amend)::before { background: var(--cpqp-info-fg); }
.cpq-qitem:has(.cpq-qchip--back)::before { background: var(--cpqp-back-fg); }
.cpq-qitem:has(.cpq-qchip--won)::before { background: var(--cpqp-ok-fg); }
.cpq-qitem:has(.cpq-qchip--lost)::before { background: var(--cpqp-err-fg); }

/* 행은 «진짜 button» 이다 — div+click 이면 키보드로 본문을 영영 못 연다. */
.cpq-qrow { display: grid; grid-template-columns: 38px minmax(0, 1fr) auto; gap: 12px;
  align-items: center; width: 100%; text-align: left; font-family: inherit; border: 0;
  background: none; cursor: pointer; padding: 12px 16px 12px 20px; color: var(--cpqp-ink);
  transition: background 120ms ease; }
.cpq-qrow:hover { background: var(--cpqp-canvas); }
.cpq-qrow:focus-visible { outline: 2px solid var(--cpqp-accent); outline-offset: -2px; }
.cpq-qitem--open .cpq-qrow { background: var(--cpqp-canvas); }
.cpq-qkind { display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: var(--wizon-ai-radius-menu-row);
  font-size: var(--wds-font-size-label-s); font-weight: 600; letter-spacing: 0.02em; }
.cpq-qkind--hw { background: var(--cpqp-info-bg); color: var(--cpqp-info-fg); }
.cpq-qkind--sw { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-qmid { min-width: 0; display: block; }
.cpq-qno { display: block; font-size: var(--wds-font-size-body-s); font-weight: 600;
  letter-spacing: -0.01em; font-variant-numeric: tabular-nums; color: var(--cpqp-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpq-qmeta { display: block; margin-top: 2px; font-size: var(--wds-font-size-label-s);
  color: var(--cpqp-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpq-qsup { margin-left: 6px; color: var(--cpqp-info-fg); font-weight: 600; }
.cpq-qend { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.cpq-qamt { font-size: var(--wds-font-size-body-s); font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--cpqp-ink); white-space: nowrap; }
.cpq-qamt--unk { font-size: var(--wds-font-size-label-s); font-weight: 400;
  color: var(--cpqp-muted); }
.cpq-qchip { font-size: var(--wds-font-size-label-s); font-weight: 600; padding: 3px 10px;
  border-radius: var(--wizon-ai-radius-pill); white-space: nowrap;
  background: var(--cpqp-gone-bg); color: var(--cpqp-muted); }
.cpq-qchip--ok { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-qchip--amend { background: var(--cpqp-info-bg); color: var(--cpqp-info-fg); }
/* ★철회 칩의 바탕(--cpqp-gone-bg)은 캔버스와 «같은 토큰»이다 — 펼친 행은 배경이
   캔버스로 바뀌므로 칩이 통째로 사라진다(1440 실측). 다른 칩과 달리 테두리를 준다. */
.cpq-qchip--gone { background: var(--cpqp-gone-bg); color: var(--cpqp-gone-fg);
  box-shadow: inset 0 0 0 1px var(--cpqp-line); }
.cpq-qchip--back { background: var(--cpqp-back-bg); color: var(--cpqp-back-fg); }
.cpq-qchip--won { background: var(--cpqp-ok-bg); color: var(--cpqp-ok-fg); }
.cpq-qchip--lost { background: var(--cpqp-err-bg); color: var(--cpqp-err-fg); }

/* ── 펼친 본문: 캔버스 위에 얹힌 안쪽 판 ── */
.cpq-qdetail { background: var(--cpqp-canvas); padding: 4px 18px 18px 20px;
  box-shadow: inset 0 1px 0 var(--cpqp-hair); }
.cpq-qfacts { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px 18px; margin: 14px 0 4px; }
.cpq-qfact dt { font-size: var(--wds-font-size-label-s); color: var(--cpqp-muted); }
.cpq-qfact dd { margin: 2px 0 0; font-size: var(--wds-font-size-body-s); font-weight: 600;
  color: var(--cpqp-ink); font-variant-numeric: tabular-nums; }
.cpq-qsub-title { font-size: var(--wds-font-size-label-s); font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--cpqp-muted);
  margin: 20px 0 8px; }
.cpq-qlines th, .cpq-qlines td { text-align: right; white-space: nowrap; }
.cpq-qlines thead th { text-align: right; }
.cpq-qlines thead th:first-child, .cpq-qlines tbody th[scope="row"] { text-align: left;
  white-space: normal; }
.cpq-qline-sec { display: block; font-style: normal; font-size: var(--wds-font-size-label-s);
  font-weight: 600; letter-spacing: 0.04em; color: var(--cpqp-accent-ink); }
.cpq-qline-sub { display: block; font-style: normal; font-weight: 400;
  font-size: var(--wds-font-size-label-s); color: var(--cpqp-muted); }

/* 세로 커넥터 + 사건별 색점. 점의 «색»이 사건 종류를 인코딩하지만 라벨이 바로 옆에
   글자로 있으므로, 색을 못 봐도 무엇이 있었는지 읽힌다. */
.cpq-qtl { list-style: none; margin: 0; padding: 0 0 0 18px; position: relative; }
.cpq-qtl::before { content: ""; position: absolute; left: 4px; top: 6px; bottom: 6px;
  width: 1px; background: var(--cpqp-hair); }
.cpq-qtl-item { position: relative; padding: 0 0 14px; }
.cpq-qtl-item:last-child { padding-bottom: 0; }
.cpq-qtl-dot { position: absolute; left: -18px; top: 5px; width: 9px; height: 9px;
  border-radius: var(--wizon-ai-radius-pill); background: var(--cpqp-line);
  box-shadow: 0 0 0 3px var(--cpqp-canvas); }
.cpq-qtl-item--ok .cpq-qtl-dot, .cpq-qtl-item--won .cpq-qtl-dot { background: var(--cpqp-ok-fg); }
.cpq-qtl-item--amend .cpq-qtl-dot { background: var(--cpqp-info-fg); }
.cpq-qtl-item--gone .cpq-qtl-dot { background: var(--cpqp-gone-fg); }
.cpq-qtl-item--back .cpq-qtl-dot { background: var(--cpqp-back-fg); }
.cpq-qtl-item--lost .cpq-qtl-dot { background: var(--cpqp-err-fg); }
.cpq-qtl-head { display: block; font-size: var(--wds-font-size-body-s); font-weight: 600;
  color: var(--cpqp-ink); }
.cpq-qtl-rev { font-style: normal; margin-left: 8px; font-weight: 400;
  font-size: var(--wds-font-size-label-s); color: var(--cpqp-muted);
  font-variant-numeric: tabular-nums; }
.cpq-qtl-meta { display: block; margin-top: 1px; font-size: var(--wds-font-size-label-s);
  color: var(--cpqp-muted); }
.cpq-qtl-note { margin: 6px 0 0; padding-left: 10px; font-size: var(--wds-font-size-caption);
  color: var(--cpqp-ink-2); box-shadow: inset 2px 0 0 var(--cpqp-hair); }
.cpq-qacts { display: flex; gap: 10px; align-items: center; margin-top: 20px;
  padding-top: 14px; box-shadow: inset 0 1px 0 var(--cpqp-hair); }
.cpq-qempty { margin: 0; font-size: var(--wds-font-size-caption); color: var(--cpqp-muted); }
.cpq-qtrunc { margin: 10px 0 0; font-size: var(--wds-font-size-caption);
  color: var(--cpqp-muted); }

@container (max-width: 560px) {
  .cpq-page-head { flex-direction: column; align-items: stretch; }
  .cpq-cards { grid-template-columns: 1fr; }
  .cpq-qrow { grid-template-columns: 30px minmax(0, 1fr); row-gap: 8px; }
  .cpq-qkind { width: 30px; height: 30px; }
  .cpq-qend { grid-column: 1 / -1; flex-direction: row; align-items: center;
    justify-content: space-between; }
  .cpq-qperiod { width: 100%; margin-right: 0; }
}
/* 런처의 CPQ 카드는 «링크»라(라우트 이동) — .chatgpt-app-card 스타일을 그대로 쓰되
   링크 기본 밑줄·색만 지운다. */
.cpq-app-card { text-decoration: none; color: inherit; }
