# AI 꾸러미 — 글자 테 · 그러데이션 글자 — -webkit-text-stroke (outlined text)
> 같은 글자를 네 겹 겹쳐 — 뒤는 굵은 어두운 테와 그림자, 가운데 흰 테, 앞은 그러데이션 글자, 맨 위 흐르는 빛 — 만화 같은 제목 글씨를 만든다.  
> 견본: https://ai-techstudio.web.app/#t/u64

이 문서를 코드 도우미(Claude Code · Cursor · ChatGPT 등)에 그대로 주면 돼요. 「## 주문서」 가 할 일, 나머지는 참고 자료예요.

## 주문서

### 만들어 줘: 글자 테 · 그러데이션 글자 — -webkit-text-stroke (outlined text)

#### 1. 목표
게임 시작 화면 제목을 만화 제목 글씨로 꾸며 줘 — 굵은 어두운 테, 흰 안쪽 테, 위에서 아래로 노랑 → 주황 그러데이션, 글자 위를 흐르는 빛. 분위기는 소년 만화 금빛 제목.

#### 2. 핵심 기술 용어
- **-webkit-text-stroke (outlined text)** — 글자 테두리
- **background-clip: text (gradient text)** — 배경을 글자 모양으로 잘라 그러데이션 글자
- **Layered text (stacked spans)** — 같은 글자를 겹겹이 쌓기
- **Shine sweep (moving background-position)** — 글자 위로 흐르는 빛

#### 3. 환경
- 플랫폼: TypeScript (브라우저), 라이브러리 없이 — 화면과 떨어진 순수 함수로
- 화면: 브라우저 — PC · 폰 모두

#### 4. 조건
- 테는 별도 뒤 겹에서 (앞 그러데이션 글자에 테를 바로 걸면 글자가 가늘어진다)
- -webkit-background-clip: text 와 background-clip: text 를 함께, 글자색은 transparent
- 겹은 모두 같은 글자 · 같은 글꼴 · position: absolute; inset: 0 으로 딱 겹치게
- 긴 번역 글(독일어 등)도 한 줄에 들어가게 white-space: nowrap + 글자 크기 줄이기

#### 5. 완성 기준 (이게 보이면 성공)
- 위 보통 글자와 아래 꾸민 글자를 나란히 보면 테 · 두께 · 그러데이션이 확실히 보인다
- 빛 줄기가 2.6초마다 글자 위를 지나가고, 그때 글자가 살짝 튀어 오른다
- 빛 흐르는 빠르기 슬라이더로 속도가 바뀐다
- 다른 언어로 바꿔도 글자가 그림이 아니라 글이라 그대로 번역된다

#### 6. 진행 방식
- 핵심 코드 위주로, 설명은 짧게. 내 프로젝트에 끼워 넣기 쉬운 함수 · 클래스로 나눠 줘.
- 처음 화면에 바로 결과가 보이게, 그리고 켬/끔(또는 전/후) 비교를 할 수 있게 만들어 줘.
- 그림 · 소리 · 모델 파일이 필요하면 코드로 만든 임시 대체물로 먼저 돌아가게 하고, 진짜 파일로 바꿀 자리를 표시해 줘.
- 마지막에 「확인 방법」(무엇을 보면 성공인지)과 「조절할 값」 목록을 짧게 정리해 줘.
- 답변과 코드 주석은 한국어로 해 줘.

## 원리
- 글자 테(-webkit-text-stroke)는 글자 선의 안팎으로 반씩 그려져 굵히면 글자 속을 파먹는다 — 그래서 테만 맡는 뒤 겹을 따로 둔다.
- 맨 뒤: 어두운 글자 + 굵은 테(2.6cqmin) + 아래로 비킨 text-shadow 두 개(두께 · 그림자). 가운데: 흰 글자 + 흰 테(1.2cqmin).
- 앞: background: linear-gradient(…) 를 background-clip: text 로 글자 모양만 남기고 color: transparent.
- 맨 위: 빛 줄기 그러데이션을 같은 방법으로 글자에 자르고 background-position 을 옮겨 빛이 흐르게 한다.

## 핵심 코드 — 네 겹 만화 제목 글씨
(발췌: demos/demosDraw2d.ts u64 의 CSS · HTML · update() 를 정리)
```ts
const css =
  '.fancy{position:relative;font-size:19cqmin;line-height:1.1;white-space:nowrap}' +
  // ① 뒤: 굵은 어두운 테 + 두께 · 그림자
  '.fancy .back{position:absolute;inset:0;color:#2a1600;-webkit-text-stroke:2.6cqmin #2a1600;' +
  'text-shadow:0 1.6cqmin 0 #2a1600,0 2.4cqmin 3cqmin #0008}' +
  // ② 가운데: 흰 안쪽 테
  '.fancy .mid{position:absolute;inset:0;color:#fff;-webkit-text-stroke:1.2cqmin #fff}' +
  // ③ 앞: 그러데이션 글자
  '.fancy .front{position:relative;background:linear-gradient(180deg,#fffbd0 0%,#ffe24a 42%,#ff9a1a 62%,#ff6a00 100%);' +
  '-webkit-background-clip:text;background-clip:text;color:transparent}' +
  // ④ 맨 위: 흐르는 빛
  '.fancy .shine{position:absolute;inset:0;background:linear-gradient(105deg,#0000 40%,#fffffff0 50%,#0000 60%) no-repeat;' +
  'background-size:250% 100%;-webkit-background-clip:text;background-clip:text;color:transparent}';

const word = '수학 검문소!';
const html = '<div class="fancy">' + ['back', 'mid', 'front', 'shine'].map((c) => '<span class="' + c + '">' + word + '</span>').join('') + '</div>';

function update(t: number, fancy: HTMLElement, shine: HTMLElement) {
  const tt = t % 2.6;
  shine.style.backgroundPosition = 120 - Math.min(1, tt / 1.2) * 140 + '% 0';
  const pop = tt < 0.35 ? 1 + Math.sin((tt / 0.35) * Math.PI) * 0.08 : 1;     // 빛이 지날 때 톡
  fancy.style.transform = 'rotate(' + (-3 + Math.sin(t * 1.5) * 1.5) + 'deg) scale(' + pop + ')';
}
```

## 흔한 실수 · 확인 목록
- [ ] **그러데이션 글자에 바로 text-stroke 를 걸면 글자가 가늘어지고 테가 그러데이션을 덮는다** — 테는 뒤 겹이 맡고, 앞 겹은 테 없이 그러데이션만.
- [ ] **background-clip: text 만 쓰면 일부 브라우저에서 네모 그러데이션이 보인다** — -webkit-background-clip: text 를 함께 쓰고 color: transparent 를 준다.
- [ ] **겹마다 글자를 따로 쓰면 하나만 바꿔 어긋난다** — 같은 글자 변수 하나로 네 겹을 만든다 (번역 글도 한 번만).
- [ ] **긴 번역 글이 두 줄로 꺾이면 겹이 어긋난다** — white-space: nowrap 으로 한 줄을 지키고, 넘치면 글자 크기를 줄인다.

## 완성 기준 체크리스트
- [ ] 위 보통 글자와 아래 꾸민 글자를 나란히 보면 테 · 두께 · 그러데이션이 확실히 보인다
- [ ] 빛 줄기가 2.6초마다 글자 위를 지나가고, 그때 글자가 살짝 튀어 오른다
- [ ] 빛 흐르는 빠르기 슬라이더로 속도가 바뀐다
- [ ] 다른 언어로 바꿔도 글자가 그림이 아니라 글이라 그대로 번역된다

## 이 기술 정보
- id: `u64` · 분류: 2D · 화면 › CSS · 화면 틀 · 공통 · 난이도 쉬움 · 폰 부담 가벼움 (폰 OK) — 글자 네 겹 · 그러데이션뿐. 빛이 흐르는 칸 하나는 폰도 가볍다.
- 라이브 견본 (브라우저에서 직접 조작): https://ai-techstudio.web.app/#t/u64
- 쓰면 좋을 때: 게임 이름 · 결과처럼 크게 한 번 보이는 글자 / 그림 파일 대신 번역되는 제목 글씨가 필요할 때
- 쓰지 말 때: 본문 · 작은 글씨 — 테가 글자를 뭉갠다. 큰 제목(화면 높이 10% 이상)에만 / 글자를 매 프레임 바꾸는 점수 — 겹마다 다시 그려야 한다

## 견본 실제 코드 (라이브 견본이 돌리는 코드 — three.js · TypeScript)
### u64 견본 항목 — `src/demos/demosDraw2d.ts:1405`
```ts
  u64: {
    kind: 'dom',
    caption: '위 보통 글자 · 아래 같은 글자에 굵은 테(text-stroke) + 그러데이션 글자(background-clip:text) + 흐르는 빛 = 만화 제목',
    make(box) {
      const root = domRoot(
        box,
        'd2-title',
        `.d2-title{background:radial-gradient(circle at 50% 62%,#fff4 0 10%,#0000 45%),repeating-conic-gradient(from 0deg at 50% 62%,#2a3a9a 0 5deg,#1c2766 5deg 10deg);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4cqmin}
         .d2-title .plain{font-family:${TF};font-size:12cqmin;color:#fff;position:relative}
         .d2-title .tag{font-family:${F};font-size:4.4cqmin;font-weight:800;padding:.2em .8em;border-radius:99px;background:#000a;margin-bottom:-2cqmin}
         .d2-title .tag.on{background:#ff6fa8}
         .d2-title .fancy{position:relative;font-family:${TF};font-size:19cqmin;line-height:1.1;white-space:nowrap}
         .d2-title .fancy .back{position:absolute;inset:0;color:#2a1600;-webkit-text-stroke:2.6cqmin #2a1600;text-shadow:0 1.6cqmin 0 #2a1600,0 2.4cqmin 3cqmin #0008}
         .d2-title .fancy .mid{position:absolute;inset:0;color:#fff;-webkit-text-stroke:1.2cqmin #fff}
         .d2-title .fancy .front{position:relative;background:linear-gradient(180deg,#fffbd0 0%,#ffe24a 42%,#ff9a1a 62%,#ff6a00 100%);-webkit-background-clip:text;background-clip:text;color:transparent}
         .d2-title .fancy .shine{position:absolute;inset:0;background:linear-gradient(105deg,#0000 40%,#fffffff0 50%,#0000 60%) no-repeat;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;color:transparent}`,
        `<div class="tag">보통</div><div class="plain">수학 검문소!</div>
         <div class="tag on">테 + 그러데이션</div>
         <div class="fancy"><span class="back">수학 검문소!</span><span class="mid">수학 검문소!</span><span class="front">수학 검문소!</span><span class="shine">수학 검문소!</span></div>`,
      );
      const fancy = q(root, '.fancy');
      const shine = q(root, '.shine');
      let speed = 1;
      return {
        update(t) {
          const tt = (t * speed) % 2.6;
          shine.style.backgroundPosition = `${120 - clamp01(tt / 1.2) * 140}% 0`;
          const pop = tt < 0.35 ? 1 + Math.sin((tt / 0.35) * Math.PI) * 0.08 : 1;
          fancy.style.transform = `rotate(${-3 + Math.sin(t * 1.5) * 1.5}deg) scale(${pop})`;
        },
        controls: [{ type: 'range', label: '빛 흐르는 빠르기', min: 0.2, max: 3, step: 0.1, value: 1, on: (v) => (speed = v) }] as Control[],
      };
    },
  }
```

## 관련 기술
- 같은 방법으로 만든 효과 예시: [글자 속 그림 · 영상](https://ai-techstudio.web.app/ai/t/i100.md) `i100`
- 먼저 알면 좋은 기술: [CSS 무늬 (그러데이션 · 데이터 SVG)](https://ai-techstudio.web.app/ai/t/u62.md) `u62`
- 다음에 해 볼 기술: [만화 펜선 + 스크린톤](https://ai-techstudio.web.app/ai/t/i335.md) `i335`
- 참고 문서: [MDN — -webkit-text-stroke](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-stroke) · [MDN — background-clip](https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip)
