Partial support in stable Firefox: the mask
- renders, but the reveal falls back to a static
+ renders, but the travel falls back to a static
always-on fade.
diff --git a/demo/input.css b/demo/input.css
index f9f0be2..020d01f 100644
--- a/demo/input.css
+++ b/demo/input.css
@@ -1,8 +1,9 @@
@import "tailwindcss" source(none);
@import "../src/tw-fade.css";
+@import "tw-shimmer";
@import "./vendor/tw-glass.css";
/* Scan the demo markup for utility classes. */
@source "./index.html";
/* The Advanced sides control composes these classes at runtime. */
-@source inline("fade-{t,b,l,r}");
+@source inline("fade-{top,bottom,start,end}");
diff --git a/demo/styles.css b/demo/styles.css
index bd205e9..a8c3beb 100644
--- a/demo/styles.css
+++ b/demo/styles.css
@@ -35,13 +35,13 @@
--fade-size-2xl: calc(var(--spacing, 0.25rem) * 24);
--fade-size-3xl: calc(var(--spacing, 0.25rem) * 32);
--fade-size-4xl: calc(var(--spacing, 0.25rem) * 40);
- --fade-range-sm: calc(var(--spacing, 0.25rem) * 8);
- --fade-range-md: calc(var(--spacing, 0.25rem) * 12);
- --fade-range-lg: calc(var(--spacing, 0.25rem) * 16);
- --fade-range-xl: calc(var(--spacing, 0.25rem) * 20);
- --fade-range-2xl: calc(var(--spacing, 0.25rem) * 24);
- --fade-range-3xl: calc(var(--spacing, 0.25rem) * 32);
- --fade-range-4xl: calc(var(--spacing, 0.25rem) * 40);
+ --fade-travel-sm: calc(var(--spacing, 0.25rem) * 8);
+ --fade-travel-md: calc(var(--spacing, 0.25rem) * 12);
+ --fade-travel-lg: calc(var(--spacing, 0.25rem) * 16);
+ --fade-travel-xl: calc(var(--spacing, 0.25rem) * 20);
+ --fade-travel-2xl: calc(var(--spacing, 0.25rem) * 24);
+ --fade-travel-3xl: calc(var(--spacing, 0.25rem) * 32);
+ --fade-travel-4xl: calc(var(--spacing, 0.25rem) * 40);
}
}
@layer base {
@@ -199,24 +199,6 @@
.static {
position: static;
}
- .container {
- width: 100%;
- @media (width >= 40rem) {
- max-width: 40rem;
- }
- @media (width >= 48rem) {
- max-width: 48rem;
- }
- @media (width >= 64rem) {
- max-width: 64rem;
- }
- @media (width >= 80rem) {
- max-width: 80rem;
- }
- @media (width >= 96rem) {
- max-width: 96rem;
- }
- }
.mx-auto {
margin-inline: auto;
}
@@ -274,496 +256,72 @@
.shrink-0 {
flex-shrink: 0;
}
- .fade-xy {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
- }
- .fade-x {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ .shimmer {
+ --_gradient-width: calc(var(--_spread) + var(--shimmer-track-height) * tan(var(--shimmer-angle)));
+ --_active-distance: calc(var(--shimmer-track-width, 200px) + var(--_gradient-width));
+ --_duration: var(--shimmer-duration, calc(var(--_active-distance) / var(--_speed) / 1px * 1000));
+ --_repeat-delay: var(--shimmer-repeat-delay, calc(20000 / var(--_speed)));
+ --_repeat-delay-px: calc(var(--_repeat-delay) * var(--_active-distance) / var(--_duration));
+ --_xy-offset-px: calc((var(--shimmer-x, 0) + var(--shimmer-y, 0) * tan(var(--shimmer-angle))) * 1px);
+ --_bg-width: calc(
+ 100% +
+ var(--shimmer-track-width, 100%) +
+ var(--_gradient-width) +
+ var(--_repeat-delay-px)
+ );
+ --_position: calc(
+ var(--shimmer-track-width, (100% - var(--_gradient-width) - var(--_repeat-delay-px)) / 2)
+ + var(--_gradient-width) / 2
+ + var(--_repeat-delay-px)
+ - var(--_xy-offset-px)
+ );
+ &:not(.shimmer-bg) {
+ --_speed: var(--shimmer-speed, 200);
+ --_spread: var(--shimmer-spread, calc(4ch + 80px));
+ --_bg: currentColor;
+ --_fg: var(--shimmer-color, oklch(from currentColor l c h / calc(alpha * 0.2)));
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
}
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
- }
- .fade-y {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ @media (prefers-color-scheme: dark) {
+ &:not(.shimmer-bg) {
+ --_fg: var(--shimmer-color, oklch(from currentColor max(0.8, calc(l + 0.4)) c h / calc(alpha + 0.4)));
+ }
}
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
- }
- .fade-b {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
+ @-moz-document url-prefix() {
+ --_duration: var(--shimmer-duration, calc(375000 / var(--_speed)));
}
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ --_mix-96: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-96: color-mix(in oklch, var(--_fg), var(--_bg) 96%);
}
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
- }
- .fade-l {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
+ --_mix-83: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-83: color-mix(in oklch, var(--_fg), var(--_bg) 83%);
}
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ --_mix-67: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-67: color-mix(in oklch, var(--_fg), var(--_bg) 67%);
}
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
- }
- .fade-r {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
+ --_mix-50: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-50: color-mix(in oklch, var(--_fg), var(--_bg) 50%);
}
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ --_mix-33: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-33: color-mix(in oklch, var(--_fg), var(--_bg) 33%);
}
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
- }
- .fade-t {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
+ --_mix-17: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-17: color-mix(in oklch, var(--_fg), var(--_bg) 17%);
}
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ --_mix-4: var(--_fg);
+ @supports (color: color-mix(in lab, red, red)) {
+ --_mix-4: color-mix(in oklch, var(--_fg), var(--_bg) 4%);
}
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
+ background: linear-gradient( calc(90deg + var(--shimmer-angle)), var(--_bg) calc(var(--_position) - var(--_spread) * 0.5), var(--_mix-96) calc(var(--_position) - var(--_spread) * 0.44), var(--_mix-83) calc(var(--_position) - var(--_spread) * 0.37), var(--_mix-67) calc(var(--_position) - var(--_spread) * 0.31), var(--_mix-50) calc(var(--_position) - var(--_spread) * 0.25), var(--_mix-33) calc(var(--_position) - var(--_spread) * 0.19), var(--_mix-17) calc(var(--_position) - var(--_spread) * 0.12), var(--_mix-4) calc(var(--_position) - var(--_spread) * 0.06), var(--_fg) var(--_position), var(--_mix-4) calc(var(--_position) + var(--_spread) * 0.06), var(--_mix-17) calc(var(--_position) + var(--_spread) * 0.12), var(--_mix-33) calc(var(--_position) + var(--_spread) * 0.19), var(--_mix-50) calc(var(--_position) + var(--_spread) * 0.25), var(--_mix-67) calc(var(--_position) + var(--_spread) * 0.31), var(--_mix-83) calc(var(--_position) + var(--_spread) * 0.37), var(--_mix-96) calc(var(--_position) + var(--_spread) * 0.44), var(--_bg) calc(var(--_position) + var(--_spread) * 0.5) ) 0 0 / var(--_bg-width) 100% no-repeat;
+ animation: tw-shimmer 1s linear 0s infinite backwards;
+ animation-duration: calc((var(--_duration) + var(--_repeat-delay)) * 1ms);
}
.flex-col {
flex-direction: column;
@@ -961,38 +519,19 @@
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
- .fade-static {
- --tw-fade-t: 1 !important;
- --tw-fade-b: 1 !important;
- --tw-fade-l: 1 !important;
- --tw-fade-r: 1 !important;
- animation-name: none;
+ .shimmer-bg {
+ --_speed: var(--shimmer-speed, 1000);
+ --_spread: var(--shimmer-spread, 480px);
+ --_bg: transparent;
+ --_fg: var(--shimmer-color, oklch(from currentColor 0 c h / 0.06));
+ @media (prefers-color-scheme: dark) {
+ --_fg: var(--shimmer-color, oklch(from currentColor 0 c h / 0.30));
+ }
}
.select-none {
-webkit-user-select: none;
user-select: none;
}
- .fade-range-2xl {
- --tw-fade-range: var(--fade-range-2xl);
- }
- .fade-range-3xl {
- --tw-fade-range: var(--fade-range-3xl);
- }
- .fade-range-4xl {
- --tw-fade-range: var(--fade-range-4xl);
- }
- .fade-range-lg {
- --tw-fade-range: var(--fade-range-lg);
- }
- .fade-range-md {
- --tw-fade-range: var(--fade-range-md);
- }
- .fade-range-sm {
- --tw-fade-range: var(--fade-range-sm);
- }
- .fade-range-xl {
- --tw-fade-range: var(--fade-range-xl);
- }
.fade-size-2xl {
--tw-fade-size: var(--fade-size-2xl);
}
@@ -1014,6 +553,27 @@
.fade-size-xl {
--tw-fade-size: var(--fade-size-xl);
}
+ .fade-travel-2xl {
+ --tw-fade-travel: var(--fade-travel-2xl);
+ }
+ .fade-travel-3xl {
+ --tw-fade-travel: var(--fade-travel-3xl);
+ }
+ .fade-travel-4xl {
+ --tw-fade-travel: var(--fade-travel-4xl);
+ }
+ .fade-travel-lg {
+ --tw-fade-travel: var(--fade-travel-lg);
+ }
+ .fade-travel-md {
+ --tw-fade-travel: var(--fade-travel-md);
+ }
+ .fade-travel-sm {
+ --tw-fade-travel: var(--fade-travel-sm);
+ }
+ .fade-travel-xl {
+ --tw-fade-travel: var(--fade-travel-xl);
+ }
.sm\:mr-4 {
@media (width >= 40rem) {
margin-right: calc(var(--spacing) * 4);
@@ -1108,39 +668,51 @@
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-t {
+@property --tw-fade-size-top {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-size-bottom {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-b {
+@property --tw-fade-size-start {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-l {
+@property --tw-fade-size-end {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-r {
+@property --tw-fade-travel {
syntax: "*";
inherits: false;
}
-@property --tw-fade-range {
+@property --tw-fade-clear {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-t {
+@property --tw-fade-clear-y {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-b {
+@property --tw-fade-clear-x {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-l {
+@property --tw-fade-clear-top {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-r {
+@property --tw-fade-clear-bottom {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-clear-start {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-clear-end {
syntax: "*";
inherits: false;
}
@@ -1160,7 +732,71 @@
syntax: "*";
inherits: false;
}
-@keyframes tw-fade-reveal-t {
+@property --tw-fade-ltr-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@keyframes tw-fade-travel-t {
from {
--tw-fade-t: 0;
}
@@ -1168,7 +804,7 @@
--tw-fade-t: 1;
}
}
-@keyframes tw-fade-reveal-b {
+@keyframes tw-fade-travel-b {
from {
--tw-fade-b: 1;
}
@@ -1176,7 +812,7 @@
--tw-fade-b: 0;
}
}
-@keyframes tw-fade-reveal-l {
+@keyframes tw-fade-travel-l {
from {
--tw-fade-l: 0;
}
@@ -1184,7 +820,7 @@
--tw-fade-l: 1;
}
}
-@keyframes tw-fade-reveal-r {
+@keyframes tw-fade-travel-r {
from {
--tw-fade-r: 1;
}
@@ -1192,11 +828,274 @@
--tw-fade-r: 0;
}
}
+@keyframes tw-fade-travel-r-leading {
+ from {
+ --tw-fade-r: 0;
+ }
+ to {
+ --tw-fade-r: 1;
+ }
+}
+@keyframes tw-fade-travel-l-trailing {
+ from {
+ --tw-fade-l: 1;
+ }
+ to {
+ --tw-fade-l: 0;
+ }
+}
@layer utilities {
- .fade-t, .fade-b, .fade-l, .fade-r, .fade-y, .fade-x, .fade-xy {
- --tw-fade-size-default: var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12));
- --tw-fade-range-active: var(--tw-fade-range, var(--fade-range-md, calc(var(--spacing, 0.25rem) * 12)));
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ --tw-fade-size-default: min(12%, var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12)));
+ --tw-fade-travel-active: var(--tw-fade-travel, var(--fade-travel-sm, calc(var(--spacing, 0.25rem) * 8)));
+ --tw-fade-identity-mask: linear-gradient(#000, #000);
+ --tw-fade-edge-size-t: var(--tw-fade-size-top, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-b: var(--tw-fade-size-bottom, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-l: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-t: var(--tw-fade-clear-top, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-b: var(--tw-fade-clear-bottom, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
+ --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
+ --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
+ --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
+ --tw-fade-onset: 8;
+ --tw-fade-alpha-t: min(1, calc(var(--tw-fade-t) * var(--tw-fade-onset)));
+ --tw-fade-alpha-b: min(1, calc(var(--tw-fade-b) * var(--tw-fade-onset)));
+ --tw-fade-alpha-l: min(1, calc(var(--tw-fade-l) * var(--tw-fade-onset)));
+ --tw-fade-alpha-r: min(1, calc(var(--tw-fade-r) * var(--tw-fade-onset)));
+ --tw-fade-gradient-t: linear-gradient(
+ to bottom,
+ #000 0 var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t))) var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.983))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.933))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.854))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.75))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.629))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.5))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.371))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.25))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.146))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.067))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.017))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
+ );
+ --tw-fade-gradient-b: linear-gradient(
+ to top,
+ #000 0 var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b))) var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.983))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.933))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.854))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.75))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.629))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.5))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.371))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.25))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.146))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.067))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.017))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
+ );
+ --tw-fade-gradient-l: linear-gradient(
+ to right,
+ #000 0 var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l))) var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.983))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.933))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.854))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.75))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.629))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.5))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.371))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.25))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.146))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.067))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.017))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
+ );
+ --tw-fade-gradient-r: linear-gradient(
+ to left,
+ #000 0 var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r))) var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.983))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.933))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.854))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.75))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.629))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.5))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.371))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.25))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.146))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.067))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.017))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
+ );
+ --tw-fade-mask-l: var(--tw-fade-ltr-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-ltr-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-ltr-start-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-ltr-end-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-ltr-start-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-ltr-end-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-ltr-start-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-ltr-end-animation-range, normal);
+ --tw-fade-animation-t: none;
+ --tw-fade-animation-b: none;
+ --tw-fade-timeline-t: none;
+ --tw-fade-timeline-b: none;
+ --tw-fade-animation-range-t: normal;
+ --tw-fade-animation-range-b: normal;
+ mask-image: var(--tw-fade-mask-t, var(--tw-fade-identity-mask)), var(--tw-fade-mask-b, var(--tw-fade-identity-mask)), var(--tw-fade-mask-l, var(--tw-fade-identity-mask)), var(--tw-fade-mask-r, var(--tw-fade-identity-mask));
+ mask-composite: intersect;
+ mask-repeat: no-repeat;
+ mask-size: 100% 100%;
+ }
+ .fade:where(:dir(rtl)), .fade-y:where(:dir(rtl)), .fade-top:where(:dir(rtl)), .fade-bottom:where(:dir(rtl)), .fade-x:where(:dir(rtl)), .fade-start:where(:dir(rtl)), .fade-end:where(:dir(rtl)) {
+ --tw-fade-edge-size-l: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-mask-l: var(--tw-fade-rtl-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-rtl-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-rtl-end-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-rtl-start-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-rtl-end-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-rtl-start-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-rtl-end-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-rtl-start-animation-range, normal);
+ }
+ .fade, .fade-y, .fade-top {
+ --tw-fade-mask-t: var(--tw-fade-gradient-t);
+ --tw-fade-animation-t: tw-fade-travel-t;
+ --tw-fade-timeline-t: scroll(self y);
+ --tw-fade-animation-range-t: 0 var(--tw-fade-travel-active);
+ }
+ .fade, .fade-y, .fade-bottom {
+ --tw-fade-mask-b: var(--tw-fade-gradient-b);
+ --tw-fade-animation-b: tw-fade-travel-b;
+ --tw-fade-timeline-b: scroll(self y);
+ --tw-fade-animation-range-b: calc(100% - var(--tw-fade-travel-active)) 100%;
+ }
+ .fade, .fade-x, .fade-start {
+ --tw-fade-ltr-start-layer: var(--tw-fade-gradient-l);
+ --tw-fade-rtl-start-layer: var(--tw-fade-gradient-r);
+ --tw-fade-ltr-start-animation: tw-fade-travel-l;
+ --tw-fade-rtl-start-animation: tw-fade-travel-r-leading;
+ --tw-fade-ltr-start-timeline: scroll(self inline);
+ --tw-fade-rtl-start-timeline: scroll(self inline);
+ --tw-fade-ltr-start-animation-range: 0 var(--tw-fade-travel-active);
+ --tw-fade-rtl-start-animation-range: 0 var(--tw-fade-travel-active);
+ }
+ .fade, .fade-x, .fade-end {
+ --tw-fade-ltr-end-layer: var(--tw-fade-gradient-r);
+ --tw-fade-rtl-end-layer: var(--tw-fade-gradient-l);
+ --tw-fade-ltr-end-animation: tw-fade-travel-r;
+ --tw-fade-rtl-end-animation: tw-fade-travel-l-trailing;
+ --tw-fade-ltr-end-timeline: scroll(self inline);
+ --tw-fade-rtl-end-timeline: scroll(self inline);
+ --tw-fade-ltr-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
+ --tw-fade-rtl-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
+ }
+ @supports (animation-timeline: scroll()) {
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ animation: var(--tw-fade-animation-t, none) auto linear both, var(--tw-fade-animation-b, none) auto linear both, var(--tw-fade-animation-l, none) auto linear both, var(--tw-fade-animation-r, none) auto linear both;
+ animation-timeline: var(--tw-fade-timeline-t, none), var(--tw-fade-timeline-b, none), var(--tw-fade-timeline-l, none), var(--tw-fade-timeline-r, none);
+ animation-range: var(--tw-fade-animation-range-t, normal), var(--tw-fade-animation-range-b, normal), var(--tw-fade-animation-range-l, normal), var(--tw-fade-animation-range-r, normal);
+ }
}
+ @supports not (animation-timeline: scroll()) {
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ --tw-fade-t: 1;
+ --tw-fade-b: 1;
+ --tw-fade-l: 1;
+ --tw-fade-r: 1;
+ }
+ }
+ .fade-none {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+ .fade-none-y {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ }
+ .fade-none-x {
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+ .fade-always {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
+ }
+ .fade-always-y {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ }
+ .fade-always-x {
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
+ }
+}
+@property --shimmer-track-height {
+ syntax: '
';
+ inherits: true;
+ initial-value: 200px;
+}
+@property --shimmer-angle {
+ syntax: '';
+ inherits: true;
+ initial-value: 15deg;
}
@property --tw-glass-blur {
syntax: "";
@@ -1360,9 +1259,16 @@
syntax: "*";
inherits: false;
}
+@keyframes tw-shimmer {
+ from {
+ background-position: 100% 0;
+ }
+}
@layer properties {
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
:root, :host {
+ --shimmer-track-height: 200px;
+ --shimmer-angle: 15deg;
--glass-bg-opacity: 0.08;
}
*, ::before, ::after, ::backdrop {
@@ -1404,19 +1310,38 @@
--tw-fade-size: initial;
--tw-fade-size-y: initial;
--tw-fade-size-x: initial;
- --tw-fade-size-t: initial;
- --tw-fade-size-b: initial;
- --tw-fade-size-l: initial;
- --tw-fade-size-r: initial;
- --tw-fade-range: initial;
- --tw-fade-clear-t: initial;
- --tw-fade-clear-b: initial;
- --tw-fade-clear-l: initial;
- --tw-fade-clear-r: initial;
+ --tw-fade-size-top: initial;
+ --tw-fade-size-bottom: initial;
+ --tw-fade-size-start: initial;
+ --tw-fade-size-end: initial;
+ --tw-fade-travel: initial;
+ --tw-fade-clear: initial;
+ --tw-fade-clear-y: initial;
+ --tw-fade-clear-x: initial;
+ --tw-fade-clear-top: initial;
+ --tw-fade-clear-bottom: initial;
+ --tw-fade-clear-start: initial;
+ --tw-fade-clear-end: initial;
--tw-fade-mask-t: initial;
--tw-fade-mask-b: initial;
--tw-fade-mask-l: initial;
--tw-fade-mask-r: initial;
+ --tw-fade-ltr-start-layer: initial;
+ --tw-fade-ltr-end-layer: initial;
+ --tw-fade-rtl-start-layer: initial;
+ --tw-fade-rtl-end-layer: initial;
+ --tw-fade-ltr-start-animation: initial;
+ --tw-fade-ltr-end-animation: initial;
+ --tw-fade-rtl-start-animation: initial;
+ --tw-fade-rtl-end-animation: initial;
+ --tw-fade-ltr-start-timeline: initial;
+ --tw-fade-ltr-end-timeline: initial;
+ --tw-fade-rtl-start-timeline: initial;
+ --tw-fade-rtl-end-timeline: initial;
+ --tw-fade-ltr-start-animation-range: initial;
+ --tw-fade-ltr-end-animation-range: initial;
+ --tw-fade-rtl-start-animation-range: initial;
+ --tw-fade-rtl-end-animation-range: initial;
--tw-glass-blur: 2px;
--tw-glass-brightness: 1.05;
--tw-glass-saturation: 1.2;
diff --git a/demo/wave-lab.html b/demo/wave-lab.html
index 761303f..4f2e245 100644
--- a/demo/wave-lab.html
+++ b/demo/wave-lab.html
@@ -436,27 +436,36 @@ wave background lab
// explicit cubic segments (p0..p3) that compose it. The cubics let us
// build closed fill shapes — either lobes (curve→tile-edge) or strips
// (the negative space *between* two adjacent wave lines).
- function columnPath(cx, s0, a, h, segs) {
- let stroke = `M${r(cx)} 0`;
+ // Short sine-matched spans remove the center-crossing curvature jump while
+ // keeping the old half-wave Bezier's tuned 45px visual reach.
+ const SINE_SEGMENTS_PER_CYCLE = 8;
+ const TUNED_AMPLITUDE_SCALE = 0.75;
+
+ function columnPath(cx, s0, amp, wl, cycles) {
+ const a = amp * TUNED_AMPLITUDE_SCALE;
+ const segs = SINE_SEGMENTS_PER_CYCLE * cycles;
+ const segmentH = wl / SINE_SEGMENTS_PER_CYCLE;
+ const phaseStep = (Math.PI * 2) / SINE_SEGMENTS_PER_CYCLE;
+ let stroke = "";
const cubics = [];
- const p0 = { x: cx, y: 0 };
- const p1 = { x: cx + s0 * a, y: 0.25 * h };
- const p2 = { x: cx + s0 * a, y: 0.75 * h };
- const p3 = { x: cx, y: h };
- stroke += `C${r(p1.x)} ${r(p1.y)} ${r(p2.x)} ${r(p2.y)} ${r(p3.x)} ${r(p3.y)}`;
- cubics.push({ p0, p1, p2, p3 });
-
- let prevP2 = p2;
- let prevP3 = p3;
- for (let i = 1; i < segs; i += 1) {
- const sign = s0 * (i % 2 === 0 ? 1 : -1);
- const cp1 = { x: 2 * prevP3.x - prevP2.x, y: 2 * prevP3.y - prevP2.y };
- const cp2 = { x: cx + sign * a, y: i * h + 0.75 * h };
- const end = { x: cx, y: (i + 1) * h };
- stroke += `S${r(cp2.x)} ${r(cp2.y)} ${r(end.x)} ${r(end.y)}`;
- cubics.push({ p0: prevP3, p1: cp1, p2: cp2, p3: end });
- prevP2 = cp2;
- prevP3 = end;
+
+ for (let i = 0; i < segs; i += 1) {
+ const phase0 = i * phaseStep;
+ const phase1 = phase0 + phaseStep;
+ const y0 = i * segmentH;
+ const y1 = (i + 1) * segmentH;
+ const x0 = cx + s0 * a * Math.sin(phase0);
+ const x3 = cx + s0 * a * Math.sin(phase1);
+ const dx0 = s0 * a * Math.cos(phase0) * phaseStep;
+ const dx1 = s0 * a * Math.cos(phase1) * phaseStep;
+ const p0 = { x: x0, y: y0 };
+ const p1 = { x: x0 + dx0 / 3, y: y0 + segmentH / 3 };
+ const p2 = { x: x3 - dx1 / 3, y: y1 - segmentH / 3 };
+ const p3 = { x: x3, y: y1 };
+
+ if (i === 0) stroke = `M${r(p0.x)} ${r(p0.y)}`;
+ stroke += `C${r(p1.x)} ${r(p1.y)} ${r(p2.x)} ${r(p2.y)} ${r(p3.x)} ${r(p3.y)}`;
+ cubics.push({ p0, p1, p2, p3 });
}
return { stroke, cubics };
@@ -502,11 +511,9 @@ wave background lab
// they stay in a cheap repeating . Per-strip stepped shading can't
// tile, so it's built separately as explicit geometry (buildSteppedStrips).
function buildWave(amp, wl) {
- const a = amp;
- const h = wl / 2;
- const segs = 2 * Math.round(params.cycles);
+ const cycles = Math.round(params.cycles);
const S = Math.round(params.spacing);
- const H = Math.round(params.cycles) * wl;
+ const H = cycles * wl;
const cols = Math.round(params.columns);
const tileW = S * cols;
let strokeD = "";
@@ -514,7 +521,7 @@ wave background lab
for (let c = 0; c < cols; c += 1) {
const cx = S * c + S / 2;
const s0 = params.stagger && c % 2 === 1 ? -1 : 1;
- const col = columnPath(cx, s0, a, h, segs);
+ const col = columnPath(cx, s0, amp, wl, cycles);
strokeD += col.stroke;
fillD += lobeFill(col, cx, S * c, S * (c + 1), H);
}
@@ -550,12 +557,10 @@ wave background lab
// darker. Built as explicit paths because per-strip shades can't tile.
function buildSteppedStrips(amp, wl, Wf, Hf) {
if (!Wf || !Hf) return "";
- const a = amp;
- const h = wl / 2;
const S = Math.round(params.spacing);
- const segs = 2 * (Math.ceil(Hf / wl) + 1); // cover full field height + overscan
- const totalH = segs * h;
- const base = columnPath(0, 1, a, h, segs).cubics; // one wave centered at x=0
+ const cycles = Math.ceil(Hf / wl) + 1; // cover full field height + overscan
+ const totalH = cycles * wl;
+ const base = columnPath(0, 1, amp, wl, cycles).cubics; // one wave centered at x=0
const kMax = Math.ceil(Wf / S) + 1;
let out = "";
for (let k = -1; k < kMax; k += 1) {
@@ -875,28 +880,31 @@ wave background lab
` var r = function (v) { return Number(Number(v).toFixed(3)); };\n` +
` var lerp = function (a, b, t) { return a + (b - a) * t; };\n` +
` var clamp01 = function (v) { return v < 0 ? 0 : v > 1 ? 1 : v; };\n` +
+ ` var SP = 8, AS = 0.75;\n` +
+ ` function columnCubics(cx, s0, amp, wl, cycles) {\n` +
+ ` var a = amp * AS, segs = SP * cycles, sh = wl / SP, step = Math.PI * 2 / SP, cs = [];\n` +
+ ` for (var i = 0; i < segs; i++) {\n` +
+ ` var p0a = i * step, p1a = p0a + step, y0 = i * sh, y1 = (i + 1) * sh;\n` +
+ ` var x0 = cx + s0 * a * Math.sin(p0a), x3 = cx + s0 * a * Math.sin(p1a);\n` +
+ ` var dx0 = s0 * a * Math.cos(p0a) * step, dx1 = s0 * a * Math.cos(p1a) * step;\n` +
+ ` cs.push({ p0: { x: x0, y: y0 }, p1: { x: x0 + dx0 / 3, y: y0 + sh / 3 }, p2: { x: x3 - dx1 / 3, y: y1 - sh / 3 }, p3: { x: x3, y: y1 } });\n` +
+ ` }\n` +
+ ` return cs;\n` +
+ ` }\n` +
+ ` function cubicsPath(cs) {\n` +
+ ` var d = "M" + r(cs[0].p0.x) + " " + r(cs[0].p0.y);\n` +
+ ` for (var i = 0; i < cs.length; i++) { var c = cs[i]; d += "C" + r(c.p1.x) + " " + r(c.p1.y) + " " + r(c.p2.x) + " " + r(c.p2.y) + " " + r(c.p3.x) + " " + r(c.p3.y); }\n` +
+ ` return d;\n` +
+ ` }\n` +
` function buildWave(amp, wl) {\n` +
- ` var h = wl / 2, segs = 2 * Math.round(P.cycles), cols = Math.round(P.columns);\n` +
- ` var tileW = Math.round(P.spacing) * cols, H = Math.round(P.cycles) * wl, d = "";\n` +
+ ` var cycles = Math.round(P.cycles), cols = Math.round(P.columns);\n` +
+ ` var tileW = Math.round(P.spacing) * cols, H = cycles * wl, d = "";\n` +
` for (var c = 0; c < cols; c++) {\n` +
` var cx = P.spacing * c + P.spacing / 2, s0 = P.stagger && c % 2 === 1 ? -1 : 1;\n` +
- ` d += "M" + r(cx) + " 0C" + r(cx + s0 * amp) + " " + r(0.25 * h) + " " + r(cx + s0 * amp) + " " + r(0.75 * h) + " " + r(cx) + " " + r(h);\n` +
- ` for (var i = 1; i < segs; i++) { var sn = s0 * (i % 2 === 0 ? 1 : -1); d += "S" + r(cx + sn * amp) + " " + r(i * h + 0.75 * h) + " " + r(cx) + " " + r((i + 1) * h); }\n` +
+ ` d += cubicsPath(columnCubics(cx, s0, amp, wl, cycles));\n` +
` }\n` +
` return { d: d, tileW: tileW, H: H };\n` +
` }\n` +
- ` function columnCubics(cx, s0, amp, h, segs) {\n` +
- ` var cs = [{ p0: { x: cx, y: 0 }, p1: { x: cx + s0 * amp, y: 0.25 * h }, p2: { x: cx + s0 * amp, y: 0.75 * h }, p3: { x: cx, y: h } }];\n` +
- ` var pP2 = cs[0].p2, pP3 = cs[0].p3;\n` +
- ` for (var i = 1; i < segs; i++) {\n` +
- ` var sn = s0 * (i % 2 === 0 ? 1 : -1);\n` +
- ` var cp1 = { x: 2 * pP3.x - pP2.x, y: 2 * pP3.y - pP2.y };\n` +
- ` var cp2 = { x: cx + sn * amp, y: i * h + 0.75 * h };\n` +
- ` var end = { x: cx, y: (i + 1) * h };\n` +
- ` cs.push({ p0: pP3, p1: cp1, p2: cp2, p3: end }); pP2 = cp2; pP3 = end;\n` +
- ` }\n` +
- ` return cs;\n` +
- ` }\n` +
` function shift(cs, dx) { return cs.map(function (c) { return { p0: { x: c.p0.x + dx, y: c.p0.y }, p1: { x: c.p1.x + dx, y: c.p1.y }, p2: { x: c.p2.x + dx, y: c.p2.y }, p3: { x: c.p3.x + dx, y: c.p3.y } }; }); }\n` +
` function stripPath(L, R, cxL, cxR, H) {\n` +
` var d = "M" + r(cxL) + " 0", i, c;\n` +
@@ -914,9 +922,8 @@ wave background lab
` }\n` +
` function buildStrips(amp, wl, W, Hh) {\n` +
` if (!W || !Hh) return "";\n` +
- ` var h = wl / 2, S = Math.round(P.spacing);\n` +
- ` var segs = 2 * (Math.ceil(Hh / wl) + 1), totalH = segs * h;\n` +
- ` var base = columnCubics(0, 1, amp, h, segs), out = "", kMax = Math.ceil(W / S) + 1;\n` +
+ ` var S = Math.round(P.spacing), cycles = Math.ceil(Hh / wl) + 1, totalH = cycles * wl;\n` +
+ ` var base = columnCubics(0, 1, amp, wl, cycles), out = "", kMax = Math.ceil(W / S) + 1;\n` +
` for (var k = -1; k < kMax; k++) {\n` +
` var cxL = k * S + S / 2, cxR = cxL + S;\n` +
` var d = stripPath(shift(base, cxL), shift(base, cxR), cxL, cxR, totalH);\n` +
diff --git a/dist/tw-fade.css b/dist/tw-fade.css
index a8573de..4bf11f5 100644
--- a/dist/tw-fade.css
+++ b/dist/tw-fade.css
@@ -1,761 +1,194 @@
/*! tw-fade — framework-free build for plain HTML / CDN.
* Generated from src/tw-fade.css; do not edit by hand. */
@layer properties;
-.fade-xy {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
-}
-.fade-x {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
-}
-.fade-y {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
-}
-.fade-b {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
-}
-.fade-l {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
-}
-.fade-r {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
-}
-.fade-t {
- mask-image: var(--tw-fade-mask-t, linear-gradient(#000, #000)), var(--tw-fade-mask-b, linear-gradient(#000, #000)), var(--tw-fade-mask-l, linear-gradient(#000, #000)), var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
- @supports (animation-timeline: scroll()) {
- animation: tw-fade-reveal-t auto linear both, tw-fade-reveal-b auto linear both, tw-fade-reveal-l auto linear both, tw-fade-reveal-r auto linear both;
- animation-timeline: scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range: 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%, 0 var(--tw-fade-range-active), calc(100% - var(--tw-fade-range-active)) 100%;
- }
- @supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
- }
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
-}
-.fade-static {
- --tw-fade-t: 1 !important;
- --tw-fade-b: 1 !important;
- --tw-fade-l: 1 !important;
- --tw-fade-r: 1 !important;
- animation-name: none;
-}
-.fade-clear-xy-2xl {
- --tw-fade-clear-t: var(--fade-clear-2xl);
- --tw-fade-clear-b: var(--fade-clear-2xl);
- --tw-fade-clear-l: var(--fade-clear-2xl);
- --tw-fade-clear-r: var(--fade-clear-2xl);
-}
-.fade-clear-xy-3xl {
- --tw-fade-clear-t: var(--fade-clear-3xl);
- --tw-fade-clear-b: var(--fade-clear-3xl);
- --tw-fade-clear-l: var(--fade-clear-3xl);
- --tw-fade-clear-r: var(--fade-clear-3xl);
-}
-.fade-clear-xy-4xl {
- --tw-fade-clear-t: var(--fade-clear-4xl);
- --tw-fade-clear-b: var(--fade-clear-4xl);
- --tw-fade-clear-l: var(--fade-clear-4xl);
- --tw-fade-clear-r: var(--fade-clear-4xl);
-}
-.fade-clear-xy-lg {
- --tw-fade-clear-t: var(--fade-clear-lg);
- --tw-fade-clear-b: var(--fade-clear-lg);
- --tw-fade-clear-l: var(--fade-clear-lg);
- --tw-fade-clear-r: var(--fade-clear-lg);
-}
-.fade-clear-xy-md {
- --tw-fade-clear-t: var(--fade-clear-md);
- --tw-fade-clear-b: var(--fade-clear-md);
- --tw-fade-clear-l: var(--fade-clear-md);
- --tw-fade-clear-r: var(--fade-clear-md);
-}
-.fade-clear-xy-sm {
- --tw-fade-clear-t: var(--fade-clear-sm);
- --tw-fade-clear-b: var(--fade-clear-sm);
- --tw-fade-clear-l: var(--fade-clear-sm);
- --tw-fade-clear-r: var(--fade-clear-sm);
-}
-.fade-clear-xy-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
-}
-.fade-clear-xy-xl {
- --tw-fade-clear-t: var(--fade-clear-xl);
- --tw-fade-clear-b: var(--fade-clear-xl);
- --tw-fade-clear-l: var(--fade-clear-xl);
- --tw-fade-clear-r: var(--fade-clear-xl);
-}
-.fade-clear-xy-xs {
- --tw-fade-clear-t: var(--fade-clear-xs);
- --tw-fade-clear-b: var(--fade-clear-xs);
- --tw-fade-clear-l: var(--fade-clear-xs);
- --tw-fade-clear-r: var(--fade-clear-xs);
+.fade-clear-2xl {
+ --tw-fade-clear: var(--fade-clear-2xl);
}
-.fade-clear-x-2xl {
- --tw-fade-clear-l: var(--fade-clear-2xl);
- --tw-fade-clear-r: var(--fade-clear-2xl);
+.fade-clear-3xl {
+ --tw-fade-clear: var(--fade-clear-3xl);
}
-.fade-clear-x-3xl {
- --tw-fade-clear-l: var(--fade-clear-3xl);
- --tw-fade-clear-r: var(--fade-clear-3xl);
+.fade-clear-4xl {
+ --tw-fade-clear: var(--fade-clear-4xl);
}
-.fade-clear-x-4xl {
- --tw-fade-clear-l: var(--fade-clear-4xl);
- --tw-fade-clear-r: var(--fade-clear-4xl);
+.fade-clear-bottom-2xl {
+ --tw-fade-clear-bottom: var(--fade-clear-2xl);
}
-.fade-clear-x-lg {
- --tw-fade-clear-l: var(--fade-clear-lg);
- --tw-fade-clear-r: var(--fade-clear-lg);
+.fade-clear-bottom-3xl {
+ --tw-fade-clear-bottom: var(--fade-clear-3xl);
}
-.fade-clear-x-md {
- --tw-fade-clear-l: var(--fade-clear-md);
- --tw-fade-clear-r: var(--fade-clear-md);
+.fade-clear-bottom-4xl {
+ --tw-fade-clear-bottom: var(--fade-clear-4xl);
}
-.fade-clear-x-sm {
- --tw-fade-clear-l: var(--fade-clear-sm);
- --tw-fade-clear-r: var(--fade-clear-sm);
+.fade-clear-bottom-lg {
+ --tw-fade-clear-bottom: var(--fade-clear-lg);
}
-.fade-clear-x-var {
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+.fade-clear-bottom-md {
+ --tw-fade-clear-bottom: var(--fade-clear-md);
}
-.fade-clear-x-xl {
- --tw-fade-clear-l: var(--fade-clear-xl);
- --tw-fade-clear-r: var(--fade-clear-xl);
+.fade-clear-bottom-sm {
+ --tw-fade-clear-bottom: var(--fade-clear-sm);
}
-.fade-clear-x-xs {
- --tw-fade-clear-l: var(--fade-clear-xs);
- --tw-fade-clear-r: var(--fade-clear-xs);
+.fade-clear-bottom-var {
+ --tw-fade-clear-bottom: var(--fade-clear-bottom, var(--fade-clear-y, var(--fade-clear, 0px)));
}
-.fade-clear-y-2xl {
- --tw-fade-clear-t: var(--fade-clear-2xl);
- --tw-fade-clear-b: var(--fade-clear-2xl);
+.fade-clear-bottom-xl {
+ --tw-fade-clear-bottom: var(--fade-clear-xl);
}
-.fade-clear-y-3xl {
- --tw-fade-clear-t: var(--fade-clear-3xl);
- --tw-fade-clear-b: var(--fade-clear-3xl);
+.fade-clear-bottom-xs {
+ --tw-fade-clear-bottom: var(--fade-clear-xs);
}
-.fade-clear-y-4xl {
- --tw-fade-clear-t: var(--fade-clear-4xl);
- --tw-fade-clear-b: var(--fade-clear-4xl);
+.fade-clear-end-2xl {
+ --tw-fade-clear-end: var(--fade-clear-2xl);
}
-.fade-clear-y-lg {
- --tw-fade-clear-t: var(--fade-clear-lg);
- --tw-fade-clear-b: var(--fade-clear-lg);
+.fade-clear-end-3xl {
+ --tw-fade-clear-end: var(--fade-clear-3xl);
}
-.fade-clear-y-md {
- --tw-fade-clear-t: var(--fade-clear-md);
- --tw-fade-clear-b: var(--fade-clear-md);
+.fade-clear-end-4xl {
+ --tw-fade-clear-end: var(--fade-clear-4xl);
}
-.fade-clear-y-sm {
- --tw-fade-clear-t: var(--fade-clear-sm);
- --tw-fade-clear-b: var(--fade-clear-sm);
+.fade-clear-end-lg {
+ --tw-fade-clear-end: var(--fade-clear-lg);
}
-.fade-clear-y-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+.fade-clear-end-md {
+ --tw-fade-clear-end: var(--fade-clear-md);
}
-.fade-clear-y-xl {
- --tw-fade-clear-t: var(--fade-clear-xl);
- --tw-fade-clear-b: var(--fade-clear-xl);
+.fade-clear-end-sm {
+ --tw-fade-clear-end: var(--fade-clear-sm);
}
-.fade-clear-y-xs {
- --tw-fade-clear-t: var(--fade-clear-xs);
- --tw-fade-clear-b: var(--fade-clear-xs);
+.fade-clear-end-var {
+ --tw-fade-clear-end: var(--fade-clear-end, var(--fade-clear-x, var(--fade-clear, 0px)));
}
-.fade-clear-b-2xl {
- --tw-fade-clear-b: var(--fade-clear-2xl);
+.fade-clear-end-xl {
+ --tw-fade-clear-end: var(--fade-clear-xl);
}
-.fade-clear-b-3xl {
- --tw-fade-clear-b: var(--fade-clear-3xl);
+.fade-clear-end-xs {
+ --tw-fade-clear-end: var(--fade-clear-xs);
}
-.fade-clear-b-4xl {
- --tw-fade-clear-b: var(--fade-clear-4xl);
+.fade-clear-lg {
+ --tw-fade-clear: var(--fade-clear-lg);
}
-.fade-clear-b-lg {
- --tw-fade-clear-b: var(--fade-clear-lg);
+.fade-clear-md {
+ --tw-fade-clear: var(--fade-clear-md);
}
-.fade-clear-b-md {
- --tw-fade-clear-b: var(--fade-clear-md);
+.fade-clear-sm {
+ --tw-fade-clear: var(--fade-clear-sm);
}
-.fade-clear-b-sm {
- --tw-fade-clear-b: var(--fade-clear-sm);
+.fade-clear-start-2xl {
+ --tw-fade-clear-start: var(--fade-clear-2xl);
}
-.fade-clear-b-var {
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+.fade-clear-start-3xl {
+ --tw-fade-clear-start: var(--fade-clear-3xl);
}
-.fade-clear-b-xl {
- --tw-fade-clear-b: var(--fade-clear-xl);
+.fade-clear-start-4xl {
+ --tw-fade-clear-start: var(--fade-clear-4xl);
}
-.fade-clear-b-xs {
- --tw-fade-clear-b: var(--fade-clear-xs);
+.fade-clear-start-lg {
+ --tw-fade-clear-start: var(--fade-clear-lg);
}
-.fade-clear-l-2xl {
- --tw-fade-clear-l: var(--fade-clear-2xl);
+.fade-clear-start-md {
+ --tw-fade-clear-start: var(--fade-clear-md);
}
-.fade-clear-l-3xl {
- --tw-fade-clear-l: var(--fade-clear-3xl);
+.fade-clear-start-sm {
+ --tw-fade-clear-start: var(--fade-clear-sm);
}
-.fade-clear-l-4xl {
- --tw-fade-clear-l: var(--fade-clear-4xl);
+.fade-clear-start-var {
+ --tw-fade-clear-start: var(--fade-clear-start, var(--fade-clear-x, var(--fade-clear, 0px)));
}
-.fade-clear-l-lg {
- --tw-fade-clear-l: var(--fade-clear-lg);
+.fade-clear-start-xl {
+ --tw-fade-clear-start: var(--fade-clear-xl);
}
-.fade-clear-l-md {
- --tw-fade-clear-l: var(--fade-clear-md);
+.fade-clear-start-xs {
+ --tw-fade-clear-start: var(--fade-clear-xs);
}
-.fade-clear-l-sm {
- --tw-fade-clear-l: var(--fade-clear-sm);
+.fade-clear-top-2xl {
+ --tw-fade-clear-top: var(--fade-clear-2xl);
}
-.fade-clear-l-var {
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+.fade-clear-top-3xl {
+ --tw-fade-clear-top: var(--fade-clear-3xl);
}
-.fade-clear-l-xl {
- --tw-fade-clear-l: var(--fade-clear-xl);
+.fade-clear-top-4xl {
+ --tw-fade-clear-top: var(--fade-clear-4xl);
}
-.fade-clear-l-xs {
- --tw-fade-clear-l: var(--fade-clear-xs);
+.fade-clear-top-lg {
+ --tw-fade-clear-top: var(--fade-clear-lg);
}
-.fade-clear-r-2xl {
- --tw-fade-clear-r: var(--fade-clear-2xl);
+.fade-clear-top-md {
+ --tw-fade-clear-top: var(--fade-clear-md);
}
-.fade-clear-r-3xl {
- --tw-fade-clear-r: var(--fade-clear-3xl);
+.fade-clear-top-sm {
+ --tw-fade-clear-top: var(--fade-clear-sm);
}
-.fade-clear-r-4xl {
- --tw-fade-clear-r: var(--fade-clear-4xl);
+.fade-clear-top-var {
+ --tw-fade-clear-top: var(--fade-clear-top, var(--fade-clear-y, var(--fade-clear, 0px)));
}
-.fade-clear-r-lg {
- --tw-fade-clear-r: var(--fade-clear-lg);
+.fade-clear-top-xl {
+ --tw-fade-clear-top: var(--fade-clear-xl);
}
-.fade-clear-r-md {
- --tw-fade-clear-r: var(--fade-clear-md);
+.fade-clear-top-xs {
+ --tw-fade-clear-top: var(--fade-clear-xs);
}
-.fade-clear-r-sm {
- --tw-fade-clear-r: var(--fade-clear-sm);
+.fade-clear-var {
+ --tw-fade-clear: var(--fade-clear, 0px);
}
-.fade-clear-r-var {
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+.fade-clear-x-2xl {
+ --tw-fade-clear-x: var(--fade-clear-2xl);
}
-.fade-clear-r-xl {
- --tw-fade-clear-r: var(--fade-clear-xl);
+.fade-clear-x-3xl {
+ --tw-fade-clear-x: var(--fade-clear-3xl);
}
-.fade-clear-r-xs {
- --tw-fade-clear-r: var(--fade-clear-xs);
+.fade-clear-x-4xl {
+ --tw-fade-clear-x: var(--fade-clear-4xl);
}
-.fade-clear-t-2xl {
- --tw-fade-clear-t: var(--fade-clear-2xl);
+.fade-clear-x-lg {
+ --tw-fade-clear-x: var(--fade-clear-lg);
}
-.fade-clear-t-3xl {
- --tw-fade-clear-t: var(--fade-clear-3xl);
+.fade-clear-x-md {
+ --tw-fade-clear-x: var(--fade-clear-md);
}
-.fade-clear-t-4xl {
- --tw-fade-clear-t: var(--fade-clear-4xl);
+.fade-clear-x-sm {
+ --tw-fade-clear-x: var(--fade-clear-sm);
}
-.fade-clear-t-lg {
- --tw-fade-clear-t: var(--fade-clear-lg);
+.fade-clear-x-var {
+ --tw-fade-clear-x: var(--fade-clear-x, var(--fade-clear, 0px));
}
-.fade-clear-t-md {
- --tw-fade-clear-t: var(--fade-clear-md);
+.fade-clear-x-xl {
+ --tw-fade-clear-x: var(--fade-clear-xl);
}
-.fade-clear-t-sm {
- --tw-fade-clear-t: var(--fade-clear-sm);
+.fade-clear-x-xs {
+ --tw-fade-clear-x: var(--fade-clear-xs);
}
-.fade-clear-t-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+.fade-clear-xl {
+ --tw-fade-clear: var(--fade-clear-xl);
}
-.fade-clear-t-xl {
- --tw-fade-clear-t: var(--fade-clear-xl);
+.fade-clear-xs {
+ --tw-fade-clear: var(--fade-clear-xs);
}
-.fade-clear-t-xs {
- --tw-fade-clear-t: var(--fade-clear-xs);
+.fade-clear-y-2xl {
+ --tw-fade-clear-y: var(--fade-clear-2xl);
}
-.fade-range-2xl {
- --tw-fade-range: var(--fade-range-2xl);
+.fade-clear-y-3xl {
+ --tw-fade-clear-y: var(--fade-clear-3xl);
}
-.fade-range-3xl {
- --tw-fade-range: var(--fade-range-3xl);
+.fade-clear-y-4xl {
+ --tw-fade-clear-y: var(--fade-clear-4xl);
}
-.fade-range-4xl {
- --tw-fade-range: var(--fade-range-4xl);
+.fade-clear-y-lg {
+ --tw-fade-clear-y: var(--fade-clear-lg);
}
-.fade-range-lg {
- --tw-fade-range: var(--fade-range-lg);
+.fade-clear-y-md {
+ --tw-fade-clear-y: var(--fade-clear-md);
}
-.fade-range-md {
- --tw-fade-range: var(--fade-range-md);
+.fade-clear-y-sm {
+ --tw-fade-clear-y: var(--fade-clear-sm);
}
-.fade-range-sm {
- --tw-fade-range: var(--fade-range-sm);
+.fade-clear-y-var {
+ --tw-fade-clear-y: var(--fade-clear-y, var(--fade-clear, 0px));
}
-.fade-range-xl {
- --tw-fade-range: var(--fade-range-xl);
+.fade-clear-y-xl {
+ --tw-fade-clear-y: var(--fade-clear-xl);
}
-.fade-range-xs {
- --tw-fade-range: var(--fade-range-xs);
+.fade-clear-y-xs {
+ --tw-fade-clear-y: var(--fade-clear-xs);
}
.fade-size-2xl {
--tw-fade-size: var(--fade-size-2xl);
@@ -766,53 +199,53 @@
.fade-size-4xl {
--tw-fade-size: var(--fade-size-4xl);
}
-.fade-size-b-2xl {
- --tw-fade-size-b: var(--fade-size-2xl);
+.fade-size-bottom-2xl {
+ --tw-fade-size-bottom: var(--fade-size-2xl);
}
-.fade-size-b-3xl {
- --tw-fade-size-b: var(--fade-size-3xl);
+.fade-size-bottom-3xl {
+ --tw-fade-size-bottom: var(--fade-size-3xl);
}
-.fade-size-b-4xl {
- --tw-fade-size-b: var(--fade-size-4xl);
+.fade-size-bottom-4xl {
+ --tw-fade-size-bottom: var(--fade-size-4xl);
}
-.fade-size-b-lg {
- --tw-fade-size-b: var(--fade-size-lg);
+.fade-size-bottom-lg {
+ --tw-fade-size-bottom: var(--fade-size-lg);
}
-.fade-size-b-md {
- --tw-fade-size-b: var(--fade-size-md);
+.fade-size-bottom-md {
+ --tw-fade-size-bottom: var(--fade-size-md);
}
-.fade-size-b-sm {
- --tw-fade-size-b: var(--fade-size-sm);
+.fade-size-bottom-sm {
+ --tw-fade-size-bottom: var(--fade-size-sm);
}
-.fade-size-b-xl {
- --tw-fade-size-b: var(--fade-size-xl);
+.fade-size-bottom-xl {
+ --tw-fade-size-bottom: var(--fade-size-xl);
}
-.fade-size-b-xs {
- --tw-fade-size-b: var(--fade-size-xs);
+.fade-size-bottom-xs {
+ --tw-fade-size-bottom: var(--fade-size-xs);
}
-.fade-size-l-2xl {
- --tw-fade-size-l: var(--fade-size-2xl);
+.fade-size-end-2xl {
+ --tw-fade-size-end: var(--fade-size-2xl);
}
-.fade-size-l-3xl {
- --tw-fade-size-l: var(--fade-size-3xl);
+.fade-size-end-3xl {
+ --tw-fade-size-end: var(--fade-size-3xl);
}
-.fade-size-l-4xl {
- --tw-fade-size-l: var(--fade-size-4xl);
+.fade-size-end-4xl {
+ --tw-fade-size-end: var(--fade-size-4xl);
}
-.fade-size-l-lg {
- --tw-fade-size-l: var(--fade-size-lg);
+.fade-size-end-lg {
+ --tw-fade-size-end: var(--fade-size-lg);
}
-.fade-size-l-md {
- --tw-fade-size-l: var(--fade-size-md);
+.fade-size-end-md {
+ --tw-fade-size-end: var(--fade-size-md);
}
-.fade-size-l-sm {
- --tw-fade-size-l: var(--fade-size-sm);
+.fade-size-end-sm {
+ --tw-fade-size-end: var(--fade-size-sm);
}
-.fade-size-l-xl {
- --tw-fade-size-l: var(--fade-size-xl);
+.fade-size-end-xl {
+ --tw-fade-size-end: var(--fade-size-xl);
}
-.fade-size-l-xs {
- --tw-fade-size-l: var(--fade-size-xs);
+.fade-size-end-xs {
+ --tw-fade-size-end: var(--fade-size-xs);
}
.fade-size-lg {
--tw-fade-size: var(--fade-size-lg);
@@ -820,56 +253,56 @@
.fade-size-md {
--tw-fade-size: var(--fade-size-md);
}
-.fade-size-r-2xl {
- --tw-fade-size-r: var(--fade-size-2xl);
+.fade-size-sm {
+ --tw-fade-size: var(--fade-size-sm);
}
-.fade-size-r-3xl {
- --tw-fade-size-r: var(--fade-size-3xl);
+.fade-size-start-2xl {
+ --tw-fade-size-start: var(--fade-size-2xl);
}
-.fade-size-r-4xl {
- --tw-fade-size-r: var(--fade-size-4xl);
+.fade-size-start-3xl {
+ --tw-fade-size-start: var(--fade-size-3xl);
}
-.fade-size-r-lg {
- --tw-fade-size-r: var(--fade-size-lg);
+.fade-size-start-4xl {
+ --tw-fade-size-start: var(--fade-size-4xl);
}
-.fade-size-r-md {
- --tw-fade-size-r: var(--fade-size-md);
+.fade-size-start-lg {
+ --tw-fade-size-start: var(--fade-size-lg);
}
-.fade-size-r-sm {
- --tw-fade-size-r: var(--fade-size-sm);
+.fade-size-start-md {
+ --tw-fade-size-start: var(--fade-size-md);
}
-.fade-size-r-xl {
- --tw-fade-size-r: var(--fade-size-xl);
+.fade-size-start-sm {
+ --tw-fade-size-start: var(--fade-size-sm);
}
-.fade-size-r-xs {
- --tw-fade-size-r: var(--fade-size-xs);
+.fade-size-start-xl {
+ --tw-fade-size-start: var(--fade-size-xl);
}
-.fade-size-sm {
- --tw-fade-size: var(--fade-size-sm);
+.fade-size-start-xs {
+ --tw-fade-size-start: var(--fade-size-xs);
}
-.fade-size-t-2xl {
- --tw-fade-size-t: var(--fade-size-2xl);
+.fade-size-top-2xl {
+ --tw-fade-size-top: var(--fade-size-2xl);
}
-.fade-size-t-3xl {
- --tw-fade-size-t: var(--fade-size-3xl);
+.fade-size-top-3xl {
+ --tw-fade-size-top: var(--fade-size-3xl);
}
-.fade-size-t-4xl {
- --tw-fade-size-t: var(--fade-size-4xl);
+.fade-size-top-4xl {
+ --tw-fade-size-top: var(--fade-size-4xl);
}
-.fade-size-t-lg {
- --tw-fade-size-t: var(--fade-size-lg);
+.fade-size-top-lg {
+ --tw-fade-size-top: var(--fade-size-lg);
}
-.fade-size-t-md {
- --tw-fade-size-t: var(--fade-size-md);
+.fade-size-top-md {
+ --tw-fade-size-top: var(--fade-size-md);
}
-.fade-size-t-sm {
- --tw-fade-size-t: var(--fade-size-sm);
+.fade-size-top-sm {
+ --tw-fade-size-top: var(--fade-size-sm);
}
-.fade-size-t-xl {
- --tw-fade-size-t: var(--fade-size-xl);
+.fade-size-top-xl {
+ --tw-fade-size-top: var(--fade-size-xl);
}
-.fade-size-t-xs {
- --tw-fade-size-t: var(--fade-size-xs);
+.fade-size-top-xs {
+ --tw-fade-size-top: var(--fade-size-xs);
}
.fade-size-x-2xl {
--tw-fade-size-x: var(--fade-size-2xl);
@@ -925,6 +358,30 @@
.fade-size-y-xs {
--tw-fade-size-y: var(--fade-size-xs);
}
+.fade-travel-2xl {
+ --tw-fade-travel: var(--fade-travel-2xl);
+}
+.fade-travel-3xl {
+ --tw-fade-travel: var(--fade-travel-3xl);
+}
+.fade-travel-4xl {
+ --tw-fade-travel: var(--fade-travel-4xl);
+}
+.fade-travel-lg {
+ --tw-fade-travel: var(--fade-travel-lg);
+}
+.fade-travel-md {
+ --tw-fade-travel: var(--fade-travel-md);
+}
+.fade-travel-sm {
+ --tw-fade-travel: var(--fade-travel-sm);
+}
+.fade-travel-xl {
+ --tw-fade-travel: var(--fade-travel-xl);
+}
+.fade-travel-xs {
+ --tw-fade-travel: var(--fade-travel-xs);
+}
@property --tw-fade-t {
syntax: "";
inherits: false;
@@ -957,39 +414,51 @@
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-t {
+@property --tw-fade-size-top {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-size-bottom {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-size-start {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-size-end {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-b {
+@property --tw-fade-travel {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-l {
+@property --tw-fade-clear {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-r {
+@property --tw-fade-clear-y {
syntax: "*";
inherits: false;
}
-@property --tw-fade-range {
+@property --tw-fade-clear-x {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-t {
+@property --tw-fade-clear-top {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-b {
+@property --tw-fade-clear-bottom {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-l {
+@property --tw-fade-clear-start {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-r {
+@property --tw-fade-clear-end {
syntax: "*";
inherits: false;
}
@@ -1009,6 +478,70 @@
syntax: "*";
inherits: false;
}
+@property --tw-fade-ltr-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
:root, :host {
--fade-size-xs: calc(var(--spacing, 0.25rem) * 6);
--fade-size-sm: calc(var(--spacing, 0.25rem) * 8);
@@ -1018,14 +551,14 @@
--fade-size-2xl: calc(var(--spacing, 0.25rem) * 24);
--fade-size-3xl: calc(var(--spacing, 0.25rem) * 32);
--fade-size-4xl: calc(var(--spacing, 0.25rem) * 40);
- --fade-range-xs: calc(var(--spacing, 0.25rem) * 6);
- --fade-range-sm: calc(var(--spacing, 0.25rem) * 8);
- --fade-range-md: calc(var(--spacing, 0.25rem) * 12);
- --fade-range-lg: calc(var(--spacing, 0.25rem) * 16);
- --fade-range-xl: calc(var(--spacing, 0.25rem) * 20);
- --fade-range-2xl: calc(var(--spacing, 0.25rem) * 24);
- --fade-range-3xl: calc(var(--spacing, 0.25rem) * 32);
- --fade-range-4xl: calc(var(--spacing, 0.25rem) * 40);
+ --fade-travel-xs: calc(var(--spacing, 0.25rem) * 6);
+ --fade-travel-sm: calc(var(--spacing, 0.25rem) * 8);
+ --fade-travel-md: calc(var(--spacing, 0.25rem) * 12);
+ --fade-travel-lg: calc(var(--spacing, 0.25rem) * 16);
+ --fade-travel-xl: calc(var(--spacing, 0.25rem) * 20);
+ --fade-travel-2xl: calc(var(--spacing, 0.25rem) * 24);
+ --fade-travel-3xl: calc(var(--spacing, 0.25rem) * 32);
+ --fade-travel-4xl: calc(var(--spacing, 0.25rem) * 40);
--fade-clear-xs: calc(var(--spacing, 0.25rem) * 6);
--fade-clear-sm: calc(var(--spacing, 0.25rem) * 8);
--fade-clear-md: calc(var(--spacing, 0.25rem) * 12);
@@ -1035,7 +568,7 @@
--fade-clear-3xl: calc(var(--spacing, 0.25rem) * 32);
--fade-clear-4xl: calc(var(--spacing, 0.25rem) * 40);
}
-@keyframes tw-fade-reveal-t {
+@keyframes tw-fade-travel-t {
from {
--tw-fade-t: 0;
}
@@ -1043,7 +576,7 @@
--tw-fade-t: 1;
}
}
-@keyframes tw-fade-reveal-b {
+@keyframes tw-fade-travel-b {
from {
--tw-fade-b: 1;
}
@@ -1051,7 +584,7 @@
--tw-fade-b: 0;
}
}
-@keyframes tw-fade-reveal-l {
+@keyframes tw-fade-travel-l {
from {
--tw-fade-l: 0;
}
@@ -1059,7 +592,7 @@
--tw-fade-l: 1;
}
}
-@keyframes tw-fade-reveal-r {
+@keyframes tw-fade-travel-r {
from {
--tw-fade-r: 1;
}
@@ -1067,10 +600,263 @@
--tw-fade-r: 0;
}
}
+@keyframes tw-fade-travel-r-leading {
+ from {
+ --tw-fade-r: 0;
+ }
+ to {
+ --tw-fade-r: 1;
+ }
+}
+@keyframes tw-fade-travel-l-trailing {
+ from {
+ --tw-fade-l: 1;
+ }
+ to {
+ --tw-fade-l: 0;
+ }
+}
@layer utilities {
- .fade-t, .fade-b, .fade-l, .fade-r, .fade-y, .fade-x, .fade-xy {
- --tw-fade-size-default: var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12));
- --tw-fade-range-active: var(--tw-fade-range, var(--fade-range-md, calc(var(--spacing, 0.25rem) * 12)));
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ --tw-fade-size-default: min(12%, var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12)));
+ --tw-fade-travel-active: var(--tw-fade-travel, var(--fade-travel-sm, calc(var(--spacing, 0.25rem) * 8)));
+ --tw-fade-identity-mask: linear-gradient(#000, #000);
+ --tw-fade-edge-size-t: var(--tw-fade-size-top, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-b: var(--tw-fade-size-bottom, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-l: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-t: var(--tw-fade-clear-top, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-b: var(--tw-fade-clear-bottom, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
+ --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
+ --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
+ --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
+ --tw-fade-onset: 8;
+ --tw-fade-alpha-t: min(1, calc(var(--tw-fade-t) * var(--tw-fade-onset)));
+ --tw-fade-alpha-b: min(1, calc(var(--tw-fade-b) * var(--tw-fade-onset)));
+ --tw-fade-alpha-l: min(1, calc(var(--tw-fade-l) * var(--tw-fade-onset)));
+ --tw-fade-alpha-r: min(1, calc(var(--tw-fade-r) * var(--tw-fade-onset)));
+ --tw-fade-gradient-t: linear-gradient(
+ to bottom,
+ #000 0 var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t))) var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.983))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.933))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.854))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.75))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.629))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.5))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.371))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.25))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.146))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.067))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.017))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
+ );
+ --tw-fade-gradient-b: linear-gradient(
+ to top,
+ #000 0 var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b))) var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.983))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.933))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.854))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.75))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.629))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.5))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.371))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.25))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.146))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.067))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.017))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
+ );
+ --tw-fade-gradient-l: linear-gradient(
+ to right,
+ #000 0 var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l))) var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.983))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.933))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.854))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.75))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.629))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.5))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.371))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.25))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.146))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.067))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.017))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
+ );
+ --tw-fade-gradient-r: linear-gradient(
+ to left,
+ #000 0 var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r))) var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.983))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.933))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.854))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.75))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.629))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.5))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.371))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.25))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.146))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.067))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.017))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
+ );
+ --tw-fade-mask-l: var(--tw-fade-ltr-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-ltr-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-ltr-start-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-ltr-end-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-ltr-start-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-ltr-end-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-ltr-start-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-ltr-end-animation-range, normal);
+ --tw-fade-animation-t: none;
+ --tw-fade-animation-b: none;
+ --tw-fade-timeline-t: none;
+ --tw-fade-timeline-b: none;
+ --tw-fade-animation-range-t: normal;
+ --tw-fade-animation-range-b: normal;
+ mask-image: var(--tw-fade-mask-t, var(--tw-fade-identity-mask)), var(--tw-fade-mask-b, var(--tw-fade-identity-mask)), var(--tw-fade-mask-l, var(--tw-fade-identity-mask)), var(--tw-fade-mask-r, var(--tw-fade-identity-mask));
+ mask-composite: intersect;
+ mask-repeat: no-repeat;
+ mask-size: 100% 100%;
+ }
+ .fade:where(:dir(rtl)), .fade-y:where(:dir(rtl)), .fade-top:where(:dir(rtl)), .fade-bottom:where(:dir(rtl)), .fade-x:where(:dir(rtl)), .fade-start:where(:dir(rtl)), .fade-end:where(:dir(rtl)) {
+ --tw-fade-edge-size-l: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-mask-l: var(--tw-fade-rtl-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-rtl-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-rtl-end-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-rtl-start-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-rtl-end-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-rtl-start-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-rtl-end-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-rtl-start-animation-range, normal);
+ }
+ .fade, .fade-y, .fade-top {
+ --tw-fade-mask-t: var(--tw-fade-gradient-t);
+ --tw-fade-animation-t: tw-fade-travel-t;
+ --tw-fade-timeline-t: scroll(self y);
+ --tw-fade-animation-range-t: 0 var(--tw-fade-travel-active);
+ }
+ .fade, .fade-y, .fade-bottom {
+ --tw-fade-mask-b: var(--tw-fade-gradient-b);
+ --tw-fade-animation-b: tw-fade-travel-b;
+ --tw-fade-timeline-b: scroll(self y);
+ --tw-fade-animation-range-b: calc(100% - var(--tw-fade-travel-active)) 100%;
+ }
+ .fade, .fade-x, .fade-start {
+ --tw-fade-ltr-start-layer: var(--tw-fade-gradient-l);
+ --tw-fade-rtl-start-layer: var(--tw-fade-gradient-r);
+ --tw-fade-ltr-start-animation: tw-fade-travel-l;
+ --tw-fade-rtl-start-animation: tw-fade-travel-r-leading;
+ --tw-fade-ltr-start-timeline: scroll(self inline);
+ --tw-fade-rtl-start-timeline: scroll(self inline);
+ --tw-fade-ltr-start-animation-range: 0 var(--tw-fade-travel-active);
+ --tw-fade-rtl-start-animation-range: 0 var(--tw-fade-travel-active);
+ }
+ .fade, .fade-x, .fade-end {
+ --tw-fade-ltr-end-layer: var(--tw-fade-gradient-r);
+ --tw-fade-rtl-end-layer: var(--tw-fade-gradient-l);
+ --tw-fade-ltr-end-animation: tw-fade-travel-r;
+ --tw-fade-rtl-end-animation: tw-fade-travel-l-trailing;
+ --tw-fade-ltr-end-timeline: scroll(self inline);
+ --tw-fade-rtl-end-timeline: scroll(self inline);
+ --tw-fade-ltr-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
+ --tw-fade-rtl-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
+ }
+ @supports (animation-timeline: scroll()) {
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ animation: var(--tw-fade-animation-t, none) auto linear both, var(--tw-fade-animation-b, none) auto linear both, var(--tw-fade-animation-l, none) auto linear both, var(--tw-fade-animation-r, none) auto linear both;
+ animation-timeline: var(--tw-fade-timeline-t, none), var(--tw-fade-timeline-b, none), var(--tw-fade-timeline-l, none), var(--tw-fade-timeline-r, none);
+ animation-range: var(--tw-fade-animation-range-t, normal), var(--tw-fade-animation-range-b, normal), var(--tw-fade-animation-range-l, normal), var(--tw-fade-animation-range-r, normal);
+ }
+ }
+ @supports not (animation-timeline: scroll()) {
+ .fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end {
+ --tw-fade-t: 1;
+ --tw-fade-b: 1;
+ --tw-fade-l: 1;
+ --tw-fade-r: 1;
+ }
+ }
+ .fade-none {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+ .fade-none-y {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ }
+ .fade-none-x {
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+ .fade-always {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
+ }
+ .fade-always-y {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ }
+ .fade-always-x {
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
}
}
@layer properties {
@@ -1083,19 +869,38 @@
--tw-fade-size: initial;
--tw-fade-size-y: initial;
--tw-fade-size-x: initial;
- --tw-fade-size-t: initial;
- --tw-fade-size-b: initial;
- --tw-fade-size-l: initial;
- --tw-fade-size-r: initial;
- --tw-fade-range: initial;
- --tw-fade-clear-t: initial;
- --tw-fade-clear-b: initial;
- --tw-fade-clear-l: initial;
- --tw-fade-clear-r: initial;
+ --tw-fade-size-top: initial;
+ --tw-fade-size-bottom: initial;
+ --tw-fade-size-start: initial;
+ --tw-fade-size-end: initial;
+ --tw-fade-travel: initial;
+ --tw-fade-clear: initial;
+ --tw-fade-clear-y: initial;
+ --tw-fade-clear-x: initial;
+ --tw-fade-clear-top: initial;
+ --tw-fade-clear-bottom: initial;
+ --tw-fade-clear-start: initial;
+ --tw-fade-clear-end: initial;
--tw-fade-mask-t: initial;
--tw-fade-mask-b: initial;
--tw-fade-mask-l: initial;
--tw-fade-mask-r: initial;
+ --tw-fade-ltr-start-layer: initial;
+ --tw-fade-ltr-end-layer: initial;
+ --tw-fade-rtl-start-layer: initial;
+ --tw-fade-rtl-end-layer: initial;
+ --tw-fade-ltr-start-animation: initial;
+ --tw-fade-ltr-end-animation: initial;
+ --tw-fade-rtl-start-animation: initial;
+ --tw-fade-rtl-end-animation: initial;
+ --tw-fade-ltr-start-timeline: initial;
+ --tw-fade-ltr-end-timeline: initial;
+ --tw-fade-rtl-start-timeline: initial;
+ --tw-fade-rtl-end-timeline: initial;
+ --tw-fade-ltr-start-animation-range: initial;
+ --tw-fade-ltr-end-animation-range: initial;
+ --tw-fade-rtl-start-animation-range: initial;
+ --tw-fade-rtl-end-animation-range: initial;
}
}
}
diff --git a/package-lock.json b/package-lock.json
index 6ce7f57..a5f82c1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,17 +1,18 @@
{
"name": "tw-fade",
- "version": "0.6.0",
+ "version": "0.7.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "tw-fade",
- "version": "0.6.0",
+ "version": "0.7.0",
"license": "MIT",
"devDependencies": {
"@tailwindcss/cli": "^4.0.0",
"playwright": "^1.61.0",
- "tailwindcss": "^4.3.1"
+ "tailwindcss": "^4.3.1",
+ "tw-shimmer": "^0.4.11"
},
"peerDependencies": {
"tailwindcss": ">=4.0.0"
@@ -1224,6 +1225,16 @@
"engines": {
"node": ">=8.0"
}
+ },
+ "node_modules/tw-shimmer": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/tw-shimmer/-/tw-shimmer-0.4.11.tgz",
+ "integrity": "sha512-pTpGJzp3xaCPO87WeHETngmZHJYvygiSTt4jqzh2oR3DWBoeudi/ANB304zks9+Cm2vQ1ai3w9fetviYdqY8HQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=4.0.0-0"
+ }
}
}
}
diff --git a/package.json b/package.json
index 558f8a3..65c5c67 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "tw-fade",
- "version": "0.6.0",
- "description": "Elegant, CSS-driven scroll-edge fade masking for Tailwind CSS v4. Add fade-t/b/l/r (or -x/-y/-xy) to any scroll container to fade content into its surface at the edges — scroll-gated with zero JavaScript.",
+ "version": "0.7.0",
+ "description": "Elegant, CSS-driven scroll-edge fade masking for Tailwind CSS v4. Add fade-y, fade-x, fade-start, or fade-end to any scroll container to fade content into its surface at the edges — scroll-gated with zero JavaScript.",
"keywords": [
"tailwindcss",
"tailwind-plugin",
@@ -12,7 +12,11 @@
"scroll-driven-animations",
"scrim",
"edge-fade",
- "overflow"
+ "overflow",
+ "rtl",
+ "direction-aware",
+ "logical-properties",
+ "bidi"
],
"license": "MIT",
"author": "Pete Petrash",
@@ -35,17 +39,20 @@
"src",
"dist",
"README.md",
+ "MIGRATING.md",
+ "CHANGELOG.md",
"LICENSE"
],
"scripts": {
"build": "node scripts/build-css.mjs",
"build:demo": "tailwindcss -i demo/input.css -o demo/styles.css",
+ "debug": "node scripts/build-debug.mjs",
"export:demo": "node scripts/export-demo-static.mjs",
"ship-demo": "node scripts/ship-demo.mjs",
"generate:seo": "node scripts/generate-seo-assets.mjs",
"release": "node scripts/release.mjs",
"test": "node --test",
- "verify": "node build/verify.mjs && node build/verify-dist.mjs && node build/verify-fade.mjs && node build/verify-demo-assets.mjs && node build/verify-page.mjs && node build/verify-demo-runtime.mjs && node build/verify-favicon.mjs && node build/verify-seo.mjs",
+ "verify": "node build/verify.mjs && node build/verify-horizontal-rtl.mjs && node build/verify-dist.mjs && node build/verify-fade.mjs && node build/verify-demo-assets.mjs && node build/verify-page.mjs && node build/verify-demo-runtime.mjs && node build/verify-favicon.mjs && node build/verify-seo.mjs",
"prepublishOnly": "node scripts/build-css.mjs && node --test"
},
"peerDependencies": {
@@ -59,6 +66,7 @@
"devDependencies": {
"@tailwindcss/cli": "^4.0.0",
"playwright": "^1.61.0",
- "tailwindcss": "^4.3.1"
+ "tailwindcss": "^4.3.1",
+ "tw-shimmer": "^0.4.11"
}
}
diff --git a/scripts/build-css.mjs b/scripts/build-css.mjs
index 856528a..784c0a1 100644
--- a/scripts/build-css.mjs
+++ b/scripts/build-css.mjs
@@ -37,12 +37,12 @@ const src = path.join(root, 'src', 'tw-fade.css')
const outFile = path.join(root, 'dist', 'tw-fade.css')
// Every class the framework-free build should contain. Arbitrary values
-// (fade-size-[6rem], fade-range-[80px], fade-clear-t-[56px]) are intentionally
+// (fade-size-[6rem], fade-travel-[80px], fade-clear-top-[56px]) are intentionally
// absent — those require Tailwind's JIT and belong to the v4 source path, not
// the prebuilt drop-in.
const SCALE = 'xs,sm,md,lg,xl,2xl,3xl,4xl'
const CLASSES =
- `fade-{t,b,l,r,x,y,xy} fade-static fade-size-{${SCALE}} fade-size-{t,b,l,r,x,y}-{${SCALE}} fade-range-{${SCALE}} fade-clear-{t,b,l,r,x,y,xy}-{${SCALE},var}`
+ `fade fade-{x,y,top,bottom,start,end} fade-none fade-none-{x,y} fade-always fade-always-{x,y} fade-size-{${SCALE}} fade-size-{x,y,top,bottom,start,end}-{${SCALE}} fade-travel-{${SCALE}} fade-clear-{${SCALE},var} fade-clear-{x,y,top,bottom,start,end}-{${SCALE},var}`
const BANNER =
'/*! tw-fade — framework-free build for plain HTML / CDN.\n' +
diff --git a/scripts/build-debug.mjs b/scripts/build-debug.mjs
new file mode 100644
index 0000000..1860a17
--- /dev/null
+++ b/scripts/build-debug.mjs
@@ -0,0 +1,111 @@
+/**
+ * build-debug.mjs — assemble debug/index.html, a self-contained pressure-test
+ * harness for the fade engine.
+ *
+ * node scripts/build-debug.mjs
+ *
+ * It inlines three sources into one standalone file (open via file:// or any
+ * static server, no build step at view time):
+ * 1. the compiled plugin CSS (compileCss() — the SAME output dist/ ships, so
+ * the harness always reflects the real engine, every named utility present);
+ * 2. scripts/debug/harness.css — UI chrome;
+ * 3. scripts/debug/harness.js — scenario config + controls + scroll sync.
+ *
+ * The harness drives the engine through its public custom properties, so this
+ * generator never needs to know the gradient internals — it just ships the
+ * current plugin CSS verbatim.
+ */
+import fs from 'node:fs'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { compileCss } from './build-css.mjs'
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const root = path.resolve(__dirname, '..')
+const debugDir = path.join(root, 'debug')
+const outFile = path.join(debugDir, 'index.html')
+
+const pluginCss = compileCss()
+const harnessCss = fs.readFileSync(path.join(__dirname, 'debug', 'harness.css'), 'utf8')
+const harnessJs = fs.readFileSync(path.join(__dirname, 'debug', 'harness.js'), 'utf8')
+
+const ctrl = (label, valId, inner) =>
+ `${label}${valId ? ` ` : ''} ${inner}
`
+
+const panel = `
+
+
+
tw-fade · pressure test
+ every sample is pinned to the same scroll offset — scrub to compare frame-for-frame
+
+ Reset
+
+
+ ${ctrl('Fade size', 'sizeVal', '
')}
+ ${ctrl('Travel (band open)', 'travelVal', '
')}
+ ${ctrl('Onset (edge speed)', 'onsetVal', '
')}
+ ${ctrl('Clear', 'clearVal', '
')}
+
+ ${ctrl('Content', null, '
auto (per scenario) text cards images code dense list ')}
+ ${ctrl('Background', null, '
light dark checkerboard photo ')}
+ ${ctrl('Container shape', null, '
rounded squircle sharp ')}
+
+
+
+ onset 1 reproduces the old coupled hard-clip (alpha = t); 8 is the decoupled default.
+ static fallback forces fade-always (the no-scroll-driven-animation path). Set scroll to 8px from start to inspect the onset edge-coverage window; switch to px from end to probe the trailing edge (fade-bottom / fade-end — a separate range).
+
+
`
+
+const html = `
+
+
+
+
+tw-fade · pressure test
+
+
+
+${panel}
+
+
+
+
+`
+
+fs.mkdirSync(debugDir, { recursive: true })
+fs.writeFileSync(outFile, html)
+console.log(`wrote ${path.relative(root, outFile)} (${(html.length / 1024).toFixed(1)} KB)`)
diff --git a/scripts/debug/README.md b/scripts/debug/README.md
new file mode 100644
index 0000000..f03231c
--- /dev/null
+++ b/scripts/debug/README.md
@@ -0,0 +1,77 @@
+# tw-fade debug harness
+
+An interactive pressure-test bench for the fade engine. It renders the plugin
+across every direction utility, a battery of real-world / edge-case layouts, and
+four parameter sweeps — all pinned to the **same scroll offset** so any bug is a
+side-by-side visual diff.
+
+## Run
+
+```bash
+npm run debug # → debug/index.html (self-contained, gitignored)
+```
+
+Open `debug/index.html` in a **Chromium-based browser** (needs scroll-driven
+animations + `corner-shape`; Chrome/Edge ≥ 115-ish, full squircle support ≥ 149).
+The file inlines the *compiled* plugin CSS — the same output `dist/` ships — so the
+harness always reflects the real engine. Re-run `npm run debug` after editing
+`src/tw-fade.css`.
+
+## What it exercises
+
+- **Directions** — all seven utilities (`fade`, `fade-y`, `fade-x`, `fade-top`,
+ `fade-bottom`, `fade-start`, `fade-end`) on identical content.
+- **Real-world & edge cases** — short (non-overflowing) content, sticky-header
+ occlusion, padding lead-in, scroll-snap, nested fade scrollers, image/code/dense
+ content, tiny containers, thick borders, oversized (50%) fades, per-edge sizes,
+ `overflow: clip` trap, and the `fade-none` / `fade-none-y` / `fade-always-x`
+ override paths.
+- **Sweeps** — travel, onset, size, clear each across their scale at the global
+ scroll offset.
+
+## Controls
+
+- **Synchronized scroll** — one slider drives every scroller. Fine chips
+ (`0/2/4/6/8/12/24px`) plus a **px-from-start / px-from-end** toggle let you probe
+ the onset edge-coverage window on the leading edge *and* the separate trailing
+ range. `auto` oscillates.
+- **size / travel / onset / clear** sliders write the public custom properties
+ (`--tw-fade-size`, `--tw-fade-travel`, `--tw-fade-onset`, `--tw-fade-clear`)
+ directly on each scroller — no class explosion, continuous values.
+ - **onset 1 reproduces the old coupled hard-clip** (`alpha = t`); 8 is the
+ decoupled default. That is the A/B.
+- **static fallback** forces `fade-always`, mirroring the `@supports not
+ (animation-timeline: scroll())` path that pins amounts to 1.
+- **RTL**, **content type**, **background** (light/dark/checker/photo — reveals the
+ mask silhouette), and **container shape** (rounded/squircle/sharp).
+- Each card shows a live readout: scroll offset, `%`, and the resolved
+ `--tw-fade-{t,b,l,r}` amounts. A non-overflowing card reads `no overflow → no
+ fade` (the key scroll-driven invariant).
+
+## Architecture
+
+Three sources, assembled into one standalone file by `scripts/build-debug.mjs`:
+
+| File | Role |
+| --- | --- |
+| `scripts/build-debug.mjs` | generator — inlines compiled plugin CSS + the two files below, writes `debug/index.html`, emits the control-panel markup |
+| `scripts/debug/harness.css` | UI chrome only (never touches the fade engine) |
+| `scripts/debug/harness.js` | scenario config, controls, scroll-sync engine |
+
+The config props are `@property … inherits:false`, so the harness sets them on
+**each `.fade*` element directly** (a parent would not cascade).
+
+### Add a scenario
+
+Append an object to `SCENARIOS.directions` / `SCENARIOS.realworld` in
+`harness.js`:
+
+```js
+{ id: 'myCase', label: 'My case', cls: 'fade-y', special: 'simple',
+ content: 'text', lock: { travel: 80, vars: { '--tw-fade-size-top': '64px' } },
+ note: 'what to look for' }
+```
+
+`special` selects a builder (`simple`, `plane`, `hscroll`, `sticky`, `leadin`,
+`snap`, `short`, `clip`, `nested`, `bordered`); `lock` overrides global params for
+that card (`size`/`travel`/`onset`/`clear`, or arbitrary inline `vars`).
diff --git a/scripts/debug/harness.css b/scripts/debug/harness.css
new file mode 100644
index 0000000..2f89792
--- /dev/null
+++ b/scripts/debug/harness.css
@@ -0,0 +1,354 @@
+/* tw-fade debug harness — UI chrome only. The plugin CSS is inlined separately
+ * by scripts/build-debug.mjs. Nothing here touches the fade engine; it only
+ * frames the sample scrollers and the control panel. */
+
+:root {
+ --ui-bg: #0d0f14;
+ --ui-panel: #151922;
+ --ui-panel-2: #1c2230;
+ --ui-line: #2a3140;
+ --ui-text: #e6e9ef;
+ --ui-dim: #9aa4b5;
+ --ui-accent: #6ea8fe;
+ --ui-accent-2: #5be0c0;
+ --ui-warn: #ffb454;
+ --stage-bg: #f4f5f7;
+ --stage-card: #ffffff;
+ --stage-text: #1b2430;
+ --stage-dim: #5b6675;
+ --stage-line: #e2e5ea;
+ --scroller-h: 220px;
+}
+
+* { box-sizing: border-box; }
+
+html, body { margin: 0; }
+
+body {
+ background: var(--ui-bg);
+ color: var(--ui-text);
+ font: 13px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
+ -webkit-font-smoothing: antialiased;
+}
+
+a { color: var(--ui-accent); }
+
+/* ---- Control panel ---------------------------------------------------- */
+
+.panel {
+ position: sticky;
+ top: 0;
+ z-index: 50;
+ background: color-mix(in srgb, var(--ui-panel) 92%, transparent);
+ backdrop-filter: blur(8px);
+ border-bottom: 1px solid var(--ui-line);
+ padding: 12px 16px;
+}
+
+.panel-title {
+ display: flex;
+ align-items: baseline;
+ gap: 10px;
+ margin: 0 0 10px;
+}
+.panel-title h1 { font-size: 14px; margin: 0; letter-spacing: 0.2px; }
+.panel-title .sub { color: var(--ui-dim); font-size: 12px; }
+.panel-title .spacer { flex: 1; }
+
+.controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px 14px;
+ align-items: flex-end;
+}
+
+.ctrl { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
+.ctrl > label {
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 0.6px;
+ color: var(--ui-dim);
+ display: flex;
+ justify-content: space-between;
+ gap: 8px;
+}
+.ctrl > label .val { color: var(--ui-accent-2); font-variant-numeric: tabular-nums; }
+
+.ctrl input[type="range"] { width: 168px; accent-color: var(--ui-accent); margin: 4px 0 0; }
+.ctrl select,
+.ctrl input[type="text"] {
+ background: var(--ui-panel-2);
+ color: var(--ui-text);
+ border: 1px solid var(--ui-line);
+ border-radius: 6px;
+ padding: 5px 8px;
+ font: inherit;
+}
+
+.seg { display: inline-flex; gap: 0; border: 1px solid var(--ui-line); border-radius: 7px; overflow: hidden; }
+.seg button {
+ background: var(--ui-panel-2);
+ color: var(--ui-dim);
+ border: 0;
+ border-right: 1px solid var(--ui-line);
+ padding: 5px 9px;
+ font: inherit;
+ cursor: pointer;
+}
+.seg button:last-child { border-right: 0; }
+.seg button:hover { color: var(--ui-text); }
+.seg button[aria-pressed="true"] { background: var(--ui-accent); color: #06121f; font-weight: 600; }
+
+.toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ background: var(--ui-panel-2);
+ border: 1px solid var(--ui-line);
+ border-radius: 7px;
+ padding: 5px 9px;
+ cursor: pointer;
+ user-select: none;
+}
+.toggle input { accent-color: var(--ui-accent); margin: 0; }
+.toggle.warn[data-on="true"] { border-color: var(--ui-warn); color: var(--ui-warn); }
+
+.btn {
+ background: var(--ui-panel-2);
+ color: var(--ui-text);
+ border: 1px solid var(--ui-line);
+ border-radius: 7px;
+ padding: 6px 11px;
+ font: inherit;
+ cursor: pointer;
+}
+.btn:hover { border-color: var(--ui-accent); }
+.btn.primary { background: var(--ui-accent); color: #06121f; border-color: transparent; font-weight: 600; }
+
+.scrubrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
+.scrubrow .steps { display: inline-flex; gap: 4px; }
+.scrubrow .steps button {
+ background: var(--ui-panel-2);
+ color: var(--ui-dim);
+ border: 1px solid var(--ui-line);
+ border-radius: 6px;
+ padding: 4px 7px;
+ font: 11px/1 ui-monospace, monospace;
+ cursor: pointer;
+}
+.scrubrow .steps button:hover { color: var(--ui-text); border-color: var(--ui-accent); }
+
+.hint { color: var(--ui-dim); font-size: 11px; margin: 8px 0 0; }
+.hint code { color: var(--ui-accent-2); }
+
+/* ---- Stage (sample area) --------------------------------------------- */
+
+.stage { padding: 18px 16px 64px; }
+
+.stage.bg-light { background: var(--stage-bg); }
+.stage.bg-dark { background: #11151c; }
+.stage.bg-check {
+ background:
+ repeating-conic-gradient(#dfe3ea 0 25%, #c5ccd8 0 50%) 0 0 / 22px 22px;
+}
+.stage.bg-photo {
+ background: linear-gradient(125deg, #ff9a9e, #fad0c4 30%, #a1c4fd 65%, #c2e9fb);
+}
+
+.section-h {
+ display: flex;
+ align-items: baseline;
+ gap: 10px;
+ margin: 26px 4px 12px;
+ color: var(--stage-text);
+}
+.stage.bg-dark .section-h, .stage.bg-photo .section-h { color: #fff; }
+.section-h h2 { font-size: 13px; text-transform: uppercase; letter-spacing: 1px; margin: 0; }
+.section-h .desc { font-size: 12px; color: var(--stage-dim); font-weight: 400; text-transform: none; letter-spacing: 0; }
+.stage.bg-dark .section-h .desc, .stage.bg-photo .section-h .desc { color: rgba(255,255,255,0.8); }
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ gap: 14px;
+}
+.grid.sweep { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
+
+.card {
+ background: var(--stage-card);
+ border: 1px solid var(--stage-line);
+ border-radius: 12px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ box-shadow: 0 1px 2px rgba(0,0,0,0.04);
+}
+
+.card-head {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 10px;
+ border-bottom: 1px solid var(--stage-line);
+ background: #fafbfc;
+}
+.card-label { font-weight: 600; font-size: 12px; color: var(--stage-text); }
+.card-tag {
+ font: 10px/1 ui-monospace, monospace;
+ background: #eef1f6;
+ color: #46506a;
+ padding: 3px 6px;
+ border-radius: 5px;
+}
+.card-head .readout {
+ margin-left: auto;
+ font: 10px/1 ui-monospace, monospace;
+ color: var(--stage-dim);
+ font-variant-numeric: tabular-nums;
+}
+
+.card-note {
+ padding: 7px 10px;
+ font-size: 11px;
+ color: var(--stage-dim);
+ border-top: 1px solid var(--stage-line);
+ background: #fafbfc;
+}
+
+/* The scroll container that actually carries a fade-* class. Position
+ * relative so the optional band overlay can pin to it. */
+.scroller {
+ position: relative;
+ height: var(--scroller-h);
+ overflow: auto;
+ background: var(--stage-card);
+ color: var(--stage-text);
+ scrollbar-width: thin;
+}
+.scroller.h { overflow: auto; }
+.scroller.short { height: 120px; }
+.scroller.tiny { height: 84px; }
+
+.stage.bg-dark .card, .stage.bg-dark .scroller { background: #1b2230; color: #dfe5ee; border-color: #2a3346; }
+.stage.bg-dark .card-head, .stage.bg-dark .card-note { background: #161d29; border-color: #2a3346; }
+.stage.bg-dark .card-label { color: #eef2f8; }
+
+/* ---- Sample content -------------------------------------------------- */
+
+.body-pad { padding: 14px 16px; }
+.body-pad p { margin: 0 0 11px; }
+.body-pad h3 { margin: 0 0 8px; font-size: 14px; }
+
+.lead-in { padding-top: 48px; padding-bottom: 48px; }
+
+.minilist { padding: 8px; display: flex; flex-direction: column; gap: 8px; }
+.minicard {
+ border: 1px solid var(--stage-line);
+ border-radius: 9px;
+ padding: 10px 12px;
+ background: #fbfcfe;
+}
+.minicard b { display: block; font-size: 12px; }
+.minicard span { color: var(--stage-dim); font-size: 11px; }
+.stage.bg-dark .minicard { background: #222a3a; border-color: #313b50; }
+
+.tilegrid { padding: 10px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
+.tile { aspect-ratio: 4 / 3; border-radius: 9px; }
+
+.code { margin: 0; padding: 12px 14px; font: 11.5px/1.7 ui-monospace, SFMono-Regular, monospace; white-space: pre; color: #2b3850; }
+.stage.bg-dark .code { color: #c7d2e6; }
+
+.dense { padding: 0; }
+.dense .row {
+ display: flex;
+ justify-content: space-between;
+ padding: 7px 12px;
+ border-bottom: 1px solid var(--stage-line);
+ font-size: 12px;
+}
+.dense .row span:last-child { color: var(--stage-dim); font-variant-numeric: tabular-nums; }
+
+/* Horizontal content */
+.scroller.h .track { display: inline-flex; gap: 10px; padding: 14px; white-space: nowrap; height: 100%; align-items: center; }
+.chip {
+ flex: 0 0 auto;
+ border: 1px solid var(--stage-line);
+ border-radius: 999px;
+ padding: 8px 16px;
+ background: #fbfcfe;
+ font-size: 12px;
+ font-weight: 500;
+}
+.stage.bg-dark .chip { background: #222a3a; border-color: #313b50; }
+.hcard {
+ flex: 0 0 180px;
+ height: 150px;
+ border-radius: 11px;
+ padding: 12px;
+ color: #fff;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ font-weight: 600;
+}
+
+/* 2D content for fade (all edges) */
+.plane { width: 760px; padding: 14px; }
+.plane .grid2d { display: grid; grid-template-columns: repeat(8, 84px); gap: 8px; }
+.plane .cell { height: 84px; border-radius: 8px; display: grid; place-items: center; color: #fff; font-weight: 600; }
+
+/* Sticky header inside a scroller */
+.sticky-h {
+ position: sticky;
+ top: 0;
+ background: color-mix(in srgb, var(--stage-card) 86%, transparent);
+ backdrop-filter: blur(4px);
+ padding: 8px 14px;
+ font-weight: 600;
+ font-size: 12px;
+ border-bottom: 1px solid var(--stage-line);
+}
+.stage.bg-dark .sticky-h { background: color-mix(in srgb, #1b2230 86%, transparent); }
+
+/* Nested scroller card */
+.nested-outer { padding: 14px; }
+.nested-inner {
+ height: 150px;
+ overflow: auto;
+ border: 1px dashed var(--stage-line);
+ border-radius: 9px;
+ margin: 10px 0;
+ background: #fbfcfe;
+}
+.stage.bg-dark .nested-inner { background: #222a3a; }
+
+/* Scroll-snap */
+.snap { scroll-snap-type: y mandatory; }
+.snap .snapitem {
+ scroll-snap-align: start;
+ height: 110px;
+ margin: 8px 12px;
+ border-radius: 10px;
+ display: grid;
+ place-items: center;
+ color: #fff;
+ font-weight: 700;
+ font-size: 18px;
+}
+
+/* Container shapes (applied to .scroller via JS shape class) */
+.shape-rounded .scroller { border-radius: 14px; }
+.shape-squircle .scroller { border-radius: 26px; corner-shape: superellipse(1.8); }
+.shape-sharp .scroller { border-radius: 0; }
+.shape-rounded .card, .shape-squircle .card { border-radius: 14px; }
+
+.legend {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 14px;
+ margin: 6px 4px 0;
+ font-size: 11px;
+ color: var(--stage-dim);
+}
+.stage.bg-dark .legend, .stage.bg-photo .legend { color: rgba(255,255,255,0.85); }
+.legend .sw { display: inline-block; width: 11px; height: 11px; border-radius: 3px; vertical-align: -1px; margin-right: 5px; }
diff --git a/scripts/debug/harness.js b/scripts/debug/harness.js
new file mode 100644
index 0000000..4bd85e0
--- /dev/null
+++ b/scripts/debug/harness.js
@@ -0,0 +1,452 @@
+/* tw-fade debug harness — runtime logic.
+ *
+ * Drives the inlined plugin via the public custom properties only:
+ * --tw-fade-size / --tw-fade-travel / --tw-fade-onset / --tw-fade-clear
+ * (all @property inherits:false, so they are set on each .fade* element
+ * directly, never a parent). Structural scenarios + parameter sweeps are
+ * generated from the SCENARIOS / SWEEPS config below. The single most useful
+ * affordance for a scroll-driven plugin is synchronized scroll: every sample
+ * scroller is pinned to the same offset so you can compare them frame-for-frame.
+ *
+ * Notes baked into the controls:
+ * - onset = 1 reproduces the OLD coupled behavior (alpha = t); 8 is the new
+ * decoupled default. That IS the A/B toggle.
+ * - "Static fallback" forces .fade-always, mirroring the @supports-not path
+ * that pins t/b/l/r = 1 where scroll-driven animation is unsupported.
+ */
+(() => {
+ 'use strict';
+
+ const COLORS = ['#6ea8fe', '#5be0c0', '#ffb454', '#ff7eb6', '#b388ff', '#7ee787', '#f0883e', '#79c0ff'];
+ const grad = (i) => `linear-gradient(135deg, ${COLORS[i % COLORS.length]}, ${COLORS[(i + 3) % COLORS.length]})`;
+
+ const state = {
+ size: null, // null = plugin default; else number (px)
+ travel: null, // null = plugin default; else number (px)
+ onset: 8,
+ clear: 0, // px
+ scrollPct: 0, // 0..1
+ scrollPx: null, // when set, absolute px offset (overrides pct)
+ scrollMode: 'start', // 'start' | 'end' — which side scrollPx is measured from
+ rtl: false,
+ content: 'auto',
+ bg: 'light',
+ shape: 'rounded',
+ fallback: false,
+ };
+
+ let autoTimer = null;
+ let autoDir = 1;
+
+ /* ---- content generators ------------------------------------------- */
+ const LOREM = [
+ 'Scroll-driven masks ride the container’s own scroll position—no JavaScript, no observers.',
+ 'The leading edge is covered the instant you scroll, while the soft band keeps easing open over the travel.',
+ 'Each edge is an independent linear-gradient mask layer, composited with mask-composite: intersect.',
+ 'Because the fade is a mask, whatever sits behind the scroller shows through the faded pixels.',
+ 'Try a checkerboard or photo background to see the exact silhouette the mask carves.',
+ 'Vertical edges stay physical; horizontal start/end edges flip with text direction.',
+ 'A flush, unscrolled edge shows nothing—alpha is zero until the scroll timeline advances.',
+ 'Crank onset down to 1 and the old hard-clip coupling returns: the edge lags the scroll.',
+ ];
+
+ function cText(n) {
+ let h = 'Read me while scrolling ';
+ for (let i = 0; i < n; i++) h += `
${LOREM[i % LOREM.length]}
`;
+ return h + '
';
+ }
+ function cCards(n) {
+ let h = '';
+ for (let i = 0; i < n; i++) h += `
Item ${i + 1} secondary line of supporting metadata
`;
+ return h + '
';
+ }
+ function cTiles(n) {
+ let h = '';
+ for (let i = 0; i < n; i++) h += `
`;
+ return h + '
';
+ }
+ function cCode() {
+ const lines = [
+ '',
+ ' ',
+ '
',
+ '',
+ '.fade-y {',
+ ' --tw-fade-size: 3rem;',
+ ' --tw-fade-travel: 2rem; /* band open */',
+ ' --tw-fade-onset: 8; /* edge speed */',
+ '}',
+ '',
+ 'fade all four edges',
+ 'fade-y top + bottom',
+ 'fade-x start + end (RTL-aware)',
+ 'fade-top leading vertical only',
+ 'fade-bottom trailing vertical only',
+ ];
+ let body = '';
+ for (let k = 0; k < 3; k++) body += lines.join('\n') + '\n\n';
+ return `${body} `;
+ }
+ function cDense(n) {
+ let h = '';
+ for (let i = 0; i < n; i++) h += `
row label ${i + 1} ${(Math.sin(i) * 1000 | 0)}
`;
+ return h + '
';
+ }
+ function cChips(n) {
+ const words = ['All', 'Design', 'Engineering', 'Marketing', 'Sales', 'Support', 'Research', 'Ops', 'Finance', 'Legal', 'People', 'Data', 'Brand', 'Growth'];
+ let h = '';
+ for (let i = 0; i < n; i++) h += `
${words[i % words.length]} ${i + 1}
`;
+ return h + '
';
+ }
+ function cHCards(n) {
+ let h = '';
+ for (let i = 0; i < n; i++) h += `
Card ${i + 1}
`;
+ return h + '
';
+ }
+ function cPlane(cols, rows) {
+ let h = ``;
+ for (let i = 0; i < cols * rows; i++) h += `
${i + 1}
`;
+ return h + '
';
+ }
+
+ const CONTENT = {
+ text: () => cText(10),
+ cards: () => cCards(14),
+ images: () => cTiles(18),
+ code: () => cCode(),
+ dense: () => cDense(28),
+ };
+
+ /* ---- scenarios ----------------------------------------------------- */
+ // kind: 'simple' (scroller + body html) or a named special builder.
+ // flex: body follows the global content-type selector when true.
+ const SCENARIOS = {
+ directions: [
+ { id: 'fy', label: 'fade-y', cls: 'fade-y', body: () => cText(10), flex: true, note: 'Top + bottom. The canonical vertical scroller.' },
+ { id: 'ftop', label: 'fade-top', cls: 'fade-top', body: () => cText(10), flex: true, note: 'Leading edge only; bottom is never masked.' },
+ { id: 'fbot', label: 'fade-bottom', cls: 'fade-bottom', body: () => cText(10), flex: true, note: 'Trailing edge only; only dissolves near the very end.' },
+ { id: 'fall', label: 'fade (all edges)', cls: 'fade', special: 'plane', note: '2-D scroll. Four mask layers intersect at the corners.' },
+ { id: 'fx', label: 'fade-x', cls: 'fade-x', special: 'hscroll', content: 'chips', note: 'Inline start + end. Flips under RTL.' },
+ { id: 'fstart', label: 'fade-start', cls: 'fade-start', special: 'hscroll', content: 'chips', note: 'Inline leading edge. Right edge under RTL.' },
+ { id: 'fend', label: 'fade-end', cls: 'fade-end', special: 'hscroll', content: 'chips', note: 'Inline trailing edge. Left edge under RTL.' },
+ ],
+ realworld: [
+ { id: 'short', label: 'Short content', cls: 'fade-y short', special: 'short', note: 'Does NOT overflow → must show NO fade (scroll-driven path).' },
+ { id: 'sticky', label: 'Sticky header', cls: 'fade-y', special: 'sticky', note: 'Sticky header sits over the faded top edge — watch for double-dim.' },
+ { id: 'leadin', label: 'Padding lead-in', cls: 'fade-y', special: 'leadin', note: 'Top/bottom padding inside the scroller; fade rides the padded edge.' },
+ { id: 'snap', label: 'Scroll-snap', cls: 'fade-y snap', special: 'snap', note: 'scroll-snap-type: y mandatory. Fade should track snapped offsets.' },
+ { id: 'nested', label: 'Nested fade', cls: 'fade-y', special: 'nested', note: 'A fade-y scroller inside a fade-y scroller (block-axis isolation).' },
+ { id: 'images', label: 'Image grid', cls: 'fade-y', special: 'simple', content: 'images', flex: true, note: 'Dense visual content; mask edge crosses tile boundaries.' },
+ { id: 'code', label: 'Code block', cls: 'fade-y', special: 'simple', content: 'code', flex: true, note: 'Monospace, pre-wrapped; check baseline alignment at the edge.' },
+ { id: 'tiny', label: 'Tiny container', cls: 'fade-y tiny', special: 'simple', content: 'dense', note: 'Very short viewport; size may exceed the box.' },
+ { id: 'bordered', label: 'Thick border', cls: 'fade-y', special: 'bordered', note: 'Mask clips the element box — border + fade interaction.' },
+ { id: 'hcards', label: 'Horizontal cards', cls: 'fade-x', special: 'hscroll', content: 'hcards', note: 'Fast flick row; both inline edges fade.' },
+ { id: 'bigsize', label: 'Oversized fade (50%)', cls: 'fade-y', special: 'simple', content: 'text', lock: { vars: { '--tw-fade-size': '50%' } }, note: 'Degenerate: each band is half the viewport. Bands should not cross.' },
+ { id: 'peredge', label: 'Per-edge sizes', cls: 'fade-y', special: 'simple', content: 'text', lock: { vars: { '--tw-fade-size-top': '72px', '--tw-fade-size-bottom': '16px' } }, note: 'top 72px / bottom 16px — asymmetric per-edge sizing.' },
+ { id: 'clip', label: 'overflow: clip (trap)', cls: 'fade-y', special: 'clip', content: 'text', note: 'overflow:clip is not a scroll container → timeline inert → NO fade though content IS clipped.' },
+ { id: 'fnone', label: 'fade-none (control)', cls: 'fade-y fade-none', special: 'simple', content: 'text', noFallback: true, note: 'Forced off — must never fade, even mid-scroll.' },
+ { id: 'noney', label: 'fade-none-y on fade', cls: 'fade fade-none-y', special: 'plane', noFallback: true, note: 'All edges armed, vertical forced off → only the inline (l/r) edges fade.' },
+ { id: 'alwaysx', label: 'fade-always-x on fade-y', cls: 'fade-y fade-always-x', special: 'simple', content: 'text', noFallback: true, note: 'l/r pinned to 1 but fade-y has no horizontal layer → identity mask, NO horizontal fade.' },
+ ],
+ };
+
+ // One parameter swept across its scale, all cells at the global scroll offset.
+ const SWEEPS = [
+ {
+ title: 'Travel sweep', key: 'travel', unit: 'px',
+ desc: 'Band-open speed. With the new decouple, the edge is covered immediately at every travel — only the soft band widens. Scrub to ~8px to compare.',
+ values: [12, 24, 48, 80, 120, 160],
+ },
+ {
+ title: 'Onset sweep', key: 'onset', unit: '',
+ desc: 'Edge-coverage speed. onset 1 = the OLD coupled hard-clip; 8 = current default. Scrub to ~8px to see the difference.',
+ values: [1, 2, 4, 8, 12, 24],
+ },
+ {
+ title: 'Size sweep', key: 'size', unit: 'px',
+ desc: 'Band width at full fade. Pure cosmetics — does not affect when the clip is covered.',
+ values: [24, 32, 48, 64, 96, 128],
+ },
+ {
+ title: 'Clear sweep', key: 'clear', unit: 'px',
+ desc: 'Untouched gap before the band starts. Useful to keep a pinned first row crisp.',
+ values: [0, 8, 16, 24, 40],
+ },
+ ];
+
+ /* ---- DOM building -------------------------------------------------- */
+ const esc = (s) => String(s).replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
+
+ function bodyHtmlFor(scn) {
+ const content = (state.content !== 'auto' && scn.flex) ? state.content : scn.content;
+ if (content && CONTENT[content]) return CONTENT[content]();
+ if (content === 'chips') return cChips(26);
+ if (content === 'hcards') return cHCards(12);
+ return cText(10);
+ }
+
+ function buildScroller(scn) {
+ const lock = scn.lock ? JSON.stringify(scn.lock) : '{}';
+ const extra = scn.noFallback ? ' data-nofallback="1"' : '';
+ const sp = scn.special;
+ let cls = 'scroller ' + scn.cls;
+ let styleAttr = '';
+ let inner;
+
+ if (sp === 'plane') { cls += ' h'; inner = cPlane(8, 8); }
+ else if (sp === 'clip') { styleAttr = ' style="overflow:clip"'; inner = bodyHtmlFor(scn); }
+ else if (sp === 'hscroll') { cls += ' h'; inner = bodyHtmlFor(scn); }
+ else if (sp === 'sticky') {
+ inner = 'Sticky header · stays pinned
' + cCards(14);
+ }
+ else if (sp === 'leadin') { inner = ''; }
+ else if (sp === 'snap') {
+ let s = '';
+ for (let i = 0; i < 10; i++) s += `
${i + 1}
`;
+ inner = s + '
';
+ }
+ else if (sp === 'short') { inner = ''; }
+ else { inner = bodyHtmlFor(scn); }
+
+ let html = `${inner}
`;
+
+ if (sp === 'nested') {
+ html = ``
+ + '
Outer scroller. The inner box is its own fade-y scroll context.
'
+ + '
' + cDense(18) + '
'
+ + '
After the nested region the outer keeps scrolling so its own bottom edge fades.
'
+ + cText(6).replace('
';
+ }
+ if (sp === 'bordered') {
+ html = `
${cCards(14)}
`;
+ }
+ return html;
+ }
+
+ function buildCard(scn) {
+ return `
`
+ + `
${esc(scn.label)} `
+ + `${esc(scn.cls.replace('scroller', '').trim())} `
+ + '
'
+ + buildScroller(scn)
+ + `
${esc(scn.note || '')}
`
+ + '
';
+ }
+
+ function buildSweepCard(sweep, value) {
+ const lock = { [sweep.key]: value };
+ const label = `${sweep.key} ${value}${sweep.unit}` + (sweep.key === 'onset' && value === 1 ? ' (old)' : (sweep.key === 'onset' && value === 8 ? ' (default)' : ''));
+ return `
${esc(label)}
`
+ + `
${cText(9)}
`
+ + '
';
+ }
+
+ function render() {
+ const stage = document.getElementById('stage');
+ let h = '';
+
+ h += '
Directions all seven public direction utilities on identical content ';
+ h += '
' + SCENARIOS.directions.map(buildCard).join('') + '
';
+
+ h += '
Real-world & edge cases layouts and content that have historically broken edge-fade plugins ';
+ h += '
' + SCENARIOS.realworld.map(buildCard).join('') + '
';
+
+ SWEEPS.forEach((sw) => {
+ h += `
${esc(sw.title)} ${esc(sw.desc)} `;
+ h += '
' + sw.values.map((v) => buildSweepCard(sw, v)).join('') + '
';
+ });
+
+ stage.innerHTML = h;
+ applyStageChrome();
+ applyAll();
+ syncScroll();
+ }
+
+ /* ---- applying parameters ------------------------------------------ */
+ function setVarPx(el, prop, value) {
+ if (value == null || value === '') el.style.removeProperty(prop);
+ else el.style.setProperty(prop, typeof value === 'number' ? value + 'px' : value);
+ }
+
+ function applyTo(el) {
+ const lock = JSON.parse(el.dataset.lock || '{}');
+ const p = {
+ size: 'size' in lock ? lock.size : state.size,
+ travel: 'travel' in lock ? lock.travel : state.travel,
+ onset: 'onset' in lock ? lock.onset : state.onset,
+ clear: 'clear' in lock ? lock.clear : state.clear,
+ };
+ setVarPx(el, '--tw-fade-size', p.size);
+ setVarPx(el, '--tw-fade-travel', p.travel);
+ el.style.setProperty('--tw-fade-onset', String(p.onset));
+ setVarPx(el, '--tw-fade-clear', p.clear);
+ if (lock.vars) for (const k in lock.vars) el.style.setProperty(k, lock.vars[k]);
+ const allowFallback = state.fallback && !el.dataset.nofallback;
+ el.classList.toggle('fade-always', allowFallback);
+ }
+
+ function applyAll() {
+ document.querySelectorAll('.scroller').forEach(applyTo);
+ }
+
+ function applyStageChrome() {
+ const stage = document.getElementById('stage');
+ stage.className = 'stage bg-' + state.bg + ' shape-' + state.shape;
+ const grid = stage;
+ grid.dir = state.rtl ? 'rtl' : 'ltr';
+ }
+
+ /* ---- scroll sync --------------------------------------------------- */
+ function syncScroll() {
+ document.querySelectorAll('.scroller').forEach((el) => {
+ const maxY = el.scrollHeight - el.clientHeight;
+ const maxX = el.scrollWidth - el.clientWidth;
+ const sign = state.rtl ? -1 : 1;
+ if (state.scrollPx != null) {
+ const fromEnd = state.scrollMode === 'end';
+ const posY = fromEnd ? maxY - state.scrollPx : state.scrollPx;
+ const posX = fromEnd ? maxX - state.scrollPx : state.scrollPx;
+ if (maxY > 0) el.scrollTop = Math.max(0, Math.min(posY, maxY));
+ if (maxX > 0) el.scrollLeft = sign * Math.max(0, Math.min(posX, maxX));
+ } else {
+ if (maxY > 0) el.scrollTop = Math.round(state.scrollPct * maxY);
+ if (maxX > 0) el.scrollLeft = sign * Math.round(state.scrollPct * maxX);
+ }
+ });
+ requestAnimationFrame(() => requestAnimationFrame(updateReadouts));
+ }
+
+ function updateReadouts() {
+ document.querySelectorAll('.card').forEach((card) => {
+ const out = card.querySelector('.readout');
+ const el = card.querySelector('.scroller');
+ if (!out || !el) return;
+ const maxY = el.scrollHeight - el.clientHeight;
+ const maxX = el.scrollWidth - el.clientWidth;
+ const cs = getComputedStyle(el);
+ const amt = (p) => (Number(cs.getPropertyValue('--tw-fade-' + p)) || 0).toFixed(2).replace(/^0(?=\.)/, '');
+ if (maxX > maxY && maxX > 0) {
+ const x = Math.abs(el.scrollLeft);
+ out.textContent = `x ${x|0}/${maxX|0} · ${Math.round(x / maxX * 100)}% · l${amt('l')} r${amt('r')}`;
+ } else if (maxY > 0) {
+ out.textContent = `y ${el.scrollTop|0}/${maxY|0} · ${Math.round(el.scrollTop / maxY * 100)}% · t${amt('t')} b${amt('b')}`;
+ } else {
+ out.textContent = 'no overflow → no fade';
+ }
+ });
+ }
+
+ /* ---- auto-scroll --------------------------------------------------- */
+ function toggleAuto(on) {
+ if (autoTimer) { cancelAnimationFrame(autoTimer); autoTimer = null; }
+ if (!on) return;
+ const tick = () => {
+ state.scrollPx = null;
+ state.scrollPct += autoDir * 0.004;
+ if (state.scrollPct >= 1) { state.scrollPct = 1; autoDir = -1; }
+ if (state.scrollPct <= 0) { state.scrollPct = 0; autoDir = 1; }
+ const slider = document.getElementById('scrollRange');
+ if (slider) slider.value = String(Math.round(state.scrollPct * 100));
+ syncScroll();
+ autoTimer = requestAnimationFrame(tick);
+ };
+ autoTimer = requestAnimationFrame(tick);
+ }
+
+ /* ---- controls ------------------------------------------------------ */
+ function fmtSize(v) { return v == null ? 'default' : v + 'px'; }
+
+ function wire() {
+ const $ = (id) => document.getElementById(id);
+
+ const bind = (id, fn) => { const e = $(id); if (e) e.addEventListener('input', fn); };
+
+ bind('sizeRange', (e) => {
+ state.size = e.target.value === '0' ? null : Number(e.target.value);
+ $('sizeVal').textContent = fmtSize(state.size);
+ applyAll();
+ });
+ bind('travelRange', (e) => {
+ state.travel = e.target.value === '0' ? null : Number(e.target.value);
+ $('travelVal').textContent = fmtSize(state.travel);
+ applyAll(); syncScroll();
+ });
+ bind('onsetRange', (e) => {
+ state.onset = Number(e.target.value);
+ $('onsetVal').textContent = String(state.onset) + (state.onset === 1 ? ' (old)' : '');
+ applyAll();
+ });
+ bind('clearRange', (e) => {
+ state.clear = Number(e.target.value);
+ $('clearVal').textContent = state.clear + 'px';
+ applyAll();
+ });
+
+ bind('scrollRange', (e) => {
+ toggleAuto(false); $('autoChk').checked = false;
+ state.scrollPx = null;
+ state.scrollPct = Number(e.target.value) / 100;
+ syncScroll();
+ });
+
+ document.querySelectorAll('[data-scrollmode]').forEach((b) => b.addEventListener('click', () => {
+ state.scrollMode = b.dataset.scrollmode;
+ document.querySelectorAll('[data-scrollmode]').forEach((x) => x.setAttribute('aria-pressed', String(x === b)));
+ if (state.scrollPx != null) syncScroll();
+ }));
+
+ document.querySelectorAll('[data-step]').forEach((b) => b.addEventListener('click', () => {
+ toggleAuto(false); $('autoChk').checked = false;
+ const v = b.dataset.step;
+ if (v.endsWith('%')) { state.scrollPx = null; state.scrollPct = parseInt(v) / 100; $('scrollRange').value = parseInt(v); }
+ else { state.scrollPx = Number(v); }
+ syncScroll();
+ }));
+
+ $('autoChk').addEventListener('change', (e) => toggleAuto(e.target.checked));
+
+ const reRender = () => render();
+ $('contentSel').addEventListener('change', (e) => { state.content = e.target.value; reRender(); });
+ $('bgSel').addEventListener('change', (e) => { state.bg = e.target.value; applyStageChrome(); });
+ $('shapeSel').addEventListener('change', (e) => { state.shape = e.target.value; applyStageChrome(); });
+
+ $('rtlChk').addEventListener('change', (e) => { state.rtl = e.target.checked; applyStageChrome(); syncScroll(); });
+ $('fallbackChk').addEventListener('change', (e) => {
+ state.fallback = e.target.checked;
+ e.target.closest('.toggle').dataset.on = String(state.fallback);
+ applyAll();
+ });
+ $('resetBtn').addEventListener('click', () => {
+ Object.assign(state, { size: null, travel: null, onset: 8, clear: 0, scrollPct: 0, scrollPx: null, fallback: false });
+ toggleAuto(false);
+ document.querySelectorAll('input,select').forEach((el) => {
+ if (el.type === 'checkbox') el.checked = false;
+ });
+ $('sizeRange').value = 0; $('sizeVal').textContent = 'default';
+ $('travelRange').value = 0; $('travelVal').textContent = 'default';
+ $('onsetRange').value = 8; $('onsetVal').textContent = '8';
+ $('clearRange').value = 0; $('clearVal').textContent = '0px';
+ $('scrollRange').value = 0;
+ render();
+ });
+
+ // Re-sync on real user scroll of any single card (so readouts stay honest)
+ document.getElementById('stage').addEventListener('scroll', (e) => {
+ if (e.target.classList && e.target.classList.contains('scroller')) {
+ requestAnimationFrame(updateReadouts);
+ }
+ }, true);
+
+ window.addEventListener('resize', () => syncScroll());
+ }
+
+ /* ---- init ---------------------------------------------------------- */
+ function init() {
+ render();
+ wire();
+ }
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
+ else init();
+})();
diff --git a/src/tw-fade.css b/src/tw-fade.css
index 1c04e54..6c77def 100644
--- a/src/tw-fade.css
+++ b/src/tw-fade.css
@@ -1,4 +1,4 @@
-/* tw-fade — CSS scroll-edge fade masking for Tailwind v4. MIT · github.com/petekp/tw-fade */
+/* tw-fade - CSS scroll-edge fade masking for Tailwind v4. MIT - github.com/petekp/tw-fade */
/* Amounts: keep
so scroll animation interpolates them; initial 0 = no fade. */
@property --tw-fade-t {
@@ -21,7 +21,12 @@
inherits: false;
initial-value: 0;
}
-/* Config: keep "*" with NO initial-value — a typed rejects the rem initial, dropping the registration (fade collapses); inherits:false stops size and mask-layer declarations leaking into nested fades. */
+
+/*
+Config: keep "*" with NO initial-value. A typed rejects the rem
+fallback and drops the registration in browsers; inherits:false stops nested
+fades from leaking size, travel, clearance, mask, or routing state.
+*/
@property --tw-fade-size {
syntax: "*";
inherits: false;
@@ -34,39 +39,51 @@
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-t {
+@property --tw-fade-size-top {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-size-bottom {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-b {
+@property --tw-fade-size-start {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-l {
+@property --tw-fade-size-end {
syntax: "*";
inherits: false;
}
-@property --tw-fade-size-r {
+@property --tw-fade-travel {
syntax: "*";
inherits: false;
}
-@property --tw-fade-range {
+@property --tw-fade-clear {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-t {
+@property --tw-fade-clear-y {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-b {
+@property --tw-fade-clear-x {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-l {
+@property --tw-fade-clear-top {
syntax: "*";
inherits: false;
}
-@property --tw-fade-clear-r {
+@property --tw-fade-clear-bottom {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-clear-start {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-clear-end {
syntax: "*";
inherits: false;
}
@@ -86,6 +103,70 @@
syntax: "*";
inherits: false;
}
+@property --tw-fade-ltr-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-layer {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-timeline {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-ltr-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-start-animation-range {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-fade-rtl-end-animation-range {
+ syntax: "*";
+ inherits: false;
+}
@theme {
--fade-size-xs: calc(var(--spacing, 0.25rem) * 6);
@@ -96,14 +177,14 @@
--fade-size-2xl: calc(var(--spacing, 0.25rem) * 24);
--fade-size-3xl: calc(var(--spacing, 0.25rem) * 32);
--fade-size-4xl: calc(var(--spacing, 0.25rem) * 40);
- --fade-range-xs: calc(var(--spacing, 0.25rem) * 6);
- --fade-range-sm: calc(var(--spacing, 0.25rem) * 8);
- --fade-range-md: calc(var(--spacing, 0.25rem) * 12);
- --fade-range-lg: calc(var(--spacing, 0.25rem) * 16);
- --fade-range-xl: calc(var(--spacing, 0.25rem) * 20);
- --fade-range-2xl: calc(var(--spacing, 0.25rem) * 24);
- --fade-range-3xl: calc(var(--spacing, 0.25rem) * 32);
- --fade-range-4xl: calc(var(--spacing, 0.25rem) * 40);
+ --fade-travel-xs: calc(var(--spacing, 0.25rem) * 6);
+ --fade-travel-sm: calc(var(--spacing, 0.25rem) * 8);
+ --fade-travel-md: calc(var(--spacing, 0.25rem) * 12);
+ --fade-travel-lg: calc(var(--spacing, 0.25rem) * 16);
+ --fade-travel-xl: calc(var(--spacing, 0.25rem) * 20);
+ --fade-travel-2xl: calc(var(--spacing, 0.25rem) * 24);
+ --fade-travel-3xl: calc(var(--spacing, 0.25rem) * 32);
+ --fade-travel-4xl: calc(var(--spacing, 0.25rem) * 40);
--fade-clear-xs: calc(var(--spacing, 0.25rem) * 6);
--fade-clear-sm: calc(var(--spacing, 0.25rem) * 8);
--fade-clear-md: calc(var(--spacing, 0.25rem) * 12);
@@ -114,7 +195,7 @@
--fade-clear-4xl: calc(var(--spacing, 0.25rem) * 40);
}
-@keyframes tw-fade-reveal-t {
+@keyframes tw-fade-travel-t {
from {
--tw-fade-t: 0;
}
@@ -122,7 +203,7 @@
--tw-fade-t: 1;
}
}
-@keyframes tw-fade-reveal-b {
+@keyframes tw-fade-travel-b {
from {
--tw-fade-b: 1;
}
@@ -130,7 +211,7 @@
--tw-fade-b: 0;
}
}
-@keyframes tw-fade-reveal-l {
+@keyframes tw-fade-travel-l {
from {
--tw-fade-l: 0;
}
@@ -138,7 +219,7 @@
--tw-fade-l: 1;
}
}
-@keyframes tw-fade-reveal-r {
+@keyframes tw-fade-travel-r {
from {
--tw-fade-r: 1;
}
@@ -146,304 +227,417 @@
--tw-fade-r: 0;
}
}
+@keyframes tw-fade-travel-r-leading {
+ from {
+ --tw-fade-r: 0;
+ }
+ to {
+ --tw-fade-r: 1;
+ }
+}
+@keyframes tw-fade-travel-l-trailing {
+ from {
+ --tw-fade-l: 1;
+ }
+ to {
+ --tw-fade-l: 0;
+ }
+}
@utility fade-size-* {
--tw-fade-size: --value(--fade-size-*, [length], [percentage]);
}
-@utility fade-size-t-* {
- --tw-fade-size-t: --value(--fade-size-*, [length], [percentage]);
-}
-@utility fade-size-b-* {
- --tw-fade-size-b: --value(--fade-size-*, [length], [percentage]);
-}
-@utility fade-size-l-* {
- --tw-fade-size-l: --value(--fade-size-*, [length], [percentage]);
-}
-@utility fade-size-r-* {
- --tw-fade-size-r: --value(--fade-size-*, [length], [percentage]);
-}
@utility fade-size-y-* {
--tw-fade-size-y: --value(--fade-size-*, [length], [percentage]);
}
@utility fade-size-x-* {
--tw-fade-size-x: --value(--fade-size-*, [length], [percentage]);
}
-@utility fade-range-* {
- --tw-fade-range: --value(--fade-range-*, [length], [percentage]);
+@utility fade-size-top-* {
+ --tw-fade-size-top: --value(--fade-size-*, [length], [percentage]);
+}
+@utility fade-size-bottom-* {
+ --tw-fade-size-bottom: --value(--fade-size-*, [length], [percentage]);
}
-@utility fade-clear-t-* {
- --tw-fade-clear-t: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-t: --value(--fade-clear-*, [length], [percentage]);
+@utility fade-size-start-* {
+ --tw-fade-size-start: --value(--fade-size-*, [length], [percentage]);
}
-@utility fade-clear-b-* {
- --tw-fade-clear-b: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-b: --value(--fade-clear-*, [length], [percentage]);
+@utility fade-size-end-* {
+ --tw-fade-size-end: --value(--fade-size-*, [length], [percentage]);
}
-@utility fade-clear-l-* {
- --tw-fade-clear-l: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-l: --value(--fade-clear-*, [length], [percentage]);
+@utility fade-travel-* {
+ --tw-fade-travel: --value(--fade-travel-*, [length], [percentage]);
}
-@utility fade-clear-r-* {
- --tw-fade-clear-r: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-r: --value(--fade-clear-*, [length], [percentage]);
+@utility fade-clear-* {
+ --tw-fade-clear: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear: --value(--fade-clear-*, [length], [percentage]);
}
@utility fade-clear-y-* {
- --tw-fade-clear-t: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-t: --value(--fade-clear-*, [length], [percentage]);
- --tw-fade-clear-b: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-b: --value(--fade-clear-*, [length], [percentage]);
+ --tw-fade-clear-y: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-y: --value(--fade-clear-*, [length], [percentage]);
}
@utility fade-clear-x-* {
- --tw-fade-clear-l: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-l: --value(--fade-clear-*, [length], [percentage]);
- --tw-fade-clear-r: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-r: --value(--fade-clear-*, [length], [percentage]);
+ --tw-fade-clear-x: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-x: --value(--fade-clear-*, [length], [percentage]);
}
-@utility fade-clear-xy-* {
- --tw-fade-clear-t: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-t: --value(--fade-clear-*, [length], [percentage]);
- --tw-fade-clear-b: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-b: --value(--fade-clear-*, [length], [percentage]);
- --tw-fade-clear-l: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-l: --value(--fade-clear-*, [length], [percentage]);
- --tw-fade-clear-r: calc(var(--spacing, 0.25rem) * --value(integer));
- --tw-fade-clear-r: --value(--fade-clear-*, [length], [percentage]);
+@utility fade-clear-top-* {
+ --tw-fade-clear-top: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-top: --value(--fade-clear-*, [length], [percentage]);
}
-@utility fade-clear-t-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+@utility fade-clear-bottom-* {
+ --tw-fade-clear-bottom: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-bottom: --value(--fade-clear-*, [length], [percentage]);
}
-@utility fade-clear-b-var {
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+@utility fade-clear-start-* {
+ --tw-fade-clear-start: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-start: --value(--fade-clear-*, [length], [percentage]);
}
-@utility fade-clear-l-var {
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+@utility fade-clear-end-* {
+ --tw-fade-clear-end: calc(var(--spacing, 0.25rem) * --value(integer));
+ --tw-fade-clear-end: --value(--fade-clear-*, [length], [percentage]);
}
-@utility fade-clear-r-var {
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+@utility fade-clear-var {
+ --tw-fade-clear: var(--fade-clear, 0px);
}
@utility fade-clear-y-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
+ --tw-fade-clear-y: var(--fade-clear-y, var(--fade-clear, 0px));
}
@utility fade-clear-x-var {
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+ --tw-fade-clear-x: var(--fade-clear-x, var(--fade-clear, 0px));
+}
+@utility fade-clear-top-var {
+ --tw-fade-clear-top: var(--fade-clear-top, var(--fade-clear-y, var(--fade-clear, 0px)));
+}
+@utility fade-clear-bottom-var {
+ --tw-fade-clear-bottom: var(--fade-clear-bottom, var(--fade-clear-y, var(--fade-clear, 0px)));
}
-@utility fade-clear-xy-var {
- --tw-fade-clear-t: var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-b: var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-l: var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
- --tw-fade-clear-r: var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)));
+@utility fade-clear-start-var {
+ --tw-fade-clear-start: var(--fade-clear-start, var(--fade-clear-x, var(--fade-clear, 0px)));
+}
+@utility fade-clear-end-var {
+ --tw-fade-clear-end: var(--fade-clear-end, var(--fade-clear-x, var(--fade-clear, 0px)));
}
-/* Keep shared defaults on public fade elements, not :root: root aliases would
- resolve before local theme overrides, and range aliases would miss
- fade-range utilities. */
@layer utilities {
- .fade-t,
- .fade-b,
- .fade-l,
- .fade-r,
+ .fade,
.fade-y,
+ .fade-top,
+ .fade-bottom,
.fade-x,
- .fade-xy {
- --tw-fade-size-default: var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12));
- --tw-fade-range-active: var(--tw-fade-range, var(--fade-range-md, calc(var(--spacing, 0.25rem) * 12)));
+ .fade-start,
+ .fade-end {
+ --tw-fade-size-default: min(12%, var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12)));
+ --tw-fade-travel-active: var(--tw-fade-travel, var(--fade-travel-sm, calc(var(--spacing, 0.25rem) * 8)));
+ --tw-fade-identity-mask: linear-gradient(#000, #000);
+ --tw-fade-edge-size-t: var(--tw-fade-size-top, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-b: var(--tw-fade-size-bottom, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-l: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-t: var(--tw-fade-clear-top, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-b: var(--tw-fade-clear-bottom, var(--tw-fade-clear-y, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
+ --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
+ --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
+ --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
+ /*
+ Decouple edge transparency from band growth. --tw-fade-t..r drive the
+ band WIDTH (above), so the band eases open over the full travel distance.
+ But the ALPHA at the very edge is driven by --tw-fade-alpha-*, a
+ saturated copy that reaches full transparency within travel/onset of
+ scroll. This covers the overflow clip almost immediately (no hard cut
+ during early scroll) while the band still widens cosmetically over the
+ whole travel. --tw-fade-onset = how fast the edge goes transparent
+ relative to the travel; higher = snappier clip coverage. At t=0 alpha is
+ also 0, so a flush (unscrolled) edge still shows no fade.
+ */
+ --tw-fade-onset: 8;
+ --tw-fade-alpha-t: min(1, calc(var(--tw-fade-t) * var(--tw-fade-onset)));
+ --tw-fade-alpha-b: min(1, calc(var(--tw-fade-b) * var(--tw-fade-onset)));
+ --tw-fade-alpha-l: min(1, calc(var(--tw-fade-l) * var(--tw-fade-onset)));
+ --tw-fade-alpha-r: min(1, calc(var(--tw-fade-r) * var(--tw-fade-onset)));
+ --tw-fade-gradient-t: linear-gradient(
+ to bottom,
+ #000 0 var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t))) var(--tw-fade-edge-clear-t),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.983))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.933))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.854))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.75))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.629))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.5))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.371))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.25))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.146))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.067))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-t) * 0.017))
+ calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
+ );
+ --tw-fade-gradient-b: linear-gradient(
+ to top,
+ #000 0 var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b))) var(--tw-fade-edge-clear-b),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.983))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.933))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.854))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.75))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.629))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.5))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.371))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.25))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.146))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.067))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-b) * 0.017))
+ calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
+ );
+ --tw-fade-gradient-l: linear-gradient(
+ to right,
+ #000 0 var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l))) var(--tw-fade-edge-clear-l),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.983))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.933))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.854))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.75))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.629))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.5))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.371))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.25))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.146))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.067))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-l) * 0.017))
+ calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
+ );
+ --tw-fade-gradient-r: linear-gradient(
+ to left,
+ #000 0 var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r))) var(--tw-fade-edge-clear-r),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.983))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.933))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.854))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.75))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.629))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.5))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.371))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.25))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.146))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.067))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
+ rgb(0 0 0 / calc(1 - var(--tw-fade-alpha-r) * 0.017))
+ calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
+ rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
+ );
+ --tw-fade-mask-l: var(--tw-fade-ltr-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-ltr-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-ltr-start-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-ltr-end-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-ltr-start-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-ltr-end-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-ltr-start-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-ltr-end-animation-range, normal);
+ /*
+ Neutral block-axis defaults. Unlike the l/r hooks above, the t/b
+ animation/timeline/range vars are not @property-registered and are set
+ only in the axis blocks below, so without a local default here a nested
+ fade child would inherit a parent's vertical hook and run a spurious
+ (inert) second scroll animation. The axis blocks override these by
+ source order at equal specificity, so top-level fades are unaffected.
+ */
+ --tw-fade-animation-t: none;
+ --tw-fade-animation-b: none;
+ --tw-fade-timeline-t: none;
+ --tw-fade-timeline-b: none;
+ --tw-fade-animation-range-t: normal;
+ --tw-fade-animation-range-b: normal;
+ mask-image:
+ var(--tw-fade-mask-t, var(--tw-fade-identity-mask)),
+ var(--tw-fade-mask-b, var(--tw-fade-identity-mask)),
+ var(--tw-fade-mask-l, var(--tw-fade-identity-mask)),
+ var(--tw-fade-mask-r, var(--tw-fade-identity-mask));
+ mask-composite: intersect;
+ mask-repeat: no-repeat;
+ mask-size: 100% 100%;
+ }
+
+ .fade:where(:dir(rtl)),
+ .fade-y:where(:dir(rtl)),
+ .fade-top:where(:dir(rtl)),
+ .fade-bottom:where(:dir(rtl)),
+ .fade-x:where(:dir(rtl)),
+ .fade-start:where(:dir(rtl)),
+ .fade-end:where(:dir(rtl)) {
+ --tw-fade-edge-size-l: var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-size-r: var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
+ --tw-fade-edge-clear-l: var(--tw-fade-clear-end, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-edge-clear-r: var(--tw-fade-clear-start, var(--tw-fade-clear-x, var(--tw-fade-clear, 0px)));
+ --tw-fade-mask-l: var(--tw-fade-rtl-end-layer, var(--tw-fade-identity-mask));
+ --tw-fade-mask-r: var(--tw-fade-rtl-start-layer, var(--tw-fade-identity-mask));
+ --tw-fade-animation-l: var(--tw-fade-rtl-end-animation, none);
+ --tw-fade-animation-r: var(--tw-fade-rtl-start-animation, none);
+ --tw-fade-timeline-l: var(--tw-fade-rtl-end-timeline, none);
+ --tw-fade-timeline-r: var(--tw-fade-rtl-start-timeline, none);
+ --tw-fade-animation-range-l: var(--tw-fade-rtl-end-animation-range, normal);
+ --tw-fade-animation-range-r: var(--tw-fade-rtl-start-animation-range, normal);
+ }
+
+ .fade,
+ .fade-y,
+ .fade-top {
+ --tw-fade-mask-t: var(--tw-fade-gradient-t);
+ --tw-fade-animation-t: tw-fade-travel-t;
+ --tw-fade-timeline-t: scroll(self y);
+ --tw-fade-animation-range-t: 0 var(--tw-fade-travel-active);
+ }
+
+ .fade,
+ .fade-y,
+ .fade-bottom {
+ --tw-fade-mask-b: var(--tw-fade-gradient-b);
+ --tw-fade-animation-b: tw-fade-travel-b;
+ --tw-fade-timeline-b: scroll(self y);
+ --tw-fade-animation-range-b: calc(100% - var(--tw-fade-travel-active)) 100%;
+ }
+
+ .fade,
+ .fade-x,
+ .fade-start {
+ --tw-fade-ltr-start-layer: var(--tw-fade-gradient-l);
+ --tw-fade-rtl-start-layer: var(--tw-fade-gradient-r);
+ --tw-fade-ltr-start-animation: tw-fade-travel-l;
+ --tw-fade-rtl-start-animation: tw-fade-travel-r-leading;
+ --tw-fade-ltr-start-timeline: scroll(self inline);
+ --tw-fade-rtl-start-timeline: scroll(self inline);
+ --tw-fade-ltr-start-animation-range: 0 var(--tw-fade-travel-active);
+ --tw-fade-rtl-start-animation-range: 0 var(--tw-fade-travel-active);
+ }
+
+ .fade,
+ .fade-x,
+ .fade-end {
+ --tw-fade-ltr-end-layer: var(--tw-fade-gradient-r);
+ --tw-fade-rtl-end-layer: var(--tw-fade-gradient-l);
+ --tw-fade-ltr-end-animation: tw-fade-travel-r;
+ --tw-fade-rtl-end-animation: tw-fade-travel-l-trailing;
+ --tw-fade-ltr-end-timeline: scroll(self inline);
+ --tw-fade-rtl-end-timeline: scroll(self inline);
+ --tw-fade-ltr-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
+ --tw-fade-rtl-end-animation-range: calc(100% - var(--tw-fade-travel-active)) 100%;
}
-}
-/* Private (only @apply'd by fade-*). The gradient must live on the element so var(--tw-fade-t) resolves per-element — a :root copy would bake in --tw-fade-t:0. */
-@utility tw-fade-mask {
- mask-image:
- var(--tw-fade-mask-t, linear-gradient(#000, #000)),
- var(--tw-fade-mask-b, linear-gradient(#000, #000)),
- var(--tw-fade-mask-l, linear-gradient(#000, #000)),
- var(--tw-fade-mask-r, linear-gradient(#000, #000));
- mask-composite: intersect;
- mask-repeat: no-repeat;
- mask-size: 100% 100%;
@supports (animation-timeline: scroll()) {
- animation:
- tw-fade-reveal-t auto linear both,
- tw-fade-reveal-b auto linear both,
- tw-fade-reveal-l auto linear both,
- tw-fade-reveal-r auto linear both;
- animation-timeline:
- scroll(self y), scroll(self y), scroll(self x), scroll(self x);
- animation-range:
- 0 var(--tw-fade-range-active),
- calc(100% - var(--tw-fade-range-active)) 100%,
- 0 var(--tw-fade-range-active),
- calc(100% - var(--tw-fade-range-active)) 100%;
+ .fade,
+ .fade-y,
+ .fade-top,
+ .fade-bottom,
+ .fade-x,
+ .fade-start,
+ .fade-end {
+ animation:
+ var(--tw-fade-animation-t, none) auto linear both,
+ var(--tw-fade-animation-b, none) auto linear both,
+ var(--tw-fade-animation-l, none) auto linear both,
+ var(--tw-fade-animation-r, none) auto linear both;
+ animation-timeline:
+ var(--tw-fade-timeline-t, none),
+ var(--tw-fade-timeline-b, none),
+ var(--tw-fade-timeline-l, none),
+ var(--tw-fade-timeline-r, none);
+ animation-range:
+ var(--tw-fade-animation-range-t, normal),
+ var(--tw-fade-animation-range-b, normal),
+ var(--tw-fade-animation-range-l, normal),
+ var(--tw-fade-animation-range-r, normal);
+ }
}
+
@supports not (animation-timeline: scroll()) {
- --tw-fade-t: 1;
- --tw-fade-b: 1;
- --tw-fade-l: 1;
- --tw-fade-r: 1;
+ .fade,
+ .fade-y,
+ .fade-top,
+ .fade-bottom,
+ .fade-x,
+ .fade-start,
+ .fade-end {
+ --tw-fade-t: 1;
+ --tw-fade-b: 1;
+ --tw-fade-l: 1;
+ --tw-fade-r: 1;
+ }
}
-}
-@utility tw-fade-edge-t {
- --tw-fade-edge-size-t: var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-t: var(--tw-fade-clear-t, 0px);
- --tw-fade-edge-band-t: calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t));
- --tw-fade-mask-t: linear-gradient(
- to bottom,
- #000 0 var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t))) var(--tw-fade-edge-clear-t),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.983))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.933))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.854))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.75))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.629))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.5))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.371))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.25))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.146))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.067))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-t) * 0.017))
- calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-t) + var(--tw-fade-edge-band-t))
- );
-}
-@utility tw-fade-edge-b {
- --tw-fade-edge-size-b: var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-b: var(--tw-fade-clear-b, 0px);
- --tw-fade-edge-band-b: calc(var(--tw-fade-edge-size-b) * var(--tw-fade-b));
- --tw-fade-mask-b: linear-gradient(
- to top,
- #000 0 var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b))) var(--tw-fade-edge-clear-b),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.983))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.933))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.854))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.75))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.629))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.5))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.371))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.25))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.146))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.067))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-b) * 0.017))
- calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-b) + var(--tw-fade-edge-band-b))
- );
-}
-@utility tw-fade-edge-l {
- --tw-fade-edge-size-l: var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-l: var(--tw-fade-clear-l, 0px);
- --tw-fade-edge-band-l: calc(var(--tw-fade-edge-size-l) * var(--tw-fade-l));
- --tw-fade-mask-l: linear-gradient(
- to right,
- #000 0 var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l))) var(--tw-fade-edge-clear-l),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.983))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.933))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.854))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.75))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.629))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.5))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.371))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.25))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.146))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.067))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-l) * 0.017))
- calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-l) + var(--tw-fade-edge-band-l))
- );
-}
-@utility tw-fade-edge-r {
- --tw-fade-edge-size-r: var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))));
- --tw-fade-edge-clear-r: var(--tw-fade-clear-r, 0px);
- --tw-fade-edge-band-r: calc(var(--tw-fade-edge-size-r) * var(--tw-fade-r));
- --tw-fade-mask-r: linear-gradient(
- to left,
- #000 0 var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r))) var(--tw-fade-edge-clear-r),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.983))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.08333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.933))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.16667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.854))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.25),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.75))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.33333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.629))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.41667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.5))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.5),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.371))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.58333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.25))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.66667),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.146))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.75),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.067))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.83333),
- rgb(0 0 0 / calc(1 - var(--tw-fade-r) * 0.017))
- calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r) * 0.91667),
- rgb(0 0 0 / 1) calc(var(--tw-fade-edge-clear-r) + var(--tw-fade-edge-band-r))
- );
-}
-/* Public utilities select mask layers; tw-fade-mask owns the shared scroll animation so edge utilities compose. */
-@utility fade-t {
- @apply tw-fade-mask tw-fade-edge-t;
-}
-@utility fade-b {
- @apply tw-fade-mask tw-fade-edge-b;
-}
-@utility fade-l {
- @apply tw-fade-mask tw-fade-edge-l;
-}
-@utility fade-r {
- @apply tw-fade-mask tw-fade-edge-r;
-}
-@utility fade-y {
- @apply tw-fade-mask tw-fade-edge-t tw-fade-edge-b;
-}
-@utility fade-x {
- @apply tw-fade-mask tw-fade-edge-l tw-fade-edge-r;
-}
-@utility fade-xy {
- @apply tw-fade-mask tw-fade-edge-t tw-fade-edge-b tw-fade-edge-l tw-fade-edge-r;
-}
+ .fade-none {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+
+ .fade-none-y {
+ --tw-fade-t: 0 !important;
+ --tw-fade-b: 0 !important;
+ }
-/* !important so the static fade outranks the running animation (which itself outranks normal author decls); order-independent vs the edge utility. */
-@utility fade-static {
- --tw-fade-t: 1 !important;
- --tw-fade-b: 1 !important;
- --tw-fade-l: 1 !important;
- --tw-fade-r: 1 !important;
- animation-name: none;
+ .fade-none-x {
+ --tw-fade-l: 0 !important;
+ --tw-fade-r: 0 !important;
+ }
+
+ .fade-always {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
+ }
+
+ .fade-always-y {
+ --tw-fade-t: 1 !important;
+ --tw-fade-b: 1 !important;
+ }
+
+ .fade-always-x {
+ --tw-fade-l: 1 !important;
+ --tw-fade-r: 1 !important;
+ }
}
diff --git a/test/plugin.test.mjs b/test/plugin.test.mjs
index 9aa3b19..e98459c 100644
--- a/test/plugin.test.mjs
+++ b/test/plugin.test.mjs
@@ -1,36 +1,26 @@
/**
* Unit tests for tw-fade.
*
- * npm test (runs `node --test`)
- *
- * tw-fade is now a pure Tailwind v4 CSS plugin: src/tw-fade.css is the single
- * source of truth, authored with @utility / @theme / --value(). These tests
- * compile that source the same way the shipped dist is built (scripts/build-css
- * → the v4 CLI, utilities-only, isolated) and assert on the REAL emitted CSS.
- * That keeps them honest: they exercise the exact bytes a consumer's gets,
- * not a hand-rolled model of what the plugin "should" produce.
- *
- * They lock in the structural invariants that make the effect correct: the
- * registered custom properties (and the @property computational-independence
- * rule that the "only large fades" bug taught us), the scroll-driven reveal
- * wiring, the multi-layer intersect-composited mask, per-edge isolation, and the
- * 13-stop smoothstep ramp. End-to-end visual behaviour is covered separately by
- * build/verify*.mjs (which drive real Chromium).
+ * These tests compile src/tw-fade.css through the same Tailwind v4 path used by
+ * scripts/build-css.mjs, then assert on the emitted CSS bytes. Browser-level
+ * behavior is covered by build/verify*.mjs.
*/
import { test } from 'node:test'
import assert from 'node:assert/strict'
+import fs from 'node:fs'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
import { compileCss } from '../scripts/build-css.mjs'
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+const root = path.resolve(__dirname, '..')
+
const css = compileCss()
-const integerClearCss = compileCss({
- classes: 'fade-clear-t-14 fade-clear-b-14 fade-clear-l-14 fade-clear-r-14 fade-clear-y-14 fade-clear-x-14 fade-clear-xy-14',
+const customCss = compileCss({
+ classes:
+ 'fade-size-[15%] fade-size-top-[56px] fade-travel-[80px] fade-clear-14 fade-clear-y-14 fade-clear-x-14 fade-clear-top-14 fade-clear-bottom-14 fade-clear-start-14 fade-clear-end-14',
})
-/**
- * Return the balanced-brace body of the first ` {` block — including any
- * nested at-rules (@supports …). A tiny brace scanner beats a regex here because
- * the utility blocks legitimately nest braces.
- */
function block(selector, source = css) {
const at = source.indexOf(selector + ' {')
if (at === -1) return null
@@ -43,7 +33,6 @@ function block(selector, source = css) {
return null
}
-/** Parse an @property registration into { syntax, inherits, initial-value }. */
function property(name) {
const body = block('@property ' + name)
if (body == null) return null
@@ -54,18 +43,19 @@ function property(name) {
return { syntax: field('syntax'), inherits: field('inherits'), 'initial-value': field('initial-value') }
}
-/** The value of a single declaration `prop: …;` within a block body. */
function declValue(body, prop) {
- const m = body.match(new RegExp(`${prop}:\\s*([^;]+);`))
+ const m = body?.match(new RegExp(`${prop}:\\s*([^;]+);`))
return m ? m[1].trim() : undefined
}
-const EDGES = { '.fade-t': 't', '.fade-b': 'b', '.fade-l': 'l', '.fade-r': 'r' }
-const ALL = ['.fade-t', '.fade-b', '.fade-l', '.fade-r', '.fade-y', '.fade-x', '.fade-xy']
-const MASK_VARS = ['--tw-fade-mask-t', '--tw-fade-mask-b', '--tw-fade-mask-l', '--tw-fade-mask-r']
-const SIZE_VARS = ['--tw-fade-size', '--tw-fade-size-y', '--tw-fade-size-x', '--tw-fade-size-t', '--tw-fade-size-b', '--tw-fade-size-l', '--tw-fade-size-r']
-const CLEAR_VARS = ['--tw-fade-clear-t', '--tw-fade-clear-b', '--tw-fade-clear-l', '--tw-fade-clear-r']
-const SHARED_DEFAULTS_SELECTOR = '.fade-t, .fade-b, .fade-l, .fade-r, .fade-y, .fade-x, .fade-xy'
+function classSelectors(source = css) {
+ return new Set(
+ [...source.matchAll(/\.(-?[_a-zA-Z][\w-]*)/g)]
+ .map((m) => m[1])
+ .filter((name) => name === 'fade' || name.startsWith('fade-')),
+ )
+}
+
const SCALE = [
['xs', 6],
['sm', 8],
@@ -76,15 +66,76 @@ const SCALE = [
['3xl', 32],
['4xl', 40],
]
-const DEFAULT_SIZE_DECL = 'var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12))'
-const DEFAULT_RANGE_DECL = 'var(--fade-range-md, calc(var(--spacing, 0.25rem) * 12))'
-const RANGE_ACTIVE_DECL = `var(--tw-fade-range, ${DEFAULT_RANGE_DECL})`
-const EDGE_SIZE_DECLS = {
- t: 'var(--tw-fade-size-t, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))))',
- b: 'var(--tw-fade-size-b, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))))',
- l: 'var(--tw-fade-size-l, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))',
- r: 'var(--tw-fade-size-r, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))',
-}
+
+const PUBLIC_DIRECTIONS = ['fade', 'fade-y', 'fade-top', 'fade-bottom', 'fade-x', 'fade-start', 'fade-end']
+// Classes that must NOT compile, both groups intentional:
+// - the old physical API removed in 0.7.0 (fade-t/b/l/r, fade-xy, fade-static, fade-left/right);
+// - the fully-logical block/inline aliases from an earlier draft. The shipped API deliberately
+// uses plain directions (physical top/bottom, direction-aware start/end) instead of
+// fade-inline-start / fade-block-* — see "Why Plain Directions" in MIGRATING.md. Re-adding
+// any of these should be a conscious decision, not an accidental regression.
+const REJECTED_CLASSES = [
+ 'fade-t',
+ 'fade-b',
+ 'fade-l',
+ 'fade-r',
+ 'fade-xy',
+ 'fade-left',
+ 'fade-right',
+ 'fade-block',
+ 'fade-block-start',
+ 'fade-block-end',
+ 'fade-inline',
+ 'fade-inline-start',
+ 'fade-inline-end',
+ 'fade-range-sm',
+ 'fade-ramp-sm',
+ 'fade-static',
+]
+const SHARED_SELECTOR = '.fade, .fade-y, .fade-top, .fade-bottom, .fade-x, .fade-start, .fade-end'
+const RTL_SELECTOR =
+ '.fade:where(:dir(rtl)), .fade-y:where(:dir(rtl)), .fade-top:where(:dir(rtl)), .fade-bottom:where(:dir(rtl)), .fade-x:where(:dir(rtl)), .fade-start:where(:dir(rtl)), .fade-end:where(:dir(rtl))'
+const TOP_SELECTOR = '.fade, .fade-y, .fade-top'
+const BOTTOM_SELECTOR = '.fade, .fade-y, .fade-bottom'
+const START_SELECTOR = '.fade, .fade-x, .fade-start'
+const END_SELECTOR = '.fade, .fade-x, .fade-end'
+const MASK_VARS = ['--tw-fade-mask-t', '--tw-fade-mask-b', '--tw-fade-mask-l', '--tw-fade-mask-r']
+const SIZE_VARS = [
+ '--tw-fade-size',
+ '--tw-fade-size-y',
+ '--tw-fade-size-x',
+ '--tw-fade-size-top',
+ '--tw-fade-size-bottom',
+ '--tw-fade-size-start',
+ '--tw-fade-size-end',
+]
+const CLEAR_VARS = [
+ '--tw-fade-clear',
+ '--tw-fade-clear-y',
+ '--tw-fade-clear-x',
+ '--tw-fade-clear-top',
+ '--tw-fade-clear-bottom',
+ '--tw-fade-clear-start',
+ '--tw-fade-clear-end',
+]
+const ROUTING_VARS = [
+ '--tw-fade-ltr-start-layer',
+ '--tw-fade-ltr-end-layer',
+ '--tw-fade-rtl-start-layer',
+ '--tw-fade-rtl-end-layer',
+ '--tw-fade-ltr-start-animation',
+ '--tw-fade-ltr-end-animation',
+ '--tw-fade-rtl-start-animation',
+ '--tw-fade-rtl-end-animation',
+ '--tw-fade-ltr-start-timeline',
+ '--tw-fade-ltr-end-timeline',
+ '--tw-fade-rtl-start-timeline',
+ '--tw-fade-rtl-end-timeline',
+ '--tw-fade-ltr-start-animation-range',
+ '--tw-fade-ltr-end-animation-range',
+ '--tw-fade-rtl-start-animation-range',
+ '--tw-fade-rtl-end-animation-range',
+]
const ALPHA_MULTIPLIERS = [
'0.983',
'0.933',
@@ -112,26 +163,16 @@ const POSITION_MULTIPLIERS = [
'0.91667',
]
-test('registers the amounts as typed and config/mask layers as universal, non-inheriting', () => {
+test('registers amounts as typed numbers and config/routing vars as universal non-inheriting', () => {
for (const amt of ['--tw-fade-t', '--tw-fade-b', '--tw-fade-l', '--tw-fade-r']) {
const prop = property(amt)
assert.ok(prop, `missing @property ${amt}`)
- // A typed (not `*`) is what lets scroll-driven animation interpolate
- // the amount SMOOTHLY instead of snapping between keyframes.
assert.equal(prop.syntax, '""')
assert.equal(prop.inherits, 'false')
- // Initial 0 = no fade: the correct base state when the timeline is inactive.
assert.equal(prop['initial-value'], '0')
}
- // --tw-fade-size* / --tw-fade-range / --tw-fade-clear-* / --tw-fade-mask-* ARE registered, but with the UNIVERSAL
- // syntax and NO initial-value. A typed @property would reject the
- // font-relative (rem) default and silently drop the registration — the "only
- // large fades" bug. The universal syntax sidesteps that rule; the omitted
- // initial-value keeps an unset value guaranteed-invalid, so `var(--tw-fade-size,
- // )` still falls back to the default. The point of registering at all is
- // `inherits: false`, which stops a nested fade from leaking its parent's
- // size/range/clearance or mask layers.
- for (const v of [...SIZE_VARS, '--tw-fade-range', ...CLEAR_VARS, ...MASK_VARS]) {
+
+ for (const v of [...SIZE_VARS, '--tw-fade-travel', ...CLEAR_VARS, ...MASK_VARS, ...ROUTING_VARS]) {
const prop = property(v)
assert.ok(prop, `missing @property ${v}`)
assert.equal(prop.syntax, '"*"')
@@ -141,16 +182,9 @@ test('registers the amounts as typed and config/mask layers as universa
})
test('every typed @property has a computationally-independent initial-value', () => {
- // Regression guard for the "only the large panel fades" bug: a registered
- // @property with a TYPED syntax (e.g. ) whose initial-value uses a
- // context-relative unit (rem/em/%/vh/cqw/lh/…) is REJECTED by the browser,
- // leaving the variable unset. We assert the REAL invariant — typed syntax pairs
- // with an independent initial — via an ABSOLUTE-unit allowlist (case-
- // insensitive, future-proof against new relative units). The universal syntax
- // (`*`) carries no such rule and legitimately omits initial-value, so it's exempt.
const ABSOLUTE = /^-?(?:\d+\.?\d*|\.\d+)(px|cm|mm|in|pt|pc|q)?$/i
const names = [...css.matchAll(/@property\s+(--[\w-]+)\s*\{/g)].map((m) => m[1])
- assert.ok(names.length >= 10, 'expected at least 10 registered properties')
+ assert.ok(names.length >= 20, 'expected registered properties')
for (const name of names) {
const decl = property(name)
if (decl.syntax === '"*"') {
@@ -166,300 +200,304 @@ test('every typed @property has a computationally-independent initial-value', ()
}
})
-test('leading edges reveal 0→1, trailing edges hide 1→0', () => {
- const kf = (n) => block('@keyframes ' + n)
- assert.match(kf('tw-fade-reveal-t'), /from\s*\{[^}]*--tw-fade-t:\s*0/)
- assert.match(kf('tw-fade-reveal-t'), /to\s*\{[^}]*--tw-fade-t:\s*1/)
- assert.match(kf('tw-fade-reveal-b'), /from\s*\{[^}]*--tw-fade-b:\s*1/)
- assert.match(kf('tw-fade-reveal-b'), /to\s*\{[^}]*--tw-fade-b:\s*0/)
- assert.match(kf('tw-fade-reveal-l'), /from\s*\{[^}]*--tw-fade-l:\s*0/)
- assert.match(kf('tw-fade-reveal-r'), /from\s*\{[^}]*--tw-fade-r:\s*1/)
+test('direction inventory matches the plain public API and stays within budget', () => {
+ const selectors = classSelectors()
+ for (const name of PUBLIC_DIRECTIONS) assert.ok(selectors.has(name), `missing .${name}`)
+ for (const name of REJECTED_CLASSES) assert.equal(selectors.has(name), false, `must not emit .${name}`)
+ assert.ok(selectors.size <= 150, `selector budget exceeded: ${selectors.size}`)
+ assert.ok(css.length <= 55_000, `byte budget exceeded: ${css.length}`)
})
-test('every edge utility carries the composited multi-layer mask base', () => {
- for (const cls of ALL) {
- const u = block(cls)
- assert.ok(u, `missing ${cls}`)
- // intersect is mandatory: the initial `add` (union) would erase the fade.
- assert.equal(declValue(u, 'mask-composite'), 'intersect')
- assert.equal(declValue(u, 'mask-repeat'), 'no-repeat')
- assert.equal(declValue(u, 'mask-size'), '100% 100%')
- // Four layers, each defaulting to the opaque identity (no-op) gradient.
- const layers = u.split('linear-gradient(#000, #000)').length - 1
- assert.equal(layers, 4, `${cls} should have 4 identity fallbacks`)
- }
+test('prebuilt dist is generated from the current default compile output', () => {
+ const dist = fs.readFileSync(path.join(root, 'dist', 'tw-fade.css'), 'utf8')
+ assert.equal(dist, css)
})
-test('each directional utility sets ONLY its own mask layer', () => {
- for (const [cls, edge] of Object.entries(EDGES)) {
- const u = block(cls)
- const mine = `--tw-fade-mask-${edge}`
- for (const v of MASK_VARS) {
- // A real declaration is `--tw-fade-mask-x: …`; a var() reference is `--tw-fade-mask-x, …`.
- // Matching the colon distinguishes the two, so the shared 4-layer fallback
- // (which references all four) doesn't read as "this utility sets all four".
- if (v === mine) assert.ok(declValue(u, v), `${cls} must set ${v}`)
- else assert.equal(declValue(u, v), undefined, `${cls} must NOT set ${v}`)
+// Guards against a dormant retired utility name surviving in the shipped CSS.
+// The REJECTED_CLASSES checks only prove the *default* compile omits a name; a
+// stray @utility / @property / @keyframes / theme token for a retired name
+// ("range" -> "ramp" -> "travel", and the never-shipped intermediate "reveal")
+// could still ship undetected. Scan the source and prebuilt artifacts on disk.
+// Scoped to the CSS files only — README/MIGRATING/CHANGELOG legitimately
+// reference the old names when documenting the rename. Token-specific patterns,
+// so the English nouns "reveal"/"ramp" in prose/comments are never matched.
+test('shipped CSS carries no retired reveal/range/ramp token names', () => {
+ const retired = [
+ /fade-reveal/,
+ /fade-range/,
+ /fade-ramp/,
+ /--fade-reveal/,
+ /--fade-range/,
+ /--fade-ramp/,
+ /--tw-fade-reveal/,
+ /--tw-fade-range/,
+ /--tw-fade-ramp/,
+ /tw-fade-reveal/,
+ /tw-fade-range/,
+ /tw-fade-ramp/,
+ ]
+ for (const file of ['src/tw-fade.css', 'dist/tw-fade.css']) {
+ const source = fs.readFileSync(path.join(root, file), 'utf8')
+ for (const pattern of retired) {
+ assert.equal(pattern.test(source), false, `${file} still contains retired token ${pattern}`)
}
}
})
-test('axis shorthands set exactly their constituent mask layers', () => {
- const y = block('.fade-y')
- assert.ok(declValue(y, '--tw-fade-mask-t') && declValue(y, '--tw-fade-mask-b'))
- assert.equal(declValue(y, '--tw-fade-mask-l'), undefined)
- const x = block('.fade-x')
- assert.ok(declValue(x, '--tw-fade-mask-l') && declValue(x, '--tw-fade-mask-r'))
- assert.equal(declValue(x, '--tw-fade-mask-t'), undefined)
- const xy = block('.fade-xy')
- for (const v of MASK_VARS) assert.ok(declValue(xy, v), `xy must set ${v}`)
+test('leading and trailing keyframes include RTL horizontal variants', () => {
+ const kf = (n) => block('@keyframes ' + n)
+ assert.match(kf('tw-fade-travel-t'), /from\s*\{[^}]*--tw-fade-t:\s*0/)
+ assert.match(kf('tw-fade-travel-t'), /to\s*\{[^}]*--tw-fade-t:\s*1/)
+ assert.match(kf('tw-fade-travel-b'), /from\s*\{[^}]*--tw-fade-b:\s*1/)
+ assert.match(kf('tw-fade-travel-b'), /to\s*\{[^}]*--tw-fade-b:\s*0/)
+ assert.match(kf('tw-fade-travel-l'), /from\s*\{[^}]*--tw-fade-l:\s*0/)
+ assert.match(kf('tw-fade-travel-r'), /from\s*\{[^}]*--tw-fade-r:\s*1/)
+ assert.match(kf('tw-fade-travel-r-leading'), /from\s*\{[^}]*--tw-fade-r:\s*0/)
+ assert.match(kf('tw-fade-travel-r-leading'), /to\s*\{[^}]*--tw-fade-r:\s*1/)
+ assert.match(kf('tw-fade-travel-l-trailing'), /from\s*\{[^}]*--tw-fade-l:\s*1/)
+ assert.match(kf('tw-fade-travel-l-trailing'), /to\s*\{[^}]*--tw-fade-l:\s*0/)
+})
+
+test('the shared mask setup owns four physical layers and scroll animation wiring', () => {
+ const shared = block(SHARED_SELECTOR)
+ assert.ok(shared, 'missing shared direction block')
+ assert.equal(declValue(shared, 'mask-composite'), 'intersect')
+ assert.equal(declValue(shared, 'mask-repeat'), 'no-repeat')
+ assert.equal(declValue(shared, 'mask-size'), '100% 100%')
+ const maskImage = declValue(shared, 'mask-image')
+ for (const v of MASK_VARS) assert.match(maskImage, new RegExp(`var\\(${v.replaceAll('-', '\\-')}`), `${v} in mask-image`)
+
+ const supports = block('@supports (animation-timeline: scroll())')
+ const animated = block(SHARED_SELECTOR, supports)
+ assert.ok(animated, 'missing animation support block')
+ assert.equal((declValue(animated, 'animation').match(/auto linear both/g) || []).length, 4)
+ assert.equal((declValue(animated, 'animation-timeline').match(/var\(--tw-fade-timeline-/g) || []).length, 4)
+ assert.equal((declValue(animated, 'animation-range').match(/var\(--tw-fade-animation-range-/g) || []).length, 4)
})
-test('mask gradients point the right way and are driven by their amount', () => {
- assert.match(declValue(block('.fade-t'), '--tw-fade-mask-t'), /^linear-gradient\(\s*to bottom/)
- assert.match(declValue(block('.fade-b'), '--tw-fade-mask-b'), /^linear-gradient\(\s*to top/)
- assert.match(declValue(block('.fade-l'), '--tw-fade-mask-l'), /^linear-gradient\(\s*to right/)
- assert.match(declValue(block('.fade-r'), '--tw-fade-mask-r'), /^linear-gradient\(\s*to left/)
- // The amount scales both the gradient alpha (1 - amount * …) and its length
- // (size * amount), so at amount 0 the layer collapses to fully opaque.
- const tBlock = block('.fade-t')
- const t = declValue(tBlock, '--tw-fade-mask-t')
- assert.match(t, /calc\(1 - var\(--tw-fade-t\)\)/)
- // Size is resolved through a shared default alias, then multiplied by the
- // scroll-gated amount. This keeps the gradient readable without weakening the
- // "no size utility still fades" invariant.
- assert.equal(declValue(block(SHARED_DEFAULTS_SELECTOR), '--tw-fade-size-default'), DEFAULT_SIZE_DECL)
- assert.equal(declValue(tBlock, '--tw-fade-edge-size-t'), EDGE_SIZE_DECLS.t)
- assert.equal(declValue(tBlock, '--tw-fade-edge-band-t'), 'calc(var(--tw-fade-edge-size-t) * var(--tw-fade-t))')
- // Clearance is an opaque edge band before the fade ramp. This lets sticky
- // headers/footers stay unmasked while rows beneath still dissolve at the edge.
- assert.equal(declValue(tBlock, '--tw-fade-edge-clear-t'), 'var(--tw-fade-clear-t, 0px)')
- assert.match(t, /#000 0 var\(--tw-fade-edge-clear-t\)/)
- assert.match(t, /rgb\(0 0 0 \/ calc\(1 - var\(--tw-fade-t\)\)\) var\(--tw-fade-edge-clear-t\)/)
+test('direction classes select the expected layers and central RTL routing', () => {
+ const top = block(TOP_SELECTOR)
+ assert.equal(declValue(top, '--tw-fade-mask-t'), 'var(--tw-fade-gradient-t)')
+ assert.equal(declValue(top, '--tw-fade-animation-t'), 'tw-fade-travel-t')
+ assert.equal(declValue(top, '--tw-fade-timeline-t'), 'scroll(self y)')
+
+ const bottom = block(BOTTOM_SELECTOR)
+ assert.equal(declValue(bottom, '--tw-fade-mask-b'), 'var(--tw-fade-gradient-b)')
+ assert.equal(declValue(bottom, '--tw-fade-animation-b'), 'tw-fade-travel-b')
+ assert.equal(declValue(bottom, '--tw-fade-timeline-b'), 'scroll(self y)')
+
+ const start = block(START_SELECTOR)
+ assert.equal(declValue(start, '--tw-fade-ltr-start-layer'), 'var(--tw-fade-gradient-l)')
+ assert.equal(declValue(start, '--tw-fade-rtl-start-layer'), 'var(--tw-fade-gradient-r)')
+ assert.equal(declValue(start, '--tw-fade-ltr-start-animation'), 'tw-fade-travel-l')
+ assert.equal(declValue(start, '--tw-fade-rtl-start-animation'), 'tw-fade-travel-r-leading')
+ assert.equal(declValue(start, '--tw-fade-ltr-start-timeline'), 'scroll(self inline)')
+ assert.equal(declValue(start, '--tw-fade-rtl-start-timeline'), 'scroll(self inline)')
+
+ const end = block(END_SELECTOR)
+ assert.equal(declValue(end, '--tw-fade-ltr-end-layer'), 'var(--tw-fade-gradient-r)')
+ assert.equal(declValue(end, '--tw-fade-rtl-end-layer'), 'var(--tw-fade-gradient-l)')
+ assert.equal(declValue(end, '--tw-fade-ltr-end-animation'), 'tw-fade-travel-r')
+ assert.equal(declValue(end, '--tw-fade-rtl-end-animation'), 'tw-fade-travel-l-trailing')
+
+ const rtl = block(RTL_SELECTOR)
+ assert.ok(rtl, 'missing central RTL routing block')
+ assert.equal(declValue(rtl, '--tw-fade-mask-l'), 'var(--tw-fade-rtl-end-layer, var(--tw-fade-identity-mask))')
+ assert.equal(declValue(rtl, '--tw-fade-mask-r'), 'var(--tw-fade-rtl-start-layer, var(--tw-fade-identity-mask))')
+ assert.equal(declValue(rtl, '--tw-fade-animation-l'), 'var(--tw-fade-rtl-end-animation, none)')
+ assert.equal(declValue(rtl, '--tw-fade-animation-r'), 'var(--tw-fade-rtl-start-animation, none)')
+ assert.equal(declValue(rtl, '--tw-fade-edge-size-l'), 'var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))')
+ assert.equal(declValue(rtl, '--tw-fade-edge-size-r'), 'var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))')
})
test('the smoothstep ramp is the 13-stop sigmoid from the reference', () => {
- for (const [cls, edge] of Object.entries(EDGES)) {
- const grad = declValue(block(cls), `--tw-fade-mask-${edge}`)
+ const shared = block(SHARED_SELECTOR)
+ const edges = { t: '--tw-fade-gradient-t', b: '--tw-fade-gradient-b', l: '--tw-fade-gradient-l', r: '--tw-fade-gradient-r' }
+ for (const [edge, prop] of Object.entries(edges)) {
+ const grad = declValue(shared, prop)
+ assert.ok(grad, `missing ${prop}`)
const stops = (grad.match(/rgb\(0 0 0 \//g) || []).length
- assert.equal(stops, 13, `${cls} gradient should have 13 colour stops`)
+ assert.equal(stops, 13, `${prop} should have 13 colour stops`)
const alphaMultipliers = [
- ...grad.matchAll(new RegExp(`var\\(--tw-fade-${edge}\\)\\s*\\*\\s*([0-9.]+)`, 'g')),
+ ...grad.matchAll(new RegExp(`var\\(--tw-fade-alpha-${edge}\\)\\s*\\*\\s*([0-9.]+)`, 'g')),
].map((m) => m[1])
- assert.deepEqual(alphaMultipliers, ALPHA_MULTIPLIERS, `${cls} alpha ramp coefficients must stay exact`)
+ assert.deepEqual(alphaMultipliers, ALPHA_MULTIPLIERS, `${prop} alpha ramp coefficients must stay exact`)
const positionMultipliers = [
...grad.matchAll(new RegExp(`var\\(--tw-fade-edge-band-${edge}\\)\\s*\\*\\s*([0-9.]+)`, 'g')),
].map((m) => m[1])
- assert.deepEqual(positionMultipliers, POSITION_MULTIPLIERS, `${cls} position ramp coefficients must stay exact`)
+ assert.deepEqual(positionMultipliers, POSITION_MULTIPLIERS, `${prop} position ramp coefficients must stay exact`)
}
- // The curve endpoints: first stop fully transparent-capable (1 - amount), last
- // stop fully opaque (rgb(0 0 0 / 1)) at the band's far edge, offset after any
- // sticky-item clearance band.
- const t = declValue(block('.fade-t'), '--tw-fade-mask-t')
- assert.match(t, /rgb\(0 0 0 \/ calc\(1 - var\(--tw-fade-t\)\)\) var\(--tw-fade-edge-clear-t\),/)
- assert.match(
- t,
- new RegExp(String.raw`rgb\(0 0 0 \/ 1\) calc\(var\(--tw-fade-edge-clear-t\) \+ var\(--tw-fade-edge-band-t\)\)\s*\)\s*$`),
- )
+ assert.match(declValue(shared, '--tw-fade-gradient-t'), /^linear-gradient\(\s*to bottom/)
+ assert.match(declValue(shared, '--tw-fade-gradient-b'), /^linear-gradient\(\s*to top/)
+ assert.match(declValue(shared, '--tw-fade-gradient-l'), /^linear-gradient\(\s*to right/)
+ assert.match(declValue(shared, '--tw-fade-gradient-r'), /^linear-gradient\(\s*to left/)
})
-test('every public fade utility uses the shared four-edge reveal setup', () => {
- // Public utilities need the same animation shorthand/longhands so arbitrary
- // combinations like `fade-t fade-r` compose instead of last-declaration-wins.
- // Physical axes (scroll(self y) / scroll(self x)) match the mask gradients.
- const defaults = block(SHARED_DEFAULTS_SELECTOR)
- assert.equal(declValue(defaults, '--tw-fade-range-active'), RANGE_ACTIVE_DECL)
- assert.ok(!css.includes('--tw-fade-range-default'), 'range default should be folded into --tw-fade-range-active')
- for (const cls of ALL) {
- const u = block(cls)
- const s = block('@supports (animation-timeline: scroll())', block(cls))
- assert.ok(s, `${cls} must include the scroll-timeline support block`)
- assert.equal(declValue(s, 'animation').split(',').length, 4, `${cls} must animate all four amounts`)
- assert.match(s, /animation-timeline:\s*scroll\(self y\), scroll\(self y\), scroll\(self x\), scroll\(self x\)/)
- // Leading reveals over the first range; trailing hides over the last. Range
- // is resolved once by the shared defaults rule (same fix as --tw-fade-size).
- assert.equal(declValue(u, '--tw-fade-range-active'), undefined)
+test('edge alpha is decoupled from band growth so the clip is covered before the band finishes widening', () => {
+ const shared = block(SHARED_SELECTOR)
+ assert.ok(shared, 'missing shared block')
+
+ // The onset constant sets how fast the edge reaches full transparency relative
+ // to the travel: full coverage by travel/onset of scroll, independent of band width.
+ assert.equal(declValue(shared, '--tw-fade-onset'), '8')
+
+ for (const edge of ['t', 'b', 'l', 'r']) {
+ // alpha-* is a saturated copy of raw scroll progress (clamped at 1). This is
+ // what drives edge transparency, so the clip is covered almost immediately.
+ assert.equal(
+ declValue(shared, `--tw-fade-alpha-${edge}`),
+ `min(1, calc(var(--tw-fade-${edge}) * var(--tw-fade-onset)))`,
+ `--tw-fade-alpha-${edge} must saturate raw progress`,
+ )
+ // Band WIDTH stays keyed to raw progress, so it still eases open over the
+ // full travel distance (cosmetic widening) while the edge is already covered.
+ assert.equal(
+ declValue(shared, `--tw-fade-edge-band-${edge}`),
+ `calc(var(--tw-fade-edge-size-${edge}) * var(--tw-fade-${edge}))`,
+ `band size for ${edge} must stay on raw --tw-fade-${edge}`,
+ )
+ const grad = declValue(shared, `--tw-fade-gradient-${edge}`)
+ // Every alpha stop reads the saturated alpha var...
assert.match(
- s,
- new RegExp(
- String.raw`animation-range:\s*0 var\(--tw-fade-range-active\), calc\(100% - var\(--tw-fade-range-active\)\) 100%, 0 var\(--tw-fade-range-active\), calc\(100% - var\(--tw-fade-range-active\)\) 100%`,
- ),
+ grad,
+ new RegExp(`calc\\(1 - var\\(--tw-fade-alpha-${edge}\\)`),
+ `${edge} gradient alpha must read the saturated alpha var`,
+ )
+ // ...and never raw progress, or the clip would re-couple to the full travel.
+ assert.doesNotMatch(
+ grad,
+ new RegExp(`calc\\(1 - var\\(--tw-fade-${edge}\\)`),
+ `${edge} gradient alpha must not key off raw --tw-fade-${edge}`,
)
}
})
-test('provides a static fallback when scroll-driven animation is unsupported', () => {
- for (const cls of ALL) {
- const fb = block('@supports not (animation-timeline: scroll())', block(cls))
- assert.ok(fb, `${cls} must include the static fallback block`)
- for (const amt of ['--tw-fade-t', '--tw-fade-b', '--tw-fade-l', '--tw-fade-r']) {
- assert.equal(declValue(fb, amt), '1', `${cls} fallback must pin ${amt}`)
- }
- }
-})
-
-test('fade-static forces the fade on, order-independently, and disables the animation', () => {
- const s = block('.fade-static')
- // The amounts are pinned with !important so fade-static wins regardless of where
- // Tailwind sorts it relative to the reveal animation — an important author value
- // outranks a running keyframe animation in the cascade.
+test('static fallback pins selected fades on when scroll-driven animation is unsupported', () => {
+ const fallback = block('@supports not (animation-timeline: scroll())')
+ const shared = block(SHARED_SELECTOR, fallback)
+ assert.ok(shared, 'missing fallback block')
for (const amt of ['--tw-fade-t', '--tw-fade-b', '--tw-fade-l', '--tw-fade-r']) {
- assert.equal(declValue(s, amt), '1 !important', `${amt} must be pinned !important`)
+ assert.equal(declValue(shared, amt), '1')
}
- assert.equal(declValue(s, 'animation-name'), 'none')
})
-test('exposes the size and range scales as theme-backed utilities', () => {
+test('exposes the size and travel scales as theme-backed utilities', () => {
for (const [name] of SCALE) {
assert.equal(declValue(block(`.fade-size-${name}`), '--tw-fade-size'), `var(--fade-size-${name})`)
- assert.equal(declValue(block(`.fade-size-t-${name}`), '--tw-fade-size-t'), `var(--fade-size-${name})`)
- assert.equal(declValue(block(`.fade-size-b-${name}`), '--tw-fade-size-b'), `var(--fade-size-${name})`)
- assert.equal(declValue(block(`.fade-size-l-${name}`), '--tw-fade-size-l'), `var(--fade-size-${name})`)
- assert.equal(declValue(block(`.fade-size-r-${name}`), '--tw-fade-size-r'), `var(--fade-size-${name})`)
assert.equal(declValue(block(`.fade-size-y-${name}`), '--tw-fade-size-y'), `var(--fade-size-${name})`)
assert.equal(declValue(block(`.fade-size-x-${name}`), '--tw-fade-size-x'), `var(--fade-size-${name})`)
- assert.equal(declValue(block(`.fade-range-${name}`), '--tw-fade-range'), `var(--fade-range-${name})`)
+ assert.equal(declValue(block(`.fade-size-top-${name}`), '--tw-fade-size-top'), `var(--fade-size-${name})`)
+ assert.equal(declValue(block(`.fade-size-bottom-${name}`), '--tw-fade-size-bottom'), `var(--fade-size-${name})`)
+ assert.equal(declValue(block(`.fade-size-start-${name}`), '--tw-fade-size-start'), `var(--fade-size-${name})`)
+ assert.equal(declValue(block(`.fade-size-end-${name}`), '--tw-fade-size-end'), `var(--fade-size-${name})`)
+ assert.equal(declValue(block(`.fade-travel-${name}`), '--tw-fade-travel'), `var(--fade-travel-${name})`)
}
- // The theme exposes the actual scale values for consumers to override/extend.
- const root = block(':root, :host')
+ const rootBlock = block(':root, :host')
for (const [name, units] of SCALE) {
const expected = `calc(var(--spacing, 0.25rem) * ${units})`
- assert.equal(declValue(root, `--fade-size-${name}`), expected)
- assert.equal(declValue(root, `--fade-range-${name}`), expected)
- }
- // No bare `.fade-size` / `.fade-range` no-op utility leaks out.
- assert.equal(block('.fade-size'), null)
- assert.equal(block('.fade-range'), null)
-})
-
-test('each edge resolves size as edge over axis over global over default', () => {
- const defaults = block(SHARED_DEFAULTS_SELECTOR)
- assert.equal(declValue(defaults, '--tw-fade-size-default'), DEFAULT_SIZE_DECL)
- for (const [cls, edge] of Object.entries(EDGES)) {
- const u = block(cls)
- assert.equal(declValue(u, '--tw-fade-size-default'), undefined)
- assert.equal(declValue(u, `--tw-fade-edge-size-${edge}`), EDGE_SIZE_DECLS[edge])
- assert.equal(declValue(u, `--tw-fade-edge-band-${edge}`), `calc(var(--tw-fade-edge-size-${edge}) * var(--tw-fade-${edge}))`)
+ assert.equal(declValue(rootBlock, `--fade-size-${name}`), expected)
+ assert.equal(declValue(rootBlock, `--fade-travel-${name}`), expected)
}
+ assert.equal(block('.fade-range-sm'), null)
+ assert.equal(block('.fade-size-left-sm'), null)
})
-test('exposes edge-clearance utilities for sticky content', () => {
- for (const [name] of SCALE) {
- assert.equal(declValue(block(`.fade-clear-t-${name}`), '--tw-fade-clear-t'), `var(--fade-clear-${name})`)
- assert.equal(declValue(block(`.fade-clear-b-${name}`), '--tw-fade-clear-b'), `var(--fade-clear-${name})`)
- assert.equal(declValue(block(`.fade-clear-l-${name}`), '--tw-fade-clear-l'), `var(--fade-clear-${name})`)
- assert.equal(declValue(block(`.fade-clear-r-${name}`), '--tw-fade-clear-r'), `var(--fade-clear-${name})`)
-
- const y = block(`.fade-clear-y-${name}`)
- assert.equal(declValue(y, '--tw-fade-clear-t'), `var(--fade-clear-${name})`)
- assert.equal(declValue(y, '--tw-fade-clear-b'), `var(--fade-clear-${name})`)
- assert.equal(declValue(y, '--tw-fade-clear-l'), undefined)
-
- const x = block(`.fade-clear-x-${name}`)
- assert.equal(declValue(x, '--tw-fade-clear-l'), `var(--fade-clear-${name})`)
- assert.equal(declValue(x, '--tw-fade-clear-r'), `var(--fade-clear-${name})`)
- assert.equal(declValue(x, '--tw-fade-clear-t'), undefined)
-
- const xy = block(`.fade-clear-xy-${name}`)
- for (const v of CLEAR_VARS) assert.equal(declValue(xy, v), `var(--fade-clear-${name})`, `xy must set ${v}`)
- }
-
- const root = block(':root, :host')
- for (const [name, units] of SCALE) {
- assert.equal(declValue(root, `--fade-clear-${name}`), `calc(var(--spacing, 0.25rem) * ${units})`)
- }
- assert.equal(block('.fade-clear'), null)
-})
-
-test('supports integer spacing values for edge clearance in the Tailwind source path', () => {
- const expected = 'calc(var(--spacing, 0.25rem) * 14)'
- assert.equal(declValue(block('.fade-clear-t-14', integerClearCss), '--tw-fade-clear-t'), expected)
- assert.equal(declValue(block('.fade-clear-b-14', integerClearCss), '--tw-fade-clear-b'), expected)
- assert.equal(declValue(block('.fade-clear-l-14', integerClearCss), '--tw-fade-clear-l'), expected)
- assert.equal(declValue(block('.fade-clear-r-14', integerClearCss), '--tw-fade-clear-r'), expected)
-
- const y = block('.fade-clear-y-14', integerClearCss)
- assert.equal(declValue(y, '--tw-fade-clear-t'), expected)
- assert.equal(declValue(y, '--tw-fade-clear-b'), expected)
- assert.equal(declValue(y, '--tw-fade-clear-l'), undefined)
-
- const x = block('.fade-clear-x-14', integerClearCss)
- assert.equal(declValue(x, '--tw-fade-clear-l'), expected)
- assert.equal(declValue(x, '--tw-fade-clear-r'), expected)
- assert.equal(declValue(x, '--tw-fade-clear-t'), undefined)
-
- const xy = block('.fade-clear-xy-14', integerClearCss)
- for (const v of CLEAR_VARS) assert.equal(declValue(xy, v), expected, `integer xy must set ${v}`)
-})
-
-test('exposes public variable utilities for dynamic edge clearance', () => {
+test('size resolves as edge over axis over global over capped default', () => {
+ const shared = block(SHARED_SELECTOR)
+ assert.equal(declValue(shared, '--tw-fade-size-default'), 'min(12%, var(--fade-size-md, calc(var(--spacing, 0.25rem) * 12)))')
assert.equal(
- declValue(block('.fade-clear-t-var'), '--tw-fade-clear-t'),
- 'var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
+ declValue(shared, '--tw-fade-edge-size-t'),
+ 'var(--tw-fade-size-top, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))))',
)
assert.equal(
- declValue(block('.fade-clear-b-var'), '--tw-fade-clear-b'),
- 'var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
+ declValue(shared, '--tw-fade-edge-size-b'),
+ 'var(--tw-fade-size-bottom, var(--tw-fade-size-y, var(--tw-fade-size, var(--tw-fade-size-default))))',
)
assert.equal(
- declValue(block('.fade-clear-l-var'), '--tw-fade-clear-l'),
- 'var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
+ declValue(shared, '--tw-fade-edge-size-l'),
+ 'var(--tw-fade-size-start, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))',
)
assert.equal(
- declValue(block('.fade-clear-r-var'), '--tw-fade-clear-r'),
- 'var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
+ declValue(shared, '--tw-fade-edge-size-r'),
+ 'var(--tw-fade-size-end, var(--tw-fade-size-x, var(--tw-fade-size, var(--tw-fade-size-default))))',
)
+})
- const y = block('.fade-clear-y-var')
- assert.equal(
- declValue(y, '--tw-fade-clear-t'),
- 'var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
- )
- assert.equal(
- declValue(y, '--tw-fade-clear-b'),
- 'var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
- )
- assert.equal(declValue(y, '--tw-fade-clear-l'), undefined)
+test('arbitrary size and travel utilities compile only through the source path', () => {
+ assert.equal(declValue(block('.fade-size-\\[15\\%\\]', customCss), '--tw-fade-size'), '15%')
+ assert.equal(declValue(block('.fade-size-top-\\[56px\\]', customCss), '--tw-fade-size-top'), '56px')
+ assert.equal(declValue(block('.fade-travel-\\[80px\\]', customCss), '--tw-fade-travel'), '80px')
+ assert.equal(block('.fade-size-\\[15\\%\\]'), null)
+ assert.equal(block('.fade-travel-\\[80px\\]'), null)
+})
- const x = block('.fade-clear-x-var')
- assert.equal(
- declValue(x, '--tw-fade-clear-l'),
- 'var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
- )
- assert.equal(
- declValue(x, '--tw-fade-clear-r'),
- 'var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
- )
- assert.equal(declValue(x, '--tw-fade-clear-t'), undefined)
+test('exposes directional clear utilities and source-path integer clear values', () => {
+ for (const [name] of SCALE) {
+ assert.equal(declValue(block(`.fade-clear-${name}`), '--tw-fade-clear'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-y-${name}`), '--tw-fade-clear-y'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-x-${name}`), '--tw-fade-clear-x'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-top-${name}`), '--tw-fade-clear-top'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-bottom-${name}`), '--tw-fade-clear-bottom'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-start-${name}`), '--tw-fade-clear-start'), `var(--fade-clear-${name})`)
+ assert.equal(declValue(block(`.fade-clear-end-${name}`), '--tw-fade-clear-end'), `var(--fade-clear-${name})`)
+ }
+ const expected = 'calc(var(--spacing, 0.25rem) * 14)'
+ assert.equal(declValue(block('.fade-clear-14', customCss), '--tw-fade-clear'), expected)
+ assert.equal(declValue(block('.fade-clear-top-14', customCss), '--tw-fade-clear-top'), expected)
+ assert.equal(declValue(block('.fade-clear-start-14', customCss), '--tw-fade-clear-start'), expected)
+ assert.equal(block('.fade-clear-left-sm'), null)
+ assert.equal(block('.fade-clear-xy-sm'), null)
+})
- const xy = block('.fade-clear-xy-var')
+test('dynamic clear variables follow edge to axis to global precedence', () => {
+ assert.equal(declValue(block('.fade-clear-var'), '--tw-fade-clear'), 'var(--fade-clear, 0px)')
+ assert.equal(declValue(block('.fade-clear-y-var'), '--tw-fade-clear-y'), 'var(--fade-clear-y, var(--fade-clear, 0px))')
+ assert.equal(declValue(block('.fade-clear-x-var'), '--tw-fade-clear-x'), 'var(--fade-clear-x, var(--fade-clear, 0px))')
assert.equal(
- declValue(xy, '--tw-fade-clear-t'),
- 'var(--fade-clear-t, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
+ declValue(block('.fade-clear-top-var'), '--tw-fade-clear-top'),
+ 'var(--fade-clear-top, var(--fade-clear-y, var(--fade-clear, 0px)))',
)
assert.equal(
- declValue(xy, '--tw-fade-clear-b'),
- 'var(--fade-clear-b, var(--fade-clear-y, var(--fade-clear-xy, 0px)))',
+ declValue(block('.fade-clear-bottom-var'), '--tw-fade-clear-bottom'),
+ 'var(--fade-clear-bottom, var(--fade-clear-y, var(--fade-clear, 0px)))',
)
assert.equal(
- declValue(xy, '--tw-fade-clear-l'),
- 'var(--fade-clear-l, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
+ declValue(block('.fade-clear-start-var'), '--tw-fade-clear-start'),
+ 'var(--fade-clear-start, var(--fade-clear-x, var(--fade-clear, 0px)))',
)
assert.equal(
- declValue(xy, '--tw-fade-clear-r'),
- 'var(--fade-clear-r, var(--fade-clear-x, var(--fade-clear-xy, 0px)))',
+ declValue(block('.fade-clear-end-var'), '--tw-fade-clear-end'),
+ 'var(--fade-clear-end, var(--fade-clear-x, var(--fade-clear, 0px)))',
)
})
+test('fade-none and fade-always pin amounts without disabling shared animations', () => {
+ const none = block('.fade-none')
+ for (const amt of ['--tw-fade-t', '--tw-fade-b', '--tw-fade-l', '--tw-fade-r']) {
+ assert.equal(declValue(none, amt), '0 !important')
+ }
+ const noneY = block('.fade-none-y')
+ assert.equal(declValue(noneY, '--tw-fade-t'), '0 !important')
+ assert.equal(declValue(noneY, '--tw-fade-b'), '0 !important')
+ assert.equal(declValue(noneY, '--tw-fade-l'), undefined)
+
+ const noneX = block('.fade-none-x')
+ assert.equal(declValue(noneX, '--tw-fade-l'), '0 !important')
+ assert.equal(declValue(noneX, '--tw-fade-r'), '0 !important')
+ assert.equal(declValue(noneX, '--tw-fade-t'), undefined)
+
+ const always = block('.fade-always')
+ for (const amt of ['--tw-fade-t', '--tw-fade-b', '--tw-fade-l', '--tw-fade-r']) {
+ assert.equal(declValue(always, amt), '1 !important')
+ }
+ assert.ok(!/animation-name:\s*none/.test(css), 'always utilities must not disable shared animations')
+ assert.ok(css.indexOf('.fade-none') < css.indexOf('.fade-always'), 'fade-always should be the emitted source-order winner')
+})
+
test('the framework-free build is real CSS, self-contained, with no Tailwind noise', () => {
- // Source-only constructs must be fully compiled away.
for (const token of ['@utility', '@theme', '@apply', '--value(']) {
assert.ok(!css.includes(token), `compiled output must not contain ${token}`)
}
- // No Preflight / theme-dump leakage from the utilities-only, isolated build.
- // Our own internal namespace is --tw-fade-*; any OTHER --tw-* would be Tailwind
- // core noise, so exclude our prefix from the leak check.
assert.ok(!/--tw-(?!fade-)/.test(css), 'no Tailwind core --tw-* variables should leak in')
assert.ok(!/\.flex\s*\{|\.grid\s*\{|\.border\s*\{/.test(css), 'no built-in utilities should leak in')
- assert.equal(block('.tw-fade-mask'), null, 'private tw-fade-mask utility should not be emitted as a public class')
})