/* nb-readability.css — NB/YN 공용 가독성 오버레이 (2026-08-11)
 *
 * 왜 오버레이인가: NB 25사이트·YN 11사이트의 CSS 가 전부 다르다(고유 톤).
 *   기존 파일을 고치거나 복사하면 사이트별 디자인이 깨진다. 그래서 **덮어쓰지 않고
 *   맨 뒤에 얹는 얇은 레이어**로 "12px 미만 글자"만 해소한다.
 *
 * 근거(라이브 실측):
 *   전수감사에서 사이트당 12px 미만 글자 151~266개 → 사장님 "글씨가 번지고 안 보인다"의 실체.
 *   · nb.mhna98.com(모바일 375): 201개 → **0개**
 *   · yn6.mhna98.com(모바일 375): 266개 → **0개**
 *   두 경우 모두 가로스크롤 미발생(scrollWidth 375 유지), NB패밀리 카드 높이 70px 정상.
 *
 * ⚠️ 선택자 주의(실측으로 배운 것):
 *   ① .nbf-logo / .nbf-txt 는 **자식(i, span)이 자체 font-size** 를 가진다 →
 *      부모만 지정하면 96개가 남는다. 그래서 자손까지 함께 지정한다.
 *   ② 사이트마다 라벨 클래스명이 다르다(deal-cat-tag, sc-badge, fs-free, latest-badge,
 *      rank-change, ad-tag, src-tag, aff-desc, aff-disclosure …). 개별 열거로는 못 끝난다 →
 *      **배지/태그/라벨 계열 부분일치([class*="-badge"] 등)** 로 안전망을 둔다.
 *      본문·제목 클래스는 건드리지 않으므로 레이아웃 위험이 없다(실측 확인).
 *
 * 접근성 기준: 본문 가독 최소 13px, 모바일 14px, 보조 라벨 12.5px(모바일 13px).
 */

/* ── 브랜드/로고 ── */
.brand-text span,
.brand-text small { font-size: 13px !important; line-height: 1.45 !important; }

/* ── NB 패밀리 추천 카드(전 사이트 공통 컴포넌트) ── */
.nbf-logo, .nbf-logo i, .nbf-logo * { font-size: 12.5px !important; }
.nbf-txt, .nbf-txt span, .nbf-txt * { font-size: 13px !important; line-height: 1.4 !important; }
.nbf-go { font-size: 13px !important; }

/* ── 섹션 키커·통계 보조문 ── */
.blog-kicker,
.active-tool-kicker,
.hero-stat-card small { font-size: 13px !important; }

/* ── 배지·태그·라벨·고지문 계열(사이트별 클래스명 차이를 부분일치로 흡수) ── */
[class*="-badge"],
[class*="-tag"],
[class*="-flag"],
[class*="-kicker"],
[class*="-eyebrow"],
[class*="-disclosure"],
[class*="-desc"],
[class*="-cat"],
[class*="-kw"],
[class*="-change"],
[class*="-meta"],
.src-badges, .src-badges *,
.fs-free,
.deal-tag,
.sc-badge,
/* 2026-08-11 추가(yn11 실측 잔여 11건): 고유 라벨 + 공통 소형 태그 */
.lang-caret,
.ad-label,
.card-soon,
.paypal-or,
[class*="-popular"],
sup, sub,
small { font-size: 12.5px !important; line-height: 1.35 !important; }

/* ── 브랜드색 라벨의 명도대비 보정 (2026-08-12 추가) ─────────────────────────
 * 사장님 지적: "글자색 때문에 안 보이는 데가 몇 개 있다".
 * 라이브 실측(WCAG 명도대비, 흰 배경 위 단색 텍스트만 집계):
 *   .promo-eyebrow  rgb(253,164,175)  1.89   ← 사실상 안 읽힘
 *   .promo-cta      amber  #f59e0b    2.15 / green 2.28 / teal 2.49 / orange 2.80
 *   .deal-tag       #ff5b59 2.81 · #ff2d55 3.36
 *   .deal-mini      #fe2c55 3.68      .channel-cta 흰글자 on #ff0033 3.96
 *   (기준: 본문급 13px 이하 텍스트는 4.5:1 필요)
 *
 * 원인: 슬라이드/제휴 카드가 각자의 브랜드색을 **글자색**으로 그대로 쓴다
 *      (.promo-slide style="--accent:#f59e0b" → .promo-cta{color:var(--accent)}).
 *      밝은 브랜드색(앰버·라임·로즈·시안)은 흰 배경에서 읽히지 않는다.
 *
 * 처방: 색상 코딩(브랜드 구분)은 살리고, 같은 색조를 어둡게 섞어 대비만 확보한다.
 *      ⚠️ color-mix 를 쓰므로 미지원 브라우저에서는 선언 자체가 무효가 되어
 *         기존 색이 그대로 남는다(깨지지 않는다). 배경/배치는 건드리지 않는다.
 */
/* 2026-08-12 2차 실측 보정: 50% 혼합으로는 라임/옐로 계열 accent 가 4.23:1 에 머물러
   기준(4.5)을 못 넘겼다(nb4 .promo-eyebrow/.promo-cta) → 42% 로 낮춘다.
   어두운 브랜드색은 더 어두워질 뿐이라 부작용이 없다. */
.promo-eyebrow,
.promo-cta,
.promo-yn { color: color-mix(in srgb, var(--accent, #4a4756) 42%, #17161c) !important; }

.rec-kicker,
.rec-cta { color: color-mix(in srgb, var(--rec, #4a4756) 42%, #17161c) !important; }

.deal-tag,
.deal-cta,
.deal-mini { color: color-mix(in srgb, var(--brand, #4a4756) 42%, #17161c) !important; }

/* 브랜드색 배경 + 흰 글자인 탭/알약 — 배경만 어둡게 덮어 흰 글자를 살린다.
   실측: `.channel-tab.active` 배경 rgb(254,40,83) 에 흰 12px = 3.71:1 (nb3·nb4).
   ⚠️ 배경색 값을 CSS 에서 읽을 수 없으므로 **inset 그림자로 덮는다**.
      inset box-shadow 는 배경 위·내용(글자) 아래에 그려져서 글자는 흐려지지 않는다.
      filter: brightness() 를 쓰면 흰 글자까지 같이 어두워져 오히려 나빠진다. */
.channel-tab.active,
.channel-tab[aria-selected="true"] {
  box-shadow: inset 0 0 0 100vmax rgba(0, 0, 0, 0.26) !important;
}

/* 흰 글자를 쓰는 브랜드 배경 알약 — 배경을 낮춰 흰 글자가 읽히게 한다
   (시안·라임처럼 밝은 채널색이 문제였다) */
.channel-cta { background: color-mix(in srgb, var(--channel, #4a4756) 48%, #141319) !important; }

/* 반투명으로 흐려진 보조 텍스트(날짜·메타) — 실측 2.94:1 */
.blog-mini small,
.blog-mini time,
.lp-mini-body small { color: #55525f !important; opacity: 1 !important; }

/* ── 광고 슬롯 높이 예약: 늦게 붙는 광고가 화면을 밀어내는 것 완화 (2026-08-12) ──
 * 실측(모바일 390px, CPU 4배 감속): CLS 0.59 (양호 기준 0.1 이하).
 *   · 큰 이동 ①0.309@4.2초 — 상단에 삽입된 자동광고 285px 가 hero/NB패밀리를 밀어냄
 *   · 큰 이동 ②0.282@7.2초 — 본문 광고(선언 슬롯)가 90px → 392px 로 커지며 아래를 밀어냄
 * 이동이 크면 "버튼을 눌렀는데 다른 게 눌린다 / 기능이 안 된다" 로 체감된다.
 *
 * 선언 슬롯(.ad-slot)은 미리 높이를 잡아 두고, 구글이 "미충전(unfilled)" 으로 표시하면
 * 그때 접어서 빈 공간이 남지 않게 한다. :has() 미지원 브라우저에서는 기본 100px 만 적용된다.
 * ⚠️ 광고를 줄이거나 끄지 않는다 — 자리만 미리 잡는다.
 */
.ad-slot { min-height: 100px; }
.ad-slot:has(ins[data-ad-format="auto"]) { min-height: 300px; }
.ad-slot:has(ins[data-ad-status="unfilled"]) { min-height: 0 !important; }

/* ── 렌더링 품질(글자 번짐 완화) ── */
html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ── 모바일: 한 단계 크게 + 터치타깃 44px(iOS HIG) ── */
@media (max-width: 768px) {
  .brand-text span,
  .brand-text small,
  .nbf-go,
  .blog-kicker,
  .active-tool-kicker,
  .hero-stat-card small { font-size: 14px !important; }
  .nbf-txt, .nbf-txt span, .nbf-txt * { font-size: 13.5px !important; }
  .nbf-logo, .nbf-logo i, .nbf-logo * { font-size: 12.5px !important; }

  [class*="-badge"],
  [class*="-tag"],
  [class*="-flag"],
  [class*="-kicker"],
  [class*="-eyebrow"],
  [class*="-disclosure"],
  [class*="-desc"],
  [class*="-cat"],
  [class*="-kw"],
  [class*="-change"],
  .src-badges, .src-badges *,
  .fs-free,
  .deal-tag,
  .sc-badge,
  .lang-caret,
  .ad-label,
  .card-soon,
  .paypal-or,
  [class*="-popular"],
  sup, sub,
  small { font-size: 13px !important; }

  /* 크기만 키운다 — 배치·색은 건드리지 않는다 */
  .theme-toggle,
  .nba-btn,
  .lang-select,
  header select,
  header button { min-height: 44px !important; }
}


/* ═══════════════════════════════════════════════════════════════════
   yn5 (YN 키워드마스터) 전용 가독성 보정 — **밝은 테마용**(글자를 어둡게) (2026-08-12 실측)
   실측 19건: #aab0bf·#9aa1b1·#666d80 보조문이 2.01~4.24 로 다수 · SVG <text> "369" 로고 1건은
   CSS 배경이 아니라 SVG fill 이라 판정 자체가 성립하지 않아 제외.
   ═══════════════════════════════════════════════════════════════════ */
/* ① 밝은 회색 보조문 → 진한 회색 */
.ad-tag,
.aff-tag,
.aff-disclosure,
.footer-disclosure,
.footer-legal,
.copy,
.social-handle,
.qc-label,
.lb-date,
.pt-cat,
.pt-go,
.aff-note,
.menu-group,
.side-sponsored,
.mode-btn,
.empty-row td { color: #565c6b !important; opacity: 1 !important; }
/* ② 컬러 글자 → 색조 유지하며 어둡게 */
.fam-free { filter: brightness(0.62) saturate(1.12); }
/* ③ 브랜드색 배경 위 흰 글자 → 배경만 어둡게 */
.tag-new,
.sbtn { box-shadow: inset 0 0 0 100vmax rgba(0, 0, 0, 0.3) !important; filter: none !important; }


/* ===============================================================================
   CLS: 상단 바 자리 예약 (2026-08-16, 라이브 실측 기반)
   -----------------------------------------------------------------------------
   증상: 첫 화면이 그려진 뒤 상단 바 2~3개가 뒤늦게 나타나며 히어로 이하 전체를
         230px 밀어낸다 -> CLS 0.733 (기준 0.1 이하).

   [경고] 왜 min-height 만으로는 안 되는가 (yn4 에서 반나절 헤맨 지점):
        바들은 `.hidden` **클래스**(속성이 아니다 - class="famband hidden") 로 숨겨져 있다. **숨겨진 요소에는 min-height 가 아무 자리도
        차지하지 않는다**(박스가 생성되지 않으므로). 그래서 숨김 상태를 함께 풀어 준다.
        - display:block      -> 박스를 만들어 자리를 잡게 한다
        - visibility:hidden  -> 자리는 잡되 화면·스크린리더 모두에서 감춘다(빈 껍데기 노출 방지)
        - height + overflow:hidden -> 초기화 전 슬라이드가 세로로 쌓여 **과대 예약**되는 것을 막는다
          (min-height 로 두면 캐러셀 초기화 전 4장이 쌓여 400px 이 되고, 초기화 후 접히며
           반대 방향으로 더 큰 CLS 가 난다 -> 그래서 height 로 못 박는다)
        JS 가 숨김을 풀면 이 규칙은 자동으로 매칭이 끊겨 원래 높이로 돌아간다.

   [경고] 값은 이 사이트에서 채워진 뒤 뷰포트 7단(1280/1024/900/768/640/480/375)을
      전부 실측한 것이다. **다른 사이트에 복사 금지** - 사이트마다 전혀 다르다.
   [경고] 광고(adsbygoogle)·제휴링크·배너는 개수·위치·표시 시점을 건드리지 않는다. 자리만 미리 잡는다.
   =============================================================================== */

/* [사고기록] 2026-08-16 1차 시도는 !important 가 없어 **전허 적용되지 않았다.**
   증거: 라이부 상태 실산에서 `#promo h0  display:none / visibility:hidden` —
   **같은 궜칙 안**의 visibility 는 적용되고 display 만 무시됐다. 그게 단서다.
   범인: style.css:104   .hidden{display:none!important}
   -> !important 대결에서는 특이도 높은 집이 이긴다. 내 선택자는 (1,1,0) 이므로
      !important 만 붙이면 이긴다. 자리예약 목적에만 사용하므로 바가 보이는 동작에는
      영향이 없다(JS 가 hidden 을 해제하면 이 궜칙은 매칭이 끊긴다).
   [경고] 이 !important 를 지우면 예약이 조용하게 사라지고 CLS 가 원래대로 돌아간다.
      숫자만 보는 검사로는 안 잡힌다 — 반드시 **계산된 display** 를 확인할 것. */
#famband.hidden,
#recruitBar.hidden { display: block !important; visibility: hidden; overflow: hidden; }
#famband.hidden    { height: 92px; }
#recruitBar.hidden { height: 106px; }

/* [경고] 이 사이트는 #nbFamilyBar 가 main.wrap 의 **맨 아래**(div#mainContent 뒤)에 삽입된다
      -> 첫 화면 아래라 CLS 에 기여하지 않는다. 그래서 패밀리바 예약을 넣지 않는다.
      (다른 YN 사이트는 헤더/369바 바로 밑에 들어가 예약이 필요하다 - 사이트별로 다르다) */

@media (max-width: 768px) { #famband.hidden { height: 82px; } }
@media (max-width: 480px) { #recruitBar.hidden { height: 90px; } }


/* -- 잔여 CLS 2차: #socialBand 자리 예약 (2026-08-16) -------------------------
   상단 바 예약만으로는 0.733 -> 0.348 에서 멈추었다. 시간축 실산으로 남은 범인을 잡았다:
     첫 페인트(733ms)  hero 258~584 / div.ad-slot 604~704 / **section.panel 724** (첫 화면 안!)
                       #latestBlog h0 · #socialBand h0  (둘 다 display:none)
     2271ms            #socialBand 가 722px 로 들어오면서 section.panel 724 -> 1510 (**+786px**)
   -> 첫 화면 에 있는 panel 이 786px 움직이니 CLS 기여도가 지배적이었다.

   [안전 검증] social.js 의 run() 은 `band.classList.remove('hidden')` 을 **조건 없이** 한다
      -> 반드시 나타나므로 예약해도 영우적 번 여백이 생기지 않는다.

   [일부러 제외] #latestBlog(269px) 는 예약하지 않는다.
      index.html 인라인 스훈립트: fetch('/blog/latest.json') 이 실패하거나 목록이 비면
      `return` 으로 **숨김을 유지**한다 -> 예약하면 그 경우 269px 영우적 번 여백이 된다.
      (yn6 #onboard 와 동일한 함정 — 조건부 노출은 예약 금지)
      #socialBand 만 예약해도 section.panel 이 첫 화면(800px) **밖**으로 밀려나가서
      이후 #latestBlog 가 밀어내는 이동은 CLS 에 산정되지 않는다(뷰포트 밖 이동).

   [경고] .hidden 이 display:none!important 이므로 여기도 !important 가 필수다.
   [경고] 값은 실산: 722(>=640) / 670(<=560) / 830(<=420) */
#socialBand.hidden {
  display: block !important;
  visibility: hidden;
  overflow: hidden;
  height: 722px;
}
@media (max-width: 560px) { #socialBand.hidden { height: 670px; } }
@media (max-width: 420px) { #socialBand.hidden { height: 830px; } }


/* -- 잔여 CLS 3차: 사이드바 언어 선택기 자리 예약 (2026-08-16) ----------------
   증상: `NAV.menu[78→127]` — 사이드바 nav 가 47px 밀린다. nav 는 첫 화면 상단이라
         이동 거리가 작아도 영향 범위가 넘어 CLS 기여도가 크다.
   원인: `.lang-switch` 는 HTML 에 없고 i18n.js 가 런타임에 만들어 넣는다
         (첫 페인트 실산: `.lang-switch` 자체가 **없음**).
         없는 요소는 min-height 로 예약할 수 없다 -> #nbFamilyBar 와 동일한 자기해제형 기법:
         **바로 앞 형제(.brand)** 에 마진을 주고, 생기면 :has(+ .lang-switch) 가 매칭되어 해제된다.

   값 산출(실산): #sidebar 는 display:block 이므로 인접 마진이 **상쇄**된다.
     언어기 없을 때  brand 밑 70 -> nav.mt 8 상쇄 -> nav top 78
     언어기 있을 때  nav top 125   (차이 47px, inline-flex 라 라인박스 포함)
     -> 없을 때 brand 에 margin-bottom 55px 을 주면 상쇄 결과가 max(55, 8)=55 이 되어
        nav top = 70 + 55 = **125** 로 정확하게 맞는다.

   [경고] .brand 의 원래 margin-bottom 은 0px 이다(실산). 그게 바뀌면 55 도 다시 계산해야 한다. */
#sidebar .brand:not(:has(+ .lang-switch)) { margin-bottom: 55px; }


/* -- 잔여 CLS 4차: 첫 화면 안 TOP 광고 자리 예약 (2026-08-16) -----------------
   실산(1280x800, CPU 4x): 상단 바·socialBand·언어기 예약 후에도 0.100 에서 멈추었다.
   슬롯들을 하나하나 재보니 범인은 **TOP 슬롯 하나**이었다:

     첫 페인트   [SIDEBAR] top 585 h100   [TOP] top 604 h100   [IN_ARTICLE] top 1620 h100   [BOTTOM] top 2928 h100
     1155ms      [TOP] h100 -> **h300**        [IN_ARTICLE] h100 -> 0 (미설정이라 display:none)
     1830ms      [BOTTOM] h100 -> h491         [SIDEBAR] h100 -> h1273 -> 결국 h21

   -> 491px 로 크게 자라는 건 **BOTTOM**(top 2928, 첫 화면 밖)이라 CLS 에 산정되지 않는다.
      실제로 산정되는 건 **top 604 의 TOP 슬롯이 200px 자라며** 그 아래(첫 화면 하단 724~800에
      보이는 #socialBand)를 밀어내는 것이다.

   [핵심] 이밌 예약 자슴은 있었다 — 단지 **늦었다.**
     위 123~125행의 `.ad-slot:has(ins[data-ad-format="auto"]) { min-height:300px }` 는
     ads.js 가 ins 를 만든 **다음**에야 매칭된다. 그러니 광고가 자라는 그 시점에
     예약도 동시에 생기므로 이동을 막지 모한다. -> **ins 없이도 잡도록 슬롯 키로 지정**한다.

   [중요 — 새 번 여백은 생기지 않는다]
     이밌 ins 생성 지점에서 300px 를 잡고 있었으니, 이 변경은 **예약 시점만 앞당긴다.**
     미출전 상황도 지금과 동일하게 동작한다:
       · status="unfilled"        -> 125행 준칙(!important)이 0 으로 접는다 (지금과 같음)
       · status="unfill-optimized" -> 지금도 300px 를 유지한다 (지금과 같음). 이게 실제 관찰된 값이다.
     즐 어느 경우에도 오늘의 레이아웃보다 나빴지지 않는다.

   [경고] 광고 개수·위치·표시 시점은 그대로다. 자리만 미리 잡는다.
   [경고] 값은 실산한 최종 도달 높이다(TOP: >=900 -> 301 / <=768 -> 302).
      광고 소재가 이보다 톤 경우만 약간 밀린다(min-height 는 상한을 안 정한다).
   [경고] BOTTOM(491px)·SIDEBAR 는 **예약하지 않는다** — 첫 화면 밖이라 CLS 이득은 0 이면서
      미출전 시 491px 번 공간 리스키만 진다. */
.ad-slot[data-ad-slot-key="TOP"] { min-height: 301px; }
@media (max-width: 768px) { .ad-slot[data-ad-slot-key="TOP"] { min-height: 302px; } }


/* -- 잔여 CLS 5차: 햤로 안 칩 행(#quickchips) 바닥 예약 (2026-08-16) ----------
   [진범 확정] 광고 자리를 예약해도(TOP 슬롯은 첫 페인트부터 h301 으로 잡힌다)
   CLS 가 0.100 에서 안 내려가 서 햤로 내부를 재보니 범인은 칩 행이었다:

      779ms   hero 326  chips   0
     1422ms   hero 397  chips  71   <- 햤로 증가분 +71 과 **칩 변화가 정확하게 일치**
     1865ms   hero 350  chips  29

   h1(40px)·p(22px) 는 전혀 안 변한다. 증 햤로가 자란 것이 아니고 칩 행만 움직인다.

   [오진 2번 기록]
     · "491px 로 자라는 광고가 범인" -> 아니다. 491px 는 **BOTTOM 슬롯(top 2928)** 으로 첫 화면 밖이다.
       첫 화면 안 TOP 슬롯은 100->300 이었고, 그건 이밋 예약해서 해결됐는데 CLS 는 그대로여서
       범인이 따로 있다는 것이 드러났다.
     · "웹폰트 교진(FOUT) 로 h1/p 이 리플로우" -> 부분적으로만 맞다.
       document.fonts 로드는 2070ms 이고 칩 변화는 1422/1865ms 로 **그보다 이른다.**
       단 한글 서부셋(92개 분할)이 줍진으로 도달하므로 fonts.status 로는 안 잡힌다.
       증 칩은 대체 글자에서 **2줄로 감기다가** 폰트 도달 후 1줄로 돌아오며 +42/-42 를 만든다.

   [예약값을 1줄(29px)로만 잡는 이유]
     뷰포트별 최종 높이를 실산하면 >=1050:29 / 830~1049:65 / 740~829:29 / 450~739:65 / <=449:101 이다.
     그러나 칩 내용은 **사용자 데이티에 따라 바뀐다** — app.js renderQuick() 은 로엔 상
     `최입 검색어`(localStorage RECENT_KEY, 개수·길이 가변 + "지우기" 버튼)가 있으면 그것을,
     없으면 EXAMPLES 를 그린다. 즐 65·101 을 박으면 **최입검색어가 짧은 재방방자에게
     영우적 번 여백 36~72px** 이 생긴다([[cls-reserve-display-trap]] — 조건부·가변 내용은 전약 금지).
     -> 칩 행은 보이면 반드시 1줄 이상이니, **29px 는 어느 경우에도 초과하지 않는 바닥값**이다.
        능토록은 0->최종 이동 중 29px 를 지우고, 새 번 여백 위험은 0 이다.

   [남는 ±42px 진동은 폰트 레벨 사안이다 — CSS 자리예약으로는 모 없다]
     제대로 잡으려면 ① Pretendard 자가호스팅 + font-display:optional(리플로우 자에 없음)
     또는 ② size-adjust/ascent-override 로 대체글자 메트릭을 맞추는 것이다. 둘 다 사이트 전역
     토이프그래피에 영향을 줌다 -> 사장님 결정 필요. 여기서는 무위험 바닥만 잡는다. */
.quickchips { min-height: 29px; }


/* -- 잔여 CLS 6차: 칩 행 감김 진동의 근본 제거 (2026-08-16) ---------------------
   [실산으로 밝힌 숫자 — Pretendard CDN 을 차단해 A/B 한 결과]
                    칩 1줄에 필요한 폭      1280px(가용 680)
     Pretendard        668px                1줄 (h29)
     대있 글자          **759px (+13.6%)**     2줄 (h71)
   -> 폰트가 도달하기 전엔 대있 글자로 2줄, 도달 후 1줄 => **+42/-42px 진동**.
      이게 yn5 잔여 CLS 의 전부다(진동 없는 실행 0.0128 vs 진동 실행 0.197 — 이봉 분포).

   [거부한 오답]
     · 칩 글자를 생이기  -> 680/759 = 89.6% 로 줄여야 하는다. 12.5px -> 11px 로
       **12px 미만 글자 금지 기준(사장님 가독성 지생)을 위반**한다. 부결.
     · flex-wrap:nowrap  -> 뷰포트별 실산에서 칩은 실제로 1~3줄 필요하다
       (1280:1줄 / 1024:2줄 / 375:3줄). nowrap 은 칩을 가려 클릭 모가능하게 한다. 부결.
     · 뷰포트별로 65·101px 박기 -> 칩 내용은 사용자의 최입 검색어로 가변이라
       재방방자에게 영우적 번 여백이 생긴다. 부결([[cls-reserve-display-trap]] ⑥).

   [채택 — 대있 글자만 메트릭을 맞춘다]
     size-adjust 는 **그 @font-face 에만** 적용되는 글리프 배율이다.
     668/759 = 0.8801 -> **88%** 로 주면 대있 글자의 진행폭이 Pretendard 와 거의 같아진다
     -> 감김 줌수가 바뀌지 않으므로 진동이 사라진다.
     **최종 토이프그래피는 전혀 바뀌지 않는다** — Pretendard 가 도달하면 이 패밀리는 안 사용된다.
     적용 범위를 **.quickchips 한 줄로만 종통**한다(사이트 전역 메트릭 변경은 위험이 큼다).

   [알고 있는 한계]
     · 로드 중(1~2초) 칩 글자가 12% 작게 보인다(12.5px -> 약 11px). 마지막엔 원래 크기다.
       42px 레이아웃 점프보다 낫다는 판단이다(사장님이 원하지 않으면 이 바록만 지우면 된다).
     · 줄높이는 ascent/descent-override 까지 맞춰야 완전해지는데, Pretendard 의 정확한
       수지를 모르면 오해려 순딜다 -> **폭(size-adjust)만** 맞춘다. 잔여 진동 약 2~6px.
     · size-adjust 미지원 구형 브라우서(Safari 16 이하 등)는 이 선언을 무시한다 -> 지금과 동일(허생 없음).
     · local() 로 잡는 글자가 없는 환경이면 패밀리 자습이 실패하고 다음 스택으로 넘어간다 -> 지금과 동일. */
@font-face {
  font-family: 'PretendardQCFallback';
  src: local('Malgun Gothic'), local('Apple SD Gothic Neo'), local('Noto Sans KR'),
       local('Noto Sans CJK KR'), local('Segoe UI');
  size-adjust: 88%;
  font-display: swap;
}
.quickchips {
  font-family: 'Pretendard Variable', Pretendard, 'PretendardQCFallback',
               -apple-system, 'Segoe UI', 'Malgun Gothic', sans-serif;
}
