2026-06-04 09:42:26 -04:00
|
|
|
|
import { keyframes, style } from '@vanilla-extract/css';
|
2023-10-30 07:14:58 +11:00
|
|
|
|
import { DefaultReset, color, config, toRem } from 'folds';
|
|
|
|
|
|
|
|
|
|
|
|
export const UrlPreview = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(400),
|
|
|
|
|
|
minHeight: toRem(102),
|
|
|
|
|
|
backgroundColor: color.SurfaceVariant.Container,
|
|
|
|
|
|
color: color.SurfaceVariant.OnContainer,
|
|
|
|
|
|
border: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-06 20:55:47 -04:00
|
|
|
|
// Wider, responsive card for interactive embeds (video players, tweets, posts)
|
|
|
|
|
|
// so the player chrome / tweet content isn't cramped or clipped. Defined after
|
|
|
|
|
|
// UrlPreview so its width wins the cascade.
|
|
|
|
|
|
export const UrlPreviewWide = style({
|
2026-07-06 22:23:32 -04:00
|
|
|
|
width: 'min(38rem, 94vw)',
|
2026-07-06 20:55:47 -04:00
|
|
|
|
});
|
|
|
|
|
|
|
2023-10-30 07:14:58 +11:00
|
|
|
|
export const UrlPreviewImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(100),
|
|
|
|
|
|
height: toRem(100),
|
|
|
|
|
|
objectFit: 'cover',
|
2025-01-10 10:42:05 +01:00
|
|
|
|
objectPosition: 'center',
|
2023-10-30 07:14:58 +11:00
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
overflow: 'hidden',
|
2026-03-14 17:22:18 +11:00
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.8)',
|
|
|
|
|
|
},
|
2023-10-30 07:14:58 +11:00
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const UrlPreviewContent = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
padding: config.space.S200,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const UrlPreviewDescription = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: '-webkit-box',
|
|
|
|
|
|
WebkitLineClamp: 2,
|
|
|
|
|
|
WebkitBoxOrient: 'vertical',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
2026-06-03 23:15:29 -04:00
|
|
|
|
|
|
|
|
|
|
// YouTube card styles
|
|
|
|
|
|
export const YouTubeThumbnailWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(160),
|
|
|
|
|
|
height: toRem(90),
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.85)',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const YouTubeThumbnailImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const YouTubePlayOverlay = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const YouTubePlayButton = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(44),
|
|
|
|
|
|
height: toRem(44),
|
|
|
|
|
|
borderRadius: '50%',
|
|
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// GitHub card styles
|
|
|
|
|
|
export const GitHubIconWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(72),
|
|
|
|
|
|
minHeight: toRem(72),
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
color: color.SurfaceVariant.OnContainer,
|
|
|
|
|
|
opacity: 0.8,
|
|
|
|
|
|
backgroundColor: color.Surface.ContainerHover,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// Generic card favicon styles
|
|
|
|
|
|
export const GenericFaviconWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: config.space.S100,
|
|
|
|
|
|
verticalAlign: 'middle',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const GenericFaviconImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(16),
|
|
|
|
|
|
height: toRem(16),
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
2026-06-03 23:34:23 -04:00
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Shared media-card thumbnail (VideoCard, Steam, etc.)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const MediaThumbnailWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(160),
|
|
|
|
|
|
height: toRem(90),
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.85)',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const MediaThumbnailImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const MediaPlayOverlay = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const MediaPlayButton = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(44),
|
|
|
|
|
|
height: toRem(44),
|
|
|
|
|
|
borderRadius: '50%',
|
|
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, 0.75)',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-06 19:48:12 -04:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Inline video embed (YouTube / Vimeo) — media-forward click-to-play facade
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const EmbedMediaLandscape = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
aspectRatio: '16 / 9',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
2026-07-06 20:55:47 -04:00
|
|
|
|
selectors: {
|
|
|
|
|
|
'&:fullscreen': { width: '100vw', height: '100vh', aspectRatio: 'auto' },
|
|
|
|
|
|
},
|
2026-07-06 19:48:12 -04:00
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const EmbedMediaPortrait = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
2026-07-06 20:55:47 -04:00
|
|
|
|
width: toRem(300),
|
2026-07-06 19:48:12 -04:00
|
|
|
|
maxWidth: '100%',
|
|
|
|
|
|
aspectRatio: '9 / 16',
|
|
|
|
|
|
margin: '0 auto',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
2026-07-06 20:55:47 -04:00
|
|
|
|
selectors: {
|
|
|
|
|
|
'&:fullscreen': { width: '100vw', height: '100vh', aspectRatio: 'auto', margin: 0 },
|
|
|
|
|
|
},
|
2026-07-06 19:48:12 -04:00
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// Fills the aspect box; used for both the <button> facade and the <a> fallback.
|
|
|
|
|
|
export const EmbedFacade = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
padding: 0,
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
background: 'none',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.85)',
|
|
|
|
|
|
},
|
2026-07-07 00:45:51 -04:00
|
|
|
|
selectors: {
|
|
|
|
|
|
'&:focus-visible': {
|
|
|
|
|
|
outline: `2px solid ${color.Primary.Main}`,
|
|
|
|
|
|
outlineOffset: '-2px',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
2026-07-06 19:48:12 -04:00
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const EmbedIframe = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
border: 0,
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-06 23:56:47 -04:00
|
|
|
|
// Variable-height iframe that sizes itself (X/Twitter, Instagram, Reddit posts —
|
|
|
|
|
|
// height set inline). Capped ~550px (X/IG native max) + centered in the wide card.
|
2026-07-06 20:14:53 -04:00
|
|
|
|
export const EmbedIframeStatic = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
2026-07-06 23:56:47 -04:00
|
|
|
|
maxWidth: toRem(550),
|
|
|
|
|
|
margin: '0 auto',
|
2026-07-06 20:14:53 -04:00
|
|
|
|
border: 0,
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-06 19:48:12 -04:00
|
|
|
|
export const EmbedPlaceholder = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
backgroundColor: '#111111',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
fontSize: toRem(28),
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-06 20:01:05 -04:00
|
|
|
|
// Audio embeds (Spotify / SoundCloud) — full-width, short fixed height (set inline).
|
|
|
|
|
|
export const EmbedMediaAudio = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-06-03 23:34:23 -04:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Shared square artwork thumbnail (Spotify, IMDb poster, Discord icon)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const ArtworkThumbnail = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(72),
|
|
|
|
|
|
height: toRem(72),
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// IMDb portrait poster (60 × 90)
|
|
|
|
|
|
export const PosterThumbnail = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(60),
|
|
|
|
|
|
height: toRem(90),
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Site-badge shared base
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const SiteBadge = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: config.space.S100,
|
|
|
|
|
|
paddingLeft: config.space.S100,
|
|
|
|
|
|
paddingRight: config.space.S100,
|
|
|
|
|
|
paddingTop: '2px',
|
|
|
|
|
|
paddingBottom: '2px',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
lineHeight: '1.4',
|
|
|
|
|
|
letterSpacing: '0.03em',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// Individual badge colour overrides (background / foreground)
|
|
|
|
|
|
export const BadgeVimeo = style({
|
|
|
|
|
|
backgroundColor: '#1ab7ea',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTwitter = style({
|
|
|
|
|
|
backgroundColor: '#000000',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeReddit = style({
|
|
|
|
|
|
backgroundColor: '#ff4500',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeSpotify = style({
|
|
|
|
|
|
backgroundColor: '#1db954',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTwitch = style({
|
|
|
|
|
|
backgroundColor: '#9146ff',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeSteam = style({
|
|
|
|
|
|
backgroundColor: '#1b2838',
|
|
|
|
|
|
color: '#c7d5e0',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeWikipedia = style({
|
|
|
|
|
|
backgroundColor: color.SurfaceVariant.ContainerLine,
|
|
|
|
|
|
color: color.SurfaceVariant.OnContainer,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeDiscord = style({
|
|
|
|
|
|
backgroundColor: '#5865f2',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeNpm = style({
|
|
|
|
|
|
backgroundColor: '#cb3837',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeStackOverflow = style({
|
|
|
|
|
|
backgroundColor: '#f48024',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeImdb = style({
|
|
|
|
|
|
backgroundColor: '#f5c518',
|
|
|
|
|
|
color: '#000000',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-06-04 09:42:26 -04:00
|
|
|
|
export const BadgeYouTubeShorts = style({
|
|
|
|
|
|
backgroundColor: '#FF0000',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTikTok = style({
|
|
|
|
|
|
backgroundColor: '#000000',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-06 20:01:05 -04:00
|
|
|
|
export const BadgeSoundCloud = style({
|
|
|
|
|
|
backgroundColor: '#ff5500',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeDailymotion = style({
|
|
|
|
|
|
backgroundColor: '#0066dc',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeStreamable = style({
|
|
|
|
|
|
backgroundColor: '#0f90fa',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-06 20:14:53 -04:00
|
|
|
|
export const BadgeAppleMusic = style({
|
|
|
|
|
|
backgroundColor: '#fa243c',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-06 20:55:47 -04:00
|
|
|
|
export const BadgeInstagram = style({
|
|
|
|
|
|
backgroundColor: '#e1306c',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTidal = style({
|
|
|
|
|
|
backgroundColor: '#000000',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-06-03 23:34:23 -04:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Twitch LIVE badge
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const TwitchLiveBadge = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
paddingLeft: config.space.S100,
|
|
|
|
|
|
paddingRight: config.space.S100,
|
|
|
|
|
|
paddingTop: '2px',
|
|
|
|
|
|
paddingBottom: '2px',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
lineHeight: '1.4',
|
|
|
|
|
|
backgroundColor: '#e91916',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
letterSpacing: '0.04em',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Icon-wrapper (generic left-side icon block — Twitter, Reddit, Wikipedia…)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const IconWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(72),
|
|
|
|
|
|
minHeight: toRem(72),
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
backgroundColor: color.Surface.ContainerHover,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
2026-06-04 09:42:26 -04:00
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Portrait thumbnail — 9:16 for Shorts & TikTok
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitThumbnail = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(80),
|
|
|
|
|
|
height: toRem(142),
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.85)',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitThumbnailImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitPlayOverlay = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
inset: 0,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitPlayButton = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(36),
|
|
|
|
|
|
height: toRem(36),
|
|
|
|
|
|
borderRadius: '50%',
|
|
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, 0.72)',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
fontSize: toRem(16),
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitPlaceholder = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(80),
|
|
|
|
|
|
height: toRem(142),
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
backgroundColor: '#111111',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
|
fontSize: toRem(32),
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Twitter / X card
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const TweetBlock = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
backgroundColor: 'rgba(0,0,0,0.15)',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
padding: config.space.S200,
|
|
|
|
|
|
display: '-webkit-box',
|
|
|
|
|
|
WebkitLineClamp: 4,
|
|
|
|
|
|
WebkitBoxOrient: 'vertical',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
fontSize: toRem(13),
|
|
|
|
|
|
lineHeight: '1.5',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const TweetMediaImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
maxHeight: toRem(200),
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
marginTop: config.space.S100,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const TwitterHeader = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: config.space.S100,
|
|
|
|
|
|
padding: `${config.space.S100} ${config.space.S200}`,
|
|
|
|
|
|
paddingTop: config.space.S200,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const ProfileAvatarImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: toRem(36),
|
|
|
|
|
|
height: toRem(36),
|
|
|
|
|
|
borderRadius: '50%',
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Twitch card
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const TwitchThumbnailWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
maxWidth: toRem(240),
|
|
|
|
|
|
aspectRatio: '16 / 9',
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
backgroundColor: '#0e0e10',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.85)',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const TwitchThumbnailImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
height: '100%',
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const TwitchLiveOverlay = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
top: config.space.S100,
|
|
|
|
|
|
right: config.space.S100,
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: '4px',
|
|
|
|
|
|
backgroundColor: '#e91916',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
paddingLeft: config.space.S100,
|
|
|
|
|
|
paddingRight: config.space.S100,
|
|
|
|
|
|
paddingTop: '2px',
|
|
|
|
|
|
paddingBottom: '2px',
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
letterSpacing: '0.04em',
|
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
const livePulseKeyframes = keyframes({
|
|
|
|
|
|
'0%': { opacity: 1 },
|
|
|
|
|
|
'100%': { opacity: 0.4 },
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const LiveDot = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '8px',
|
|
|
|
|
|
height: '8px',
|
|
|
|
|
|
borderRadius: '50%',
|
|
|
|
|
|
backgroundColor: '#ffffff',
|
|
|
|
|
|
animation: `${livePulseKeyframes} 1s ease-in-out infinite alternate`,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTwitchPurple = style({
|
|
|
|
|
|
backgroundColor: '#9146FF',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Reddit card
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const RedditPostLayout = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
gap: config.space.S200,
|
|
|
|
|
|
padding: config.space.S200,
|
|
|
|
|
|
alignItems: 'flex-start',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const RedditThumb = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
width: toRem(80),
|
|
|
|
|
|
height: toRem(60),
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const RedditSubBadge = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
paddingLeft: config.space.S100,
|
|
|
|
|
|
paddingRight: config.space.S100,
|
|
|
|
|
|
paddingTop: '2px',
|
|
|
|
|
|
paddingBottom: '2px',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
lineHeight: '1.4',
|
|
|
|
|
|
backgroundColor: '#FF4500',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
letterSpacing: '0.02em',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const RedditUpvote = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
color: '#FF4500',
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
fontSize: toRem(12),
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const RedditMeta = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: config.space.S200,
|
|
|
|
|
|
marginTop: config.space.S100,
|
|
|
|
|
|
fontSize: toRem(12),
|
|
|
|
|
|
opacity: 0.75,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// TikTok hashtag chip
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const HashtagChip = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
opacity: 0.7,
|
|
|
|
|
|
marginRight: '4px',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Shorts card header bar
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const ShortsHeader = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: config.space.S100,
|
|
|
|
|
|
padding: `${config.space.S100} ${config.space.S200}`,
|
|
|
|
|
|
backgroundColor: color.Surface.ContainerHover,
|
|
|
|
|
|
borderBottom: `1px solid ${color.SurfaceVariant.ContainerLine}`,
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Side-by-side portrait layout (Shorts, TikTok)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const PortraitSideLayout = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
gap: config.space.S200,
|
|
|
|
|
|
padding: config.space.S200,
|
|
|
|
|
|
alignItems: 'flex-start',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
2026-06-04 15:51:18 -04:00
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// GIF card (Giphy / Tenor)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
export const GifThumbnailWrapper = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'relative',
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
maxHeight: toRem(200),
|
|
|
|
|
|
overflow: 'hidden',
|
|
|
|
|
|
flexShrink: 0,
|
|
|
|
|
|
backgroundColor: color.Surface.Container,
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
|
|
|
|
|
|
':hover': {
|
|
|
|
|
|
filter: 'brightness(0.9)',
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const GifThumbnailImg = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
maxHeight: toRem(200),
|
|
|
|
|
|
objectFit: 'cover',
|
|
|
|
|
|
objectPosition: 'center',
|
|
|
|
|
|
display: 'block',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const GifBadge = style([
|
|
|
|
|
|
DefaultReset,
|
|
|
|
|
|
{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
top: config.space.S100,
|
|
|
|
|
|
right: config.space.S100,
|
|
|
|
|
|
display: 'inline-flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
paddingLeft: config.space.S100,
|
|
|
|
|
|
paddingRight: config.space.S100,
|
|
|
|
|
|
paddingTop: '2px',
|
|
|
|
|
|
paddingBottom: '2px',
|
|
|
|
|
|
borderRadius: config.radii.R300,
|
|
|
|
|
|
fontSize: toRem(11),
|
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
|
lineHeight: '1.4',
|
|
|
|
|
|
letterSpacing: '0.05em',
|
|
|
|
|
|
backgroundColor: 'rgba(0, 0, 0, 0.65)',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
|
},
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeGiphy = style({
|
|
|
|
|
|
backgroundColor: '#00c0c0',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
export const BadgeTenor = style({
|
|
|
|
|
|
backgroundColor: '#0078d4',
|
|
|
|
|
|
color: '#ffffff',
|
|
|
|
|
|
});
|