Files
boc/aamos-admin-upgrade/web/assets/admin.css
T
Bernt 6de2455917 v1.2.0: Add Global Markets footer, translated to 9 languages
- 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
2026-07-08 19:56:03 +00:00

2178 lines
52 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ============================================================
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; /* 0100, 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;
}
}