6de2455917
- Added GLOBAL_MARKETS_TITLE to all translation files - Updated footer with 12 markets (4 active + 8 upcoming) - Translated market section to: zh-cn, zh-tw, ja, ko, th, vi, id, ms, hi - Built and deployed to production - CloudFront invalidation: I3RTMXVFDJXWLG3SYX208OP1CC
2178 lines
52 KiB
CSS
2178 lines
52 KiB
CSS
/* ============================================================
|
||
AAMOS Admin — Apple iOS 18 Design System
|
||
============================================================ */
|
||
|
||
/* ── Design Tokens ────────────────────────────────────────── */
|
||
:root {
|
||
/* Backgrounds */
|
||
--bg-primary: #F2F2F7;
|
||
--bg-secondary: #FFFFFF;
|
||
--bg-tertiary: #E5E5EA;
|
||
--bg-grouped: #F2F2F7;
|
||
--bg-card: #FFFFFF;
|
||
--bg-elevated: #FFFFFF;
|
||
--bg-overlay: rgba(0, 0, 0, 0.40);
|
||
|
||
/* Labels / Text */
|
||
--label-primary: #000000;
|
||
--label-secondary: #3C3C43CC; /* 80% */
|
||
--label-tertiary: #3C3C4399; /* 60% */
|
||
--label-quaternary: #3C3C4366; /* 40% */
|
||
--label-inverted: #FFFFFF;
|
||
|
||
/* System Colors */
|
||
--color-blue: #007AFF;
|
||
--color-green: #34C759;
|
||
--color-orange: #FF9500;
|
||
--color-red: #FF3B30;
|
||
--color-yellow: #FFCC00;
|
||
--color-purple: #AF52DE;
|
||
--color-teal: #5AC8FA;
|
||
--color-indigo: #5856D6;
|
||
--color-pink: #FF2D55;
|
||
|
||
/* Semantic aliases */
|
||
--color-primary: var(--color-blue);
|
||
--color-success: var(--color-green);
|
||
--color-warning: var(--color-orange);
|
||
--color-danger: var(--color-red);
|
||
|
||
/* Fill layers (iOS system fills) */
|
||
--fill-primary: rgba(120, 120, 128, 0.20);
|
||
--fill-secondary: rgba(120, 120, 128, 0.16);
|
||
--fill-tertiary: rgba(118, 118, 128, 0.12);
|
||
--fill-quaternary: rgba(116, 116, 128, 0.08);
|
||
|
||
/* Separators */
|
||
--separator: rgba(60, 60, 67, 0.29);
|
||
--separator-opaque: #C6C6C8;
|
||
|
||
/* Shadows */
|
||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04);
|
||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08), 0 2px 6px rgba(0, 0, 0, 0.06);
|
||
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
|
||
--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||
|
||
/* Radius */
|
||
--radius-xs: 4px;
|
||
--radius-sm: 8px;
|
||
--radius-md: 12px;
|
||
--radius-lg: 16px;
|
||
--radius-xl: 20px;
|
||
--radius-2xl: 24px;
|
||
--radius-full: 9999px;
|
||
|
||
/* Spacing (8pt grid) */
|
||
--space-1: 4px;
|
||
--space-2: 8px;
|
||
--space-3: 12px;
|
||
--space-4: 16px;
|
||
--space-5: 20px;
|
||
--space-6: 24px;
|
||
--space-8: 32px;
|
||
--space-10: 40px;
|
||
--space-12: 48px;
|
||
|
||
/* Typography */
|
||
--font-family: -apple-system, "SF Pro Display", "SF Pro Text",
|
||
BlinkMacSystemFont, "Helvetica Neue", Helvetica, sans-serif;
|
||
--font-mono: "SF Mono", ui-monospace, "Cascadia Code", "Fira Code",
|
||
Menlo, Consolas, monospace;
|
||
|
||
--text-xs: 11px;
|
||
--text-sm: 13px;
|
||
--text-base: 15px;
|
||
--text-md: 17px;
|
||
--text-lg: 20px;
|
||
--text-xl: 22px;
|
||
--text-2xl: 28px;
|
||
--text-3xl: 34px;
|
||
|
||
--weight-regular: 400;
|
||
--weight-medium: 500;
|
||
--weight-semibold: 600;
|
||
--weight-bold: 700;
|
||
|
||
/* Layout */
|
||
--sidebar-width: 240px;
|
||
--header-height: 52px;
|
||
--tab-bar-height: 83px; /* includes safe area */
|
||
--content-max: 1200px;
|
||
|
||
/* Transitions */
|
||
--ease: cubic-bezier(0.4, 0, 0.2, 1);
|
||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
--duration-fast: 150ms;
|
||
--duration-base: 300ms;
|
||
--duration-slow: 500ms;
|
||
--transition: var(--duration-base) var(--ease);
|
||
}
|
||
|
||
/* ── Dark Mode Tokens ────────────────────────────────────── */
|
||
@media (prefers-color-scheme: dark) {
|
||
:root {
|
||
--bg-primary: #000000;
|
||
--bg-secondary: #1C1C1E;
|
||
--bg-tertiary: #2C2C2E;
|
||
--bg-grouped: #000000;
|
||
--bg-card: #1C1C1E;
|
||
--bg-elevated: #2C2C2E;
|
||
--bg-overlay: rgba(0, 0, 0, 0.65);
|
||
|
||
--label-primary: #FFFFFF;
|
||
--label-secondary: rgba(235, 235, 245, 0.60);
|
||
--label-tertiary: rgba(235, 235, 245, 0.30);
|
||
--label-quaternary: rgba(235, 235, 245, 0.18);
|
||
--label-inverted: #000000;
|
||
|
||
--color-blue: #0A84FF;
|
||
--color-green: #30D158;
|
||
--color-orange: #FF9F0A;
|
||
--color-red: #FF453A;
|
||
--color-yellow: #FFD60A;
|
||
--color-purple: #BF5AF2;
|
||
--color-teal: #64D2FF;
|
||
--color-indigo: #5E5CE6;
|
||
--color-pink: #FF375F;
|
||
|
||
--fill-primary: rgba(120, 120, 128, 0.36);
|
||
--fill-secondary: rgba(120, 120, 128, 0.32);
|
||
--fill-tertiary: rgba(118, 118, 128, 0.24);
|
||
--fill-quaternary: rgba(116, 116, 128, 0.18);
|
||
|
||
--separator: rgba(84, 84, 88, 0.65);
|
||
--separator-opaque: #38383A;
|
||
|
||
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.40);
|
||
--shadow-md: 0 4px 16px rgba(0, 0, 0, 0.50);
|
||
--shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.60);
|
||
--shadow-card: 0 2px 8px rgba(0, 0, 0, 0.40);
|
||
}
|
||
}
|
||
|
||
/* ── Reset ───────────────────────────────────────────────── */
|
||
*, *::before, *::after {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
html {
|
||
font-size: 16px;
|
||
-webkit-text-size-adjust: 100%;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
scroll-behavior: smooth;
|
||
}
|
||
|
||
body {
|
||
font-family: var(--font-family);
|
||
font-size: var(--text-base);
|
||
font-weight: var(--weight-regular);
|
||
line-height: 1.5;
|
||
color: var(--label-primary);
|
||
background: var(--bg-primary);
|
||
min-height: 100dvh;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
a {
|
||
color: var(--color-primary);
|
||
text-decoration: none;
|
||
transition: opacity var(--duration-fast) var(--ease);
|
||
}
|
||
a:hover { opacity: 0.75; }
|
||
|
||
button, input, select, textarea {
|
||
font-family: inherit;
|
||
font-size: inherit;
|
||
}
|
||
|
||
ul, ol { list-style: none; }
|
||
|
||
img, svg { display: block; }
|
||
|
||
hr {
|
||
border: none;
|
||
border-top: 0.5px solid var(--separator);
|
||
}
|
||
|
||
/* ── App Shell ───────────────────────────────────────────── */
|
||
.app-shell {
|
||
display: flex;
|
||
min-height: 100dvh;
|
||
}
|
||
|
||
/* ── Sidebar ─────────────────────────────────────────────── */
|
||
.sidebar {
|
||
width: var(--sidebar-width);
|
||
min-height: 100dvh;
|
||
background: var(--bg-secondary);
|
||
border-right: 0.5px solid var(--separator);
|
||
display: flex;
|
||
flex-direction: column;
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
bottom: 0;
|
||
z-index: 200;
|
||
transition: transform var(--transition);
|
||
overflow-y: auto;
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
.sidebar-header {
|
||
padding: var(--space-6) var(--space-4) var(--space-4);
|
||
border-bottom: 0.5px solid var(--separator);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sidebar-logo {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
}
|
||
|
||
.sidebar-logo-icon {
|
||
width: 36px;
|
||
height: 36px;
|
||
border-radius: var(--radius-sm);
|
||
background: var(--color-primary);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.sidebar-logo-text {
|
||
font-size: var(--text-md);
|
||
font-weight: var(--weight-semibold);
|
||
letter-spacing: -0.4px;
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.sidebar-logo-sub {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
letter-spacing: 0.2px;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.sidebar-section {
|
||
padding: var(--space-3) 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.sidebar-section-title {
|
||
padding: var(--space-2) var(--space-4) var(--space-1);
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-tertiary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.6px;
|
||
}
|
||
|
||
.sidebar-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-2) var(--space-4);
|
||
margin: 1px var(--space-2);
|
||
border-radius: var(--radius-sm);
|
||
color: var(--label-primary);
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-medium);
|
||
cursor: pointer;
|
||
transition: background var(--duration-fast) var(--ease),
|
||
color var(--duration-fast) var(--ease);
|
||
text-decoration: none;
|
||
user-select: none;
|
||
position: relative;
|
||
}
|
||
|
||
.sidebar-item:hover {
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
.sidebar-item.active {
|
||
background: rgba(0, 122, 255, 0.12);
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.sidebar-item.active {
|
||
background: rgba(10, 132, 255, 0.20);
|
||
color: var(--color-primary);
|
||
}
|
||
}
|
||
|
||
.sidebar-item-icon {
|
||
width: 22px;
|
||
height: 22px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
opacity: 0.6;
|
||
transition: opacity var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.sidebar-item.active .sidebar-item-icon,
|
||
.sidebar-item:hover .sidebar-item-icon {
|
||
opacity: 1;
|
||
}
|
||
|
||
.sidebar-item-badge {
|
||
margin-left: auto;
|
||
}
|
||
|
||
.sidebar-footer {
|
||
padding: var(--space-4);
|
||
border-top: 0.5px solid var(--separator);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* Sidebar collapse toggle (desktop) */
|
||
.sidebar-toggle {
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--bg-tertiary);
|
||
border: 0.5px solid var(--separator);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
position: absolute;
|
||
right: -12px;
|
||
top: 62px;
|
||
z-index: 10;
|
||
transition: background var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.sidebar-toggle:hover {
|
||
background: var(--fill-primary);
|
||
}
|
||
|
||
/* ── Main Content ─────────────────────────────────────────── */
|
||
.main-content {
|
||
flex: 1;
|
||
margin-left: var(--sidebar-width);
|
||
min-height: 100dvh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: var(--bg-primary);
|
||
transition: margin-left var(--transition);
|
||
}
|
||
|
||
.page-header {
|
||
height: var(--header-height);
|
||
background: rgba(var(--bg-secondary), 0.85);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
border-bottom: 0.5px solid var(--separator);
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 0 var(--space-6);
|
||
gap: var(--space-4);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
.page-header-bg {
|
||
background: rgba(242, 242, 247, 0.85);
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.page-header-bg {
|
||
background: rgba(28, 28, 30, 0.85);
|
||
}
|
||
}
|
||
|
||
.page-title {
|
||
font-size: var(--text-xl);
|
||
font-weight: var(--weight-bold);
|
||
letter-spacing: -0.5px;
|
||
color: var(--label-primary);
|
||
flex: 1;
|
||
}
|
||
|
||
.page-subtitle {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.page-body {
|
||
flex: 1;
|
||
padding: var(--space-6);
|
||
max-width: var(--content-max);
|
||
width: 100%;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
/* ── KPI Card ─────────────────────────────────────────────── */
|
||
.kpi-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||
gap: var(--space-4);
|
||
}
|
||
|
||
.kpi-card {
|
||
background: var(--bg-card);
|
||
border-radius: var(--radius-md);
|
||
padding: var(--space-5);
|
||
box-shadow: var(--shadow-card);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-2);
|
||
cursor: default;
|
||
transition: transform var(--duration-fast) var(--ease),
|
||
box-shadow var(--duration-fast) var(--ease);
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.kpi-card:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: var(--shadow-md);
|
||
}
|
||
|
||
.kpi-card::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 3px;
|
||
background: var(--kpi-accent, var(--color-primary));
|
||
border-radius: var(--radius-md) var(--radius-md) 0 0;
|
||
}
|
||
|
||
.kpi-card--success { --kpi-accent: var(--color-success); }
|
||
.kpi-card--warning { --kpi-accent: var(--color-warning); }
|
||
.kpi-card--danger { --kpi-accent: var(--color-danger); }
|
||
.kpi-card--primary { --kpi-accent: var(--color-primary); }
|
||
.kpi-card--purple { --kpi-accent: var(--color-purple); }
|
||
|
||
.kpi-label {
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.kpi-value {
|
||
font-size: var(--text-2xl);
|
||
font-weight: var(--weight-bold);
|
||
letter-spacing: -1px;
|
||
color: var(--label-primary);
|
||
line-height: 1.1;
|
||
}
|
||
|
||
.kpi-delta {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
padding: 2px 6px;
|
||
border-radius: var(--radius-full);
|
||
}
|
||
|
||
.kpi-delta--up {
|
||
color: var(--color-success);
|
||
background: rgba(52, 199, 89, 0.12);
|
||
}
|
||
|
||
.kpi-delta--down {
|
||
color: var(--color-danger);
|
||
background: rgba(255, 59, 48, 0.12);
|
||
}
|
||
|
||
.kpi-delta--neutral {
|
||
color: var(--label-secondary);
|
||
background: var(--fill-tertiary);
|
||
}
|
||
|
||
.kpi-meta {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
margin-top: auto;
|
||
}
|
||
|
||
/* ── Health Ring ──────────────────────────────────────────── */
|
||
.health-ring {
|
||
--ring-size: 80px;
|
||
--ring-stroke: 7px;
|
||
--ring-value: 75; /* 0–100, set via inline style or JS */
|
||
--ring-color: var(--color-success);
|
||
--ring-bg: var(--fill-tertiary);
|
||
|
||
position: relative;
|
||
width: var(--ring-size);
|
||
height: var(--ring-size);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.health-ring--sm { --ring-size: 56px; --ring-stroke: 5px; }
|
||
.health-ring--lg { --ring-size: 112px; --ring-stroke: 9px; }
|
||
|
||
.health-ring svg {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
transform: rotate(-90deg);
|
||
}
|
||
|
||
.health-ring__track {
|
||
fill: none;
|
||
stroke: var(--ring-bg);
|
||
stroke-width: var(--ring-stroke);
|
||
}
|
||
|
||
.health-ring__fill {
|
||
fill: none;
|
||
stroke: var(--ring-color);
|
||
stroke-width: var(--ring-stroke);
|
||
stroke-linecap: round;
|
||
/* circumference ~= 2π × (r=38) ≈ 238.76 */
|
||
stroke-dasharray: 238.76;
|
||
stroke-dashoffset: calc(238.76 * (1 - var(--ring-value) / 100));
|
||
transition: stroke-dashoffset var(--duration-slow) var(--ease),
|
||
stroke var(--duration-base) var(--ease);
|
||
}
|
||
|
||
.health-ring--warning { --ring-color: var(--color-warning); }
|
||
.health-ring--danger { --ring-color: var(--color-danger); }
|
||
.health-ring--blue { --ring-color: var(--color-primary); }
|
||
|
||
.health-ring__label {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
line-height: 1.1;
|
||
z-index: 1;
|
||
}
|
||
|
||
.health-ring__value {
|
||
font-size: var(--text-md);
|
||
font-weight: var(--weight-bold);
|
||
color: var(--label-primary);
|
||
letter-spacing: -0.5px;
|
||
}
|
||
|
||
.health-ring__unit {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
}
|
||
|
||
/* ── iOS Toggle ───────────────────────────────────────────── */
|
||
.ios-toggle {
|
||
position: relative;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
gap: var(--space-3);
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
|
||
.ios-toggle__input {
|
||
position: absolute;
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.ios-toggle__track {
|
||
position: relative;
|
||
width: 51px;
|
||
height: 31px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--fill-secondary);
|
||
transition: background var(--duration-base) var(--ease);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.ios-toggle__input:checked + .ios-toggle__track {
|
||
background: var(--color-success);
|
||
}
|
||
|
||
.ios-toggle__input:focus-visible + .ios-toggle__track {
|
||
outline: 3px solid var(--color-primary);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
.ios-toggle__thumb {
|
||
position: absolute;
|
||
top: 2px;
|
||
left: 2px;
|
||
width: 27px;
|
||
height: 27px;
|
||
border-radius: var(--radius-full);
|
||
background: #FFFFFF;
|
||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.10);
|
||
transition: transform var(--duration-base) var(--ease-spring);
|
||
}
|
||
|
||
.ios-toggle__input:checked ~ .ios-toggle__track .ios-toggle__thumb,
|
||
.ios-toggle__input:checked + .ios-toggle__track .ios-toggle__thumb {
|
||
transform: translateX(20px);
|
||
}
|
||
|
||
/* Thumb is a child of track, so use sibling trick via parent */
|
||
.ios-toggle__track .ios-toggle__thumb {
|
||
transition: transform var(--duration-base) var(--ease-spring);
|
||
}
|
||
|
||
.ios-toggle--primary .ios-toggle__input:checked + .ios-toggle__track {
|
||
background: var(--color-primary);
|
||
}
|
||
|
||
.ios-toggle__label {
|
||
font-size: var(--text-base);
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.ios-toggle__label-sub {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
margin-top: 1px;
|
||
}
|
||
|
||
/* ── iOS Table ────────────────────────────────────────────── */
|
||
.table-ios {
|
||
width: 100%;
|
||
background: var(--bg-card);
|
||
border-radius: var(--radius-md);
|
||
overflow: hidden;
|
||
box-shadow: var(--shadow-card);
|
||
}
|
||
|
||
.table-ios thead {
|
||
background: var(--bg-tertiary);
|
||
}
|
||
|
||
.table-ios th {
|
||
padding: var(--space-3) var(--space-4);
|
||
text-align: left;
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
white-space: nowrap;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
}
|
||
|
||
.table-ios td {
|
||
padding: var(--space-3) var(--space-4);
|
||
font-size: var(--text-sm);
|
||
color: var(--label-primary);
|
||
border-bottom: 0.5px solid var(--separator);
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.table-ios tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.table-ios tbody tr {
|
||
transition: background var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.table-ios tbody tr:hover {
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
.table-ios--striped tbody tr:nth-child(even) {
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
.table-ios--striped tbody tr:nth-child(even):hover {
|
||
background: var(--fill-tertiary);
|
||
}
|
||
|
||
.table-ios th:first-child,
|
||
.table-ios td:first-child { padding-left: var(--space-5); }
|
||
.table-ios th:last-child,
|
||
.table-ios td:last-child { padding-right: var(--space-5); }
|
||
|
||
.table-ios .cell-mono {
|
||
font-family: var(--font-mono);
|
||
font-size: var(--text-xs);
|
||
color: var(--label-secondary);
|
||
}
|
||
|
||
.table-ios .cell-action {
|
||
text-align: right;
|
||
width: 1px;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* ── Modal Overlay ────────────────────────────────────────── */
|
||
.modal-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: var(--bg-overlay);
|
||
-webkit-backdrop-filter: blur(8px) saturate(180%);
|
||
backdrop-filter: blur(8px) saturate(180%);
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: var(--space-4);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity var(--duration-base) var(--ease);
|
||
}
|
||
|
||
.modal-overlay.open {
|
||
opacity: 1;
|
||
pointer-events: all;
|
||
}
|
||
|
||
.modal {
|
||
background: var(--bg-card);
|
||
border-radius: var(--radius-xl);
|
||
box-shadow: var(--shadow-lg);
|
||
width: 100%;
|
||
max-width: 540px;
|
||
max-height: 90dvh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
transform: scale(0.94) translateY(12px);
|
||
transition: transform var(--duration-base) var(--ease-spring);
|
||
}
|
||
|
||
.modal-overlay.open .modal {
|
||
transform: scale(1) translateY(0);
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--space-5) var(--space-5) var(--space-4);
|
||
border-bottom: 0.5px solid var(--separator);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: var(--text-lg);
|
||
font-weight: var(--weight-semibold);
|
||
letter-spacing: -0.3px;
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.modal-close {
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--fill-secondary);
|
||
border: none;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--label-secondary);
|
||
flex-shrink: 0;
|
||
transition: background var(--duration-fast) var(--ease),
|
||
color var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.modal-close:hover {
|
||
background: var(--fill-primary);
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.modal-body {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
padding: var(--space-5);
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: var(--space-3);
|
||
padding: var(--space-4) var(--space-5);
|
||
border-top: 0.5px solid var(--separator);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* Bottom sheet variant */
|
||
.modal-overlay--sheet {
|
||
align-items: flex-end;
|
||
padding: 0;
|
||
}
|
||
|
||
.modal-overlay--sheet .modal {
|
||
max-width: 100%;
|
||
border-radius: var(--radius-2xl) var(--radius-2xl) 0 0;
|
||
transform: translateY(100%);
|
||
max-height: 85dvh;
|
||
}
|
||
|
||
.modal-overlay--sheet.open .modal {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.modal-sheet-handle {
|
||
width: 36px;
|
||
height: 5px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--fill-primary);
|
||
margin: var(--space-2) auto var(--space-1);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* ── Toast / Snackbar ─────────────────────────────────────── */
|
||
.toast-container {
|
||
position: fixed;
|
||
top: var(--space-4);
|
||
right: var(--space-4);
|
||
z-index: 2000;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-2);
|
||
pointer-events: none;
|
||
max-width: 360px;
|
||
width: calc(100% - 2 * var(--space-4));
|
||
}
|
||
|
||
.toast {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: var(--space-3);
|
||
padding: var(--space-3) var(--space-4);
|
||
background: var(--bg-elevated);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-lg);
|
||
border: 0.5px solid var(--separator);
|
||
pointer-events: all;
|
||
cursor: pointer;
|
||
|
||
opacity: 0;
|
||
transform: translateX(calc(100% + var(--space-4)));
|
||
transition: opacity var(--duration-base) var(--ease),
|
||
transform var(--duration-base) var(--ease-spring);
|
||
}
|
||
|
||
.toast.show {
|
||
opacity: 1;
|
||
transform: translateX(0);
|
||
}
|
||
|
||
.toast.hide {
|
||
opacity: 0;
|
||
transform: translateX(calc(100% + var(--space-4)));
|
||
}
|
||
|
||
.toast__icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.toast--success .toast__icon { background: rgba(52, 199, 89, 0.15); color: var(--color-success); }
|
||
.toast--warning .toast__icon { background: rgba(255, 149, 0, 0.15); color: var(--color-warning); }
|
||
.toast--danger .toast__icon { background: rgba(255, 59, 48, 0.15); color: var(--color-danger); }
|
||
.toast--info .toast__icon { background: rgba(0, 122, 255, 0.15); color: var(--color-primary); }
|
||
|
||
.toast__body { flex: 1; min-width: 0; }
|
||
|
||
.toast__title {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.toast__message {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-secondary);
|
||
margin-top: 2px;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.toast__dismiss {
|
||
width: 20px;
|
||
height: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
color: var(--label-tertiary);
|
||
border: none;
|
||
background: none;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
border-radius: var(--radius-full);
|
||
transition: color var(--duration-fast) var(--ease),
|
||
background var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.toast__dismiss:hover {
|
||
color: var(--label-primary);
|
||
background: var(--fill-secondary);
|
||
}
|
||
|
||
/* ── Badge ────────────────────────────────────────────────── */
|
||
.badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 2px 7px;
|
||
border-radius: var(--radius-full);
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
line-height: 1.4;
|
||
white-space: nowrap;
|
||
letter-spacing: 0.1px;
|
||
}
|
||
|
||
.badge--primary {
|
||
background: rgba(0, 122, 255, 0.12);
|
||
color: var(--color-primary);
|
||
}
|
||
.badge--success {
|
||
background: rgba(52, 199, 89, 0.12);
|
||
color: var(--color-success);
|
||
}
|
||
.badge--warning {
|
||
background: rgba(255, 149, 0, 0.12);
|
||
color: var(--color-warning);
|
||
}
|
||
.badge--danger {
|
||
background: rgba(255, 59, 48, 0.12);
|
||
color: var(--color-danger);
|
||
}
|
||
.badge--purple {
|
||
background: rgba(175, 82, 222, 0.12);
|
||
color: var(--color-purple);
|
||
}
|
||
.badge--gray {
|
||
background: var(--fill-secondary);
|
||
color: var(--label-secondary);
|
||
}
|
||
.badge--filled-primary { background: var(--color-primary); color: #fff; }
|
||
.badge--filled-success { background: var(--color-success); color: #fff; }
|
||
.badge--filled-warning { background: var(--color-warning); color: #fff; }
|
||
.badge--filled-danger { background: var(--color-danger); color: #fff; }
|
||
|
||
/* Dot badge (notification count) */
|
||
.badge-dot {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 18px;
|
||
height: 18px;
|
||
padding: 0 5px;
|
||
border-radius: var(--radius-full);
|
||
font-size: 11px;
|
||
font-weight: var(--weight-bold);
|
||
line-height: 1;
|
||
background: var(--color-danger);
|
||
color: #fff;
|
||
}
|
||
|
||
/* ── Avatar ───────────────────────────────────────────────── */
|
||
.avatar {
|
||
--av-size: 40px;
|
||
--av-radius: var(--radius-full);
|
||
|
||
width: var(--av-size);
|
||
height: var(--av-size);
|
||
border-radius: var(--av-radius);
|
||
background: var(--fill-secondary);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
flex-shrink: 0;
|
||
font-size: calc(var(--av-size) * 0.4);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
letter-spacing: -0.2px;
|
||
}
|
||
|
||
.avatar--xs { --av-size: 24px; }
|
||
.avatar--sm { --av-size: 32px; }
|
||
.avatar--md { --av-size: 40px; }
|
||
.avatar--lg { --av-size: 48px; }
|
||
.avatar--xl { --av-size: 64px; }
|
||
.avatar--2xl { --av-size: 80px; }
|
||
|
||
.avatar--rounded { --av-radius: var(--radius-sm); }
|
||
.avatar--square { --av-radius: 0; }
|
||
|
||
.avatar img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.avatar--blue { background: rgba(0, 122, 255, 0.15); color: var(--color-primary); }
|
||
.avatar--green { background: rgba(52, 199, 89, 0.15); color: var(--color-success); }
|
||
.avatar--orange { background: rgba(255, 149, 0, 0.15); color: var(--color-warning); }
|
||
.avatar--red { background: rgba(255, 59, 48, 0.15); color: var(--color-danger); }
|
||
.avatar--purple { background: rgba(175, 82, 222, 0.15); color: var(--color-purple); }
|
||
|
||
.avatar-group {
|
||
display: flex;
|
||
flex-direction: row-reverse;
|
||
}
|
||
|
||
.avatar-group .avatar {
|
||
border: 2px solid var(--bg-secondary);
|
||
margin-left: -8px;
|
||
}
|
||
|
||
.avatar-group .avatar:last-child {
|
||
margin-left: 0;
|
||
}
|
||
|
||
/* ── Buttons ──────────────────────────────────────────────── */
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: var(--space-2);
|
||
padding: 0 var(--space-5);
|
||
height: 44px;
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--text-base);
|
||
font-weight: var(--weight-semibold);
|
||
letter-spacing: -0.2px;
|
||
border: none;
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
user-select: none;
|
||
white-space: nowrap;
|
||
-webkit-tap-highlight-color: transparent;
|
||
transition: opacity var(--duration-fast) var(--ease),
|
||
transform var(--duration-fast) var(--ease),
|
||
background var(--duration-fast) var(--ease),
|
||
box-shadow var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.btn:active {
|
||
transform: scale(0.97);
|
||
opacity: 0.85;
|
||
}
|
||
|
||
.btn:disabled {
|
||
opacity: 0.38;
|
||
cursor: not-allowed;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.btn--sm {
|
||
height: 36px;
|
||
padding: 0 var(--space-4);
|
||
font-size: var(--text-sm);
|
||
border-radius: var(--radius-sm);
|
||
}
|
||
|
||
.btn--lg {
|
||
height: 50px;
|
||
padding: 0 var(--space-6);
|
||
font-size: var(--text-md);
|
||
border-radius: var(--radius-lg);
|
||
}
|
||
|
||
.btn--full { width: 100%; }
|
||
|
||
.btn--icon {
|
||
width: 44px;
|
||
padding: 0;
|
||
border-radius: var(--radius-md);
|
||
}
|
||
|
||
.btn--icon.btn--sm { width: 36px; }
|
||
.btn--icon.btn--lg { width: 50px; }
|
||
|
||
.btn-primary {
|
||
background: var(--color-primary);
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: color-mix(in srgb, var(--color-primary) 88%, #000);
|
||
box-shadow: 0 4px 12px rgba(0, 122, 255, 0.35);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: var(--fill-secondary);
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: var(--fill-primary);
|
||
}
|
||
|
||
.btn-danger {
|
||
background: var(--color-danger);
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.btn-danger:hover {
|
||
background: color-mix(in srgb, var(--color-danger) 88%, #000);
|
||
box-shadow: 0 4px 12px rgba(255, 59, 48, 0.35);
|
||
}
|
||
|
||
.btn-success {
|
||
background: var(--color-success);
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.btn-success:hover {
|
||
background: color-mix(in srgb, var(--color-success) 88%, #000);
|
||
}
|
||
|
||
.btn-ghost {
|
||
background: transparent;
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.btn-ghost:hover {
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
.btn-outline {
|
||
background: transparent;
|
||
color: var(--color-primary);
|
||
border: 1.5px solid var(--color-primary);
|
||
}
|
||
|
||
.btn-outline:hover {
|
||
background: rgba(0, 122, 255, 0.06);
|
||
}
|
||
|
||
.btn-outline-danger {
|
||
background: transparent;
|
||
color: var(--color-danger);
|
||
border: 1.5px solid var(--color-danger);
|
||
}
|
||
|
||
.btn-outline-danger:hover {
|
||
background: rgba(255, 59, 48, 0.06);
|
||
}
|
||
|
||
/* Loading state */
|
||
.btn.loading {
|
||
pointer-events: none;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.btn.loading::after {
|
||
content: "";
|
||
width: 16px;
|
||
height: 16px;
|
||
border: 2px solid currentColor;
|
||
border-top-color: transparent;
|
||
border-radius: var(--radius-full);
|
||
animation: btn-spin 0.6s linear infinite;
|
||
}
|
||
|
||
@keyframes btn-spin {
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
|
||
/* ── Section Group (iOS grouped style) ───────────────────── */
|
||
.section-group {
|
||
background: var(--bg-card);
|
||
border-radius: var(--radius-md);
|
||
overflow: hidden;
|
||
box-shadow: var(--shadow-card);
|
||
margin-bottom: var(--space-4);
|
||
}
|
||
|
||
.section-group-header {
|
||
padding: var(--space-3) var(--space-4) var(--space-2);
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.section-group-footer {
|
||
padding: var(--space-2) var(--space-4) var(--space-3);
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.section-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-3) var(--space-4);
|
||
min-height: 44px;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
transition: background var(--duration-fast) var(--ease);
|
||
text-decoration: none;
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.section-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.section-row--tappable {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.section-row--tappable:hover {
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
.section-row--tappable:active {
|
||
background: var(--fill-secondary);
|
||
}
|
||
|
||
.section-row__icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: var(--radius-xs);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
font-size: 15px;
|
||
}
|
||
|
||
.section-row__icon--blue { background: var(--color-primary); color: #fff; }
|
||
.section-row__icon--green { background: var(--color-success); color: #fff; }
|
||
.section-row__icon--orange { background: var(--color-warning); color: #fff; }
|
||
.section-row__icon--red { background: var(--color-danger); color: #fff; }
|
||
.section-row__icon--purple { background: var(--color-purple); color: #fff; }
|
||
|
||
.section-row__body {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.section-row__label {
|
||
font-size: var(--text-base);
|
||
color: var(--label-primary);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.section-row__detail {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
margin-top: 1px;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.section-row__value {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.section-row__chevron {
|
||
color: var(--label-quaternary);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* ── Wizard Step ──────────────────────────────────────────── */
|
||
.wizard {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0;
|
||
}
|
||
|
||
.wizard-steps {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: var(--space-4) var(--space-5);
|
||
gap: 0;
|
||
counter-reset: wizard-counter;
|
||
}
|
||
|
||
.wizard-step {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
min-width: 0;
|
||
counter-increment: wizard-counter;
|
||
}
|
||
|
||
.wizard-step:last-child {
|
||
flex: 0;
|
||
}
|
||
|
||
.wizard-step__indicator {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: var(--radius-full);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-bold);
|
||
flex-shrink: 0;
|
||
transition: background var(--duration-base) var(--ease),
|
||
color var(--duration-base) var(--ease),
|
||
box-shadow var(--duration-base) var(--ease);
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
|
||
.wizard-step__indicator::before {
|
||
content: counter(wizard-counter);
|
||
}
|
||
|
||
/* pending */
|
||
.wizard-step .wizard-step__indicator {
|
||
background: var(--fill-secondary);
|
||
color: var(--label-tertiary);
|
||
}
|
||
|
||
/* active */
|
||
.wizard-step--active .wizard-step__indicator {
|
||
background: var(--color-primary);
|
||
color: #fff;
|
||
box-shadow: 0 0 0 4px rgba(0, 122, 255, 0.20);
|
||
}
|
||
|
||
/* completed */
|
||
.wizard-step--done .wizard-step__indicator {
|
||
background: var(--color-success);
|
||
color: #fff;
|
||
}
|
||
|
||
.wizard-step--done .wizard-step__indicator::before {
|
||
content: "✓";
|
||
}
|
||
|
||
/* error */
|
||
.wizard-step--error .wizard-step__indicator {
|
||
background: var(--color-danger);
|
||
color: #fff;
|
||
}
|
||
|
||
.wizard-step--error .wizard-step__indicator::before {
|
||
content: "!";
|
||
}
|
||
|
||
.wizard-step__connector {
|
||
flex: 1;
|
||
height: 2px;
|
||
background: var(--fill-secondary);
|
||
margin: 0 var(--space-2);
|
||
border-radius: 1px;
|
||
transition: background var(--duration-base) var(--ease);
|
||
}
|
||
|
||
.wizard-step--done + .wizard-step .wizard-step__connector,
|
||
.wizard-step--done .wizard-step__connector {
|
||
background: var(--color-success);
|
||
}
|
||
|
||
.wizard-step__label {
|
||
display: none;
|
||
}
|
||
|
||
/* Show labels on wider screens */
|
||
@media (min-width: 640px) {
|
||
.wizard-step {
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: var(--space-2);
|
||
}
|
||
|
||
.wizard-step__connector {
|
||
display: none;
|
||
}
|
||
|
||
.wizard-steps {
|
||
gap: var(--space-2);
|
||
}
|
||
|
||
.wizard-step__label {
|
||
display: block;
|
||
font-size: var(--text-xs);
|
||
font-weight: var(--weight-medium);
|
||
color: var(--label-tertiary);
|
||
text-align: center;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.wizard-step--active .wizard-step__label {
|
||
color: var(--color-primary);
|
||
font-weight: var(--weight-semibold);
|
||
}
|
||
|
||
.wizard-step--done .wizard-step__label {
|
||
color: var(--color-success);
|
||
}
|
||
|
||
.wizard-step::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 14px;
|
||
left: calc(50% + 18px);
|
||
right: calc(-50% + 18px);
|
||
height: 2px;
|
||
background: var(--fill-secondary);
|
||
}
|
||
}
|
||
|
||
.wizard-panel {
|
||
display: none;
|
||
}
|
||
|
||
.wizard-panel--active {
|
||
display: block;
|
||
animation: wizard-in var(--duration-base) var(--ease);
|
||
}
|
||
|
||
@keyframes wizard-in {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateX(12px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateX(0);
|
||
}
|
||
}
|
||
|
||
.wizard-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--space-4) var(--space-5);
|
||
border-top: 0.5px solid var(--separator);
|
||
}
|
||
|
||
/* ── Timeline ─────────────────────────────────────────────── */
|
||
.timeline {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0;
|
||
padding: var(--space-2) 0;
|
||
}
|
||
|
||
.timeline-item {
|
||
display: flex;
|
||
gap: var(--space-4);
|
||
position: relative;
|
||
padding-bottom: var(--space-5);
|
||
}
|
||
|
||
.timeline-item:last-child {
|
||
padding-bottom: 0;
|
||
}
|
||
|
||
.timeline-item__left {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
width: 32px;
|
||
}
|
||
|
||
.timeline-item__dot {
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: var(--radius-full);
|
||
background: var(--fill-primary);
|
||
border: 2px solid var(--bg-primary);
|
||
flex-shrink: 0;
|
||
z-index: 1;
|
||
transition: background var(--duration-fast) var(--ease);
|
||
}
|
||
|
||
.timeline-item--success .timeline-item__dot { background: var(--color-success); }
|
||
.timeline-item--warning .timeline-item__dot { background: var(--color-warning); }
|
||
.timeline-item--danger .timeline-item__dot { background: var(--color-danger); }
|
||
.timeline-item--info .timeline-item__dot { background: var(--color-primary); }
|
||
|
||
.timeline-item__line {
|
||
flex: 1;
|
||
width: 1.5px;
|
||
background: var(--separator);
|
||
margin-top: 4px;
|
||
min-height: var(--space-5);
|
||
}
|
||
|
||
.timeline-item:last-child .timeline-item__line {
|
||
display: none;
|
||
}
|
||
|
||
.timeline-item__body {
|
||
flex: 1;
|
||
padding-top: 0;
|
||
min-width: 0;
|
||
}
|
||
|
||
.timeline-item__header {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: var(--space-3);
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.timeline-item__title {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.timeline-item__time {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
white-space: nowrap;
|
||
margin-left: auto;
|
||
}
|
||
|
||
.timeline-item__content {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
margin-top: var(--space-1);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
.timeline-item__meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-2);
|
||
margin-top: var(--space-2);
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
/* ── Form Elements ────────────────────────────────────────── */
|
||
.form-group {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--space-2);
|
||
margin-bottom: var(--space-5);
|
||
}
|
||
|
||
.form-label {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-medium);
|
||
color: var(--label-secondary);
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
height: 44px;
|
||
padding: 0 var(--space-4);
|
||
background: var(--bg-tertiary);
|
||
border: 1.5px solid transparent;
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--text-base);
|
||
color: var(--label-primary);
|
||
outline: none;
|
||
transition: border-color var(--duration-fast) var(--ease),
|
||
background var(--duration-fast) var(--ease);
|
||
-webkit-appearance: none;
|
||
}
|
||
|
||
.form-input::placeholder {
|
||
color: var(--label-quaternary);
|
||
}
|
||
|
||
.form-input:focus {
|
||
background: var(--bg-secondary);
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
.form-input--error {
|
||
border-color: var(--color-danger);
|
||
}
|
||
|
||
.form-hint {
|
||
font-size: var(--text-xs);
|
||
color: var(--label-tertiary);
|
||
line-height: 1.4;
|
||
}
|
||
|
||
.form-error {
|
||
font-size: var(--text-xs);
|
||
color: var(--color-danger);
|
||
font-weight: var(--weight-medium);
|
||
}
|
||
|
||
.form-select {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23888' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
|
||
background-repeat: no-repeat;
|
||
background-position: right var(--space-4) center;
|
||
padding-right: var(--space-8);
|
||
}
|
||
|
||
textarea.form-input {
|
||
height: auto;
|
||
padding: var(--space-3) var(--space-4);
|
||
resize: vertical;
|
||
min-height: 100px;
|
||
}
|
||
|
||
/* ── Search Bar ───────────────────────────────────────────── */
|
||
.search-bar {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.search-bar__icon {
|
||
position: absolute;
|
||
left: var(--space-3);
|
||
color: var(--label-tertiary);
|
||
pointer-events: none;
|
||
z-index: 1;
|
||
}
|
||
|
||
.search-bar__input {
|
||
width: 100%;
|
||
height: 36px;
|
||
padding: 0 var(--space-4) 0 var(--space-8);
|
||
background: var(--fill-secondary);
|
||
border: none;
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--text-sm);
|
||
color: var(--label-primary);
|
||
outline: none;
|
||
transition: background var(--duration-fast) var(--ease);
|
||
-webkit-appearance: none;
|
||
}
|
||
|
||
.search-bar__input::placeholder {
|
||
color: var(--label-tertiary);
|
||
}
|
||
|
||
.search-bar__input:focus {
|
||
background: var(--fill-primary);
|
||
}
|
||
|
||
/* ── Progress Bar ─────────────────────────────────────────── */
|
||
.progress-bar {
|
||
height: 6px;
|
||
background: var(--fill-secondary);
|
||
border-radius: var(--radius-full);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.progress-bar__fill {
|
||
height: 100%;
|
||
border-radius: var(--radius-full);
|
||
background: var(--color-primary);
|
||
transition: width var(--duration-slow) var(--ease);
|
||
}
|
||
|
||
.progress-bar--success .progress-bar__fill { background: var(--color-success); }
|
||
.progress-bar--warning .progress-bar__fill { background: var(--color-warning); }
|
||
.progress-bar--danger .progress-bar__fill { background: var(--color-danger); }
|
||
|
||
/* ── Skeleton Loading ─────────────────────────────────────── */
|
||
.skeleton {
|
||
background: var(--fill-secondary);
|
||
border-radius: var(--radius-sm);
|
||
animation: skeleton-pulse 1.4s ease-in-out infinite;
|
||
}
|
||
|
||
@keyframes skeleton-pulse {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.45; }
|
||
}
|
||
|
||
/* ── Empty State ──────────────────────────────────────────── */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
padding: var(--space-12) var(--space-6);
|
||
gap: var(--space-4);
|
||
}
|
||
|
||
.empty-state__icon {
|
||
width: 56px;
|
||
height: 56px;
|
||
border-radius: var(--radius-lg);
|
||
background: var(--fill-tertiary);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28px;
|
||
color: var(--label-tertiary);
|
||
}
|
||
|
||
.empty-state__title {
|
||
font-size: var(--text-lg);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
.empty-state__body {
|
||
font-size: var(--text-base);
|
||
color: var(--label-secondary);
|
||
max-width: 300px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* ── Stat Row ─────────────────────────────────────────────── */
|
||
.stat-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-4);
|
||
padding: var(--space-3) 0;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
}
|
||
|
||
.stat-row:last-child { border-bottom: none; }
|
||
|
||
.stat-row__label {
|
||
font-size: var(--text-sm);
|
||
color: var(--label-secondary);
|
||
flex: 1;
|
||
}
|
||
|
||
.stat-row__value {
|
||
font-size: var(--text-sm);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
font-family: var(--font-mono);
|
||
}
|
||
|
||
.stat-row__bar {
|
||
width: 80px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
/* ── Code Block ───────────────────────────────────────────── */
|
||
.code-block {
|
||
background: var(--bg-tertiary);
|
||
border-radius: var(--radius-sm);
|
||
padding: var(--space-4);
|
||
overflow-x: auto;
|
||
font-family: var(--font-mono);
|
||
font-size: var(--text-xs);
|
||
line-height: 1.6;
|
||
color: var(--label-primary);
|
||
border: 0.5px solid var(--separator);
|
||
position: relative;
|
||
}
|
||
|
||
.code-block pre {
|
||
margin: 0;
|
||
white-space: pre;
|
||
}
|
||
|
||
code {
|
||
font-family: var(--font-mono);
|
||
font-size: 0.875em;
|
||
background: var(--fill-tertiary);
|
||
padding: 1px 5px;
|
||
border-radius: var(--radius-xs);
|
||
color: var(--label-primary);
|
||
}
|
||
|
||
/* ── Card ─────────────────────────────────────────────────── */
|
||
.card {
|
||
background: var(--bg-card);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-card);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--space-4) var(--space-5);
|
||
border-bottom: 0.5px solid var(--separator);
|
||
}
|
||
|
||
.card-title {
|
||
font-size: var(--text-base);
|
||
font-weight: var(--weight-semibold);
|
||
color: var(--label-primary);
|
||
letter-spacing: -0.2px;
|
||
}
|
||
|
||
.card-body {
|
||
padding: var(--space-5);
|
||
}
|
||
|
||
.card-footer {
|
||
padding: var(--space-3) var(--space-5);
|
||
border-top: 0.5px solid var(--separator);
|
||
background: var(--fill-quaternary);
|
||
}
|
||
|
||
/* ── Context Menu / Dropdown ──────────────────────────────── */
|
||
.dropdown {
|
||
position: relative;
|
||
display: inline-block;
|
||
}
|
||
|
||
.dropdown-menu {
|
||
position: absolute;
|
||
top: calc(100% + 6px);
|
||
right: 0;
|
||
min-width: 200px;
|
||
background: var(--bg-elevated);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-lg);
|
||
border: 0.5px solid var(--separator);
|
||
z-index: 500;
|
||
overflow: hidden;
|
||
|
||
opacity: 0;
|
||
transform: scale(0.94) translateY(-6px);
|
||
pointer-events: none;
|
||
transform-origin: top right;
|
||
transition: opacity var(--duration-fast) var(--ease),
|
||
transform var(--duration-fast) var(--ease-spring);
|
||
}
|
||
|
||
.dropdown-menu.open {
|
||
opacity: 1;
|
||
transform: scale(1) translateY(0);
|
||
pointer-events: all;
|
||
}
|
||
|
||
.dropdown-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--space-3);
|
||
padding: var(--space-3) var(--space-4);
|
||
font-size: var(--text-sm);
|
||
color: var(--label-primary);
|
||
cursor: pointer;
|
||
border-bottom: 0.5px solid var(--separator);
|
||
transition: background var(--duration-fast) var(--ease);
|
||
text-decoration: none;
|
||
}
|
||
|
||
.dropdown-item:last-child { border-bottom: none; }
|
||
|
||
.dropdown-item:hover { background: var(--fill-quaternary); }
|
||
|
||
.dropdown-item--danger { color: var(--color-danger); }
|
||
|
||
.dropdown-separator {
|
||
height: 0.5px;
|
||
background: var(--separator);
|
||
}
|
||
|
||
/* ── Tab Bar (mobile bottom navigation) ─────────────────── */
|
||
.tab-bar {
|
||
display: none;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: var(--tab-bar-height);
|
||
padding-bottom: env(safe-area-inset-bottom, 16px);
|
||
background: rgba(242, 242, 247, 0.92);
|
||
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||
backdrop-filter: blur(20px) saturate(180%);
|
||
border-top: 0.5px solid var(--separator);
|
||
z-index: 200;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.tab-bar {
|
||
background: rgba(28, 28, 30, 0.92);
|
||
}
|
||
}
|
||
|
||
.tab-bar-inner {
|
||
display: flex;
|
||
align-items: center;
|
||
height: calc(var(--tab-bar-height) - env(safe-area-inset-bottom, 16px));
|
||
}
|
||
|
||
.tab-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 3px;
|
||
padding: var(--space-1) 0;
|
||
cursor: pointer;
|
||
color: var(--label-tertiary);
|
||
text-decoration: none;
|
||
transition: color var(--duration-fast) var(--ease);
|
||
-webkit-tap-highlight-color: transparent;
|
||
position: relative;
|
||
}
|
||
|
||
.tab-item.active {
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.tab-item__icon {
|
||
width: 24px;
|
||
height: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: transform var(--duration-fast) var(--ease-spring);
|
||
}
|
||
|
||
.tab-item:active .tab-item__icon {
|
||
transform: scale(0.88);
|
||
}
|
||
|
||
.tab-item__label {
|
||
font-size: 10px;
|
||
font-weight: var(--weight-medium);
|
||
letter-spacing: 0.1px;
|
||
line-height: 1;
|
||
}
|
||
|
||
.tab-item__badge {
|
||
position: absolute;
|
||
top: 4px;
|
||
left: calc(50% + 6px);
|
||
}
|
||
|
||
/* ── Utility Classes ──────────────────────────────────────── */
|
||
.text-primary { color: var(--color-primary) !important; }
|
||
.text-success { color: var(--color-success) !important; }
|
||
.text-warning { color: var(--color-warning) !important; }
|
||
.text-danger { color: var(--color-danger) !important; }
|
||
.text-secondary { color: var(--label-secondary) !important; }
|
||
.text-tertiary { color: var(--label-tertiary) !important; }
|
||
|
||
.text-xs { font-size: var(--text-xs) !important; }
|
||
.text-sm { font-size: var(--text-sm) !important; }
|
||
.text-base { font-size: var(--text-base) !important; }
|
||
.text-md { font-size: var(--text-md) !important; }
|
||
.text-lg { font-size: var(--text-lg) !important; }
|
||
|
||
.font-regular { font-weight: var(--weight-regular) !important; }
|
||
.font-medium { font-weight: var(--weight-medium) !important; }
|
||
.font-semibold { font-weight: var(--weight-semibold) !important; }
|
||
.font-bold { font-weight: var(--weight-bold) !important; }
|
||
.font-mono { font-family: var(--font-mono) !important; }
|
||
|
||
.truncate {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.flex { display: flex; }
|
||
.flex-col { flex-direction: column; }
|
||
.items-center { align-items: center; }
|
||
.justify-between { justify-content: space-between; }
|
||
.gap-1 { gap: var(--space-1); }
|
||
.gap-2 { gap: var(--space-2); }
|
||
.gap-3 { gap: var(--space-3); }
|
||
.gap-4 { gap: var(--space-4); }
|
||
.gap-6 { gap: var(--space-6); }
|
||
|
||
.m-0 { margin: 0; }
|
||
.mt-2 { margin-top: var(--space-2); }
|
||
.mt-4 { margin-top: var(--space-4); }
|
||
.mt-6 { margin-top: var(--space-6); }
|
||
.mb-2 { margin-bottom: var(--space-2); }
|
||
.mb-4 { margin-bottom: var(--space-4); }
|
||
.mb-6 { margin-bottom: var(--space-6); }
|
||
|
||
.p-4 { padding: var(--space-4); }
|
||
.p-5 { padding: var(--space-5); }
|
||
.p-6 { padding: var(--space-6); }
|
||
|
||
.sr-only {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
padding: 0;
|
||
margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0, 0, 0, 0);
|
||
white-space: nowrap;
|
||
border-width: 0;
|
||
}
|
||
|
||
/* ── Scrollbars ───────────────────────────────────────────── */
|
||
::-webkit-scrollbar {
|
||
width: 6px;
|
||
height: 6px;
|
||
}
|
||
|
||
::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb {
|
||
background: var(--fill-secondary);
|
||
border-radius: var(--radius-full);
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb:hover {
|
||
background: var(--fill-primary);
|
||
}
|
||
|
||
/* ── Animations ───────────────────────────────────────────── */
|
||
@keyframes fade-in {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
@keyframes slide-up {
|
||
from { opacity: 0; transform: translateY(16px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
@keyframes slide-down {
|
||
from { opacity: 0; transform: translateY(-16px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
@keyframes scale-in {
|
||
from { opacity: 0; transform: scale(0.92); }
|
||
to { opacity: 1; transform: scale(1); }
|
||
}
|
||
|
||
.animate-fade-in { animation: fade-in var(--duration-base) var(--ease) both; }
|
||
.animate-slide-up { animation: slide-up var(--duration-base) var(--ease) both; }
|
||
.animate-scale-in { animation: scale-in var(--duration-base) var(--ease-spring) both; }
|
||
|
||
/* ── Reduced Motion ───────────────────────────────────────── */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*, *::before, *::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.01ms !important;
|
||
}
|
||
}
|
||
|
||
/* ── Responsive: Tablet (≤ 1024px) ───────────────────────── */
|
||
@media (max-width: 1024px) {
|
||
:root {
|
||
--sidebar-width: 200px;
|
||
}
|
||
}
|
||
|
||
/* ── Responsive: Mobile (≤ 767px) ────────────────────────── */
|
||
@media (max-width: 767px) {
|
||
.sidebar {
|
||
transform: translateX(-100%);
|
||
box-shadow: var(--shadow-lg);
|
||
}
|
||
|
||
.sidebar.open {
|
||
transform: translateX(0);
|
||
}
|
||
|
||
.main-content {
|
||
margin-left: 0;
|
||
padding-bottom: var(--tab-bar-height);
|
||
}
|
||
|
||
.tab-bar {
|
||
display: block;
|
||
}
|
||
|
||
.page-body {
|
||
padding: var(--space-4);
|
||
}
|
||
|
||
.kpi-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: var(--space-3);
|
||
}
|
||
|
||
.modal {
|
||
max-width: 100%;
|
||
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
|
||
margin: auto 0 0;
|
||
}
|
||
|
||
.modal-overlay {
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.modal-overlay .modal {
|
||
transform: translateY(100%);
|
||
}
|
||
|
||
.modal-overlay.open .modal {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
.toast-container {
|
||
top: auto;
|
||
bottom: calc(var(--tab-bar-height) + var(--space-3));
|
||
right: var(--space-3);
|
||
left: var(--space-3);
|
||
max-width: 100%;
|
||
width: auto;
|
||
}
|
||
|
||
.table-ios {
|
||
display: block;
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
|
||
.wizard-step__label { display: none; }
|
||
}
|
||
|
||
/* ── Responsive: Large (≥ 1280px) ────────────────────────── */
|
||
@media (min-width: 1280px) {
|
||
.kpi-grid {
|
||
grid-template-columns: repeat(4, 1fr);
|
||
}
|
||
}
|
||
|
||
/* Sidebar overlay for mobile */
|
||
.sidebar-overlay {
|
||
display: none;
|
||
position: fixed;
|
||
inset: 0;
|
||
background: var(--bg-overlay);
|
||
z-index: 199;
|
||
opacity: 0;
|
||
transition: opacity var(--transition);
|
||
}
|
||
|
||
@media (max-width: 767px) {
|
||
.sidebar-overlay {
|
||
display: block;
|
||
}
|
||
|
||
.sidebar-overlay.open {
|
||
opacity: 1;
|
||
}
|
||
}
|