151 lines
4.0 KiB
SCSS
151 lines
4.0 KiB
SCSS
@use './variables' as *;
|
|
|
|
:root {
|
|
--color-text: #1a1a1a;
|
|
--color-text-muted: #6b6b6b;
|
|
--color-background: #ffffff;
|
|
--color-surface: #f7f7f5;
|
|
--color-border: #e2e0dc;
|
|
--color-primary: #b5432b;
|
|
--color-primary-contrast: #ffffff;
|
|
--color-danger: #a33333;
|
|
--color-success: #2f7a4f;
|
|
color-scheme: light;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
--color-text: #ededed;
|
|
--color-text-muted: #9d9d9d;
|
|
--color-background: #161616;
|
|
--color-surface: #202020;
|
|
--color-border: #383838;
|
|
--color-primary: #d9694a;
|
|
--color-primary-contrast: #ffffff;
|
|
--color-danger: #ef6b62;
|
|
--color-success: #4fbb7c;
|
|
color-scheme: dark;
|
|
}
|
|
}
|
|
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
// Reserve the scrollbar's width on every page, scrollable or not — without
|
|
// this, the sticky nav bar (and page content) shifts a few pixels wider
|
|
// when navigating from a short page (no scrollbar) to a tall one (has one).
|
|
// `scrollbar-gutter` only takes effect on an actual scroll container, so
|
|
// `html` needs an explicit non-visible overflow for it to apply at all.
|
|
html {
|
|
overflow-y: scroll;
|
|
scrollbar-gutter: stable;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
font-family:
|
|
system-ui,
|
|
-apple-system,
|
|
'Segoe UI',
|
|
Roboto,
|
|
sans-serif;
|
|
color: $color-text;
|
|
background: $color-background;
|
|
}
|
|
|
|
button {
|
|
font: inherit;
|
|
}
|
|
|
|
// Route navigation transitions, powered by the router's defaultViewTransition
|
|
// (see router.tsx). No-ops in browsers without View Transitions support.
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
::view-transition-old(root),
|
|
::view-transition-new(root) {
|
|
animation-duration: 0.22s;
|
|
animation-timing-function: ease;
|
|
}
|
|
|
|
::view-transition-old(root) {
|
|
animation-name: view-transition-fade-out;
|
|
}
|
|
|
|
::view-transition-new(root) {
|
|
animation-name: view-transition-fade-in;
|
|
}
|
|
|
|
// Any element that carries a matching `view-transition-name` on both the
|
|
// outgoing and incoming page (e.g. an Order card morphing into its detail
|
|
// header, see OrdersListView / OrderStatusView) gets its own transition
|
|
// group — this smooths and slows the browser's default morph/resize
|
|
// animation for those to match the root crossfade's pace instead of the
|
|
// UA default's snappier one.
|
|
::view-transition-group(*) {
|
|
animation-duration: 0.32s;
|
|
animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
|
|
}
|
|
|
|
// The top nav bar (see __root.tsx) carries its own `view-transition-name`
|
|
// so it's excluded from the root snapshot above — otherwise the root
|
|
// fade's translateY drags the persistent header along with it, making it
|
|
// visibly jump on every navigation. It doesn't change between routes, so
|
|
// it should just stay put: no morph, no crossfade.
|
|
::view-transition-group(site-header) {
|
|
animation: none;
|
|
}
|
|
|
|
::view-transition-old(site-header),
|
|
::view-transition-new(site-header) {
|
|
animation: none;
|
|
}
|
|
|
|
// Same reasoning as site-header: the admin sidebar nav is identical across
|
|
// every /admin/* route, so it should stay put across those navigations
|
|
// instead of fading/translating along with the root snapshot.
|
|
::view-transition-group(admin-sidebar) {
|
|
animation: none;
|
|
}
|
|
|
|
::view-transition-old(admin-sidebar),
|
|
::view-transition-new(admin-sidebar) {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
// document.startViewTransition() itself doesn't check this preference —
|
|
// without an explicit override every browser falls back to its own default
|
|
// crossfade/morph animations, unanimated only for the rules above (which
|
|
// only apply under no-preference). Kill all of it outright here instead.
|
|
@media (prefers-reduced-motion: reduce) {
|
|
::view-transition-group(*),
|
|
::view-transition-old(*),
|
|
::view-transition-new(*) {
|
|
animation: none !important;
|
|
}
|
|
}
|
|
|
|
@keyframes view-transition-fade-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(6px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
@keyframes view-transition-fade-out {
|
|
from {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
to {
|
|
opacity: 0;
|
|
transform: translateY(-6px);
|
|
}
|
|
}
|