* feat(web): fade in newly streamed response words Animate only new word-level deltas while markdown is still streaming, and cache markdown-it instances per parser id so concurrent Response trees do not rebuild or reparse on every render. * fix(web): keep CodeMirror editor alive across keystroke re-renders Deliver onKeyDown through a ref instead of the extensions memo so a new handler identity no longer tears down the EditorView, which reset the cursor to the document start and made typing appear right-to-left. * feat(web): add unsaved changes confirmation dialog in PlaygroundMessageEditor Implement a confirmation dialog to warn users about unsaved changes when attempting to leave the editor. This includes handling the beforeunload event to prevent accidental navigation away from the editor. Additionally, add tests to verify the dialog's behavior under various scenarios. * test(web): cover beforeunload guard and fade hydration suppression Address review feedback: add regression tests for the unsaved-changes beforeunload guard and the first-render fade suppression of hydrated content, and annotate getCachedMarkdown's return type.
721 lines
17 KiB
CSS
721 lines
17 KiB
CSS
/*
|
|
Copyright (C) 2023-2026 QuantumNous
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
For commercial licensing, please contact support@quantumnous.com
|
|
*/
|
|
@import 'tailwindcss';
|
|
@import 'tw-animate-css';
|
|
@import 'shadcn/tailwind.css';
|
|
@import '@fontsource-variable/public-sans';
|
|
/* Editorial serif (Lora) backing the `serif` font axis and the Anthropic
|
|
* preset's default typography. See `--font-serif` in theme.css for the
|
|
* full Latin + CJK fallback stack and `theme-presets.css` for the cascade
|
|
* that activates it. Loaded globally so font-switching is instantaneous
|
|
* with no FOUT once the variable is fetched. */
|
|
@import '@fontsource-variable/lora';
|
|
|
|
@import './theme.css';
|
|
@import './theme-presets.css';
|
|
|
|
/* Shiki dual themes: token colors follow dark theme (pre background stays `bg-background` on the block) */
|
|
@layer components {
|
|
.shiki span {
|
|
color: var(--shiki-light) !important;
|
|
font-style: var(--shiki-light-font-style) !important;
|
|
font-weight: var(--shiki-light-font-weight) !important;
|
|
text-decoration: var(--shiki-light-text-decoration) !important;
|
|
}
|
|
|
|
.dark .shiki span {
|
|
color: var(--shiki-dark) !important;
|
|
font-style: var(--shiki-dark-font-style) !important;
|
|
font-weight: var(--shiki-dark-font-weight) !important;
|
|
text-decoration: var(--shiki-dark-text-decoration) !important;
|
|
}
|
|
|
|
.json-code-editor-textarea {
|
|
overflow: auto !important;
|
|
scrollbar-gutter: stable;
|
|
}
|
|
|
|
.json-code-editor-textarea::placeholder {
|
|
color: var(--muted-foreground);
|
|
opacity: 1;
|
|
-webkit-text-fill-color: var(--muted-foreground);
|
|
}
|
|
|
|
.json-code-editor-textarea,
|
|
.json-code-editor-highlight,
|
|
.json-code-editor-lines {
|
|
overflow-wrap: normal !important;
|
|
white-space: pre !important;
|
|
}
|
|
|
|
.json-code-editor-highlight .yace-tok--str {
|
|
color: var(--chart-5);
|
|
}
|
|
|
|
.json-code-editor-highlight .yace-tok--num {
|
|
color: var(--chart-4);
|
|
}
|
|
|
|
.json-code-editor-highlight .yace-tok--kw {
|
|
color: var(--chart-1);
|
|
}
|
|
|
|
.json-code-editor-highlight .yace-tok--punc {
|
|
color: var(--muted-foreground);
|
|
}
|
|
|
|
.json-code-editor-highlight .yace-tok--com {
|
|
color: var(--muted-foreground);
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border outline-ring/50;
|
|
scrollbar-width: thin;
|
|
scrollbar-color: var(--border) transparent;
|
|
}
|
|
html {
|
|
@apply overflow-x-hidden font-sans;
|
|
}
|
|
body {
|
|
@apply bg-background text-foreground has-[div[data-variant='inset']]:bg-sidebar min-h-svh w-full;
|
|
/* Font is driven by the theme's font axis via `--font-body`
|
|
* (defined in theme.css, swapped by `[data-theme-font='...']` blocks
|
|
* in theme-presets.css). Defaults to the project's humanist sans. */
|
|
font-family: var(--font-body);
|
|
}
|
|
|
|
/* Keep sticky headers stable while primitives lock body scrolling. */
|
|
body[data-scroll-locked] {
|
|
overflow: unset !important;
|
|
}
|
|
|
|
/* Cursor pointer for buttons */
|
|
button:not(:disabled),
|
|
[role='button']:not(:disabled) {
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Prevent focus zoom on mobile devices */
|
|
@media screen and (max-width: 767px) {
|
|
input,
|
|
select,
|
|
textarea {
|
|
font-size: 16px !important;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Vercel Geist-style skeleton shimmer */
|
|
.skeleton-shimmer {
|
|
background: linear-gradient(
|
|
90deg,
|
|
var(--skeleton-base) 0%,
|
|
var(--skeleton-base) 33%,
|
|
var(--skeleton-highlight) 50%,
|
|
var(--skeleton-base) 67%,
|
|
var(--skeleton-base) 100%
|
|
);
|
|
background-size: 300% 100%;
|
|
animation: skeleton-shimmer 1.8s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes skeleton-shimmer {
|
|
0% {
|
|
background-position: 100% 50%;
|
|
}
|
|
100% {
|
|
background-position: -100% 50%;
|
|
}
|
|
}
|
|
|
|
/* Override auto-skeleton-react inline styles with Vercel shimmer */
|
|
.auto-skeleton-fade [class^='skeleton-'] {
|
|
background: linear-gradient(
|
|
90deg,
|
|
var(--skeleton-base) 0%,
|
|
var(--skeleton-base) 33%,
|
|
var(--skeleton-highlight) 50%,
|
|
var(--skeleton-base) 67%,
|
|
var(--skeleton-base) 100%
|
|
) !important;
|
|
background-size: 300% 100% !important;
|
|
animation: skeleton-shimmer 1.8s ease-in-out infinite !important;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.skeleton-shimmer,
|
|
.auto-skeleton-fade [class^='skeleton-'] {
|
|
animation: none !important;
|
|
background: var(--skeleton-base) !important;
|
|
}
|
|
}
|
|
|
|
@utility container {
|
|
margin-inline: auto;
|
|
padding-inline: 2rem;
|
|
}
|
|
|
|
@utility max-w-container {
|
|
max-width: 1280px;
|
|
}
|
|
|
|
@utility max-w-container-lg {
|
|
max-width: 1536px;
|
|
}
|
|
|
|
@utility no-scrollbar {
|
|
/* Hide scrollbar for Chrome, Safari and Opera */
|
|
&::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
/* Hide scrollbar for IE, Edge and Firefox */
|
|
-ms-overflow-style: none; /* IE and Edge */
|
|
scrollbar-width: none; /* Firefox */
|
|
}
|
|
|
|
/* Tooltip content can still scroll, but should not show a distracting axis. */
|
|
[data-slot='tooltip-content'],
|
|
[data-slot='tooltip-content'] * {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
[data-slot='tooltip-content']::-webkit-scrollbar,
|
|
[data-slot='tooltip-content'] *::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
@utility hover-scrollbar {
|
|
/* Hide scrollbar by default */
|
|
scrollbar-width: thin;
|
|
scrollbar-color: transparent transparent;
|
|
|
|
/* Show scrollbar on hover */
|
|
&:hover {
|
|
scrollbar-color: var(--border) transparent;
|
|
}
|
|
|
|
/* Webkit browsers (Chrome, Safari, Edge) */
|
|
&::-webkit-scrollbar {
|
|
width: 8px;
|
|
}
|
|
|
|
&::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
&::-webkit-scrollbar-thumb {
|
|
background-color: transparent;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
&:hover::-webkit-scrollbar-thumb {
|
|
background-color: var(--border);
|
|
}
|
|
|
|
&:hover::-webkit-scrollbar-thumb:hover {
|
|
background-color: color-mix(in oklch, var(--border) 60%, transparent);
|
|
}
|
|
}
|
|
|
|
@utility faded-bottom {
|
|
@apply after:pointer-events-none after:absolute after:start-0 after:bottom-0 after:hidden after:h-32 after:w-full after:rounded-b-2xl after:bg-[linear-gradient(180deg,_transparent_10%,_var(--background)_70%)] md:after:block;
|
|
}
|
|
|
|
.CollapsibleContent {
|
|
overflow: hidden;
|
|
}
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
.CollapsibleContent[data-open] {
|
|
animation: slideDown 300ms ease-out;
|
|
}
|
|
.CollapsibleContent:not([data-open]) {
|
|
animation: slideUp 300ms ease-out;
|
|
}
|
|
}
|
|
|
|
@keyframes slideDown {
|
|
from {
|
|
height: 0;
|
|
}
|
|
to {
|
|
height: var(--collapsible-panel-height);
|
|
}
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from {
|
|
height: var(--collapsible-panel-height);
|
|
}
|
|
to {
|
|
height: 0;
|
|
}
|
|
}
|
|
|
|
/* Launch UI Animations and Effects - Matching Template Exactly */
|
|
@layer utilities {
|
|
/* Gradient utilities */
|
|
.bg-radial {
|
|
background-image: radial-gradient(var(--tw-gradient-stops));
|
|
}
|
|
|
|
/* Glass morphism effects - matching Launch UI template */
|
|
.glass-1 {
|
|
@apply border-border from-card/80 to-card/40 dark:border-border/10 dark:border-b-border/5 dark:border-t-border/20 dark:from-card/5 dark:to-card/0 border bg-linear-to-b;
|
|
}
|
|
|
|
.glass-2 {
|
|
@apply border-border from-card/100 to-card/80 dark:border-border/10 dark:border-b-border/5 dark:border-t-border/20 dark:from-card/10 dark:to-card/5 border bg-linear-to-b;
|
|
}
|
|
|
|
.glass-3 {
|
|
@apply border-border from-card/30 to-card/20 dark:border-border/10 dark:border-t-border/20 dark:border-b-border/5 dark:from-primary/5 dark:to-primary/2 border bg-linear-to-b;
|
|
}
|
|
|
|
.glass-4 {
|
|
@apply border-border border-b-input/90 from-card/60 to-card/20 dark:border-border/10 dark:border-t-border/30 dark:from-primary/10 dark:to-primary/5 border bg-linear-to-b dark:border-b-0;
|
|
}
|
|
|
|
.glass-5 {
|
|
@apply border-border border-b-input from-card/100 to-card/20 dark:border-border/10 dark:border-t-border/30 dark:from-primary/15 dark:to-primary/5 border bg-linear-to-b dark:border-b-0;
|
|
}
|
|
|
|
/* Fade effects - matching Launch UI template */
|
|
.fade-x {
|
|
mask-image: linear-gradient(
|
|
to right,
|
|
transparent 0%,
|
|
black 25%,
|
|
black 75%,
|
|
transparent 100%
|
|
);
|
|
}
|
|
|
|
.fade-y {
|
|
mask-image: linear-gradient(
|
|
to top,
|
|
transparent 0%,
|
|
black 25%,
|
|
black 75%,
|
|
transparent 100%
|
|
);
|
|
}
|
|
|
|
.fade-top {
|
|
mask-image: linear-gradient(to bottom, transparent 0%, black 35%);
|
|
}
|
|
|
|
.fade-bottom {
|
|
mask-image: linear-gradient(to top, transparent 0%, black 35%);
|
|
}
|
|
|
|
.fade-top-lg {
|
|
mask-image: linear-gradient(to bottom, transparent 15%, black 100%);
|
|
}
|
|
|
|
.fade-bottom-lg {
|
|
mask-image: linear-gradient(to top, transparent 15%, black 100%);
|
|
}
|
|
|
|
.fade-left {
|
|
mask-image: linear-gradient(to right, transparent 0%, black 35%);
|
|
}
|
|
|
|
.fade-right {
|
|
mask-image: linear-gradient(to left, transparent 0%, black 35%);
|
|
}
|
|
|
|
.fade-left-lg {
|
|
mask-image: linear-gradient(to right, transparent 15%, black 100%);
|
|
}
|
|
|
|
.fade-right-lg {
|
|
mask-image: linear-gradient(to left, transparent 15%, black 100%);
|
|
}
|
|
|
|
/* Animations */
|
|
.animate-appear {
|
|
animation: appear 0.6s forwards ease-out;
|
|
}
|
|
|
|
.animate-appear-zoom {
|
|
animation: appear-zoom 0.6s forwards ease-out;
|
|
}
|
|
|
|
.animation-delay-100 {
|
|
animation-delay: 100ms;
|
|
}
|
|
|
|
.animation-delay-300 {
|
|
animation-delay: 300ms;
|
|
}
|
|
|
|
.animation-delay-700 {
|
|
animation-delay: 700ms;
|
|
}
|
|
|
|
.animation-delay-1000 {
|
|
animation-delay: 1000ms;
|
|
}
|
|
|
|
@keyframes appear {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(1rem);
|
|
filter: blur(0.5rem);
|
|
}
|
|
50% {
|
|
filter: blur(0);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
filter: blur(0);
|
|
}
|
|
}
|
|
|
|
@keyframes appear-zoom {
|
|
0% {
|
|
opacity: 0;
|
|
transform: scale(0.5);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
|
|
/* Vertical scroll animation for icon lists */
|
|
@keyframes scroll-up {
|
|
0% {
|
|
transform: translateY(0);
|
|
}
|
|
100% {
|
|
transform: translateY(-50%);
|
|
}
|
|
}
|
|
|
|
.animate-scroll-up {
|
|
animation: scroll-up 20s linear infinite;
|
|
will-change: transform;
|
|
}
|
|
|
|
.animate-scroll-down {
|
|
animation: scroll-up 20s linear infinite reverse;
|
|
will-change: transform;
|
|
}
|
|
|
|
/* Pause animation on hover */
|
|
.scroll-container:hover .animate-scroll-up,
|
|
.scroll-container:hover .animate-scroll-down {
|
|
animation-play-state: paused;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.animate-appear,
|
|
.animate-appear-zoom,
|
|
.animate-scroll-up,
|
|
.animate-scroll-down,
|
|
[data-slot='table'] tbody tr {
|
|
animation: none !important;
|
|
opacity: 1;
|
|
transform: none;
|
|
}
|
|
}
|
|
|
|
/* Smooth streaming: one-shot fade-in on newly streamed words.
|
|
* Duration must match FADE_DURATION_MS in response-fade.ts */
|
|
@keyframes stream-fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
[data-stream-fade] {
|
|
animation: stream-fade-in 250ms ease-out both;
|
|
animation-delay: var(--stream-fade-delay, 0ms);
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
[data-stream-fade] {
|
|
animation: none;
|
|
}
|
|
}
|
|
|
|
/* ── Landing page scroll-triggered animations ── */
|
|
@keyframes landing-fade-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(24px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
@keyframes landing-fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
@keyframes landing-scale-in {
|
|
from {
|
|
opacity: 0;
|
|
transform: scale(0.95);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
@keyframes landing-fade-left {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(24px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
@keyframes landing-fade-right {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(-24px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.landing-animate-fade-up {
|
|
animation: landing-fade-up 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
}
|
|
.landing-animate-fade-in {
|
|
animation: landing-fade-in 0.6s ease-out both;
|
|
}
|
|
.landing-animate-scale-in {
|
|
animation: landing-scale-in 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
}
|
|
.landing-animate-fade-left {
|
|
animation: landing-fade-left 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
}
|
|
.landing-animate-fade-right {
|
|
animation: landing-fade-right 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.landing-animate-fade-up,
|
|
.landing-animate-fade-in,
|
|
.landing-animate-scale-in,
|
|
.landing-animate-fade-left,
|
|
.landing-animate-fade-right {
|
|
animation: none !important;
|
|
opacity: 1 !important;
|
|
transform: none !important;
|
|
}
|
|
}
|
|
|
|
/* Micro-interactions — Vercel-style subtle hover/active feedback */
|
|
@media (prefers-reduced-motion: no-preference) {
|
|
[data-slot='card']:not([data-card-hover='false']) {
|
|
transition:
|
|
transform 150ms ease,
|
|
box-shadow 150ms ease;
|
|
}
|
|
|
|
@media (min-width: 641px) {
|
|
[data-slot='card']:not([data-card-hover='false']):hover {
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 12px rgb(0 0 0 / 0.06);
|
|
}
|
|
|
|
.dark [data-slot='card']:not([data-card-hover='false']):hover {
|
|
box-shadow: 0 4px 12px rgb(0 0 0 / 0.3);
|
|
}
|
|
}
|
|
|
|
button:not(:disabled):active,
|
|
[role='button']:not(:disabled):active {
|
|
transform: scale(0.98);
|
|
}
|
|
|
|
[data-slot='table'] tr {
|
|
transition: background-color 120ms ease;
|
|
}
|
|
|
|
/* Table row stagger-in animation */
|
|
[data-slot='table'] tbody tr {
|
|
animation: tableRowEnter 0.2s cubic-bezier(0.33, 1, 0.68, 1) both;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(2) {
|
|
animation-delay: 25ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(3) {
|
|
animation-delay: 50ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(4) {
|
|
animation-delay: 75ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(5) {
|
|
animation-delay: 100ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(6) {
|
|
animation-delay: 125ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(7) {
|
|
animation-delay: 150ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(8) {
|
|
animation-delay: 175ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(9) {
|
|
animation-delay: 200ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(10) {
|
|
animation-delay: 225ms;
|
|
}
|
|
[data-slot='table'] tbody tr:nth-child(n + 11) {
|
|
animation-delay: 250ms;
|
|
}
|
|
}
|
|
|
|
@keyframes tableRowEnter {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(4px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Tabular numbers for data-heavy contexts */
|
|
[data-slot='table'] td,
|
|
.tabular-nums {
|
|
font-variant-numeric: tabular-nums;
|
|
}
|
|
|
|
/* Long list rendering optimization */
|
|
.content-auto {
|
|
content-visibility: auto;
|
|
contain-intrinsic-size: 0 80px;
|
|
}
|
|
|
|
/* ── Hero terminal demo animations ── */
|
|
@keyframes terminal-demo-blink {
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
.terminal-demo-blink {
|
|
animation: terminal-demo-blink 1s step-end infinite;
|
|
}
|
|
|
|
@keyframes terminal-demo-spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
.terminal-demo-spin {
|
|
animation: terminal-demo-spin 0.8s linear infinite;
|
|
}
|
|
|
|
@keyframes terminal-demo-pulse {
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0.3;
|
|
}
|
|
}
|
|
.terminal-demo-pulse {
|
|
animation: terminal-demo-pulse 1.5s ease-in-out infinite;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.terminal-demo-blink,
|
|
.terminal-demo-spin,
|
|
.terminal-demo-pulse {
|
|
animation: none !important;
|
|
}
|
|
}
|
|
|
|
/* ── Auto group flowing border ── */
|
|
@property --auto-group-flow-angle {
|
|
syntax: '<angle>';
|
|
inherits: false;
|
|
initial-value: 0deg;
|
|
}
|
|
|
|
@keyframes auto-group-flow-border-travel {
|
|
to {
|
|
--auto-group-flow-angle: 360deg;
|
|
}
|
|
}
|
|
|
|
/* Border-only effect: the conic gradient covers the whole layer, but the
|
|
* two-layer mask (content-box XOR full box) keeps only a `padding`-wide
|
|
* ring visible, so the highlight hugs the rounded perimeter. Animating
|
|
* the gradient's start angle makes the bright segment travel around all
|
|
* four edges and corners without touching the interior. */
|
|
.auto-group-flow-border {
|
|
padding: 1.5px;
|
|
border-radius: inherit;
|
|
background: conic-gradient(
|
|
from var(--auto-group-flow-angle),
|
|
transparent 0deg,
|
|
transparent 240deg,
|
|
color-mix(in oklch, var(--primary) 45%, transparent) 300deg,
|
|
var(--primary) 342deg,
|
|
transparent 360deg
|
|
);
|
|
mask:
|
|
linear-gradient(#000 0 0) content-box,
|
|
linear-gradient(#000 0 0);
|
|
-webkit-mask:
|
|
linear-gradient(#000 0 0) content-box,
|
|
linear-gradient(#000 0 0);
|
|
-webkit-mask-composite: xor;
|
|
mask-composite: exclude;
|
|
animation: auto-group-flow-border-travel 3.2s linear infinite;
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.auto-group-flow-border {
|
|
display: none;
|
|
}
|
|
}
|