/* 오늘얼마 — 공개 웹 공통 스타일 (개발계획서2.md §7.2 · docs/MASTER.md v1.0)
 *
 * 🔴 2026-09-12 — 브랜드를 빨강에서 **로고(brand/icon_e.png)의 숲 초록**으로 옮겼다
 *    (사용자 확정). 옛 토큰 `--brand-red`(#C62828)·`--brand-red-button`(#A31515)·
 *    `--brand-red-ink` 는 제거됐고 `--brand-ink`·`--brand-on-ink` 가 대신한다.
 *
 * 색 규칙(요약에 대비 계산 근거를 남긴다 — 전부 이 저장소의 WCAG 계산식 실측값):
 *   - **헤더·강조 글자·주 버튼**은 `--brand-ink:#0F5132` 하나다. 헤더는 `.tabs`·`.site-search`
 *     처럼 사용자가 읽고 누르는 요소를 담고 있어 로고 단독 라벨이 아니므로 본문과 같은
 *     7:1(AAA)을 적용한다. 실측: `#0F5132` on `#fff` = **9.361:1**,
 *     흰 글자 on `#0F5132` 헤더 = **9.361:1**, `#0F5132` on 바닥 `#F4F7F2` = **8.663:1**.
 *   - 🔴 **바닥과 카드를 분리했다.** `--color-bg` 가 `#fff` 에서 `#F4F7F2`(들판)로 바뀌고
 *     `--color-card-bg:#fff` 가 새로 생겼다. "흰 바탕에 흰 카드라 구분이 안 된다"는
 *     사용자 지적의 해법이다 — 경계를 선이 아니라 **색**이 만든다(둘의 대비 1.081).
 *     🔴 `--color-card-bg` 가 생기면서 `AppCssContrastTest` 가 글자 토큰을 **바닥과 카드
 *     양쪽**에 대해 검사한다(그 테스트의 `backgrounds()` 가 이 이름을 먼저 찾는다).
 *   - 🔴 **`--accent-fill`(#F57C00)은 글자가 될 수 없다.** 흰 바탕 대비 **2.704:1**,
 *     흰 글자를 올려도 2.704:1 이다. `background`·`border`·`fill` 에만 쓴다. 주황 위에
 *     글자를 올려야 하면 `--color-text` 뿐이다(**6.983:1**). 그래서 이 토큰은 일부러
 *     `color:` 선언에 한 번도 안 쓰이고, `AppCssContrastTest` 가 그걸 감시한다.
 *   - 등락(▲▼) 색은 그대로 둔다. 브랜드가 초록으로 옮겨가면서 옛 주석이 걱정하던
 *     "가격 글자를 브랜드 빨강으로 칠하면 모든 가격이 오른 것처럼 읽힌다"는 위험이
 *     **구조적으로 사라졌다** — 빨강은 이제 `--tone-up` 전용이다.
 *     상승 #B3261E(카드 6.536 / 바닥 6.049:1) · 하락 #1565C0(5.746 / 5.318:1).
 *   - 시각 배지(`.time-badge`)의 검정 오버레이 `rgba(0,0,0,.16)` — 유효 배경 `#0d442a`,
 *     흰 글자 대비 **11.186:1**. (흰 오버레이는 배경을 밝혀 AA 에도 미달시킨다 — 쓰지 않는다.)
 *   - 본문·가격 숫자는 `#111`: 카드에서 18.883:1, 바닥에서 17.474:1.
 */

:root {
  /* 바닥과 면 — 카드 구분의 근거 */
  --color-bg: #F4F7F2;        /* 들판 바닥. 본문 #111 과 17.474:1 */
  --color-card-bg: #FFFFFF;   /* 카드 면. 바닥과 1.081 차 — 선 없이도 떠 보인다 */
  --color-text: #111;         /* 카드 18.883:1 · 바닥 17.474:1 */
  --color-text-sub: #4a4a4a;  /* 카드 8.862:1 · 바닥 8.201:1 */
  --color-border: #D2DBCD;    /* 카드 바깥 테두리(초록 쪽 중립) */
  --color-border-soft: #E2E8DE; /* 카드 안쪽 구획선 */
  --color-border-lead: #C3CFBE; /* 첫 품목 카드 테두리 — 한 단 진하다. 흰 면 1.616:1
                                   🔴 장식이다(정보를 싣지 않는다) — "떠 있음"을 말하는 것은
                                   --shadow-lead 고, 이 선은 그 그림자를 받쳐 준다 */

  /* 브랜드 — 로고 icon_e.png 의 숲 초록 */
  --brand-ink: #0F5132;       /* 헤더 배경·강조 글자·주 버튼. 흰 글자 9.361:1(AAA) */
  --brand-on-ink: #fff;
  --brand-soft: #E8F3E9;      /* 칩 배경 — 그 위 --brand-ink 글자 8.215:1 */
  --brand-mid: #9CCFAE;       /* --brand-soft 와 --brand-ink 사이. 분포 막대 그라데이션의
                                 옅은 끝(§4.3). 채움 전용 — 흰 면 1.757:1 로 글자 불가 */
  --brand-on-ink-dim: #E3EFE7; /* 초록 헤더 위 보조 글자. 흰색보다 한 단 낮다 — 7.920:1(AAA) */

  /* 🔴 채움 전용 — color: 에 쓰지 않는다(흰 바탕 2.704:1) */
  --accent-fill: #F57C00;
  --accent-soft: #FFE0B2;

  --tone-up: #B3261E;         /* 등락 전용 톤 */
  --tone-down: #1565C0;
  --tone-flat: #555555;
  --tone-none: #6b6b6b;       /* 바닥에서 4.932:1 — 가장 빠듯하다. 더 밝히지 않는다 */
  --focus-ring: #0b57d0;

  --touch-min: 48px;
  --gap-min: 8px;
  --radius-card: 14px;
  --radius-inner: 11px;
  --radius-chip: 10px;
  --radius-pill: 999px;

  /* 🔴 꺾쇠(›) — **글자가 아니라 그림**이다(사용자 지시 2026-09-18 "화살표는 기기에 따라
     다르게 보이고 있어, 일괄성 있는 표시로 해줘"). `›`(U+203A)는 원래 따옴표라 한글 글꼴
     스택(Apple SD Gothic Neo / One UI / Noto Sans KR / 시스템 폴백)마다 굵기·기울기·높이가
     다르다. 마스크 SVG 로 그리면 어느 기기든 같다. 쓰는 곳: `m1.css` 의 품종명·접힘줄 둘,
     이 파일의 `.item-spec-minmax-summary`. 자세히는 docs/MASTER.md §4.12.
     🔴 기본 방향은 **오른쪽**이어야 한다 — 아래를 가리키게 그리면 `[open]{rotate(90deg)}`
     가 접힘·펼침을 거꾸로 만든다(에러가 안 난다).
     🔴 `stroke='black'` 은 색이 아니다 — 마스크는 알파만 읽는다(§1.1 토큰 규칙 밖).
     🔴 크기가 `rem` 인 이유: 쓰는 세 자리의 부모 글자 크기가 다르다(0.85·0.9·1.05rem).
     `em` 이면 꺾쇠가 자리마다 달라져 **없애려던 불일치가 그대로 돌아온다**. */
  --chev-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 14'%3E%3Cpath d='M1.6 1.6 6.4 7 1.6 12.4' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --chev-w: 0.42rem;
  --chev-h: 0.74rem;
  /* 🔴 60px 이었다 — AdMob **Large 적응형(large anchored adaptive) 배너** 실제 크기가
     432x135 이라 60px 짜리 자리표시는 배너가 내용 **75px 를 덮는다**(사용자 통보 2026-09-13).
     Google 문서: large anchored adaptive 는 폭으로 높이를 정하고 **50~150pt** 사이,
     화면 높이의 **20% 이하**다. 432:135 는 LARGE_BANNER 320x100 과 같은 **3.2:1** 이고
     그 비율이 clamp 양끝(160→50 · 480→150)에 정확히 맞는다 ⇒ height ≈ 폭/3.2.
     ⇒ 우리 목표 폭에서 360→112.5 · 393→122.8 · 430→134.4 · 432→**135**.
     🔴 **최댓값 135 로 못 박는다** — 모자라게 잡으면 배너가 내용을 조용히 덮는다(가장 나쁜 방향).
     360px 폭에서 최대 22px 를 더 비우는 대가는 감수한다. SDK 가 폭 비례가 아니라 계단식으로
     밝혀지면 그때 다시 본다. 🔴 **유효 폴드 = 852 − 135 = 717** 이다(옛 792 아님). */
  --ad-slot-height: 135px;
  --ad-gap: 32px;
  --safe-bottom: 80px;

  /* 동작 — docs/MASTER.md §5. 스크롤 연동·바운스는 쓰지 않는다 */
  --ease: cubic-bezier(.2, .7, .3, 1);
  --dur-fast: 140ms;
  --dur-open: 160ms;
  --dur-bar: 220ms;

  /* 그림자는 첫 품목 카드 하나에만 — 전부에 주면 위계가 평평해진다 */
  --shadow-lead: 0 1px 2px rgba(22,24,15,.06), 0 10px 22px -18px rgba(15,81,50,.55);
}

/* 🔴 앱(WebView)에는 광고 자리를 내보내지 않는다(Layout::adSlot). 그러면 이 변수들이 잡아 둔
   135 + 32 + 80 = 247px 이 화면 바닥에 빈 띠로 남는다 — 앱에서만 걷어낸다.
   하단 AdMob 배너는 WebView 바깥(네이티브)이라 웹이 자리를 비울 필요가 없다. */
html.is-app {
  --ad-slot-height: 0px;
  --ad-gap: 0px;
  --safe-bottom: 24px;
}

/* ── M6 큰 글씨 모드(3단계) · M10 정보밀도(brief-T2-11a) ────────────────
 * 🔴 루트 글자 크기는 **%** 로만 준다(px 고정 금지 — 브라우저 "글꼴 크기" 설정이
 * 안 먹던 버그, CLAUDE.md 실측). 100% = 브라우저 기본값(보통 16px)이라 사용자가
 * OS·브라우저에서 기본 글꼴 크기를 키우면 이 %값에 그대로 곱해진다(200% 확대도
 * 마찬가지 — 둘 다 곱연산으로 합성된다, 개발계획서2.md §7.2).
 * 터치 타깃(48px)·버튼(56px)·광고 자리(135px)·배너 여백(32px) 등 "몸의 크기"는
 * 위 `:root` 의 px 변수 그대로 둔다 — 글자가 커져도 버튼이 작아지면 안 된다.
 *
 * `top.php` 가 `<html class="fs-… density-…">` 로 서버 렌더한다(Day\View\DisplayPrefs) —
 * JS 없이 첫 페인트부터 적용돼 깜빡임이 없다.
 *
 * 3×2 조합표 (16px 기준 환산):
 *   | 글자 크기 \ 밀도 | 크게 보기(comfortable, 기본) | 한눈에 보기(compact)   |
 *   |---|---|---|
 *   | 기본(m, 기본값)   | 112.5% (18px)                | 112.5% (18px) — 여백만 줄인다 |
 *   | 크게(l)           | 131.25% (21px)                | 112.5% (18px)          |
 *   | 아주 크게(xl)     | 150% (24px)                   | 125% (20px)            |
 * 🔴 §9.4 [A] "축소 모드에서도 15px 이상" 은 **화면의 글자 전부**다. 공개 화면 CSS 의 가장 작은
 * 내용 글자가 `0.85rem` 이라 루트가 18px 아래로 내려가면 그 글자가 15px 아래가 된다
 * (루트 93.75% 였을 때 12.75px — 메인 400px 실측, T2-11a 리뷰). 그래서 모든 조합의 루트는
 * 112.5% 이상이고, `기본×한눈에` 는 글자를 줄이지 않고 여백·줄 간격·원천 기록값 숨김으로만
 * 밀도를 높인다. `AppCssTest::test_가장_작은_내용_글자도_모든_조합에서_15px_이상이다` 가 고정한다.
 */
html.fs-m { font-size: 112.5%; }
html.fs-l { font-size: 131.25%; }
html.fs-xl { font-size: 150%; }
html.fs-m.density-compact { font-size: 112.5%; }
html.fs-l.density-compact { font-size: 112.5%; }
html.fs-xl.density-compact { font-size: 125%; }
/* class 가 아직 안 붙은 예외 상황(예: 컴포넌트 단위 프리뷰) 대비 기본값 폴백 */
:root { font-size: 112.5%; }

* { box-sizing: border-box; }

html, body {
  max-width: 100%;
  /* 🔴 overflow-x:hidden 을 쓰지 않는다 — brief-T2-7b §1. 그 규칙은 넘침을 "막는" 게
     아니라 스크롤바만 숨기고 내용을 조용히 잘라낸다(scrollWidth 도 clamp 되어
     감지 스크립트마저 속인다). 넘침은 레이아웃(min-width:0, overflow-wrap)으로 없앤다. */
}

html {
  /* 키보드 포커스가 요소를 스크롤해 넣을 때 하단 고정 광고 자리에 가려지지 않게 한다
     (WCAG 2.2 SC 2.4.11 Focus Not Obscured). */
  scroll-padding-bottom: calc(var(--ad-slot-height) + var(--gap-min));
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font: 1rem/1.6 -apple-system, BlinkMacSystemFont, "Malgun Gothic", "맑은 고딕",
        "Apple SD Gothic Neo", sans-serif; /* 외부 폰트·CDN 없음 */
  /* 하단 광고 자리(고정 135px) + 32px 여백 + 80px 안전 패딩(WCAG 2.4.11) = 247px */
  padding-bottom: calc(var(--ad-slot-height) + var(--ad-gap) + var(--safe-bottom));
  /* 끊을 수 없는 긴 토큰(법인명·긴 숫자 등)이 뷰포트를 밀어내지 않게 한다.
     보통 줄바꿈에는 영향이 없다 — 필요할 때만 개입하는 안전망이다. */
  overflow-wrap: anywhere;
  /* 🔴 한글은 낱자 아무 데서나 끊으면 안 읽힌다. `overflow-wrap: anywhere` 만 있으면
     "공공데이터 반영에…" 가 `공공` / `데이터 반영에…` 로 **낱말 한가운데서** 갈린다
     (헤더 안내 실측). `keep-all` 은 어절(띄어쓰기) 단위로만 끊게 하고, 그래도 안 들어가는
     긴 토큰은 위의 `overflow-wrap` 이 받아 낸다 — 둘이 같이 있어야 맞다. */
  word-break: keep-all;
}

img { max-width: 100%; }

/* 화면에는 안 보이고 보조 기술에만 읽히는 글자. `display:none`·`visibility:hidden` 은
   스크린리더에서도 사라지므로 쓰지 않는다. 링크 글자가 품종명뿐이면 어디로 가는지
   알 수 없어(WCAG 2.4.4) 여기에 목적어를 붙인다 — `aria-label` 은 화면 글자를 통째로
   덮어써(WCAG 2.5.3 Label in Name) 쓰지 않는다. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  /* `clip` 은 낡았지만 구형 웹뷰가 `clip-path` 를 모를 때의 안전망이다 — 둘 다 둔다. */
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
  white-space: nowrap;
}

a, button, input, select { font: inherit; color: inherit; }

:focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

/* ── 헤더 — 모든 화면 같은 위치에 기준시각 배지(WCAG 3.2.6) ───────────── */
.site-header {
  background: var(--brand-ink); /* 흰 글자 기준 7.849:1(AAA) — brief-T2-9c */
  color: var(--brand-on-ink);
}
.site-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-min);
  flex-wrap: wrap;
  padding: 10px 16px 0;
}
/* 배지 줄 — 브랜드·검색·즐겨찾기·보기 와 **같은 줄에 끼워 넣지 않는다**. 배지는 폭이
   내용에 따라 크게 변해서(수집 시각 + 낙찰 시각 + 지연 안내) 한 줄에 넣으면 좁은 폭에서
   버튼들을 밀어낸다. 헤더 안 둘째 줄로 내려 폭 경쟁을 없앤다. */
/* 🔴 배지와 안내를 **각자 줄**로 둔다. 한때 한 글줄로 이어 붙여 8px 를 아꼈는데,
   그러면 배지 꼬리가 넘쳐서 `최근 낙찰 9/11` / `13:30` 처럼 **시각 하나가 두 줄로 갈렸다**
   (실측). 8px 아끼자고 시각을 못 읽게 만들지 않는다. */
.site-header-meta {
  padding: 5px 16px 10px;
  line-height: 1.35;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.site-header-row > * {
  /* flex 기본 min-width:auto 는 내용이 길면 줄바꿈 대신 컨테이너를 밀어 넘친다.
     0 으로 풀어야 flex-wrap·overflow-wrap 이 실제로 동작한다. */
  min-width: 0;
}
.site-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--brand-on-ink);
  text-decoration: none;
  font-weight: 800;
  font-size: 1.15rem;
  letter-spacing: -0.01em;
  min-height: var(--touch-min);
}
/* 🔴 `brand/icon_e.png` 은 1254x1254 **흰 배경 불투명**이다(GD 로 알파 실측 — 전 구간 0).
   초록 헤더에 그냥 얹으면 흰 사각형이 된다. 흰 라운드 칩 안에 넣어 그 칩 자체가 마크
   역할을 하게 한다 — 헤더 색이 또 바뀌어도 안전하다. 칩 크기는 글자가 커져도 고정이다
   (--touch-min 과 같은 "몸의 크기" 규칙). */
.site-brand-mark {
  width: 36px;
  height: 36px;
  flex: none;
  border-radius: var(--radius-chip);
  background: var(--brand-on-ink); /* 초록 헤더 위 흰 칩 — MASTER.md §6 */
  padding: 2px;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
}
/* 검색 진입(M7) — 모든 화면 헤더 같은 위치(WCAG 3.2.6). 48px 터치 타깃. */
.site-search {
  display: flex;
  align-items: center;
  gap: 4px;
  color: var(--brand-on-ink);
  text-decoration: none;
  min-height: var(--touch-min);
  min-width: var(--touch-min);
  padding: 0 10px;
  border-radius: var(--radius-pill);
  transition: background-color var(--dur-fast) var(--ease);
}
.site-search:hover, .site-search:focus-visible { background: rgba(0, 0, 0, 0.16); }
.site-search svg { flex: none; }
.site-search-label { font-size: 0.9rem; font-weight: 600; }

/* 즐겨찾기·보기 설정 진입(brief-T2-11a §4·§5) — 검색과 같은 모양·48px 터치 타깃. */
.site-favorites, .site-settings {
  display: flex;
  align-items: center;
  gap: 4px;
  color: var(--brand-on-ink);
  text-decoration: none;
  min-height: var(--touch-min);
  min-width: var(--touch-min);
  padding: 0 10px;
  border-radius: var(--radius-pill);
  transition: background-color var(--dur-fast) var(--ease);
}
.site-favorites:hover, .site-favorites:focus-visible,
.site-settings:hover, .site-settings:focus-visible { background: rgba(0, 0, 0, 0.16); }
.site-favorites svg { flex: none; }
.site-favorites-label, .site-settings-label { font-size: 0.9rem; font-weight: 600; }
.site-settings-icon { font-weight: 800; font-size: 0.95rem; line-height: 1; }

.time-badge {
  font-size: 0.85rem;
  font-weight: 600;
  /* 🔴 흰 오버레이는 배경을 밝혀 흰 글자 대비를 AA 에도 미달시킨다. 검정 오버레이는
     반대로 어둡혀 유효 배경 #0d442a, 흰 글자 **11.186:1**(AAA)이 된다. */
  background: rgba(0, 0, 0, 0.16);
  padding: 6px 10px;
  border-radius: var(--radius-pill);
  overflow-wrap: anywhere;
  white-space: normal;
}
/* 🔴 지연 안내("공공데이터 반영에 20~40분 걸립니다")가 들어오는 자리.
 * 예전에는 본문 맨 위에 한 줄(약 49px)로 있어서 **시세보다 설명이 먼저 읽혔다**
 * (사용자 지적: "시세를 보여주기 전에 설명이 먼저 부각되고 있는거 같아").
 * 수집 시각과 같은 성격의 메타라 배지 옆이 원래 자리다 — 문구는 한 글자도 지우지 않는다.
 * 알약을 늘리지 않고 배지 뒤에 이어 붙여 좁은 폭에서는 자연스럽게 둘째 줄로 접힌다. */
.time-note {
  font-size: 0.85rem;
  font-weight: 500;
  /* 초록 헤더 위에서 흰색보다 한 단 낮춰 배지가 주가 되게 한다. 🔴 그래도 7:1 아래로는
     안 내려간다 — `#E3EFE7` on `#0F5132` = 7.920:1(실측). 한 단 더 어둡히면(#CFE3D6)
     6.959:1 로 AAA 를 깬다. `AppCssContrastTest` 가 이 값을 지킨다. */
  color: var(--brand-on-ink-dim);
  overflow-wrap: anywhere;
}
.page-title {
  margin: 0;
  padding: 0 16px 12px;
  font-size: 1.3rem;
}

/* ── 장애 배너(S9) ───────────────────────────────────────────────── */
.fault-banner {
  background: #fff3e0;
  color: #7a4a00;
  border-bottom: 1px solid #e0a542;
  padding: 10px 16px;
  font-weight: 700;
}

/* ── 본문 ────────────────────────────────────────────────────────── */
main {
  padding: 16px;
  max-width: 720px;
  margin: 0 auto;
}

.price {
  font-size: 1.45rem; /* 26px 이상 */
  font-weight: 700;
  color: var(--color-text);
  /* 🔴 자릿수가 흔들리면 값끼리 비교가 안 된다 — 숫자는 전부 등폭으로 */
  font-variant-numeric: tabular-nums;
}

/* 🔴 카드는 이제 **배경을 가진다** — 바닥(--color-bg)이 흰색이 아니라서 이 한 줄이
   카드 경계를 만든다. 배경을 빼면 카드가 바닥에 잠겨 "구분이 안 된다"로 되돌아간다. */
.card {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: 16px;
  margin-bottom: 16px;
}

.muted { color: var(--color-text-sub); }

/* 등락 배지 — 텍스트 자체(기호+부호+한글)가 의미를 전달하고, 색은 보조일 뿐이다 */
.change-badge { font-weight: 700; }
.change-badge.up { color: var(--tone-up); }
.change-badge.down { color: var(--tone-down); }
.change-badge.flat { color: var(--tone-flat); }
.change-badge.none { color: var(--tone-none); }

/* ── M10 정보밀도 "한눈에 보기" (density-compact, brief-T2-11a) ─────────
 * 🔴 글자 크기만 줄이지 않는다(브리프 틀린 설계 b) — 카드·행 안쪽 여백, 줄 간격,
 * 목록 사이 간격도 함께 줄인다. 글자 크기 자체는 위 fs-*.density-compact 규칙이
 * 맡는다(여기서는 손대지 않는다).
 * 🔴 숫자(가중평균·등락·상자수)와 기준시각 배지는 절대 숨기지 않는다 — 아래 규칙은
 * "원천 기록값"(최저·최고, 보조 정보)만 감추고, 나머지는 전부 여백·줄간격만 줄인다.
 * 셀렉터가 다른 화면 CSS(m1.css·compare.css 등, web 판 소유 아님)의 클래스명을
 * 겨냥하지만 새 마크업을 만들지 않는다 — `.density-compact .x` 는 클래스 2개라
 * 그 파일의 단일 클래스 규칙(`.x`)보다 명세도가 높아 순서와 무관하게 이긴다. */
html.density-compact body { line-height: 1.4; } /* 기본 1.6 → 1.4, §7.2 하한 아래로는 안 내려간다 */

html.density-compact .card,
html.density-compact .item-spec-card,
html.density-compact .compare-card,
html.density-compact .search-result,
html.density-compact .search-notice,
html.density-compact .m1-row {
  padding: 10px 12px;
  margin-bottom: 8px;
}
html.density-compact .m1-item-summary { padding: 9px 12px 0; }
html.density-compact .m1-item-body { padding: 2px 8px 8px; }
html.density-compact .m1-variety { padding: 7px 9px 8px; margin-top: 6px; }
html.density-compact .m1-item-fold-summary { padding: 0 12px; }
html.density-compact .m1-stats { margin-top: 6px; }
html.density-compact .m1-dist { margin-top: 8px; }
html.density-compact .m1-item-list,
html.density-compact .m1-row-list,
html.density-compact .compare-card-list { gap: 6px; }

/* 품목 상세 "원천 기록값"(최저·최고) — 후속 (26) 으로 **숨김을 걷어냈다**.
 * 예전에는 여기에 `html.density-compact .item-spec-minmax { display: none }` 가 있었다.
 * 그건 접기가 아니라 숨김이라 최저·최고 두 숫자를 다시 볼 방법이 없었고, REQ-M10
 * ("여백·줄간격만 줄인다 · 숫자는 숨기지 않는다")을 정면으로 어겼다. 지금은
 * `ItemSpecCard` 가 한눈에 보기에서 `<details>` 마크업을 내고, 그 모양은 아래
 * `.item-spec-minmax-summary` 규칙이 잡는다(카드 규칙 묶음에 있다).
 * 🔴 여기에 `display: none` 을 다시 넣지 마라 — `AppCssTest` 가 막는다. */

/* 등급 참고선(M1 `.m1-grade-line`) — 숨기지 않고 **여백만** 줄인다.
 * 🔴 예전에는 여기서 `font-size: 0.85em` 도 같이 줄였다. 참고선이 한 줄 문단이던 시절의
 *    규칙이고, 지금은 값·등급·출처가 각자 rem 으로 크기를 갖는 블록이라 컨테이너의 em 은
 *    아무 자식에게도 닿지 않는다(있으나 마나 한 선언이었다). 더 중요한 건 만약 닿았다면
 *    출처 줄(0.85rem)이 0.7225rem = 13px 로 **15px 하한을 깼을** 것이라는 점이다. 뺀다. */
html.density-compact .m1-grade-line { padding: 7px 9px 8px; }
html.density-compact .m1-grade-src { margin-top: 7px; padding-top: 6px; }

/* ── 탭 ──────────────────────────────────────────────────────────── */
/* ── 탭 — 기간("무엇")을 고르는 장치. 시장 세그먼트("어디")와 **다른 모양**이어야 한다.
 * 🔴 예전엔 시장·탭이 똑같은 테두리 알약 4개라 두 축이 한 덩어리로 보였다(사용자 지적).
 *    탭은 밑줄 + 부제, 시장은 채움 세그먼트(m1.css)로 갈랐다.
 * 🔴 밑줄만으로 현재 탭을 알리지 않는다 — 글자색(--brand-ink)·굵기도 같이 바뀐다.
 *    색각 이상에서 주황 밑줄만 남으면 구분이 안 된다(WCAG 1.4.1 색에만 의존 금지). */
.tabs {
  display: flex;
  gap: 22px;
  margin: 0 0 12px;
  padding: 0 2px;
  border-bottom: 1px solid var(--color-border);
}
.tabs a {
  min-height: var(--touch-min);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
  padding: 2px 0 6px;
  margin-bottom: -1px;             /* 컨테이너 밑줄과 겹쳐 한 줄로 보이게 */
  border-bottom: 3px solid transparent;
  text-decoration: none;
  color: var(--color-text-sub);
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.tabs a > .tab-label { font-weight: 700; }
/* 부제("진행 중"·"09-10") — 두 탭의 차이가 누르기 전에 읽히게 한다. 0.85rem = 15.3px 하한 */
.tabs a > .tab-sub { font-size: 0.85rem; line-height: 1.2; }
.tabs a:hover { color: var(--brand-ink); }
.tabs a[aria-current="page"] {
  color: var(--brand-ink);               /* 카드 9.361 · 바닥 8.663:1 */
  border-bottom-color: var(--accent-fill); /* 🔴 채움으로만 — 이 주황은 글자가 될 수 없다 */
}

.empty-state {
  padding: 24px 16px;
  text-align: center;
  color: var(--color-text-sub);
}

/* 날짜 이동 — 스와이프 대체 단일 탭 버튼(WCAG 2.5.7) */
.day-nav { display: flex; gap: var(--gap-min); align-items: center; justify-content: center; margin: 16px 0; flex-wrap: wrap; }
.day-nav button, .day-nav a, .day-nav-disabled {
  min-height: var(--touch-min);
  min-width: var(--touch-min);
  padding: 0 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
  background: var(--color-card-bg);
  /* 🔴 밑줄을 쓰지 않는다(사용자 지시 2026-09-12) — 이미 테두리·면·48px 상자가
     "누르는 것"이라고 말한다. 밑줄까지 있으면 장식이 두 겹이라 시끄럽다. */
  text-decoration: none;
}
/* 최신일이면 "다음"은 눌러도 반응 없는 링크로 남기지 않는다 — 비활성 표시 + 이유 텍스트 */
.day-nav-disabled {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--color-text-sub);
  /* 🔴 중립 회색(#f5f5f5)이 아니라 바닥 토큰 — 비활성은 바닥에 잠기는 것이 맞고,
     초록빛 바닥 위에서 중립 회색은 탁한 얼룩으로 뜬다. 보조 글자 8.201:1(MASTER §1.2). */
  background: var(--color-bg);
}

/* ── 품목 상세(M3) ───────────────────────────────────────────────── */
.item-header { margin-bottom: 8px; }
/* 🔴 제목과 즐겨찾기를 한 줄에(사용자 지시 2026-09-12) — 버튼이 제 줄을 통째로 먹어
   시세가 한 줄만큼 밀려 있었다. 제목이 길면 `wrap` 으로 버튼이 아래로 내려간다. */
.item-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gap-min);
  flex-wrap: wrap;
}
.item-title-row .fav-toggle { margin: 0; flex: none; }
/* 🔴 `flex: 1 1 auto` 면 제목이 남은 폭을 **다 먹어** 버튼이 다음 줄로 밀린다(실측).
   `0 1 auto` 로 제 글자만큼만 차지하게 해야 옆에 붙는다. 제목이 정말 길면 그때 wrap 된다. */
.item-title { margin: 0; font-size: 1.4rem; flex: 0 1 auto; min-width: 0; }
/* 확정일 — 날짜만 굵게. 회색 줄 안에서 날짜가 먼저 잡힌다(사용자 지시) */
.item-biz-date { color: var(--color-text); font-weight: 700; white-space: nowrap; }

/* 🔴 상단 묶음을 카드 하나로(사용자 지시 2026-09-13 "가독성 있도록", §10.20).
   바닥이 #F4F7F2 라 배경 없는 묶음은 바닥에 잠긴다 — `.card` 가 배경을 준다. */
.item-head { margin-bottom: 16px; }
.item-head-meta { color: var(--color-text-sub); margin: 6px 0 0; }
/* 총 상자수 — 이 화면에서 제목 다음으로 큰 값이다. 회색 보조글자였던 것을 본문색·굵게로
   올렸다(사용자가 "가독성"이라고 한 자리).
   🔴 `white-space: nowrap` 을 쓰면 안 된다 — 이 문장은 "전체 거래 78,910상자(상위 200개 규격
      합)" 처럼 길어서 360px 에서 **문서가 18~134px 가로로 넘쳤다**(6조합 실측 2026-09-13).
      숫자만 보호하면 된다: `overflow-wrap: normal` 로 body 의 `anywhere` 상속을 끊으면
      `78,910상자` 같은 덩어리는 통째로 유지되고, 줄바꿈은 띄어쓰기에서만 일어난다
      (`word-break: keep-all` 과 짝). 값 칸의 nowrap 규칙(§10.9)은 **짧은 숫자 칸** 이야기다. */
.item-head-qty {
  margin: 4px 0 0;
  font-weight: 700;
  overflow-wrap: normal;
}
/* 날짜 달력 — 이전·다음 버튼을 대신한다. 라벨·입력·버튼이 한 줄, 좁으면 접힌다. */
.datepick {
  display: flex;
  align-items: center;
  gap: var(--gap-min);
  flex-wrap: wrap;
  margin: 12px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--color-border-soft);
}
.datepick-label { font-weight: 700; }
/* 🔴 `min-height` 은 48px(터치 타깃), 폭 문턱은 **rem** 이다 — px 문턱을 쓰면 큰 글씨에서
   달력 입력이 제 글자를 못 담는다(§10.12 에서 같은 실수를 값 칸에서 했다). */
.datepick-input {
  min-height: var(--touch-min);
  flex: 1 1 11rem;
  min-width: 0;
  padding: 0 10px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
  background: var(--color-card-bg);
  color: var(--color-text);
}
.datepick-go { flex: none; }
/* 자료 없는 날을 골랐을 때 — 가장 가까운 경매일로 가는 길 */
.item-nearest { margin: 8px 0 0; }
.item-nearest a { min-height: var(--touch-min); display: inline-flex; align-items: center; font-weight: 700; }

/* M3 → M4(추이)·M2(비교) 진입 버튼 — 48px 터치 타깃(brief-T2-9d-m3) */
.item-entry-links { display: flex; flex-wrap: wrap; gap: var(--gap-min); margin: 0 0 16px; }
.item-entry-links a {
  min-height: var(--touch-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
  background: var(--color-card-bg);
  text-decoration: none;
  color: var(--color-text);
  font-weight: 600;
  font-size: 0.9rem;
}

.item-corp-tabs { display: flex; flex-wrap: wrap; gap: var(--gap-min); margin: 0 0 16px; }
.item-corp-tabs a {
  min-height: var(--touch-min);
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  text-decoration: none;
  color: var(--color-text);
  font-weight: 600;
  font-size: 0.9rem;
}
.item-corp-tabs a { background: var(--color-card-bg); transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.item-corp-tabs a[aria-current="page"] { border-color: var(--brand-ink); color: var(--brand-ink); background: var(--brand-soft); } /* 카드 9.361 · 칩 8.215:1 */

.item-spec-list { list-style: none; margin: 0; padding: 0; }
.item-spec-card {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: 16px;
  margin-bottom: 12px;
}
.item-spec-head { display: flex; justify-content: space-between; gap: var(--gap-min); flex-wrap: wrap; }
.item-spec-name { font-weight: 700; font-size: 1.05rem; }
.item-spec-sub { margin-top: 2px; }
.item-spec-price { display: flex; align-items: baseline; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.item-spec-minmax { margin-top: 4px; font-size: 0.85rem; }
/* 🔴 최저·최고를 **각각 한 덩어리**로 세운다(사용자 지적 2026-09-12: "이 줄이 모두 한 줄로
   되어 있어서 최고가 밀리거나 또는 당겨지거나 규칙이 없어").
   예전에는 세 조각이 한 문장이라 카드마다 끊기는 자리가 달랐다. 이제 덩어리가 `nowrap`
   이고 문턱이 rem 이라, 넓으면 나란히·좁으면 통째로 아래로 — 어느 쪽이든 규칙이 같다.
   🔴 `<details>`(한눈에 보기) 자체에는 grid 를 주지 않는다 — summary/body 구조가 깨진다.
      그래서 `:not(.item-spec-minmax-fold)` 로 가르고, 접힌 쪽은 body 에 같은 격자를 준다. */
.item-spec-minmax:not(.item-spec-minmax-fold),
.item-spec-minmax-body {
  display: grid;
  /* 🔴 문턱 8rem — 9rem 이면 400px 카드 안쪽(327px)에서 2칸에 **12px 모자라** 한 칸으로
     떨어졌고, 카드가 오히려 길어졌다(실측 2026-09-12: 페이지 2231 → 3016px).
     8rem 이면 2*144+10 = 298 ≤ 327 로 나란히 서고, 루트가 21px 이상이면 알아서 쌓인다. */
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 2px 10px;
}
.item-spec-minmax-title { grid-column: 1 / -1; }
.item-spec-minmax-pair { white-space: nowrap; overflow-wrap: normal; }
/* 한눈에 보기에서만 나오는 `<details>` 모양(마크업은 `ItemSpecCard::minMaxHtml`).
 * 🔴 글자 크기를 새로 주지 않는다 — 위 `.item-spec-minmax` 의 0.85rem 을 그대로 물려받는다
 *    (루트 최소 112.5% 에서 15.3px, `MinFontSizeCssTest` 의 15px 하한 바로 위다).
 * 🔴 `<summary>` 는 누르는 자리라 48px 를 준다(ACC-B1, 36조합 미달 0건 게이트). `.m1-rows-summary`
 *    와 같은 방식이다 — `display:flex` 로 기본 `list-item` 마커를 떼고, 웹킷 마커도 따로 지우고,
 *    꺾쇠를 **오른쪽 끝** `::after` 로 그린다(2026-09-18, 아래 참조).
 * 🔴 `flex-wrap: wrap` 을 쓰지 않는다 — flex 는 줄이기보다 줄 나누기를 먼저 해서 마커만 있는
 *    빈 줄이 생긴다(홈에서 카드마다 23.5px 씩 붙어 폴드를 넘겼던 그 회귀다, §10.8). */
.item-spec-minmax-summary {
  display: flex;
  align-items: center;
  gap: 4px;
  min-height: var(--touch-min, 48px);
  cursor: pointer;
  list-style: none;
  overflow-wrap: anywhere;
}
.item-spec-minmax-summary::-webkit-details-marker { display: none; }
/* 🔴 왼쪽 `▸` → **오른쪽 끝 꺾쇠**(사용자 지시 2026-09-18, M1 접힘줄과 같은 처방).
   원문(09-18 오전): "앞에 ... 블릿은 그냥 범례로 볼 수가 있어, 클릭을 유도하지 않아
   사용자가 하위 내용을 확인하지 못함". 그때 `m1.css` 의 접힘줄 둘만 고쳤고 이 줄이
   남아 있었다(MASTER.md §4.12 가 "확인 필요"로 달아 둔 자리) — 같은 날 오후 지시로 닫는다.
   🔴 `::before` 를 **옮긴** 것이지 더한 것이 아니다 — flex 항목 수도 gap 수도 그대로다.
   🔴 모양은 글자가 아니라 `--chev-mask`(app.css `:root`)가 그린다. M1 의 세 꺾쇠와 같은
   그림·같은 크기·같은 색이라 화면이 달라도 "누르면 열린다"가 한 가지 모양으로 읽힌다. */
.item-spec-minmax-summary::after {
  content: "";   /* 읽힐 글자는 없다 — <summary> 가 이미 펼침 상태를 알린다 */
  flex: none;
  margin-left: auto;
  display: inline-block;          /* inline 에는 transform 이 안 먹는다 */
  width: var(--chev-w);
  height: var(--chev-h);
  background-color: var(--brand-ink);
  -webkit-mask-image: var(--chev-mask);
          mask-image: var(--chev-mask);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-size: contain;
          mask-size: contain;
  transition: transform var(--dur-fast) var(--ease);
}
.item-spec-minmax-fold[open] > .item-spec-minmax-summary::after { transform: rotate(90deg); }
/* 글자 덩어리가 줄어들 수 있어야 한 줄에 남는다(min-width 기본값 auto 면 안 줄어든다). */
.item-spec-minmax-label { flex: 1 1 auto; min-width: 0; }
.item-spec-minmax-body { padding: 2px 0 4px; }
/* 🔴 기준 문구가 제 줄, 등락이 다음 줄(사용자 지시 2026-09-12) — "무엇과 비교했나 →
   어떻게 됐나" 순서로 읽힌다. 예전엔 한 배지 안 한 문장이라 아무 데서나 갈렸다. */
.item-spec-change { margin-top: 8px; }
.item-spec-basis {
  display: block;
  font-size: 0.85rem;
  color: var(--color-text-sub);
  margin-bottom: 2px;
}
.item-spec-corp { margin-top: 6px; font-weight: 600; }

.item-origins-section { margin-top: 24px; }
.item-origins { list-style: none; margin: 0; padding: 0; }
.item-origins li {
  display: flex;
  justify-content: space-between;
  gap: var(--gap-min);
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border);
}

/* ── 표 — 컨테이너 내부에서만 가로 스크롤(360px 대응) ─────────────── */
/* 표는 컨테이너 안에서만 가로 스크롤한다(brief-T2-7b §1 예외) — 그래서 셀은 줄바꿈 대신
   가로 스크롤을 택한다. 줄바꿈을 허용하면 200% 확대에서 "점검 여부"가 "점/검/여/부"처럼
   한 글자씩 쪼개져 오히려 더 읽기 어려워진다. */
.tablewrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; }
th, td { padding: 8px; text-align: left; border-bottom: 1px solid var(--color-border); white-space: nowrap; }

/* ── 버튼 ────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  min-width: var(--touch-min);
  padding: 0 20px;
  border-radius: 10px;
  border: none;
  background: var(--brand-ink); /* 브랜드 빨강보다 어두운 톤 — 7:1(AAA), brief-T2-7b §3 */
  color: var(--brand-on-ink);
  font-weight: 700;
  font-size: 1.05rem;
  cursor: pointer;
  text-decoration: none;
}
/* 보조 버튼(상세 이동 등) — 배경 대신 테두리. 글자색은 버튼과 같은 어두운 톤(7:1 유지) */
.btn-ghost {
  background: var(--color-card-bg);
  color: var(--brand-ink);
  border: 2px solid var(--brand-ink);
}

/* ── 검색(M7) ────────────────────────────────────────────────────── */
.search-form { margin-bottom: 16px; }
.search-label { display: block; font-weight: 700; margin-bottom: 8px; }
.search-row { display: flex; flex-wrap: wrap; gap: var(--gap-min); }
.search-row input[type="text"] {
  flex: 1 1 200px;
  min-width: 0;
  min-height: var(--touch-min);
  padding: 0 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
  background: var(--color-card-bg);
  font-size: 1rem;
}
.search-row select {
  min-height: var(--touch-min);
  padding: 0 8px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-chip);
  background: var(--color-card-bg);
  font-size: 1rem;
}
.search-notice {
  background: var(--color-card-bg);
  padding: 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  margin-bottom: 16px;
}
.search-notice-error { border-color: var(--tone-up); }
.search-results { list-style: none; margin: 0; padding: 0; }
.search-result {
  background: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: 16px;
  margin-bottom: 12px;
}
.search-result-name { font-size: 1.2rem; font-weight: 700; }
.search-result-note { margin-top: 4px; }
.search-result-actions { display: flex; flex-wrap: wrap; gap: var(--gap-min); margin-top: 12px; }
.search-result-actions .btn, .search-result-actions .btn-ghost {
  min-height: var(--touch-min);
  padding: 0 16px;
  font-size: 0.95rem;
}

/* ── 푸터 — 데이터 출처·용어 안내 · 문의, 오늘얼마 + dayvalue.kr ──── */
.site-footer {
  border-top: 1px solid var(--color-border);
  padding: 20px 16px;
  text-align: center;
}
.site-footer nav {
  display: flex;
  justify-content: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.site-footer nav a {
  min-height: var(--touch-min);
  display: inline-flex;
  align-items: center;
  /* 🔴 밑줄 제거(사용자 지시 2026-09-12). 대신 브랜드 초록 + 굵게로 링크임을 말한다 —
     바닥 8.663:1(AAA). 밑줄만 지우고 색을 본문색으로 두면 링크로 안 읽힌다. */
  color: var(--brand-ink);
  font-weight: 700;
  text-decoration: none;
}
.site-footer-brand { color: var(--color-text-sub); font-weight: 700; margin: 0; }
.site-footer-brand small { font-weight: 400; }

/* ── 화면을 떠나는 버튼 vs 필터를 넓히는 텍스트 ──────────────────────
 * 🔴 사용자 결정 2026-09-12(2차): 품목 상세로 가는 것은 **추이·비교 둘 다 버튼**이다.
 *    한때 둘 다 텍스트로 맞췄다가("가격 추이에서는 텍스트, 여기서는 버튼 일괄성이 없음"),
 *    실제 화면을 보고 **버튼 쪽으로** 통일하기로 바꿨다. 두 화면 모두 `.btn-ghost` 를
 *    같이 달아 **같은 부품**을 쓴다 — 한쪽만 바뀔 자리를 만들지 않는다.
 * 🔴 `.trend-link`(품종·거래구분 전체로 보기)는 **필터를 넓히는 안내**라 텍스트로 남긴다.
 *    화면을 떠나는 행동과 성격이 다르고, 필터 칩 옆에서 버튼이 하나 더 늘면 무엇이
 *    주된 행동인지 흐려진다. 밑줄은 쓰지 않는다(사용자 지시) — 색·굵기·▸ 로 말한다. */
.trend-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: var(--touch-min);
  padding: 0 2px;
  color: var(--brand-ink);
  font-weight: 700;
  text-decoration: none;
}
.trend-link::before { content: "▸"; flex: none; }

/* 떠나는 버튼 — **머리 바로 아래**에 온다(사용자 지시 2026-09-18 "올리고").
   🔴 09-12 2차 결정("등급을 눌러 아래 값을 보는" 흐름을 가로막지 마라)은 그대로다 —
   그건 **등급 고르기와 값 사이**를 금지한 것이고, 여기는 등급 고르기보다 위다.
   🔴 `.btn-ghost` 는 색만 주는 **덧붙임**이다 — 크기·여백은 `.btn` 에 있는데 이 두 링크는
   `.btn` 을 달지 않는다. 그래서 48px 터치 타깃(ACC-B1)을 여기서 직접 준다.
   안 주면 테두리만 있는 납작한 상자가 된다(실측: min-height 0). */
/* 🔴 `.trend-nav-links` 는 비교 화면 `.compare-nav-links` 와 **같은 자리·같은 모양**이다
   (사용자 지시 2026-09-13: 추이도 버튼을 아래로). 한 줄에 여러 개가 오므로 감싸고 띄운다. */
/* 🔴 위 여백 20 → **아래 여백 16**. 묶음이 머리 다음으로 올라가 뒤에 오는 것이
   필터·값이라, 위를 띄우면 머리에서 떨어지고 아래가 붙어 버린다(자리를 옮기면 여백도
   같이 뒤집어야 한다 — 안 하면 "어디에 붙은 버튼인지"가 뒤바뀐다).
   `.trend-back` 은 여전히 아래에 남는 되돌아가기라 옛 값을 지킨다. */
.compare-nav-links, .trend-nav-links { margin: 0 0 16px; }
.trend-back { margin: 20px 0 0; }
.trend-nav-links { display: flex; flex-wrap: wrap; gap: var(--gap-min); }
.compare-nav-link, .trend-nav-link, .trend-back-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch-min);
  padding: 0 16px;
  border-radius: var(--radius-chip);
  font-weight: 700;
  text-decoration: none;
}

/* ── 하단 광고 자리 — 고정 높이, 레이아웃 밀림 방지(CLS) ──────────── */
.ad-slot {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--ad-slot-height);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg); /* 🔴 중립 회색이 아니라 바닥 토큰 — 자리표시는 바닥에 잠긴다 */
  color: var(--color-text-sub);
  border-top: 1px solid var(--color-border);
  /* 🔴 0.8rem 이었다 — 루트 18px(가장 작은 조합)에서 14.4px 로 렌더돼 §9.4 [A] 의 15px 하한을
     깼다(메인 실측: 9화면 x 360/393/430 폭 전부에서 이게 최소 글자였다). `aria-hidden` 자리표시라
     `AppCssTest` 의 최소 글자 검사가 일부러 제외하고 있었는데, 제외해도 **사람 눈에는 보이는 글자**다.
     px 로 못 박는 길은 막혀 있다 — OS·브라우저 글꼴 크기 설정이 안 먹는다(CLAUDE.md 실측,
     `test_글자_크기가_px로_고정돼_있지_않다`). 공개 화면의 다른 보조 글자와 같은 0.85rem 으로 맞춘다
     (= 18 x 0.85 = 15.3px). 광고 자리의 **높이**(135px, AdMob Large 적응형)는
     `--ad-slot-height` 그대로다 — 값의 근거는 `:root` 의 그 선언 주석에 있다. */
  font-size: 0.85rem;
}

/* ── 보기 설정(M6·M10, brief-T2-11a §4) ─────────────────────────────── */
.settings-form { display: flex; flex-direction: column; gap: 20px; }
.settings-group { background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-card); padding: 12px 16px 16px; margin: 0; }
.settings-legend { font-weight: 700; padding: 0 4px; }
.settings-option {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--touch-min);
  padding: 8px 4px;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
}
.settings-option:last-child { border-bottom: none; }
.settings-option input[type="radio"] { width: 22px; height: 22px; flex: none; }
.settings-option-text { display: flex; flex-direction: column; gap: 2px; }
.settings-option-label { font-weight: 700; }
.settings-option-preview { font-size: 0.85rem; }
.settings-save { align-self: flex-start; }

/* ── 보기 설정: **고르는 즉시** 그 크기로 보인다(사용자 지시 2026-09-12) ──────
 * 예전에는 라디오를 눌러도 아무 변화가 없고 `저장`을 눌러 되돌아와야 크기를 알 수 있었다.
 * "아주 크게가 얼마나 큰지"를 모르는 채로 고르는 셈이었다.
 *
 * 🔴 JS 없이 `:has()` 만으로 한다. 이 화면은 JS 를 쓰지 않고(공개 화면 전체가 그렇다),
 *    라디오는 `id` 가 고정돼 있다(`SettingsForm::radio`).
 * 🔴 `html.fs-*`(저장된 값, 명세도 0,1,1)보다 세야 하므로 `html:has():has()`(0,2,1)로 쓴다.
 * 🔴 루트 %는 위 3x2 조합표와 **같은 값**이어야 한다 — 여기만 다른 값을 쓰면 미리보기가
 *    거짓말이 된다. `SettingsLivePreviewCssTest` 가 두 곳이 같은지 검사한다.
 * 🔴 `:has()` 를 모르는 구형 웹뷰에서는 규칙이 통째로 무시되고 예전처럼 저장 뒤 적용된다
 *    — 기능이 사라지는 게 아니라 즉시성만 없다. 그래서 안내 문구도 `@supports` 로 가린다.
 * ⛔ `font-size` 에 transition 을 걸지 않는다 — 매 프레임 전체 레이아웃을 다시 계산한다. */
html:has(#settings-fs-m:checked):has(#settings-density-comfortable:checked) { font-size: 112.5%; }
html:has(#settings-fs-l:checked):has(#settings-density-comfortable:checked) { font-size: 131.25%; }
html:has(#settings-fs-xl:checked):has(#settings-density-comfortable:checked) { font-size: 150%; }
html:has(#settings-fs-m:checked):has(#settings-density-compact:checked) { font-size: 112.5%; }
html:has(#settings-fs-l:checked):has(#settings-density-compact:checked) { font-size: 112.5%; }
html:has(#settings-fs-xl:checked):has(#settings-density-compact:checked) { font-size: 125%; }

/* 안내 문구는 실제로 즉시 반영되는 브라우저에서만 보인다 — 안 되는데 "바로 바뀝니다"라고
   적으면 그게 거짓말이다. */
.settings-live { display: none; }
@supports selector(html:has(#x:checked)) {
  .settings-live {
    display: block;
    margin: 0 0 14px;
    padding: 10px 12px;
    background: var(--brand-soft);
    color: var(--brand-ink);        /* 8.215:1 — 실측 */
    border-radius: var(--radius-chip);
    font-size: 0.85rem;
    font-weight: 700;
  }
}

/* 선택된 보기 설정 항목을 눈에 띄게 — 지금은 라디오 점 하나뿐이라 뭘 골랐는지 흐릿하다. */
.settings-option:has(input:checked) {
  background: var(--brand-soft);
  border-radius: var(--radius-chip);
}
.settings-option:has(input:checked) .settings-option-label { color: var(--brand-ink); }

/* ── 동작 — docs/MASTER.md §5 ────────────────────────────────────────
 * 🔴 `transition: all` 을 쓰지 않는다(바꿀 생각 없던 속성까지 따라 움직인다).
 * 🔴 `height`·`width` 를 애니메이션하지 않는다 — 매 프레임 레이아웃을 다시 계산한다.
 *    펼침은 `<details>` 안쪽 내용의 opacity + 6px 올리기로만 표현한다.
 * 🔴 스크롤 연동(animation-timeline)·바운스·일래스틱·숫자 카운트업은 쓰지 않는다.
 *    대상이 고령 사용자와 저사양 웹뷰이고, 시세 숫자가 움직이면 잘못 읽힌다.
 * 🔴 정지 상태에서 모든 글자가 이미 보인다 — opacity:0 으로 대기시키는 요소가 없다. */
/* 🔴 누르는 것 **전부**가 이 목록에 있어야 한다(MASTER.md §4.5 5가지 상태).
   서브 화면(trend·compare·favorites·source)의 칩·접기 머리·버튼이 빠져 있어
   같은 장치가 화면마다 다르게 반응했다 — 여기서 한 곳에 모은다.
   `.compare-filter-chip`·`.compare-nav-link` 는 마크업에서 `.btn-ghost` 를 함께 달아
   이미 포함된다(lib/View/Compare/CompareFilters.php). */
.btn, .btn-ghost, .tabs a, .item-corp-tabs a, .item-entry-links a, .day-nav a,
.trend-chip, .trend-link,
.trend-grade > summary, .trend-big > summary,
.compare-grade-details > summary,
.item-spec-minmax-summary,
.fav-toggle-btn, .fav-remove,
.source-origin-list a {
  transition: background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
/* 누름은 한 단계뿐이다. hover 는 보조다 — 대상이 터치다. */
.btn:active, .btn-ghost:active, .tabs a:active,
.item-corp-tabs a:active, .item-entry-links a:active, .day-nav a:active,
.trend-chip:active, .trend-link:active,
.trend-grade > summary:active, .trend-big > summary:active,
.compare-grade-details > summary:active,
.item-spec-minmax-summary:active,
.fav-toggle-btn:active, .fav-remove:active,
.source-origin-list a:active {
  transform: scale(0.985);
}
/* hover 는 보조지만 있어야 한다 — 데스크톱에서 같은 칩이 어떤 화면에서는 반응하고 어떤
   화면에서는 죽어 있으면 눌리는 것인지 읽히지 않는다.
   🔴 `@media (hover: hover)` 로 가둔다 — MASTER.md §4.5 "hover 는 보조다, 대상이 터치다".
   터치 브라우저 다수가 탭 뒤 `:hover` 를 **붙잡고 있어서**, 이걸 안 가두면 `<summary>` 를
   한 번 눌러 펼친 뒤 칩이 초록으로 **눌린 채 남아** "선택된 것"처럼 읽힌다.
   focus-visible 은 키보드 전용이라 이 안에 두지 않는다 — 터치에서도 살아 있어야 한다. */
@media (hover: hover) {
  .trend-chip:hover,
  .trend-grade > summary:hover, .trend-big > summary:hover,
  .compare-grade-details > summary:hover,
  .fav-toggle-btn:hover,
  .fav-remove:hover { background: var(--brand-soft); }
}
.trend-chip:focus-visible,
.fav-toggle-btn:focus-visible,
.fav-remove:focus-visible { background: var(--brand-soft); }
.btn:hover, .btn:focus-visible { background: #0B3F27; } /* 흰 글자 11.6:1 — 더 어둡게만 간다 */
.btn-ghost:hover, .btn-ghost:focus-visible { background: var(--brand-soft); }

/* 펼침 — `<details>` 가 열릴 때 내용만 살짝 올라온다. 높이는 건드리지 않는다. */
details[open] > .m1-item-body,
details[open] > .m1-row-list,
details[open] > .item-spec-minmax-body {
  animation: dv-open var(--dur-open) var(--ease) both;
}
@keyframes dv-open {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* 🔴 동작 줄이기에서는 **최종 상태로 즉시** 선다 — 사라지지 않는다.
   `animation: none` 만 주면 `both` 로 고정돼 있던 최종값도 풀리므로 opacity 를 되돌린다. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  details[open] > .m1-item-body,
  details[open] > .m1-row-list,
  details[open] > .item-spec-minmax-body { opacity: 1; transform: none; }
  .btn:active, .btn-ghost:active, .tabs a:active,
  .item-corp-tabs a:active, .item-entry-links a:active, .day-nav a:active,
  .trend-chip:active, .trend-link:active,
  .trend-grade > summary:active, .trend-big > summary:active,
  .compare-grade-details > summary:active,
  .item-spec-minmax-summary:active,
  .fav-toggle-btn:active, .fav-remove:active,
  .source-origin-list a:active { transform: none; }
}

/* ── 반응형: 360px 소형 화면(기획서.md §8.3) ──────────────────────── */
@media (max-width: 390px) {
  .site-header-row { padding: 10px 12px; }
  main { padding: 12px; }
}
/* 🔴 브랜드·검색·즐겨찾기·보기 가 한 줄에 안 들어간다 — 버튼은 그대로 두고 시각 라벨만 숨긴다
   (brief-T2-11a §4). `aria-label` 이 각 링크에 남아 스크린리더는 계속 "품목·품종 검색"·"즐겨찾기"·
   "보기 설정…" 을 읽는다. 처음엔 390px 이하만 숨겼는데 실서버 400px 캡처에서 "보기" 가 혼자
   둘째 줄로 떨어졌다(메인 리뷰) — 흔한 폰 폭 393·412·430px 가 전부 그 사이라 480px 이하로 넓혔다. */
@media (max-width: 480px) {
  .site-search-label, .site-favorites-label, .site-settings-label { display: none; }
}
/* 🔴 후속 (28) — 글자 크기 `아주 크게`(150%) + 뷰포트 520px 에서 헤더 링크가 두 줄이 됐다
 * (이전 세션 실측). 480px 문턱은 루트 112.5%(18px) 를 기준으로 잡은 값이고, 라벨 글자 폭은
 * 루트에 비례해 늘어난다 — 루트가 125%·131.25%·150% 로 커지면 같은 폭에서 더는 안 맞는다.
 * 미디어쿼리의 `em` 은 브라우저 기본값(16px)에만 걸리고 `html` 의 % 를 따라오지 않으므로
 * 문턱을 하나만 넓히는 대신 **루트 크기 단계별로** 문턱을 나눈다.
 *
 * 한 줄 소요 폭(선언값 + Layout::header 의 실제 글자, 한글 1.0em 기준 계산):
 *   | 루트            | 라벨 보임 | 라벨 숨김 | 이 파일의 문턱 |
 *   |---|---|---|---|
 *   | 112.5% (18px)   | 442px     | 323px     | 480px  |
 *   | 125%   (20px)   | 467px     | 332px     | 540px  |
 *   | 131.25%(21px)   | 480px     | 337px     | 540px  |
 *   | 150%   (24px)   | 518px     | 350px     | 600px  |
 * 🔴 문턱을 실측 지점(520)에 딱 맞추지 않는다 — 계산상 150% 소요 폭은 518px 로 520 에
 *    "2px 차이로 들어가는" 값인데 실제로는 두 줄이었다. 즉 이 계산은 **실물보다 낙관적**이다
 *    (스크롤바 폭·글꼴 실제 자족 등). 그래서 각 문턱에 15% 안팎의 여유를 둔다. 480->520 으로
 *    문턱 하나만 넓히는 설계(틀린 설계 D-1)는 반대로 **기본 글자 크기에서 481~520px 의 라벨을
 *    괜히 지우면서**(계산상 442px 면 충분하다) 521px 이상의 150% 는 그대로 둔다.
 * 라벨을 지워도 `aria-label` 은 각 링크에 남아 스크린리더는 계속 읽는다. 숨김 상태의 소요 폭은
 * 가장 큰 루트에서도 350px 라 360px 화면까지 한 줄로 들어간다. */
@media (max-width: 540px) {
  html.fs-xl.density-compact .site-search-label,
  html.fs-xl.density-compact .site-favorites-label,
  html.fs-xl.density-compact .site-settings-label,
  html.fs-l:not(.density-compact) .site-search-label,
  html.fs-l:not(.density-compact) .site-favorites-label,
  html.fs-l:not(.density-compact) .site-settings-label { display: none; }
}
@media (max-width: 600px) {
  html.fs-xl:not(.density-compact) .site-search-label,
  html.fs-xl:not(.density-compact) .site-favorites-label,
  html.fs-xl:not(.density-compact) .site-settings-label { display: none; }
}