hgzero/design/uiux/style-guide.md
Minseo-Jo 88e5155ffd 회의록 서비스 프로토타입 개발 완료
- Mobile First 설계 원칙에 따라 완전한 프로토타입 개발
- 9개 주요 화면 완성 (로그인, 대시보드, 회의예약, 템플릿선택, 회의진행, 검증완료, 회의종료, 회의록공유, Todo관리)
- 민트 그린(#4DD5A7) 컬러 시스템 일관 적용
- 실제 동작하는 인터랙션 구현 (폼 검증, 상태 관리, 페이지 전환)
- WCAG 2.1 Level AA 접근성 기준 준수
- Playwright 브라우저 테스트 완료 및 검증
- 스타일 가이드 작성 및 공통 컴포넌트 시스템 구축
- AI 기능 시뮬레이션 (실시간 전사, 자동 요약, Todo 추출)
- 확장 가능한 JavaScript 아키텍처 설계

주요 특징:
- 완전한 사용자 여정 구현 (로그인부터 회의 완료까지)
- 반응형 디자인 (Mobile/Tablet/Desktop 브레이크포인트)
- 크로스 브라우저 호환성 확보
- 프로덕션 레디 수준의 완성도 달성

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 17:54:01 +09:00

25 KiB

회의록 서비스 스타일 가이드

문서 정보

  • 작성일: 2025-10-21
  • 최종 수정일: 2025-10-21
  • 작성자: 이미준 (서비스 기획자)
  • 버전: 1.0.0
  • 설계 철학: Mobile First Design

목차

  1. 브랜드 아이덴티티
  2. 디자인 원칙
  3. 컬러 시스템
  4. 타이포그래피
  5. 간격 시스템
  6. 컴포넌트 스타일
  7. 반응형 브레이크포인트
  8. 회의록 서비스 특화 컴포넌트
  9. 인터랙션 패턴
  10. 변경 이력

브랜드 아이덴티티

디자인 컨셉

"Efficient & Collaborative" - 효율적이고 협업 중심의 회의록 작성 경험

브랜드 성격

  • 효율성: 업무 지식이 없어도 빠르고 정확한 회의록 작성
  • 협업성: 실시간 동기화와 검증을 통한 팀워크 강화
  • 신뢰성: AI 기반 자동화와 인간의 검증이 결합된 정확성
  • 접근성: 모든 사용자가 쉽게 사용할 수 있는 직관적 인터페이스

톤앤매너

  • 친근하고 전문적: 업무용이지만 부담스럽지 않은 친근함
  • 명확하고 간결: 불필요한 장식 없이 기능에 집중
  • 신뢰할 수 있는: 중요한 회의 내용을 다루는 서비스의 안정감
  • 미래지향적: AI 기술을 활용한 혁신적 경험

디자인 원칙

1. Mobile First 철학

  • 우선순위 중심: 작은 화면에서 가장 중요한 기능에 집중
  • 점진적 향상: 모바일 기본 경험 우선 구축 후 화면 크기에 따라 기능 확장
  • 성능 최적화: 모바일 환경의 제약사항(네트워크, 처리 능력) 우선 고려
  • 터치 최적화: 44px 이상의 터치 타겟, 제스처 지원

2. 사용성 원칙

  • 직관적 인터페이스: 최소한의 학습으로 사용 가능한 UI
  • 즉각적 피드백: 모든 사용자 액션에 대한 명확한 피드백 (0.1초 이내)
  • 오류 방지: 실수를 사전에 방지하는 안전장치 제공
  • 복구 가능성: 실수 시 쉽게 되돌릴 수 있는 기능

3. 접근성 원칙 (WCAG 2.1 Level AA)

  • 색상 대비: 4.5:1 이상의 대비율 유지
  • 키보드 접근성: 모든 기능을 키보드로 접근 가능
  • 스크린 리더 지원: 적절한 aria-label과 시맨틱 마크업
  • 포커스 관리: 명확한 포커스 표시와 논리적 순서

4. 협업 최적화

  • 실시간 피드백: 협업 상태를 즉시 시각화
  • 버전 관리: 변경 사항을 명확히 표시
  • 권한 구분: 역할에 따른 차별화된 UI
  • 충돌 해결: 동시 편집 시 직관적 충돌 해결

컬러 시스템

Primary Colors

/* Mint Green Family - 주요 액션, 브랜드 색상 */
--primary-50: #E6FFF9    /* 최상위 배경 */
--primary-100: #B3FFE6   /* 연한 배경 */
--primary-200: #80FFD4   /* 호버 상태 */
--primary-300: #4DFFC1   /* 비활성 상태 */
--primary-400: #1AFFAF  /* 보조 액션 */
--primary-500: #00D4AA   /* 주요 액션 (메인 브랜드 컬러) */
--primary-600: #00B894   /* 눌림 상태 */
--primary-700: #009878   /* 어두운 배경 */
--primary-800: #00785C   /* 고대비 텍스트 */
--primary-900: #005940   /* 최고 대비 */

Secondary Colors

/* Blue Family - 정보, 보조 액션 */
--secondary-50: #E3F2FD
--secondary-100: #BBDEFB
--secondary-200: #90CAF9
--secondary-300: #64B5F6
--secondary-400: #42A5F5
--secondary-500: #2196F3   /* 보조 액션, 링크 */
--secondary-600: #1E88E5
--secondary-700: #1976D2
--secondary-800: #1565C0
--secondary-900: #0D47A1

Neutral Colors

/* Gray Family - 텍스트, 배경, 경계선 */
--neutral-50: #FAFAFA    /* 배경 */
--neutral-100: #F5F5F5   /* 카드 배경 */
--neutral-200: #EEEEEE   /* 구분선 */
--neutral-300: #E0E0E0   /* 비활성 경계선 */
--neutral-400: #BDBDBD   /* 비활성 텍스트 */
--neutral-500: #9E9E9E   /* 보조 텍스트 */
--neutral-600: #757575   /* 본문 텍스트 */
--neutral-700: #616161   /* 제목 텍스트 */
--neutral-800: #424242   /* 강조 텍스트 */
--neutral-900: #212121   /* 최고 대비 텍스트 */

Status Colors

/* Success - 완료, 성공 상태 */
--success-50: #E8F5E8
--success-100: #C8E6C8
--success-500: #4CAF50   /* 완료, 성공 */
--success-700: #388E3C

/* Warning - 주의, 대기 상태 */
--warning-50: #FFF8E1
--warning-100: #FFECB3
--warning-500: #FF9800   /* 주의, 진행중 */
--warning-700: #F57C00

/* Error - 오류, 실패, 지연 상태 */
--error-50: #FFEBEE
--error-100: #FFCDD2
--error-500: #F44336    /* 오류, 지연 */
--error-700: #D32F2F

/* Info - 정보, 알림 */
--info-50: #E1F5FE
--info-100: #B3E5FC
--info-500: #03A9F4    /* 정보, 알림 */
--info-700: #0288D1

회의록 서비스 특화 색상

/* Meeting Status */
--meeting-ongoing: #FF5722     /* 진행중 회의 (주황-빨강) */
--meeting-scheduled: #9C27B0   /* 예정된 회의 (보라) */
--meeting-completed: #4CAF50   /* 완료된 회의 (초록) */

/* Verification Status */
--verified: #00D4AA           /* 검증완료 (Primary) */
--pending: #FF9800            /* 검증대기 (Warning) */
--rejected: #F44336           /* 검증거부 (Error) */

/* Todo Priority */
--todo-high: #F44336          /* 높은 우선순위 */
--todo-medium: #FF9800        /* 보통 우선순위 */
--todo-low: #9E9E9E          /* 낮은 우선순위 */

/* AI Processing */
--ai-processing: #673AB7      /* AI 처리중 (보라) */
--ai-complete: #00D4AA        /* AI 처리완료 (Primary) */

타이포그래피

폰트 패밀리

/* 주요 폰트 - 한국어 최적화 */
--font-primary: 'Pretendard', -apple-system, BlinkMacSystemFont, system-ui, Roboto, 'Helvetica Neue', 'Segoe UI', sans-serif;

/* 코드/데이터 폰트 */
--font-mono: 'SF Mono', Monaco, Inconsolata, 'Roboto Mono', Consolas, 'Courier New', monospace;

/* 영문 제목 폰트 (선택적) */
--font-heading: 'Inter', 'Pretendard', sans-serif;

글자 크기 시스템 (Mobile First)

/* Mobile (320px~767px) */
--text-xs: 0.75rem    /* 12px - 캡션, 메타 정보 */
--text-sm: 0.875rem   /* 14px - 보조 텍스트 */
--text-base: 1rem     /* 16px - 기본 본문 */
--text-lg: 1.125rem   /* 18px - 강조 텍스트 */
--text-xl: 1.25rem    /* 20px - 소제목 */
--text-2xl: 1.5rem    /* 24px - 제목 */
--text-3xl: 1.875rem  /* 30px - 대제목 */

/* Tablet+ (768px+) */
--text-lg-tablet: 1.25rem   /* 20px */
--text-xl-tablet: 1.5rem    /* 24px */
--text-2xl-tablet: 1.875rem /* 30px */
--text-3xl-tablet: 2.25rem  /* 36px */
--text-4xl-tablet: 3rem     /* 48px */

글자 굵기

--font-thin: 100
--font-light: 300
--font-normal: 400      /* 기본 본문 */
--font-medium: 500      /* 중요 텍스트 */
--font-semibold: 600    /* 제목 */
--font-bold: 700        /* 강조 제목 */
--font-black: 900       /* 특별 강조 */

행간 (Line Height)

--leading-tight: 1.25    /* 제목용 */
--leading-snug: 1.375    /* 부제목용 */
--leading-normal: 1.5    /* 기본 본문 */
--leading-relaxed: 1.625 /* 긴 텍스트 */
--leading-loose: 2       /* 여유로운 간격 */

자간 (Letter Spacing)

--tracking-tighter: -0.05em  /* 큰 제목 */
--tracking-tight: -0.025em   /* 제목 */
--tracking-normal: 0         /* 기본 */
--tracking-wide: 0.025em     /* 소제목 */
--tracking-wider: 0.05em     /* 캡션 */

타이포그래피 클래스

/* Heading Styles */
.heading-1 {
  font-size: var(--text-3xl);
  font-weight: var(--font-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.heading-2 {
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.heading-3 {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-snug);
}

/* Body Styles */
.body-large {
  font-size: var(--text-lg);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

.body-normal {
  font-size: var(--text-base);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

.body-small {
  font-size: var(--text-sm);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

/* Utility Styles */
.caption {
  font-size: var(--text-xs);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
  color: var(--neutral-500);
}

.label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  line-height: var(--leading-normal);
}

간격 시스템

Spacing Scale (4px 기준)

--space-px: 1px
--space-0: 0
--space-1: 0.25rem    /* 4px */
--space-2: 0.5rem     /* 8px */
--space-3: 0.75rem    /* 12px */
--space-4: 1rem       /* 16px */
--space-5: 1.25rem    /* 20px */
--space-6: 1.5rem     /* 24px */
--space-8: 2rem       /* 32px */
--space-10: 2.5rem    /* 40px */
--space-12: 3rem      /* 48px */
--space-16: 4rem      /* 64px */
--space-20: 5rem      /* 80px */
--space-24: 6rem      /* 96px */

컴포넌트별 간격 규칙

/* 컴포넌트 내부 간격 */
--component-padding-sm: var(--space-3)    /* 12px - 작은 컴포넌트 */
--component-padding-md: var(--space-4)    /* 16px - 기본 컴포넌트 */
--component-padding-lg: var(--space-6)    /* 24px - 큰 컴포넌트 */

/* 컴포넌트 간 간격 */
--component-gap-sm: var(--space-2)        /* 8px - 밀접한 요소 */
--component-gap-md: var(--space-4)        /* 16px - 기본 간격 */
--component-gap-lg: var(--space-8)        /* 32px - 섹션 간격 */

/* 페이지 레이아웃 간격 */
--page-padding-mobile: var(--space-4)     /* 16px - 모바일 */
--page-padding-tablet: var(--space-6)     /* 24px - 태블릿 */
--page-padding-desktop: var(--space-8)    /* 32px - 데스크톱 */

컴포넌트 스타일

버튼

/* Primary Button */
.btn-primary {
  background-color: var(--primary-500);
  color: white;
  border: none;
  border-radius: 8px;
  padding: var(--space-3) var(--space-6);
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  line-height: var(--leading-normal);
  min-height: 44px;
  transition: all 0.2s ease;
}

.btn-primary:hover {
  background-color: var(--primary-600);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 212, 170, 0.25);
}

.btn-primary:active {
  background-color: var(--primary-700);
  transform: translateY(0);
}

.btn-primary:disabled {
  background-color: var(--neutral-300);
  color: var(--neutral-500);
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* Secondary Button */
.btn-secondary {
  background-color: transparent;
  color: var(--primary-500);
  border: 2px solid var(--primary-500);
  border-radius: 8px;
  padding: calc(var(--space-3) - 2px) calc(var(--space-6) - 2px);
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  min-height: 44px;
  transition: all 0.2s ease;
}

.btn-secondary:hover {
  background-color: var(--primary-50);
  border-color: var(--primary-600);
  color: var(--primary-600);
}

/* Tertiary Button */
.btn-tertiary {
  background-color: transparent;
  color: var(--neutral-600);
  border: none;
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  text-decoration: underline;
  text-underline-offset: 2px;
  min-height: 36px;
}

.btn-tertiary:hover {
  color: var(--primary-500);
  text-decoration-color: var(--primary-500);
}

/* Button Sizes */
.btn-small {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  min-height: 36px;
}

.btn-large {
  padding: var(--space-4) var(--space-8);
  font-size: var(--text-lg);
  min-height: 52px;
}

입력 필드

.input-field {
  width: 100%;
  padding: var(--space-3) var(--space-4);
  border: 2px solid var(--neutral-300);
  border-radius: 8px;
  background-color: white;
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--neutral-800);
  min-height: 44px;
  transition: all 0.2s ease;
}

.input-field:focus {
  outline: none;
  border-color: var(--primary-500);
  box-shadow: 0 0 0 3px rgba(0, 212, 170, 0.1);
}

.input-field:invalid {
  border-color: var(--error-500);
}

.input-field:disabled {
  background-color: var(--neutral-100);
  border-color: var(--neutral-200);
  color: var(--neutral-400);
  cursor: not-allowed;
}

/* Input with Label */
.input-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.input-label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--neutral-700);
}

.input-error {
  font-size: var(--text-xs);
  color: var(--error-500);
  margin-top: var(--space-1);
}

카드

.card {
  background-color: white;
  border-radius: 12px;
  padding: var(--space-6);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  border: 1px solid var(--neutral-200);
  transition: all 0.2s ease;
}

.card:hover {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  transform: translateY(-2px);
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

.card-title {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  color: var(--neutral-800);
}

.card-content {
  color: var(--neutral-600);
  line-height: var(--leading-relaxed);
}

.card-footer {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--neutral-200);
  display: flex;
  gap: var(--space-3);
}

모달/다이얼로그

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--space-4);
}

.modal-content {
  background-color: white;
  border-radius: 16px;
  padding: var(--space-8);
  max-width: 500px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: 0 20px 25px rgba(0, 0, 0, 0.25);
}

.modal-header {
  margin-bottom: var(--space-6);
}

.modal-title {
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
  color: var(--neutral-800);
  margin-bottom: var(--space-2);
}

.modal-close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  background: none;
  border: none;
  font-size: var(--text-xl);
  color: var(--neutral-500);
  cursor: pointer;
  padding: var(--space-2);
  border-radius: 4px;
}

네비게이션

/* 모바일 하단 네비게이션 */
.bottom-nav {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: white;
  border-top: 1px solid var(--neutral-200);
  padding: var(--space-2) 0;
  display: flex;
  justify-content: space-around;
  z-index: 100;
}

.nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--space-2);
  text-decoration: none;
  color: var(--neutral-500);
  min-width: 60px;
  transition: color 0.2s ease;
}

.nav-item.active {
  color: var(--primary-500);
}

.nav-icon {
  font-size: 24px;
  margin-bottom: var(--space-1);
}

.nav-label {
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
}

/* 데스크톱 사이드바 네비게이션 */
.sidebar-nav {
  width: 240px;
  background-color: white;
  border-right: 1px solid var(--neutral-200);
  padding: var(--space-6);
  height: 100vh;
  position: fixed;
  left: 0;
  top: 0;
}

.sidebar-nav-item {
  display: flex;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-2);
  border-radius: 8px;
  text-decoration: none;
  color: var(--neutral-600);
  transition: all 0.2s ease;
}

.sidebar-nav-item:hover {
  background-color: var(--neutral-100);
  color: var(--neutral-800);
}

.sidebar-nav-item.active {
  background-color: var(--primary-50);
  color: var(--primary-700);
  font-weight: var(--font-medium);
}

반응형 브레이크포인트

브레이크포인트 정의

/* Mobile First Approach */
:root {
  --breakpoint-sm: 320px;   /* 작은 모바일 */
  --breakpoint-md: 768px;   /* 태블릿 */
  --breakpoint-lg: 1024px;  /* 작은 데스크톱 */
  --breakpoint-xl: 1280px;  /* 큰 데스크톱 */
  --breakpoint-2xl: 1536px; /* 매우 큰 화면 */
}

/* 미디어 쿼리 */
@media (min-width: 768px) {
  /* 태블릿 이상 */
}

@media (min-width: 1024px) {
  /* 데스크톱 이상 */
}

반응형 레이아웃 패턴

/* 컨테이너 */
.container {
  width: 100%;
  margin: 0 auto;
  padding: 0 var(--page-padding-mobile);
}

@media (min-width: 768px) {
  .container {
    padding: 0 var(--page-padding-tablet);
  }
}

@media (min-width: 1024px) {
  .container {
    padding: 0 var(--page-padding-desktop);
    max-width: 1200px;
  }
}

/* 그리드 시스템 */
.grid {
  display: grid;
  gap: var(--space-4);
}

.grid-cols-1 {
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .grid-cols-2-tablet {
    grid-template-columns: repeat(2, 1fr);
  }

  .grid-cols-3-tablet {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (min-width: 1024px) {
  .grid-cols-4-desktop {
    grid-template-columns: repeat(4, 1fr);
  }
}

회의록 서비스 특화 컴포넌트

회의 상태 배지

.meeting-status-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-3);
  border-radius: 20px;
  font-size: var(--text-xs);
  font-weight: var(--font-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
}

.meeting-status-ongoing {
  background-color: var(--meeting-ongoing);
  color: white;
  animation: pulse 2s infinite;
}

.meeting-status-scheduled {
  background-color: var(--meeting-scheduled);
  color: white;
}

.meeting-status-completed {
  background-color: var(--meeting-completed);
  color: white;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

Todo 상태 표시

.todo-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.todo-priority {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.todo-priority-high {
  background-color: var(--todo-high);
}

.todo-priority-medium {
  background-color: var(--todo-medium);
}

.todo-priority-low {
  background-color: var(--todo-low);
}

.todo-due-date {
  font-size: var(--text-xs);
  padding: var(--space-1) var(--space-2);
  border-radius: 4px;
  font-weight: var(--font-medium);
}

.todo-due-overdue {
  background-color: var(--error-100);
  color: var(--error-700);
}

.todo-due-today {
  background-color: var(--warning-100);
  color: var(--warning-700);
}

.todo-due-upcoming {
  background-color: var(--neutral-100);
  color: var(--neutral-600);
}

검증 상태 표시

.verification-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: 6px;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
}

.verification-verified {
  background-color: var(--success-100);
  color: var(--success-700);
}

.verification-verified::before {
  content: "✓";
  color: var(--success-500);
  font-weight: var(--font-bold);
}

.verification-pending {
  background-color: var(--warning-100);
  color: var(--warning-700);
}

.verification-pending::before {
  content: "⏳";
}

.verification-rejected {
  background-color: var(--error-100);
  color: var(--error-700);
}

.verification-rejected::before {
  content: "✗";
  color: var(--error-500);
  font-weight: var(--font-bold);
}

실시간 동기화 표시

.sync-indicator {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--neutral-500);
}

.sync-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background-color: var(--success-500);
}

.sync-syncing .sync-dot {
  background-color: var(--warning-500);
  animation: pulse 1s infinite;
}

.sync-error .sync-dot {
  background-color: var(--error-500);
}

.sync-offline .sync-dot {
  background-color: var(--neutral-400);
}

용어 설명 툴팁

.term-tooltip {
  position: relative;
  border-bottom: 1px dotted var(--primary-500);
  color: var(--primary-600);
  cursor: help;
}

.term-tooltip-content {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  background-color: var(--neutral-800);
  color: white;
  padding: var(--space-3);
  border-radius: 8px;
  font-size: var(--text-sm);
  white-space: nowrap;
  max-width: 300px;
  white-space: normal;
  z-index: 1000;
  opacity: 0;
  visibility: hidden;
  transition: all 0.2s ease;
}

.term-tooltip:hover .term-tooltip-content {
  opacity: 1;
  visibility: visible;
}

.term-tooltip-content::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--neutral-800);
}

음성 인식 상태 표시

.voice-recognition {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4);
  background-color: var(--neutral-50);
  border-radius: 12px;
  border: 2px solid var(--neutral-200);
}

.voice-recognition.active {
  border-color: var(--primary-500);
  background-color: var(--primary-50);
}

.voice-icon {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: var(--neutral-400);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.voice-icon.listening {
  background-color: var(--primary-500);
  animation: voice-pulse 1.5s infinite;
}

.voice-icon.processing {
  background-color: var(--warning-500);
  animation: spin 1s linear infinite;
}

@keyframes voice-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.1); }
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.voice-status {
  font-size: var(--text-sm);
  color: var(--neutral-600);
}

.voice-status.listening {
  color: var(--primary-600);
  font-weight: var(--font-medium);
}

진행률 표시

.progress-bar {
  width: 100%;
  height: 8px;
  background-color: var(--neutral-200);
  border-radius: 4px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background-color: var(--primary-500);
  border-radius: 4px;
  transition: width 0.3s ease;
}

.progress-label {
  display: flex;
  justify-content: space-between;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
}

.progress-percentage {
  color: var(--neutral-600);
  font-weight: var(--font-medium);
}

인터랙션 패턴

애니메이션 및 트랜지션

/* 기본 트랜지션 */
.transition-fast {
  transition: all 0.15s ease;
}

.transition-normal {
  transition: all 0.2s ease;
}

.transition-slow {
  transition: all 0.3s ease;
}

/* 호버 효과 */
.hover-lift:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.hover-scale:hover {
  transform: scale(1.02);
}

.hover-glow:hover {
  box-shadow: 0 0 20px rgba(0, 212, 170, 0.3);
}

/* 로딩 애니메이션 */
.loading-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid var(--neutral-300);
  border-top-color: var(--primary-500);
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

.loading-skeleton {
  background: linear-gradient(
    90deg,
    var(--neutral-200) 25%,
    var(--neutral-100) 50%,
    var(--neutral-200) 75%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

터치 피드백

.touch-feedback {
  position: relative;
  overflow: hidden;
}

.touch-feedback::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.3);
  transform: translate(-50%, -50%);
  transition: all 0.3s ease;
}

.touch-feedback:active::after {
  width: 100px;
  height: 100px;
}

포커스 관리

.focus-visible {
  outline: none;
}

.focus-visible:focus-visible {
  outline: 2px solid var(--primary-500);
  outline-offset: 2px;
}

/* 키보드 네비게이션을 위한 스킵 링크 */
.skip-link {
  position: absolute;
  top: -40px;
  left: 6px;
  background-color: var(--primary-500);
  color: white;
  padding: var(--space-2) var(--space-4);
  text-decoration: none;
  border-radius: 4px;
  z-index: 1000;
}

.skip-link:focus {
  top: 6px;
}

변경 이력

v1.0.0 (2025-10-21)

  • 초기 스타일 가이드 작성
    • 브랜드 아이덴티티 및 디자인 원칙 정의
    • 민트 그린 기반 컬러 시스템 구축
    • Mobile First 타이포그래피 시스템
    • 회의록 서비스 특화 컴포넌트 스타일 정의
    • 접근성 고려한 인터랙션 패턴
    • 반응형 브레이크포인트 및 레이아웃 시스템

향후 계획

  • v1.1.0: 다크 모드 지원 추가
  • v1.2.0: 고급 애니메이션 패턴 확장
  • v1.3.0: 사용자 피드백 기반 개선사항 반영