import { style } from '@vanilla-extract/css'; import { color, toRem } from 'folds'; /** Discord nameplate static.png assets are 448×84. */ export const NAMEPLATE_ASPECT_RATIO = '448 / 84'; /** * Mini profile hero preview — matches UserRoomProfile menu width (260) and UserHero layout, * with extra vertical space below the name so effects have room to play. */ export const PROFILE_HERO_PREVIEW_WIDTH = 260; export const PROFILE_HERO_CONTENT_HEIGHT = 235; export const PROFILE_HERO_PREVIEW_EXTRA_HEIGHT = Math.round(PROFILE_HERO_CONTENT_HEIGHT * 0.5); export const PROFILE_HERO_PREVIEW_HEIGHT = PROFILE_HERO_CONTENT_HEIGHT + PROFILE_HERO_PREVIEW_EXTRA_HEIGHT; export const PROFILE_HERO_PREVIEW_ASPECT_RATIO = `${PROFILE_HERO_PREVIEW_WIDTH} / ${PROFILE_HERO_PREVIEW_HEIGHT}`; export const CollectibleGroupGrid = style({ display: 'grid', width: '100%', }); export const CollectibleGroupGridNameplate = style({ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: toRem(3), }); export const CollectibleGroupGridEffects = style({ gridTemplateColumns: 'repeat(auto-fill, minmax(130px, 1fr))', gap: toRem(12), }); export const CollectibleGroupGridDecorations = style({ gridTemplateColumns: 'repeat(auto-fill, minmax(120px, 1fr))', gap: toRem(12), }); export const CollectibleGroupCard = style({ position: 'relative', display: 'flex', flexDirection: 'column', gap: toRem(4), width: '100%', }); export const CollectibleGroupPreview = style({ position: 'relative', display: 'block', width: '100%', border: 'none', padding: 0, overflow: 'visible', background: 'transparent', cursor: 'pointer', textAlign: 'left', }); export const CollectibleGroupPreviewDisabled = style({ cursor: 'wait', }); export const CollectibleGroupPreviewDimmed = style({ opacity: 0.5, }); export const CollectiblePreviewFrame = style({ width: '100%', borderRadius: toRem(6), overflow: 'hidden', backgroundColor: color.Surface.ContainerLine, display: 'flex', alignItems: 'center', justifyContent: 'center', }); export const CollectiblePreviewFrameDecoration = style({ overflow: 'visible', backgroundColor: 'transparent', }); export const CollectiblePreviewFrameProfileEffect = style({ backgroundColor: color.Surface.Container, alignItems: 'stretch', justifyContent: 'stretch', }); export const ProfileEffectHeroPreview = style({ position: 'relative', width: '100%', height: '100%', overflow: 'hidden', backgroundColor: color.Surface.Container, }); export const ProfileEffectHeroCover = style({ position: 'absolute', left: 0, right: 0, top: 0, height: `${(140 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, overflow: 'hidden', zIndex: 1, }); export const ProfileEffectHeroBanner = style({ width: '100%', height: '100%', objectFit: 'cover', display: 'block', }); export const ProfileEffectHeroCoverBlur = style({ width: '100%', height: '100%', objectFit: 'cover', filter: 'blur(16px)', transform: 'scale(2)', display: 'block', }); export const ProfileEffectHeroAvatarSlot = style({ position: 'absolute', left: 0, right: 0, top: `${(140 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, height: `${(29 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, zIndex: 4, pointerEvents: 'none', }); export const ProfileEffectHeroAvatar = style({ position: 'absolute', left: '50%', top: 0, transform: 'translate(-50%, -50%)', width: `${(72 / PROFILE_HERO_PREVIEW_WIDTH) * 100}%`, aspectRatio: '1', borderRadius: '50%', overflow: 'hidden', border: `${toRem(1)} solid ${color.Surface.Container}`, backgroundColor: color.Surface.Container, }); export const ProfileEffectHeroAvatarImg = style({ width: '100%', height: '100%', display: 'block', objectFit: 'cover', }); export const ProfileEffectHeroInfo = style({ position: 'absolute', left: 0, right: 0, top: `${((140 + 29) / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, marginTop: `${(-36 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, paddingTop: `${(44 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, paddingLeft: `${(16 / PROFILE_HERO_PREVIEW_WIDTH) * 100}%`, paddingRight: `${(16 / PROFILE_HERO_PREVIEW_WIDTH) * 100}%`, paddingBottom: `${(16 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: `${(8 / PROFILE_HERO_PREVIEW_HEIGHT) * 100}%`, textAlign: 'center', zIndex: 4, pointerEvents: 'none', }); export const ProfileEffectHeroName = style({ width: '100%', fontSize: toRem(11), lineHeight: 1.2, fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', }); export const ProfileEffectHeroEffectLayer = style({ position: 'absolute', inset: 0, zIndex: 10, pointerEvents: 'none', overflow: 'visible', }); export const ProfileEffectHeroEffect = style({ position: 'absolute', left: 0, right: 0, top: 0, width: '100%', aspectRatio: '450 / 880', objectFit: 'contain', objectPosition: 'top center', }); export const NameplatePreview = style({ display: 'block', width: '100%', aspectRatio: NAMEPLATE_ASPECT_RATIO, objectFit: 'cover', objectPosition: 'center', borderRadius: toRem(4), }); export const NameplatePreviewFallback = style({ width: '100%', aspectRatio: NAMEPLATE_ASPECT_RATIO, borderRadius: toRem(4), }); export const CollectibleHoverCaption = style({ position: 'absolute', top: `calc(100% + ${toRem(2)})`, left: 0, right: 0, display: 'flex', flexDirection: 'column', gap: toRem(1), padding: `${toRem(4)} ${toRem(6)}`, background: color.Surface.Container, border: `${toRem(1)} solid ${color.Surface.ContainerLine}`, borderRadius: toRem(4), boxShadow: '0 2px 8px rgba(0, 0, 0, 0.12)', opacity: 0, transition: 'opacity 0.15s ease', pointerEvents: 'none', zIndex: 2, selectors: { [`${CollectibleGroupPreview}:hover &`]: { opacity: 1, }, [`${CollectibleGroupPreview}:focus-visible &`]: { opacity: 1, }, }, }); export const CollectibleHoverLabel = style({ color: color.Surface.OnContainer, fontSize: toRem(12), fontWeight: 500, lineHeight: 1.3, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', }); export const CollectibleHoverMeta = style({ color: color.Surface.OnContainer, fontSize: toRem(10), lineHeight: 1.3, opacity: 0.7, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', }); export const VariantRow = style({ display: 'flex', flexWrap: 'wrap', gap: toRem(4), justifyContent: 'center', padding: `0 ${toRem(2)}`, }); export const VariantChip = style({ border: `${toRem(1)} solid ${color.Surface.ContainerLine}`, borderRadius: toRem(4), padding: 0, background: color.Surface.Container, cursor: 'pointer', overflow: 'hidden', flexShrink: 0, }); export const VariantChipSelected = style({ border: `${toRem(2)} solid ${color.Primary.Main}`, }); export const VariantChipNameplate = style({ width: toRem(28), height: toRem(10), borderRadius: toRem(3), }); export const VariantChipThumbnail = style({ width: toRem(28), height: toRem(28), objectFit: 'cover', display: 'block', }); export const VariantChipDecorationStack = style({ position: 'relative', width: toRem(28), height: toRem(28), display: 'block', }); export const VariantChipDecorationAvatar = style({ width: '62.5%', height: '62.5%', borderRadius: '50%', overflow: 'hidden', position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', }); export const DecorationPreviewAvatar = style({ width: '100%', height: '100%', display: 'block', objectFit: 'cover', }); export const GridPreviewMedia = style({ width: '100%', height: '100%', objectFit: 'contain', objectPosition: 'top center', }); export const GridPreviewMediaCover = style({ width: '100%', height: '100%', objectFit: 'cover', objectPosition: 'top center', });