Geizkragen/style.css

1324 lines
32 KiB
CSS
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ==========================================================
GEIZKRAGEN DESIGN SYSTEM v2
Animated Dark Theme · Glassmorphism · Glow
========================================================== */
/**
* @file style.css
* @brief Main stylesheet for the Geizkragen Design System v2.
*
* This file contains all global styles, CSS variables, keyframe animations,
* layout rules, typography, and component-specific styling (such as buttons,
* cards, navigation, and footer) for the application. It utilizes a dark theme
* with glassmorphism and glow effects.
*
* @version 2.0
*/
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');
/* ==========================================================
RESET & BASIS
========================================================== */
/**
* @brief Global CSS reset.
*
* Resets margin and padding for all elements and sets box-sizing to border-box
* to ensure consistent box model calculations across the entire application.
*/
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/**
* @brief Root CSS variables defining the design token system.
*
* This pseudo-class contains all the fundamental design tokens including:
* - Colors (backgrounds, semantics, text, borders)
* - Border radii for various component sizes
* - Box shadows for elevation and glow effects
* - Transition timings for smooth animations
* - Layout spacing values
* - Primary typography settings
*/
:root {
/* ─── Farben ─── */
--bg-main: #151923;
--bg-card: #1f2937;
--bg-surface: #2d3b50;
--bg-header: #151923;
--bg-input: #1e2537;
--color-primary: #274a97;
--color-primary-hover:#1d4ed8;
--color-primary-soft: rgba(39, 74, 151, 0.15);
--color-primary-glow: rgba(39, 74, 151, 0.25);
--color-accent: #4ade80;
--color-accent-soft: rgba(74, 222, 128, 0.1);
--color-accent-glow: rgba(74, 222, 128, 0.2);
--color-danger: #d92d20;
--color-danger-soft: rgba(217, 45, 32, 0.1);
--color-warning: #f59e0b;
--color-success: #22c55e;
--text-primary: #ffffff;
--text-secondary: #cbd5e1;
--text-muted: #cbd5e1;
--text-invert: #ffffff;
--border-subtle: #2f3c52;
--border-default: #5e6075;
--border-strong: #7a7f94;
--border-glow: rgba(37, 99, 235, 0.3);
/* ─── Radii (kompakt) ─── */
--radius-sm: 3px;
--radius-md: 5px;
--radius-lg: 5px;
--radius-xl: 10px;
--radius-full: 9999px;
/* ─── Schatten ─── */
--shadow-sm: 0 10px 30px rgba(0, 0, 0, 0.08);
--shadow-md: 0 14px 34px rgba(2, 6, 23, 0.35);
--shadow-lg: 0 20px 50px rgba(0, 0, 0, 0.35);
--shadow-glow-blue: 0 0 40px rgba(37, 99, 235, 0.12);
--shadow-glow-green: 0 0 40px rgba(74, 222, 128, 0.1);
/* ─── Transitions ─── */
--transition-fast: 150ms ease;
--transition-normal: 280ms ease;
--transition-smooth: 400ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-bounce: 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
/* ─── Spacing ─── */
--nav-gutter: 1.5rem;
/* ─── Font ─── */
--font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
/* ==========================================================
KEYFRAME ANIMATIONS
========================================================== */
/**
* @brief Fade in and slide up animation.
*
* Elements transition from transparent and slightly translated down
* to fully opaque at their original position.
*/
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(24px); }
to { opacity: 1; transform: translateY(0); }
}
/**
* @brief Simple fade in animation.
*/
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/**
* @brief Slide in from the right animation.
*
* Elements transition from transparent and translated right
* to fully opaque at their original position.
*/
@keyframes slideInRight {
from { opacity: 0; transform: translateX(20px); }
to { opacity: 1; transform: translateX(0); }
}
/**
* @brief Scale in animation for a subtle zoom effect.
*
* Elements transition from transparent and slightly scaled down
* to fully opaque at their original size.
*/
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
/**
* @brief Shimmering animation for loading placeholders.
*
* Creates a moving gradient effect to simulate a shimmering light.
*/
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
/**
* @brief Pulsating glow animation for emphasis.
*
* Elements receive a glowing shadow that intensifies and fades.
*/
@keyframes pulse-glow {
0%, 100% { box-shadow: 0 0 20px rgba(37, 99, 235, 0.08); }
50% { box-shadow: 0 0 40px rgba(37, 99, 235, 0.18); }
}
/**
* @brief Continuous float animation for ambient background elements.
*/
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
/**
* @brief Gradient shifting animation for vibrant backgrounds.
*/
@keyframes gradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
/**
* @brief Border glowing animation for emphasis.
*
* Elements' borders transition between two glow states.
*/
@keyframes borderGlow {
0%, 100% { border-color: rgba(37, 99, 235, 0.15); }
50% { border-color: rgba(37, 99, 235, 0.35); }
}
/* ==========================================================
GLOBAL
========================================================== */
/**
* @brief Global standard HTML element rules.
*
* Enables smooth scrolling behavior across the entire document.
*/
html {
scroll-behavior: smooth;
}
/**
* @brief Primary body base styles.
*
* Establishes the core typography, background color, text color,
* and standard flexbox layout structure to ensure the footer sticks to the bottom.
*/
body {
font-family: var(--font-family);
background: var(--bg-main);
color: var(--text-primary);
line-height: 1.6;
min-height: 100vh;
display: flex;
flex-direction: column;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
position: relative;
overflow-x: hidden;
}
/* ─── Animated Background Grid ─── */
body::before {
content: "";
position: fixed;
inset: 0;
background-image:
linear-gradient(rgba(37, 99, 235, 0.02) 1px, transparent 1px),
linear-gradient(90deg, rgba(37, 99, 235, 0.02) 1px, transparent 1px);
background-size: 80px 80px;
pointer-events: none;
z-index: 0;
animation: fadeIn 2s ease forwards;
}
/* ─── Ambient Glow Orbs ─── */
body::after {
content: "";
position: fixed;
top: -20%;
right: -10%;
width: 600px;
height: 600px;
border-radius: 50%;
background: radial-gradient(circle, rgba(37, 99, 235, 0.06), transparent 70%);
pointer-events: none;
z-index: 0;
animation: float 15s ease-in-out infinite;
}
main {
flex: 1 0 auto;
position: relative;
z-index: 1;
}
a {
color: var(--color-primary);
text-decoration: none;
transition: color var(--transition-normal);
}
a:hover {
color: var(--color-primary-hover);
}
::selection {
background: rgba(37, 99, 235, 0.3);
color: var(--text-invert);
}
/* ==========================================================
CONTAINER
========================================================== */
/**
* @brief Standard layout container.
*
* Centers content horizontally and limits its maximum width to maintain
* readability on large screens, applying standard horizontal padding.
*/
.container {
max-width: 1400px;
margin-inline: auto;
padding-inline: var(--nav-gutter);
}
/* ==========================================================
HEADER Glassmorphism
========================================================== */
/**
* @brief Primary site header with glassmorphism effect.
*
* Ensures the header is sticky at the top, applies a blur filter for the
* glassmorphic look, and controls the initial fade-in animation.
*/
.header {
position: sticky;
top: 0;
z-index: 1000;
background: rgba(21, 25, 35, 0.92);
backdrop-filter: blur(24px) saturate(200%);
-webkit-backdrop-filter: blur(24px) saturate(200%);
border-bottom: 1px solid var(--border-subtle);
padding: 0;
animation: fadeIn 0.6s ease;
}
/* ==========================================================
NAVBAR
========================================================== */
.nav {
min-height: 64px;
width: 100%;
display: flex;
align-items: center;
position: relative;
}
.nav__logoLink {
display: inline-flex;
align-items: center;
padding-left: 0;
margin-left: 0;
transition: transform var(--transition-smooth), opacity var(--transition-normal);
}
.nav__logoLink:hover {
opacity: 0.9;
transform: scale(1.02);
}
.nav__logo {
display: block;
margin: 0;
max-width: 150px;
height: auto;
}
.nav__inner {
margin-right: 0;
flex: 1;
width: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
gap: 1.25rem;
}
/* ==========================================================
SEARCH AUTOCOMPLETE DROPDOWN
========================================================== */
/**
* @brief Wrapper for the search field when it contains a dropdown.
*/
.nav__searchField--hasDropdown {
position: relative;
}
/**
* @brief Autocomplete dropdown container styling.
*/
.searchDropdown {
position: absolute;
left: 0;
right: 0;
top: calc(100% + 10px);
z-index: 1200;
background: rgba(21, 25, 35, 0.96);
backdrop-filter: blur(18px) saturate(160%);
-webkit-backdrop-filter: blur(18px) saturate(160%);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-md);
overflow: hidden;
}
.searchDropdown__status {
padding: 12px 14px;
color: var(--text-secondary);
font-size: 0.95rem;
}
.searchDropdown__item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
color: var(--text-primary);
text-decoration: none;
border-top: 1px solid rgba(94, 96, 117, 0.18);
transition: background var(--transition-fast), transform var(--transition-fast);
}
.searchDropdown__item:first-child {
border-top: 0;
}
.searchDropdown__item:hover,
.searchDropdown__item.is-active {
background: rgba(39, 74, 151, 0.18);
}
.searchDropdown__img {
width: 44px;
height: 44px;
object-fit: cover;
border-radius: var(--radius-md);
border: 1px solid rgba(94, 96, 117, 0.25);
flex: 0 0 auto;
}
.searchDropdown__meta {
min-width: 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.searchDropdown__title {
font-weight: 700;
font-size: 0.98rem;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.searchDropdown__desc {
font-size: 0.86rem;
color: var(--text-secondary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.nav__inner.container {
margin-left: auto;
}
/* ─── Desktop: nav__menu ist eine horizontale Flex-Zeile ─── */
.nav__menu {
display: flex;
align-items: center;
}
.nav__list {
display: flex;
gap: 0.25rem;
list-style: none;
margin: 0;
padding: 0;
}
.nav__link {
color: var(--text-secondary);
font-size: 0.9rem;
font-weight: 500;
text-decoration: none;
padding: 0.5rem 1.1rem;
border-radius: var(--radius-full);
transition: all var(--transition-normal);
position: relative;
}
.nav__link:hover {
color: var(--text-invert);
background: rgba(255, 255, 255, 0.06);
transform: translateY(-1px);
}
.nav__link.active {
color: var(--color-primary);
background: var(--color-primary-soft);
box-shadow: 0 0 12px rgba(37, 99, 235, 0.12);
}
/* ”€”€”€ Nav Actions ”€”€”€ */
.nav__actions {
display: flex;
align-items: center;
gap: 0.25rem;
}
.nav__search,
.nav__login {
font-size: 1.3rem;
color: var(--text-secondary);
cursor: pointer;
transition: all var(--transition-normal);
padding: 0.5rem;
border-radius: var(--radius-md);
display: inline-flex;
align-items: center;
justify-content: center;
position: relative;
overflow: hidden;
}
.nav__login {
border-radius: var(--radius-full);
}
.nav__btn-text {
max-width: 0;
opacity: 0;
white-space: nowrap;
font-size: 0.85rem;
font-weight: 500;
transition: all 0.5s ease;
margin-left: 0;
display: inline-block;
overflow: hidden;
}
.nav__login:hover .nav__btn-text {
max-width: 100px;
opacity: 1;
margin-left: 8px;
}
.nav__search:hover,
.nav__login:hover {
color: var(--text-invert);
background: rgba(255, 255, 255, 0.08);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.nav__wishlist {
color: var(--text-secondary);
}
.nav__wishlist:hover {
color: var(--color-primary);
background: var(--color-primary-soft);
box-shadow: var(--shadow-glow-blue);
}
/* ==========================================================
TOGGLE / CLOSE auf Desktop komplett versteckt
========================================================== */
.nav__toggle,
.nav__close {
display: none;
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
padding: 0.5rem;
border-radius: var(--radius-md);
transition: color var(--transition-normal),
background var(--transition-normal),
transform var(--transition-normal);
}
.nav__toggle:hover,
.nav__close:hover {
color: var(--text-invert);
background: rgba(255, 255, 255, 0.08);
}
/* Auf Desktop versteckt */
.nav__searchBar { display: none; }
.nav__item--mobile { display: none !important; }
/* ==========================================================
MOBILE NAV (≤ 900 px)
========================================================== */
@media (max-width: 900px) {
/* Hamburger-Button sichtbar machen */
.nav__toggle {
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Mobile-only Links sichtbar */
.nav__item--mobile {
display: list-item !important;
}
/* ────────────────────────────────────────────
Das Slide-In-Panel
- position:fixed → über allem
- right:-100% → standardmäßig außerhalb
- right:0 → reingleiten bei .show-menu
──────────────────────────────────────────── */
.nav__menu {
position: fixed;
top: 0;
right: -100%;
width: min(300px, 85vw);
height: 100vh;
height: 100dvh; /* dynamic viewport auf Mobilgeräten */
background: rgba(21, 25, 35, 0.98);
backdrop-filter: blur(30px);
-webkit-backdrop-filter: blur(30px);
border-left: 1px solid var(--border-subtle);
box-shadow: -10px 0 40px rgba(0, 0, 0, 0.4);
/* Layout */
display: flex;
flex-direction: column;
align-items: stretch;
gap: 0.5rem;
padding: 4.5rem 1.5rem 2rem;
/* Scroll */
overflow-y: auto;
-webkit-overflow-scrolling: touch;
/* Z-Index */
z-index: 1001;
/* Transition */
transition: right 350ms cubic-bezier(0.4, 0, 0.2, 1);
}
.nav__menu.show-menu {
right: 0;
}
/* ─── Mobile-Suchleiste im Header (unterhalb der Nav) ─── */
.nav__searchBar {
display: block;
padding: 0 0.75rem 0.6rem;
}
.nav__searchBar .nav__searchField {
width: 100%;
}
.nav__searchBar .nav__searchInput {
width: 100%;
height: 40px;
padding: 0 14px 0 36px;
font-size: 16px; /* verhindert iOS-Zoom */
border-radius: var(--radius-full);
background: rgba(255, 255, 255, 0.05);
border: 1px solid var(--border-default);
}
.nav__searchBar .nav__searchField::before {
content: "🔍";
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
font-size: 0.78rem;
pointer-events: none;
opacity: 0.45;
}
.nav__searchBar .nav__searchInput:focus {
border-color: var(--color-primary);
background: rgba(255, 255, 255, 0.08);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}
/* ─── Links im Panel ─── */
.nav__list {
flex-direction: column;
gap: 0.15rem;
width: 100%;
}
.nav__link {
font-size: 1rem;
color: var(--text-secondary);
display: flex;
align-items: center;
min-height: 46px;
padding: 0.6rem 1rem;
border-radius: var(--radius-md);
width: 100%;
}
.nav__link:hover {
background: rgba(255, 255, 255, 0.06);
transform: translateX(4px);
}
/* ─── Schließen-Button ─── */
.nav__close {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 1rem;
right: 1rem;
min-height: 44px;
min-width: 44px;
z-index: 1;
}
.nav__close:hover {
transform: rotate(90deg);
}
}
/* ==========================================================
NAVBAR: ZENTRIERTE SUCHE
========================================================== */
.nav__searchForm {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
width: min(480px, calc(100% - 520px));
z-index: 1;
}
.nav__searchForm.auth__form,
.nav__searchForm .auth__field,
.nav__searchForm.auth__search {
margin-top: 0;
}
.nav__searchField {
width: 100%;
margin-top: 0;
position: relative;
}
.nav__searchInput {
width: 100%;
height: 42px;
padding: 0 18px 0 42px;
border-radius: var(--radius-full);
border: 1px solid var(--border-default);
background: rgba(255, 255, 255, 0.04);
color: var(--text-primary);
font-size: 0.88rem;
font-family: var(--font-family);
outline: none;
transition: all var(--transition-smooth);
}
.nav__searchField::before {
content: "🔍";
position: absolute;
left: 14px;
top: 50%;
transform: translateY(-50%);
font-size: 0.85rem;
pointer-events: none;
opacity: 0.4;
transition: opacity var(--transition-normal);
}
.nav__searchInput::placeholder {
color: var(--text-muted);
}
.nav__searchInput:focus {
border-color: var(--color-primary);
background: rgba(255, 255, 255, 0.07);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12),
var(--shadow-glow-blue);
}
.nav__searchInput:focus + .nav__searchField::before,
.nav__searchField:focus-within::before {
opacity: 0.7;
}
@media (max-width: 900px) {
.nav__searchForm {
display: none;
}
}
/* ==========================================================
LAYOUT (Grid mit Sidebar)
========================================================== */
/**
* @brief Main grid layout establishing a sidebar and main content area.
*
* Employs CSS Grid to define a 260px sidebar alongside a fluid main content area.
*/
.layout {
margin: 2rem auto;
padding: 0 2rem;
display: grid;
grid-template-columns: 260px 1fr;
gap: 2rem;
}
/* ==========================================================
FILTER / SIDEBAR
========================================================== */
/**
* @brief Sidebar container styles.
*
* Utilizes standard card background, subtle borders, and smooth fade-in animations.
*/
.sidebar {
background: var(--bg-card);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
padding: 1.25rem;
box-shadow: var(--shadow-sm);
animation: fadeInUp 0.5s ease both;
}
.sidebar h3 {
font-size: 1rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--text-primary);
}
.filter-group {
margin-bottom: 1.2rem;
}
.filter-group label {
display: block;
font-size: 0.85rem;
color: var(--text-muted);
margin-bottom: 0.35rem;
}
.filter-group input,
.filter-group select {
width: 100%;
padding: 0.5rem 0.65rem;
border-radius: var(--radius-sm);
border: 1px solid var(--border-default);
background: var(--bg-input);
color: var(--text-primary);
font-size: 0.9rem;
font-family: var(--font-family);
transition: all var(--transition-normal);
}
.filter-group input:focus,
.filter-group select:focus {
border-color: var(--color-primary);
outline: none;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}
/* ==========================================================
PRODUCT GRID
========================================================== */
/**
* @brief CSS Grid setup for laying out multiple product cards.
*
* Implements an auto-fill behavior for highly responsive product grids.
*/
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 1.6rem;
}
/* Hinweistext bei leeren Suchergebnissen */
.search-empty {
color: var(--text-secondary);
margin: 0.5rem 2rem 0;
}
/* ==========================================================
PRODUCT CARD (global)
========================================================== */
/**
* @brief Main product card component styling.
*
* Sets the background, borders, border-radius, and shadow for product items.
* Implements hover scaling and glow transitions.
*/
.product-card {
background: var(--bg-card);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
display: flex;
flex-direction: column;
transition: all var(--transition-smooth);
position: relative;
overflow: hidden;
}
.product-card::before {
content: "";
position: absolute;
inset: 0;
border-radius: var(--radius-lg);
padding: 1px;
background: linear-gradient(135deg, transparent, rgba(37,99,235,0.15), transparent);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
transition: opacity var(--transition-smooth);
}
.product-card:hover {
transform: translateY(-8px) scale(1.01);
box-shadow: var(--shadow-md), var(--shadow-glow-blue);
border-color: var(--border-strong);
}
.product-card:hover::before {
opacity: 1;
}
.product-image {
height: 180px;
background: var(--bg-surface);
border-top-left-radius: var(--radius-lg);
border-top-right-radius: var(--radius-lg);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
color: var(--text-muted);
}
.product-content {
padding: 1rem 1.1rem 1.2rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.product-title {
font-size: 0.95rem;
font-weight: 600;
color: var(--text-primary);
}
.product-meta {
font-size: 0.8rem;
color: var(--text-muted);
}
.product-price {
margin-top: 0.6rem;
font-size: 1.4rem;
font-weight: 700;
color: var(--color-primary);
}
.product-actions {
margin-top: auto;
display: flex;
gap: 0.5rem;
}
/* ==========================================================
BUTTONS Gradient & Glow
========================================================== */
/**
* @brief Base styling for all button elements.
*
* Defines flexible sizing, border radius, typography, and foundational
* transition properties for standard interactive elements.
*/
.btn {
flex: 1;
padding: 0.6rem 1.1rem;
border-radius: var(--radius-md);
font-size: 0.85rem;
font-weight: 600;
font-family: var(--font-family);
cursor: pointer;
border: none;
transition: all var(--transition-normal);
position: relative;
overflow: hidden;
}
.btn::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.1), transparent);
opacity: 0;
transition: opacity var(--transition-fast);
}
.btn:hover::after {
opacity: 1;
}
.btn:hover {
transform: translateY(-2px);
}
.btn:active {
transform: translateY(0) scale(0.98);
}
.btn-primary {
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-hover));
color: #fff;
box-shadow: 0 4px 16px rgba(37, 99, 235, 0.3);
}
.btn-primary:hover {
box-shadow: 0 6px 24px rgba(37, 99, 235, 0.45);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.04);
color: var(--text-primary);
border: 1px solid var(--border-default);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.08);
border-color: var(--border-strong);
}
.btn-danger {
background: linear-gradient(135deg, var(--color-danger), #dc2626);
color: #fff;
box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3);
}
.btn-danger:hover {
box-shadow: 0 6px 24px rgba(239, 68, 68, 0.45);
}
/* ==========================================================
BADGES
========================================================== */
/**
* @brief Basic aesthetic container for miniature tags or status labels.
*/
.badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.7rem;
border-radius: var(--radius-full);
font-size: 0.72rem;
font-weight: 600;
letter-spacing: 0.4px;
text-transform: uppercase;
}
.badge-green {
background: var(--color-accent-soft);
color: var(--color-accent);
box-shadow: 0 0 12px rgba(16, 185, 129, 0.08);
}
.badge-red {
background: var(--color-danger-soft);
color: var(--color-danger);
box-shadow: 0 0 12px rgba(239, 68, 68, 0.08);
}
/* ==========================================================
RESPONSIVE LAYOUT
========================================================== */
@media (max-width: 900px) {
.layout {
grid-template-columns: 1fr;
}
.sidebar { order: 2; }
}
/* ==========================================================
ICONS
========================================================== */
.icon-user {
width: 22px;
height: 22px;
fill: currentColor;
transition: transform var(--transition-normal);
}
.nav__login:hover .icon-user {
transform: scale(1.12);
}
/* ==========================================================
FOOTER Glassmorphism
========================================================== */
/**
* @brief Global footer component.
*
* Adheres to the overall glassmorphism aesthetic with background blur,
* border separation, and sticky-to-bottom layout integration.
*/
.footer {
margin-top: auto;
background: rgba(21, 25, 35, 0.92);
backdrop-filter: blur(24px) saturate(200%);
-webkit-backdrop-filter: blur(24px) saturate(200%);
border-top: 1px solid var(--border-subtle);
position: relative;
z-index: 1;
}
.footer .container {
padding-block: 1.75rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.footer p {
margin: 0;
font-size: 0.82rem;
color: var(--text-muted);
}
.footer__nav {
display: flex;
align-items: center;
gap: 1.5rem;
}
.footer__nav a {
color: var(--text-secondary);
text-decoration: none;
font-size: 0.82rem;
font-weight: 500;
padding: 0.4rem 0.85rem;
border-radius: var(--radius-full);
transition: all var(--transition-normal);
}
.footer__nav a:hover,
.footer__nav a:focus-visible {
color: var(--text-invert);
background: rgba(255, 255, 255, 0.06);
transform: translateY(-1px);
}
@media (max-width: 600px) {
.footer .container {
flex-direction: column;
align-items: center;
text-align: center;
}
}
/* ==========================================================
UTILITY: Staggered fade-in for child elements
========================================================== */
.animate-children > * {
animation: fadeInUp 0.5s ease both;
}
.animate-children > *:nth-child(1) { animation-delay: 0.05s; }
.animate-children > *:nth-child(2) { animation-delay: 0.1s; }
.animate-children > *:nth-child(3) { animation-delay: 0.15s; }
.animate-children > *:nth-child(4) { animation-delay: 0.2s; }
.animate-children > *:nth-child(5) { animation-delay: 0.25s; }
.animate-children > *:nth-child(6) { animation-delay: 0.3s; }
/* ==========================================================
MOBILE OPTIMIZATIONS
========================================================== */
/* ─── Touch Optimizations ─── */
@media (pointer: coarse) {
.home-nav__list li a,
.nav__login,
.nav__wishlist,
.btn,
.auth__submit,
.shop-line {
min-height: 44px;
display: inline-flex;
align-items: center;
}
/* Disable hover-only effects on touch */
.product-card:hover {
transform: none;
box-shadow: var(--shadow-sm);
}
.product-card:active {
transform: scale(0.98);
box-shadow: var(--shadow-md), var(--shadow-glow-blue);
}
.shop-line:hover {
transform: none;
padding-left: 1.5rem;
}
.shop-line:active {
background: #243248;
}
}
/* ─── Reduce motion for accessibility ─── */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ─── Tablet (max-width: 900px) ─── */
@media (max-width: 900px) {
:root {
--nav-gutter: 1rem;
}
.nav {
min-height: 56px;
padding: 0 0.5rem;
}
.nav__logo {
max-width: 120px;
}
.container {
padding-inline: 1rem;
}
.layout {
padding: 0 1rem;
margin: 1.5rem auto;
gap: 1.5rem;
}
}
/* ─── Phone (max-width: 600px) ─── */
@media (max-width: 600px) {
:root {
--nav-gutter: 0.75rem;
}
body {
font-size: 0.95rem;
}
/* Simplify background effects on mobile */
body::before {
background-size: 60px 60px;
}
body::after {
width: 300px;
height: 300px;
}
.nav {
min-height: 52px;
padding: 0 0.25rem;
}
.nav__logo {
max-width: 110px;
}
.nav__actions {
gap: 0;
}
.nav__login,
.nav__search {
padding: 0.4rem;
}
.icon-user {
width: 20px;
height: 20px;
}
.product-grid {
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: 0.8rem;
}
.product-content {
padding: 0.7rem 0.8rem 0.9rem;
}
.product-title {
font-size: 0.82rem;
}
.product-price {
font-size: 1.1rem;
}
/* Buttons larger touch targets */
.btn {
padding: 0.7rem 1.1rem;
font-size: 0.88rem;
}
.container {
padding-inline: 0.75rem;
}
}
/* ─── Tiny phones (max-width: 380px) ─── */
@media (max-width: 380px) {
.nav__logo {
max-width: 90px;
}
.nav__login,
.nav__search {
padding: 0.3rem;
}
.icon-user {
width: 18px;
height: 18px;
}
}