> element. */
@keyframes fade-in {
from {
opacity: 0;
}
}
@keyframes fade-out {
to {
opacity: 0;
}
}
@keyframes slide-from-right {
from {
transform: translateX(120px);
}
}
@keyframes slide-to-left {
to {
transform: translateX(-120px);
}
}
@keyframes slide-to-right {
to {
transform: translateX(120px);
}
}
@keyframes slide-from-left {
from {
transform: translateX(-120px);
}
}
/* For browsers that support it, use view transition animations for pages */
/* View transition animation for the old page going out */
::view-transition-old(root) {
animation: 90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
/* View transition animation for the new page coming in */
::view-transition-new(root) {
animation: 310ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
400ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
/* Overrides for 'back' view page transitions */
/* View transition animation the old page going out on back navigation */
.back-transition::view-transition-old(root) {
animation-name: fade-out, slide-to-right;
}
/* View transition animation the new page coming in on back navigation */
.back-transition::view-transition-new(root) {
animation-name: fade-in, slide-from-left;
}
/* Exclude the header and footer from view transition by giving each its own view transition name. This way the header and footer won't transition in and out with the page content. */
::part(app-header) {
view-transition-name: app-header-transition;
}
::part(app-footer) {
view-transition-name: app-footer-transition;
}
::view-transition-group(product-logo-transition),
::view-transition-group(product-title-transition) {
animation-duration: 400ms;
}
::view-transition-new(product-logo-transition),
::view-transition-new(product-title-transition) {
mix-blend-mode: normal;
}
::view-transition-image-pair(product-logo-transition),
::view-transition-image-pair(product-title-transition) {
isolation: none;
}
/* On mobile, card titles are left-aligned but PDP titles are centered.
Animate only the PDP title snapshot to avoid overlapping text.
Keep the movement and scaling; desktop and logo animations stay unchanged. */
@media (max-width: 575px) {
::view-transition-old(product-title-transition) {
display: none;
}
::view-transition-new(product-title-transition) {
animation: none;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
:root::view-transition-old(root),
:root::view-transition-new(root),
::view-transition-group(product-logo-transition),
::view-transition-group(product-title-transition),
::view-transition-old(product-logo-transition),
::view-transition-old(product-title-transition),
::view-transition-new(product-logo-transition),
::view-transition-new(product-title-transition) {
animation: none;
}
}
/* Toasts should appear below the app header. This is a custom fixed-position stack that hosts
alerts (Web Awesome has no built-in toast stack like Shoelace's sl-alert.toast()). */
.wa-toast-stack {
position: fixed;
top: 100px;
inset-inline-end: 1rem;
z-index: var(--wa-z-index-toast, 950);
display: flex;
flex-direction: column;
gap: 0.5rem;
width: 28rem;
max-width: calc(100% - 2rem);
pointer-events: none;
}
.wa-toast-stack .alert-toast {
position: relative;
pointer-events: auto;
box-shadow: var(--wa-shadow-l, 0 4px 16px rgba(0, 0, 0, 0.24));
}
.wa-toast-stack .alert-toast .alert-close-btn {
position: absolute;
top: 0.25rem;
inset-inline-end: 0.25rem;
}
/* Adding cookie banner here due to shadow dom limiting access */
#cookie-banner {
position: fixed;
bottom: 0;
z-index: 1000;
}
.wa-scroll-lock {
/* When screenshots pops up a dialog, as the default value of this variable is 15px,
there is space between the scrollbar and the edge, which causes the nav header to also have space between it and the edge.*/
--wa-scroll-lock-size: 0 !important;
}
.wa-scroll-lock body {
overflow: hidden !important;
}
/* ====== Pill collection page transitions ======
The hero element gets an isolated view-transition name assigned in its
Lit component (pill-hero), with pill-nav isolating the sticky pill row.
Direction is signalled by a class on documentElement set in
category-pills.handlePillClick — pill-flip-forward when the user clicks a
pill to the right of the current one, pill-flip-back for a pill to the left. */
/* When a pill-flip is active, suppress the global root slide-and-fade so the
whole page doesn't slide alongside the hero flip. The hero, content, and
pill row each animate (or stay) on their own. */
:root.pill-flip-forward::view-transition-old(root),
:root.pill-flip-forward::view-transition-new(root),
:root.pill-flip-back::view-transition-old(root),
:root.pill-flip-back::view-transition-new(root) {
animation: none;
}
/* 3D depth so the hero can rotate like a book page. */
::view-transition-group(pill-hero) {
perspective: 1400px;
}
/* Avoid double-fade artifacts; we control opacity in keyframes ourselves. */
::view-transition-old(pill-hero),
::view-transition-new(pill-hero) {
mix-blend-mode: normal;
}
/* ----- Forward (clicked a pill to the right of current) ----- */
:root.pill-flip-forward::view-transition-old(pill-hero) {
animation: pillHeroFlipOutForward 360ms cubic-bezier(0.4, 0, 0.6, 1) both;
transform-origin: left center;
backface-visibility: hidden;
}
:root.pill-flip-forward::view-transition-new(pill-hero) {
animation: pillHeroFlipInForward 360ms cubic-bezier(0.4, 0, 0.6, 1) both;
transform-origin: left center;
backface-visibility: hidden;
}
/* ----- Back (clicked a pill to the left of current) ----- */
:root.pill-flip-back::view-transition-old(pill-hero) {
animation: pillHeroFlipOutBack 360ms cubic-bezier(0.4, 0, 0.6, 1) both;
transform-origin: right center;
backface-visibility: hidden;
}
:root.pill-flip-back::view-transition-new(pill-hero) {
animation: pillHeroFlipInBack 360ms cubic-bezier(0.4, 0, 0.6, 1) both;
transform-origin: right center;
backface-visibility: hidden;
}
@keyframes pillHeroFlipOutForward {
from { transform: rotateY(0); opacity: 1; }
to { transform: rotateY(-92deg); opacity: 0.15; }
}
@keyframes pillHeroFlipInForward {
from { transform: rotateY(92deg); opacity: 0; }
to { transform: rotateY(0); opacity: 1; }
}
@keyframes pillHeroFlipOutBack {
from { transform: rotateY(0); opacity: 1; }
to { transform: rotateY(92deg); opacity: 0.15; }
}
@keyframes pillHeroFlipInBack {
from { transform: rotateY(-92deg); opacity: 0; }
to { transform: rotateY(0); opacity: 1; }
}
/* Reduced motion: skip the flip; default crossfade applies. */
@media (prefers-reduced-motion: reduce) {
:root.pill-flip-forward::view-transition-old(pill-hero),
:root.pill-flip-forward::view-transition-new(pill-hero),
:root.pill-flip-back::view-transition-old(pill-hero),
:root.pill-flip-back::view-transition-new(pill-hero) {
animation: none;
}
}