/* 풍수아씨 웹 디자인 토큰 — Mocha Glass + Copper
 *
 * 값의 출처: 스티치 디자인 시스템 "Traditional Modern Saju"(2026-09-09~10 이식).
 * 그 전에는 `풍수아씨 디자인_최종_0824/풍수아씨 디자인 시스템.dc.html` 이었다.
 * **값은 옮겨 적은 것이다. 화면마다 손으로 흔들지 않는다.**
 *
 * ## 이 파일이 무엇을 맡나
 *
 * 뿌리 블록의 토큰 74개와, `.ds-*` 로 시작하는 부품 규칙. 두 자리에서 읽힌다.
 *
 *   `static/index.html`             tokens.css 다음에 `app.css` 를 더 읽는다
 *   `static/developer-portal.html`  tokens.css **만** 읽는다
 *
 * 개발자 포털이 `.ds-card` · `.ds-cta` · `.ds-body` · `.ds-meta` ·
 * `.ds-section-label` · `.ds-btn-ghost` 를 쓴다. 그래서 이 파일의 `.ds-*` 규칙은
 * `app.css` 와 겹쳐 보여도 **지울 수 없다** — 지우면 포털이 맨 HTML 로 떨어진다.
 *
 * ## 아직 어긋나 있는 것 (2026-09-11 실측)
 *
 * `app.css` 가 제 뿌리 블록에 토큰 59개를 따로 갖고 있다(`--navy` · `--rose` ·
 * `--cream` · `--champagne-*` · `--radius` … 옛 이름들). 그중 **11개가 이 파일과
 * 이름이 겹치고**, `app.css` 가 뒤에 읽히므로 제품 화면에서는 그쪽이 이긴다.
 * 값까지 다른 것이 셋이다.
 *
 *   --sans   여기: "Noto Sans KR", system-ui …  app.css: var(--font) — Apple SD Gothic Neo 등이 더 붙는다
 *   --serif  여기: "Gowun Batang", serif        app.css: "Noto Serif KR" · "Batang" 이 더 붙는다
 *   --gold   여기: 어두운 블록에만 있다           app.css: 뿌리에 var(--bronze-300)
 *
 * 그래서 **여기를 고쳐도 제품 화면이 안 따라오는 토큰이 11개 있다.** 고칠 자리는
 * `app.css` 쪽이고, 지금은 다른 사람이 그 파일을 들고 있다. 자세한 것은
 * `docs/DESIGN_TOKENS.md`.
 *
 * ## 이름을 바꾸지 않는다
 *
 * 한 값에 이름이 여럿 붙어 있다(흰색에 열셋). 값을 한 자리에 두고 나머지
 * 이름이 그 자리를 가리키게 했다 — 이름을 줄이지는 않았다. 부르는 자리가
 * `app.css` 와 `index.html` 에 흩어져 있어서, 이름이 사라지면 화면이 깨진다.
 */

:root {
  /* ── 종이 · 화면 바탕 ─────────────────────────────────────────
   * 스티치 표면 램프. 세 값이 2% 안에 붙어 있어 눈에는 평평한 한 장으로
   * 보인다 — 층은 색이 아니라 실선과 그림자가 낸다. */

  /* 바탕 맨 위. 가장 밝은 종이. 한 단 가라앉은 카드 면으로도 쓴다 */
  --paper-0: #FBF9F9;
  /* 바탕 가운데. 넓은 창에서는 페이지 바탕이 이 값이다 */
  --paper-1: #F5F3F3;
  /* 바탕 맨 아래. 가장 어두운 종이 */
  --paper-2: #EFEDED;
  /* 화면 바탕. 170deg — 위에서 아래로 살짝 기울여 깐다 */
  --app-bg: linear-gradient(170deg, var(--paper-0) 0%, var(--paper-1) 48%, var(--paper-2) 100%);
  /* 640 아래(폰)의 바탕. **색은 위와 같고 각도만 172deg** 로 더 세운다 —
     화면이 세로로 길어서 같은 각도로는 램프가 덜 보인다 */
  --app-bg-narrow: linear-gradient(172deg, var(--paper-narrow-0), var(--paper-narrow-1) 52%, var(--paper-narrow-2));

  /* ── 잉크 · 글자 ──────────────────────────────────────────── */

  /* 본문 글자. 흰 면에서 대비 15.9 — 순검정까지 가지 않는 까닭은 한글 획이
     많아 #000 이면 글자가 뭉쳐 보이기 때문이다 */
  --ink: #1B1C1C;
  /* 보조 글자 · 설명 한 줄. 흰 면에서 8.4 */
  --ink-soft: #4E463A;
  /* 메타 · 각주. 흰 면에서 12.1 — 작게 쓰이므로 오히려 짙게 잡았다 */
  --mocha: #303031;
  /* 어두운 면 위의 글자. 감정서 · 전문 화면이 쓴다 */
  --on-dark: #F2F0F0;

  /* ── 금 · 구리 ────────────────────────────────────────────────
   * 라벨 · CTA · 켜진 테두리. 셋은 같은 금색의 세 단이다. */

  /* 밝은 단. 어두운 면 위의 금색 글자 · 선 */
  --bronze-300: #E6C184;
  /* 가운데 단. 켜진 카드의 테두리 */
  --bronze-500: #B8965D;
  /* 짙은 단. **밝은 면 위의 금색 글자는 반드시 이것** — 흰 면에서 5.2 이고
     한 단 밝은 --bronze-500 은 3.3 으로 본문 바닥(4.5) 아래다 */
  --bronze-700: #765A27;
  /* 구리 실선. 값은 --bronze-700 과 같다. 이름을 둘로 두는 까닭은 부르는
     자리 6군데가 "선"을 뜻하고 "글자색"을 뜻하지 않기 때문이다 */
  --copper-line: var(--bronze-700);
  /* 밤색 가운데 단. **켜진 칩의 면과 테두리** — 위에 종이색(--paper-0) 글자를
     얹어 대비 9.4. 앱 `colors.brownMid`(native/theme/tokens.ts)와 같은 값이다.
     2026-09-15 칩 결정(「가 · 밤색 채움」)에서 이름을 얻었다 */
  --brown-mid: #5C4211;
  /* 금색 단추. 150deg — 왼쪽 위가 밝고 오른쪽 아래가 짙다.

     2026-09-14 에 짙은 끝을 700 에서 500 으로 당겼다. 흰 글자를 얹고 있었는데
     밝은 끝에서 대비가 **1.70** 이었다 — 본문 기준 4.5 를 그라디언트의 77%
     지점부터만 넘었다. 글자를 짙은 밤색으로 바꾸면서 면도 함께 좁혔다.
     이제 어디서나 4.55 위다. */
  --cta: linear-gradient(150deg, var(--bronze-300), var(--bronze-500));
  /* 마우스를 올리면 **밝아진다**. 짙은 글자를 얹었으니 어두워지면 안 읽힌다 */
  --cta-hover: linear-gradient(150deg, #E8C790, #BFA06D);
  /* 금색 단추 **위**의 글자. 값을 var() 로 돌리지 않는다 —
     tests/test_web_contrast.py 가 이 줄을 헥스로 읽어 대비를 잰다 */
  --on-cta: #452F00;
  /* **제목용 짙은 잉크.** 이름은 cta 지만 실제로 쓰이는 59군데가 전부 밝은 면
     위의 제목 · 라벨이다(`.expired-shell h1` · `.legal-card h2` …).
     2026-09-10 에 이걸 흰색으로 바꿨다가 그 제목들이 통째로 안 보였다.
     이름이 틀렸으니 언젠가 --title-ink 로 옮겨야 한다 — 그때 59군데를 함께 고친다 */
  --cta-ink: #452F00;
  /* **금색 글자.** 면에 따라 돈다 — 밝은 면은 짙은 단(대비 6,14), 어두운
     감정서는 밝은 단(8,83). 하나로 두면 한쪽이 반드시 묻힌다:
     밝은 면의 300 은 1,62 이고 어두운 면의 700 은 2,34 다.
     어두운 쪽 값은 아래 [data-theme="dark"] 무리에서 다시 적는다. */
  --gold-ink: var(--bronze-700);

  /* ── 경고 ─────────────────────────────────────────────────── */

  /* 이 시스템의 **유일한** 경고색. #8E3A33 은 2026.08.23 에 물러났다.
     어두운 화면에서는 아래에서 #EF8073 으로 올려 쓴다 */
  --wine: #8C2F43;

  /* ── 실선 ─────────────────────────────────────────────────────
   * 선은 둘뿐이다. 장식선 · 제목 옆 선을 새로 만들지 않는다. */

  /* 머리카락 선. --ink(27,28,28)를 10% 로 깐 것이다. 카드 안의 줄을 가른다 */
  --line: rgba(27, 28, 28, .10);
  /* 카드 테두리. 종이보다 한 단 짙은 회색 — 흰 카드가 흰 바탕에서 갈린다 */
  --glass-border: #E3E2E2;

  /* ── 면 ───────────────────────────────────────────────────────
   * **카드는 속이 찬 흰색이다.** 전에는 그라디언트였는데 끝색(#F5F3F3)이
   * 프레임 바탕(--paper-1)과 값이 같아 카드 아랫부분이 바탕에 녹았다.
   *
   * 흰색에 이름이 열셋 붙어 있다. 값은 --white 한 자리에 두고 나머지가 그것을
   * 가리킨다 — 흰색을 한 톤 내릴 일이 생기면 고칠 줄이 하나다. */

  /* 흰색의 주인. 아래 열 이름이 이것을 가리킨다 */
  --white: #FFFFFF;
  /* 카드 면 — 기본 · 강조 · 칩. 세 이름이 다 흰색인 것은 유리였던 흔적이다.
     층은 테두리(--glass-border)와 그림자(--sh-sm)가 낸다 */
  --glass-1: var(--white);
  --glass-2: var(--white);
  --glass-3: var(--white);
  /* 종이보다 한 단 밝게 띄운 면 · 바탕까지 꽉 채운 면 */
  --paper-bright: var(--white);
  --paper-flush: var(--white);
  /* 640 아래의 바탕 램프. 색은 --paper-0/1/2 와 같고 각도만 다르다 */
  --paper-narrow-0: var(--paper-0);
  --paper-narrow-1: var(--paper-1);
  --paper-narrow-2: var(--paper-2);
  /* 폰 전용 램프. 맨 위만 종이가 아니라 **흰색**이다 — 상단 바가 붙는 자리라
     거기서부터 흰 면이 이어져야 경계가 안 보인다 */
  --paper-mobi-0: var(--white);
  --paper-mobi-1: var(--paper-1);
  --paper-mobi-2: var(--paper-2);
  /* 유리였던 이름들. --glass-fill-70 은 70% 투명도를 뜻했으나 지금은 불투명하다 */
  --glass-fill: var(--white);
  --glass-fill-70: var(--white);
  --glass-wash: var(--white);
  /* 한 단 가라앉은 면. 카드 안의 작은 칸 · 입력칸 바닥 */
  --glass-fill-soft: var(--paper-0);
  --glass-wash-soft: var(--paper-0);

  /* 금색 베일 — --bronze-700(118,90,39)을 옅게 깐 것이다. rgba 안에서는
     var() 를 쓸 수 없어 숫자가 박혀 있다. 농도만 다른 네 단계다 */
  --bronze-veil: rgba(118, 90, 39, .14);
  --bronze-veil-16: rgba(118, 90, 39, .16);
  --bronze-veil-13: rgba(118, 90, 39, .13);
  --bronze-veil-10: rgba(118, 90, 39, .10);
  /* 2026-09-15 피그마 부품을 짜다 이름 없는 색으로 걸린 다섯 단. app.css 에 값이
     **정확히 같은** 자리가 여덟 곳 넘게 있던 농도만 세웠다(비교 · 설문 · 결과 칸).
     한두 곳뿐인 .04 · .06 · .08 · .09 · .20 · .22 · .26 · .28 · .32 · .40 은
     가까운 단으로 몰지 않았다. 앱에는 이 베일을 쓰는 자리가 없어 짝이 없다 */
  --bronze-veil-05: rgba(118, 90, 39, .05);
  --bronze-veil-07: rgba(118, 90, 39, .07);
  --bronze-veil-12: rgba(118, 90, 39, .12);
  --bronze-veil-18: rgba(118, 90, 39, .18);
  --bronze-veil-24: rgba(118, 90, 39, .24);
  /* 회갈색 베일 — #7F7668 을 옅게 깐 것. **그 회갈색은 이 파일에 제 이름이
     없다**(app.css 는 --mute, 앱은 colors.inkFaint). 여기서는 rgba 로만 산다.
     앱 `colors.mochaVeil*` 와 같은 이름 · 같은 값이다(2026-09-15,
     tests/test_colour_names_0915.py). 그림자 색에는 붙이지 않았다 — 뜻이 다르다 */
  --mocha-veil-10: rgba(127, 118, 104, .10);
  --mocha-veil: rgba(127, 118, 104, .12);
  --mocha-veil-14: rgba(127, 118, 104, .14);
  --mocha-veil-16: rgba(127, 118, 104, .16);
  --mocha-veil-20: rgba(127, 118, 104, .20);
  --mocha-veil-24: rgba(127, 118, 104, .24);
  --mocha-veil-26: rgba(127, 118, 104, .26);
  /* 점선 — 아직 안 채운 칸 · 물어볼 거리 칩의 테두리. 앱 `colors.dashed` 와 같은 값 */
  --dashed: rgba(127, 118, 104, .30);
  /* 금색 안개 — --bronze-500(184,150,93)을 18% 로. 강조 카드의 면 */
  --bronze-mist: rgba(184, 150, 93, .18);

  /* ── 모서리 ───────────────────────────────────────────────────
   * **2026-09-12.** 얼굴을 셋 그려 놓고 하나를 고르는 대신 **자리를 나눠**
   * 쓰기로 했다 — 뼈대는 서첩, 잰 값 안쪽은 지적도, 장의 끝은 조언.
   *
   * 그래서 모서리는 두 몫이다.
   *
   *   바깥(카드·단추·입력칸)   여기 값을 쓴다. 문서의 낯이라 각지지 않는다
   *   안쪽(잰 값 표·눈금)      모서리가 없다. 실선과 칸으로만 짠다
   *
   * 26·18·14 였던 것을 16·10·8 로 한 단씩 좁혔다. 문서의 부드러움은 남기고
   * 카드가 물방울처럼 보이던 것만 걷는다. 앱 카드가 16·18·22 셋으로 갈려
   * 있던 문제는 이 한 벌로 함께 풀린다. */

  /* 단추 · 입력칸 */
  --r-sm: 8px;
  /* 카드 기본 */
  --r-md: 10px;
  /* 화면을 여는 큰 카드. 한 화면에 하나 */
  --r-lg: 16px;
  /* 단추의 키 세 단(`docs/BUTTON_SYSTEM.md`). 앱 `btn` 과 짝이다.
     36 은 모양만 작고 누르는 자리는 44 까지 넓힌다. */
  --btn-h-lg: 48px;
  --btn-h-md: 44px;
  --btn-h-sm: 36px;
  /* **손가락이 닿아야 하는 자리.** 애플 44 · 구글 48 을 최소로 본다.
     모양이 그보다 작아도 되지만 누르는 자리는 이만큼이어야 한다 —
     앱의 `tap` 과 같은 뜻이다(native/theme/tokens.ts). 쓰는 법은
     `.reach` 한 줄(app.css). 시험: tests/test_tap_reach.py */
  --tap-min: 44px;
  /* 단추. 2026-09-14 대표님이 알약으로 정하셨다(`docs/BUTTON_SYSTEM.md`).
     앱의 `radius.btn` 과 짝이다 — 두 뿌리가 이 이름 하나를 본다.
     카드와 입력칸은 그대로 네 단을 쓴다. 알약이 되는 것은 단추뿐이다. */
  --r-btn: 999px;
  /* 무른 사각. **하단 탭의 켜진 자리** 하나에 쓴다.
     알약이면 아이콘이 알에 갇힌 것처럼 보이고, 카드(10)면 각져서 눌린 자국
     같다. 그 사이 한 단이다 — 2026-09-14 대표님 참고 그림의 자리.
     14 는 옛 토큰 값이기도 하다. **여기서만** 되살린다(앱 `radius.soft`). */
  --r-soft: 14px;
  /* 알약 · 원. 999 는 "높이의 절반" 을 뜻하는 관용값이다.
     **이것만 그대로 둔다** — 얼굴과 점은 여전히 동그래야 한다 */
  --r-pill: 999px;

  /* ── 선의 굵기 ────────────────────────────────────────────────
   * 2026-09-14 에 세었더니 테두리 굵기가 열아홉 가지였다. 굵기는 **뜻**이다 —
   * 칸을 가르는 실선과 무언가를 가리키는 선은 달라야 한다.
   * 앱의 `stroke` 와 같은 값이다. */
  /* 칸을 가르는 실선. 테두리 471군데 가운데 364가 이것이다 */
  --stroke-hair: 1px;
  /* 한 단 굵은 선. 켜진 칩 · 고른 카드 */
  --stroke-line: 1.5px;
  /* 무언가를 가리키는 선. 인용의 왼쪽 · 손님의 한 줄 */
  --stroke-mark: 2px;
  /* 아이콘의 획 */
  --stroke-icon: 1.7px;

  /* ── 움직임 ───────────────────────────────────────────────────
   * 화면이 바뀌는 속도는 **손이 기다리는 시간**이다. 값이 흩어지면 어떤 카드는
   * 툭 나타나고 어떤 카드는 느릿하다. 앱의 `motion` 과 같은 값이다. */
  --dur-fast: .12s;
  --dur-base: .16s;
  --dur-slow: .28s;
  --ease: cubic-bezier(.2, .7, .3, 1);

  /* ── 흐림 ─────────────────────────────────────────────────────
   * 앱에서 「누르는 중」 하나가 다섯 값으로 흩어져 있었다(0.7 · 0.75 · 0.85 ·
   * 0.86 · 0.88). 웹도 같은 이름을 든다. */
  --alpha-pressed: .85;
  --alpha-off: .42;
  --alpha-idle: .55;
  /* --alpha-wash(.07) 는 배경 등고선에만 썼다 — 등고선을 걷으며 함께 뺐다(2026-09-23). */

  /* ── 그림자 ───────────────────────────────────────────────────
   * **2026-09-12.** 속삭이는 정도만 남긴다. 문서는 종이 위에 놓인 것이라
   * 아주 얕은 층이 있어야 카드가 바탕에서 갈린다. 전보다 번짐을 절반으로
   * 줄이고 농도를 4~6% 로 둔다.
   *
   * **금색 단추의 그림자는 되살리지 않는다.** 금색이 제 빛을 내면 계기판이
   * 아니라 장식이 된다. 이 하나가 지적도가 바깥까지 나오는 자리다. */

  /* 카드. 12px 번짐에 4% */
  --sh-sm: 0 2px 12px rgba(27, 28, 28, .04);
  /* 띄운 카드 · 강조 카드. 28px 번짐에 6% */
  --sh-md: 0 8px 28px rgba(27, 28, 28, .06);
  /* 금색 단추 — 그림자 없이 납작하게 */
  --sh-cta: none;

  /* ── 글자 크기 ────────────────────────────────────────────────
   * 여덟 단. 앱(`native/theme/tokens.ts` 의 `type`)에서 그대로 옮겨 적었다 —
   * 30 · 25 · 20 · 17 · 15 · 14 · 13 · 12. 앱은 이 척도를 607군데에서 쓰고
   * 척도 밖 숫자가 0이다. 웹은 `app.css` 의 font-size 371군데가 전부 제 숫자를
   * 적고 있었다(값 55가지).
   *
   * 뿌리 글자 크기는 `html` 에 적지 않았으므로 브라우저 기본 16px 이다. 그래서
   * 한 단 = 값/16 rem 이다. rem 으로 두는 까닭: 손님이 브라우저 글자 크기를
   * 키우면 여덟 단이 함께 커진다. px 로 박으면 안 따라온다.
   *
   * `micro`(12)가 **바닥**이다. iOS HIG 는 11pt 아래를 쓰지 말라고 못 박고
   * Material 의 최소도 11sp 다. 한글은 자모가 한 칸에 겹쳐 들어가 획이
   * 빽빽하므로 라틴보다 더 커야 읽힌다. 자세한 것은 `.claude/rules/type.md`.
   *
   * **단을 늘리지 않는다.** 새 크기가 필요하다고 느껴지면 대개 위계를 잘못
   * 잡은 것이다. */

  /* 화면을 여는 큰 물음. 한 화면에 하나 */
  --t-display: 1.875rem;
  /* 절의 제목 · 카드 머리 */
  --t-title: 1.5625rem;
  /* 카드 안의 강조 문장 · 굵은 숫자 */
  --t-headline: 1.25rem;
  /* 본문. 손님이 가장 오래 읽는 크기 */
  --t-body: 1.0625rem;
  /* 보조 본문 · 설명 한 줄 */
  --t-bodySm: 0.9375rem;
  /* 라벨 · 단추 글자 */
  --t-label: 0.875rem;
  /* 각주 · 도움말 */
  --t-caption: 0.8125rem;
  /* 눈금 · 자간 벌린 라벨. 바닥 */
  --t-micro: 0.75rem;

  /* ── 행간 · 자간 · 한 줄의 길이 ──────────────────────────────
   * 2026-09-14 · `.claude/rules/read.md` 1~3장. 실제 CSS 를 브라우저에 올려
   * 재어 보니 감정서 문단이 12px/1.92, 맛보기 본문이 15px/1.85 로 **줄이 떠
   * 있었고**, 1440 폭에서 한 줄에 114~135자가 섰다. 폭 제한은 하나도 없었다.
   *
   * **제목은 좁게, 본문은 넉넉하게.** 큰 글씨는 줄 사이가 넓으면 한 문장이
   * 흩어져 보이고, 작은 글씨는 좁으면 다음 줄을 찾느라 눈이 되돌아간다.
   * 여덟 단마다 하나씩, 앱 `leading`(40·34·28·27·24·22·20·18)과 같은 비다. */

  /* 30 → 40. 화면을 여는 큰 물음 */
  --lh-display: 1.33;
  /* 25 → 34. 제목 */
  --lh-title: 1.36;
  /* 20 → 28. 카드 안의 강조 문장 */
  --lh-headline: 1.4;
  /* 17 → 27. 가장 오래 읽는 글. 앱은 1.41 로 한 단 작은 글보다 빡빡했다 */
  --lh-body: 1.6;
  /* 15 → 24. 보조 본문. 맛보기 본문 한 줄이 1.85 였다 */
  --lh-bodySm: 1.6;
  /* 14 → 22 */
  --lh-label: 1.57;
  /* 13 → 20. 「오늘 할 수 있는 한 가지」의 까닭이 1.75 였다 */
  --lh-caption: 1.54;
  /* 12 → 18. 바닥 */
  --lh-micro: 1.5;
  /* 명조(고운바탕) 긴 글은 한 단 넉넉히. 획이 촘촘해 같은 행간이면 더
     빽빽하게 읽힌다 — 옛말 인용 · 감정서 첫머리 · 장 본문 */
  --lh-serif-read: 1.7;

  /* 자간은 **작은 라벨 한 가지**에만 준다(고정폭 눈금 · 눈썹 · 칸 이름).
     한글 본문 · 제목은 0 이다(W3C KLREQ). 재어 보니 웹 작은 라벨의 자간이
     0.01~0.24em 사이 15가지였다. 새 라벨은 이 하나에서 고른다. 앱은 1.4 */
  --tr-label: 0.12em;

  /* 읽는 문단 한 줄의 길이. 36em ≈ 한 줄 50자 — 40~60자 안이다. 넓은 창에서
     줄이 끝없이 늘면 줄 끝에서 다음 줄 머리를 찾느라 눈이 지친다.
     앱은 폭이 430 으로 묶여 28~34자라 따로 두지 않는다 */
  --measure-read: 36em;

  /* ── 형광펜 ───────────────────────────────────────────────────
   * `.claude/rules/read.md` 5장. 본문 속 **측정값(숫자+단위)** 아래 옅은 띠.
   * 한 문단에 둘까지 — 긋는 일은 `app.js` 의 `markValues` 가 한다.
   *
   * 금을 면으로 깔지 않는다(`look.md`). 이 띠는 면이 아니라 **글자에 딸린
   * 표시**로 본다 — 글자 높이의 아래 45% 만 칠하고, 42% 로 옅게 둔다.
   * 띠 위의 --ink 는 가장 어두운 종이(#EFEDED)에 겹쳐도 대비 4.5 를 넘는다
   * (tests/test_value_marks_web.py). 어두운 감정서 값은 아래 무리에서 다시 적는다. */

  --mark: rgba(230, 193, 132, .42);
  /* 띠가 시작하는 높이. 위 55% 는 비워 글자 윗부분이 종이 위에 선다 */
  --mark-cut: 55%;

  /* ── 글꼴 ─────────────────────────────────────────────────────
   * --sans · --serif 는 app.css 가 뒤에서 다시 정의한다. 제품 화면에서는
   * 그쪽이 이긴다 — 여기 값은 개발자 포털에만 닿는다. */

  /* 제목 · 감정서 본문. 명조는 판단을 적는 글에 쓴다 */
  --serif: "Gowun Batang", serif;
  /* 본문 · 단추 · 라벨 */
  --sans: "Noto Sans KR", system-ui, sans-serif;
  /* 눈금 · 좌표 · 코드. 자리가 흔들리면 안 되는 숫자에 쓴다 */
  --mono: ui-monospace, Menlo, monospace;

  /* ── 조작부 높이 ──────────────────────────────────────────────
   * 디자인 시스템의 control 표에서 그대로 옮겼다. */

  /* 기본 단추 */
  --h-cta: 48px;
  /* 보조 단추 */
  --h-secondary: 46px;
  /* 소셜 로그인. 세 줄이 나란히 서므로 한 단 크다 */
  --h-social: 52px;
  /* 목록 한 줄의 최소 */
  --h-row: 44px;
  /* 설문 선택 한 줄의 최소. 두 줄 문장이 들어간다 */
  --h-choice: 56px;
  /* 칩 */
  --h-chip: 34px;
  /* 바닥 탭 바 */
  --h-tab: 58px;
  /* 상단 바 */
  --h-topbar: 68px;
  /* **손가락이 닿는 가장 작은 넓이.** 애플 44pt · 구글 48dp 가운데 작은 쪽이다.
     34px 원형 단추는 모양을 그대로 두고 가짜 요소로 이 넓이를 만든다.
     값이 --h-row 와 같지만 뜻이 다르므로(줄 높이 / 손가락) 따로 둔다.
     tests/test_payment_ui.py 가 이 줄을 글자 그대로 읽는다 */
  --hit-min: 44px;

  /* ── 여백 ─────────────────────────────────────────────────────
   * **2026-09-12 실측을 먼저 적는다.** 웹에 여백 선언이 1,770군데 있고 값이
   * 서로 다르게 흩어져 있다 — 많이 쓰이는 순서로 12 · 8 · 10 · 14 · 9 · 6 · 4 · 7.
   * 앱도 같다(858군데 · 10 이 138 · 12 가 111).
   *
   * **여덟 배수 척도가 이 제품에 안 맞는다.** 앱의 네 단(8·16·24·32)과 값이
   * 같은 자리는 858 가운데 164군데뿐이다. 나머지를 여덟 배수로 몰면 700군데가
   * 1~4px 씩 움직인다 — 그건 정리가 아니라 조판을 다시 잡는 일이고, 눈으로
   * 확인할 수단 없이 할 일이 아니다.
   *
   * 그래서 **네 단을 세워 두되 값이 같은 자리만** 옮긴다. 새 화면은 여기서
   * 고르고, 옛 화면은 그 화면을 고칠 때 함께 옮긴다. 앱 `space` 와 같은 값이다. */

  /* 붙은 것들 사이 */
  --sp-tight: 8px;
  /* 카드 안쪽 여백 */
  --sp-snug: 16px;
  /* 덩이와 덩이 사이. **웹은 여기까지다** — 32px 을 부르는 자리가 하나도
     없어서 넷째 단은 세우지 않았다(`WebDeadTokenTest`). 앱에는 `space.section`
     이 있다. 웹에서 그만한 사이가 필요해지면 그때 이름을 준다 */
  --sp-block: 24px;
  /* 장과 장 — 큰 갈래 사이. 2026-09-14 에 다섯째 층으로 세웠다
     (`.claude/rules/read.md` 4장). 한 층 올라갈 때마다 1.5배 넘게 벌린다 —
     8 → 16 → 24 → 40. 32 는 여전히 부르는 자리가 없어 두지 않는다 */
  --sp-chapter: 40px;

  /* 카드 안여백 */
  --pad-card: 16px;
  /* 화면 좌우 여백 */
  --pad-side: 18px;

  /* ── 초점 ─────────────────────────────────────────────────────
   * outline:none 을 홀로 쓰지 않는다. 키보드로 다니는 손님이 길을 잃는다. */

  --focus-ring: 2px solid var(--bronze-700);
  --focus-offset: 2px;

  /* ── 브랜드 ───────────────────────────────────────────────────
   * 각 사가 퍼낸 값 그대로다. **모카 팔레트로 물들이지 않는다** — 물들이면
   * 손님이 "카카오로 로그인" 단추를 못 알아본다. 흰색도 var() 로 돌리지 않는다. */

  --kakao-bg: #FEE500;
  --kakao-ink: rgba(0, 0, 0, .85);
  --naver-bg: #03C75A;
  --naver-ink: #FFFFFF;
  --google-bg: #FFFFFF;
  --google-border: #747775;
  --google-ink: #1F1F1F;
}

/* 어두운 화면 — 감정서(R33 · R36)와 온보딩.
 *
 * **같은 이름에 다른 값을 깐다.** 값을 치르고 받는 문서라 다른 공간에 두는
 * 편이 낫다(2026-09-10 결정). 램프가 위에서 아래로 대비를 7.7 → 5.4 로
 * 떨어뜨리므로, 화면 아래쪽 카드 본문은 여기서 --ink-soft 를 쓴다.
 *
 * --gold 는 **여기에만 있다** — 밝은 쪽 뿌리 블록에는 없다. 밝은 화면에서
 * var(--gold) 를 부르면 app.css 가 제 뿌리에 둔 var(--bronze-300) 으로 떨어진다.
 * 값이 같아서 지금은 아무 일도 안 일어나지만, app.css 를 고치면 드러난다. */
[data-theme="dark"],
.is-dark,
.full-shell,
/* 감정서는 2026-09-26 부터 **표지만 어둡고 본문은 밝은 종이**다(대표님 · task-report-0926).
   전엔 `.report-shell` · 결과 화면 통째가 여기 있었다. 표지 한 칸(`.report-cover`)만 남긴다. */
.report-cover,
.screen[data-screen="full"] {
  /* 168deg. 밝은 쪽(170deg)과 두 도 다르다. 세 값은 앱 감정서 '대표' 갈래의
     바탕과 같다(native/theme/dark.ts 의 SEEDS.site.grounds) */
  --app-bg: linear-gradient(168deg, #1F1B15, #2A261F 46%, #343028);
  /* 어두운 면 위의 본문. 앱 감정서의 `pal.ink` 와 같은 값이다 */
  --ink: #E3E2E2;
  /* 어두운 면 위의 보조 글자. 앱 감정서의 `pal.inkSoft` 와 같은 값이다.
     2026-09-17 #9D9B95 → #B3B1AB. 실제 감정서를 열어 픽셀로 재니 금빛 막을 두 겹 깐 카드
     (가장 밝은 어두운 면 rgb(70,65,53))에서 3,65~4,19 · 50곳이었다. 이 값은 4,74 이고
     본문 --ink 보다는 한 단 어둡다(`tests/test_dark_report_contrast_0917.py`). */
  --ink-soft: #B3B1AB;
  /* 어두운 면의 금색. 밝은 쪽 --bronze-300 과 같은 값이다 */
  --gold: #E6C184;
  /* 어두운 면에서는 금색 글자가 밝은 단이다 (대비 8,83) */
  --gold-ink: var(--gold);
  /* 머리카락 선도 금색으로 바뀐다 — 먹빛 선은 어두운 면에서 사라진다 */
  --line: rgba(230, 193, 132, .16);
  /* 경고색을 끌어올린다. #8C2F43 은 어두운 바탕에서 2.0 으로 안 읽힌다 */
  --wine: #EF8073;
  /* 조용한 글자 셋. 밝은 뿌리(app.css)는 #726A5E 로 짙게 올렸는데, 그 값은
     어두운 면에서 안 읽힌다. 여기서 어두운 면의 보조 글자로 다시 적는다.
     var() 는 **적힌 자리에서** 풀리므로 셋을 다 여기서 다시 적어야 한다 —
     뿌리의 `--mute: var(--ink-faint)` 는 뿌리에서 이미 풀려 내려온다. */
  --ink-faint: var(--ink-soft);
  --mute: var(--ink-soft);
  --taupe: var(--ink-soft);
  /* 형광펜. 밝은 쪽 42% 를 어두운 면에 그대로 두면 띠가 등불처럼 떠서 글자보다
     먼저 읽힌다. 20% 로 내려도 어두운 바탕 위에서 띠가 갈리고, 그 위의
     --ink(#E3E2E2)는 대비 4.5 를 넘는다 */
  --mark: rgba(230, 193, 132, .20);

  /* 어두운 감정서의 **면**. 2026-09-16 까지 이 이름들이 돌지 않아 어두운 화면 안에서
     `var(--white)` 흰 면 그대로였다 — 그 위에 밝은 글자(--ink #E3E2E2)가 서서 대비
     1,29 였다. 값을 치르고 공유받은 감정서를 여는 손님이 목차를 못 읽었다.

     시안(「0 · 먼저 읽기」)이 「어두운 감정서의 카드 면은 아직 이름이 없는 것」이라
     적어 두었기에 색을 지어내지 않고 **앱에 있는 뜻을 가져왔다** —
     `native/theme/dark.ts` 의 `pal.surface` 는 갈래 밝은 색을 5% 로 깐다.
     어두운 바탕 위에 흰색을 아주 옅게. 다른 색을 정하시면 이 몇 줄만 바꾼다.

     면이 밝을수록 밝은 글자의 대비가 준다. 4% 에서 본문 9,01 · 보조 4,19 다.
     `--white` 는 돌리지 않는다 — 그 이름은 「흰색」이라는 뜻이라 도는 것이 거짓말이다. */
  --glass-1: rgba(255, 255, 255, .04);
  --glass-2: rgba(255, 255, 255, .04);
  --paper-flush: rgba(255, 255, 255, .04);
  --paper-lift: rgba(255, 255, 255, .06);
  --glass-fill-70: rgba(255, 255, 255, .04);
}

/* Base */

body {
  background: var(--app-bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.78;
}

@media (max-width: 640px) {
  body { background: var(--app-bg-narrow); }
}

/* Type scale
 *
 * 크기는 이제 뿌리의 여덟 단(`--t-display` … `--t-micro`, 위 「글자 크기」)이
 * 들고 있다. 아래 `.ds-*` 줄은 **그 단을 고르는 자리**다 — 숫자를 여기에
 * 다시 적지 않는다.
 *
 * 아직 제 숫자를 적고 있는 다섯 줄(21 · 16 · clamp(15,4vw,27) · 12.5 · 11)은
 * 여덟 단에 없는 값이다. 여덟으로 모으는 일은 화면 위계를 새로 잡는 일이므로
 * 따로 한다 — `docs/DESIGN_TOKENS.md` 5장.
 *
 * `.ds-section-label` 은 9px 이었다. 여덟 단의 바닥(`--t-micro`)보다 낮고
 * iOS HIG · Material 이 공통으로 긋는 11 아래였다. 2026-09-11 에 바닥으로
 * 올렸다 — 자간을 벌린 대문자 라벨이라 가장 먼저 읽히지 않아도 되지만,
 * 읽을 수는 있어야 한다. */

.ds-screen-title { font: 700 21px/1.5 var(--serif); color: var(--ink); }
.ds-card-title   { font: 700 16px/1.5 var(--serif); color: var(--ink); }
.ds-figure       { font: 700 clamp(15px, 4vw, 27px)/1.3 var(--serif); font-variant-numeric: tabular-nums; }
.ds-body         { font: 400 13px/1.78 var(--sans); color: var(--ink-soft); }
.ds-list-item    { font: 500 12.5px/1.6 var(--sans); }
/* 2026-09-15 · 11px → 바닥(--t-micro 12). 제품 화면의 입력칸 안내(가입 비밀번호 · 동의 ·
   재설정 · 상태 줄)가 이 한 줄로 11px 에 서 있었다 — app.css 만 재던 그물 밖이었다. */
.ds-meta         { font: 400 var(--t-micro)/1.65 var(--sans); color: var(--mocha); }
/* 색은 도는 이름으로 — 밝은 면에서는 --bronze-700 그대로, 어두운 감정서에서는 밝은 금.
   못 박았더니 어두운 감정서의 목차 라벨이 대비 2,57 이었다(2026-09-17 실측). */
.ds-section-label { font: 400 var(--t-micro)/1.4 var(--mono); letter-spacing: .14em; color: var(--gold-ink); text-transform: uppercase; }
.ds-code         { font: 400 11px/1.5 var(--mono); }

/* Report body copy: serif, wider leading, indented paragraphs. */
/* 12px/1.92 에서 옮겼다(2026-09-14). 12px 은 라벨의 바닥이지 문단 크기가 아니고,
   명조 긴 글의 행간은 --lh-serif-read 한 값이다(.claude/rules/read.md 1장). */
.ds-report-body { font: 400 var(--t-bodySm)/var(--lh-serif-read) var(--serif); text-indent: 1em; }

/* Surfaces
 *
 * **카드 면의 주인은 `.ds-card` 하나다.** 화면별 클래스는 배치(여백·크기)만
 * 맡는다 — 전에는 카드를 칠하는 규칙이 403군데였고, 토큰을 바꿔도 화면이
 * 안 따라왔다. 그물 = `tests/test_web_card_surface.py`.
 *
 * 아래 셋은 `app.css` 에도 같은 이름이 있다(2026-09-11 실측).
 *
 *   `.ds-card`          두 파일의 본문이 **글자까지 같다.** 포털이 이쪽을 쓴다
 *   `.ds-card--accent`  두 파일이 **다르다.** 아래는 1.5px --bronze-500 테두리 +
 *                       --glass-2 면 + --sh-md. 제품 화면에서는 이 셋이 하나도
 *                       살지 않는다 — app.css 가 뒤에 실려 그쪽 `.ds-card` 와
 *                       `.ds-card--accent` 가 셋을 다 덮는다. 2026-09-11 에
 *                       app.css 쪽에 이기는 값을 다 적어 **주인을 한 파일로**
 *                       세웠다. 아래 본문은 `app.css` 를 읽지 않는
 *                       developer-portal.html 의 것이다
 *   `.ds-row`           값은 같고(44px) app.css 가 배치까지 얹는다
 */

.ds-card {
  background: var(--glass-1);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-md);
  box-shadow: var(--sh-sm);
  padding: var(--pad-card);
}

.ds-card--accent {
  border: 1.5px solid var(--bronze-500);
  background: var(--glass-2);
  box-shadow: var(--sh-md);
}

.ds-note {
  background: var(--bronze-veil-07);
  border: 1px solid var(--bronze-veil-16);
  border-radius: 12px;
  padding: 12px 13px;
}

.ds-warn {
  background: rgba(140, 47, 67, .08);
  border: 1px solid rgba(140, 47, 67, .26);
  border-radius: 12px;
  padding: 12px 13px;
}

/* The hairline is the only rule in the system. No card outlines, no
 * decorative lines beside section headings. */
.ds-divider { border: 0; border-top: 1px solid var(--line); }

/* Controls */

.ds-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: var(--h-cta);
  padding: 0 18px;
  border: 1px solid rgba(118, 90, 39, .40);
  border-radius: var(--r-sm);
  background: var(--cta);
  box-shadow: var(--sh-cta);
  color: var(--on-cta);
  font: 700 15px var(--sans);
  cursor: pointer;
}

.ds-btn-secondary {
  min-height: var(--h-secondary);
  padding: 0 16px;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-sm);
  background: var(--glass-2);
  color: var(--ink);
  font: 500 14px var(--sans);
  cursor: pointer;
}

.ds-btn-ghost {
  min-height: var(--h-secondary);
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--ink-soft);
  font: 500 14px var(--sans);
  cursor: pointer;
}

/* 한 칩(2026-09-15 「가 · 밤색 채움」). app.css 의 `.chip` 과 값이 같다 —
   흰 알약 34 · 13 굵게 · 켜지면 밤색으로 채운다. 금색 면은 쓰지 않는다 */
.ds-chip {
  display: inline-grid;
  place-items: center;
  min-height: var(--h-chip);
  padding: 0 14px;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-pill);
  background: var(--glass-3);
  color: var(--ink-soft);
  font: 700 var(--t-caption)/var(--lh-caption) var(--sans);
  letter-spacing: 0;
  cursor: pointer;
}

.ds-chip[aria-pressed="true"],
.ds-chip.is-on {
  background: var(--brown-mid);
  border-color: var(--brown-mid);
  color: var(--paper-0);
}

.ds-row    { min-height: var(--h-row); }
.ds-choice { min-height: var(--h-choice); }

/* A 34px circle that still answers to a 44x44 finger. */
.ds-icon-btn {
  position: relative;
  width: 34px;
  height: 34px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: var(--glass-3);
  cursor: pointer;
}

.ds-icon-btn::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--hit-min);
  height: var(--hit-min);
  transform: translate(-50%, -50%);
}

/* Social sign-in. Brand colours are used as published, never tinted to the
 * mocha palette — and neither is anything else each provider pins down.
 *
 * The four buttons are NOT one shape. Every provider publishes its own corner
 * radius, symbol size, left padding and label weight, and every provider fixes
 * the wording of the label. Height alone is shared, so the Apple button carries
 * the same weight as the rest (App Store guideline 4.8). Native reads the same
 * numbers from `native/theme/social.ts`; the ledger is `docs/SOCIAL_BUTTONS.md`. */
.ds-social {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  height: var(--h-social);
  border-radius: var(--social-radius, var(--r-sm));
  border: 1px solid transparent;
  font: var(--social-weight, 700) 15px var(--sans);
  cursor: pointer;
}

.ds-social-symbol {
  position: absolute;
  left: var(--social-pad, 16px);
  top: 50%;
  width: var(--social-mark, 18px);
  height: var(--social-mark, 18px);
  transform: translateY(-50%);
}

.ds-social-symbol svg,
.ds-social-symbol img { width: 100%; height: 100%; object-fit: contain; display: block; }

.ds-social--kakao {
  background: var(--kakao-bg); color: var(--kakao-ink);
  --social-radius: 12px; --social-mark: 20px; --social-pad: 16px; --social-weight: 700;
}
.ds-social--naver {
  background: var(--naver-bg); color: var(--naver-ink);
  --social-radius: 6px; --social-mark: 20px; --social-pad: 16px; --social-weight: 700;
}
/* Google asks for Medium, not Bold, and a 4px corner with 12px of left padding. */
.ds-social--google {
  background: var(--google-bg); color: var(--google-ink); border-color: var(--google-border);
  --social-radius: 4px; --social-mark: 20px; --social-pad: 12px; --social-weight: 500;
}
/* 애플 단추는 웹에 없다 — 지침 4.8은 앱스토어에 올라가는 앱을 겨눈다.
 * 앱 쪽 값은 `native/theme/social.ts` 에 있다. 여기에 안 불리는 규칙을
 * 두면 다음 사람이 웹에도 있는 줄 안다. */

/* Layout */

/* Breakpoints are 640 and 1024. Navigation moves; its items, labels and
 * order never change. Content is never added or removed by width. */
.ds-shell { padding-inline: var(--pad-side); }

@media (min-width: 641px) {
  .ds-shell { max-width: 720px; margin-inline: auto; }
}

@media (min-width: 1024px) {
  .ds-shell { max-width: 1200px; }
}

.ds-nav-bottom { height: var(--h-tab); }
.ds-nav-top    { height: var(--h-topbar); }

@media (min-width: 1024px) {
  .ds-nav-bottom { display: none; }
}

@media (max-width: 1023px) {
  .ds-nav-top { display: none; }
}

/* Immersive screens (payment, legal, errors) hide both navs and show only
 * the logo plus the SSL notice. */
.ds-immersive .ds-nav-bottom,
.ds-immersive .ds-nav-top { display: none; }

/* Accessibility */

/* Never outline:none on its own. */
:where(a, button, [role="button"], input, select, textarea, [tabindex]):focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* Reading text stays at 11px or above. Meta labels may go to 9px but must
 * never be the only place a fact appears. Nothing goes to 8.5px or below. */
.ds-meta-min { font-size: 9px; }

/* Colour is never the only signal. Disabled things get a dimmed colour, a
 * not-allowed cursor, and a sentence saying why.
 *
 * The strike used to sit on this blanket rule. text-decoration paints down
 * into every descendant, so a parked card had its title, its description AND
 * the line explaining why it was parked all struck through — the one line the
 * reader most needed. Keep the strike as something you opt into, on the short
 * label it belongs on. */
[aria-disabled="true"],
.is-disabled {
  color: #9C8977;
  cursor: not-allowed;
}
.is-struck {
  text-decoration: line-through;
}

/* `app.css` 가 같은 규칙을 1ms 로 다시 적는다. 제품 화면에서는 그쪽이 이기고
 * 이 값은 개발자 포털에만 닿는다. 둘 다 "움직임을 없앤다"는 뜻이라 손님이
 * 보는 결과는 같다 — 두 파일이 한 규칙을 두고 갈린 자리라서 적어 둔다. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Wide content scrolls inside itself; the page body never scrolls sideways. */
.ds-scroll-x { overflow-x: auto; }

/* ── 넓은 화면 글자 (1024px 이상) · 2026-09-23 ─────────────────────────
 * 웹은 휴대폰 · 태블릿 · 데스크톱이 같은 크기였다. 1440 에서 잰 글자의 78% 가
 * 12~13px(micro · caption)이었고, 1440 캔버스에서 그 크기는 각주처럼 읽혔다.
 * **단은 여덟 그대로 두고 값만 한 칸 올린다** — 이름과 위계는 바뀌지 않는다.
 * 14 · 15 · 16 · 17 · 19 · 23 · 29 · 35. 앱(430 폭)과 좁은 웹은 위 값 그대로다.
 * 근거와 전후 측정: design-system/MASTER.md 「넓은 화면 한 층」. */
@media (min-width: 1024px) {
  :root {
    --t-display: 2.1875rem;
    --t-title: 1.8125rem;
    --t-headline: 1.4375rem;
    --t-body: 1.1875rem;
    --t-bodySm: 1.0625rem;
    --t-label: 1rem;
    --t-caption: 0.9375rem;
    --t-micro: 0.875rem;
  }
}
