# Typography

oc-ui typography foundation은 19개 variant와 `normal | medium | bold` weight 조합을 제공합니다. variant 이름은 정보 위계와 읽기 맥락의 계약이고, size·line-height 값은 responsive profile과 consumer override에 따라 달라질 수 있는 기본값입니다.

## Variant hierarchy

- `display1`~`display3`: 캠페인 hero나 대형 숫자처럼 짧고 가장 강한 표현
- `title1`~`title3`: 페이지 표제
- `heading1`~`heading2`: 큰 section의 제목
- `headline1`~`headline2`: 내비게이션과 소섹션(sub-section)의 제목
- `body1`~`body2`: 일반 본문과 UI 설명. `body1`이 기본 페이지 typography
- `label1`~`label2`: 대상을 지칭하는 '라벨' 텍스트 — form field label, 항목명, button·menu 같은 control의 라벨
- `caption1`~`caption2`: metadata, timestamp, 짧은 보조 정보

variant 숫자가 작을수록 같은 계층 안에서 더 큽니다. 계층을 오직 크기 선택 도구로 사용하지 말고 문서 구조와 UI 역할에 맞춰 선택합니다.

## Reading variants

`body1reading`, `body2reading`, `label1reading`은 대응 기본 variant와 font-size·letter-spacing·weight가 같고 line-height만 더 넓습니다. 여러 줄로 이어지는 본문, 안내문, 조밀한 label 묶음처럼 읽기 호흡이 필요한 경우에 사용합니다. 한 줄 control label이나 짧은 badge에는 기본 variant를 유지합니다.

## Responsive stops

기본 profile은 `sm / md / lg / xl` 4개 stop을 사용합니다.

- `body*`, `label*`, `caption*`은 `md` stop을 포함합니다.
- `heading*`, `headline*`, `body*`, `label*`, `caption*`은 `xl` stop을 포함합니다.
- `display*`, `title*`은 `sm / lg`, `heading*`과 `headline*`은 `sm / lg / xl` 기본값을 가집니다.
- 정의되지 않은 stop은 responsive segment에서 인접한 유효 stop을 기준으로 보간·유지됩니다. 표의 `—`는 token이 없다는 뜻이 아니라 해당 variant map에 별도 stop 값이 없다는 뜻입니다.

## Weight policy

모든 variant는 `normal`, `medium`, `bold` 세 이름을 제공하지만 `bold`의 숫자는 계층에 따라 낮아집니다. display·title은 700, heading·headline·body는 600, label은 550, caption1은 540, caption2는 530입니다. 작은 글자에서 지나치게 뭉치는 것을 피하면서 의미상 같은 `bold` 역할을 유지하기 위한 정책입니다.

## 기본값 표

<!-- prettier-ignore-start -->
<!-- generated:typography:start -->
> 아래 표는 기본 responsive profile의 SCSS map에서 생성됩니다. 값은 고정 스펙이 아니라 기본값입니다. line-height 괄호 안 숫자는 `line-height / font-size` 비율입니다.

| Variant | Size sm | Size md | Size lg | Size xl | Line-height sm | Line-height md | Line-height lg | Line-height xl | Letter spacing | Normal | Medium | Bold |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| `display1` | 48px | — | 64px | — | 62px (1.29) | — | 82px (1.28) | — | 0em | 400 | 500 | 700 |
| `display2` | 40px | — | 48px | — | 52px (1.30) | — | 62px (1.29) | — | 0em | 400 | 500 | 700 |
| `display3` | 36px | — | 40px | — | 48px (1.33) | — | 52px (1.30) | — | 0em | 400 | 500 | 700 |
| `title1` | 32px | — | 36px | — | 44px (1.38) | — | 48px (1.33) | — | 0em | 400 | 500 | 700 |
| `title2` | 28px | — | 32px | — | 38px (1.36) | — | 42px (1.31) | — | 0em | 400 | 500 | 700 |
| `title3` | 24px | — | 28px | — | 32px (1.33) | — | 36px (1.29) | — | 0em | 400 | 500 | 700 |
| `heading1` | 22px | — | 24px | 26px | 30px (1.36) | — | 32px (1.33) | 34px (1.31) | 0em | 400 | 500 | 600 |
| `heading2` | 20px | — | 22px | 24px | 28px (1.40) | — | 30px (1.36) | 32px (1.33) | 0em | 400 | 500 | 600 |
| `headline1` | 18px | — | 20px | 22px | 26px (1.44) | — | 28px (1.40) | 30px (1.36) | 0em | 400 | 500 | 600 |
| `headline2` | 17px | — | 18px | 20px | 24px (1.41) | — | 26px (1.44) | 28px (1.40) | 0em | 400 | 500 | 600 |
| `body1` | 16px | 17px | 18px | 20px | 24px (1.50) | 26px (1.53) | 28px (1.56) | 30px (1.50) | 0em | 400 | 500 | 600 |
| `body1reading` | 16px | 17px | 18px | 20px | 26px (1.63) | 28px (1.65) | 30px (1.67) | 32px (1.60) | 0em | 400 | 500 | 600 |
| `body2` | 15px | 16px | 17px | 18px | 22px (1.47) | 24px (1.50) | 26px (1.53) | 28px (1.56) | 0em | 400 | 500 | 600 |
| `body2reading` | 15px | 16px | 17px | 18px | 24px (1.60) | 26px (1.63) | 28px (1.65) | 30px (1.67) | 0em | 400 | 500 | 600 |
| `label1` | 14px | 15px | 16px | 17px | 20px (1.43) | 22px (1.47) | 24px (1.50) | 26px (1.53) | 0.01em | 400 | 500 | 550 |
| `label1reading` | 14px | 15px | 16px | 17px | 22px (1.57) | 24px (1.60) | 26px (1.63) | 28px (1.65) | 0.01em | 400 | 500 | 550 |
| `label2` | 13px | 14px | 15px | 16px | 18px (1.38) | 20px (1.43) | 22px (1.47) | 24px (1.50) | 0.01em | 400 | 500 | 550 |
| `caption1` | 12px | 13px | 14px | 15px | 16px (1.33) | 18px (1.38) | 20px (1.43) | 22px (1.47) | 0.01em | 400 | 500 | 540 |
| `caption2` | 11px | 12px | 13px | 14px | 14px (1.27) | 16px (1.33) | 18px (1.38) | 20px (1.43) | 0.01em | 400 | 500 | 530 |
<!-- generated:typography:end -->
<!-- prettier-ignore-end -->

## Usage

raw `--oc-typo-size-*`, `--oc-typo-height-*`, `--oc-typo-spacing-*`, `--oc-typo-weight-*`를 직접 조합하지 말고 반드시 `typo()` mixin을 사용합니다. mixin은 네 속성을 같은 variant contract에서 출력하고 runtime `--oc-typo-size-factor`도 반영합니다.

```scss
@use '@orioncactuscorp/ui/scss/mixins/typo' as *;

.pageTitle {
  @include typo(title1, bold);
}

.articleBody {
  @include typo(body1reading, normal);
}

.fieldLabel {
  @include typo(label1, medium);
}
```

## Customize

### Size and line-height maps

foundation을 직접 compile할 때 `$oc-typo-size-overrides`와 `$oc-typo-height-overrides`로 필요한 variant·stop만 덮습니다. 역할 이름은 유지하고 제품에 필요한 기본값만 조정합니다.

```scss
@use '@orioncactuscorp/ui/scss/foundations/typo' as * with (
  $oc-typo-size-overrides: (
    title1: (
      sm: 36,
    ),
  ),
  $oc-typo-height-overrides: (
    title1: (
      sm: 48,
    ),
  )
);
```

### Runtime size factor

`--oc-typo-size-factor`는 size와 line-height에 함께 적용되는 runtime multiplier입니다. 특정 subtree의 접근성 확대나 preview에 사용할 수 있지만, variant 간 위계를 다시 설계하는 용도로 남용하지 않습니다.

```css
.largeTypeScope {
  --oc-typo-size-factor: 1.125;
}
```

fluid·stepped·static 출력과 active stop 범위는 [Responsive Foundation Profile](./responsive-foundation-profile.md), mixin signature는 [SCSS Helpers](./scss-helpers.md)를 참조하세요. Storybook typography matrix는 현재 foundation profile의 CSS variable을 사용하므로 override 환경의 실값을 그대로 보여줍니다.
