# Design System — Aurora Glass (오로라 글래스)

> 짙은 흑청색 밤하늘 위로 오로라처럼 번지는 메시 그라디언트, 그 위에 떠 있는 반투명 유리 카드, 밝은 청록과 분홍 액센트. 공모전·해커톤·런칭 카운트다운처럼 "지금 무언가 벌어지고 있다"는 긴장감을 주는 다크 스타일이다.
> 공통 규칙은 `anti-slop.md`를 함께 적용한다. 미리보기: `preview/aurora-glass.html` (사내 AI 챌린지 랜딩 + 실시간 순위표 + 마감 카운트다운 예시)

> **이 문서는 anti-slop.md의 "그라디언트·글로우·blur 금지"를 풀어 준다. 단, 5절 효과 레시피에 적힌 효과만, 적힌 곳에, 적힌 양까지만이다.** 오로라는 페이지 바탕 한 겹, 유리는 카드, 글로우는 숫자 한두 곳. 그 밖의 anti-slop 원칙(이모지 금지, 현실적인 한국어 더미 데이터, 아이콘 카드 3개 나열 금지, 빈 상태·로딩·에러 상태)은 그대로 지킨다. 오로라는 배경이지 주인공이 아니다. 주인공은 순위와 남은 시간이다.

---

## 1. 분위기

불 꺼진 강당 천장에 오로라를 쏜 느낌이다. 바탕은 거의 검은 남색이고, 화면 가장자리에서 청록·분홍·청색 빛이 천천히 번진다. 그 위에 살짝 비치는 어두운 유리 카드가 떠 있고, 카드 안의 숫자(남은 시간, 득표 수)만 밝게 빛난다.

유리 카드는 **어둡게 착색**한다. 투명한 흰 유리(`rgba(255,255,255,.1)`)를 그대로 쓰면 오로라가 밝은 곳에서 글자가 묻힌다. 이 스타일의 유리는 흑청색을 55% 깔고 뒤를 18px 흐린 "선팅 유리"다. 그래서 오로라가 어디에 있든 본문 대비가 유지된다.

**어울리는 곳**
- 사내 아이디어 공모전, AI 챌린지, 해커톤 랜딩과 실시간 순위
- 신제품·신규 서비스 오픈 카운트다운, 사내 방송 티저
- 저녁 행사·시상식 안내, 투표 결과 발표 화면

**쓰면 안 되는 곳**
- 하루 종일 켜 두는 업무 도구, 데이터 입력이 많은 화면 (blur는 스크롤 성능을 깎고, 다크는 긴 문서를 읽기 어렵게 한다)
- 인쇄·PDF로 나갈 문서 (반투명과 그라디언트가 인쇄에서 깨진다)
- 품질·안전·규정 공지, 숫자 정확도가 최우선인 보고 화면
- 저사양 PC가 많은 생산 현장 단말 (blur 비용)

**핵심 특징**
- 바탕 `#070B1A` + 메시 그라디언트 오로라 **1겹** (페이지 고정 레이어)
- 카드는 착색 유리: `rgba(14,20,44,.55)` + `blur(18px)` + 1px 밝은 테두리
- 액센트 2색: 청록 `#3EE6D2`(주 행동·1위·남은 시간), 분홍 `#FF6FB1`(새 소식·급상승)
- 숫자 글로우는 **화면당 2곳 이하**
- 한글 Pretendard, 영문 디스플레이 Sora, 숫자 JetBrains Mono

---

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

다크가 기본이다. 라이트 모드는 "새벽 오로라"로 따로 정의하되, 행사 페이지는 다크 하나만 제공해도 된다.

### Dark (기본)

```css
:root {
  /* 바탕·표면 */
  --bg:          #070B1A;               /* 페이지 바탕, 흑청 */
  --bg-2:        #0C1228;               /* 오로라 미지원 시 단색 폴백 */
  --glass:       rgba(14, 20, 44, .55); /* 유리 카드 착색 */
  --glass-solid: #121A33;               /* backdrop-filter 미지원 폴백 */
  --glass-hi:    rgba(255, 255, 255, .06); /* 행 호버, 칩 */
  --edge:        rgba(255, 255, 255, .12); /* 유리 테두리 */
  --edge-hi:     rgba(255, 255, 255, .22); /* 유리 윗면 반사 */

  /* 텍스트 */
  --text:        #EAF0FF;  /* 본문 (glass-solid 위 14.2:1) */
  --muted:       #9AA6C8;  /* 보조 (glass-solid 위 6.6:1) */
  --faint:       #66729A;  /* 메타·축 (본문에 쓰지 않음) */

  /* 액센트 */
  --teal:        #3EE6D2;  /* 주 행동, 1위, 남은 시간 */
  --teal-ink:    #04121A;  /* 청록 버튼 위 글자 (12.9:1) */
  --pink:        #FF6FB1;  /* 새 제출, 급상승, 마감 임박 */
  --blue:        #4C8DFF;  /* 오로라 재료 전용, UI 채색 금지 */

  /* 의미 */
  --success:     #4BD69A;
  --danger:      #FF7A85;
}
```

### Light ("새벽 오로라")

```css
:root[data-theme="light"] {
  --bg:          #EEF3FB;
  --bg-2:        #E2E9F5;
  --glass:       rgba(255, 255, 255, .62);
  --glass-solid: #FFFFFF;
  --glass-hi:    rgba(7, 11, 26, .04);
  --edge:        rgba(7, 11, 26, .10);
  --edge-hi:     rgba(255, 255, 255, .9);
  --text:        #0B1226;
  --muted:       #4A5675;  /* 흰 유리 위 7.4:1 */
  --faint:       #8792AF;
  --teal:        #0B7F73;  /* 라이트에서 명도를 낮춰 흰 글자 대비 4.9:1 확보 */
  --teal-ink:    #FFFFFF;  /* 라이트 청록 버튼 위 글자는 흰색 */
  --pink:        #D63C84;
}
```

라이트에서는 오로라 불투명도를 절반으로 낮춘다(5-1의 알파값 × 0.5).

### 역할 규칙

| 토큰 | 쓰는 곳 | 쓰지 않는 곳 |
|---|---|---|
| `--teal` | 주 버튼 1개, 1위 행 표시, 카운트다운 숫자, 진행 막대 | 본문, 카드 배경, 링크 전부 |
| `--pink` | "새로 들어옴" 점, 급상승 화살표, 마감 24시간 이내 경고 | 버튼 배경, 제목 |
| `--blue` | 오로라 그라디언트 안에서만 | 버튼·글자·아이콘 |
| `--glass` | 모든 카드, 내비 바 | 페이지 바탕 |
| `--edge` | 유리 테두리, 표 구분선 | 굵은 테두리(1px 초과 금지) |

---

## 3. 타이포그래피

| 역할 | 서체 |
|---|---|
| 한글 UI·본문 | **Pretendard Variable** (`cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css`) |
| 영문 디스플레이·라벨 | **Sora** (Google Fonts, 500·600·700) |
| 숫자·시간·순위 | **JetBrains Mono** (Google Fonts), `tabular-nums` |

```css
--font-sans:    "Pretendard Variable", Pretendard, -apple-system, sans-serif;
--font-display: "Sora", "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: 600 12px/1 var(--font-display); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
```

### 스케일 (6단계)

| 토큰 | 크기 / 굵기 / 자간 | 용도 |
|---|---|---|
| `countdown` | `clamp(44px, 5vw, 64px)` / mono 600 / -0.04em | 카운트다운 숫자 (글로우 1) |
| `display` | `clamp(36px, 4.2vw, 56px)` / Pretendard 800 / -0.04em / 1.15 | 랜딩 한글 제목 |
| `h2` | 20px / 700 / -0.02em | 카드 제목 |
| `body` | 15px / 400 / 1.65 | 본문 |
| `small` | 13px / 500 | 표 셀, 보조 |
| `eyebrow` | 12px / Sora 600 / 0.14em / 대문자 | 섹션 라벨 |

다크 바탕에서는 같은 굵기도 얇아 보인다. 본문은 400 아래로 내리지 않고, 행간은 1.65로 넉넉하게 둔다.

---

## 4. 컴포넌트

### 유리 카드

```css
.glass {
  background: var(--glass);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--edge);
  border-radius: 20px;                       /* 모든 카드 동일 */
  box-shadow: inset 0 1px 0 var(--edge-hi),  /* 윗면 반사 1줄 */
              0 20px 40px -24px rgba(0, 0, 0, .6);
  padding: 24px;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: var(--glass-solid); }
}
```

유리 위에 유리를 겹치지 않는다. 카드 안의 하위 박스는 `--glass-hi` 단색 칠만 쓴다(blur 중첩 금지).

### 주 버튼 (청록, 화면에 1개)

```css
.btn-primary {
  display: inline-flex; align-items: center; gap: 8px;
  height: 50px; padding: 0 26px; border: 0; border-radius: 14px;
  background: var(--teal); color: var(--teal-ink);
  font: 700 16px var(--font-sans); cursor: pointer;
  box-shadow: 0 0 0 1px rgba(62,230,210,.4), 0 8px 24px -8px rgba(62,230,210,.55);
  transition: transform .18s ease, box-shadow .18s ease;
}
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 0 0 1px rgba(62,230,210,.6), 0 10px 30px -8px rgba(62,230,210,.7); }
.btn-primary:focus-visible { outline: 2px solid #FFFFFF; outline-offset: 3px; }
.btn-primary:disabled { background: #26304F; color: var(--faint); box-shadow: none; cursor: not-allowed; }
```

### 보조 버튼

```css
.btn-glass { height: 44px; padding: 0 18px; border-radius: 12px;
             background: var(--glass-hi); border: 1px solid var(--edge);
             color: var(--text); font: 600 14px var(--font-sans); }
.btn-glass:hover { background: rgba(255,255,255,.1); }
```

### 배지·칩

```css
.chip { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px;
        border-radius: 999px; background: var(--glass-hi); border: 1px solid var(--edge);
        font: 600 12px var(--font-sans); color: var(--muted); }
.chip--live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--pink); }
.chip--teal { color: var(--teal); border-color: rgba(62,230,210,.35); background: rgba(62,230,210,.08); }
```

### 입력

```css
.input { width: 100%; height: 46px; padding: 0 16px; border-radius: 12px;
         background: rgba(7, 11, 26, .6); border: 1px solid var(--edge);
         color: var(--text); font: 400 15px var(--font-sans); }
.input::placeholder { color: var(--faint); }
.input:focus { outline: none; border-color: var(--teal); box-shadow: 0 0 0 3px rgba(62,230,210,.18); }
.input[aria-invalid="true"] { border-color: var(--danger); }
```

입력창 배경은 유리보다 더 어둡게 깐다(유리 위의 또 다른 blur가 되지 않도록 단색).

### 내비 (상단 유리 바)

```css
.nav { position: sticky; top: 16px; z-index: 10; display: flex; align-items: center; gap: 24px;
       height: 56px; padding: 0 20px; border-radius: 16px; }       /* .glass 함께 적용 */
.nav a { font: 600 14px var(--font-sans); color: var(--muted); }
.nav a[aria-current="page"] { color: var(--text); box-shadow: inset 0 -2px 0 var(--teal); }
```

### 순위표

```css
.rank-row { display: grid; grid-template-columns: 40px 1fr 120px 80px; gap: 14px; align-items: center;
            padding: 12px 14px; border-radius: 12px; }
.rank-row + .rank-row { margin-top: 4px; }
.rank-row:hover { background: var(--glass-hi); }
.rank-row.first { background: rgba(62,230,210,.07); box-shadow: inset 2px 0 0 var(--teal); }
.rank-bar { height: 6px; border-radius: 999px; background: rgba(255,255,255,.08); overflow: hidden; }
.rank-bar i { display: block; height: 100%; background: var(--teal); border-radius: 999px; }
```

1위만 청록 띠와 배경 틴트. 2위 이하는 막대만 청록, 행은 투명.

---

## 5. 효과 레시피

이 절에 적힌 CSS만 쓴다.

### 5-1. 오로라 메시 (페이지 바탕 1겹)

```css
.aurora {
  position: fixed; inset: -10%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(38% 46% at 14% 18%, rgba(62, 230, 210, .42), transparent 70%),
    radial-gradient(34% 40% at 86% 12%, rgba(255, 111, 177, .32), transparent 70%),
    radial-gradient(46% 52% at 62% 92%, rgba(76, 141, 255, .30), transparent 72%),
    radial-gradient(30% 34% at 32% 70%, rgba(62, 230, 210, .16), transparent 70%),
    #070B1A;
  filter: saturate(120%);
}
@media (prefers-reduced-motion: no-preference) {
  .aurora { animation: aurora-drift 28s ease-in-out infinite alternate; }
}
@keyframes aurora-drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(-3%, 2%, 0) scale(1.06); }
  100% { transform: translate3d(2%, -2%, 0) scale(1.02); }
}
```

움직이는 것은 `transform`뿐이다. `background-position`을 애니메이션하면 매 프레임 다시 그려 무거워진다. 오로라 요소는 `body` 바로 아래 하나만 둔다.

### 5-2. 노이즈 질감 (선택, 오로라 위 1겹)

밴딩(색 띠 계단)을 줄이려면 SVG 노이즈를 3% 얹는다. 외부 이미지 없이 data URI로.

```css
.aurora::after { content: ""; position: absolute; inset: 0; opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
```

### 5-3. 숫자 글로우 (화면당 2곳 이하)

```css
.glow-teal { color: var(--teal); text-shadow: 0 0 18px rgba(62,230,210,.55), 0 0 2px rgba(62,230,210,.9); }
.glow-pink { color: var(--pink); text-shadow: 0 0 16px rgba(255,111,177,.5); }
```

카운트다운 숫자 1곳 + 1위 득표 수 1곳이 일반적이다. 제목·버튼 글자에는 글로우를 넣지 않는다.

### 5-4. 그라디언트 테두리 (강조 카드 1장)

```css
.edge-aurora { position: relative; }
.edge-aurora::before { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px;
  background: linear-gradient(135deg, rgba(62,230,210,.8), rgba(255,111,177,.6) 50%, rgba(76,141,255,.6));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; }
```

### 쓰는 양의 상한

| 효과 | 상한 | 비고 |
|---|---|---|
| 오로라 메시 (5-1) | 페이지에 **1겹** | 카드 안·섹션마다 다시 깔지 않음 |
| `backdrop-filter` 유리 | 화면에 보이는 카드 **6장 이하** | 겹침(유리 위 유리) 금지 |
| 숫자 글로우 (5-3) | **2곳** | 본문·제목 금지 |
| 그라디언트 테두리 (5-4) | **1장** | 보통 카운트다운 카드 |
| 청록 채움 | 주 버튼 1개 + 진행 막대 | 큰 면 채우기 금지 |

---

## 6. 레이아웃

- 최대 폭 1200px 중앙, 좌우 32px(모바일 16px). 상단 유리 내비는 sticky.
- 첫 화면은 **좌 7열: 제목·설명·주 버튼·접수 현황 숫자 / 우 5열: 카운트다운 카드(그라디언트 테두리)** 비대칭.
- 그 아래 **순위표(8열) + 부문·일정(4열)**. 부문 소개를 아이콘 카드 3장으로 나열하지 않는다. 표나 목록으로.
- 카드 사이 20px, 섹션 사이 48px. 반경은 카드 20px, 버튼·입력 12~14px, 칩 999px.

```css
.page { max-width: 1200px; margin: 0 auto; padding: 16px 32px 64px; }
.hero { display: grid; grid-template-columns: 7fr 5fr; gap: 20px; margin-top: 40px; align-items: stretch; }
.board { display: grid; grid-template-columns: 8fr 4fr; gap: 20px; margin-top: 20px; }
@media (max-width: 900px) { .hero, .board { grid-template-columns: 1fr; } }
```

---

## 7. 모션

| 상황 | 시간 | 방식 |
|---|---|---|
| 오로라 흐름 | 28s 주기 | transform 이동·확대, 페이지 1겹 |
| 카운트다운 초 변경 | 200ms | 숫자 4px 아래→제자리 + 페이드 |
| 순위 변동 | 300ms | 행 위치 이동(FLIP), 급상승 분홍 화살표 1회 깜빡 |
| 카드 등장 | 360ms | 10px 상승 + 페이드, 40ms 순차 |
| 버튼 호버 | 180ms | 1px 상승 + 글로우 확대 |

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

모션을 끄면 오로라는 멈춘 그림으로 남고, 카운트다운은 숫자만 바뀐다(애니메이션 없이 1초마다 갱신).

---

## 8. 접근성

- **착색 유리가 대비의 열쇠다.** 유리 알파를 0.55 아래로 내리지 않는다. 0.55에서 오로라 최대 밝기 지점 위의 실효 배경이 `#1A2A44` 근처라 `--text` 대비 11:1 이상, `--muted` 4.9:1 이상을 지킨다.
- 오로라 바탕 위에 유리 없이 글자를 바로 올리는 곳은 **히어로 제목뿐**이며, 그 아래 오로라는 가장 밝은 곳에서 떨어진 왼쪽 아래에 둔다(제목 블록 뒤에 청록 원을 두지 않는다). 본문 문단은 반드시 유리 위에.
- 포커스 링은 흰색 2px(청록 버튼 위에서도 보이게). 탭 순서는 내비 → 주 버튼 → 카운트다운 → 순위표.
- 카운트다운은 `aria-live`를 쓰지 않는다(매초 읽힘). 대신 `aria-label="마감까지 17일 6시간"`처럼 분 단위로 갱신하고, 숫자 칸은 `aria-hidden`.
- 순위 변동을 색(분홍)만으로 알리지 않는다. 화살표 + "3계단 상승" 텍스트.
- 효과 끄기 폴백:

```css
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background: var(--glass-solid); }
}
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .glass { background: var(--glass-solid); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .aurora { background: var(--bg-2); }
  .glow-teal, .glow-pink { text-shadow: none; }
}
@media (forced-colors: active) { .aurora { display: none; } .glass { border: 1px solid CanvasText; } }
```

---

## 9. 하지 말 것

- 흰 투명 유리(`rgba(255,255,255,.1)`)에 본문 올리기 — 오로라 밝은 곳에서 글자가 사라진다
- 유리 카드 안에 또 유리 카드 (blur 중첩은 뭉개지고 무겁다)
- 오로라를 카드마다, 섹션마다 따로 깔기
- 보라→분홍 그라디언트 버튼, 버튼에 오로라 채우기
- 모든 숫자에 글로우, 제목에 네온
- "혁신을 위한 여정에 함께하세요" 같은 빈 카피, 이모지
- 부문 소개를 아이콘+제목+설명 카드 3장으로
- 득표 1,234표, 참여율 99.9% 같은 가짜 숫자
- 마감 후에도 카운트다운이 0에서 멈춘 채 "제출하기"가 살아 있는 화면 (마감 상태를 따로 디자인한다)

---

## 10. 셀프 체크리스트

- [ ] 오로라 레이어가 페이지에 1겹뿐인가?
- [ ] 모든 본문이 착색 유리(알파 0.55 이상) 위에 있는가?
- [ ] 유리 위에 유리를 겹치지 않았는가?
- [ ] 글로우가 2곳 이하이고 숫자에만 있는가?
- [ ] 청록 채움 버튼이 화면에 1개인가?
- [ ] `backdrop-filter` 미지원·`prefers-reduced-transparency`·`prefers-reduced-motion` 폴백이 있는가?
- [ ] 마감 후, 순위 데이터 없음(빈 상태), 불러오기 실패 상태가 있는가?
- [ ] 이름·팀·득표 수·날짜가 현실적인가?

### 복사용 프롬프트

```
오로라 글래스 스타일로 사내 AI 챌린지 랜딩 페이지를 만들어줘. designs/aurora-glass.md를 따른다.
- 바탕 #070B1A 위에 position:fixed 오로라 메시 1겹(radial-gradient 4개: 청록 #3EE6D2, 분홍 #FF6FB1, 청색 #4C8DFF), 28초 transform 드리프트
- 카드는 착색 유리 rgba(14,20,44,.55) + backdrop-filter blur(18px) saturate(140%) + 1px rgba(255,255,255,.12) 테두리, 반경 20px
- 첫 화면: 좌 7열 제목·설명·청록 주 버튼 1개·접수 현황 / 우 5열 마감 카운트다운(그라디언트 테두리 카드)
- 아래: 실시간 순위표 8열(1위만 청록 띠) + 부문·일정 목록 4열
- 글로우는 카운트다운 숫자와 1위 득표 수 2곳만
- 한글 Pretendard, 영문 Sora, 숫자 JetBrains Mono tabular-nums
- 마감 후 상태, 빈 순위표, 불러오기 실패 상태, backdrop-filter 폴백, prefers-reduced-motion 포함

[디자인 제약 — AI 기본값 금지]
- 효과는 문서 5절 레시피만, 정해진 곳·양만
- 흰 투명 유리 위 본문 금지, 유리 중첩 금지
- 보라/인디고 그라디언트 버튼, 블롭 남발 금지
- 아이콘+제목+설명 카드 3개 나열 금지
- 이모지 금지, 아이콘은 SVG 또는 lucide-react
- 현실적인 한국어 더미 데이터, 빈 상태·로딩·에러 포함
```
