e70267f738
Build & Deploy to K8s / build-and-deploy (push) Failing after 1m14s
- 음성 인식 (scada-demo/js/voice.js) — 한국어 발화 → 키워드 매핑 → INVYONE_UI.select() · 사이드바 마이크 버튼 + transcript 라벨, 매칭 시 청록 펄스 · Chrome/Edge HTTPS 환경 (운영 siflex.invyone.com OK) - 경고시스템/다중경고 버튼을 음성 인식과 동일 톤 · 🚨 emoji → SVG 삼각형 아이콘, voice-btn 패턴 (다크 솔리드 + 컬러 액센트) · 정적 (반짝 펄스 애니메이션 제거) - client.ts stash pop conflict 정리 (DEV_TENANT_HOST + 도메인 정리 통합) - ui.js 다중 경고 시연 wiring + scada 작업 노트 2건 - 기타 syncthing 보류분 batch (대시보드/레이아웃/로그인 layout 정리) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
658 lines
24 KiB
CSS
658 lines
24 KiB
CSS
/* ===================================================================
|
|
INVYONE v5 — Atomic Component Library
|
|
Ported from INVYONE Design System (ui_kits/app + preview/*).
|
|
All classes use .v5- prefix to avoid shadcn/Tailwind collision.
|
|
Tokens defined in v5-layout.css :root / .dark.
|
|
Concept: "Solid + Glow" (no blur on main app).
|
|
=================================================================== */
|
|
|
|
/* ===================================================================
|
|
⚠️ DEPRECATION NOTICE (2026-04-22)
|
|
-------------------------------------------------------------------
|
|
NEW CODE MUST USE shadcn components from @/components/ui/*:
|
|
<Button>, <Input>, <Table>, <Dialog>, <Badge>, <Select>, ...
|
|
|
|
The .v5-* classes below are LEGACY and kept only for:
|
|
- Atomic patterns inside v5-only prototypes
|
|
- Gradual migration of existing code (see grep for .v5-btn / .v5-bdg /
|
|
.v5-tbl / .v5-modal / .v5-fi usages — currently < 20 hits)
|
|
|
|
DO NOT reference .v5-* classes in new components.
|
|
Prefer shadcn ui primitives which wrap Radix + semantic tokens.
|
|
=================================================================== */
|
|
|
|
/* =================================================================
|
|
Buttons (.v5-btn + variants)
|
|
Defaults: 30px height, 0.7rem text, primary fills, glow on hover.
|
|
================================================================= */
|
|
.v5-btn {
|
|
display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
|
|
height: 34px; padding: 0 var(--v5-sp-4);
|
|
font-family: var(--v5-font-sans);
|
|
font-size: .8125rem; font-weight: var(--v5-fw-semi);
|
|
border: 1px solid transparent; border-radius: var(--v5-radius-md);
|
|
background: transparent; color: var(--v5-text);
|
|
cursor: pointer; user-select: none; white-space: nowrap;
|
|
transition: background .2s var(--v5-ease-move),
|
|
border-color .2s var(--v5-ease-move),
|
|
color .2s var(--v5-ease-move),
|
|
box-shadow .2s var(--v5-ease-move),
|
|
transform .12s var(--v5-ease-move),
|
|
opacity .2s var(--v5-ease-move);
|
|
}
|
|
.v5-btn svg { width: 14px; height: 14px; stroke-width: 1.75; flex-shrink: 0; }
|
|
.v5-btn:disabled { opacity: .4; cursor: not-allowed; }
|
|
.v5-btn:active:not(:disabled) { transform: scale(.98); }
|
|
|
|
/* primary — filled accent */
|
|
.v5-btn.primary {
|
|
background: var(--v5-primary); color: #fff;
|
|
border-color: var(--v5-primary);
|
|
}
|
|
.v5-btn.primary:hover:not(:disabled) {
|
|
opacity: .92; box-shadow: var(--v5-glow-sm); transform: translateY(-1px);
|
|
}
|
|
|
|
/* secondary — solid surface, neutral */
|
|
.v5-btn.secondary {
|
|
background: var(--v5-surface-solid); color: var(--v5-text);
|
|
border-color: var(--v5-border);
|
|
}
|
|
.v5-btn.secondary:hover:not(:disabled) {
|
|
background: var(--v5-surface-hover); border-color: rgba(var(--v5-primary-rgb), .25);
|
|
}
|
|
|
|
/* ghost — text-only, no fill */
|
|
.v5-btn.ghost {
|
|
background: transparent; color: var(--v5-text-sec); border-color: transparent;
|
|
}
|
|
.v5-btn.ghost:hover:not(:disabled) {
|
|
background: var(--v5-surface-hover); color: var(--v5-text);
|
|
}
|
|
|
|
/* danger — destructive action */
|
|
.v5-btn.danger {
|
|
background: var(--v5-red); color: #fff; border-color: var(--v5-red);
|
|
}
|
|
.v5-btn.danger:hover:not(:disabled) {
|
|
opacity: .92; box-shadow: var(--v5-glow-danger); transform: translateY(-1px);
|
|
}
|
|
|
|
/* size: sm — compact 28px */
|
|
.v5-btn.sm {
|
|
height: 28px; padding: 0 var(--v5-sp-3);
|
|
font-size: .75rem; border-radius: var(--v5-radius-sm);
|
|
}
|
|
.v5-btn.sm svg { width: 12px; height: 12px; }
|
|
|
|
/* size: lg — prominent 40px */
|
|
.v5-btn.lg {
|
|
height: 40px; padding: 0 var(--v5-sp-5);
|
|
font-size: .875rem; border-radius: var(--v5-radius-md-2);
|
|
}
|
|
.v5-btn.lg svg { width: 16px; height: 16px; }
|
|
|
|
/* focus ring (keyboard) */
|
|
.v5-btn:focus-visible {
|
|
outline: none;
|
|
border-color: var(--v5-primary);
|
|
box-shadow: 0 0 0 3px rgba(var(--v5-primary-rgb), .15), var(--v5-glow-sm);
|
|
}
|
|
|
|
/* =================================================================
|
|
Badges (.v5-bdg + status variants)
|
|
Pill, tiny caps, status-tinted.
|
|
================================================================= */
|
|
.v5-bdg {
|
|
display: inline-flex; align-items: center; gap: .35rem;
|
|
padding: .22rem .55rem;
|
|
font-size: .72rem; font-weight: var(--v5-fw-semi);
|
|
border-radius: var(--v5-radius-pill);
|
|
background: var(--v5-bg-subtle); color: var(--v5-text-sec);
|
|
white-space: nowrap;
|
|
line-height: 1.2;
|
|
}
|
|
.v5-bdg .v5-bdg-dot {
|
|
width: 5px; height: 5px; border-radius: 50%;
|
|
background: currentColor; flex-shrink: 0;
|
|
}
|
|
.v5-bdg.in { background: rgba(var(--v5-primary-rgb), .10); color: var(--v5-primary); }
|
|
.v5-bdg.ok { background: rgba(var(--v5-green-rgb), .12); color: rgb(var(--v5-green-rgb)); }
|
|
.v5-bdg.warn { background: rgba(var(--v5-amber-rgb), .22); color: #8a5a00; }
|
|
.v5-bdg.err { background: rgba(var(--v5-red-rgb), .10); color: rgb(var(--v5-red-rgb)); }
|
|
.v5-bdg.off { background: var(--v5-bg-subtle); color: var(--v5-text-sec); }
|
|
.v5-bdg.cy { background: rgba(var(--v5-cyan-rgb), .12); color: rgb(var(--v5-cyan-rgb)); }
|
|
.dark .v5-bdg.warn { color: rgb(var(--v5-amber-rgb)); }
|
|
|
|
/* =================================================================
|
|
Cards (.v5-card + .glow / .elev)
|
|
Solid surface, primary border, optional glow.
|
|
================================================================= */
|
|
.v5-card {
|
|
background: var(--v5-surface-solid);
|
|
border: 1px solid var(--v5-border);
|
|
border-radius: var(--v5-radius-md-2);
|
|
padding: var(--v5-sp-4);
|
|
transition: border-color .2s var(--v5-ease-move), box-shadow .3s var(--v5-ease-move);
|
|
}
|
|
.v5-card.glow { box-shadow: var(--v5-glow-sm); }
|
|
.v5-card.elev { box-shadow: var(--v5-glow-lg); }
|
|
.v5-card:hover { border-color: rgba(var(--v5-primary-rgb), .22); }
|
|
|
|
.v5-card-head {
|
|
display: flex; align-items: flex-start; justify-content: space-between;
|
|
gap: .6rem; margin-bottom: .4rem;
|
|
}
|
|
.v5-card-title {
|
|
font-size: var(--v5-fs-body-sm); font-weight: 700;
|
|
color: var(--v5-text);
|
|
line-height: 1.3;
|
|
}
|
|
|
|
/* =================================================================
|
|
Page Head (.v5-page-head)
|
|
crumbs / title / sub / actions(우정렬, max 3)
|
|
================================================================= */
|
|
.v5-page-head {
|
|
display: flex; align-items: flex-start; justify-content: space-between;
|
|
gap: 1rem; margin-bottom: var(--v5-sp-5);
|
|
}
|
|
.v5-page-head-l { min-width: 0; flex: 1; }
|
|
.v5-page-head-r { display: flex; align-items: center; gap: .4rem; flex-shrink: 0; }
|
|
.v5-crumbs {
|
|
font-size: .72rem; color: var(--v5-text-muted);
|
|
display: flex; align-items: center; gap: .4rem;
|
|
margin-bottom: .3rem;
|
|
}
|
|
.v5-crumbs .sep { opacity: .5; }
|
|
.v5-page-title {
|
|
font-size: var(--v5-fs-h1);
|
|
font-weight: 800; letter-spacing: var(--v5-ls-tight);
|
|
line-height: var(--v5-lh-tight);
|
|
color: var(--v5-text);
|
|
}
|
|
.v5-page-sub {
|
|
font-size: var(--v5-fs-body-sm); color: var(--v5-text-muted);
|
|
margin-top: .25rem;
|
|
}
|
|
|
|
/* =================================================================
|
|
Tables (.v5-tbl wrapped in .v5-table-wrap)
|
|
================================================================= */
|
|
.v5-table-wrap {
|
|
border: 1px solid var(--v5-border);
|
|
border-radius: var(--v5-radius-md-2);
|
|
overflow: hidden;
|
|
background: var(--v5-surface-solid);
|
|
}
|
|
.v5-tbl {
|
|
width: 100%; border-collapse: collapse;
|
|
font-size: var(--v5-fs-body-sm);
|
|
color: var(--v5-text);
|
|
}
|
|
.v5-tbl thead th {
|
|
text-align: left;
|
|
padding: .7rem var(--v5-sp-4);
|
|
font-size: var(--v5-fs-caption-lg);
|
|
font-weight: 600;
|
|
color: var(--v5-text-sec);
|
|
background: var(--v5-bg-subtle);
|
|
border-bottom: 1px solid var(--v5-border);
|
|
white-space: nowrap;
|
|
}
|
|
.v5-tbl tbody td {
|
|
padding: .65rem var(--v5-sp-4);
|
|
border-bottom: 1px solid var(--v5-border-subtle);
|
|
vertical-align: middle;
|
|
}
|
|
.v5-tbl tbody tr:last-child td { border-bottom: none; }
|
|
.v5-tbl tbody tr:hover td { background: rgba(var(--v5-primary-rgb), .04); }
|
|
.v5-tbl .mono {
|
|
font-family: var(--v5-font-mono);
|
|
font-size: .68rem;
|
|
color: var(--v5-text-sec);
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
.v5-tbl .num {
|
|
text-align: right;
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* =================================================================
|
|
KPI (.v5-kpi-num + .v5-kpi-delta + .v5-kpi-sub)
|
|
Large number with trend pill underneath.
|
|
================================================================= */
|
|
.v5-kpi-num {
|
|
font-size: var(--v5-fs-display); font-weight: 800;
|
|
letter-spacing: -0.03em;
|
|
font-variant-numeric: tabular-nums;
|
|
line-height: 1.05;
|
|
color: var(--v5-text);
|
|
display: flex; align-items: baseline; gap: .6rem;
|
|
}
|
|
.v5-kpi-num.kpi-cyan { color: rgb(var(--v5-cyan-rgb)); }
|
|
.v5-kpi-num.kpi-green { color: rgb(var(--v5-green-rgb)); }
|
|
.v5-kpi-num.kpi-pink { color: rgb(var(--v5-pink-rgb)); }
|
|
.v5-kpi-num.kpi-amber { color: rgb(var(--v5-amber-rgb)); }
|
|
|
|
.v5-kpi-delta {
|
|
display: inline-flex; align-items: center; gap: .2rem;
|
|
font-size: .75rem; font-weight: var(--v5-fw-bold);
|
|
padding: .18rem .5rem; border-radius: var(--v5-radius-sm);
|
|
}
|
|
.v5-kpi-delta.up { background: rgba(var(--v5-green-rgb), .12); color: rgb(var(--v5-green-rgb)); }
|
|
.v5-kpi-delta.down { background: rgba(var(--v5-red-rgb), .12); color: rgb(var(--v5-red-rgb)); }
|
|
.v5-kpi-delta svg { width: 11px; height: 11px; stroke-width: 2; }
|
|
|
|
.v5-kpi-sub {
|
|
font-size: .75rem;
|
|
color: var(--v5-text-muted);
|
|
margin-top: .3rem;
|
|
}
|
|
|
|
/* =================================================================
|
|
Bar chart (.v5-bars / .v5-bar / .v5-bars-ax)
|
|
================================================================= */
|
|
.v5-bars {
|
|
display: flex; gap: 4px; height: 80px; align-items: flex-end;
|
|
padding: .3rem 0;
|
|
}
|
|
.v5-bar {
|
|
flex: 1; border-radius: 3px 3px 0 0;
|
|
background: linear-gradient(180deg, rgba(var(--v5-primary-rgb), .55), rgba(var(--v5-primary-rgb), .18));
|
|
transition: background .25s var(--v5-ease-move);
|
|
min-height: 2px;
|
|
}
|
|
.v5-bar:hover {
|
|
background: linear-gradient(180deg, var(--v5-primary), rgba(var(--v5-primary-rgb), .4));
|
|
}
|
|
.v5-bars-ax {
|
|
display: flex; gap: 4px; margin-top: .35rem;
|
|
font-size: .52rem; color: var(--v5-text-muted);
|
|
font-family: var(--v5-font-mono);
|
|
}
|
|
.v5-bars-ax > * { flex: 1; text-align: center; }
|
|
|
|
/* =================================================================
|
|
Activity Feed (.v5-feed / .v5-feed-row / .v5-feed-dot / .v5-feed-txt)
|
|
================================================================= */
|
|
.v5-feed {
|
|
display: flex; flex-direction: column; gap: .55rem;
|
|
}
|
|
.v5-feed-row {
|
|
display: flex; gap: .6rem; align-items: flex-start;
|
|
padding: .35rem .15rem; border-radius: var(--v5-radius-sm);
|
|
transition: background .2s var(--v5-ease-move);
|
|
}
|
|
.v5-feed-row:hover { background: var(--v5-surface-hover); }
|
|
.v5-feed-dot {
|
|
width: 28px; height: 28px; border-radius: var(--v5-radius-sm);
|
|
display: flex; align-items: center; justify-content: center;
|
|
background: rgba(var(--v5-primary-rgb), .12);
|
|
color: var(--v5-primary); flex-shrink: 0;
|
|
}
|
|
.v5-feed-dot.g { background: rgba(var(--v5-green-rgb), .12); color: rgb(var(--v5-green-rgb)); }
|
|
.v5-feed-dot.a { background: rgba(var(--v5-amber-rgb), .18); color: rgb(var(--v5-amber-rgb)); }
|
|
.v5-feed-dot.c { background: rgba(var(--v5-cyan-rgb), .12); color: rgb(var(--v5-cyan-rgb)); }
|
|
.v5-feed-dot.r { background: rgba(var(--v5-red-rgb), .12); color: rgb(var(--v5-red-rgb)); }
|
|
.v5-feed-dot svg { width: 14px; height: 14px; stroke-width: 1.75; }
|
|
.v5-feed-txt {
|
|
flex: 1; min-width: 0;
|
|
font-size: var(--v5-fs-body-sm);
|
|
color: var(--v5-text);
|
|
line-height: 1.4;
|
|
}
|
|
.v5-feed-txt b { color: var(--v5-text); font-weight: var(--v5-fw-semi); }
|
|
.v5-feed-txt .tm {
|
|
display: block;
|
|
font-size: .72rem; color: var(--v5-text-muted);
|
|
font-family: var(--v5-font-mono);
|
|
margin-top: .2rem;
|
|
}
|
|
|
|
/* =================================================================
|
|
Sparkline wrapper (.v5-spark)
|
|
================================================================= */
|
|
.v5-spark { display: block; width: 100%; height: 36px; }
|
|
|
|
/* =================================================================
|
|
Grid layouts (.v5-grid + .grid-2 / 3 / 4)
|
|
================================================================= */
|
|
.v5-grid { display: grid; gap: var(--v5-sp-4); }
|
|
.v5-grid.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
.v5-grid.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
.v5-grid.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
@media (max-width: 1024px) {
|
|
.v5-grid.grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
.v5-grid.grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
}
|
|
@media (max-width: 640px) {
|
|
.v5-grid.grid-2,
|
|
.v5-grid.grid-3,
|
|
.v5-grid.grid-4 { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* =================================================================
|
|
Form input wrapper (.v5-fi) + bare input (.v5-input)
|
|
================================================================= */
|
|
.v5-fi {
|
|
position: relative; display: inline-flex; align-items: center;
|
|
width: 100%;
|
|
}
|
|
.v5-fi > svg, .v5-fi > .v5-fi-icon {
|
|
position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
|
|
width: 14px; height: 14px; stroke-width: 1.75;
|
|
color: var(--v5-text-muted); pointer-events: none;
|
|
transition: color .2s var(--v5-ease-move);
|
|
}
|
|
.v5-fi:focus-within > svg, .v5-fi:focus-within > .v5-fi-icon { color: var(--v5-primary); }
|
|
.v5-input,
|
|
.v5-fi > input,
|
|
.v5-fi > select {
|
|
height: 32px; width: 100%;
|
|
padding: 0 var(--v5-sp-3) 0 2rem;
|
|
font-family: var(--v5-font-sans);
|
|
font-size: var(--v5-fs-body-sm);
|
|
color: var(--v5-text);
|
|
background: var(--v5-surface-solid);
|
|
border: 1px solid var(--v5-border);
|
|
border-radius: var(--v5-radius-md);
|
|
outline: none;
|
|
transition: border-color .2s var(--v5-ease-move), box-shadow .2s var(--v5-ease-move);
|
|
}
|
|
.v5-input:focus,
|
|
.v5-fi > input:focus,
|
|
.v5-fi > select:focus {
|
|
border-color: var(--v5-primary);
|
|
box-shadow: 0 0 0 3px rgba(var(--v5-primary-rgb), .15), var(--v5-glow-sm);
|
|
}
|
|
.v5-input::placeholder,
|
|
.v5-fi > input::placeholder { color: var(--v5-text-muted); }
|
|
|
|
/* When wrapper has no leading icon, remove the left padding. */
|
|
.v5-fi.no-icon > input,
|
|
.v5-fi.no-icon > select { padding-left: var(--v5-sp-3); }
|
|
|
|
/* Checkbox / radio */
|
|
.v5-check, .v5-radio {
|
|
width: 14px; height: 14px;
|
|
accent-color: var(--v5-primary);
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Toggle switch (.v5-toggle) */
|
|
.v5-toggle {
|
|
display: inline-block; position: relative;
|
|
width: 30px; height: 16px;
|
|
background: var(--v5-border); border-radius: var(--v5-radius-pill);
|
|
cursor: pointer; transition: background .25s var(--v5-ease-move);
|
|
}
|
|
.v5-toggle::after {
|
|
content: ''; position: absolute; left: 2px; top: 2px;
|
|
width: 12px; height: 12px; background: #fff; border-radius: 50%;
|
|
transition: transform .25s var(--v5-ease-move);
|
|
box-shadow: 0 1px 2px rgba(0, 0, 0, .15);
|
|
}
|
|
.v5-toggle.on { background: var(--v5-primary); }
|
|
.v5-toggle.on::after { transform: translateX(14px); }
|
|
|
|
/* =================================================================
|
|
Modal (.v5-overlay + .v5-modal)
|
|
Solid surface, glow shadow, scale-in animation.
|
|
================================================================= */
|
|
.v5-overlay {
|
|
position: fixed; inset: 0; z-index: 100;
|
|
background: rgba(6, 5, 14, .45);
|
|
display: flex; align-items: center; justify-content: center;
|
|
padding: 1rem;
|
|
animation: v5-overlay-in .22s var(--v5-ease-enter);
|
|
}
|
|
.v5-modal {
|
|
width: 100%; max-width: 560px;
|
|
background: var(--v5-surface-solid);
|
|
border: 1px solid var(--v5-border);
|
|
border-radius: var(--v5-radius-lg-2);
|
|
box-shadow: var(--v5-glow-lg);
|
|
padding: var(--v5-sp-5);
|
|
animation: v5-modal-in .3s var(--v5-ease-enter);
|
|
}
|
|
.v5-modal.sm { max-width: 420px; }
|
|
.v5-modal.lg { max-width: 720px; }
|
|
.v5-modal.xl { max-width: 960px; }
|
|
.v5-modal-head {
|
|
display: flex; align-items: flex-start; justify-content: space-between;
|
|
gap: .6rem; margin-bottom: .7rem;
|
|
}
|
|
.v5-modal-title {
|
|
font-size: var(--v5-fs-h2);
|
|
font-weight: var(--v5-fw-bold);
|
|
letter-spacing: var(--v5-ls-tight);
|
|
color: var(--v5-text);
|
|
}
|
|
.v5-modal-body {
|
|
font-size: var(--v5-fs-body);
|
|
color: var(--v5-text-sec);
|
|
line-height: 1.55;
|
|
margin-bottom: 1.1rem;
|
|
}
|
|
.v5-modal-body b { color: var(--v5-text); font-weight: var(--v5-fw-bold); }
|
|
.v5-modal-foot {
|
|
display: flex; justify-content: flex-end; gap: .4rem;
|
|
}
|
|
|
|
@keyframes v5-overlay-in {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
@keyframes v5-modal-in {
|
|
from { opacity: 0; transform: scale(.97) translateY(8px); }
|
|
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
}
|
|
|
|
/* =================================================================
|
|
Generic icon helper (.v5-ic) — keeps lucide aspect-locked.
|
|
================================================================= */
|
|
.v5-ic { display: inline-flex; flex-shrink: 0; }
|
|
.v5-ic svg { width: 100%; height: 100%; display: block; stroke-width: 1.75; }
|
|
|
|
/* =================================================================
|
|
TopNav (horizontal 메뉴바) — 디자인시스템 shell-components.jsx TopNav 포팅.
|
|
헤더 로고 오른쪽에 위치. 섹션 hover → flyout → sub-flyout.
|
|
================================================================= */
|
|
.v5-topnav{
|
|
display:flex;align-items:center;height:100%;
|
|
gap:.1rem;
|
|
font-family:var(--v5-font-sans);
|
|
}
|
|
.v5-tn-section{
|
|
position:relative;height:100%;display:flex;align-items:center;
|
|
animation:v5-tn-in .4s var(--v5-ease-enter) backwards;
|
|
}
|
|
@keyframes v5-tn-in{
|
|
from{opacity:0;transform:translateY(-4px);}
|
|
to {opacity:1;transform:translateY(0);}
|
|
}
|
|
.v5-tn-item{
|
|
display:inline-flex;align-items:center;gap:.3rem;
|
|
height:30px;padding:0 var(--v5-sp-4);
|
|
border:none;background:transparent;color:var(--v5-text-sec);
|
|
font-family:inherit;font-size:.78rem;font-weight:var(--v5-fw-semi);
|
|
letter-spacing:var(--v5-ls-tight);cursor:pointer;
|
|
border-radius:var(--v5-radius-md);
|
|
transition:background .2s var(--v5-ease-move),color .2s var(--v5-ease-move);
|
|
}
|
|
.v5-tn-item svg{opacity:.55;transition:opacity .2s var(--v5-ease-move),transform .2s var(--v5-ease-move);}
|
|
.v5-tn-section:hover .v5-tn-item,
|
|
.v5-tn-section.open .v5-tn-item{color:var(--v5-primary);}
|
|
.v5-tn-section:hover .v5-tn-item svg,
|
|
.v5-tn-section.open .v5-tn-item svg{opacity:1;}
|
|
/* open 상태에선 chevron 을 살짝 내려서(2px) "펼쳤다" 감만 주기 — 180° 회전은 flyout 방향과 역방향이라 혼동 유발 */
|
|
.v5-tn-section.open .v5-tn-item svg{transform:translateY(1px);}
|
|
.v5-tn-section.on .v5-tn-item{color:var(--v5-primary);}
|
|
.v5-admin-mode .v5-tn-section.on .v5-tn-item{color:var(--v5-primary);}
|
|
|
|
/* Flyout (1단) — 섹션과 border 가 맞닿게(top:100%) + 내부 top 패딩으로 시각 여백만 유지.
|
|
→ 2px 공백 구간에서 mouseleave 가 타서 flyout 이 순간 사라지던 문제 제거. */
|
|
.v5-tn-flyout{
|
|
position:absolute;top:100%;left:0;min-width:200px;
|
|
background:var(--v5-surface-solid);
|
|
border:1px solid var(--v5-border);
|
|
border-radius:var(--v5-radius-md);
|
|
padding:.6rem .3rem .3rem .3rem;z-index:40;
|
|
animation:v5-tn-flyout-in .2s var(--v5-ease-enter) backwards;
|
|
}
|
|
/* 섹션의 마지막 1px 과 flyout 의 첫 1px 를 겹쳐 "끊김" 제로. 시각적으론 boundary 가 안 보임(밝은 border 2중). */
|
|
.v5-tn-flyout::before{
|
|
content:'';position:absolute;left:0;right:0;top:-6px;height:6px;
|
|
background:transparent;pointer-events:auto;
|
|
}
|
|
@keyframes v5-tn-flyout-in{
|
|
from{opacity:0;transform:translateY(-6px);}
|
|
to {opacity:1;transform:translateY(0);}
|
|
}
|
|
|
|
/* Row (flyout 아이템) */
|
|
.v5-tn-row{
|
|
display:flex;align-items:center;gap:.45rem;
|
|
padding:.5rem .55rem;border-radius:var(--v5-radius-sm);
|
|
font-size:.74rem;font-weight:500;
|
|
color:var(--v5-text-sec);cursor:pointer;position:relative;
|
|
animation:v5-tn-row-in .28s var(--v5-ease-enter) backwards;
|
|
transition:
|
|
background .18s var(--v5-ease-move),
|
|
color .18s var(--v5-ease-move),
|
|
transform .18s var(--v5-ease-move);
|
|
white-space:nowrap;
|
|
}
|
|
@keyframes v5-tn-row-in{
|
|
from{opacity:0;transform:translateX(-6px);}
|
|
to {opacity:1;transform:translateX(0);}
|
|
}
|
|
.v5-tn-row:hover{background:var(--v5-surface-hover);color:var(--v5-text);transform:translateX(2px);}
|
|
.v5-tn-row.on{background:rgba(var(--v5-primary-rgb),.1);color:var(--v5-primary);font-weight:600;}
|
|
.v5-admin-mode .v5-tn-row.on{background:rgba(var(--v5-primary-rgb),.1);color:var(--v5-primary);}
|
|
.v5-tn-row .v5-tn-row-label{flex:1;min-width:0;}
|
|
.v5-tn-row .v5-tn-ic{display:inline-flex;width:14px;height:14px;color:currentColor;opacity:.7;}
|
|
.v5-tn-row svg:last-of-type{opacity:.5;flex-shrink:0;}
|
|
|
|
/* Badge (e.g., pending count) */
|
|
.v5-tn-badge{
|
|
display:inline-flex;align-items:center;justify-content:center;
|
|
min-width:16px;height:14px;padding:0 .3rem;
|
|
background:rgba(var(--v5-primary-rgb),.14);
|
|
color:var(--v5-primary);
|
|
font-size:.56rem;font-weight:var(--v5-fw-bold);
|
|
border-radius:var(--v5-radius-pill);
|
|
line-height:1;
|
|
}
|
|
|
|
/* Sub-flyout (2단) */
|
|
.v5-tn-sub{
|
|
position:absolute;left:calc(100% + 6px);top:0;min-width:200px;
|
|
background:var(--v5-surface-solid);
|
|
border:1px solid var(--v5-border);
|
|
border-radius:var(--v5-radius-md-2);
|
|
padding:.3rem;z-index:45;
|
|
animation:v5-tn-flyout-in .2s var(--v5-ease-enter) backwards;
|
|
}
|
|
|
|
/* =================================================================
|
|
Tweaks floating panel (디자인시스템 Tweaks UX).
|
|
헤더 우측 SlidersHorizontal 버튼 anchor popover (top:56px right:14px).
|
|
헤더 높이 50px + 6px gap. SettingsModal 이 사용.
|
|
================================================================= */
|
|
.v5-tweaks-panel{
|
|
position:fixed;top:56px;right:14px;
|
|
width:240px;z-index:200;
|
|
background:var(--v5-surface-solid);
|
|
border:1px solid var(--v5-border);
|
|
border-radius:var(--v5-radius-lg-2);
|
|
padding:var(--v5-sp-4);
|
|
font-family:var(--v5-font-sans);
|
|
box-shadow:0 8px 24px rgba(0,0,0,.08);
|
|
opacity:0;transform:translateY(-6px) scale(.97);pointer-events:none;
|
|
transition:
|
|
opacity .2s var(--v5-ease-enter),
|
|
transform .25s var(--v5-ease-enter);
|
|
}
|
|
.v5-tweaks-panel.on{
|
|
opacity:1;transform:translateY(0) scale(1);pointer-events:auto;
|
|
}
|
|
|
|
.v5-tweaks-head{
|
|
display:flex;align-items:center;justify-content:space-between;
|
|
font-size:var(--v5-fs-body);
|
|
font-weight:var(--v5-fw-bold);
|
|
letter-spacing:var(--v5-ls-tight);
|
|
color:var(--v5-text);
|
|
margin-bottom:var(--v5-sp-3);
|
|
}
|
|
|
|
.v5-tweaks-row{
|
|
display:flex;flex-direction:column;gap:.35rem;
|
|
padding:.4rem 0;
|
|
border-top:1px solid var(--v5-border-subtle);
|
|
}
|
|
.v5-tweaks-row:first-of-type{border-top:none;padding-top:0;}
|
|
.v5-tweaks-row label{
|
|
font-size:var(--v5-fs-caption);
|
|
font-weight:var(--v5-fw-bold);
|
|
text-transform:uppercase;
|
|
letter-spacing:var(--v5-ls-wide);
|
|
color:var(--v5-text-muted);
|
|
}
|
|
|
|
.v5-tweaks-swatches{
|
|
display:grid;grid-template-columns:repeat(6,1fr);gap:5px;
|
|
}
|
|
.v5-tweaks-swatch{
|
|
position:relative;width:100%;aspect-ratio:1/1;
|
|
border-radius:var(--v5-radius-sm);
|
|
border:2px solid transparent;
|
|
cursor:pointer;
|
|
display:inline-flex;align-items:center;justify-content:center;
|
|
color:#fff;
|
|
transition:
|
|
transform .15s var(--v5-ease-move),
|
|
border-color .2s var(--v5-ease-move),
|
|
box-shadow .2s var(--v5-ease-move);
|
|
}
|
|
.v5-tweaks-swatch:hover{transform:scale(1.08);}
|
|
.v5-tweaks-swatch.on{
|
|
border-color:var(--v5-text);
|
|
box-shadow:0 0 0 2px var(--v5-surface-solid), 0 0 0 3px currentColor, var(--v5-glow-sm);
|
|
}
|
|
|
|
.v5-tweaks-seg{
|
|
display:flex;gap:4px;
|
|
}
|
|
.v5-tweaks-seg .v5-btn{flex:1;justify-content:center;}
|
|
|
|
.v5-tweaks-foot{
|
|
font-size:.52rem;
|
|
color:var(--v5-text-muted);
|
|
margin-top:.6rem;
|
|
padding-top:.5rem;
|
|
border-top:1px solid var(--v5-border-subtle);
|
|
font-family:var(--v5-font-mono);
|
|
letter-spacing:.03em;
|
|
}
|
|
|
|
/* =================================================================
|
|
Mode line (cyan/primary gradient under the header).
|
|
Already styled in v5-layout.css for shell — this is the standalone
|
|
helper for any sub-shell that wants the same accent.
|
|
================================================================= */
|
|
.v5-mode-line {
|
|
position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
|
|
background: linear-gradient(90deg,
|
|
transparent,
|
|
var(--v5-primary),
|
|
var(--v5-cyan),
|
|
var(--v5-pink),
|
|
transparent);
|
|
opacity: 0; pointer-events: none;
|
|
transition: opacity .35s var(--v5-ease-move);
|
|
}
|
|
.v5-mode-line.on { opacity: 1; }
|