Files
CurrenciCombo/src/styles/tokens.css

133 lines
5.1 KiB
CSS
Raw Normal View History

/*
Design tokens responsive foundation
Loaded BEFORE index.css so existing rules can consume these
variables. Strictly additive: no variable declared here conflicts
with an existing value in index.css.
Breakpoint policy (mobile-first, min-width):
xs: 0 479px (narrow phones, portrait)
sm: 480 767px (large phones, small tablets portrait)
md: 768 1023px (tablets landscape, small laptops)
lg: 1024 1439px (desktops, larger laptops)
xl: 1440px+ (wide desktops, ultra-wide)
We prefer container/fluid behavior; breakpoints gate only layout
switches that cannot be expressed fluidly (nav drawer, workspace
availability, tablecard transform).
*/
:root {
/* Breakpoints (CSS custom props mirror the JS hook constants) */
--bp-xs: 0px;
--bp-sm: 480px;
--bp-md: 768px;
--bp-lg: 1024px;
--bp-xl: 1440px;
/* Fluid type scale clamp(min, preferred, max)
Preferred uses a viewport-width linear function so text grows
smoothly between xs and xl without hard breakpoint jumps.
All values are in rem so user font-size preferences are honored. */
--fs-2xs: clamp(0.625rem, 0.59rem + 0.17vw, 0.75rem); /* 10→12px */
--fs-xs: clamp(0.6875rem, 0.65rem + 0.19vw, 0.8125rem); /* 11→13px */
--fs-sm: clamp(0.75rem, 0.71rem + 0.21vw, 0.875rem); /* 12→14px */
--fs-base: clamp(0.8125rem, 0.77rem + 0.23vw, 1rem); /* 13→16px */
--fs-md: clamp(0.875rem, 0.83rem + 0.25vw, 1.125rem); /* 14→18px */
--fs-lg: clamp(1rem, 0.93rem + 0.38vw, 1.25rem); /* 16→20px */
--fs-xl: clamp(1.125rem, 1.0rem + 0.63vw, 1.5rem); /* 18→24px */
--fs-2xl: clamp(1.25rem, 1.04rem + 1.04vw, 1.875rem); /* 20→30px */
--fs-3xl: clamp(1.5rem, 1.19rem + 1.56vw, 2.25rem); /* 24→36px */
--fs-4xl: clamp(1.875rem, 1.35rem + 2.60vw, 3rem); /* 30→48px */
/* Line heights */
--lh-tight: 1.2;
--lh-snug: 1.35;
--lh-normal: 1.5;
--lh-relaxed: 1.65;
/* Fluid spacing scale (8pt grid, fluid from xs to xl) */
--space-0: 0;
--space-1: clamp(0.125rem, 0.11rem + 0.05vw, 0.1875rem); /* 2→3px */
--space-2: clamp(0.25rem, 0.22rem + 0.10vw, 0.375rem); /* 4→6px */
--space-3: clamp(0.375rem, 0.33rem + 0.17vw, 0.5rem); /* 6→8px */
--space-4: clamp(0.5rem, 0.44rem + 0.26vw, 0.75rem); /* 8→12px */
--space-5: clamp(0.75rem, 0.65rem + 0.42vw, 1rem); /* 12→16px */
--space-6: clamp(1rem, 0.87rem + 0.56vw, 1.5rem); /* 16→24px */
--space-7: clamp(1.25rem, 1.04rem + 0.83vw, 2rem); /* 20→32px */
--space-8: clamp(1.5rem, 1.22rem + 1.04vw, 2.5rem); /* 24→40px */
--space-10: clamp(2rem, 1.65rem + 1.46vw, 3.5rem); /* 32→56px */
--space-12: clamp(2.5rem, 2.00rem + 2.08vw, 4.5rem); /* 40→72px */
/* Touch target minimum (WCAG 2.5.5 AA is 44×44 CSS px) */
--tap-min: 44px;
/* Container widths */
--container-sm: 640px;
--container-md: 768px;
--container-lg: 1024px;
--container-xl: 1280px;
--container-2xl: 1536px;
/* Motion tokens */
--motion-fast: 120ms;
--motion-base: 200ms;
--motion-slow: 320ms;
--motion-ease: cubic-bezier(0.4, 0, 0.2, 1);
/* Z-index scale */
--z-base: 0;
--z-sticky: 10;
--z-drawer-backdrop: 40;
--z-drawer: 50;
--z-dropdown: 60;
--z-modal: 100;
--z-toast: 200;
--z-tooltip: 300;
--z-focus: 999;
/* Focus ring */
--focus-ring-color: #60a5fa; /* light blue, visible on dark bg */
--focus-ring-offset: 2px;
--focus-ring-width: 2px;
/* Safe area insets (iOS notch, Android gesture areas) */
--safe-top: env(safe-area-inset-top, 0px);
--safe-right: env(safe-area-inset-right, 0px);
--safe-bottom: env(safe-area-inset-bottom, 0px);
--safe-left: env(safe-area-inset-left, 0px);
}
/* Honor OS-level reduced motion apply across the entire app.
Anything that relies on animation for state feedback (toasts,
drawer slide, spinner) must still convey state without motion.
Spinners use opacity pulses under the same media query. */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}
/* Honor OS-level contrast preference */
@media (prefers-contrast: more) {
:root {
--focus-ring-width: 3px;
--focus-ring-color: #ffffff;
}
}
/* High-DPI tuning: tighten 1px borders on >= 2x DPR so they read as
hairlines and don't visually bloom. */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
:root {
--hairline: 0.5px;
}
}
@media not all and (-webkit-min-device-pixel-ratio: 2), not all and (min-resolution: 2dppx) {
:root {
--hairline: 1px;
}
}