---
description: 프로젝트 공통 UI 퍼블리싱 가이드 및 코딩 컨벤션
globs: ['*.html', '*.css', '*.js']
alwaysApply: true
---

# Design Rules (Base)

이 문서는 프로젝트의 공통 스타일/마크업 패턴을 정리한 **팀 표준 가이드라인(베이스)** 입니다.
다른 프로젝트로 이식할 때도 **같은 규칙/구조/네이밍**을 유지하는 것을 목표로 합니다.

---

## HTML 작성 규칙 (팀 표준)

-   **들여쓰기**
    -   **탭 들여쓰기**를 사용합니다. (탭 폭 4 기준)
-   **속성 줄바꿈**
    -   기본적으로 속성은 **한 줄 유지**를 우선합니다.
    -   길어질 경우에만 의미 단위(이벤트/바인딩/접근성)로 묶어 줄바꿈을 허용합니다.
-   **링크/버튼**
    -   동작 없는 더미 링크는 `href="#none"`를 사용합니다.

---

## CSS 작성 규칙 (팀 표준)

### 포맷 규칙 (필수)

-   **속성 1줄 규칙**
    -   스타일 속성은 **한 줄로 이어서 작성**하고, 속성마다 개행하지 않습니다.
    -   예: `display: flex; align-items: center; gap: 10px;`
    -   블록 간 불필요한 빈 줄을 넣지 않습니다. (예외: 섹션 구분이 명확히 필요한 경우에만 1줄 허용)
-   **Prettier 자동 포맷 비적용**
    -   CSS 파일은 Prettier 자동 포맷 대상에서 제외되어 있습니다. 위 규칙을 수동으로 준수합니다.

**✅ 올바른 예시:**

<!-- prettier-ignore -->
.list-info { display: flex; gap: 10px; }
.list-info .tit { font-size: 16px; font-weight: bold; color: var(--text-main); }

**❌ 잘못된 예시:**

<!-- prettier-ignore -->
.list-info {
    display: flex;
    gap: 10px;
}
.list-info {
    display: flex; gap: 10px;
}

### 셀렉터 스코프 및 계층 구조 규칙 (필수)

UI 컴포넌트의 응집도를 높이고 셀렉터만으로 DOM 구조를 파악할 수 있도록, 아래의 기준을 엄격히 준수하세요.

-   **컴포넌트의 '기준 블록(Context Root)'을 항상 최상위에 고정하세요.**

    -   최상위부터 전체 `<body>` 경로를 다 쓸 필요는 없지만, 해당 UI 요소들을 하나로 묶어주는 **의미 있는 최상위 부모 클래스(기준 블록)**는 모든 셀렉터의 시작점에 반드시 포함되어야 합니다.
    -   이 기준 블록이 생략되면 관련된 스타일 코드가 흩어지게 되므로 절대 생략하지 마세요.

-   **기준 블록 내부의 자식/후손 경로는 건너뛰지 않고 순차적으로 작성하세요.**
    -   단순히 '직계 부모'만 작성하여 최상위 컨텍스트를 잃어버리는 것을 엄격히 금지합니다.
    -   항상 `[기준 블록] [중간 부모] [최종 타겟]`의 계층 구조를 유지하세요.

### 반응형 작성 규칙 (권장)

-   **인라인 `@media` 금지**
    -   셀렉터 블록 내부에 `@media`를 넣지 않습니다.
-   **파일 하단으로 모으기**
    -   해당 파일의 주요 스타일 선언 이후, 파일 하단에 브레이크포인트별로 모아서 작성합니다.
-   **브레이크포인트 유연성 (AI 주의사항)**
    -   브레이크포인트는 디자인 시안이나 각 페이지의 특성에 따라 유연하게 설정됩니다. (예: `1024px`, `768px`, `680px`, `580px` 등)
    -   **절대 주의:** 기존 코드에 작성된 브레이크포인트 값을 임의의 다른 값으로 **절대 수정하지 마세요.** 기존 값을 무조건 존중하고 유지해야 합니다.

---

## 네이밍 규칙

### 클래스 네이밍 (필수)

-   **kebab-case(하이픈 케이스)** 를 사용합니다.
    -   예: `page-nav-wrap`, `quick-nav-wrap`, `card-list-group`, `search-input`
-   **역할 기반 suffix/prefix 패턴**을 우선합니다.
    -   `*-wrap`: 레이아웃 래퍼/컨테이너
    -   `*-area`: 특정 영역(블록) 단위
    -   `*-group`: 그룹(반복/묶음)
    -   `*-list`, `*-item`: 리스트/아이템
    -   `*-title`, `tit`, `txt`: 타이포 요소
    -   `btn`, `btn-wrap`, `a-btn`: 버튼 계열
-   **상태 클래스**
    -   상태는 짧게: `active`, `open`, `show`, `fixed`, `disabled`
    -   예: `.page-nav-wrap.fixed`, `.selectbox.active`, `.popup-zone.show`

### 금지/지양

-   **BEM 구문(`__`, `--`)은 팀 표준으로 사용하지 않습니다.**

---

## 폴더/파일 구조 규칙

### 폴더/파일 네이밍 규칙 (필수)

-   폴더/파일명은 **영문 소문자**를 기본으로 합니다.
-   단어 구분은 **kebab-case**를 사용합니다.
    -   예: `main.css`, `sub-page.css`, `common.js`

### 폴더 구조

```
project/
├── html/          # 페이지별 HTML 파일
├── css/           # 페이지별 CSS 파일
├── js/            # 페이지별 JS 파일
└── img/
    ├── common/    # 공통 이미지 (로고, 아이콘 등)
    └── {페이지명}/ # 페이지별 이미지
```

### 파일 네이밍

-   HTML: 페이지명 기준 kebab-case (예: `main.html`, `sub-page.html`)
-   CSS: HTML 파일명과 동일하게 맞춥니다. (예: `main.css`, `sub-page.css`)
-   JS: HTML 파일명과 동일하게 맞춥니다. (예: `main.js`, `sub-page.js`)
-   이미지: kebab-case, 역할/순서 포함 (예: `visual_img1.webp`, `training_icon1.svg`)

---

## 공통 UI 마크업/스타일 규칙

### 웹접근성: img alt 규칙 (필수)

-   이미지에는 반드시 `alt` 속성을 작성합니다.
-   **이미지 바로 옆에 동일한 의미의 텍스트가 명확히 존재하는 경우 `alt="icon"` 또는 `alt="image"`로 작성합니다.** `alt=""`로 완전히 비우지 않습니다.
    -   예: 아이콘 옆에 "주소", "교육 기간" 등 레이블 텍스트가 있는 경우 → `alt="icon"`
    -   예: 버튼 아이콘 옆에 버튼 텍스트가 있는 경우 → `alt="icon"`
-   텍스트 없이 이미지 단독으로 의미를 전달하는 경우에는 반드시 내용을 기술합니다.
    -   예: 로고, 썸네일, 배너 이미지 등

### 웹접근성: label 규칙 (필수)

-   `input`, `textarea`, `select`는 **반드시 레이블을 제공**합니다.
-   디자인상 레이블이 노출되기 어렵다면, 해당 태그 **직전에** `<label class="hidden">`을 함께 사용합니다.
-   `label`의 `for`와 폼 요소의 `id`를 **반드시 매칭**합니다.

### 높이 지정 규칙 (필수)

-   **박스형 라벨·버튼의 높이는 `height` px로 고정하지 않고 `padding`으로 조절합니다.**
    -   `height` 고정 시 텍스트가 길어지면 넘치거나 잘리는 문제가 발생합니다.
    -   예: `height: 26px; padding: 0 10px;` ❌ → `padding: 5px 10px;` ✅
    -   단, 아이콘 전용 버튼처럼 텍스트가 없는 정사각형 요소는 `width`/`height` 사용을 허용합니다.

### 버튼

**표준 마크업:**

```html
<div class="btn-wrap">
	<a href="#none" class="a-btn bg-theme">확인</a>
	<button type="button" class="bg-white">취소</button>
</div>
```

**규칙:**

-   버튼 래퍼는 기본적으로 `.btn-wrap` (레이아웃에 따라 `span`도 허용)
-   링크 버튼은 `.a-btn`, 실제 버튼은 `button`
-   색/변형은 클래스 조합으로 처리: `bg-theme`, `bg-white`, `s-btn`, `full-btn` 등

### 인풋 텍스트/텍스트에리어

**표준 마크업:**

```html
<div class="input-text">
	<label class="hidden" for="sample-input">입력</label>
	<input id="sample-input" type="text" placeholder="입력" />
</div>

<div class="input-textarea">
	<label class="hidden" for="sample-textarea">입력</label>
	<textarea id="sample-textarea" placeholder="입력"></textarea>
	<div class="text-limit"><span class="count">0</span><span class="unit">/ 100</span></div>
</div>
```

### 셀렉트박스

**표준 마크업:**

```html
<div class="selectbox">
	<label class="hidden" for="sample-select">전체</label>
	<select id="sample-select">
		<option>전체</option>
	</select>
</div>
```

---

## 컬러/변수 사용 규칙

-   색상은 가능하면 **CSS 변수(`var(--theme)`, `var(--line)` 등)**를 우선 사용합니다.
-   **`border-color`는 기본적으로 `var(--line)`을 사용합니다.** 디자인상 명시적으로 다른 색이 필요한 경우에만 예외를 허용합니다.
-   전역 리셋/기본 요소 스타일은 `css/common.css`에서 관리하고, 페이지별 CSS에서 임의로 추가하지 않습니다.

---
