339 lines
6.8 KiB
CSS
339 lines
6.8 KiB
CSS
/**
|
|
* MobileApp Shared Base Styles
|
|
*
|
|
* Common styles for all mobile PWAs including:
|
|
* - Dark mode support
|
|
* - PWA-specific optimizations
|
|
* - Common animations
|
|
* - Utility classes
|
|
*/
|
|
|
|
/* ==================== ROOT & DARK MODE ==================== */
|
|
|
|
:root {
|
|
--color-primary: #005384;
|
|
--color-secondary: #fac41b;
|
|
--color-success: #22c55e;
|
|
--color-danger: #ef4444;
|
|
--color-warning: #f59e0b;
|
|
}
|
|
|
|
/* Dark mode is toggled by adding 'dark' class to <html> */
|
|
.dark {
|
|
color-scheme: dark;
|
|
}
|
|
|
|
|
|
/* ==================== PWA OPTIMIZATIONS ==================== */
|
|
|
|
html, body {
|
|
/* Prevents rubber-band scroll on iOS and pull-to-refresh on Android */
|
|
overscroll-behavior: none;
|
|
/* Prevent text selection on double tap */
|
|
-webkit-user-select: none;
|
|
user-select: none;
|
|
/* Smooth font rendering */
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
/* Prevent zoom on input focus (iOS) */
|
|
touch-action: manipulation;
|
|
}
|
|
|
|
/* Allow text selection in inputs and textareas */
|
|
input, textarea, [contenteditable] {
|
|
-webkit-user-select: text;
|
|
user-select: text;
|
|
}
|
|
|
|
/* Safe area insets for notched devices (iPhone Dynamic Island, etc.) */
|
|
.safe-area-top {
|
|
padding-top: env(safe-area-inset-top, 0px);
|
|
}
|
|
|
|
.safe-area-bottom {
|
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
}
|
|
|
|
/* App header with safe area - extends background into notch area */
|
|
.app-header {
|
|
padding-top: calc(env(safe-area-inset-top, 0px) + 0.5rem);
|
|
padding-bottom: 0.5rem;
|
|
}
|
|
|
|
/* Full safe area container that accounts for both top and bottom */
|
|
.safe-area-container {
|
|
padding-top: env(safe-area-inset-top, 0px);
|
|
padding-bottom: env(safe-area-inset-bottom, 0px);
|
|
padding-left: env(safe-area-inset-left, 0px);
|
|
padding-right: env(safe-area-inset-right, 0px);
|
|
}
|
|
|
|
|
|
/* ==================== ANIMATIONS ==================== */
|
|
|
|
/* Slide transition for panels */
|
|
.slide-enter-active,
|
|
.slide-leave-active {
|
|
transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.slide-enter-from,
|
|
.slide-leave-to {
|
|
transform: translateX(100%);
|
|
}
|
|
|
|
/* Slide up transition for modals */
|
|
.slide-up-enter-active,
|
|
.slide-up-leave-active {
|
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.slide-up-enter-from,
|
|
.slide-up-leave-to {
|
|
transform: translateY(100%);
|
|
}
|
|
|
|
/* Slide down transition for top sheets */
|
|
.slide-down-enter-active,
|
|
.slide-down-leave-active {
|
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
}
|
|
|
|
.slide-down-enter-from,
|
|
.slide-down-leave-to {
|
|
transform: translateY(-100%);
|
|
}
|
|
|
|
/* Fade transition */
|
|
.fade-enter-active,
|
|
.fade-leave-active {
|
|
transition: opacity 0.2s ease-in-out;
|
|
}
|
|
|
|
.fade-enter-from,
|
|
.fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
/* Overlay transition */
|
|
.overlay-enter-active,
|
|
.overlay-leave-active {
|
|
transition: opacity 0.35s ease;
|
|
}
|
|
|
|
.overlay-enter-from,
|
|
.overlay-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
/* Scale in transition */
|
|
.scale-enter-active,
|
|
.scale-leave-active {
|
|
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
}
|
|
|
|
.scale-enter-from,
|
|
.scale-leave-to {
|
|
transform: scale(0.95);
|
|
opacity: 0;
|
|
}
|
|
|
|
/* Spinner animation */
|
|
@keyframes spin {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|
|
|
|
.spin {
|
|
animation: spin 1s linear infinite;
|
|
}
|
|
|
|
/* Pulse animation for loading states */
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
}
|
|
|
|
.pulse {
|
|
animation: pulse 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
/* Network background animations */
|
|
@keyframes node-glow {
|
|
0%, 100% {
|
|
transform: scale(1);
|
|
opacity: 0.8;
|
|
}
|
|
50% {
|
|
transform: scale(1.4);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes node-glow-slow {
|
|
0%, 100% {
|
|
transform: scale(1);
|
|
opacity: 0.7;
|
|
}
|
|
50% {
|
|
transform: scale(1.3);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes line-pulse {
|
|
0%, 100% { opacity: 0.3; }
|
|
50% { opacity: 0.6; }
|
|
}
|
|
|
|
@keyframes line-flow {
|
|
0% { stroke-dashoffset: 1000; }
|
|
100% { stroke-dashoffset: 0; }
|
|
}
|
|
|
|
.network-node {
|
|
animation: node-glow 2s ease-in-out infinite;
|
|
}
|
|
|
|
.network-node-slow {
|
|
animation: node-glow-slow 3s ease-in-out infinite;
|
|
}
|
|
|
|
.network-lines {
|
|
animation: line-pulse 3s ease-in-out infinite;
|
|
}
|
|
|
|
.network-line-flow {
|
|
stroke-dasharray: 20 30;
|
|
animation: line-flow 8s linear infinite;
|
|
}
|
|
|
|
|
|
/* ==================== PANEL EFFECTS ==================== */
|
|
|
|
/* Background blur effect when panel is open */
|
|
.panel-open {
|
|
transform: scale(0.95);
|
|
filter: blur(4px);
|
|
opacity: 0.7;
|
|
transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1),
|
|
filter 0.35s,
|
|
opacity 0.35s;
|
|
}
|
|
|
|
.list-container {
|
|
transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1),
|
|
filter 0.35s,
|
|
opacity 0.35s;
|
|
}
|
|
|
|
|
|
/* ==================== OVERLAY ==================== */
|
|
|
|
.overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background-color: rgba(0, 0, 0, 0.4);
|
|
transition: opacity 0.35s ease;
|
|
z-index: 15;
|
|
}
|
|
|
|
|
|
/* ==================== TOAST NOTIFICATIONS ==================== */
|
|
|
|
.toast-container {
|
|
position: fixed;
|
|
bottom: calc(1rem + env(safe-area-inset-bottom));
|
|
left: 1rem;
|
|
right: 1rem;
|
|
z-index: 100;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.toast {
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 0.5rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
text-align: center;
|
|
pointer-events: auto;
|
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.toast-success {
|
|
background-color: var(--color-success);
|
|
color: white;
|
|
}
|
|
|
|
.toast-error {
|
|
background-color: var(--color-danger);
|
|
color: white;
|
|
}
|
|
|
|
.toast-warning {
|
|
background-color: var(--color-warning);
|
|
color: white;
|
|
}
|
|
|
|
|
|
/* ==================== FORM ELEMENTS ==================== */
|
|
|
|
/* Prevent iOS zoom on input focus */
|
|
input[type="text"],
|
|
input[type="password"],
|
|
input[type="email"],
|
|
input[type="number"],
|
|
input[type="tel"],
|
|
input[type="search"],
|
|
textarea,
|
|
select {
|
|
font-size: 16px !important;
|
|
}
|
|
|
|
/* Remove tap highlight on mobile */
|
|
button, a, input, select, textarea {
|
|
-webkit-tap-highlight-color: transparent;
|
|
}
|
|
|
|
/* Better focus styles for accessibility */
|
|
button:focus-visible,
|
|
input:focus-visible,
|
|
select:focus-visible,
|
|
textarea:focus-visible {
|
|
outline: 2px solid var(--color-primary);
|
|
outline-offset: 2px;
|
|
}
|
|
|
|
|
|
/* ==================== UTILITIES ==================== */
|
|
|
|
/* Hide scrollbar but allow scrolling */
|
|
.hide-scrollbar {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.hide-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
/* Loading overlay */
|
|
.loading-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 50;
|
|
}
|
|
|
|
/* Numeric keypad input */
|
|
.numeric-input {
|
|
font-variant-numeric: tabular-nums;
|
|
letter-spacing: 0.05em;
|
|
}
|