# Design System — Cyber Neon (사이버 네온)

> 거의 검정에 가까운 남보라 바탕 위에 마젠타·시안 네온이 번지는 게임 HUD 스타일. e스포츠 대회, 게임 동호회, 해커톤, 연말 행사 페이지처럼 "오늘은 놀아도 되는 날"을 알리는 화면에 쓴다.
> 공통 규칙은 `anti-slop.md`를 함께 적용한다. 미리보기: `preview/cyber-neon.html` (사내 e스포츠 대회 페이지 예시)

> **anti-slop 예외 범위**: 이 문서는 anti-slop.md 의 "글로우 금지"를 **5절 효과 레시피가 정한 범위에 한해서만** 풀어 준다. 글로우는 화면당 4곳 이하, 정해진 3가지 레시피만 쓴다. 그 밖의 anti-slop 원칙(이모지 금지, 현실적인 한국어 더미 데이터, 아이콘 카드 3개 나열 금지, 빈 상태·로딩·에러 포함)은 그대로 지킨다. 보라→인디고 **그라디언트 배경**과 떠다니는 블롭은 이 스타일에서도 금지다.

---

## 1. 분위기

밤 경기장 전광판 앞에 선 느낌이다. 바탕은 빛이 거의 없는 남보라, 그 위에 **얇은 네온 선**과 **모노 숫자**가 떠 있다. 화려함은 색을 많이 쓰는 데서 오지 않는다. 어두운 면이 넓고 빛나는 곳이 적어야 빛이 산다. 화면의 80%는 어둡고 조용하며, 지금 봐야 하는 것(진행 중인 경기, 카운트다운, 1위 점수)만 빛난다.

모서리는 둥글지 않다. 카드 한쪽 귀퉁이를 사선으로 잘라낸(`clip-path`) 각진 패널이 게임 HUD 를 떠올리게 한다. 숫자는 전부 모노 스페이스라 점수가 바뀌어도 자리가 흔들리지 않는다. 배경에는 아주 옅은 격자와 스캔라인이 깔려 "화면 속 화면" 질감을 준다. 눈에 띌 정도면 너무 진한 것이다.

**어울리는 곳**
- 사내 e스포츠·보드게임 대회, 게임 동호회 모집
- 해커톤·바이브 코딩 경진대회 결과 발표
- 연말 행사·송년회 경품 추첨, 실시간 투표 결과판
- 신규 IT 서비스 런칭 티저 (짧게 보는 한 장짜리)

**쓰면 안 되는 곳**
- 업무 시스템, 결재·인사·재무 화면 (하루 종일 보는 화면에 글로우는 피로를 만든다)
- 품질·안전·GMP 관련 공지, 의약품 정보, 환자·고객 대면 페이지 (신뢰가 먼저다)
- 긴 글을 읽는 문서·가이드 (어두운 바탕에 장문은 눈이 아프다)
- 고령 사용자가 많은 화면, 인쇄가 필요한 화면

**핵심 특징**
- 바탕 `#0B0816`, 표면 2단계(`#140F26`, `#1C1534`)로만 깊이를 만든다
- 네온 2색: 마젠타(주 액션·진행 중) + 시안(정보·데이터). 3번째 네온 금지
- 1px 네온 테두리 + 귀퉁이 사선 컷(clip-path), 둥근 모서리 없음
- 숫자·시간·점수는 JetBrains Mono + `tabular-nums`
- 영문 라벨은 Chakra Petch 대문자, 한글은 Pretendard
- 배경 격자 + 스캔라인은 투명도 4% 이하

---

## 2. 컬러 팔레트 & 역할

### Dark (유일한 모드)

```css
:root {
  /* 표면 */
  --bg:         #0B0816;   /* 페이지 바탕, 남보라 검정 */
  --surface:    #140F26;   /* 기본 패널 */
  --surface-2:  #1C1534;   /* 강조 패널, 입력, 표 헤더 */
  --line:       #2E2550;   /* 기본 테두리, 구분선 */
  --line-2:     #43386E;   /* 호버 테두리 */

  /* 텍스트 */
  --text:       #EDE9FF;   /* 본문 (bg 대비 16.6:1) */
  --muted:      #9D94C4;   /* 라벨·보조 (bg 대비 7.1:1) */
  --faint:      #6A6290;   /* 메타·축 눈금, 14px 이상에만 (bg 대비 3.6:1, 장식용) */

  /* 네온 */
  --neon-m:     #FF3DCB;   /* 마젠타: 주 버튼, LIVE, 진행 중 경기 */
  --neon-c:     #2EF2FF;   /* 시안: 데이터, 카운트다운, 링크, 포커스 */
  --neon-m-dim: rgba(255, 61, 203, .14);  /* 마젠타 면 채움 */
  --neon-c-dim: rgba(46, 242, 255, .12);  /* 시안 면 채움 */

  /* 상태 (네온과 별개, 글로우 없음) */
  --win:        #7CFFB2;   /* 승리·완료 */
  --warn:       #FFC53D;   /* 지연·대기 */
  --danger:     #FF5C7A;   /* 오류·실격 */

  --on-neon:    #0B0816;   /* 네온 배경 위 글자 */
}
```

### 라이트 모드는 없다

네온 글로우는 주변이 어두울 때만 "빛"으로 읽힌다. 밝은 바탕에 같은 마젠타·시안을 쓰면 형광펜 낙서처럼 보이고, 시안(`#2EF2FF`)은 흰 바탕 대비가 1.3:1 로 글자로 쓸 수 없다. 라이트가 꼭 필요한 화면이면 이 스타일을 쓰지 말고 다른 스타일(예: `bento.md`)을 고른다. 다만 `prefers-contrast: more` 사용자를 위해 글로우를 끄는 고대비 변형은 8절에 둔다.

### 역할 규칙

| 토큰 | 쓰는 곳 | 쓰지 않는 곳 |
|---|---|---|
| `--neon-m` | 주 버튼 1개, LIVE 배지, 진행 중 경기 테두리, 1위 강조 | 본문 글자, 패널 배경 전체, 보조 버튼 |
| `--neon-c` | 카운트다운 숫자, 차트 선, 링크, 포커스 링, 선택된 탭 | 경고·오류 표시 |
| `--surface-2` | 강조 패널, 표 헤더, 입력 바탕 | 페이지 바탕 |
| `--win/--warn/--danger` | 상태 배지(글자 라벨과 함께) | 장식, 글로우 |
| `--faint` | 14px 이상 메타, 축 눈금 | 본문, 12px 이하 글자 |

**네온 2색 원칙**: 한 화면에서 마젠타는 "지금 일어나는 것", 시안은 "정보·숫자"다. 둘을 같은 요소에 겹치지 않는다. 대진표에서 진행 중 경기는 마젠타, 끝난 경기의 승자 점수는 `--text`, 다음 경기 시각은 시안.

---

## 3. 타이포그래피

| 역할 | 서체 | 불러오기 |
|---|---|---|
| 한글 UI·본문 | **Pretendard Variable** | `cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css` |
| 영문 디스플레이·라벨 | **Chakra Petch** 500/600/700 | Google Fonts |
| 숫자·시간·점수·코드 | **JetBrains Mono** 400/500/700 | Google Fonts |

```css
--font-sans:    "Pretendard Variable", Pretendard, -apple-system, sans-serif;
--font-display: "Chakra Petch", "Pretendard Variable", sans-serif;
--font-num:     "JetBrains Mono", ui-monospace, monospace;
.num { font-family: var(--font-num); font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.eyebrow { font-family: var(--font-display); font-size: 12px; font-weight: 600;
           letter-spacing: .16em; text-transform: uppercase; color: var(--neon-c); }
```

Chakra Petch 는 한글 글리프가 없다. **한글 제목에는 쓰지 않는다** (폴백 Pretendard 로 떨어져 굵기가 어긋난다). 영문 대문자 라벨(`GRAND FINAL`, `LIVE`, `ROUND 2`)과 짧은 영문 로고에만 쓴다.

### 스케일 (6단계 고정)

| 토큰 | 크기 / 굵기 / 자간 | 서체 | 용도 |
|---|---|---|---|
| `display` | `clamp(40px, 4.4vw, 56px)` / 700 / -0.02em | JetBrains Mono | 카운트다운·결승 점수 1곳 |
| `h1` | 30px / 800 / -0.03em | Pretendard | 페이지 제목 (한글) |
| `h2` | 18px / 700 / -0.02em | Pretendard | 패널 제목 |
| `body` | 14px / 400 / line-height 1.6 | Pretendard | 설명, 목록 |
| `label` | 12px / 600 / 0.16em 대문자 | Chakra Petch | 영문 라벨·배지 |
| `score` | 22px / 700 | JetBrains Mono | 대진표·점수판 숫자 |

원칙: 한글은 굵기로, 영문 라벨은 자간으로, 숫자는 모노로. 글로우 글자는 `display`·`score` 크기(22px 이상)에서만 허용한다.

---

## 4. 컴포넌트

### 패널 (기본 카드)

귀퉁이 하나를 12px 사선으로 자른다. `clip-path` 는 `border` 도 함께 잘라내므로, 테두리는 **바깥 요소 배경 + 1px 안쪽 요소** 2겹으로 그린다.

```css
.panel {
  --cut: 12px;
  position: relative;
  background: var(--line);                 /* 테두리 색 */
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
  padding: 1px;                            /* 테두리 두께 */
}
.panel > .in {
  background: var(--surface);
  clip-path: inherit;
  padding: 20px;
  height: 100%;
}
.panel--live { background: var(--neon-m); }   /* 진행 중: 테두리만 마젠타 */
.panel-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
```

### 버튼

```css
.btn {
  --cut: 8px;
  display: inline-flex; align-items: center; gap: 8px;
  height: 40px; padding: 0 20px; border: 0; cursor: pointer;
  font: 700 14px var(--font-sans);
  clip-path: polygon(var(--cut) 0, 100% 0, 100% calc(100% - var(--cut)),
                     calc(100% - var(--cut)) 100%, 0 100%, 0 var(--cut));
  transition: filter .2s ease, transform .2s ease;
}
.btn-primary { background: var(--neon-m); color: var(--on-neon); }    /* 화면에 1개 */
.btn-primary:hover { filter: brightness(1.12); }
.btn-ghost  { background: var(--surface-2); color: var(--text);
              box-shadow: inset 0 0 0 1px var(--line-2); }
.btn-ghost:hover { box-shadow: inset 0 0 0 1px var(--neon-c); color: var(--neon-c); }
.btn:focus-visible { outline: 2px solid var(--neon-c); outline-offset: 3px; }
.btn:disabled { background: var(--surface-2); color: var(--faint); cursor: not-allowed; }
```

`clip-path` 버튼은 `box-shadow` 바깥 글로우가 잘린다. 주 버튼의 빛은 6절의 `drop-shadow` 를 부모 래퍼에 건다.

### 배지

모양 + 글자 + 색 3가지가 모두 있어야 한다. 색만 다른 배지 금지.

```css
.badge { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 8px;
         font: 600 11px var(--font-display); letter-spacing: .12em; text-transform: uppercase;
         border: 1px solid currentColor; }
.badge--live { color: var(--neon-m); background: var(--neon-m-dim); }
.badge--live::before { content: ""; width: 6px; height: 6px; background: currentColor; } /* 네모 점 */
.badge--done { color: var(--win); }
.badge--wait { color: var(--warn); }
```

LIVE 의 점은 **깜빡이지 않는다**. 정지한 네모 점이면 충분하다.

### 입력

```css
.input { height: 40px; width: 100%; padding: 0 12px; background: var(--surface-2);
         border: 1px solid var(--line); border-radius: 0; color: var(--text);
         font: 400 14px var(--font-sans); }
.input::placeholder { color: var(--faint); }
.input:focus { outline: none; border-color: var(--neon-c);
               box-shadow: 0 0 0 1px var(--neon-c), 0 0 12px rgba(46,242,255,.35); }
.input[aria-invalid="true"] { border-color: var(--danger); }
.field-error { margin-top: 6px; font-size: 13px; color: var(--danger); }  /* 아이콘 + 문장 */
```

### 내비게이션 (상단 HUD 바)

```css
.nav { height: 56px; display: flex; align-items: center; gap: 28px;
       border-bottom: 1px solid var(--line); }
.nav a { position: relative; height: 56px; display: flex; align-items: center;
         font: 600 14px var(--font-sans); color: var(--muted); text-decoration: none; }
.nav a:hover { color: var(--text); }
.nav a[aria-current="page"] { color: var(--neon-c); }
.nav a[aria-current="page"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
         height: 2px; background: var(--neon-c); }
```

### 대진표 (브래킷) 칸

```css
.match { display: grid; grid-template-rows: 1fr 1fr; background: var(--surface);
         border: 1px solid var(--line); }
.match .row { display: grid; grid-template-columns: 1fr 36px; align-items: center;
              height: 36px; padding: 0 10px; }
.match .row + .row { border-top: 1px solid var(--line); }
.match .row.win { color: var(--text); font-weight: 700; }
.match .row.lose { color: var(--faint); }
.match .s { font: 700 15px var(--font-num); text-align: right; }
.match.live { border-color: var(--neon-m); }
.bracket-link { stroke: var(--line-2); stroke-width: 1.5; fill: none; }   /* SVG 연결선 */
```

---

## 5. 효과 레시피

**상한: 글로우는 화면당 4곳까지.** 보통 ① 카운트다운 숫자 ② 진행 중 경기 테두리 ③ 주 버튼 ④ 제목 영문 로고. 5곳째가 필요하면 하나를 끈다.

### 글로우 (정해진 3가지만)

```css
/* A. 글자 글로우 — 22px 이상 숫자·영문 로고에만 */
.glow-text-c { color: var(--neon-c);
  text-shadow: 0 0 6px rgba(46,242,255,.55), 0 0 18px rgba(46,242,255,.25); }
.glow-text-m { color: var(--neon-m);
  text-shadow: 0 0 6px rgba(255,61,203,.55), 0 0 18px rgba(255,61,203,.25); }

/* B. 테두리 글로우 — 사각형(clip-path 없는) 요소 */
.glow-box-m { box-shadow: 0 0 0 1px var(--neon-m), 0 0 16px rgba(255,61,203,.35); }

/* C. clip-path 요소 글로우 — 부모 래퍼에 drop-shadow */
.glow-wrap-m { filter: drop-shadow(0 0 8px rgba(255,61,203,.45)); }
```

규칙: 블러 반경은 최대 18px, 불투명도 최대 .55. 글로우 3겹 이상, `text-shadow` 에 흰색 섞기, 본문 글자 글로우 금지.

### 배경 격자 + 스캔라인

`body` 한 곳에만, `position: fixed` 가상 요소로 깐다. 패널마다 따로 깔지 않는다.

```css
body::before {             /* 40px 격자 */
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background-image:
    linear-gradient(rgba(46,242,255,.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(46,242,255,.035) 1px, transparent 1px);
  background-size: 40px 40px;
}
body::after {              /* 스캔라인: 3px 간격, 정지 */
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  background: repeating-linear-gradient(0deg, rgba(255,255,255,.025) 0 1px, transparent 1px 3px);
}
.page { position: relative; z-index: 1; }
```

스캔라인은 **움직이지 않는다**. 위아래로 흐르는 스캔라인 애니메이션은 광과민성 위험이 있다.

### clip-path 각진 모서리

| 이름 | 값 | 용도 |
|---|---|---|
| 우상단 컷 | `polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%)` | 패널 |
| 대각 2컷 | `polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px)` | 버튼 |
| 탭 컷 | `polygon(0 0, calc(100% - 10px) 0, 100% 100%, 0 100%)` | 탭·라벨 띠 |

컷 크기는 8 / 10 / 12px 3종만. 한 패널에 컷은 최대 2곳.

### 코너 브래킷 (선택)

히어로 패널 하나에만 네 귀퉁이 꺾쇠를 둔다.

```css
.corners { position: relative; }
.corners::before, .corners::after { content: ""; position: absolute; width: 14px; height: 14px;
  border: 2px solid var(--neon-c); }
.corners::before { top: -1px; left: -1px; border-right: 0; border-bottom: 0; }
.corners::after  { bottom: -1px; right: -1px; border-left: 0; border-top: 0; }
```

---

## 6. 레이아웃

- 최대 폭 1240px, 페이지 좌우 여백 24px(모바일 16px)
- 12열 그리드, 간격 16px. 패널 안 여백 20px
- 첫 화면 구성: 상단 HUD 바 → 히어로(대회명 + 카운트다운 + 주 버튼, 7:5 비대칭) → 대진표(8열 폭) + 점수판·일정(4열 폭)
- 같은 크기 패널 3개 연속 금지. 대진표처럼 넓은 패널 하나를 기준으로 좌우 폭을 다르게 잡는다
- 정보 밀도는 높게: 표 행 높이 36px, 목록 행 44px

| 구간 | 열 | 비고 |
|---|---|---|
| ≥1024px | 12 | 대진표 8 + 사이드 4 |
| 641~1023px | 6 | 대진표 전체 폭, 가로 스크롤 영역으로(페이지는 스크롤 안 됨) |
| ≤640px | 1 | 대진표를 라운드별 탭으로 전환, 카운트다운 최상단 |

---

## 7. 모션

- **깜빡임 금지**. `opacity` 를 0과 1 사이로 반복하거나 초당 3회 이상 밝기가 바뀌는 효과는 쓰지 않는다 (광과민성 발작 기준).
- 시간은 150~400ms, `ease-out`. 반복 애니메이션은 카운트다운 숫자 교체(1초 1회, 단순 교체) 외에 없다.
- 허용: 호버 시 테두리 색 전환(200ms), 패널 등장(8px 상승 + 페이드 320ms, 순차 40ms), 점수 갱신 시 숫자 위로 밀기(250ms).
- 금지: 글리치 흔들림, RGB 분리 진동, 네온 "켜지는" 깜빡임, 흐르는 스캔라인, 무한 펄스 글로우.

```css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
```

reduced-motion 이어도 카운트다운 숫자는 갱신된다(애니메이션이 아니라 텍스트 교체이므로).

---

## 8. 접근성

- **글로우 글자는 22px 이상만.** 작은 글자에 글로우를 넣으면 획이 번져 읽히지 않는다. 본문·라벨은 글로우 없이 `--text`/`--muted`.
- **대비 4.5:1 이상**: `--text` 16.6:1, `--muted` 7.1:1, `--neon-c` 14.4:1, `--neon-m` 6.4:1 (모두 `--bg` 기준). `--faint` 3.6:1 은 14px 이상 메타·장식에만.
- 네온 배경 위 글자는 `--on-neon`(#0B0816). 흰 글자 금지 (마젠타 위 흰 글자 3.1:1).
- **네온 색만으로 상태를 구분하지 않는다.** 진행 중 = 마젠타 테두리 + `LIVE` 배지 글자 + 네모 점. 승리 = 굵기 + 점수 + "승" 텍스트.
- 포커스 링은 시안 2px 실선 + 3px 간격. 마우스 사용자도 키보드로 넘어가면 보이게 `:focus-visible`.
- 고대비 모드에서는 글로우와 배경 질감을 끈다.

```css
@media (prefers-contrast: more) {
  [class*="glow-"] { text-shadow: none !important; box-shadow: none !important; filter: none !important; }
  body::before, body::after { display: none; }
  :root { --muted: #C9C2EC; --line: #5A4E8C; }
}
```

- 카운트다운은 `aria-live="off"` (초마다 읽어 주면 소음). 대신 `<time datetime>` 과 시각 텍스트를 함께 둔다.

---

## 9. 하지 말 것

- 네온 3색 이상 (초록·노랑 네온 추가). 상태색은 글로우 없이 작게만
- 글로우 5곳 이상, 패널마다 테두리 글로우
- 본문·12px 라벨에 `text-shadow`
- 깜빡이는 LIVE 점, 흐르는 스캔라인, 글리치 흔들림
- 보라→분홍 그라디언트 배경, 블롭, 유리(blur) 패널
- `border-radius` 와 `clip-path` 섞기 (둥근 버튼 + 각진 패널)
- Chakra Petch 로 한글 제목 쓰기
- 이모지 (트로피, 불꽃, 게임패드). 아이콘은 lucide SVG
- "Team Alpha / Player1 / 9999점" 같은 가짜 데이터. 팀은 부서 기반("품질보증 QA크루"), 점수는 실제 경기 단위(세트 2:1, 킬 수)
- 빈 대진표를 빈칸으로 두기 → "4강 대진 추첨 6.12 (금) 18:00" 처럼 다음 일정을 쓴다

---

## 10. 셀프 체크리스트

- [ ] 화면에서 빛나는 곳을 세어 보았나? 4곳 이하인가?
- [ ] 마젠타는 "지금", 시안은 "숫자·정보"로만 쓰였나? 두 색이 한 요소에 겹치지 않나?
- [ ] 글로우가 있는 글자는 전부 22px 이상인가?
- [ ] 깜빡이거나 반복되는 애니메이션이 없나? reduced-motion 에서 모두 멈추나?
- [ ] 상태가 색 말고 글자·모양으로도 구분되나?
- [ ] 모서리가 전부 각져 있나? `border-radius` 가 섞이지 않았나?
- [ ] 격자·스캔라인이 눈에 띄지 않을 만큼 옅은가? (스크린숏을 축소해 보이면 너무 진하다)
- [ ] 숫자는 전부 모노 + `tabular-nums` 인가?
- [ ] 팀명·이름·날짜가 현실적인가? 빈 상태·로딩·에러가 있나?
- [ ] 업무 화면·의약품 정보 화면에 쓰고 있지 않나?

### 복사용 프롬프트

```
사이버 네온 스타일로 사내 e스포츠 대회 페이지를 만들어줘. designs/cyber-neon.md 를 따른다.
- 바탕 #0B0816, 패널 #140F26 / #1C1534, 테두리 #2E2550, 본문 #EDE9FF, 보조 #9D94C4
- 네온 2색만: 마젠타 #FF3DCB(주 버튼·LIVE·진행 중 경기), 시안 #2EF2FF(카운트다운·데이터·포커스)
- 글로우는 화면당 4곳 이하, 22px 이상 글자에만. 깜빡임·흐르는 스캔라인 금지
- 모서리는 clip-path 사선 컷(8/10/12px), border-radius 0
- 한글 Pretendard, 영문 라벨 Chakra Petch 대문자, 숫자 JetBrains Mono tabular-nums
- 구성: 다음 경기 카운트다운 히어로, 8강 대진표(SVG 연결선), 실시간 점수판, 참가 팀 명단
- 팀은 부서 기반 이름, 실제 날짜(2026년), 경기 단위 점수. 빈 상태·로딩·에러 포함
- prefers-reduced-motion, prefers-contrast 처리. 이모지 금지, lucide 아이콘
```
