Clothing Brand Website Prompt:
Luxury Fashion Ecommerce Website Prompt
Build a premium React + Vite + Tailwind CSS ecommerce website for [BRAND NAME], a contemporary fashion label. The aesthetic should feel like a hybrid of luxury brands such as Prada, Jil Sander, The Row, and modern editorial design agencies.
The website should emphasize clean luxury, fashion-forward minimalism, premium product photography, sophisticated typography, and immersive motion design.
OVERALL DESIGN DIRECTION
Visual Personality
High-fashion editorial
Luxury ecommerce
Sophisticated minimalism
Museum-quality whitespace
Premium product storytelling
Quiet confidence
Elevated digital experience
Color Palette
Primary Background:
#EFEFEF
#F5F5F5
#FFFFFF
Typography:
#111111
#222222
#555555
Accent:
#F26522
Secondary Accent:
Warm beige tones
Soft stone gray
Subtle metallic silver highlights
Avoid:
Bright colors
Heavy gradients
Cheap ecommerce aesthetics
Large promotional banners
TYPOGRAPHY SYSTEM
Style:
Editorial luxury
Large oversized headlines
Tight tracking
Strong hierarchy
Headline:
clamp(3rem,8vw,8rem)
font-medium
tracking[-0.04em]
line-height 0.95–1.05
Body:
15–17px
line-height 1.6
Navigation:
13–14px
uppercase optional
subtle letter spacing
MOTION PRINCIPLES
All animations should feel:
Smooth
Organic
Expensive
Deliberate
Use:
duration-500
cubic-bezier(0.25,0.1,0.25,1)
Interactions:
Hover reveals
Text-roll animations
Product image transitions
Subtle zoom effects
Magnetic buttons
Smooth page scrolling
Floating motion on hero assets
Never use:
Bouncy animations
Excessive scaling
Flashy effects
HERO SECTION
Full viewport height.
Background:
Soft light gray
Animated luxury shader overlay
Film grain texture
Glass distortion effects
Navigation:
Left:
Brand logo
Shop
Collections
New Arrivals
Journal
About
Right:
Search
Wishlist
Cart
Account
Primary CTA:
Shop Collection
Secondary CTA:
View Lookbook
Hero Layout:
Small Label:
"[BRAND NAME]"
Massive headline:
"Designed for
those who dress
with intention."
Large editorial typography occupying most of the viewport.
Bottom-right floating product card:
Featured collection
Small campaign image
Collection title
Season label
COLLECTION SHOWCASE SECTION
White background.
Section badge:
"01 — Collection"
Large heading:
"Contemporary silhouettes,
crafted for everyday luxury."
Layout:
Desktop:
Editorial split layout
Left:
Large campaign image
Right:
Collection description
CTA button
Collection metadata
Images:
Full-bleed photography
High-fashion campaign imagery
Natural shadows
Clean styling
Hover:
Slow zoom
Image transition
Soft parallax movement
FEATURED PRODUCTS SECTION
Light gray background.
Section badge:
"02 — Featured"
Large heading:
"Selected pieces."
Grid:
2 columns desktop
1 column mobile
Each product card:
Image:
Large
Editorial crop
Rounded corners
Hover:
Alternate product image
Slight zoom
Quick add button appears
Product Details:
Product name
Category
Price
Floating action:
Expandable luxury button
Animated arrow icon
Product cards should resemble fashion campaign visuals rather than standard ecommerce listings.
LOOKBOOK SECTION
White background.
Immersive editorial layout.
Mix:
Portrait photography
Full-width imagery
Editorial typography overlays
Collection storytelling
Layout:
Magazine-inspired
Asymmetrical grid
High whitespace
Include:
Season title
Collection notes
Designer statement
Images should feel like a luxury fashion campaign shot for Vogue, SSENSE, or MatchesFashion.
NEW ARRIVALS SECTION
Minimal product rail.
Horizontal scroll on mobile.
Large heading:
"Latest arrivals."
Cards:
Editorial imagery
Hover transitions
Quick-view interaction
Display:
Product
Price
Sizes available
BRAND STORY SECTION
White background.
Editorial presentation.
Heading:
"Crafted with precision.
Designed with purpose."
Two-column layout.
Left:
Brand philosophy
Right:
Studio imagery
Atelier photography
Material closeups
Button:
"Discover our story"
TESTIMONIAL / PRESS SECTION
Light gray background.
Display:
Fashion publication logos
Press quotes
Industry recognition
Style:
Minimal
Refined
No heavy borders
FOOTER
Luxury editorial footer.
Large typography:
"[BRAND NAME]"
Navigation:
Shop
Collections
Journal
About
Contact
Newsletter:
Email field
Subscribe button
Social:
Instagram
Pinterest
TikTok
Bottom:
Copyright
Terms
Privacy
PRODUCT PAGE DESIGN LANGUAGE
Product gallery:
Full-screen imagery
Editorial photography
Sticky purchase panel:
Product title
Price
Size selector
Add to cart
Additional sections:
Materials
Fit guide
Care instructions
Related products
Images should dominate the experience.
TECHNICAL STACK
React 18
TypeScript
Vite
Tailwind CSS 3.4
Framer Motion
Lucide React
Shaders package for hero background
Responsive mobile-first architecture
DESIGN REFERENCES
The final result should feel like:
Luxury fashion editorial website
Premium DTC clothing brand
Art-directed campaign experience
Modern ecommerce blended with magazine design
Minimalist, cinematic, and highly curated
Think:
Prada × The Row × COS × SSENSE × High-end creative agency portfolio, transformed into a premium fashion ecommerce experience.
ReactBits Prompt:
## Integrate the <StaggeredMenu /> component from React Bits
You are helping integrate an open-source React component into an existing application.
### Component: StaggeredMenu
### Variant: JavaScript + CSS
### Dependencies: gsap
---
### Usage Example
```jsx
import StaggeredMenu from './StaggeredMenu';
const menuItems = [
{ label: 'Home', ariaLabel: 'Go to home page', link: '/' },
{ label: 'About', ariaLabel: 'Learn about us', link: '/about' },
{ label: 'Services', ariaLabel: 'View our services', link: '/services' },
{ label: 'Contact', ariaLabel: 'Get in touch', link: '/contact' }
];
const socialItems = [
{ label: 'Twitter', link: '<https://twitter.com>' },
{ label: 'GitHub', link: '<https://github.com>' },
{ label: 'LinkedIn', link: '<https://linkedin.com>' }
];
<div style={{ height: '100vh', background: '#1a1a1a' }}>
<StaggeredMenu
position="right"
items={menuItems}
socialItems={socialItems}
displaySocials={true}
displayItemNumbering={true}
menuButtonColor="#fff"
openMenuButtonColor="#fff"
changeMenuColorOnOpen={true}
colors={['#B497CF', '#5227FF']}
logoUrl="/path-to-your-logo.svg"
accentColor="#ff6b6b"
onMenuOpen={() => console.log('Menu opened')}
onMenuClose={() => console.log('Menu closed')}
/>
</div>
| Prop | Type | Default | Description |
|---|---|---|---|
| position | "left" | "right" | "right" |
| colors | string[] | ["#B497CF", "#5227FF"] | Colors used for staggered underlay layers. |
| items | StaggeredMenuItem[] | [] | Menu items rendered inside the panel. |
| socialItems | StaggeredMenuSocialItem[] | [] | Social links displayed in the menu panel. |
| displaySocials | boolean | false | Whether to display the social links section. |
| displayItemNumbering | boolean | true | Whether to show numbering for menu items. |
| className | string | undefined | Optional extra class names. |
| logoUrl | string | — | Path to the logo image. |
| menuButtonColor | string | "#fff" | Color of the menu toggle button when closed. |
| openMenuButtonColor | string | "#fff" | Color of the menu toggle button when open. |
| accentColor | string | undefined | Hover accent color for menu items. |
| changeMenuColorOnOpen | boolean | true | Whether to animate the button color when opening/closing. |
| onMenuOpen | () => void | undefined | Callback function called when menu opens. |
| onMenuClose | () => void | undefined | Callback function called when menu closes. |
| closeOnClickAway | boolean | true | Whether to close the menu when clicking outside. |
import React, { useCallback, useLayoutEffect, useRef, useState } from 'react';
import { gsap } from 'gsap';
import './StaggeredMenu.css';
export const StaggeredMenu = ({
position = 'right',
colors = ['#B497CF', '#5227FF'],
items = [],
socialItems = [],
displaySocials = true,
displayItemNumbering = true,
className,
logoUrl = '/src/assets/logos/reactbits-gh-white.svg',
menuButtonColor = '#fff',
openMenuButtonColor = '#fff',
accentColor = '#5227FF',
changeMenuColorOnOpen = true,
isFixed = false,
closeOnClickAway = true,
onMenuOpen,
onMenuClose
}) => {
const [open, setOpen] = useState(false);
const openRef = useRef(false);
const panelRef = useRef(null);
const preLayersRef = useRef(null);
const preLayerElsRef = useRef([]);
const plusHRef = useRef(null);
const plusVRef = useRef(null);
const iconRef = useRef(null);
const textInnerRef = useRef(null);
const textWrapRef = useRef(null);
const [textLines, setTextLines] = useState(['Menu', 'Close']);
const openTlRef = useRef(null);
const closeTweenRef = useRef(null);
const spinTweenRef = useRef(null);
const textCycleAnimRef = useRef(null);
const colorTweenRef = useRef(null);
const toggleBtnRef = useRef(null);
const busyRef = useRef(false);
const itemEntranceTweenRef = useRef(null);
useLayoutEffect(() => {
const ctx = gsap.context(() => {
const panel = panelRef.current;
const preContainer = preLayersRef.current;
const plusH = plusHRef.current;
const plusV = plusVRef.current;
const icon = iconRef.current;
const textInner = textInnerRef.current;
if (!panel || !plusH || !plusV || !icon || !textInner) return;
let preLayers = [];
if (preContainer) {
preLayers = Array.from(preContainer.querySelectorAll('.sm-prelayer'));
}
preLayerElsRef.current = preLayers;
const offscreen = position === 'left' ? -100 : 100;
gsap.set([panel, ...preLayers], { xPercent: offscreen, opacity: 1 });
if (preContainer) {
gsap.set(preContainer, { xPercent: 0, opacity: 1 });
}
gsap.set(plusH, { transformOrigin: '50% 50%', rotate: 0 });
gsap.set(plusV, { transformOrigin: '50% 50%', rotate: 90 });
gsap.set(icon, { rotate: 0, transformOrigin: '50% 50%' });
gsap.set(textInner, { yPercent: 0 });
if (toggleBtnRef.current) gsap.set(toggleBtnRef.current, { color: menuButtonColor });
});
return () => ctx.revert();
}, [menuButtonColor, position]);
const buildOpenTimeline = useCallback(() => {
const panel = panelRef.current;
const layers = preLayerElsRef.current;
if (!panel) return null;
openTlRef.current?.kill();
if (closeTweenRef.current) {
closeTweenRef.current.kill();
closeTweenRef.current = null;
}
itemEntranceTweenRef.current?.kill();
const itemEls = Array.from(panel.querySelectorAll('.sm-panel-itemLabel'));
const numberEls = Array.from(panel.querySelectorAll('.sm-panel-list[data-numbering] .sm-panel-item'));
const socialTitle = panel.querySelector('.sm-socials-title');
const socialLinks = Array.from(panel.querySelectorAll('.sm-socials-link'));
const offscreen = position === 'left' ? -100 : 100;
const layerStates = layers.map(el => ({ el, start: offscreen }));
const panelStart = offscreen;
if (itemEls.length) {
gsap.set(itemEls, { yPercent: 140, rotate: 10 });
}
if (numberEls.length) {
gsap.set(numberEls, { '--sm-num-opacity': 0 });
}
if (socialTitle) {
gsap.set(socialTitle, { opacity: 0 });
}
if (socialLinks.length) {
gsap.set(socialLinks, { y: 25, opacity: 0 });
}
const tl = gsap.timeline({ paused: true });
layerStates.forEach((ls, i) => {
tl.fromTo(ls.el, { xPercent: ls.start }, { xPercent: 0, duration: 0.5, ease: 'power4.out' }, i * 0.07);
});
const lastTime = layerStates.length ? (layerStates.length - 1) * 0.07 : 0;
const panelInsertTime = lastTime + (layerStates.length ? 0.08 : 0);
const panelDuration = 0.65;
tl.fromTo(
panel,
{ xPercent: panelStart },
{ xPercent: 0, duration: panelDuration, ease: 'power4.out' },
panelInsertTime
);
if (itemEls.length) {
const itemsStartRatio = 0.15;
const itemsStart = panelInsertTime + panelDuration * itemsStartRatio;
tl.to(
itemEls,
{
yPercent: 0,
rotate: 0,
duration: 1,
ease: 'power4.out',
stagger: { each: 0.1, from: 'start' }
},
itemsStart
);
if (numberEls.length) {
tl.to(
numberEls,
{
duration: 0.6,
ease: 'power2.out',
'--sm-num-opacity': 1,
stagger: { each: 0.08, from: 'start' }
},
itemsStart + 0.1
);
}
}
if (socialTitle || socialLinks.length) {
const socialsStart = panelInsertTime + panelDuration * 0.4;
if (socialTitle) {
tl.to(
socialTitle,
{
opacity: 1,
duration: 0.5,
ease: 'power2.out'
},
socialsStart
);
}
if (socialLinks.length) {
tl.to(
socialLinks,
{
y: 0,
opacity: 1,
duration: 0.55,
ease: 'power3.out',
stagger: { each: 0.08, from: 'start' },
onComplete: () => {
gsap.set(socialLinks, { clearProps: 'opacity' });
}
},
socialsStart + 0.04
);
}
}
openTlRef.current = tl;
return tl;
}, []);
const playOpen = useCallback(() => {
if (busyRef.current) return;
busyRef.current = true;
const tl = buildOpenTimeline();
if (tl) {
tl.eventCallback('onComplete', () => {
busyRef.current = false;
});
tl.play(0);
} else {
busyRef.current = false;
}
}, [buildOpenTimeline]);
const playClose = useCallback(() => {
openTlRef.current?.kill();
openTlRef.current = null;
itemEntranceTweenRef.current?.kill();
const panel = panelRef.current;
const layers = preLayerElsRef.current;
if (!panel) return;
const all = [...layers, panel];
closeTweenRef.current?.kill();
const offscreen = position === 'left' ? -100 : 100;
closeTweenRef.current = gsap.to(all, {
xPercent: offscreen,
duration: 0.32,
ease: 'power3.in',
overwrite: 'auto',
onComplete: () => {
const itemEls = Array.from(panel.querySelectorAll('.sm-panel-itemLabel'));
if (itemEls.length) {
gsap.set(itemEls, { yPercent: 140, rotate: 10 });
}
const numberEls = Array.from(panel.querySelectorAll('.sm-panel-list[data-numbering] .sm-panel-item'));
if (numberEls.length) {
gsap.set(numberEls, { '--sm-num-opacity': 0 });
}
const socialTitle = panel.querySelector('.sm-socials-title');
const socialLinks = Array.from(panel.querySelectorAll('.sm-socials-link'));
if (socialTitle) gsap.set(socialTitle, { opacity: 0 });
if (socialLinks.length) gsap.set(socialLinks, { y: 25, opacity: 0 });
busyRef.current = false;
}
});
}, [position]);
const animateIcon = useCallback(opening => {
const icon = iconRef.current;
if (!icon) return;
spinTweenRef.current?.kill();
if (opening) {
spinTweenRef.current = gsap.to(icon, { rotate: 225, duration: 0.8, ease: 'power4.out', overwrite: 'auto' });
} else {
spinTweenRef.current = gsap.to(icon, { rotate: 0, duration: 0.35, ease: 'power3.inOut', overwrite: 'auto' });
}
}, []);
const animateColor = useCallback(
opening => {
const btn = toggleBtnRef.current;
if (!btn) return;
colorTweenRef.current?.kill();
if (changeMenuColorOnOpen) {
const targetColor = opening ? openMenuButtonColor : menuButtonColor;
colorTweenRef.current = gsap.to(btn, {
color: targetColor,
delay: 0.18,
duration: 0.3,
ease: 'power2.out'
});
} else {
gsap.set(btn, { color: menuButtonColor });
}
},
[openMenuButtonColor, menuButtonColor, changeMenuColorOnOpen]
);
React.useEffect(() => {
if (toggleBtnRef.current) {
if (changeMenuColorOnOpen) {
const targetColor = openRef.current ? openMenuButtonColor : menuButtonColor;
gsap.set(toggleBtnRef.current, { color: targetColor });
} else {
gsap.set(toggleBtnRef.current, { color: menuButtonColor });
}
}
}, [changeMenuColorOnOpen, menuButtonColor, openMenuButtonColor]);
const animateText = useCallback(opening => {
const inner = textInnerRef.current;
if (!inner) return;
textCycleAnimRef.current?.kill();
const currentLabel = opening ? 'Menu' : 'Close';
const targetLabel = opening ? 'Close' : 'Menu';
const cycles = 3;
const seq = [currentLabel];
let last = currentLabel;
for (let i = 0; i < cycles; i++) {
last = last === 'Menu' ? 'Close' : 'Menu';
seq.push(last);
}
if (last !== targetLabel) seq.push(targetLabel);
seq.push(targetLabel);
setTextLines(seq);
gsap.set(inner, { yPercent: 0 });
const lineCount = seq.length;
const finalShift = ((lineCount - 1) / lineCount) * 100;
textCycleAnimRef.current = gsap.to(inner, {
yPercent: -finalShift,
duration: 0.5 + lineCount * 0.07,
ease: 'power4.out'
});
}, []);
const toggleMenu = useCallback(() => {
const target = !openRef.current;
openRef.current = target;
setOpen(target);
if (target) {
onMenuOpen?.();
playOpen();
} else {
onMenuClose?.();
playClose();
}
animateIcon(target);
animateColor(target);
animateText(target);
}, [playOpen, playClose, animateIcon, animateColor, animateText, onMenuOpen, onMenuClose]);
const closeMenu = useCallback(() => {
if (openRef.current) {
openRef.current = false;
setOpen(false);
onMenuClose?.();
playClose();
animateIcon(false);
animateColor(false);
animateText(false);
}
}, [playClose, animateIcon, animateColor, animateText, onMenuClose]);
React.useEffect(() => {
if (!closeOnClickAway || !open) return;
const handleClickOutside = event => {
if (
panelRef.current &&
!panelRef.current.contains(event.target) &&
toggleBtnRef.current &&
!toggleBtnRef.current.contains(event.target)
) {
closeMenu();
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [closeOnClickAway, open, closeMenu]);
return (
<div
className={(className ? className + ' ' : '') + 'staggered-menu-wrapper' + (isFixed ? ' fixed-wrapper' : '')}
style={accentColor ? { ['--sm-accent']: accentColor } : undefined}
data-position={position}
data-open={open || undefined}
>
<div ref={preLayersRef} className="sm-prelayers" aria-hidden="true">
{(() => {
const raw = colors && colors.length ? colors.slice(0, 4) : ['#1e1e22', '#35353c'];
let arr = [...raw];
if (arr.length >= 3) {
const mid = Math.floor(arr.length / 2);
arr.splice(mid, 1);
}
return arr.map((c, i) => <div key={i} className="sm-prelayer" style={{ background: c }} />);
})()}
</div>
<header className="staggered-menu-header" aria-label="Main navigation header">
<div className="sm-logo" aria-label="Logo">
<img
src={logoUrl || '/src/assets/logos/reactbits-gh-white.svg'}
alt="Logo"
className="sm-logo-img"
draggable={false}
width={110}
height={24}
/>
</div>
<button
ref={toggleBtnRef}
className="sm-toggle"
aria-label={open ? 'Close menu' : 'Open menu'}
aria-expanded={open}
aria-controls="staggered-menu-panel"
onClick={toggleMenu}
type="button"
>
<span ref={textWrapRef} className="sm-toggle-textWrap" aria-hidden="true">
<span ref={textInnerRef} className="sm-toggle-textInner">
{textLines.map((l, i) => (
<span className="sm-toggle-line" key={i}>
{l}
</span>
))}
</span>
</span>
<span ref={iconRef} className="sm-icon" aria-hidden="true">
<span ref={plusHRef} className="sm-icon-line" />
<span ref={plusVRef} className="sm-icon-line sm-icon-line-v" />
</span>
</button>
</header>
<aside id="staggered-menu-panel" ref={panelRef} className="staggered-menu-panel" aria-hidden={!open}>
<div className="sm-panel-inner">
<ul className="sm-panel-list" role="list" data-numbering={displayItemNumbering || undefined}>
{items && items.length ? (
items.map((it, idx) => (
<li className="sm-panel-itemWrap" key={it.label + idx}>
<a className="sm-panel-item" href={it.link} aria-label={it.ariaLabel} data-index={idx + 1}>
<span className="sm-panel-itemLabel">{it.label}</span>
</a>
</li>
))
) : (
<li className="sm-panel-itemWrap" aria-hidden="true">
<span className="sm-panel-item">
<span className="sm-panel-itemLabel">No items</span>
</span>
</li>
)}
</ul>
{displaySocials && socialItems && socialItems.length > 0 && (
<div className="sm-socials" aria-label="Social links">
<h3 className="sm-socials-title">Socials</h3>
<ul className="sm-socials-list" role="list">
{socialItems.map((s, i) => (
<li key={s.label + i} className="sm-socials-item">
<a href={s.link} target="_blank" rel="noopener noreferrer" className="sm-socials-link">
{s.label}
</a>
</li>
))}
</ul>
</div>
)}
</div>
</aside>
</div>
);
};
export default StaggeredMenu;
.staggered-menu-wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 40;
pointer-events: none;
}
.staggered-menu-wrapper.fixed-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 40;
overflow: hidden;
}
.staggered-menu-header {
position: absolute;
top: 0;
left: 0;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
padding: 2em;
background: transparent;
pointer-events: none;
z-index: 20;
}
.staggered-menu-header > * {
pointer-events: auto;
}
.sm-logo {
display: flex;
align-items: center;
user-select: none;
}
.sm-logo-img {
display: block;
height: 32px;
width: auto;
object-fit: contain;
}
.sm-toggle {
position: relative;
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: transparent;
border: none;
cursor: pointer;
color: #e9e9ef;
font-weight: 500;
line-height: 1;
overflow: visible;
}
.sm-toggle:focus-visible {
outline: 2px solid #ffffffaa;
outline-offset: 4px;
border-radius: 4px;
}
.sm-line:last-of-type {
margin-top: 6px;
}
.sm-toggle-textWrap {
position: relative;
display: inline-block;
height: 1em;
overflow: hidden;
white-space: nowrap;
width: var(--sm-toggle-width, auto);
min-width: var(--sm-toggle-width, auto);
}
.sm-toggle-textInner {
display: flex;
flex-direction: column;
line-height: 1;
}
.sm-toggle-line {
display: block;
height: 1em;
line-height: 1;
}
.sm-icon {
position: relative;
width: 14px;
height: 14px;
flex: 0 0 14px;
display: inline-flex;
align-items: center;
justify-content: center;
will-change: transform;
}
.sm-panel-itemWrap {
position: relative;
overflow: hidden;
line-height: 1;
}
.sm-icon-line {
position: absolute;
left: 50%;
top: 50%;
width: 100%;
height: 2px;
background: currentColor;
border-radius: 2px;
transform: translate(-50%, -50%);
will-change: transform;
}
.sm-line {
display: none !important;
}
.staggered-menu-panel {
position: absolute;
top: 0;
right: 0;
width: clamp(260px, 38vw, 420px);
height: 100%;
background: white;
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
display: flex;
flex-direction: column;
padding: 6em 2em 2em 2em;
overflow-y: auto;
z-index: 10;
pointer-events: auto;
opacity: 0;
}
[data-position='left'] .staggered-menu-panel {
right: auto;
left: 0;
}
.sm-prelayers {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: clamp(260px, 38vw, 420px);
pointer-events: none;
z-index: 5;
opacity: 0;
}
[data-position='left'] .sm-prelayers {
right: auto;
left: 0;
}
.sm-prelayer {
position: absolute;
top: 0;
right: 0;
height: 100%;
width: 100%;
transform: translateX(0);
opacity: 0;
}
.sm-panel-inner {
flex: 1;
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.sm-socials {
margin-top: auto;
padding-top: 2rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.sm-socials-title {
margin: 0;
font-size: 1rem;
font-weight: 500;
color: var(--sm-accent, #ff0000);
}
.sm-socials-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
.sm-socials-list .sm-socials-link {
opacity: 1;
}
.sm-socials-list:hover .sm-socials-link {
opacity: 0.35;
}
.sm-socials-list:hover .sm-socials-link:hover {
opacity: 1;
}
.sm-socials-link:focus-visible {
outline: 2px solid var(--sm-accent, #ff0000);
outline-offset: 3px;
}
.sm-socials-list:focus-within .sm-socials-link {
opacity: 0.35;
}
.sm-socials-list:focus-within .sm-socials-link:focus-visible {
opacity: 1;
}
.sm-socials-link {
font-size: 1.2rem;
font-weight: 500;
color: #111;
text-decoration: none;
position: relative;
padding: 2px 0;
display: inline-block;
transition:
color 0.3s ease,
opacity 0.3s ease;
}
.sm-socials-link:hover {
color: var(--sm-accent, #ff0000);
}
.sm-panel-title {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: #fff;
text-transform: uppercase;
}
.sm-panel-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.sm-panel-item {
position: relative;
color: #000;
font-weight: 600;
font-size: 3.5rem;
cursor: pointer;
line-height: 1;
letter-spacing: -2px;
text-transform: uppercase;
transition:
background 0.25s,
color 0.25s;
display: inline-block;
text-decoration: none;
padding-right: 1.4em;
}
.staggered-menu-panel .sm-socials-list .sm-socials-link {
opacity: 1;
transition: opacity 0.3s ease;
}
.staggered-menu-panel .sm-socials-list:hover .sm-socials-link:not(:hover) {
opacity: 0.35;
}
.staggered-menu-panel .sm-socials-list:focus-within .sm-socials-link:not(:focus-visible) {
opacity: 0.35;
}
.staggered-menu-panel .sm-socials-list .sm-socials-link:hover,
.staggered-menu-panel .sm-socials-list .sm-socials-link:focus-visible {
opacity: 1;
}
.sm-panel-itemLabel {
display: inline-block;
will-change: transform;
transform-origin: 50% 100%;
}
.sm-panel-item:hover {
color: var(--sm-accent, #5227ff);
}
.sm-panel-list[data-numbering] {
counter-reset: smItem;
}
.sm-panel-list[data-numbering] .sm-panel-item::after {
counter-increment: smItem;
content: counter(smItem, decimal-leading-zero);
position: absolute;
top: 0.1em;
right: 2.8em;
font-size: 18px;
font-weight: 400;
color: var(--sm-accent, #5227ff);
letter-spacing: 0;
pointer-events: none;
user-select: none;
opacity: var(--sm-num-opacity, 0);
}
@media (max-width: 1024px) {
.staggered-menu-panel {
width: 100%;
left: 0;
right: 0;
}
.staggered-menu-wrapper[data-open] .sm-logo-img {
filter: invert(100%);
}
}
@media (max-width: 640px) {
.staggered-menu-panel {
width: 100%;
left: 0;
right: 0;
}
.staggered-menu-wrapper[data-open] .sm-logo-img {
filter: invert(100%);
}
}