/* ============================================================ POTHOLE REPORTING PORTAL — DESIGN SYSTEM Box.com-inspired Enterprise SaaS UI ============================================================ */ /* ── Google Fonts Import ──────────────────────────────────── */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap'); /* ============================================================ 1. CSS RESET & BASE ============================================================ */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { font-size: 16px; scroll-behavior: smooth; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background-color: var(--color-body-bg); color: var(--color-text-dark); line-height: 1.6; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; min-height: 100vh; } img, video, svg { display: block; max-width: 100%; } a { color: var(--color-blue); text-decoration: none; transition: color var(--transition-fast); } a:hover { color: var(--color-blue-dark); } ul, ol { list-style: none; } button, input, select, textarea { font-family: inherit; font-size: inherit; } button { cursor: pointer; border: none; background: none; } h1, h2, h3, h4, h5, h6 { font-weight: 700; line-height: 1.2; color: var(--color-text-dark); } /* ============================================================ 2. ROOT DESIGN TOKENS ============================================================ */ :root { /* ── Brand Colors ── */ --color-blue: #0061D5; --color-blue-dark: #004FA8; --color-blue-light: #E8F0FB; --color-blue-subtle: #F0F5FF; /* ── Neutral Palette ── */ --color-text-dark: #1A1A2E; --color-body-bg: #F7F9FC; --color-card-bg: #FFFFFF; --color-border: #E4E9F0; --color-muted: #6B7280; --color-muted-light: #9CA3AF; --color-surface: #F3F6FA; /* ── Semantic Colors ── */ --color-success: #26C281; --color-success-bg: #EAFAF2; --color-warning: #F4A300; --color-warning-bg: #FFF8E6; --color-danger: #E53E3E; --color-danger-bg: #FEF2F2; --color-info: #3B82F6; --color-info-bg: #EFF6FF; /* ── Hero / Dark palette ── */ --color-hero-from: #0A1628; --color-hero-to: #1B3A6B; --color-footer-bg: #0D1B2E; /* ── Typography ── */ --font-xs: 0.75rem; /* 12px */ --font-sm: 0.875rem; /* 14px */ --font-base: 1rem; /* 16px */ --font-md: 1.0625rem; /* 17px */ --font-lg: 1.125rem; /* 18px */ --font-xl: 1.25rem; /* 20px */ --font-2xl: 1.5rem; /* 24px */ --font-3xl: 1.875rem; /* 30px */ --font-4xl: 2.25rem; /* 36px */ --font-5xl: 3rem; /* 48px */ /* ── Spacing ── */ --sp-1: 0.25rem; /* 4px */ --sp-2: 0.5rem; /* 8px */ --sp-3: 0.75rem; /* 12px */ --sp-4: 1rem; /* 16px */ --sp-5: 1.25rem; /* 20px */ --sp-6: 1.5rem; /* 24px */ --sp-8: 2rem; /* 32px */ --sp-10: 2.5rem; /* 40px */ --sp-12: 3rem; /* 48px */ --sp-16: 4rem; /* 64px */ --sp-20: 5rem; /* 80px */ /* ── Border Radii ── */ --radius-sm: 4px; --radius-md: 8px; --radius-lg: 12px; --radius-xl: 16px; --radius-2xl: 20px; --radius-pill: 50px; --radius-full: 9999px; /* ── Shadows ── */ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04); --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.04); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.04); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.04); --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.10), 0 10px 10px -5px rgba(0, 0, 0, 0.04); --shadow-blue: 0 0 0 3px rgba(0, 97, 213, 0.18); /* ── Transitions ── */ --transition-fast: 150ms ease; --transition-base: 200ms ease; --transition-slow: 300ms ease; --transition-smooth: 350ms cubic-bezier(0.4, 0, 0.2, 1); /* ── Z-index layers ── */ --z-base: 1; --z-dropdown: 100; --z-sticky: 200; --z-overlay: 300; --z-modal: 400; --z-toast: 500; } /* ============================================================ 3. NAVIGATION HEADER ============================================================ */ .nav-header { position: sticky; top: 0; z-index: var(--z-sticky); background: var(--color-card-bg); border-bottom: 1px solid var(--color-border); box-shadow: var(--shadow-xs); height: 64px; display: flex; align-items: center; } .nav-header__inner { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--sp-6); display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8); } .nav-header__logo { display: flex; align-items: center; gap: var(--sp-3); font-weight: 700; font-size: var(--font-lg); color: var(--color-text-dark); text-decoration: none; flex-shrink: 0; transition: opacity var(--transition-fast); } .nav-header__logo:hover { opacity: 0.85; color: var(--color-text-dark); } .nav-header__logo-icon { width: 36px; height: 36px; background: linear-gradient(135deg, var(--color-blue) 0%, var(--color-blue-dark) 100%); border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; color: #fff; font-size: var(--font-lg); box-shadow: 0 2px 8px rgba(0, 97, 213, 0.30); } .nav-header__links { display: flex; align-items: center; gap: var(--sp-1); } .nav-header__link { padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-md); font-size: var(--font-sm); font-weight: 500; color: var(--color-muted); text-decoration: none; transition: color var(--transition-fast), background var(--transition-fast); white-space: nowrap; } .nav-header__link:hover { color: var(--color-text-dark); background: var(--color-surface); } .nav-header__link.active { color: var(--color-blue); background: var(--color-blue-light); font-weight: 600; } .nav-header__actions { display: flex; align-items: center; gap: var(--sp-3); flex-shrink: 0; } .nav-header__divider { width: 1px; height: 24px; background: var(--color-border); } /* ============================================================ 3b. CITIZEN NAV COMPATIBILITY (#app-nav / .nav-wrap) ============================================================ */ #app-nav { position: fixed; top: 0; left: 0; z-index: 100; background: #ffffff; border-bottom: 1px solid var(--color-border); height: 64px; display: flex; align-items: center; box-shadow: var(--shadow-xs); width: 100%; } .nav-wrap { width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; justify-content: space-between; } .nav-brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: inherit; } .brand-icon { width: 36px; height: 36px; background: linear-gradient(135deg, var(--color-blue) 0%, var(--color-blue-dark) 100%); border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-shadow: 0 2px 8px rgba(0,97,213,0.28); } .brand-city { font-size: 13px; font-weight: 700; color: var(--color-text-dark); } .brand-sys { font-size: 11px; color: var(--color-muted); } .nav-menu { display: flex; align-items: center; gap: 4px; } .nav-item { padding: 8px 14px; border-radius: 8px; font-size: 14px; font-weight: 500; color: var(--color-muted); text-decoration: none; transition: all 0.15s; } .nav-item:hover { background: var(--color-surface); color: var(--color-text-dark); } .nav-item.active { background: var(--color-blue-light); color: var(--color-blue); font-weight: 600; } .nav-item--settings { border: 1px solid var(--color-border); margin-left: 8px; } /* ============================================================ 4. HERO SECTION ============================================================ */ .hero { position: relative; background: linear-gradient(135deg, var(--color-hero-from) 0%, var(--color-hero-to) 100%); color: #ffffff; text-align: center; padding: var(--sp-20) var(--sp-6); overflow: hidden; isolation: isolate; } /* CSS grid overlay pattern */ .hero::before { content: ''; position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px); background-size: 48px 48px; z-index: 0; pointer-events: none; } /* Subtle radial glow */ .hero::after { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse 70% 60% at 50% 40%, rgba(0, 97, 213, 0.22) 0%, transparent 70%); z-index: 0; pointer-events: none; } .hero__content { position: relative; z-index: 1; max-width: 720px; margin: 0 auto; } .hero__eyebrow { display: inline-flex; align-items: center; gap: var(--sp-2); background: rgba(255, 255, 255, 0.10); border: 1px solid rgba(255, 255, 255, 0.15); border-radius: var(--radius-pill); padding: var(--sp-1) var(--sp-4); font-size: var(--font-xs); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(255,255,255,0.80); margin-bottom: var(--sp-6); backdrop-filter: blur(8px); } .hero__title { font-size: var(--font-5xl); font-weight: 800; line-height: 1.1; color: #ffffff; letter-spacing: -0.02em; margin-bottom: var(--sp-5); } .hero__title span { background: linear-gradient(90deg, #60A5FA, #93C5FD); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .hero__subtitle { font-size: var(--font-lg); font-weight: 400; color: rgba(255, 255, 255, 0.70); max-width: 520px; margin: 0 auto var(--sp-10); line-height: 1.7; } .hero__cta { display: flex; align-items: center; justify-content: center; gap: var(--sp-4); flex-wrap: wrap; } .hero__stats { display: flex; align-items: center; justify-content: center; gap: var(--sp-10); margin-top: var(--sp-16); padding-top: var(--sp-8); border-top: 1px solid rgba(255,255,255,0.10); flex-wrap: wrap; } .hero__stat-value { font-size: var(--font-3xl); font-weight: 800; color: #ffffff; display: block; } .hero__stat-label { font-size: var(--font-xs); color: rgba(255,255,255,0.55); font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; margin-top: var(--sp-1); } /* ============================================================ 5. PROGRESS STEPS / STEP INDICATOR ============================================================ */ .step-indicator { display: flex; align-items: center; justify-content: center; gap: 0; padding: var(--sp-6) 0; width: 100%; } .step-indicator__item { display: flex; flex-direction: column; align-items: center; position: relative; flex: 1; max-width: 180px; } /* Connecting line */ .step-indicator__item:not(:last-child)::after { content: ''; position: absolute; top: 18px; left: calc(50% + 20px); right: calc(-50% + 20px); height: 2px; background: var(--color-border); transition: background var(--transition-smooth); z-index: 0; } .step-indicator__item.done:not(:last-child)::after { background: var(--color-blue); } .step-indicator__bubble { width: 36px; height: 36px; border-radius: var(--radius-full); border: 2px solid var(--color-border); background: var(--color-card-bg); display: flex; align-items: center; justify-content: center; font-size: var(--font-sm); font-weight: 600; color: var(--color-muted); position: relative; z-index: 1; transition: background var(--transition-smooth), border-color var(--transition-smooth), color var(--transition-smooth), box-shadow var(--transition-smooth); } .step-indicator__item.active .step-indicator__bubble { background: var(--color-blue); border-color: var(--color-blue); color: #ffffff; box-shadow: 0 0 0 4px rgba(0, 97, 213, 0.18); } .step-indicator__item.done .step-indicator__bubble { background: var(--color-blue); border-color: var(--color-blue); color: #ffffff; } .step-indicator__item.done .step-indicator__bubble::after { content: '✓'; font-size: var(--font-sm); font-weight: 700; } .step-indicator__label { margin-top: var(--sp-2); font-size: var(--font-xs); font-weight: 500; color: var(--color-muted); text-align: center; transition: color var(--transition-fast); white-space: nowrap; } .step-indicator__item.active .step-indicator__label { color: var(--color-blue); font-weight: 600; } .step-indicator__item.done .step-indicator__label { color: var(--color-text-dark); } /* ============================================================ 6. UPLOAD ZONE ============================================================ */ .upload-zone { border: 2px dashed var(--color-border); border-radius: var(--radius-lg); background: var(--color-surface); padding: var(--sp-12) var(--sp-8); text-align: center; cursor: pointer; transition: border-color var(--transition-smooth), background var(--transition-smooth), box-shadow var(--transition-smooth); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-4); position: relative; overflow: hidden; } .upload-zone:hover { border-color: var(--color-blue); background: var(--color-blue-subtle); box-shadow: var(--shadow-blue); } .upload-zone.drag-over { border-color: var(--color-blue); background: var(--color-blue-light); box-shadow: var(--shadow-blue), inset 0 0 0 1px var(--color-blue); transform: scale(1.01); } .upload-zone__icon { width: 56px; height: 56px; border-radius: var(--radius-xl); background: var(--color-blue-light); display: flex; align-items: center; justify-content: center; color: var(--color-blue); font-size: 1.5rem; transition: background var(--transition-smooth), transform var(--transition-smooth); } .upload-zone:hover .upload-zone__icon, .upload-zone.drag-over .upload-zone__icon { background: var(--color-blue); color: #ffffff; transform: translateY(-2px); } .upload-zone__title { font-size: var(--font-md); font-weight: 600; color: var(--color-text-dark); } .upload-zone__sub { font-size: var(--font-sm); color: var(--color-muted); } .upload-zone__link { color: var(--color-blue); font-weight: 600; } .upload-zone__meta { font-size: var(--font-xs); color: var(--color-muted-light); } .upload-zone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; } /* Image previews */ .upload-zone__previews { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-4); justify-content: center; } .upload-zone__preview-thumb { width: 72px; height: 72px; object-fit: cover; border-radius: var(--radius-md); border: 2px solid var(--color-border); transition: border-color var(--transition-fast), transform var(--transition-fast); } .upload-zone__preview-thumb:hover { border-color: var(--color-blue); transform: scale(1.05); } /* ============================================================ 7. MAP CONTAINER ============================================================ */ .map-wrap { border-radius: var(--radius-lg); overflow: hidden; border: 1px solid var(--color-border); box-shadow: var(--shadow-md); background: var(--color-surface); height: 300px; position: relative; } .map-wrap iframe, .map-wrap .map-embed { width: 100%; height: 100%; border: none; display: block; } .map-wrap__overlay { position: absolute; inset: 0; background: rgba(26, 26, 46, 0.04); pointer-events: none; border-radius: var(--radius-lg); } .map-wrap__label { position: absolute; bottom: var(--sp-3); left: var(--sp-3); background: rgba(255, 255, 255, 0.95); border-radius: var(--radius-md); padding: var(--sp-2) var(--sp-3); font-size: var(--font-xs); font-weight: 600; color: var(--color-text-dark); box-shadow: var(--shadow-sm); backdrop-filter: blur(8px); display: flex; align-items: center; gap: var(--sp-2); } .map-wrap__loading { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; background: var(--color-surface); gap: var(--sp-3); color: var(--color-muted); font-size: var(--font-sm); } /* ============================================================ 8. FORM INPUTS ============================================================ */ .field-group { display: flex; flex-direction: column; gap: var(--sp-2); } .field-label { font-size: var(--font-sm); font-weight: 600; color: var(--color-text-dark); display: flex; align-items: center; gap: var(--sp-2); } .field-label .required { color: var(--color-danger); font-weight: 700; } .field-label .optional { font-size: var(--font-xs); font-weight: 400; color: var(--color-muted-light); } .field-input, .field-select, .field-textarea { width: 100%; padding: var(--sp-3) var(--sp-4); border: 1.5px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-card-bg); color: var(--color-text-dark); font-size: var(--font-sm); font-weight: 400; line-height: 1.5; outline: none; transition: border-color var(--transition-base), box-shadow var(--transition-base), background var(--transition-fast); -webkit-appearance: none; appearance: none; } .field-input::placeholder, .field-textarea::placeholder { color: var(--color-muted-light); font-weight: 400; } .field-input:hover, .field-select:hover, .field-textarea:hover { border-color: #C4CFDE; } .field-input:focus, .field-select:focus, .field-textarea:focus { border-color: var(--color-blue); box-shadow: 0 0 0 3px rgba(0, 97, 213, 0.14); background: var(--color-card-bg); } .field-input.error, .field-select.error, .field-textarea.error { border-color: var(--color-danger); box-shadow: 0 0 0 3px rgba(229, 62, 62, 0.12); } .field-input.success, .field-select.success, .field-textarea.success { border-color: var(--color-success); box-shadow: 0 0 0 3px rgba(38, 194, 129, 0.12); } .field-select { 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='%236B7280' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right var(--sp-4) center; padding-right: var(--sp-10); cursor: pointer; } .field-textarea { resize: vertical; min-height: 100px; } .field-hint { font-size: var(--font-xs); color: var(--color-muted); line-height: 1.5; } .field-error { font-size: var(--font-xs); color: var(--color-danger); font-weight: 500; display: flex; align-items: center; gap: var(--sp-1); } /* Input with icon prefix */ .field-input-wrap { position: relative; display: flex; align-items: center; } .field-input-wrap .field-input { padding-left: 2.75rem; } .field-input-wrap .field-icon { position: absolute; left: var(--sp-3); color: var(--color-muted); pointer-events: none; font-size: 1rem; transition: color var(--transition-fast); } .field-input-wrap:focus-within .field-icon { color: var(--color-blue); } /* ============================================================ 9. BUTTONS ============================================================ */ /* Base button */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2); padding: var(--sp-3) var(--sp-6); border-radius: var(--radius-md); font-size: var(--font-sm); font-weight: 600; line-height: 1; white-space: nowrap; cursor: pointer; border: 1.5px solid transparent; text-decoration: none; transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast), color var(--transition-fast), transform var(--transition-fast); position: relative; overflow: hidden; user-select: none; -webkit-user-select: none; vertical-align: middle; } .btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; pointer-events: none; } .btn:active:not(:disabled) { transform: translateY(1px); } /* Ripple shimmer on hover */ .btn::after { content: ''; position: absolute; inset: 0; background: rgba(255,255,255,0); transition: background var(--transition-fast); } .btn:hover::after { background: rgba(255,255,255,0.08); } /* Primary */ .btn-primary { background: var(--color-blue); border-color: var(--color-blue); color: #ffffff; box-shadow: 0 1px 3px rgba(0, 97, 213, 0.30); } .btn-primary:hover { background: var(--color-blue-dark); border-color: var(--color-blue-dark); box-shadow: 0 4px 12px rgba(0, 97, 213, 0.35); color: #ffffff; } .btn-primary:focus-visible { outline: 3px solid rgba(0, 97, 213, 0.40); outline-offset: 2px; } .btn-primary:active:not(:disabled) { background: #003E99; border-color: #003E99; } /* Secondary */ .btn-secondary { background: var(--color-card-bg); border-color: var(--color-border); color: var(--color-text-dark); box-shadow: var(--shadow-xs); } .btn-secondary:hover { background: var(--color-surface); border-color: #C4CFDE; color: var(--color-text-dark); box-shadow: var(--shadow-sm); } .btn-secondary:focus-visible { outline: 3px solid rgba(0, 97, 213, 0.25); outline-offset: 2px; } .btn-secondary:active:not(:disabled) { background: #EDF1F7; } /* Ghost */ .btn-ghost { background: transparent; border-color: transparent; color: var(--color-blue); } .btn-ghost:hover { background: var(--color-blue-light); color: var(--color-blue-dark); } .btn-ghost:focus-visible { outline: 3px solid rgba(0, 97, 213, 0.25); outline-offset: 2px; } .btn-ghost:active:not(:disabled) { background: var(--color-blue-light); } /* Danger variant */ .btn-danger { background: var(--color-danger); border-color: var(--color-danger); color: #ffffff; box-shadow: 0 1px 3px rgba(229, 62, 62, 0.28); } .btn-danger:hover { background: #C53030; border-color: #C53030; color: #ffffff; } /* Success variant */ .btn-success { background: var(--color-success); border-color: var(--color-success); color: #ffffff; } .btn-success:hover { background: #1EAA6E; border-color: #1EAA6E; color: #ffffff; } /* Size modifiers */ .btn-sm { padding: var(--sp-2) var(--sp-4); font-size: var(--font-xs); border-radius: var(--radius-md); } .btn-lg { padding: var(--sp-4) var(--sp-8); font-size: var(--font-md); border-radius: var(--radius-lg); } .btn-xl { padding: var(--sp-5) var(--sp-10); font-size: var(--font-lg); border-radius: var(--radius-lg); } .btn-icon { padding: var(--sp-2); width: 36px; height: 36px; border-radius: var(--radius-md); } /* Loading state */ .btn.loading { pointer-events: none; opacity: 0.8; } .btn.loading::before { content: ''; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.4); border-top-color: #ffffff; border-radius: var(--radius-full); animation: spin 600ms linear infinite; flex-shrink: 0; } .btn-secondary.loading::before { border-color: rgba(0,0,0,0.15); border-top-color: var(--color-text-dark); } /* ============================================================ 10. CARDS ============================================================ */ .card { background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--sp-6); box-shadow: var(--shadow-sm); transition: box-shadow var(--transition-smooth), border-color var(--transition-smooth); } .card:hover { box-shadow: var(--shadow-md); } .card--interactive { cursor: pointer; } .card--interactive:hover { border-color: #C4CFDE; box-shadow: var(--shadow-md); } .card--interactive:active { box-shadow: var(--shadow-sm); transform: translateY(1px); transition: transform var(--transition-fast), box-shadow var(--transition-fast); } .card--highlighted { border-color: var(--color-blue); box-shadow: 0 0 0 1px var(--color-blue), var(--shadow-md); } .card--flat { box-shadow: none; } .card__header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-5); padding-bottom: var(--sp-5); border-bottom: 1px solid var(--color-border); } .card__title { font-size: var(--font-lg); font-weight: 700; color: var(--color-text-dark); } .card__subtitle { font-size: var(--font-sm); color: var(--color-muted); margin-top: var(--sp-1); } .card__body { display: flex; flex-direction: column; gap: var(--sp-4); } .card__footer { margin-top: var(--sp-5); padding-top: var(--sp-5); border-top: 1px solid var(--color-border); display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-3); } /* ============================================================ 11. GPS VERIFICATION BADGE ============================================================ */ .gps-badge { display: inline-flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-pill); font-size: var(--font-xs); font-weight: 600; line-height: 1; white-space: nowrap; border: 1.5px solid transparent; transition: all var(--transition-base); } .gps-badge::before { content: ''; width: 6px; height: 6px; border-radius: var(--radius-full); flex-shrink: 0; } /* Default / pending */ .gps-badge { background: var(--color-surface); border-color: var(--color-border); color: var(--color-muted); } .gps-badge::before { background: var(--color-muted-light); } /* Verified */ .gps-badge.verified { background: var(--color-success-bg); border-color: rgba(38, 194, 129, 0.30); color: #16A366; } .gps-badge.verified::before { background: var(--color-success); } /* Mismatch */ .gps-badge.mismatch { background: var(--color-danger-bg); border-color: rgba(229, 62, 62, 0.25); color: var(--color-danger); } .gps-badge.mismatch::before { background: var(--color-danger); } /* Manual entry */ .gps-badge.manual { background: var(--color-warning-bg); border-color: rgba(244, 163, 0, 0.25); color: #B97700; } .gps-badge.manual::before { background: var(--color-warning); } /* Verifying (animated) */ .gps-badge.verifying { background: var(--color-info-bg); border-color: rgba(59, 130, 246, 0.25); color: var(--color-info); } .gps-badge.verifying::before { background: var(--color-info); animation: pulse 1.2s ease-in-out infinite; } /* ============================================================ 12. SUCCESS SCREEN ============================================================ */ .success-screen { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: var(--sp-16) var(--sp-6); gap: var(--sp-5); animation: fadeInUp 0.5s var(--transition-smooth) both; } .success-screen__check { width: 80px; height: 80px; border-radius: var(--radius-full); background: var(--color-success-bg); border: 3px solid var(--color-success); display: flex; align-items: center; justify-content: center; animation: popIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s both; position: relative; } /* Animated SVG checkmark */ .success-screen__check svg { width: 40px; height: 40px; } .success-screen__check-path { stroke: var(--color-success); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; fill: none; stroke-dasharray: 60; stroke-dashoffset: 60; animation: drawCheck 0.4s ease 0.6s forwards; } /* Expanding ring */ .success-screen__ring { position: absolute; inset: -8px; border-radius: var(--radius-full); border: 2px solid var(--color-success); opacity: 0; animation: ringPulse 0.6s ease 0.5s forwards; } .success-screen__title { font-size: var(--font-2xl); font-weight: 800; color: var(--color-text-dark); } .success-screen__subtitle { font-size: var(--font-base); color: var(--color-muted); max-width: 380px; line-height: 1.6; } .success-screen__ref { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--sp-4) var(--sp-6); display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); } .success-screen__ref-label { font-size: var(--font-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-muted); } .success-screen__ref-value { font-size: var(--font-xl); font-weight: 800; color: var(--color-blue); letter-spacing: 0.04em; } /* ============================================================ 13. SETTINGS PAGE ============================================================ */ .settings-wrap { max-width: 760px; margin: 0 auto; padding: var(--sp-8) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-6); } .settings-header { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-2); } .settings-header-icon { width: 48px; height: 48px; border-radius: var(--radius-xl); background: var(--color-blue-light); display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--color-blue); box-shadow: 0 2px 8px rgba(0,97,213,0.15); } .settings-title { font-size: var(--font-2xl); font-weight: 800; color: var(--color-text-dark); } .settings-sub { font-size: var(--font-sm); color: var(--color-muted); margin-top: 2px; } /* Settings Cards */ .settings-card { margin-bottom: var(--sp-2); } .settings-card-head { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-4); } .settings-card-icon { width: 44px; height: 44px; border-radius: var(--radius-lg); display: flex; align-items: center; justify-content: center; flex-shrink: 0; box-shadow: var(--shadow-sm); } .settings-card-title { font-size: var(--font-md); font-weight: 700; color: var(--color-text-dark); } .settings-card-sub { font-size: var(--font-xs); color: var(--color-muted); margin-top: 1px; } /* Settings Group Container */ .settings-group { background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-sm); display: flex; flex-direction: column; } /* Settings Row - Default Vertical Stack for Inputs */ .settings-row { display: flex; flex-direction: column; align-items: stretch; padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--color-border); gap: var(--sp-2); transition: background var(--transition-fast); } .settings-row:last-child { border-bottom: none; } /* 2-Column Grid Layout for Desktop Settings */ .settings-group > .settings-row-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--color-border); } /* Remove nested row styles when inside row-2 */ .settings-row-2 .settings-row { padding: 0; border-bottom: none; background: transparent; } /* PIN Input grid support */ .settings-row .settings-row-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); padding: 0; border-bottom: none; margin-top: 4px; } /* Test connection button alignment */ #btn-test-connection { align-self: flex-start; margin-top: 4px; } /* Token Input Show/Hide Wrapper */ .token-input-wrap { position: relative; display: flex; align-items: center; width: 100%; } .token-input-wrap .field-input { padding-right: 3rem; } .btn-reveal { position: absolute; right: 4px; height: 34px; width: 38px; display: flex; align-items: center; justify-content: center; color: var(--color-muted); background: transparent; border: none; cursor: pointer; border-radius: var(--radius-md); transition: color var(--transition-fast), background var(--transition-fast); } .btn-reveal:hover { color: var(--color-text-dark); background: var(--color-surface); } .btn-reveal svg { stroke-width: 2.2px; } /* Connection Test Banner Alert */ .connection-banner { padding: var(--sp-4) var(--sp-5); border-radius: var(--radius-lg); font-size: var(--font-sm); font-weight: 500; display: flex; align-items: center; gap: var(--sp-3); animation: fadeInDown 0.3s ease; margin-bottom: var(--sp-4); } .connection-banner.success, .connection-status--success { background: var(--color-success-bg); color: #16A366; border: 1.5px solid rgba(38, 194, 129, 0.30); } .connection-banner.error, .connection-status--error { background: var(--color-danger-bg); color: var(--color-danger); border: 1.5px solid rgba(229, 62, 62, 0.25); } .connection-banner.pending, .connection-status--pending { background: var(--color-blue-subtle); color: var(--color-blue); border: 1.5px solid rgba(0, 97, 213, 0.20); } /* Action Buttons Footer */ .settings-actions { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-6) 0 var(--sp-12); border-top: 1px solid var(--color-border); margin-top: var(--sp-6); flex-wrap: wrap; } .settings-actions-left { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; } .btn-ghost.btn-danger { color: var(--color-danger); } .btn-ghost.btn-danger:hover { background: var(--color-danger-bg); color: #C53030; } /* Toggle Switch Slider Controls */ .toggle-switch { position: relative; width: 44px; height: 24px; flex-shrink: 0; display: inline-block; } .toggle-switch input { opacity: 0; width: 0; height: 0; position: absolute; } .toggle-track { position: absolute; inset: 0; background: var(--color-border); border-radius: var(--radius-pill); cursor: pointer; transition: background var(--transition-smooth); } .toggle-track::after { content: ''; position: absolute; width: 18px; height: 18px; border-radius: var(--radius-full); background: #ffffff; top: 3px; left: 3px; box-shadow: var(--shadow-sm); transition: transform var(--transition-smooth); } .toggle-switch input:checked + .toggle-track { background: var(--color-blue); } .toggle-switch input:checked + .toggle-track::after { transform: translateX(20px); } .toggle-switch input:focus-visible + .toggle-track { outline: 3px solid rgba(0, 97, 213, 0.30); outline-offset: 2px; } .toggle-wrap { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-1); } .toggle-label { font-size: var(--font-sm); color: var(--color-muted); } /* PIN Gate */ .pin-gate { background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-xl); padding: var(--sp-10); max-width: 400px; margin: var(--sp-10) auto; text-align: center; box-shadow: var(--shadow-lg); display: flex; flex-direction: column; align-items: center; gap: var(--sp-5); } .pin-gate__icon { width: 64px; height: 64px; border-radius: var(--radius-full); background: var(--color-blue-light); display: flex; align-items: center; justify-content: center; font-size: 1.75rem; color: var(--color-blue); } .pin-gate__title { font-size: var(--font-xl); font-weight: 700; } .pin-gate__desc { font-size: var(--font-sm); color: var(--color-muted); max-width: 280px; line-height: 1.6; } .pin-gate__inputs { display: flex; gap: var(--sp-3); justify-content: center; } .pin-gate__input { width: 52px; height: 60px; text-align: center; font-size: var(--font-2xl); font-weight: 700; border: 2px solid var(--color-border); border-radius: var(--radius-md); outline: none; transition: border-color var(--transition-base), box-shadow var(--transition-base); -webkit-appearance: none; appearance: none; } .pin-gate__input:focus { border-color: var(--color-blue); box-shadow: var(--shadow-blue); } .pin-gate__input.error { border-color: var(--color-danger); animation: shake 0.3s ease; } /* ============================================================ 14. TRACK PAGE ============================================================ */ .track-wrap { max-width: 720px; margin: 0 auto; padding: var(--sp-8) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-6); } .track-wrap__title { font-size: var(--font-2xl); font-weight: 800; color: var(--color-text-dark); } .track-wrap__header { display: flex; align-items: flex-start; gap: var(--sp-4); flex-wrap: wrap; } .track-wrap__meta { flex: 1; min-width: 0; } /* Timeline */ .timeline { display: flex; flex-direction: column; gap: 0; position: relative; padding-left: 32px; } .timeline::before { content: ''; position: absolute; left: 11px; top: 0; bottom: 0; width: 2px; background: var(--color-border); } .timeline-item { position: relative; padding: 0 0 var(--sp-8) var(--sp-5); transition: opacity var(--transition-base); } .timeline-item:last-child { padding-bottom: 0; } .timeline-item__dot { position: absolute; left: calc(-32px + 6px); top: 3px; width: 14px; height: 14px; border-radius: var(--radius-full); border: 2px solid var(--color-border); background: var(--color-card-bg); z-index: 1; transition: background var(--transition-smooth), border-color var(--transition-smooth), box-shadow var(--transition-smooth); } .timeline-item.active .timeline-item__dot { background: var(--color-blue); border-color: var(--color-blue); box-shadow: 0 0 0 3px rgba(0, 97, 213, 0.18); } .timeline-item.done .timeline-item__dot { background: var(--color-success); border-color: var(--color-success); } .timeline-item.pending .timeline-item__dot { background: var(--color-card-bg); border-color: var(--color-border); } .timeline-item__header { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-2); } .timeline-item__title { font-size: var(--font-sm); font-weight: 700; color: var(--color-text-dark); } .timeline-item.pending .timeline-item__title { color: var(--color-muted); } .timeline-item__date { font-size: var(--font-xs); color: var(--color-muted-light); margin-left: auto; white-space: nowrap; } .timeline-item__body { font-size: var(--font-sm); color: var(--color-muted); line-height: 1.6; } .timeline-item__tag { display: inline-flex; align-items: center; gap: var(--sp-1); background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-pill); padding: 2px var(--sp-3); font-size: var(--font-xs); font-weight: 600; color: var(--color-muted); margin-top: var(--sp-2); } /* ============================================================ 15. TOAST NOTIFICATIONS ============================================================ */ .toast-container { position: fixed; bottom: var(--sp-6); right: var(--sp-6); z-index: var(--z-toast); display: flex; flex-direction: column; gap: var(--sp-3); pointer-events: none; max-width: 380px; width: calc(100% - var(--sp-8)); } .toast { background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: var(--sp-4) var(--sp-5); box-shadow: var(--shadow-xl); display: flex; align-items: flex-start; gap: var(--sp-3); pointer-events: all; opacity: 0; transform: translateX(calc(100% + var(--sp-6))); transition: opacity var(--transition-smooth), transform var(--transition-smooth); overflow: hidden; position: relative; } .toast.show, .toast.toast--visible { opacity: 1; transform: translateX(0); } .toast.hide { opacity: 0; transform: translateX(calc(100% + var(--sp-6))); } /* Progress bar */ .toast::after { content: ''; position: absolute; bottom: 0; left: 0; height: 2px; width: 100%; background: var(--color-blue); transform-origin: left; animation: toastProgress 4s linear forwards; } .toast--success::after { background: var(--color-success); } .toast--warning::after { background: var(--color-warning); } .toast--danger::after { background: var(--color-danger); } .toast__icon { width: 32px; height: 32px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: 0.875rem; flex-shrink: 0; background: var(--color-blue-light); color: var(--color-blue); } .toast--success .toast__icon { background: var(--color-success-bg); color: var(--color-success); } .toast--warning .toast__icon { background: var(--color-warning-bg); color: var(--color-warning); } .toast--danger .toast__icon { background: var(--color-danger-bg); color: var(--color-danger); } .toast__content { flex: 1; min-width: 0; } .toast__title { font-size: var(--font-sm); font-weight: 700; color: var(--color-text-dark); line-height: 1.3; } .toast__message { font-size: var(--font-xs); color: var(--color-muted); margin-top: 3px; line-height: 1.5; } .toast__close { padding: var(--sp-1); border-radius: var(--radius-sm); color: var(--color-muted-light); cursor: pointer; transition: color var(--transition-fast), background var(--transition-fast); flex-shrink: 0; align-self: flex-start; } .toast__close:hover { color: var(--color-text-dark); background: var(--color-surface); } /* ============================================================ 16. MOBILE RESPONSIVE — 480px BREAKPOINT ============================================================ */ @media (max-width: 480px) { :root { --sp-6: 1rem; } .nav-header { height: 56px; } .nav-header__inner { padding: 0 var(--sp-4); } .nav-header__links { display: none; } .nav-header__logo span { display: none; } /* Hero */ .hero { padding: var(--sp-12) var(--sp-4); } .hero__title { font-size: var(--font-3xl); } .hero__subtitle { font-size: var(--font-base); } .hero__cta { flex-direction: column; gap: var(--sp-3); } .hero__cta .btn { width: 100%; } .hero__stats { gap: var(--sp-6); } /* Steps */ .step-indicator__label { display: none; } /* Wizard */ .wizard-wrap { padding: var(--sp-4); border-radius: 0; box-shadow: none; } /* Cards */ .card { padding: var(--sp-4); border-radius: var(--radius-md); } /* Buttons */ .btn-xl { padding: var(--sp-4) var(--sp-6); font-size: var(--font-base); width: 100%; } /* Upload zone */ .upload-zone { padding: var(--sp-8) var(--sp-4); } /* Map */ .map-wrap { height: 220px; } /* Toast */ .toast-container { bottom: var(--sp-4); right: var(--sp-3); left: var(--sp-3); max-width: none; width: auto; } /* Settings */ .settings-wrap { padding: var(--sp-4); } .settings-row { flex-direction: column; align-items: flex-start; gap: var(--sp-3); } .settings-row .toggle { align-self: flex-start; } /* Track */ .track-wrap { padding: var(--sp-4); } /* PIN gate */ .pin-gate { padding: var(--sp-6); } .pin-gate__input { width: 44px; height: 52px; font-size: var(--font-xl); } /* Timeline */ .timeline-item__date { display: none; } /* Footer */ .portal-footer__links { flex-direction: column; gap: var(--sp-4); } .portal-footer__bottom { flex-direction: column; text-align: center; gap: var(--sp-3); } } /* ============================================================ 17. WIZARD CONTAINER ============================================================ */ .wizard-wrap { max-width: 680px; margin: 0 auto; padding: var(--sp-8) var(--sp-6); background: var(--color-card-bg); border: 1px solid var(--color-border); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); } /* Step panels */ .step-panel { display: none; flex-direction: column; gap: var(--sp-6); animation: fadeInUp 0.3s var(--transition-smooth) both; } .step-panel.active { display: flex; } .step-panel__title { font-size: var(--font-2xl); font-weight: 800; color: var(--color-text-dark); letter-spacing: -0.01em; } .step-panel__subtitle { font-size: var(--font-sm); color: var(--color-muted); margin-top: var(--sp-1); line-height: 1.6; } .step-panel__actions { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--color-border); flex-wrap: wrap; } .step-panel__actions-right { display: flex; align-items: center; gap: var(--sp-3); margin-left: auto; } /* ============================================================ 18. AI BADGE ============================================================ */ .ai-badge { display: inline-flex; align-items: center; gap: var(--sp-2); background: linear-gradient(135deg, #EEF2FF 0%, #E0E7FF 100%); border: 1.5px solid rgba(99, 102, 241, 0.25); border-radius: var(--radius-pill); padding: var(--sp-2) var(--sp-4); font-size: var(--font-xs); font-weight: 700; color: #4338CA; white-space: nowrap; transition: all var(--transition-smooth); } .ai-badge__icon { font-size: 0.875rem; animation: sparkle 2s ease-in-out infinite; } .ai-badge__label { text-transform: uppercase; letter-spacing: 0.05em; } .ai-badge__value { font-weight: 800; font-size: var(--font-sm); } .ai-badge__confidence { font-weight: 400; color: #6366F1; font-size: var(--font-xs); } /* Size variants */ .ai-badge--low { background: linear-gradient(135deg, var(--color-warning-bg), #FFF3D0); border-color: rgba(244, 163, 0, 0.30); color: #92550A; } .ai-badge--low .ai-badge__confidence { color: var(--color-warning); } .ai-badge--medium { background: linear-gradient(135deg, var(--color-info-bg), #DBEAFE); border-color: rgba(59, 130, 246, 0.25); color: #1D4ED8; } .ai-badge--medium .ai-badge__confidence { color: var(--color-info); } .ai-badge--high { background: linear-gradient(135deg, var(--color-danger-bg), #FEE2E2); border-color: rgba(229, 62, 62, 0.25); color: #9B1C1C; } .ai-badge--high .ai-badge__confidence { color: var(--color-danger); } .ai-badge--critical { background: linear-gradient(135deg, #FDF2F8, #FCE7F3); border-color: rgba(219, 39, 119, 0.25); color: #831843; } /* ============================================================ 19. PORTAL FOOTER ============================================================ */ .portal-footer { background: var(--color-footer-bg); color: rgba(255,255,255,0.75); padding: var(--sp-16) var(--sp-6) var(--sp-8); margin-top: auto; } .portal-footer__inner { max-width: 1200px; margin: 0 auto; display: grid; grid-template-columns: 280px 1fr 1fr 1fr; gap: var(--sp-10); } /* City seal / branding area */ .portal-footer__brand { display: flex; flex-direction: column; gap: var(--sp-4); } .portal-footer__seal { width: 64px; height: 64px; border-radius: var(--radius-full); background: rgba(255,255,255,0.08); border: 2px solid rgba(255,255,255,0.12); display: flex; align-items: center; justify-content: center; font-size: 1.75rem; color: rgba(255,255,255,0.60); transition: background var(--transition-smooth), border-color var(--transition-smooth); } .portal-footer__seal:hover { background: rgba(255,255,255,0.12); border-color: rgba(255,255,255,0.20); } .portal-footer__brand-name { font-size: var(--font-base); font-weight: 700; color: #ffffff; } .portal-footer__brand-desc { font-size: var(--font-xs); color: rgba(255,255,255,0.45); line-height: 1.7; } .portal-footer__col-title { font-size: var(--font-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: rgba(255,255,255,0.40); margin-bottom: var(--sp-4); } .portal-footer__links { display: flex; flex-direction: column; gap: var(--sp-3); } .portal-footer__link { font-size: var(--font-sm); color: rgba(255,255,255,0.60); text-decoration: none; transition: color var(--transition-fast); line-height: 1.4; } .portal-footer__link:hover { color: #ffffff; } .portal-footer__bottom { max-width: 1200px; margin: var(--sp-10) auto 0; padding-top: var(--sp-6); border-top: 1px solid rgba(255,255,255,0.08); display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; } .portal-footer__copyright { font-size: var(--font-xs); color: rgba(255,255,255,0.35); } .portal-footer__bottom-links { display: flex; align-items: center; gap: var(--sp-5); } .portal-footer__bottom-link { font-size: var(--font-xs); color: rgba(255,255,255,0.40); text-decoration: none; transition: color var(--transition-fast); } .portal-footer__bottom-link:hover { color: rgba(255,255,255,0.75); } /* Responsive footer */ @media (max-width: 900px) { .portal-footer__inner { grid-template-columns: 1fr 1fr; gap: var(--sp-8); } } @media (max-width: 480px) { .portal-footer { padding: var(--sp-10) var(--sp-4) var(--sp-6); } .portal-footer__inner { grid-template-columns: 1fr; gap: var(--sp-6); } } /* ============================================================ 20. LOADING SPINNER ============================================================ */ .spinner { display: inline-block; width: 24px; height: 24px; border: 2.5px solid var(--color-border); border-top-color: var(--color-blue); border-radius: var(--radius-full); animation: spin 650ms linear infinite; flex-shrink: 0; } .spinner--sm { width: 16px; height: 16px; border-width: 2px; } .spinner--lg { width: 40px; height: 40px; border-width: 3.5px; } .spinner--white { border-color: rgba(255,255,255,0.3); border-top-color: #ffffff; } .spinner--success { border-color: rgba(38, 194, 129, 0.2); border-top-color: var(--color-success); } /* Full-page overlay loader */ .spinner-overlay { position: fixed; inset: 0; z-index: var(--z-overlay); background: rgba(255,255,255,0.80); backdrop-filter: blur(4px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--sp-4); opacity: 0; animation: fadeIn 0.2s ease 0.1s forwards; } .spinner-overlay__label { font-size: var(--font-sm); font-weight: 500; color: var(--color-muted); } /* Dots loader variant */ .spinner-dots { display: inline-flex; align-items: center; gap: var(--sp-2); } .spinner-dots__dot { width: 6px; height: 6px; border-radius: var(--radius-full); background: var(--color-blue); animation: dotBounce 1.2s ease-in-out infinite; } .spinner-dots__dot:nth-child(2) { animation-delay: 0.15s; } .spinner-dots__dot:nth-child(3) { animation-delay: 0.30s; } /* ============================================================ UTILITY CLASSES ============================================================ */ /* Layout */ .flex { display: flex; } .flex-col { flex-direction: column; } .items-center { align-items: center; } .items-start { align-items: flex-start; } .justify-between { justify-content: space-between; } .justify-center { justify-content: center; } .gap-2 { gap: var(--sp-2); } .gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); } .gap-6 { gap: var(--sp-6); } .flex-1 { flex: 1; } .flex-wrap { flex-wrap: wrap; } .grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4); } .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); } /* Spacing */ .mt-2 { margin-top: var(--sp-2); } .mt-4 { margin-top: var(--sp-4); } .mt-6 { margin-top: var(--sp-6); } .mt-8 { margin-top: var(--sp-8); } .mb-2 { margin-bottom: var(--sp-2); } .mb-4 { margin-bottom: var(--sp-4); } .mb-6 { margin-bottom: var(--sp-6); } .p-4 { padding: var(--sp-4); } .p-6 { padding: var(--sp-6); } /* Typography */ .text-xs { font-size: var(--font-xs); } .text-sm { font-size: var(--font-sm); } .text-base { font-size: var(--font-base); } .text-lg { font-size: var(--font-lg); } .text-xl { font-size: var(--font-xl); } .text-2xl { font-size: var(--font-2xl); } .font-medium { font-weight: 500; } .font-semibold { font-weight: 600; } .font-bold { font-weight: 700; } .text-muted { color: var(--color-muted); } .text-dark { color: var(--color-text-dark); } .text-blue { color: var(--color-blue); } .text-success { color: var(--color-success); } .text-warning { color: var(--color-warning); } .text-danger { color: var(--color-danger); } .text-center { text-align: center; } .text-right { text-align: right; } .leading-relaxed { line-height: 1.7; } .truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Visibility */ .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; } .hidden { display: none !important; } /* Misc */ .divider { height: 1px; background: var(--color-border); width: 100%; } .section { padding: var(--sp-16) var(--sp-6); } .container { max-width: 1200px; margin: 0 auto; width: 100%; } .badge { display: inline-flex; align-items: center; padding: 2px var(--sp-3); border-radius: var(--radius-pill); font-size: var(--font-xs); font-weight: 600; white-space: nowrap; } .badge--blue { background: var(--color-blue-light); color: var(--color-blue); } .badge--success { background: var(--color-success-bg); color: #16A366; } .badge--warning { background: var(--color-warning-bg); color: #B97700; } .badge--danger { background: var(--color-danger-bg); color: var(--color-danger); } .badge--neutral { background: var(--color-surface); color: var(--color-muted); } /* ============================================================ CSS KEYFRAME ANIMATIONS ============================================================ */ @keyframes spin { to { transform: rotate(360deg); } } @keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(0.85); } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeInUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } @keyframes fadeInDown { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; transform: translateY(0); } } @keyframes popIn { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: scale(1); } } @keyframes ringPulse { from { opacity: 0.8; transform: scale(0.85); } to { opacity: 0; transform: scale(1.4); } } @keyframes drawCheck { to { stroke-dashoffset: 0; } } @keyframes shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-6px); } 40% { transform: translateX(6px); } 60% { transform: translateX(-4px); } 80% { transform: translateX(4px); } } @keyframes toastProgress { from { transform: scaleX(1); } to { transform: scaleX(0); } } @keyframes dotBounce { 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; } 40% { transform: scale(1.2); opacity: 1; } } @keyframes sparkle { 0%, 100% { transform: scale(1) rotate(0deg); } 25% { transform: scale(1.15) rotate(10deg); } 75% { transform: scale(0.9) rotate(-8deg); } } @keyframes slideInRight { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: translateX(0); } } @keyframes slideInLeft { from { opacity: 0; transform: translateX(-24px); } to { opacity: 1; transform: translateX(0); } } /* ============================================================ AI TWO-STAGE RESULT CARD ============================================================ */ /* Wrapper shown beneath the uploaded photo */ .photo-meta { margin-top: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); } .photo-meta-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; } .photo-file-info { font-size: var(--font-sm); color: var(--color-muted); font-weight: 500; } /* EXIF / No-EXIF badges */ .exif-badge { display: inline-flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-md); font-size: var(--font-xs); font-weight: 600; animation: fadeInUp 0.3s ease; } .exif-badge.verified { background: var(--color-success-bg); color: #166534; border: 1px solid rgba(38,194,129,0.3); } .exif-badge.manual { background: var(--color-warning-bg); color: #92400E; border: 1px solid rgba(244,163,0,0.3); } /* AI loading row */ .ai-loading { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); background: var(--color-blue-subtle); border: 1px solid var(--color-blue-light); border-radius: var(--radius-md); font-size: var(--font-sm); color: var(--color-blue); font-weight: 500; } /* Main AI badge card */ .ai-badge { border-radius: var(--radius-lg); border: 1.5px solid var(--color-border); background: var(--color-card-bg); padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); animation: fadeInUp 0.35s ease; box-shadow: var(--shadow-sm); } /* Rejection state — red border */ .ai-badge--reject { border-color: rgba(229, 62, 62, 0.35); background: #FEF9F9; } /* Success result — subtle colored border */ .ai-badge--result { border-color: rgba(0, 97, 213, 0.2); } .ai-badge--small { border-color: rgba(38, 194, 129, 0.3); } .ai-badge--medium { border-color: rgba(244, 163, 0, 0.3); } .ai-badge--large { border-color: rgba(229, 62, 62, 0.3); } /* Error state */ .ai-badge--error { flex-direction: row; align-items: center; border-color: rgba(229, 62, 62, 0.3); background: var(--color-danger-bg); padding: var(--sp-3) var(--sp-4); } /* Stage row — icon + text side by side */ .ai-stage-row { display: flex; align-items: flex-start; gap: var(--sp-3); } .ai-stage-icon { width: 36px; height: 36px; border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .ai-stage-icon--pass { background: var(--color-success-bg); color: var(--color-success); } .ai-stage-icon--fail { background: var(--color-danger-bg); color: var(--color-danger); } .ai-stage-body { display: flex; flex-direction: column; gap: 2px; flex: 1; } .ai-stage-label { font-size: var(--font-xs); font-weight: 600; color: var(--color-muted); text-transform: uppercase; letter-spacing: 0.06em; } .ai-stage-result { font-size: var(--font-sm); font-weight: 700; color: var(--color-text-dark); } .ai-stage-result--pass { color: var(--color-success); } .ai-stage-result--fail { color: var(--color-danger); } .ai-stage-sub { font-size: var(--font-xs); color: var(--color-muted); line-height: 1.5; margin-top: 2px; } /* Divider between the two stages */ .ai-divider { height: 1px; background: var(--color-border); margin: var(--sp-1) 0; } /* Size pill (Small / Medium / Large) */ .ai-size-pill { width: 64px; height: 36px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: var(--font-xs); font-weight: 700; flex-shrink: 0; letter-spacing: 0.04em; } /* Confidence score bars */ .ai-scores { display: flex; flex-direction: column; gap: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--color-border); margin-top: var(--sp-1); } .ai-score-row { display: flex; align-items: center; gap: var(--sp-3); } .ai-score-row--winner .ai-score-label { font-weight: 600; color: var(--color-text-dark); } .ai-score-label { font-size: var(--font-xs); font-weight: 500; color: var(--color-muted); width: 52px; flex-shrink: 0; } .ai-score-bar-wrap { flex: 1; height: 6px; background: var(--color-border); border-radius: var(--radius-full); overflow: hidden; } .ai-score-bar { height: 100%; border-radius: var(--radius-full); transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1); } .ai-score-pct { font-size: var(--font-xs); color: var(--color-muted); width: 38px; text-align: right; flex-shrink: 0; } /* Rejection notice at the bottom */ .ai-reject-note { font-size: var(--font-xs); color: var(--color-danger); font-weight: 500; padding: var(--sp-2) var(--sp-3); background: var(--color-danger-bg); border-radius: var(--radius-md); border: 1px solid rgba(229,62,62,0.15); } /* Badge dot (used in error state) */ .ai-badge-dot { width: 8px; height: 8px; border-radius: var(--radius-full); flex-shrink: 0; } .ai-badge-label { font-size: var(--font-xs); font-weight: 600; color: var(--color-muted); } .ai-badge-result { font-size: var(--font-xs); color: var(--color-danger); } /* ── End of Design System ──────────────────────────────────── */