/* BagDrop — Webfonts
   *** 이 주석 안에 '*'+'/' 를 절대 쓰지 말 것 ***
   경로 예시에 와일드카드를 그대로 넣었다가 그 두 글자가 주석을 조기
   종료시켰다. 그러면 뒤따르는 텍스트가 CSS 로 파싱되고, 오류 복구 과정에서
   바로 다음 규칙(Pretendard Variable 메인 @font-face)이 통째로 버려진다.
   증상이 조용하다 — 파일은 200 으로 잘 받아지고 콘솔 오류도 없이 한국어·
   영어만 OS 기본 폰트로 렌더링된다. 와일드카드는 <ds-id> 처럼 적을 것.
   확인법: document.styleSheets 에서 fonts.css 의 @font-face 규칙 수가
   파일 안 선언 수(13)와 같은지 본다.

   Pretendard Variable: Korean + English
   PretendardJP Variable: Japanese
   Noto Sans SC: Chinese Simplified
   Noto Sans TC: Chinese Traditional

   Each @font-face loads a page-specific SUBSET (woff2) containing only the
   unicode characters actually used across index.html AND 예약하기.dc.html
   in all 5 languages (ko/en/ja/zh-hans/zh-hant), generated with fonttools
   pyftsubset. This cuts the combined font payload from ~49MB to under 1MB,
   which matters a lot on the flaky mobile connections this page sees (see
   bd-token-fallback note in index.html for the related mobile CSS-loading
   issue). The original full variable TTFs stay in this folder as a
   reference/rebuild source, not as a live fallback (see warning below).

   *** MANDATORY PROJECT RULE — READ BEFORE EDITING PAGE TEXT ***
   Any time copy is added or changed on index.html or 예약하기.dc.html, in
   ANY of the 5 languages, the subset woff2 files below MUST be checked and
   regenerated (if needed) BEFORE that change ships. Do not assume the full
   .ttf listed as a second `src` will silently cover missing glyphs — a
   single @font-face rule loads only ONE of its listed src entries (the
   first format the browser supports, which is woff2 on effectively every
   current browser). The .ttf is NOT merged in per missing glyph. A
   character missing from the subset renders in the wrong typeface or as a
   tofu box on the live site — it does not quietly fall back to the full
   font.

   How to verify: load each *.subset.woff2 with fontTools
   (`TTFont(path).getBestCmap()`) and check that every character in the
   current page text (both HTML files, all 5 languages) has a codepoint in
   that set. If anything is missing, regenerate with `pyftsubset` using the
   full current text of both pages as input.

   *** MANDATORY: FILENAME MUST CHANGE WHEN CONTENT CHANGES (CACHE-BUSTING) ***
   *** 2026-08-12 갱신: 캐시 기간이 1년 → 1일로 바뀌었다 ***
   The root `_headers` file sets these subset woff2 files
   (`/_ds/<ds-id>/assets/fonts/`) to `Cache-Control: public, max-age=86400`
   (1 day, on both the Cloudflare edge cache and every visitor's browser
   cache). 원래는 1년 immutable 이었으나, 배포 전파 전에 요청된 404 폴백이 그
   헤더를 뒤집어쓰고 1년간 눌러앉는 사고가 반복돼 1일로 내렸다(_headers 상단
   주석 참조). 기간이 짧아졌어도 filename 이 유일한 캐시버스팅 신호라는 점은
   그대로다. Because of this, the filename itself is the
   ONLY cache-busting signal — redeploying new bytes under the SAME
   filename will NOT reach visitors even though the deploy succeeds and
   the new file is correctly committed (this bit us once: 2026-07-20,
   required a manual "Purge Everything" in the Cloudflare dashboard to
   fix). To avoid depending on remembering a manual purge, filenames now
   carry a short content-hash suffix, e.g.
   `PretendardVariable.subset.69c97f9d.woff2`. Whenever you regenerate a
   subset font:
     1. Compute a new hash for the changed file (e.g. `sha256sum file |
        cut -c1-8`) and rename it `{original-name}.{hash}.woff2`.
     2. Update the matching `url(...)` below to the new filename.
     3. Deploy the new-named file alongside the old one (or remove the
        old one — either is safe, since nothing references it once the
        CSS is updated).
   *** 그리고 이 CSS 를 부르는 <link> 의 ?v= 도 같이 올려야 한다 ***
   위 파일명 해시만으로는 부족하다. _headers 가 `/_ds/*` 전체를 1년 immutable
   로 캐싱하는데, 이 fonts.css 의 URL 은 고정이라 엣지/브라우저가 옛 CSS 를
   1년간 그대로 붙들고 있고, 그 옛 CSS 는 옛 폰트 파일명을 가리킨다. 즉 폰트만
   새로 배포하면 아무에게도 도달하지 않는다(2026-07-21 실제 발생: 새 폰트는
   200 으로 떠 있는데 엣지 CSS 는 cf-cache-status=HIT, age 5406s 로 옛 이름을
   반환). HTML 은 immutable 이 아니라 항상 재검증되므로, 참조 URL 에 버전을
   붙이는 쪽이 확실하다. 서브셋 재생성 시 반드시 3곳을 함께 고칠 것:
     1. 새 해시로 woff2 파일명 변경 + 아래 url(...) 갱신
     2. index.html 의 fonts.css?v=<새 해시>
     3. 예약하기.dc.html 의 fonts.css?v=<새 해시>
   옛 이름의 woff2 는 하루만 남겨두고 지운다. 옛 CSS 를 이미 캐시한 방문자가
   삭제된 파일을 요청해 404 → 웹폰트 없음이 되는 것을 막기 위한 안전망인데,
   그 캐시 수명이 이제 1일이므로 하루가 지나면 옛 이름을 들고 있는 방문자는
   존재할 수 없다. 예전 규칙("한동안 남겨둔다")대로 방치했더니 이전 세대
   서브셋 41개 9.25MB 가 쌓여 배포 용량의 40% 를 차지하고 있었다(2026-08-12
   정리, 참조되는 7개 1.31MB 만 남김). 서브셋을 재생성하면 새 파일과 옛 파일을
   하루 공존시킨 뒤 옛 것을 지울 것.

   Current hashes (as of 2026-08-21): Pretendard=69c97f9d,
   PretendardJP=fd2943c8, NotoSansSC=c4c73d99, NotoSansTC=646812ed.
   (직전 2026-08-07 세대: 680b5aef / 5f8238d3 / fb85a15e / b081bd2a
    — 하루 공존시킨 뒤 삭제할 것)
   ?v= 는 이제 개별 폰트 해시가 아니라 이 fonts.css 내용의 sha256 앞 8자다
   (Pretendard 는 그대로인데 JP/SC/TC 만 바뀌는 경우 값이 안 변해서).
   ?v= 는 이제 개별 폰트 해시가 아니라 이 fonts.css 내용의 sha256 앞 8자다
   (Pretendard 는 그대로인데 JP/SC/TC 만 바뀌는 경우 값이 안 변해서).

   *** 검사 자동화: tools/check_font_subset.py ***
   위 "How to verify" 를 손으로 하지 않아도 되게 스크립트로 만들어 뒀다. 카피를
   고쳤으면 커밋 전에 그냥 돌리면 된다:

       python tools/check_font_subset.py     # 의존성: pip install fonttools brotli

   언어별로 실제 노출되는 텍스트를 모아 해당 서브셋의 cmap 과 대조하고, 빠진
   글자를 코드포인트로 찍는다. 원본 폰트 자체에 없어서 대응이 불가능한 글자와
   재생성 대기 중인 기존 누락은 스크립트 안 KNOWN_GAPS 에 사유와 함께 등록해
   두었으니, 새로 FAIL 이 뜨면 그건 이번 수정으로 새로 생긴 누락이다.

   원본 TTF 는 이 폴더에 없다(약 47MB 라 저장소에 두지 않는다). 재생성은
   손으로 하지 말고 스크립트를 쓸 것 — 원본을 받아오는 것부터 파일명 해시·
   fonts.css url()·두 페이지의 ?v= 갱신까지 한 번에 처리한다:

       python tools/regen_font_subsets.py
       python tools/check_font_subset.py     # 반드시 이어서 확인

   2026-08-21 확인: Pretendard/PretendardJP v1.3.9, NotoSansSC/TC v2.004-H2 가
   현재 서브셋과 글리프 외곽선·메트릭이 완전히 동일하다. 버전을 올리면 자형이
   달라져 레이아웃이 흔들릴 수 있으니, 올리기 전에 공통 글자의 외곽선을
   기존 서브셋과 대조할 것.

   2026-08-21 재생성 이력: 사이즈 가이드 모달의 이전/다음 버튼(&#8249; &#8250;
   = ‹ ›)이 전 언어 공통으로 보이는데 네 서브셋 모두에 없었다. 여기에 더해
   ja 는 写右左真秒, zh 는 右左滑秒 가 빠져 있었다 — 스와이프 안내문과
   "30秒" 거리 표기가 대체 서체로 렌더링되고 있었다는 뜻이다(히어로 위치
   배지에 들어가는 글자라 눈에 띄는 자리였다). 네 서브셋을 모두 재생성해
   해소. 이때 '현재 필요분' 만으로 자르지 않고 기존 커버리지와 합집합을
   취했다 — 검사기는 두 HTML 만 보므로 그 밖에서 쓰이는 글자를 놓칠 수 있다.

   2026-07-21 NotoSansTC 재생성 이력: 히어로에 繁體 "正式開幕" 문구를 추가하면서
   幕(U+5E55) 이 서브셋에 없어 대체 폰트로 렌더링됨. 幕 과 함께 그때까지 누락돼
   있던 →⋯✓共直程 을 추가(739→746 글리프, +160 bytes).
*/

@font-face {
  font-family: 'Pretendard Variable';
  src: url('../assets/fonts/PretendardVariable.subset.69c97f9d.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'PretendardJP Variable';
  src: url('../assets/fonts/PretendardJPVariable.subset.96bdf8ef.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Noto Sans SC';
  src: url('../assets/fonts/NotoSansSC.subset.37c39f31.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Noto Sans TC';
  src: url('../assets/fonts/NotoSansTC.subset.6832d522.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ── 타 언어 글자 갭필러 ─────────────────────────────────────────────
   언어 라벨(한국어/English/日本語/简体中文/繁體中文)과 결제수단명(支付宝/
   微信支付), 새로고침 기호(↺)는 어느 언어 모드에서든 화면에 뜬다. 그런데 각
   주 폰트의 '원본'이 그 글자를 아예 갖고 있지 않은 경우가 있다(서브셋 문제가
   아니라서 재생성으로는 해결 안 됨). 그러면 그 글자만 시스템 폰트로 튀어
   단어 한복판에서 서체가 섞인다 (예: ja 모드의 简, ko 모드의 支付宝).
   같은 family 에 unicode-range 로 초소형 서브셋(1.1~4.9KB)을 겹쳐 선언해
   부족한 글자만 채운다. 나중에 선언된 face 가 해당 범위에서 우선한다.
   Pretendard 는 본고딕(Source Han) 계열이라 Noto 글리프와 잘 어울린다.
   해당 글자가 실제 렌더될 때만 로드된다(unicode-range 지연 로드).
   ※ check_font_subset.py 는 이 갭필러 face 들을 읽어서 커버리지에 포함한다.
     여기에 face 를 추가/수정하면 검사 결과도 자동으로 따라온다. */
@font-face { /* ko/en 모드: CJK 라벨(日本語简体中文繁體) + 결제수단(付信微支宝) ← NotoSC */
  font-family: 'Pretendard Variable';
  src: url('../assets/fonts/LangGapSC.1c8c8506.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+65E5,U+672C,U+8A9E,U+7B80,U+4F53,U+4E2D,U+6587,U+7E41,U+9AD4,U+4ED8,U+4FE1,U+5FAE,U+652F,U+5B9D;
}
@font-face { /* ja 모드: 简 (JP 원본에 없음) ← NotoSC */
  font-family: 'PretendardJP Variable';
  src: url('../assets/fonts/LangGapSC.1c8c8506.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+7B80;
}
@font-face { /* zh-hant 모드: 简 (TC 원본에 없음) ← NotoSC */
  font-family: 'Noto Sans TC';
  src: url('../assets/fonts/LangGapSC.1c8c8506.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+7B80;
}
/* 새로고침 기호 ↺(U+21BA) 는 5개 언어에서 모두 같은 버튼에 뜬다. SC/TC 원본에는
   글리프가 아예 없고, Pretendard/PretendardJP 주 서브셋에도 들어 있지 않다.
   네 family 에 같은 파일을 걸어 어느 언어에서든 동일한 화살표가 나오게 한다
   (파일은 Pretendard 에서 뽑았고 1.1KB, 실제로 그려질 때만 로드된다). */
@font-face { font-family: 'Pretendard Variable';
  src: url('../assets/fonts/LangGapArrow.d62f0d94.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+21BA,U+21BB;
}
@font-face { font-family: 'PretendardJP Variable';
  src: url('../assets/fonts/LangGapArrow.d62f0d94.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+21BA,U+21BB;
}
@font-face { font-family: 'Noto Sans SC';
  src: url('../assets/fonts/LangGapArrow.d62f0d94.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+21BA,U+21BB;
}
@font-face { font-family: 'Noto Sans TC';
  src: url('../assets/fonts/LangGapArrow.d62f0d94.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+21BA,U+21BB;
}
@font-face { /* zh-hans 모드: 한국어 (SC 원본에 한글 없음) ← Pretendard */
  font-family: 'Noto Sans SC';
  src: url('../assets/fonts/LangGapHangul.3bf32432.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+D55C,U+AD6D,U+C5B4;
}
@font-face { /* zh-hant 모드: 한국어 ← Pretendard */
  font-family: 'Noto Sans TC';
  src: url('../assets/fonts/LangGapHangul.3bf32432.woff2') format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
  unicode-range: U+D55C,U+AD6D,U+C5B4;
}
