/* * Custom Tailwind v4 utilities migrated from packages/config/ui.config.js * (addUtilities + matchUtilities) and packages/config/tailwind.config.js * (the .bg legacy shim). */ /* * The `bg` class worked in Tailwind v3 but stopped working in v4. Restored as * an alias for `bg-default` to avoid a wide rename across the codebase. * Should be deprecated in favor of `bg-default`. */ @utility bg { background-color: var(--background); } /* * Soft shimmer gradient used by LoadingLine. */ @utility line-loading-bg { background: rgb(0, 0, 0); background: linear-gradient( 90deg, rgba(0, 0, 0, 0) 0%, rgba(255, 255, 255, 0.65) 50%, rgba(0, 0, 0, 0) 100% ); } @utility line-loading-bg-light { background: rgb(0, 0, 0); background: linear-gradient( 90deg, rgba(0, 0, 0, 0) 0%, rgba(33, 33, 33, 0.65) 50%, rgba(0, 0, 0, 0) 100% ); } /* may be unused — verify before pruning */ @utility mask-fadeout-right { -webkit-mask-image: linear-gradient(to right, white 98%, transparent 100%); mask-image: linear-gradient(to right, white 98%, transparent 100%); } /* may be unused — verify before pruning */ @utility mask-fadeout-left { -webkit-mask-image: linear-gradient(to left, white 98%, transparent 100%); mask-image: linear-gradient(to left, white 98%, transparent 100%); } /* * Functional color utilities. The `--value(--color-*)` token accepts any * registered --color-* design token (e.g. highlight-foreground-light). */ /* may be unused — verify before pruning */ @utility highlight-* { box-shadow: inset 0 1px 0 0 --value(--color-*); } /* may be unused — verify before pruning */ @utility subhighlight-* { box-shadow: inset 0 -1px 0 0 --value(--color-*); } /* * Inline-SVG grid background. Used by ProjectLinker as bg-grid-black/5 and * bg-grid-white/5 for the integrations onboarding visuals. */ @utility bg-grid-* { background-image: url("data:image/svg+xml;utf8,"); } @utility no-scrollbar { -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ &::-webkit-scrollbar { display: none; /* Chrome, Safari, Opera */ } } /* * Text shimmer (shadcn shimmer utility, inlined so we don't pull in the full * shadcn CSS package). Apply `shimmer` to text to draw attention. */ @property --shimmer-angle { syntax: ''; inherits: true; initial-value: 20deg; } @property --shimmer-image { syntax: '*'; inherits: false; } @property --shimmer-text-fill { syntax: '*'; inherits: false; } @utility shimmer { --_spread: var(--shimmer-spread, calc(3ch + 40px)); --_base: currentColor; --_highlight: var(--shimmer-color, oklch(from currentColor l c h / calc(alpha* 0.2))); background-image: var( --shimmer-image, linear-gradient( calc(90deg + var(--shimmer-angle)), var(--_base) calc(50% - var(--_spread)), color-mix(in oklch, var(--_highlight), var(--_base) 50%) calc(50% - var(--_spread) * 0.5), var(--_highlight) 50%, color-mix(in oklch, var(--_highlight), var(--_base) 50%) calc(50% + var(--_spread) * 0.5), var(--_base) calc(50% + var(--_spread)) ) ); background-repeat: no-repeat; background-size: calc(200% + var(--_spread) * 2) 100%; background-position: 0 0; background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: var(--shimmer-text-fill, transparent); animation: tw-shimmer var(--shimmer-duration, 2s) linear infinite; transition: -webkit-text-fill-color 0.5s ease; /* Fade to solid text on dismiss — keep the gradient until fill is opaque */ &[data-shimmer-fading] { -webkit-text-fill-color: currentColor; animation-play-state: paused; } @variant dark { --_highlight: var( --shimmer-color, oklch(from currentColor max(0.8, calc(l + 0.4)) c h / calc(alpha + 0.4)) ); } &:where([dir='rtl'], [dir='rtl'] *) { animation-direction: reverse; } } @utility shimmer-once { animation-iteration-count: 1; } @utility shimmer-reverse { animation-direction: reverse; } @utility shimmer-none { --shimmer-image: none; --shimmer-text-fill: currentColor; background-image: none; -webkit-text-fill-color: currentColor; } @utility shimmer-color-* { --shimmer-color: --value(--color-*, [color]); --shimmer-color: color-mix( in oklch, --value(--color-*, [color]) calc(--modifier(integer) * 1%), transparent ); } @utility shimmer-duration-* { --shimmer-duration: calc(--value(integer) * 1ms); } @utility shimmer-spread-* { --shimmer-spread: calc(var(--spacing) * --value(integer)); --shimmer-spread: --value([length], [percentage]); } @utility shimmer-angle-* { --shimmer-angle: calc(--value(integer) * 1deg); } @media (prefers-reduced-motion: reduce) { .shimmer { animation: none; background-image: none; -webkit-text-fill-color: currentColor; } } /* * Canonical keyboard focus rings. Prefer these over inventing local ring/outline * stacks. * * - focus-ring: default offset ring (buttons, inputs, most controls). * `outline-hidden` stays always-on so mouse click does not show the browser * default; the ring is `:focus-visible` only. * - focus-inset: dense/flush surfaces such as interactive s. Must use * outline (not ring/box-shadow) — box-shadow on table-row is unreliable, * especially in Safari. Do NOT pair with outline-hidden: that sets * outline-style: none and suppresses the focus outline. */ @utility focus-ring { @apply outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background; } @utility focus-inset { &:focus-visible { outline-style: solid; outline-width: 2px; outline-offset: -2px; outline-color: var(--ring); border-radius: var(--radius-md, 0.375rem); } }