/* ===================================================================== UI 프리미티브 스타일 — 토큰 변수만 참조(tokens.css). 철칙: border-left 강조선 0 · 카드 상단 강조선 0 · 알약 radius 금지(원형은 dot/오브/아바타만). 강조 = weight + accent 텍스트 + accent-tint 배경 + kicker(+dot). ===================================================================== */ /* ── Kicker (상단 소제목, 양산형 좌측바 대체 위계 신호) §3.6 ── */ .vg-kicker { font-family: var(--font-num); font-size: var(--fs-kicker); font-weight: 600; letter-spacing: 0.08em; color: var(--text-accent); display: inline-flex; align-items: center; gap: 8px; text-transform: none; } .vg-kicker__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent-bright); flex: none; } /* ── SectionHead ── */ .vg-sechead { margin-bottom: var(--sp-5); } .vg-sechead__kicker { margin-bottom: 6px; } .vg-sechead__title { font-size: var(--fs-h2); font-weight: 600; letter-spacing: 0; color: var(--text-strong); line-height: 1.35; } .vg-sechead__desc { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 4px; } /* ── Button (위계 3단 + danger). radius 8px, 알약 금지 §7.1 ── */ .vg-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; font: 600 var(--fs-sm) / 1 var(--font-sans); padding: 10px 18px; border-radius: var(--radius); border: 1px solid transparent; transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-spring), box-shadow var(--dur-fast) var(--ease-out); cursor: pointer; white-space: nowrap; user-select: none; } .vg-btn:active { transform: translateY(1px) scale(0.98); } .vg-btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; } .vg-btn--block { width: 100%; } .vg-btn--sm { padding: 7px 13px; font-size: var(--fs-xs); } .vg-btn--lg { padding: 13px 22px; font-size: var(--fs-body); } .vg-btn--primary { background: linear-gradient(105deg, color-mix(in srgb, var(--accent) 90%, var(--bg-surface)), var(--accent)); color: var(--text-on-accent); border-color: color-mix(in srgb, var(--botanical-gold) 24%, var(--accent)); box-shadow: inset 0 1px 0 color-mix(in srgb, var(--bg-surface) 32%, transparent); } .vg-btn--primary:hover:not(:disabled) { background: var(--accent-deep); } .vg-btn--secondary { background: var(--surface-gradient); color: var(--text-accent); border-color: color-mix(in srgb, var(--accent) 62%, var(--botanical-hair)); } .vg-btn--secondary:hover:not(:disabled) { background: var(--accent-tint); } .vg-btn--ghost { background: transparent; color: var(--text-body); } .vg-btn--ghost:hover:not(:disabled) { background: var(--bg-surface-2); color: var(--text-strong); } .vg-btn--danger { background: var(--crit-solid); color: var(--text-on-accent); } .vg-btn--danger:hover:not(:disabled) { background: var(--crit-text); } /* ── Surface SSOT ── */ .vg-surface.vg-surface--panel { background: var(--glass-surface); border: 1px solid var(--glass-border); border-radius: var(--radius-lg); box-shadow: var(--glass-shadow); } .vg-surface.vg-surface--inset { background: var(--bg-surface-2); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); box-shadow: var(--glass-inset-shadow); } .vg-surface.vg-surface--interactive { background: var(--bg-surface); border: 1px solid var(--border-subtle); border-radius: var(--radius); box-shadow: var(--shadow-sm); transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out); } .vg-surface.vg-surface--interactive:hover { border-color: color-mix(in srgb, var(--accent) 48%, var(--glass-border)); background: var(--glass-surface-strong); box-shadow: var(--shadow-island); transform: translateY(-1px); } /* 포커스 가시성 — outline 채널로 링을 그린다(WCAG 2.4.7). */ .vg-surface.vg-surface--interactive:focus-visible { outline: 3px solid var(--focus-ring); outline-offset: 2px; } .vg-surface.vg-surface--flat { box-shadow: none; } .vg-surface.vg-surface--tint { background: var(--bg-tint); border-color: transparent; box-shadow: none; } /* ── Tabs behavior primitive. 시각 표면은 만들지 않는다. ── */ .vg-tabs, .vg-tabs__panel { min-width: 0; } .vg-tabs__trigger:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; } /* ── Card / Panel 크기 계약. 표면은 위 Surface만 소유한다. ── */ .vg-card { padding: var(--sp-5); } .vg-panel { border-radius: var(--radius-lg); padding: var(--sp-6); } /* ── Badge (배경 틴트 + 텍스트, 좌측바 없음) ── */ .vg-badge { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-num); font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.01em; padding: 2px 9px; border-radius: 100px; /* 칩/배지만 100px 관용 (DESIGN_CONCEPT 데모 일치) */ line-height: 1.5; } .vg-badge--neutral { color: var(--ink-2); background: var(--paper-2); } .vg-badge--accent { color: var(--accent-deep); background: var(--accent-tint); } .vg-badge--pos { color: var(--pos-text); background: var(--pos-tint); } .vg-badge--warn { color: var(--warn-text); background: var(--warn-tint); } .vg-badge--crit { color: var(--crit-text); background: var(--crit-tint); } .vg-badge--info { color: var(--info-text); background: var(--info-tint); } /* ── Dot (상태 점). 원형 예외 허용 대상 ── */ .vg-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--neutral-200); } .vg-dot--accent { background: var(--accent); } .vg-dot--pos { background: var(--pos-solid); } .vg-dot--warn { background: var(--warn-solid); } .vg-dot--crit { background: var(--crit-solid); } .vg-dot--info { background: var(--info-solid); } .vg-dot--muted { background: var(--ink-3); } /* ── StatLine (요약 스탯, tabular) ── */ .vg-statline { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-5); } .vg-statline__item { display: inline-flex; align-items: baseline; gap: 7px; } .vg-statline__num { font-size: 20px; font-weight: 700; color: var(--text-strong); font-variant-numeric: tabular-nums; letter-spacing: 0; } .vg-statline__lab { font-size: var(--fs-xs); color: var(--text-muted); } .vg-statline__sep { width: 1px; height: 18px; background: var(--hair); } /* ── ProgressBar (가로 게이지, 라운드 없는 사각 트랙) §5.5/§6.4 ── */ .vg-progress { width: 100%; height: 8px; background: var(--paper-2); border-radius: 4px; overflow: hidden; } .vg-progress--slim { height: 4px; } .vg-progress__fill { height: 100%; border-radius: 4px; background: var(--accent); transition: width var(--dur-slow) var(--ease-out); } .vg-progress__fill--muted { background: var(--neutral-200); } .vg-progress__fill--warn { background: var(--warn-solid); } .vg-progress__fill--crit { background: var(--crit-solid); } .vg-progress__fill--clay { background: var(--clay); } /* ── Field / Input §7.2 (radius 6px, 포커스 보더색+ring, 좌측바 X) ── */ .vg-field { display: flex; flex-direction: column; gap: 6px; } .vg-field__label { font-size: var(--fs-sm); font-weight: 600; color: var(--text-strong); } .vg-field__hint { font-size: var(--fs-xs); color: var(--text-muted); } .vg-field__error { font-size: var(--fs-xs); color: var(--crit-text); } .vg-input { width: 100%; background: var(--bg-surface-2); color: var(--text-strong); border: 1px solid var(--border-strong); border-radius: var(--radius-sm); padding: 10px 12px; font: var(--fs-body) / 1.5 var(--font-sans); transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out); } .vg-input::placeholder { color: var(--neutral-400); } .vg-input:focus { border-color: var(--border-focus); outline: none; box-shadow: 0 0 0 3px var(--focus-ring); } .vg-input[aria-invalid="true"] { border-color: var(--crit-solid); } /* ── 빈/준비중 상태 (스텁 페이지 공통) ── */ .vg-empty { display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-3); max-width: var(--maxw-read); } .vg-empty__title { font-size: var(--fs-h1); font-weight: 700; letter-spacing: 0; color: var(--text-strong); line-height: 1.3; } .vg-empty__desc { font-size: var(--fs-lead); color: var(--text-body); line-height: 1.6; }