add site refactors and media for scent notes
BIN
parfum-shop/public/blasse-seide-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
parfum-shop/public/blasse-seide-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
parfum-shop/public/blasse-seide-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
parfum-shop/public/kalter-beton-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
parfum-shop/public/kalter-beton-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 279 KiB |
BIN
parfum-shop/public/kalter-beton-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 175 KiB |
BIN
parfum-shop/public/nasser-marmor-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
parfum-shop/public/nasser-marmor-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
parfum-shop/public/nasser-marmor-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
parfum-shop/public/schwarzes-benzin-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
parfum-shop/public/schwarzes-benzin-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 201 KiB |
BIN
parfum-shop/public/schwarzes-benzin-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
parfum-shop/public/verbranntes-chrom-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
parfum-shop/public/verbranntes-chrom-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 270 KiB |
BIN
parfum-shop/public/verbranntes-chrom-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
parfum-shop/public/weisse-asche-visual-phase-1.webp
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
parfum-shop/public/weisse-asche-visual-phase-2.webp
Normal file
|
After Width: | Height: | Size: 209 KiB |
BIN
parfum-shop/public/weisse-asche-visual-phase-3.webp
Normal file
|
After Width: | Height: | Size: 220 KiB |
@ -16,6 +16,7 @@ import CartToast from "./components/CartToast";
|
||||
import { ProductTransitionProvider } from "./components/ProductTransition";
|
||||
import useLenisSmoothScroll from "./hooks/useLenisSmoothScroll";
|
||||
import useScrollTextReveal from "./hooks/useScrollTextReveal";
|
||||
import useButtonInteractions from "./hooks/useButtonInteractions";
|
||||
import { ThemeProvider } from "./theme/ThemeContext";
|
||||
import "./style/textReveal.css";
|
||||
|
||||
@ -35,6 +36,7 @@ function App() {
|
||||
|
||||
useLenisSmoothScroll(location.pathname);
|
||||
useScrollTextReveal(routeContentRef, location.pathname);
|
||||
useButtonInteractions();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
@ -626,23 +626,54 @@
|
||||
}
|
||||
|
||||
.structure-phase-card {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
min-height: 280px;
|
||||
padding: clamp(1rem, 2vw, 1.5rem);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: var(--gap-md);
|
||||
border-color: rgba(255, 255, 255, 0.18);
|
||||
background: #262626;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.structure-phase-card::before,
|
||||
.structure-phase-card::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.structure-phase-card::before {
|
||||
background: var(--phase-visual-image, none) center / cover no-repeat;
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.structure-phase-card::after {
|
||||
background:
|
||||
linear-gradient(180deg, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.72)),
|
||||
linear-gradient(90deg, rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0.12));
|
||||
}
|
||||
|
||||
.structure-phase-card > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.structure-index {
|
||||
color: var(--theme-accent);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-size: var(--text-sm);
|
||||
letter-spacing: 0.2em;
|
||||
}
|
||||
|
||||
.structure-phase-card h3 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
color: #fff;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.02em;
|
||||
@ -657,8 +688,9 @@
|
||||
|
||||
.structure-phase-card div span {
|
||||
padding: 0.55rem 0.75rem;
|
||||
border: 1px solid var(--theme-border);
|
||||
color: var(--theme-text-muted);
|
||||
border: 1px solid rgba(255, 255, 255, 0.22);
|
||||
background: rgba(0, 0, 0, 0.26);
|
||||
color: rgba(255, 255, 255, 0.86);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
|
||||
@ -279,10 +279,23 @@ function ProductStorySection({ perfume }) {
|
||||
}
|
||||
|
||||
function ProductStructureSection({ perfume }) {
|
||||
const phaseVisualImages = perfume.phaseVisualImages || [];
|
||||
const phaseGroups = [
|
||||
{ label: "Top Notes / 0-1 h", notes: perfume.phases.top },
|
||||
{ label: "Heart Notes / 1-4 h", notes: perfume.phases.heart },
|
||||
{ label: "Base Notes / 4 h+", notes: perfume.phases.base },
|
||||
{
|
||||
label: "Top Notes / 0-1 h",
|
||||
notes: perfume.phases.top,
|
||||
visualImage: phaseVisualImages[0],
|
||||
},
|
||||
{
|
||||
label: "Heart Notes / 1-4 h",
|
||||
notes: perfume.phases.heart,
|
||||
visualImage: phaseVisualImages[1],
|
||||
},
|
||||
{
|
||||
label: "Base Notes / 4 h+",
|
||||
notes: perfume.phases.base,
|
||||
visualImage: phaseVisualImages[2],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
@ -294,7 +307,16 @@ function ProductStructureSection({ perfume }) {
|
||||
|
||||
<div className="structure-timeline">
|
||||
{phaseGroups.map((phase, index) => (
|
||||
<article className="structure-phase-card" key={phase.label} data-reveal="fade">
|
||||
<article
|
||||
className="structure-phase-card"
|
||||
key={phase.label}
|
||||
data-reveal="fade"
|
||||
style={
|
||||
phase.visualImage
|
||||
? { "--phase-visual-image": `url(${phase.visualImage})` }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<span className="structure-index">0{index + 1}</span>
|
||||
<h3>{phase.label}</h3>
|
||||
<div>
|
||||
|
||||
@ -18,6 +18,11 @@ const perfumes = [
|
||||
heart: ["Stein Akkord", "Salz", "Staubnote"],
|
||||
base: ["Zedernholz", "Pfeffer", "Weihrauch"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/kalter-beton-visual-phase-1.webp",
|
||||
"/kalter-beton-visual-phase-2.webp",
|
||||
"/kalter-beton-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Unbewohnte Räume. Erste Kälte. Architektonische Stille.",
|
||||
dosage: "2–3 Sprühstösse",
|
||||
longevity: "8–12 Stunden",
|
||||
@ -98,6 +103,11 @@ const perfumes = [
|
||||
heart: ["Marmorakkord", "Iris", "Nebelnote"],
|
||||
base: ["Moschus", "Vetiver", "Ambra"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/nasser-marmor-visual-phase-1.webp",
|
||||
"/nasser-marmor-visual-phase-2.webp",
|
||||
"/nasser-marmor-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Feuchte Flächen. Kühle Eleganz. Polierte Ruhe.",
|
||||
dosage: "2–3 Sprühstösse",
|
||||
longevity: "7–11 Stunden",
|
||||
@ -178,6 +188,11 @@ const perfumes = [
|
||||
heart: ["Iris", "Seidenakkord", "Puder"],
|
||||
base: ["Kaschmirholz", "Weisser Moschus", "Ambrette"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/blasse-seide-visual-phase-1.webp",
|
||||
"/blasse-seide-visual-phase-2.webp",
|
||||
"/blasse-seide-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Helles Gewebe. Stille Hautnähe. Gedämpfte Wärme.",
|
||||
dosage: "3–4 Sprühstösse",
|
||||
longevity: "6–10 Stunden",
|
||||
@ -258,6 +273,11 @@ const perfumes = [
|
||||
heart: ["Ascheakkord", "Papyrus", "Kreide"],
|
||||
base: ["Weisses Holz", "Rauch", "Harz"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/weisse-asche-visual-phase-1.webp",
|
||||
"/weisse-asche-visual-phase-2.webp",
|
||||
"/weisse-asche-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Stille Rückstände. Helle Spuren. Erhobene Leere.",
|
||||
dosage: "2–3 Sprühstösse",
|
||||
longevity: "8–12 Stunden",
|
||||
@ -338,6 +358,11 @@ const perfumes = [
|
||||
heart: ["Metallakkord", "Rauch", "Harz"],
|
||||
base: ["Oud", "Labdanum", "Dunkles Holz"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/verbranntes-chrom-visual-phase-1.webp",
|
||||
"/verbranntes-chrom-visual-phase-2.webp",
|
||||
"/verbranntes-chrom-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Hitze auf Metall. Dunkler Glanz. Kontrollierte Zerstörung.",
|
||||
dosage: "1–2 Sprühstösse",
|
||||
longevity: "10–14 Stunden",
|
||||
@ -418,6 +443,11 @@ const perfumes = [
|
||||
heart: ["Leder", "Birke", "Harz"],
|
||||
base: ["Patchouli", "Vetiver", "Dunkles Holz"],
|
||||
},
|
||||
phaseVisualImages: [
|
||||
"/schwarzes-benzin-visual-phase-1.webp",
|
||||
"/schwarzes-benzin-visual-phase-2.webp",
|
||||
"/schwarzes-benzin-visual-phase-3.webp",
|
||||
],
|
||||
mood: "Verbotene Oberfläche. Glanz im Schatten. Asphalt nach Regen.",
|
||||
dosage: "1–2 Sprühstösse",
|
||||
longevity: "9–13 Stunden",
|
||||
|
||||
99
parfum-shop/src/hooks/useButtonInteractions.js
Normal file
@ -0,0 +1,99 @@
|
||||
import { useEffect } from "react";
|
||||
import { gsap } from "gsap";
|
||||
|
||||
/**
|
||||
* Global, subtle GSAP micro-interactions for every `.atmos-btn`.
|
||||
*
|
||||
* Uses event delegation on the document so newly mounted buttons (drawer,
|
||||
* route changes, conditional CTAs) work without re-binding.
|
||||
*
|
||||
* Effect = premium-but-quiet:
|
||||
* - pointerenter: smooth lift + faint glow (overrides CSS transition)
|
||||
* - pointerleave: return to rest
|
||||
* - pointerdown: precise press
|
||||
* - pointerup: release
|
||||
*
|
||||
* Skipped when prefers-reduced-motion is set, or when the button is disabled.
|
||||
*/
|
||||
function useButtonInteractions() {
|
||||
useEffect(() => {
|
||||
if (typeof document === "undefined") return undefined;
|
||||
|
||||
const reduceMotion = window.matchMedia(
|
||||
"(prefers-reduced-motion: reduce)"
|
||||
).matches;
|
||||
if (reduceMotion) return undefined;
|
||||
|
||||
const isInteractiveButton = (target) => {
|
||||
if (!target || typeof target.closest !== "function") return null;
|
||||
const button = target.closest(".atmos-btn");
|
||||
if (!button) return null;
|
||||
if (button.disabled || button.getAttribute("aria-disabled") === "true") {
|
||||
return null;
|
||||
}
|
||||
return button;
|
||||
};
|
||||
|
||||
const onPointerEnter = (event) => {
|
||||
const button = isInteractiveButton(event.target);
|
||||
if (!button) return;
|
||||
gsap.to(button, {
|
||||
y: -2,
|
||||
duration: 0.32,
|
||||
ease: "power2.out",
|
||||
overwrite: "auto",
|
||||
});
|
||||
};
|
||||
|
||||
const onPointerLeave = (event) => {
|
||||
const button = isInteractiveButton(event.target);
|
||||
if (!button) return;
|
||||
gsap.to(button, {
|
||||
y: 0,
|
||||
scale: 1,
|
||||
duration: 0.42,
|
||||
ease: "power2.out",
|
||||
overwrite: "auto",
|
||||
});
|
||||
};
|
||||
|
||||
const onPointerDown = (event) => {
|
||||
const button = isInteractiveButton(event.target);
|
||||
if (!button) return;
|
||||
gsap.to(button, {
|
||||
scale: 0.97,
|
||||
duration: 0.12,
|
||||
ease: "power2.out",
|
||||
overwrite: "auto",
|
||||
});
|
||||
};
|
||||
|
||||
const onPointerUp = (event) => {
|
||||
const button = isInteractiveButton(event.target);
|
||||
if (!button) return;
|
||||
gsap.to(button, {
|
||||
scale: 1,
|
||||
duration: 0.28,
|
||||
ease: "power3.out",
|
||||
overwrite: "auto",
|
||||
});
|
||||
};
|
||||
|
||||
const root = document;
|
||||
root.addEventListener("pointerenter", onPointerEnter, true);
|
||||
root.addEventListener("pointerleave", onPointerLeave, true);
|
||||
root.addEventListener("pointerdown", onPointerDown, true);
|
||||
root.addEventListener("pointerup", onPointerUp, true);
|
||||
root.addEventListener("pointercancel", onPointerLeave, true);
|
||||
|
||||
return () => {
|
||||
root.removeEventListener("pointerenter", onPointerEnter, true);
|
||||
root.removeEventListener("pointerleave", onPointerLeave, true);
|
||||
root.removeEventListener("pointerdown", onPointerDown, true);
|
||||
root.removeEventListener("pointerup", onPointerUp, true);
|
||||
root.removeEventListener("pointercancel", onPointerLeave, true);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
|
||||
export default useButtonInteractions;
|
||||
@ -9,6 +9,7 @@
|
||||
@import "./style/tokens.css";
|
||||
@import "./style/grid.css";
|
||||
@import "./style/breakpoints.css";
|
||||
@import "./style/buttons.css";
|
||||
|
||||
@font-face {
|
||||
font-family: "Questrial";
|
||||
|
||||
@ -1,43 +1,42 @@
|
||||
/**
|
||||
* AboutPage — aligned to the visual language of LandingPage / ProductDetail:
|
||||
* - shared 12-column container width via .shell
|
||||
* - small uppercase "eyebrow" label + large light-weight headline
|
||||
* - section-y rhythm tokens
|
||||
* - hard-edge surface cards with subtle gradient overlay
|
||||
* - accent-filled CTA banner reused from product page
|
||||
*/
|
||||
|
||||
.about-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 0 var(--section-y-sm);
|
||||
color: var(--theme-text);
|
||||
background:
|
||||
radial-gradient(circle at 86% 8%, rgba(var(--theme-accent-rgb) / 0.13), transparent 28rem),
|
||||
linear-gradient(180deg, var(--theme-bg), color-mix(in srgb, var(--theme-bg) 88%, #000 12%));
|
||||
background: var(--theme-bg);
|
||||
}
|
||||
|
||||
.about-kicker,
|
||||
.about-label,
|
||||
.about-panel-label,
|
||||
.about-origin-box span,
|
||||
.about-panel-meta span,
|
||||
.about-method-points span {
|
||||
/* Eyebrow — single source of truth for kicker/label styling on this page. */
|
||||
.about-eyebrow {
|
||||
display: block;
|
||||
margin-bottom: var(--gap-2xs);
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ----- Hero -------------------------------------------------------------- */
|
||||
|
||||
.about-hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.45fr) minmax(18rem, 0.72fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: end;
|
||||
padding: clamp(2rem, 5vw, 5rem) 0 var(--section-y-sm);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
gap: clamp(0.75rem, 1.6vw, 1.25rem);
|
||||
padding: clamp(5rem, 9vw, 8rem) 0 var(--section-y-sm);
|
||||
}
|
||||
|
||||
.about-hero-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.about-hero-copy h1 {
|
||||
max-width: 11.4ch;
|
||||
margin: clamp(0.85rem, 2vw, 1.2rem) 0 clamp(1rem, 2vw, 1.35rem);
|
||||
.about-hero h1 {
|
||||
max-width: 14ch;
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(3rem, 7.4vw, 8.8rem);
|
||||
font-size: clamp(2.8rem, 8vw, 8rem);
|
||||
line-height: 0.9;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
@ -45,66 +44,45 @@
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.about-intro {
|
||||
.about-lead {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
margin: clamp(1rem, 2vw, 1.4rem) 0 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.about-hero-panel {
|
||||
padding: clamp(1.25rem, 3vw, 2rem);
|
||||
border: 1px solid rgba(var(--theme-accent-rgb) / 0.2);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(var(--theme-accent-rgb) / 0.1), transparent 62%),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.about-hero-panel p {
|
||||
margin: 0.75rem 0 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.about-panel-meta {
|
||||
display: grid;
|
||||
gap: var(--gap-sm);
|
||||
margin-top: clamp(1.2rem, 2.6vw, 2rem);
|
||||
padding-top: var(--gap-sm);
|
||||
border-top: 1px solid rgba(var(--theme-accent-rgb) / 0.2);
|
||||
/* ----- Quote ------------------------------------------------------------- */
|
||||
|
||||
.about-quote {
|
||||
margin-top: var(--section-y-sm);
|
||||
padding-top: clamp(1.6rem, 3.5vw, 2.6rem);
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.about-panel-meta p,
|
||||
.about-origin-box p,
|
||||
.about-method-points p {
|
||||
margin: 0.45rem 0 0;
|
||||
.about-quote p {
|
||||
max-width: 64rem;
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-sm);
|
||||
line-height: 1.55;
|
||||
font-size: clamp(1.6rem, 4vw, 3.6rem);
|
||||
line-height: 1.1;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.about-section {
|
||||
padding-top: var(--section-y-sm);
|
||||
}
|
||||
/* ----- Section heading (shared) ----------------------------------------- */
|
||||
|
||||
.about-section--split,
|
||||
.about-origin-section,
|
||||
.about-method-section {
|
||||
.about-section-head {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(16rem, 0.72fr) minmax(0, 1.28fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: start;
|
||||
gap: var(--gap-2xs);
|
||||
margin-bottom: clamp(1.6rem, 4vw, 3rem);
|
||||
}
|
||||
|
||||
.about-section-heading h2,
|
||||
.about-origin-copy h2,
|
||||
.about-bottom-copy h2,
|
||||
.about-method-copy h2 {
|
||||
margin: 0.75rem 0 0;
|
||||
.about-section-head h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2.15rem, 5.2vw, 6rem);
|
||||
font-size: clamp(2.2rem, 5.4vw, 6rem);
|
||||
line-height: 0.94;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
@ -112,149 +90,110 @@
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.about-section-copy,
|
||||
.about-method-points {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-sm);
|
||||
}
|
||||
/* ----- Pillars ----------------------------------------------------------- */
|
||||
|
||||
.about-section-copy p,
|
||||
.about-origin-copy p,
|
||||
.about-bottom-copy p,
|
||||
.about-method-copy p,
|
||||
.about-credential-card p,
|
||||
.about-card p,
|
||||
.about-proof-item p,
|
||||
.about-trust-note p {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.about-section-copy p + p,
|
||||
.about-origin-copy p + p {
|
||||
margin-top: var(--gap-sm);
|
||||
}
|
||||
|
||||
/* These three sections use the global Grid12 system (see Grid.jsx).
|
||||
We keep only the section-level spacing here. */
|
||||
.about-proof-strip,
|
||||
.about-grid-section,
|
||||
.about-credentials-grid {
|
||||
.about-pillars {
|
||||
margin-top: var(--section-y-sm);
|
||||
}
|
||||
|
||||
.about-card,
|
||||
.about-proof-item,
|
||||
.about-credential-card,
|
||||
.about-origin-box,
|
||||
.about-method-section,
|
||||
.about-trust-note {
|
||||
.about-pillars-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
}
|
||||
|
||||
.about-pillar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-xs);
|
||||
min-height: 14rem;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.about-card,
|
||||
.about-proof-item,
|
||||
.about-credential-card {
|
||||
min-height: 100%;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
border-color var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.about-card:hover,
|
||||
.about-proof-item:hover,
|
||||
.about-credential-card:hover {
|
||||
.about-pillar:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.42);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.about-card h3,
|
||||
.about-credential-card h3 {
|
||||
margin: 0.9rem 0 0.75rem;
|
||||
.about-pillar h3 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1.08;
|
||||
font-weight: 400;
|
||||
line-height: 1.1;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.about-proof-item {
|
||||
min-height: 9rem;
|
||||
}
|
||||
|
||||
.about-proof-item p {
|
||||
margin-top: 0.7rem;
|
||||
}
|
||||
|
||||
.about-quote-block {
|
||||
margin-top: var(--section-y-sm);
|
||||
padding: clamp(1.4rem, 4vw, 3rem);
|
||||
overflow: hidden;
|
||||
border-left: 3px solid var(--theme-accent);
|
||||
background:
|
||||
radial-gradient(circle at 100% 0%, rgba(var(--theme-accent-rgb) / 0.18), transparent 18rem),
|
||||
#171717;
|
||||
}
|
||||
|
||||
.about-quote-block p {
|
||||
max-width: 58rem;
|
||||
.about-pillar p {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: clamp(1.7rem, 4vw, 4.2rem);
|
||||
line-height: 1.08;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.about-process-section,
|
||||
.about-origin-section {
|
||||
/* ----- Origin ------------------------------------------------------------ */
|
||||
|
||||
.about-origin {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: start;
|
||||
margin-top: var(--section-y-sm);
|
||||
padding-top: var(--section-y-sm);
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.about-method-section {
|
||||
margin-top: var(--section-y-sm);
|
||||
padding: clamp(1.25rem, 3vw, 2.4rem);
|
||||
.about-origin-copy h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2.2rem, 5.2vw, 5.4rem);
|
||||
line-height: 0.94;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.about-method-points > div,
|
||||
.about-origin-box > div {
|
||||
padding-top: 1rem;
|
||||
.about-origin-copy p {
|
||||
max-width: var(--text-measure);
|
||||
margin: clamp(1rem, 2vw, 1.4rem) 0 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.about-origin-meta {
|
||||
display: grid;
|
||||
gap: var(--gap-sm);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.about-origin-meta li {
|
||||
padding-top: var(--gap-xs);
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.about-origin-box {
|
||||
display: grid;
|
||||
gap: var(--gap-sm);
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
}
|
||||
|
||||
.about-trust-note {
|
||||
margin-top: var(--section-y-sm);
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.24);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(var(--theme-accent-rgb) / 0.11), transparent 60%),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.about-trust-note p {
|
||||
max-width: 72rem;
|
||||
margin-top: 0.75rem;
|
||||
.about-origin-meta p {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.about-bottom-cta {
|
||||
/* ----- Bottom CTA (shares language with .detail-bottom-cta) ------------- */
|
||||
|
||||
.about-cta {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: var(--gap-lg);
|
||||
@ -263,88 +202,49 @@
|
||||
padding: clamp(1.5rem, 4vw, 3.5rem);
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(circle at 92% 0%, rgba(255, 255, 255, 0.22), transparent 20rem),
|
||||
var(--theme-accent-fill);
|
||||
radial-gradient(circle at 86% 12%, rgba(255, 255, 255, 0.24), transparent 18rem),
|
||||
linear-gradient(135deg, var(--theme-accent-fill), var(--theme-accent-fill-strong));
|
||||
}
|
||||
|
||||
.about-bottom-copy .about-label,
|
||||
.about-bottom-copy h2,
|
||||
.about-bottom-copy p {
|
||||
.about-cta .about-eyebrow,
|
||||
.about-cta h2 {
|
||||
color: var(--theme-accent-contrast);
|
||||
}
|
||||
|
||||
.about-bottom-copy p {
|
||||
max-width: 48rem;
|
||||
margin-top: 1rem;
|
||||
.about-cta-copy h2 {
|
||||
max-width: 22ch;
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 5vw, 5rem);
|
||||
line-height: 0.96;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.about-bottom-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--gap-xs);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.about-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
padding: 0 1.1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-lg);
|
||||
color: inherit;
|
||||
font-size: var(--text-sm);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out),
|
||||
background-color var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.about-btn:hover,
|
||||
.about-btn:focus-visible {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.about-btn--primary {
|
||||
background: #fff;
|
||||
color: var(--theme-accent-fill-strong);
|
||||
}
|
||||
|
||||
.about-btn--secondary {
|
||||
border-color: rgba(255, 255, 255, 0.22);
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
color: #fff;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
/* ----- Responsive -------------------------------------------------------- */
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.about-hero,
|
||||
.about-section--split,
|
||||
.about-origin-section,
|
||||
.about-method-section,
|
||||
.about-bottom-cta {
|
||||
.about-pillars-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.about-origin,
|
||||
.about-cta {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.about-hero {
|
||||
padding-top: clamp(1.4rem, 5vw, 2rem);
|
||||
padding-top: clamp(5.5rem, 18vw, 7rem);
|
||||
}
|
||||
|
||||
.about-hero-copy h1 {
|
||||
.about-hero h1 {
|
||||
font-size: clamp(2.55rem, 13vw, 4.4rem);
|
||||
}
|
||||
|
||||
.about-bottom-actions {
|
||||
display: grid;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.about-btn {
|
||||
width: 100%;
|
||||
.about-pillars-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,54 +1,23 @@
|
||||
import { Link } from "react-router";
|
||||
import SharedNavbar from "../components/SharedNavbar";
|
||||
import Grid, { Col } from "../components/layout/Grid";
|
||||
import PageMeta from "../components/seo/PageMeta";
|
||||
import "./AboutPage.css";
|
||||
|
||||
const PROOF_ITEMS = [
|
||||
{ label: "ATELIER", text: "Entwicklung aus einem kuratierten Duft- und Materialkontext" },
|
||||
{ label: "KLEINSERIEN", text: "Chargenbasiert gedacht statt massenmarktfähig optimiert" },
|
||||
{ label: "KOMPOSITION", text: "Materiallogik vor Trendformel und Lautstärke" },
|
||||
{ label: "HERKUNFT", text: "Creative Direction und Qualitätsanspruch aus der Schweiz" },
|
||||
];
|
||||
|
||||
const APPROACH_CARDS = [
|
||||
const PILLARS = [
|
||||
{
|
||||
label: "01 / DEKODIEREN",
|
||||
label: "01 / Material",
|
||||
title: "Atmosphäre lesen",
|
||||
text: "Wir beobachten Licht, Materialität, Temperatur, Distanz und Spannung. Nicht als Moodboard allein, sondern als System von Eindrücken, das eine bestimmte Wirkung erzeugt.",
|
||||
text: "Licht, Temperatur, Oberfläche. Wir beobachten zuerst — dann komponieren wir.",
|
||||
},
|
||||
{
|
||||
label: "02 / VERDICHTEN",
|
||||
label: "02 / Komposition",
|
||||
title: "In Duft übersetzen",
|
||||
text: "Diese Eindrücke werden in eine olfaktorische Sprache übertragen: mineralisch, staubig, metallisch, glatt, rau, still oder warm. So entsteht keine Kopie eines Objekts, sondern seine Atmosphäre.",
|
||||
text: "Eindrücke werden zu olfaktorischer Sprache: mineralisch, staubig, glatt, still.",
|
||||
},
|
||||
{
|
||||
label: "03 / REDUZIEREN",
|
||||
label: "03 / Reduktion",
|
||||
title: "Wirkung schärfen",
|
||||
text: "Wir lassen weg, was beliebig ist. Übrig bleibt eine klare Signatur: charaktervoll, hochwertig und bewusst nischig. Ein Duft, der Haltung zeigt, statt nur zu gefallen.",
|
||||
},
|
||||
];
|
||||
|
||||
const CREDENTIAL_CARDS = [
|
||||
{
|
||||
label: "ATELIER / ENTWICKLUNG",
|
||||
title: "Komposition aus einem klaren Duftverständnis",
|
||||
text: "Jede Arbeit basiert auf einem kuratierten Konzept, einer definierten Materialwelt und mehreren internen Entwicklungsstufen statt auf kurzfristigen Trendbriefings.",
|
||||
},
|
||||
{
|
||||
label: "MATERIALLOGIK",
|
||||
title: "Noten folgen einer Idee, nicht bloss einer Wirkung",
|
||||
text: "Rohstoffe und Akkorde werden danach gewählt, welche Oberfläche, Temperatur oder Spannung sie transportieren – nicht nur danach, ob sie möglichst sofort gefallen.",
|
||||
},
|
||||
{
|
||||
label: "CHARGENPRINZIP",
|
||||
title: "Kleinserie statt gesichtsloser Massenästhetik",
|
||||
text: "atmos denkt in kontrollierten Batches und klaren Editionen. Das stärkt Nachvollziehbarkeit, Qualitätsfokus und die Eigenständigkeit jeder Komposition.",
|
||||
},
|
||||
{
|
||||
label: "QUALITÄTSPRÜFUNG",
|
||||
title: "Komposition, Haltbarkeit und Verlauf werden bewusst geprüft",
|
||||
text: "Bewertet werden nicht nur Auftakt und Präsenz, sondern auch Übergänge, Balance, Textur, Wiedererkennbarkeit und das Verhalten auf Haut über mehrere Stunden.",
|
||||
text: "Wir lassen weg, was beliebig ist. Übrig bleibt eine klare, eigene Signatur.",
|
||||
},
|
||||
];
|
||||
|
||||
@ -57,294 +26,100 @@ function AboutPage() {
|
||||
<div className="about-page">
|
||||
<PageMeta
|
||||
title="About"
|
||||
description="atmos dekodiert Atmosphären und übersetzt Materialität, Raum und Charakter in konzeptionelle Düfte. Nischig. Hochwertig. Made in Switzerland."
|
||||
description="atmos dekodiert Atmosphären und übersetzt Materialität, Raum und Charakter in konzeptionelle Düfte. Made in Switzerland."
|
||||
path="/about"
|
||||
/>
|
||||
<SharedNavbar variant="hero" />
|
||||
|
||||
<main id="main-content" className="shell">
|
||||
<section className="about-hero" data-reveal-group>
|
||||
<div className="about-hero-copy">
|
||||
<span className="about-kicker" data-reveal="fade">
|
||||
<span className="about-eyebrow" data-reveal="fade">
|
||||
ABOUT atmos
|
||||
</span>
|
||||
<h1 data-reveal="lines">
|
||||
WIR DEKODIEREN
|
||||
<br />
|
||||
ATMOSPHÄREN
|
||||
<br />
|
||||
UND WANDELN
|
||||
<br />
|
||||
SIE IN DÜFTE
|
||||
ATMOSPHÄREN.
|
||||
</h1>
|
||||
<p className="about-intro" data-reveal="fade">
|
||||
atmos entwickelt Nischendüfte, die nicht bloss gut riechen sollen,
|
||||
sondern eine Atmosphäre präzise übersetzen: Material, Raum, Kälte,
|
||||
Licht, Oberfläche, Spannung. Jeder Duft ist eine verdichtete
|
||||
Komposition aus Eindruck, Haltung und Charakter.
|
||||
<p className="about-lead" data-reveal="fade">
|
||||
atmos entwickelt Nischendüfte, die eine Atmosphäre präzise
|
||||
übersetzen — Material, Raum, Licht, Spannung. Reduziert in der
|
||||
Form, konsequent in der Wirkung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="about-hero-panel" data-reveal="fade">
|
||||
<span className="about-panel-label">POSITIONIERUNG</span>
|
||||
<p>
|
||||
Nischig. Hochwertig. Edel. Luxuriös. Reduziert in der Form,
|
||||
konsequent in der Wirkung.
|
||||
</p>
|
||||
|
||||
<div className="about-panel-meta">
|
||||
<div>
|
||||
<span>HERKUNFT</span>
|
||||
<p>Made in Switzerland</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>ANSATZ</span>
|
||||
<p>Atmosphäre vor Mainstream</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>FOKUS</span>
|
||||
<p>Duft als Konzeptobjekt</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="about-section about-section--split" data-reveal-group>
|
||||
<div className="about-section-heading">
|
||||
<span className="about-label" data-reveal="fade">
|
||||
UNSER VERSTÄNDNIS
|
||||
</span>
|
||||
<h2 data-reveal="lines">NICHT DEKORATION. SONDERN HALTUNG.</h2>
|
||||
</div>
|
||||
|
||||
<div className="about-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
atmos versteht Parfum nicht als beiläufiges Accessoire, sondern als
|
||||
Form von Ausdruck. Unsere Düfte entstehen nicht aus Trends, sondern
|
||||
aus Stimmungen, Kontrasten und räumlichen Eindrücken. Uns interessiert
|
||||
nicht das Laute, Überladene oder Gefällige, sondern das Präzise, das
|
||||
Eigenständige und das, was nachwirkt.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Deshalb arbeiten wir mit Atmosphären wie kaltem Beton, nassem Marmor,
|
||||
heller Asche oder textilem Puder. Wir übersetzen Oberflächen,
|
||||
Materialien und emotionale Spannung in olfaktorische Kompositionen,
|
||||
die sich bewusst von klassischer Parfümerie abheben.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Grid
|
||||
as="section"
|
||||
gap="sm"
|
||||
className="about-proof-strip"
|
||||
data-reveal-group
|
||||
data-reveal-start="top 90%"
|
||||
>
|
||||
{PROOF_ITEMS.map((item) => (
|
||||
<Col
|
||||
key={item.label}
|
||||
span={12}
|
||||
md={6}
|
||||
lg={3}
|
||||
className="about-proof-item"
|
||||
data-reveal="fade"
|
||||
>
|
||||
<span className="about-label">{item.label}</span>
|
||||
<p>{item.text}</p>
|
||||
</Col>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<section className="about-quote-block" data-reveal-group>
|
||||
<section className="about-quote" data-reveal-group>
|
||||
<p data-reveal="fade">
|
||||
„Jeder Duft beginnt bei uns nicht mit einer Note, sondern mit einem
|
||||
Raumgefühl.“
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<Grid
|
||||
as="section"
|
||||
gap="sm"
|
||||
className="about-grid-section"
|
||||
data-reveal-group
|
||||
data-reveal-start="top 84%"
|
||||
>
|
||||
{APPROACH_CARDS.map((card) => (
|
||||
<Col
|
||||
key={card.label}
|
||||
span={12}
|
||||
md={6}
|
||||
lg={4}
|
||||
className="about-card"
|
||||
data-reveal="fade"
|
||||
>
|
||||
<span className="about-label">{card.label}</span>
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.text}</p>
|
||||
</Col>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<section
|
||||
className="about-section about-section--split about-process-section"
|
||||
data-reveal-group
|
||||
>
|
||||
<div className="about-section-heading">
|
||||
<span className="about-label" data-reveal="fade">
|
||||
PROZESS & KOMPETENZ
|
||||
<section className="about-pillars" data-reveal-group data-reveal-start="top 86%">
|
||||
<header className="about-section-head">
|
||||
<span className="about-eyebrow" data-reveal="fade">
|
||||
Unser Ansatz
|
||||
</span>
|
||||
<h2 data-reveal="lines">
|
||||
WIE AUS EINER IDEE EINE BELASTBARE KOMPOSITION WIRD.
|
||||
</h2>
|
||||
</div>
|
||||
<h2 data-reveal="lines">DREI SCHRITTE. EINE HALTUNG.</h2>
|
||||
</header>
|
||||
|
||||
<div className="about-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
atmos arbeitet nicht mit einem losgelösten Storytelling, das im
|
||||
Nachhinein auf einen Duft gelegt wird. Jede Komposition beginnt mit
|
||||
einer klaren Material- und Spannungslogik: Welche Oberfläche soll
|
||||
spürbar werden? Welche Temperatur? Welche Dichte? Welche Distanz?
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Erst danach wird in Akkorden, Übergängen und Gewichtungen gedacht.
|
||||
So entstehen Düfte, die nicht bloss „inspirierte Namen“ tragen,
|
||||
sondern in sich konsistent wirken – vom ersten Eindruck bis in den
|
||||
Drydown.
|
||||
</p>
|
||||
<div className="about-pillars-grid">
|
||||
{PILLARS.map((pillar) => (
|
||||
<article className="about-pillar" key={pillar.label} data-reveal="fade">
|
||||
<span className="about-eyebrow">{pillar.label}</span>
|
||||
<h3>{pillar.title}</h3>
|
||||
<p>{pillar.text}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Grid
|
||||
as="section"
|
||||
gap="sm"
|
||||
className="about-credentials-grid"
|
||||
data-reveal-group
|
||||
data-reveal-start="top 84%"
|
||||
>
|
||||
{CREDENTIAL_CARDS.map((card) => (
|
||||
<Col
|
||||
key={card.label}
|
||||
as="article"
|
||||
span={12}
|
||||
md={6}
|
||||
className="about-credential-card"
|
||||
data-reveal="fade"
|
||||
>
|
||||
<span className="about-label">{card.label}</span>
|
||||
<h3>{card.title}</h3>
|
||||
<p>{card.text}</p>
|
||||
</Col>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
<section className="about-method-section" data-reveal-group>
|
||||
<div className="about-method-copy">
|
||||
<span className="about-label" data-reveal="fade">
|
||||
NACHWEISBARE DUFTLOGIK
|
||||
</span>
|
||||
<h2 data-reveal="lines">
|
||||
FÜR MENSCHEN, DIE HYPE ERKENNEN UND SUBSTANZ SUCHEN.
|
||||
</h2>
|
||||
<p data-reveal="fade">
|
||||
Wer in der Szene unterwegs ist, erkennt schnell, wenn ein Duft vor
|
||||
allem über Bildsprache verkauft wird. Genau deshalb machen wir unsere
|
||||
Denkweise sichtbar: über Struktur, Materialbezug, Edition, Trageverlauf
|
||||
und eine klare innere Logik der Komposition.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="about-method-points" data-reveal="fade">
|
||||
<div>
|
||||
<span>DUFTSTRUKTUR</span>
|
||||
<p>Top, Heart und Base werden als Verlauf und nicht nur als Liste gedacht.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>MATERIALBEZUG</span>
|
||||
<p>Jeder Duft wird über Atmosphäre, Oberfläche und sensorische Spannung verankert.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>EDITIONEN</span>
|
||||
<p>Chargen und Editionen machen Entwicklung und Kontext nachvollziehbarer.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>TRAGBARKEIT</span>
|
||||
<p>Nische bedeutet bei uns Charakter – nicht Beliebigkeit oder reine Provokation.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="about-section about-origin-section" data-reveal-group>
|
||||
<section className="about-origin" data-reveal-group>
|
||||
<div className="about-origin-copy">
|
||||
<span className="about-label" data-reveal="fade">
|
||||
MADE IN SWITZERLAND
|
||||
<span className="about-eyebrow" data-reveal="fade">
|
||||
Made in Switzerland
|
||||
</span>
|
||||
<h2 data-reveal="lines">PRÄZISION IN FORM, DUFT UND AUFTRITT.</h2>
|
||||
<h2 data-reveal="lines">PRÄZISION IN FORM UND DUFT.</h2>
|
||||
<p data-reveal="fade">
|
||||
atmos ist in der Schweiz verankert. Dieser Ursprung zeigt sich nicht
|
||||
nur in der Herstellung, sondern auch in unserer Haltung zur Qualität:
|
||||
kontrolliert, bewusst, präzise und kompromisslos in der Ausarbeitung.
|
||||
</p>
|
||||
<p data-reveal="fade">
|
||||
Unsere Düfte bewegen sich zwischen Luxus und Konzept. Sie sollen
|
||||
hochwertig wirken, ohne laut zu werden. Edel, ohne klassisch zu sein.
|
||||
Und luxuriös, ohne sich über Überfluss zu definieren.
|
||||
Verankert in der Schweiz. Kontrollierte Chargen, klare Editionen,
|
||||
eine Designsprache zwischen Luxus und Konzept. Hochwertig, ohne
|
||||
laut zu werden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="about-origin-box" data-reveal="fade">
|
||||
<div>
|
||||
<span>QUALITÄTSVERSPRECHEN</span>
|
||||
<p>Kuratiert, präzise und mit Fokus auf charakterstarke Kompositionen.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>DESIGNSPRACHE</span>
|
||||
<p>Reduziert, architektonisch und materialorientiert.</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>ZIEL</span>
|
||||
<p>Düfte schaffen, die nicht austauschbar sind, sondern erinnerbar.</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="about-origin-meta" data-reveal="fade">
|
||||
<li>
|
||||
<span className="about-eyebrow">Herkunft</span>
|
||||
<p>Made in Switzerland</p>
|
||||
</li>
|
||||
<li>
|
||||
<span className="about-eyebrow">Ansatz</span>
|
||||
<p>Atmosphäre vor Mainstream</p>
|
||||
</li>
|
||||
<li>
|
||||
<span className="about-eyebrow">Fokus</span>
|
||||
<p>Duft als Konzeptobjekt</p>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="about-trust-note" data-reveal-group>
|
||||
<span className="about-label" data-reveal="fade">
|
||||
QUALITÄTSVERSTÄNDNIS
|
||||
</span>
|
||||
<p data-reveal="fade">
|
||||
Bei atmos steht nicht die schnelle Aufmerksamkeit im Vordergrund, sondern die
|
||||
Qualität der Komposition. Unsere Düfte entstehen aus klaren Materialideen,
|
||||
kontrollierter Entwicklung und einem kuratierten Anspruch an Verlauf,
|
||||
Balance, Haltbarkeit und Charakter. Jede Edition soll nicht nur auffallen,
|
||||
sondern bestehen – durch Präzision, Eigenständigkeit und eine spürbare
|
||||
kompositorische Disziplin.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="about-bottom-cta" data-reveal-group>
|
||||
<div className="about-bottom-copy">
|
||||
<span className="about-label" data-reveal="fade">
|
||||
<section className="about-cta" data-reveal-group data-on-accent>
|
||||
<div className="about-cta-copy">
|
||||
<span className="about-eyebrow" data-reveal="fade">
|
||||
atmos
|
||||
</span>
|
||||
<h2 data-reveal="lines">
|
||||
FÜR MENSCHEN, DIE NICHT NUR EINEN DUFT SUCHEN, SONDERN EINE HALTUNG.
|
||||
FÜR MENSCHEN, DIE SUBSTANZ SUCHEN.
|
||||
</h2>
|
||||
<p data-reveal="fade">
|
||||
Entdecke Düfte, die Atmosphäre nicht illustrieren, sondern in eine
|
||||
tragbare Form übersetzen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="about-bottom-actions" data-reveal="fade">
|
||||
<Link to="/" className="about-btn about-btn--primary">
|
||||
Zur Startseite
|
||||
</Link>
|
||||
<Link to="/#dufte" className="about-btn about-btn--secondary">
|
||||
<div className="atmos-btn-row atmos-btn-row--responsive" data-reveal="fade">
|
||||
<Link to="/#dufte" className="atmos-btn atmos-btn--primary">
|
||||
Düfte entdecken
|
||||
</Link>
|
||||
<Link to="/discovery-set" className="atmos-btn atmos-btn--secondary">
|
||||
Discovery Set
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@ -1,108 +1,11 @@
|
||||
/**
|
||||
* Datenschutz-specific overrides.
|
||||
*
|
||||
* The full visual system lives in ImpressumPage.css under the shared
|
||||
* `.legal-*` namespace; both pages are rendered with `class="legal-page"`
|
||||
* so they stay perfectly consistent. Page-specific tweaks belong here.
|
||||
*/
|
||||
|
||||
.datenschutz-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 0 var(--section-y-sm);
|
||||
color: var(--theme-text);
|
||||
background:
|
||||
radial-gradient(circle at 86% 8%, rgba(var(--theme-accent-rgb) / 0.12), transparent 28rem),
|
||||
linear-gradient(180deg, var(--theme-bg), color-mix(in srgb, var(--theme-bg) 88%, #000 12%));
|
||||
}
|
||||
|
||||
.datenschutz-kicker,
|
||||
.datenschutz-label {
|
||||
display: block;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.datenschutz-hero {
|
||||
padding: clamp(2rem, 5vw, 5rem) 0 var(--section-y-sm);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.datenschutz-hero h1 {
|
||||
margin: clamp(0.85rem, 2vw, 1.2rem) 0 clamp(1rem, 2vw, 1.35rem);
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(3rem, 8vw, 7.2rem);
|
||||
line-height: 0.9;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.datenschutz-intro {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.datenschutz-section {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(14rem, 0.72fr) minmax(0, 1.28fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: start;
|
||||
margin-top: var(--section-y-sm);
|
||||
padding-top: var(--section-y-sm);
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.datenschutz-section-heading h2 {
|
||||
margin: 0.75rem 0 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2rem, 4.2vw, 4.5rem);
|
||||
line-height: 0.96;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.datenschutz-section-copy p {
|
||||
margin: 0 0 1rem;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.datenschutz-list {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
margin: 0;
|
||||
padding-left: 1.1rem;
|
||||
}
|
||||
|
||||
.datenschutz-list li {
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.datenschutz-note-box {
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
border: 1px solid rgba(var(--theme-accent-rgb) / 0.24);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(var(--theme-accent-rgb) / 0.11), transparent 60%),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.datenschutz-note-box p {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.datenschutz-section {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.datenschutz-hero {
|
||||
padding-top: clamp(1.4rem, 5vw, 2rem);
|
||||
}
|
||||
/* No bespoke overrides today — kept for future page-only needs. */
|
||||
}
|
||||
|
||||
@ -1,10 +1,86 @@
|
||||
import SharedNavbar from "../components/SharedNavbar";
|
||||
import PageMeta from "../components/seo/PageMeta";
|
||||
// Datenschutz reuses the shared legal-page system defined in ImpressumPage.css.
|
||||
import "./ImpressumPage.css";
|
||||
import "./DatenschutzPage.css";
|
||||
|
||||
const SECTIONS = [
|
||||
{
|
||||
label: "Verantwortliche Stelle",
|
||||
title: "Wer für die Datenverarbeitung verantwortlich ist",
|
||||
body: [
|
||||
"Verantwortlich für die Datenverarbeitung im Zusammenhang mit dieser Website ist die atmos GmbH, Musterstrasse 12, 7000 Chur, Schweiz.",
|
||||
"E-Mail: hello@atmos.ch · Telefon: +41 00 000 00 00",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Allgemeines",
|
||||
title: "Welche Daten erhoben werden",
|
||||
body: [
|
||||
"Beim Besuch dieser Website können automatisch technische Daten erfasst werden — etwa IP-Adresse, Datum und Uhrzeit des Zugriffs, Browsertyp, Betriebssystem und Referrer-URL.",
|
||||
"Personenbezogene Daten werden darüber hinaus nur erhoben, wenn du sie freiwillig mitteilst — etwa bei einer Bestellung, einer Supportanfrage oder einer Newsletter-Anmeldung.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Zweck",
|
||||
title: "Wofür die Daten verwendet werden",
|
||||
body: ["Die Verarbeitung personenbezogener Daten erfolgt insbesondere:"],
|
||||
list: [
|
||||
"zur Bereitstellung und technischen Optimierung der Website,",
|
||||
"zur Bearbeitung von Anfragen und Supportfällen,",
|
||||
"zur Abwicklung von Bestellungen und Vertragsverhältnissen,",
|
||||
"zur Sicherheit und Missbrauchsprävention,",
|
||||
"zur Erfüllung gesetzlicher Verpflichtungen.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Cookies & Tracking",
|
||||
title: "Cookies und ähnliche Technologien",
|
||||
body: [
|
||||
"Diese Website kann Cookies oder ähnliche Technologien verwenden, um Funktionen bereitzustellen und das Nutzererlebnis zu verbessern.",
|
||||
"Soweit nicht technisch notwendige Cookies oder Tracking-Tools eingesetzt werden, erfolgt dies nur im Rahmen der jeweils geltenden rechtlichen Vorgaben.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Weitergabe",
|
||||
title: "Weitergabe an Dritte",
|
||||
body: [
|
||||
"Eine Weitergabe personenbezogener Daten an Dritte erfolgt nur, soweit dies zur Vertragserfüllung notwendig ist, eine gesetzliche Verpflichtung besteht oder eine entsprechende Einwilligung erteilt wurde.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Speicherdauer",
|
||||
title: "Wie lange Daten gespeichert werden",
|
||||
body: [
|
||||
"Personenbezogene Daten werden nur so lange gespeichert, wie dies für die jeweiligen Zwecke erforderlich ist oder gesetzliche Aufbewahrungspflichten bestehen.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Rechte",
|
||||
title: "Rechte der betroffenen Personen",
|
||||
body: [
|
||||
"Betroffene Personen haben im Rahmen des anwendbaren Datenschutzrechts insbesondere das Recht auf Auskunft, Berichtigung, Löschung, Einschränkung der Verarbeitung sowie gegebenenfalls auf Widerspruch.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Sicherheit",
|
||||
title: "Technische und organisatorische Massnahmen",
|
||||
body: [
|
||||
"Wir treffen angemessene technische und organisatorische Sicherheitsmassnahmen, um personenbezogene Daten vor unbefugtem Zugriff, Verlust oder Manipulation zu schützen.",
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Aktualisierung",
|
||||
title: "Änderungen dieser Datenschutzerklärung",
|
||||
body: [
|
||||
"atmos behält sich vor, diese Datenschutzerklärung bei Bedarf anzupassen. Es gilt jeweils die auf dieser Website veröffentlichte aktuelle Fassung.",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
function DatenschutzPage() {
|
||||
return (
|
||||
<div className="datenschutz-page">
|
||||
<div className="datenschutz-page legal-page">
|
||||
<PageMeta
|
||||
title="Datenschutz"
|
||||
description="Datenschutzerklärung von atmos: Erhebung, Speicherung und Verarbeitung personenbezogener Daten."
|
||||
@ -13,205 +89,41 @@ function DatenschutzPage() {
|
||||
<SharedNavbar variant="hero" />
|
||||
|
||||
<main id="main-content" className="shell">
|
||||
<section className="datenschutz-hero" data-reveal-group>
|
||||
<span className="datenschutz-kicker" data-reveal="fade">RECHTLICHE ANGABEN</span>
|
||||
<section className="legal-hero" data-reveal-group>
|
||||
<span className="legal-eyebrow" data-reveal="fade">
|
||||
Rechtliche Angaben
|
||||
</span>
|
||||
<h1 data-reveal="lines">DATENSCHUTZ</h1>
|
||||
<p className="datenschutz-intro" data-reveal="fade">
|
||||
<p className="legal-lead" data-reveal="fade">
|
||||
Der Schutz persönlicher Daten hat für atmos einen hohen Stellenwert.
|
||||
Nachfolgend informieren wir darüber, welche personenbezogenen Daten bei
|
||||
der Nutzung dieser Website erhoben, verarbeitet und gespeichert werden,
|
||||
zu welchen Zwecken dies erfolgt und welche Rechte betroffene Personen im
|
||||
Zusammenhang mit ihren Daten haben.
|
||||
Nachfolgend erfährst du, welche Daten wir bei der Nutzung dieser
|
||||
Website verarbeiten und welche Rechte du dabei hast.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">VERANTWORTLICHE STELLE</span>
|
||||
<h2 data-reveal="lines">WER FÜR DIE DATENVERARBEITUNG VERANTWORTLICH IST</h2>
|
||||
</div>
|
||||
{SECTIONS.map((section) => (
|
||||
<section className="legal-section" key={section.label} data-reveal-group>
|
||||
<header className="legal-section-head">
|
||||
<span className="legal-eyebrow" data-reveal="fade">
|
||||
{section.label}
|
||||
</span>
|
||||
<h2 data-reveal="lines">{section.title}</h2>
|
||||
</header>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Verantwortlich für die Datenverarbeitung im Zusammenhang mit dieser
|
||||
Website ist:
|
||||
</p>
|
||||
<p>
|
||||
atmos GmbH
|
||||
<br />
|
||||
Musterstrasse 12
|
||||
<br />
|
||||
7000 Chur
|
||||
<br />
|
||||
Schweiz
|
||||
</p>
|
||||
<p>
|
||||
E-Mail: hello@atmos.ch
|
||||
<br />
|
||||
Telefon: +41 00 000 00 00
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">ALLGEMEINES</span>
|
||||
<h2 data-reveal="lines">WELCHE DATEN ERHOBEN WERDEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Beim Besuch dieser Website können automatisch technische Daten
|
||||
erfasst werden. Dazu gehören insbesondere IP-Adresse, Datum und
|
||||
Uhrzeit des Zugriffs, Browsertyp, Betriebssystem, Referrer-URL sowie
|
||||
weitere Informationen, die zur Stabilität und Sicherheit der Website
|
||||
erforderlich sind.
|
||||
</p>
|
||||
<p>
|
||||
Personenbezogene Daten werden darüber hinaus nur dann erhoben, wenn
|
||||
du uns diese freiwillig mitteilst, beispielsweise über ein
|
||||
Kontaktformular, bei einer Bestellung, bei einer Supportanfrage oder
|
||||
durch die Anmeldung zu einem Newsletter.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">ZWECK</span>
|
||||
<h2 data-reveal="lines">WOFÜR DIE DATEN VERWENDET WERDEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>Die Verarbeitung personenbezogener Daten erfolgt insbesondere:</p>
|
||||
<ul className="datenschutz-list">
|
||||
<li>zur Bereitstellung und technischen Optimierung der Website,</li>
|
||||
<li>zur Bearbeitung von Anfragen und Supportfällen,</li>
|
||||
<li>zur Abwicklung von Bestellungen und Vertragsverhältnissen,</li>
|
||||
<li>zur Kommunikation mit Kundinnen und Kunden,</li>
|
||||
<li>zur Sicherheit und Missbrauchsprävention,</li>
|
||||
<li>zur Erfüllung gesetzlicher Verpflichtungen.</li>
|
||||
<div className="legal-section-body" data-reveal="fade">
|
||||
{section.body.map((paragraph) => (
|
||||
<p key={paragraph}>{paragraph}</p>
|
||||
))}
|
||||
{section.list && (
|
||||
<ul className="legal-list">
|
||||
{section.list.map((item) => (
|
||||
<li key={item}>{item}</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">COOKIES & TRACKING</span>
|
||||
<h2 data-reveal="lines">COOKIES UND ÄHNLICHE TECHNOLOGIEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Diese Website kann Cookies oder ähnliche Technologien verwenden, um
|
||||
Funktionen bereitzustellen, die Nutzung zu analysieren und das
|
||||
Nutzererlebnis zu verbessern. Cookies sind kleine Textdateien, die
|
||||
auf deinem Endgerät gespeichert werden.
|
||||
</p>
|
||||
<p>
|
||||
Soweit technisch nicht notwendige Cookies oder Tracking-Tools
|
||||
eingesetzt werden, erfolgt dies nur im Rahmen der jeweils geltenden
|
||||
rechtlichen Vorgaben. Falls du ein Cookie-Banner oder
|
||||
Einwilligungs-Tool einsetzt, sollten die hier gemachten Angaben exakt
|
||||
auf dieses Setup abgestimmt sein.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">WEITERGABE</span>
|
||||
<h2 data-reveal="lines">WEITERGABE AN DRITTE</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Eine Weitergabe personenbezogener Daten an Dritte erfolgt nur, soweit
|
||||
dies zur Vertragserfüllung notwendig ist, eine gesetzliche
|
||||
Verpflichtung besteht, ein berechtigtes Interesse vorliegt oder eine
|
||||
entsprechende Einwilligung erteilt wurde.
|
||||
</p>
|
||||
<p>
|
||||
Eine Datenweitergabe kann insbesondere an technische Dienstleister,
|
||||
Hosting-Anbieter, Zahlungsdienstleister, Versandpartner oder
|
||||
Analyseanbieter erfolgen, sofern dies für den Betrieb der Website
|
||||
oder die angebotenen Leistungen erforderlich ist.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">SPEICHERDAUER</span>
|
||||
<h2 data-reveal="lines">WIE LANGE DATEN GESPEICHERT WERDEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Personenbezogene Daten werden nur so lange gespeichert, wie dies für
|
||||
die jeweiligen Zwecke erforderlich ist oder gesetzliche
|
||||
Aufbewahrungspflichten bestehen. Anschliessend werden die Daten
|
||||
gelöscht oder anonymisiert, soweit keine weitere rechtliche Grundlage
|
||||
für die Verarbeitung besteht.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">RECHTE</span>
|
||||
<h2 data-reveal="lines">RECHTE DER BETROFFENEN PERSONEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Betroffene Personen haben im Rahmen des anwendbaren Datenschutzrechts
|
||||
insbesondere das Recht auf Auskunft, Berichtigung, Löschung,
|
||||
Einschränkung der Verarbeitung sowie gegebenenfalls auf Widerspruch
|
||||
gegen bestimmte Datenverarbeitungen.
|
||||
</p>
|
||||
<p>
|
||||
Anfragen hierzu können an die oben genannte verantwortliche Stelle
|
||||
gerichtet werden.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">SICHERHEIT</span>
|
||||
<h2 data-reveal="lines">TECHNISCHE UND ORGANISATORISCHE MASSNAHMEN</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Wir treffen angemessene technische und organisatorische
|
||||
Sicherheitsmassnahmen, um personenbezogene Daten vor unbefugtem
|
||||
Zugriff, Verlust, Missbrauch oder Manipulation zu schützen.
|
||||
</p>
|
||||
<p>
|
||||
Bitte beachte jedoch, dass die Datenübertragung im Internet trotz
|
||||
aller Sorgfalt Sicherheitslücken aufweisen kann.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="datenschutz-section" data-reveal-group>
|
||||
<div className="datenschutz-section-heading">
|
||||
<span className="datenschutz-label" data-reveal="fade">AKTUALISIERUNG</span>
|
||||
<h2 data-reveal="lines">ÄNDERUNGEN DIESER DATENSCHUTZERKLÄRUNG</h2>
|
||||
</div>
|
||||
|
||||
<div className="datenschutz-note-box" data-reveal="fade">
|
||||
<p>
|
||||
atmos behält sich vor, diese Datenschutzerklärung bei Bedarf
|
||||
anzupassen, insbesondere wenn sich rechtliche Vorgaben, technische
|
||||
Prozesse oder die angebotenen digitalen Leistungen weiterentwickeln.
|
||||
Es gilt jeweils die auf dieser Website veröffentlichte aktuelle
|
||||
Fassung.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,91 +1,105 @@
|
||||
.impressum-page {
|
||||
/**
|
||||
* Shared legal-page styling — used by both Impressum and Datenschutz.
|
||||
* Aligned with the global design system: .shell container, eyebrow + light
|
||||
* weight headlines, hard-edge surface cards, accent stripes via tokens.
|
||||
*
|
||||
* Class prefix `.legal-*` is shared so both pages stay perfectly consistent.
|
||||
*/
|
||||
|
||||
.legal-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 0 var(--section-y-sm);
|
||||
color: var(--theme-text);
|
||||
background:
|
||||
radial-gradient(circle at 86% 8%, rgba(var(--theme-accent-rgb) / 0.12), transparent 28rem),
|
||||
linear-gradient(180deg, var(--theme-bg), color-mix(in srgb, var(--theme-bg) 88%, #000 12%));
|
||||
background: var(--theme-bg);
|
||||
}
|
||||
|
||||
.impressum-kicker,
|
||||
.impressum-label {
|
||||
.legal-eyebrow {
|
||||
display: block;
|
||||
margin-bottom: var(--gap-2xs);
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.impressum-hero {
|
||||
padding: clamp(2rem, 5vw, 5rem) 0 var(--section-y-sm);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
/* ----- Hero -------------------------------------------------------------- */
|
||||
|
||||
.legal-hero {
|
||||
display: grid;
|
||||
gap: clamp(0.75rem, 1.6vw, 1.25rem);
|
||||
padding: clamp(5rem, 9vw, 8rem) 0 var(--section-y-sm);
|
||||
}
|
||||
|
||||
.impressum-hero h1 {
|
||||
margin: clamp(0.85rem, 2vw, 1.2rem) 0 clamp(1rem, 2vw, 1.35rem);
|
||||
.legal-hero h1 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(3rem, 8vw, 7.2rem);
|
||||
font-size: clamp(3rem, 8vw, 7.6rem);
|
||||
line-height: 0.9;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.impressum-intro {
|
||||
.legal-lead {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
margin: clamp(1rem, 2vw, 1.4rem) 0 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.65;
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.impressum-grid {
|
||||
/* ----- Fact grid (Impressum address blocks) ---------------------------- */
|
||||
|
||||
.legal-fact-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
margin-top: var(--section-y-sm);
|
||||
}
|
||||
|
||||
.impressum-card,
|
||||
.impressum-note-box {
|
||||
.legal-fact {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-xs);
|
||||
min-height: 12rem;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.6rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.impressum-card {
|
||||
min-height: 210px;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
border-color var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.impressum-card:hover {
|
||||
.legal-fact:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.42);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.impressum-card h2 {
|
||||
margin: 0.9rem 0 0.75rem;
|
||||
.legal-fact h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1.08;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 400;
|
||||
line-height: 1.15;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.impressum-card p {
|
||||
.legal-fact p {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.7;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.impressum-section {
|
||||
/* ----- Long-form sections ----------------------------------------------- */
|
||||
|
||||
.legal-section {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(14rem, 0.72fr) minmax(0, 1.28fr);
|
||||
gap: var(--gap-lg);
|
||||
@ -95,10 +109,10 @@
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.impressum-section-heading h2 {
|
||||
margin: 0.75rem 0 0;
|
||||
.legal-section-head h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2rem, 4.2vw, 4.5rem);
|
||||
font-size: clamp(1.85rem, 4vw, 3.6rem);
|
||||
line-height: 0.96;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
@ -106,37 +120,44 @@
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.impressum-section-copy p {
|
||||
margin: 0 0 1rem;
|
||||
.legal-section-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-sm);
|
||||
max-width: var(--text-measure);
|
||||
}
|
||||
|
||||
.legal-section-body p {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.75;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.impressum-note-box {
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.24);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(var(--theme-accent-rgb) / 0.11), transparent 60%),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.impressum-note-box p {
|
||||
.legal-list {
|
||||
display: grid;
|
||||
gap: 0.6rem;
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
padding-left: 1.1rem;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.65;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.impressum-grid,
|
||||
.impressum-section {
|
||||
/* ----- Responsive -------------------------------------------------------- */
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.legal-section {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.impressum-hero {
|
||||
padding-top: clamp(1.4rem, 5vw, 2rem);
|
||||
@media (max-width: 760px) {
|
||||
.legal-hero {
|
||||
padding-top: clamp(5.5rem, 18vw, 7rem);
|
||||
}
|
||||
|
||||
.legal-fact-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,70 @@ import SharedNavbar from "../components/SharedNavbar";
|
||||
import PageMeta from "../components/seo/PageMeta";
|
||||
import "./ImpressumPage.css";
|
||||
|
||||
const FACTS = [
|
||||
{
|
||||
label: "Anbieter",
|
||||
title: "Unternehmen",
|
||||
body: (
|
||||
<>
|
||||
atmos GmbH
|
||||
<br />
|
||||
Musterstrasse 12
|
||||
<br />
|
||||
7000 Chur, Schweiz
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: "Kontakt",
|
||||
title: "Erreichbarkeit",
|
||||
body: (
|
||||
<>
|
||||
hello@atmos.ch
|
||||
<br />
|
||||
+41 00 000 00 00
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
label: "Vertretungsberechtigt",
|
||||
title: "Geschäftsführung",
|
||||
body: <>Amanda Nielsen, Ermin Zoronjic, Tobias Högger, Salih Hasicic</>,
|
||||
},
|
||||
{
|
||||
label: "Handelsregister",
|
||||
title: "Registereintrag",
|
||||
body: (
|
||||
<>
|
||||
Handelsregisteramt: Kanton Graubünden
|
||||
<br />
|
||||
UID: CHE-000.000.000
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const SECTIONS = [
|
||||
{
|
||||
label: "Inhaltliche Verantwortung",
|
||||
title: "Verantwortlich für den Inhalt",
|
||||
body: "Verantwortlich für diese Website und die publizierten Inhalte ist die atmos GmbH, Musterstrasse 12, 7000 Chur, Schweiz.",
|
||||
},
|
||||
{
|
||||
label: "Haftung",
|
||||
title: "Haftungsausschluss",
|
||||
body: "Trotz sorgfältiger Kontrolle übernimmt atmos keine Gewähr für Aktualität, Richtigkeit oder Vollständigkeit der bereitgestellten Informationen. Haftungsansprüche werden im gesetzlich zulässigen Rahmen ausgeschlossen.",
|
||||
},
|
||||
{
|
||||
label: "Urheberrecht",
|
||||
title: "Urheber- und Markenrechte",
|
||||
body: "Sämtliche Inhalte dieser Website sind urheberrechtlich geschützt. Jede Vervielfältigung oder Bearbeitung bedarf der vorherigen schriftlichen Zustimmung.",
|
||||
},
|
||||
];
|
||||
|
||||
function ImpressumPage() {
|
||||
return (
|
||||
<div className="impressum-page">
|
||||
<div className="impressum-page legal-page">
|
||||
<PageMeta
|
||||
title="Impressum"
|
||||
description="Rechtliche Angaben, Verantwortlichkeit und Erreichbarkeit von atmos."
|
||||
@ -13,148 +74,40 @@ function ImpressumPage() {
|
||||
<SharedNavbar variant="hero" />
|
||||
|
||||
<main id="main-content" className="shell">
|
||||
<section className="impressum-hero" data-reveal-group>
|
||||
<span className="impressum-kicker" data-reveal="fade">
|
||||
RECHTLICHE ANGABEN
|
||||
<section className="legal-hero" data-reveal-group>
|
||||
<span className="legal-eyebrow" data-reveal="fade">
|
||||
Rechtliche Angaben
|
||||
</span>
|
||||
<h1 data-reveal="lines">IMPRESSUM</h1>
|
||||
<p className="impressum-intro" data-reveal="fade">
|
||||
Dieses Impressum enthält die rechtlichen Angaben zu atmos sowie
|
||||
Informationen zur Verantwortlichkeit, Erreichbarkeit und zu den
|
||||
veröffentlichten Inhalten dieser Website.
|
||||
<p className="legal-lead" data-reveal="fade">
|
||||
Rechtliche Angaben zu atmos sowie Informationen zur Verantwortlichkeit,
|
||||
Erreichbarkeit und zu den veröffentlichten Inhalten dieser Website.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="impressum-grid" data-reveal-group data-reveal-start="top 90%">
|
||||
<article className="impressum-card" data-reveal="fade">
|
||||
<span className="impressum-label">ANBIETER</span>
|
||||
<h2>Unternehmen</h2>
|
||||
<p>
|
||||
atmos GmbH
|
||||
<br />
|
||||
Musterstrasse 12
|
||||
<br />
|
||||
7000 Chur
|
||||
<br />
|
||||
Schweiz
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="impressum-card" data-reveal="fade">
|
||||
<span className="impressum-label">KONTAKT</span>
|
||||
<h2>Erreichbarkeit</h2>
|
||||
<p>
|
||||
E-Mail: hello@atmos.ch
|
||||
<br />
|
||||
Telefon: +41 00 000 00 00
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="impressum-card" data-reveal="fade">
|
||||
<span className="impressum-label">VERTRETUNGSBERECHTIGT</span>
|
||||
<h2>Geschäftsführung</h2>
|
||||
<p>
|
||||
Amanda Nielsen, Ermin Zoronjic, Tobias Högger, Salih Hasicic
|
||||
<br />
|
||||
Geschäftsführer*innen
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="impressum-card" data-reveal="fade">
|
||||
<span className="impressum-label">HANDELSREGISTER</span>
|
||||
<h2>Registereintrag</h2>
|
||||
<p>
|
||||
Handelsregisteramt: Kanton Graubünden
|
||||
<br />
|
||||
Unternehmens-Identifikationsnummer: CHE-000.000.000
|
||||
</p>
|
||||
<section className="legal-fact-grid" data-reveal-group data-reveal-start="top 88%">
|
||||
{FACTS.map((fact) => (
|
||||
<article className="legal-fact" key={fact.label} data-reveal="fade">
|
||||
<span className="legal-eyebrow">{fact.label}</span>
|
||||
<h2>{fact.title}</h2>
|
||||
<p>{fact.body}</p>
|
||||
</article>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<section className="impressum-section" data-reveal-group>
|
||||
<div className="impressum-section-heading">
|
||||
<span className="impressum-label" data-reveal="fade">
|
||||
INHALTLICHE VERANTWORTUNG
|
||||
{SECTIONS.map((section) => (
|
||||
<section className="legal-section" key={section.label} data-reveal-group>
|
||||
<header className="legal-section-head">
|
||||
<span className="legal-eyebrow" data-reveal="fade">
|
||||
{section.label}
|
||||
</span>
|
||||
<h2 data-reveal="lines">VERANTWORTLICH FÜR DEN INHALT</h2>
|
||||
</div>
|
||||
|
||||
<div className="impressum-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Verantwortlich für diese Website und die publizierten Inhalte:
|
||||
</p>
|
||||
<p>
|
||||
atmos GmbH
|
||||
<br />
|
||||
Musterstrasse 12
|
||||
<br />
|
||||
7000 Chur
|
||||
<br />
|
||||
Schweiz
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="impressum-section" data-reveal-group>
|
||||
<div className="impressum-section-heading">
|
||||
<span className="impressum-label" data-reveal="fade">
|
||||
HAFTUNG
|
||||
</span>
|
||||
<h2 data-reveal="lines">HAFTUNGSAUSSCHLUSS</h2>
|
||||
</div>
|
||||
|
||||
<div className="impressum-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Trotz sorgfältiger inhaltlicher Kontrolle übernimmt atmos keine
|
||||
Gewähr für die Aktualität, Richtigkeit, Vollständigkeit oder
|
||||
Qualität der bereitgestellten Informationen. Haftungsansprüche gegen
|
||||
atmos wegen Schäden materieller oder immaterieller Art, welche aus
|
||||
dem Zugriff oder der Nutzung beziehungsweise Nichtnutzung der
|
||||
veröffentlichten Informationen, durch Missbrauch der Verbindung oder
|
||||
durch technische Störungen entstanden sind, werden im gesetzlich
|
||||
zulässigen Rahmen ausgeschlossen.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="impressum-section" data-reveal-group>
|
||||
<div className="impressum-section-heading">
|
||||
<span className="impressum-label" data-reveal="fade">
|
||||
URHEBERRECHT
|
||||
</span>
|
||||
<h2 data-reveal="lines">URHEBER- UND MARKENRECHTE</h2>
|
||||
</div>
|
||||
|
||||
<div className="impressum-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Sämtliche Inhalte dieser Website, einschliesslich Texte, Bilder,
|
||||
Gestaltungselemente, Logos und Marken, sind urheberrechtlich
|
||||
geschützt und Eigentum von atmos oder der jeweils genannten
|
||||
Rechteinhaber, sofern nicht anders angegeben. Jede Vervielfältigung,
|
||||
Bearbeitung, Verbreitung oder sonstige Verwendung ausserhalb der
|
||||
gesetzlichen Schranken bedarf der vorherigen schriftlichen Zustimmung.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="impressum-section" data-reveal-group>
|
||||
<div className="impressum-section-heading">
|
||||
<span className="impressum-label" data-reveal="fade">
|
||||
TRANSPARENZ
|
||||
</span>
|
||||
<h2 data-reveal="lines">KLARE ANGABEN UND ERREICHBARKEIT</h2>
|
||||
</div>
|
||||
|
||||
<div className="impressum-note-box" data-reveal="fade">
|
||||
<p>
|
||||
atmos legt Wert auf eine klare, transparente und nachvollziehbare
|
||||
Kommunikation. Dieses Impressum dient der eindeutigen
|
||||
Anbieterkennzeichnung und stellt die wesentlichen Informationen zur
|
||||
verantwortlichen Stelle, Kontaktaufnahme und rechtlichen Zuordnung
|
||||
dieser Website bereit.
|
||||
</p>
|
||||
<h2 data-reveal="lines">{section.title}</h2>
|
||||
</header>
|
||||
<div className="legal-section-body" data-reveal="fade">
|
||||
<p>{section.body}</p>
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,124 +1,153 @@
|
||||
/**
|
||||
* SmallBatchPage (Early Access) — same visual rhythm as About / Support.
|
||||
* All buttons go through the global .atmos-btn system; only structural,
|
||||
* data-display styling lives here.
|
||||
*/
|
||||
|
||||
.small-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 0 var(--section-y-sm);
|
||||
color: var(--theme-text);
|
||||
background:
|
||||
radial-gradient(circle at 84% 8%, rgba(var(--theme-accent-rgb) / 0.13), transparent 28rem),
|
||||
linear-gradient(180deg, var(--theme-bg), color-mix(in srgb, var(--theme-bg) 88%, #000 12%));
|
||||
background: var(--theme-bg);
|
||||
}
|
||||
|
||||
.small-hero {
|
||||
max-width: 64rem;
|
||||
padding: clamp(2rem, 5vw, 5rem) 0 var(--section-y-sm);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.small-kicker,
|
||||
.small-requirement span,
|
||||
.release-card span {
|
||||
.small-eyebrow {
|
||||
display: block;
|
||||
margin-bottom: 0.75rem;
|
||||
margin-bottom: var(--gap-2xs);
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.small-hero h1,
|
||||
.small-panel h2 {
|
||||
margin: 0 0 clamp(0.85rem, 2vw, 1.2rem);
|
||||
color: var(--theme-text);
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
/* ----- Hero -------------------------------------------------------------- */
|
||||
|
||||
.small-hero {
|
||||
display: grid;
|
||||
gap: clamp(0.75rem, 1.6vw, 1.25rem);
|
||||
max-width: 64rem;
|
||||
padding: clamp(5rem, 9vw, 8rem) 0 var(--section-y-sm);
|
||||
}
|
||||
|
||||
.small-hero h1 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(3rem, 8.6vw, 9rem);
|
||||
line-height: 0.88;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.small-panel h2 {
|
||||
font-size: clamp(2.2rem, 5vw, 5.4rem);
|
||||
line-height: 0.94;
|
||||
}
|
||||
|
||||
.small-hero p,
|
||||
.small-panel p,
|
||||
.release-card p {
|
||||
.small-lead {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
margin: clamp(1rem, 2vw, 1.4rem) 0 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.65;
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.small-panel,
|
||||
.release-card,
|
||||
.small-error {
|
||||
/* ----- Panels ------------------------------------------------------------ */
|
||||
|
||||
.small-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-sm);
|
||||
margin-top: var(--section-y-sm);
|
||||
padding: clamp(1.25rem, 3vw, 2.2rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.small-panel {
|
||||
max-width: 68rem;
|
||||
margin-top: var(--section-y-sm);
|
||||
padding: clamp(1.25rem, 3vw, 2.2rem);
|
||||
.small-panel h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(1.85rem, 4vw, 3.4rem);
|
||||
line-height: 0.96;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.small-panel button,
|
||||
.release-card button {
|
||||
.small-panel p {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.small-panel-head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: end;
|
||||
justify-content: space-between;
|
||||
gap: var(--gap-sm);
|
||||
}
|
||||
|
||||
.small-panel-head > div {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.small-status-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
margin-top: 1.2rem;
|
||||
padding: 0 1.1rem;
|
||||
border: 1px solid #111;
|
||||
border-radius: var(--radius-lg);
|
||||
background: #111;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
font-size: var(--text-sm);
|
||||
min-height: 32px;
|
||||
padding: 0 0.85rem;
|
||||
border: 1px solid var(--theme-border);
|
||||
background: transparent;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out),
|
||||
background-color var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.small-panel button:hover,
|
||||
.release-card button:hover,
|
||||
.small-panel button:focus-visible,
|
||||
.release-card button:focus-visible {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
.small-status-pill.is-unlocked {
|
||||
border-color: var(--theme-accent);
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
|
||||
/* ----- Requirements grid ------------------------------------------------ */
|
||||
|
||||
.small-requirements {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
margin-top: clamp(1.4rem, 3vw, 2.4rem);
|
||||
gap: var(--gap-xs);
|
||||
margin-top: var(--gap-sm);
|
||||
}
|
||||
|
||||
.small-requirement {
|
||||
min-height: 7rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: var(--gap-xs);
|
||||
padding: clamp(1rem, 2vw, 1.4rem);
|
||||
min-height: 7rem;
|
||||
padding: clamp(0.95rem, 2vw, 1.25rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background: var(--theme-paper);
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.small-requirement span {
|
||||
margin-bottom: 0;
|
||||
.small-requirement::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--theme-accent);
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
transition: transform var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.small-requirement.is-met::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.small-requirement strong {
|
||||
@ -128,18 +157,26 @@
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.small-requirement strong.met {
|
||||
.small-requirement.is-met strong {
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
|
||||
.small-error {
|
||||
max-width: 68rem;
|
||||
/* ----- Status / error message ------------------------------------------ */
|
||||
|
||||
.small-message {
|
||||
max-width: 64rem;
|
||||
margin: var(--gap-sm) 0 0;
|
||||
padding: clamp(1rem, 2vw, 1.4rem);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.45);
|
||||
border: 1px solid rgba(var(--theme-accent-rgb) / 0.45);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
/* ----- Releases --------------------------------------------------------- */
|
||||
|
||||
.release-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@ -148,12 +185,15 @@
|
||||
}
|
||||
|
||||
.release-card {
|
||||
min-height: 280px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: var(--gap-sm);
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
gap: var(--gap-xs);
|
||||
min-height: 18rem;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.6rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
border-color var(--duration-med) var(--ease-out),
|
||||
@ -166,21 +206,30 @@
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.release-card span {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.release-card h3 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1.08;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 400;
|
||||
line-height: 1.15;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.release-card p {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ----- Responsive -------------------------------------------------------- */
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.small-requirements,
|
||||
.small-requirements {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.release-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
@ -188,7 +237,7 @@
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.small-hero {
|
||||
padding-top: clamp(1.4rem, 5vw, 2rem);
|
||||
padding-top: clamp(5.5rem, 18vw, 7rem);
|
||||
}
|
||||
|
||||
.small-hero h1 {
|
||||
@ -199,9 +248,4 @@
|
||||
.release-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.small-panel button,
|
||||
.release-card button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,9 +7,9 @@ import "./SmallBatchPage.css";
|
||||
|
||||
function Requirement({ label, met, children }) {
|
||||
return (
|
||||
<div className="small-requirement">
|
||||
<span>{label}</span>
|
||||
<strong className={met ? "met" : ""}>{children || (met ? "met" : "open")}</strong>
|
||||
<div className={`small-requirement ${met ? "is-met" : ""}`}>
|
||||
<span className="small-eyebrow">{label}</span>
|
||||
<strong>{children || (met ? "Erfüllt" : "Offen")}</strong>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -70,57 +70,89 @@ function SmallBatchPage() {
|
||||
|
||||
<main id="main-content" className="shell">
|
||||
<section className="small-hero" data-reveal-group>
|
||||
<span className="small-kicker" data-reveal="fade">
|
||||
SMALL BATCH / ARCHIVE / PROTOTYPE
|
||||
<span className="small-eyebrow" data-reveal="fade">
|
||||
Small Batch · Archive · Prototype
|
||||
</span>
|
||||
<h1 data-reveal="fade">EARLY ACCESS</h1>
|
||||
<p data-reveal="fade">
|
||||
Limited releases are reserved for customers with enough purchase
|
||||
history to understand the atmos material language.
|
||||
<h1 data-reveal="lines">EARLY ACCESS.</h1>
|
||||
<p className="small-lead" data-reveal="fade">
|
||||
Limitierte Releases sind Kund:innen vorbehalten, die genug
|
||||
Berührung mit der atmos Materialwelt hatten — kuratiert,
|
||||
chargenbasiert, in kleiner Auflage.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{!user ? (
|
||||
<section className="small-panel" data-reveal-group>
|
||||
<span className="small-kicker" data-reveal="fade">
|
||||
LOGIN REQUIRED
|
||||
<span className="small-eyebrow" data-reveal="fade">
|
||||
Login erforderlich
|
||||
</span>
|
||||
<h2 data-reveal="fade">Sign in to check access.</h2>
|
||||
<p data-reveal="fade">Small Batch access is calculated from your completed orders.</p>
|
||||
<button type="button" onClick={openProfile}>
|
||||
Login / Register
|
||||
<h2 data-reveal="fade">Melde dich an, um deinen Zugang zu prüfen.</h2>
|
||||
<p data-reveal="fade">
|
||||
Small Batch Access wird aus deinen abgeschlossenen Bestellungen
|
||||
berechnet.
|
||||
</p>
|
||||
<div className="atmos-btn-row" data-reveal="fade">
|
||||
<button
|
||||
type="button"
|
||||
className="atmos-btn atmos-btn--primary"
|
||||
onClick={openProfile}
|
||||
>
|
||||
Anmelden / Registrieren
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<>
|
||||
<section className="small-panel" data-reveal-group>
|
||||
<span className="small-kicker" data-reveal="fade">
|
||||
ACCESS STATUS
|
||||
<div className="small-panel-head">
|
||||
<div>
|
||||
<span className="small-eyebrow" data-reveal="fade">
|
||||
Access Status
|
||||
</span>
|
||||
<h2 data-reveal="fade">{loyalty.unlocked ? "Unlocked" : "Locked"}</h2>
|
||||
<h2 data-reveal="fade">
|
||||
{loyalty.unlocked ? "Freigeschaltet" : "Noch gesperrt"}
|
||||
</h2>
|
||||
</div>
|
||||
<span
|
||||
className={`small-status-pill ${loyalty.unlocked ? "is-unlocked" : ""}`}
|
||||
data-reveal="fade"
|
||||
>
|
||||
{loyalty.unlocked ? "Unlocked" : "Locked"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="small-requirements" data-reveal="fade">
|
||||
<Requirement label="Discovery Set" met={loyalty.hasDiscoverySet} />
|
||||
<Requirement label="Full Size" met={loyalty.hasFullSize} />
|
||||
<Requirement label="Purchases" met={loyalty.purchases >= 3}>
|
||||
{loyalty.purchases}/3 Purchases
|
||||
<Requirement label="Bestellungen" met={loyalty.purchases >= 3}>
|
||||
{loyalty.purchases}/3
|
||||
</Requirement>
|
||||
<Requirement label="Spend" met={loyalty.spent_cents > 50000}>
|
||||
<Requirement label="Umsatz" met={loyalty.spent_cents > 50000}>
|
||||
{formatChf(loyalty.spent_cents)} / CHF 500+
|
||||
</Requirement>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{state.error && <p className="small-error">{state.error}</p>}
|
||||
{state.loading && <p className="small-error">Loading access...</p>}
|
||||
{state.error && <p className="small-message">{state.error}</p>}
|
||||
{state.loading && <p className="small-message">Loading access…</p>}
|
||||
|
||||
{loyalty.unlocked && (
|
||||
<section className="release-grid" data-reveal-group data-reveal-start="top 88%">
|
||||
{loyalty.unlocked && state.releases.length > 0 && (
|
||||
<section
|
||||
className="release-grid"
|
||||
data-reveal-group
|
||||
data-reveal-start="top 88%"
|
||||
>
|
||||
{state.releases.map((release) => (
|
||||
<article className="release-card" key={release.name} data-reveal="fade">
|
||||
<span>{release.type}</span>
|
||||
<span className="small-eyebrow">{release.type}</span>
|
||||
<h3>{release.name}</h3>
|
||||
<p>{release.note}</p>
|
||||
<button type="button">Request Allocation</button>
|
||||
<button
|
||||
type="button"
|
||||
className="atmos-btn atmos-btn--outline atmos-btn--block"
|
||||
>
|
||||
Allokation anfragen
|
||||
</button>
|
||||
</article>
|
||||
))}
|
||||
</section>
|
||||
|
||||
@ -1,30 +1,35 @@
|
||||
/**
|
||||
* SupportPage — same visual rhythm as AboutPage:
|
||||
* - .shell container, eyebrow + light-weight headline
|
||||
* - hard-edge surface cards
|
||||
* - accent CTA banner reused at the bottom
|
||||
* - all CTAs use the global .atmos-btn system
|
||||
*/
|
||||
|
||||
.support-page {
|
||||
min-height: 100vh;
|
||||
padding: 0 0 var(--section-y-sm);
|
||||
color: var(--theme-text);
|
||||
background:
|
||||
radial-gradient(circle at 86% 8%, rgba(var(--theme-accent-rgb) / 0.13), transparent 28rem),
|
||||
linear-gradient(180deg, var(--theme-bg), color-mix(in srgb, var(--theme-bg) 88%, #000 12%));
|
||||
background: var(--theme-bg);
|
||||
}
|
||||
|
||||
.support-kicker,
|
||||
.support-label,
|
||||
.support-panel-label,
|
||||
.support-panel-meta span {
|
||||
.support-eyebrow {
|
||||
display: block;
|
||||
margin-bottom: var(--gap-2xs);
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-xs);
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* ----- Hero -------------------------------------------------------------- */
|
||||
|
||||
.support-hero {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1.45fr) minmax(18rem, 0.72fr);
|
||||
grid-template-columns: minmax(0, 1.4fr) minmax(18rem, 0.72fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: end;
|
||||
padding: clamp(2rem, 5vw, 5rem) 0 var(--section-y-sm);
|
||||
border-bottom: 1px solid var(--theme-border);
|
||||
padding: clamp(5rem, 9vw, 8rem) 0 var(--section-y-sm);
|
||||
}
|
||||
|
||||
.support-hero-copy {
|
||||
@ -32,10 +37,10 @@
|
||||
}
|
||||
|
||||
.support-hero-copy h1 {
|
||||
max-width: 10.8ch;
|
||||
margin: clamp(0.85rem, 2vw, 1.2rem) 0 clamp(1rem, 2vw, 1.35rem);
|
||||
max-width: 12ch;
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(3rem, 7.4vw, 8.8rem);
|
||||
font-size: clamp(2.8rem, 8vw, 8rem);
|
||||
line-height: 0.9;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
@ -43,108 +48,68 @@
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.support-intro {
|
||||
.support-lead {
|
||||
max-width: var(--text-measure);
|
||||
margin: 0;
|
||||
margin: clamp(1rem, 2vw, 1.4rem) 0 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-lg);
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
.support-hero-panel {
|
||||
padding: clamp(1.25rem, 3vw, 2rem);
|
||||
border: 1px solid rgba(var(--theme-accent-rgb) / 0.2);
|
||||
background:
|
||||
linear-gradient(135deg, rgba(var(--theme-accent-rgb) / 0.1), transparent 62%),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.support-hero-panel p {
|
||||
margin: 0.75rem 0 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.62;
|
||||
}
|
||||
|
||||
.support-panel-meta {
|
||||
display: grid;
|
||||
gap: var(--gap-sm);
|
||||
margin-top: clamp(1.2rem, 2.6vw, 2rem);
|
||||
padding-top: var(--gap-sm);
|
||||
border-top: 1px solid rgba(var(--theme-accent-rgb) / 0.2);
|
||||
/* ----- Contact card ------------------------------------------------------ */
|
||||
|
||||
.support-contact-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-xs);
|
||||
padding: clamp(1.25rem, 3vw, 1.8rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
var(--theme-surface-soft);
|
||||
}
|
||||
|
||||
.support-panel-meta p {
|
||||
margin: 0.45rem 0 0;
|
||||
.support-mail-link {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(1.25rem, 2.4vw, 1.75rem);
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
text-decoration: none;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.support-mail-link:hover {
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
|
||||
.support-contact-card p {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-sm);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.support-quick-grid,
|
||||
.support-info-grid,
|
||||
.support-faq-grid {
|
||||
display: grid;
|
||||
gap: var(--gap-sm);
|
||||
.support-contact-card .atmos-btn {
|
||||
margin-top: var(--gap-xs);
|
||||
}
|
||||
|
||||
.support-quick-grid {
|
||||
/* ----- Topic cards ------------------------------------------------------- */
|
||||
|
||||
.support-topics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
margin-top: var(--section-y-sm);
|
||||
}
|
||||
|
||||
.support-section,
|
||||
.support-faq-section {
|
||||
padding-top: var(--section-y-sm);
|
||||
}
|
||||
|
||||
.support-section--split,
|
||||
.support-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(16rem, 0.72fr) minmax(0, 1.28fr);
|
||||
gap: var(--gap-lg);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.support-info-grid {
|
||||
margin-top: var(--section-y-sm);
|
||||
}
|
||||
|
||||
.support-section-heading h2,
|
||||
.support-bottom-copy h2 {
|
||||
margin: 0.75rem 0 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2.15rem, 5.2vw, 6rem);
|
||||
line-height: 0.94;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.support-section-copy {
|
||||
.support-topic,
|
||||
.support-faq-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap-sm);
|
||||
}
|
||||
|
||||
.support-section-copy p,
|
||||
.support-bottom-copy p,
|
||||
.support-quick-card p,
|
||||
.support-faq-card p,
|
||||
.support-info-box p,
|
||||
.support-list li {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.support-quick-card,
|
||||
.support-faq-card,
|
||||
.support-info-box {
|
||||
min-height: 100%;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.8rem);
|
||||
gap: var(--gap-xs);
|
||||
min-height: 12rem;
|
||||
padding: clamp(1.1rem, 2.4vw, 1.6rem);
|
||||
border: 1px solid var(--theme-border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.008)),
|
||||
@ -155,82 +120,65 @@
|
||||
box-shadow var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.support-quick-card:hover,
|
||||
.support-faq-card:hover,
|
||||
.support-info-box:hover {
|
||||
.support-topic:hover,
|
||||
.support-faq-item:hover {
|
||||
transform: translateY(-4px);
|
||||
border-color: rgba(var(--theme-accent-rgb) / 0.42);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.support-quick-card h3,
|
||||
.support-faq-card h3,
|
||||
.support-info-box h3 {
|
||||
margin: 0.9rem 0 0.75rem;
|
||||
.support-topic h3,
|
||||
.support-faq-item h3 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: var(--text-xl);
|
||||
line-height: 1.08;
|
||||
font-size: var(--text-lg);
|
||||
font-weight: 400;
|
||||
line-height: 1.15;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.support-info-box--dark {
|
||||
border-color: rgba(255, 255, 255, 0.16);
|
||||
background:
|
||||
radial-gradient(circle at 100% 0%, rgba(var(--theme-accent-rgb) / 0.18), transparent 18rem),
|
||||
#171717;
|
||||
.support-topic p,
|
||||
.support-faq-item p {
|
||||
margin: 0;
|
||||
color: var(--theme-text-muted);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.support-info-box--dark .support-label,
|
||||
.support-info-box--dark p {
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
}
|
||||
/* ----- FAQ --------------------------------------------------------------- */
|
||||
|
||||
.support-info-box--dark h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.support-list {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
margin: 1rem 0 0;
|
||||
padding-left: 1.1rem;
|
||||
}
|
||||
|
||||
.support-mail-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
margin-top: 1.15rem;
|
||||
padding: 0 1.1rem;
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--theme-accent-fill);
|
||||
color: var(--theme-accent-contrast);
|
||||
font-size: var(--text-sm);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.support-mail-btn:hover,
|
||||
.support-mail-btn:focus-visible {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.support-faq-section {
|
||||
.support-faq {
|
||||
margin-top: var(--section-y-sm);
|
||||
padding-top: var(--section-y-sm);
|
||||
border-top: 1px solid var(--theme-border);
|
||||
}
|
||||
|
||||
.support-faq-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
margin-top: clamp(1.6rem, 4vw, 3rem);
|
||||
.support-section-head {
|
||||
display: grid;
|
||||
gap: var(--gap-2xs);
|
||||
margin-bottom: clamp(1.6rem, 4vw, 3rem);
|
||||
}
|
||||
|
||||
.support-bottom-cta {
|
||||
.support-section-head h2 {
|
||||
margin: 0;
|
||||
color: var(--theme-text);
|
||||
font-size: clamp(2.2rem, 5.4vw, 6rem);
|
||||
line-height: 0.94;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.support-faq-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--gap-sm);
|
||||
}
|
||||
|
||||
/* ----- CTA --------------------------------------------------------------- */
|
||||
|
||||
.support-cta {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: var(--gap-lg);
|
||||
@ -239,72 +187,35 @@
|
||||
padding: clamp(1.5rem, 4vw, 3.5rem);
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(circle at 92% 0%, rgba(255, 255, 255, 0.22), transparent 20rem),
|
||||
var(--theme-accent-fill);
|
||||
radial-gradient(circle at 86% 12%, rgba(255, 255, 255, 0.24), transparent 18rem),
|
||||
linear-gradient(135deg, var(--theme-accent-fill), var(--theme-accent-fill-strong));
|
||||
}
|
||||
|
||||
.support-bottom-copy .support-label,
|
||||
.support-bottom-copy h2,
|
||||
.support-bottom-copy p {
|
||||
.support-cta .support-eyebrow,
|
||||
.support-cta h2 {
|
||||
color: var(--theme-accent-contrast);
|
||||
}
|
||||
|
||||
.support-bottom-copy p {
|
||||
max-width: 48rem;
|
||||
margin-top: 1rem;
|
||||
.support-cta-copy h2 {
|
||||
max-width: 22ch;
|
||||
margin: 0;
|
||||
font-size: clamp(2rem, 5vw, 5rem);
|
||||
line-height: 0.96;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.support-bottom-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--gap-xs);
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.support-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 48px;
|
||||
padding: 0 1.1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius-lg);
|
||||
color: inherit;
|
||||
font-size: var(--text-sm);
|
||||
text-decoration: none;
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out),
|
||||
background-color var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
.support-btn:hover,
|
||||
.support-btn:focus-visible {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--theme-shadow-soft);
|
||||
}
|
||||
|
||||
.support-btn--primary {
|
||||
background: #fff;
|
||||
color: var(--theme-accent-fill-strong);
|
||||
}
|
||||
|
||||
.support-btn--secondary {
|
||||
border-color: rgba(255, 255, 255, 0.22);
|
||||
background: rgba(255, 255, 255, 0.14);
|
||||
color: #fff;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
/* ----- Responsive -------------------------------------------------------- */
|
||||
|
||||
@media (max-width: 1180px) {
|
||||
.support-hero,
|
||||
.support-section--split,
|
||||
.support-info-grid,
|
||||
.support-bottom-cta {
|
||||
.support-cta {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.support-quick-grid,
|
||||
.support-topics,
|
||||
.support-faq-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
@ -312,24 +223,15 @@
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.support-hero {
|
||||
padding-top: clamp(1.4rem, 5vw, 2rem);
|
||||
padding-top: clamp(5.5rem, 18vw, 7rem);
|
||||
}
|
||||
|
||||
.support-hero-copy h1 {
|
||||
font-size: clamp(2.55rem, 13vw, 4.4rem);
|
||||
}
|
||||
|
||||
.support-quick-grid,
|
||||
.support-topics,
|
||||
.support-faq-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.support-bottom-actions {
|
||||
display: grid;
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
.support-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,6 +3,43 @@ import SharedNavbar from "../components/SharedNavbar";
|
||||
import PageMeta from "../components/seo/PageMeta";
|
||||
import "./SupportPage.css";
|
||||
|
||||
const TOPICS = [
|
||||
{
|
||||
label: "Bestellung",
|
||||
title: "Status, Anpassung, Ablauf",
|
||||
text: "Fragen zu einer laufenden Bestellung beantworten wir schnell und direkt.",
|
||||
},
|
||||
{
|
||||
label: "Versand",
|
||||
title: "Lieferung & Zustellung",
|
||||
text: "Versanddauer, Zustellung, Bestätigung oder mögliche Verzögerungen.",
|
||||
},
|
||||
{
|
||||
label: "Beratung",
|
||||
title: "Duft, Sample, Discovery",
|
||||
text: "Unterstützung bei der Auswahl oder beim Einordnen eines Duftes.",
|
||||
},
|
||||
];
|
||||
|
||||
const FAQ = [
|
||||
{
|
||||
q: "Wie lange dauert der Versand?",
|
||||
a: "Bestellungen werden in der Regel innerhalb von 1–2 Werktagen bearbeitet und zugestellt.",
|
||||
},
|
||||
{
|
||||
q: "Kann ich zuerst testen?",
|
||||
a: "Ja — über das Discovery Set oder ein einzelnes Sample. So erlebst du den Duft auf der Haut.",
|
||||
},
|
||||
{
|
||||
q: "Welcher Duft passt zu mir?",
|
||||
a: "Schreib uns kurz, welche Materialien oder Stimmungen dich ansprechen. Wir helfen bei der Einordnung.",
|
||||
},
|
||||
{
|
||||
q: "Problem mit der Bestellung?",
|
||||
a: "Schick uns die Bestellnummer und eine kurze Beschreibung. Wir prüfen den Fall und melden uns zeitnah.",
|
||||
},
|
||||
];
|
||||
|
||||
function SupportPage() {
|
||||
return (
|
||||
<div className="support-page">
|
||||
@ -16,192 +53,79 @@ function SupportPage() {
|
||||
<main id="main-content" className="shell">
|
||||
<section className="support-hero" data-reveal-group>
|
||||
<div className="support-hero-copy">
|
||||
<span className="support-kicker" data-reveal="fade">
|
||||
SUPPORT
|
||||
<span className="support-eyebrow" data-reveal="fade">
|
||||
Support
|
||||
</span>
|
||||
<h1 data-reveal="lines">
|
||||
WIR HELFEN
|
||||
<br />
|
||||
KLAR, DIREKT
|
||||
<br />
|
||||
UND OHNE
|
||||
<br />
|
||||
UMWEGE
|
||||
UND PERSÖNLICH.
|
||||
</h1>
|
||||
<p className="support-intro" data-reveal="fade">
|
||||
Wenn du Fragen zu Bestellung, Versand, Discovery Set, Produkten oder
|
||||
deiner Auswahl hast, ist das Support-Team von atmos für dich da.
|
||||
Präzise, persönlich und mit dem Anspruch, jedes Anliegen sorgfältig
|
||||
zu bearbeiten.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="support-hero-panel" data-reveal="fade">
|
||||
<span className="support-panel-label">KONTAKT</span>
|
||||
<p>
|
||||
Für Anliegen rund um Bestellung, Produkte, Versand und allgemeine
|
||||
Fragen erreichst du uns direkt per E-Mail.
|
||||
</p>
|
||||
|
||||
<div className="support-panel-meta">
|
||||
<div>
|
||||
<span>E-MAIL</span>
|
||||
<p>support@atmos.ch</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>ANTWORTZEIT</span>
|
||||
<p>In der Regel innerhalb von 1–2 Werktagen</p>
|
||||
</div>
|
||||
<div>
|
||||
<span>SERVICE</span>
|
||||
<p>Persönlich, präzise und sorgfältig</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="support-quick-grid" data-reveal-group data-reveal-start="top 90%">
|
||||
<article className="support-quick-card" data-reveal="fade">
|
||||
<span className="support-label">BESTELLUNG</span>
|
||||
<h3>Fragen zu einer laufenden Bestellung</h3>
|
||||
<p>
|
||||
Bei Fragen zu Bestellstatus, Anpassungen oder Unklarheiten zum Ablauf
|
||||
hilft dir unser Support schnell und direkt weiter.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="support-quick-card" data-reveal="fade">
|
||||
<span className="support-label">VERSAND</span>
|
||||
<h3>Lieferung und Zustellung</h3>
|
||||
<p>
|
||||
Wir unterstützen bei Fragen zu Versanddauer, Zustellung,
|
||||
Lieferbestätigung oder allfälligen Verzögerungen.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="support-quick-card" data-reveal="fade">
|
||||
<span className="support-label">PRODUKTE</span>
|
||||
<h3>Beratung zu Duft, Sample oder Discovery Set</h3>
|
||||
<p>
|
||||
Wenn du Unterstützung bei der Auswahl brauchst oder einen Duft besser
|
||||
einordnen möchtest, helfen wir dir gerne weiter.
|
||||
</p>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section className="support-section support-section--split" data-reveal-group>
|
||||
<div className="support-section-heading">
|
||||
<span className="support-label" data-reveal="fade">
|
||||
SO ERREICHST DU UNS
|
||||
</span>
|
||||
<h2 data-reveal="lines">EIN GUTER SUPPORT BEGINNT MIT EINER KLAREN ANFRAGE.</h2>
|
||||
</div>
|
||||
|
||||
<div className="support-section-copy" data-reveal="fade">
|
||||
<p>
|
||||
Damit wir dein Anliegen möglichst schnell bearbeiten können, hilft es,
|
||||
wenn du uns in deiner Nachricht die wichtigsten Informationen direkt
|
||||
mitgibst. Dazu gehören je nach Fall deine Bestellnummer, der betroffene
|
||||
Duft oder Artikel sowie eine kurze Beschreibung deines Anliegens.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Bei Fragen zur Auswahl genügt oft schon ein Hinweis darauf, welche
|
||||
Düfte dich bisher angesprochen haben oder welche Richtung du suchst.
|
||||
So können wir gezielter und hilfreicher antworten.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="support-info-grid" data-reveal-group>
|
||||
<div className="support-info-box" data-reveal="fade">
|
||||
<span className="support-label">AM BESTEN MITGEBEN</span>
|
||||
<ul className="support-list">
|
||||
<li>Bestellnummer, falls bereits bestellt wurde</li>
|
||||
<li>Produkt- oder Duftname</li>
|
||||
<li>Kurze Beschreibung des Anliegens</li>
|
||||
<li>Bei Bedarf Fotos oder relevante Details</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="support-info-box support-info-box--dark" data-reveal="fade">
|
||||
<span className="support-label">KONTAKT</span>
|
||||
<h3>support@atmos.ch</h3>
|
||||
<p>
|
||||
Unser Support beantwortet Anfragen in der Regel innerhalb von 1–2
|
||||
<p className="support-lead" data-reveal="fade">
|
||||
Fragen zu Bestellung, Versand, Discovery Set oder einem Duft?
|
||||
Unser Team antwortet sorgfältig — meist innerhalb von 1–2
|
||||
Werktagen.
|
||||
</p>
|
||||
<a href="mailto:support@atmos.ch" className="support-mail-btn">
|
||||
Support kontaktieren
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<aside className="support-contact-card" data-reveal="fade">
|
||||
<span className="support-eyebrow">Kontakt</span>
|
||||
<a className="support-mail-link" href="mailto:support@atmos.ch">
|
||||
support@atmos.ch
|
||||
</a>
|
||||
<p>Antwortzeit 1–2 Werktage · persönlich, präzise.</p>
|
||||
<a
|
||||
href="mailto:support@atmos.ch"
|
||||
className="atmos-btn atmos-btn--primary atmos-btn--block"
|
||||
>
|
||||
E-Mail schreiben
|
||||
</a>
|
||||
</aside>
|
||||
</section>
|
||||
|
||||
<section className="support-faq-section" data-reveal-group>
|
||||
<div className="support-section-heading">
|
||||
<span className="support-label" data-reveal="fade">
|
||||
HÄUFIGE FRAGEN
|
||||
<section className="support-topics" data-reveal-group data-reveal-start="top 88%">
|
||||
{TOPICS.map((topic) => (
|
||||
<article className="support-topic" key={topic.label} data-reveal="fade">
|
||||
<span className="support-eyebrow">{topic.label}</span>
|
||||
<h3>{topic.title}</h3>
|
||||
<p>{topic.text}</p>
|
||||
</article>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<section className="support-faq" data-reveal-group>
|
||||
<header className="support-section-head">
|
||||
<span className="support-eyebrow" data-reveal="fade">
|
||||
Häufige Fragen
|
||||
</span>
|
||||
<h2 data-reveal="lines">DIE WICHTIGSTEN THEMEN AUF EINEN BLICK.</h2>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="support-faq-grid">
|
||||
<article className="support-faq-card" data-reveal="fade">
|
||||
<h3>Wie lange dauert der Versand?</h3>
|
||||
<p>
|
||||
Bestellungen werden in der Regel innerhalb von 1–2 Werktagen
|
||||
bearbeitet. Die Zustellung erfolgt üblicherweise wenige Werktage
|
||||
danach.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="support-faq-card" data-reveal="fade">
|
||||
<h3>Kann ich zuerst testen?</h3>
|
||||
<p>
|
||||
Ja. Dafür ist das Discovery Set oder ein einzelnes Sample gedacht.
|
||||
So kannst du einen Duft erst auf der Haut erleben, bevor du dich
|
||||
für eine Full Size entscheidest.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="support-faq-card" data-reveal="fade">
|
||||
<h3>Ich bin unsicher, welcher Duft zu mir passt.</h3>
|
||||
<p>
|
||||
Schreib uns kurz, welche Duftcharaktere, Materialien oder Stimmungen
|
||||
dich ansprechen. Wir helfen dir gerne bei der Einordnung.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="support-faq-card" data-reveal="fade">
|
||||
<h3>Was tun bei einem Problem mit der Bestellung?</h3>
|
||||
<p>
|
||||
Kontaktiere uns direkt mit deiner Bestellnummer und einer kurzen
|
||||
Beschreibung des Anliegens. Wir prüfen den Fall sorgfältig und
|
||||
melden uns so schnell wie möglich zurück.
|
||||
</p>
|
||||
{FAQ.map((item) => (
|
||||
<article className="support-faq-item" key={item.q} data-reveal="fade">
|
||||
<h3>{item.q}</h3>
|
||||
<p>{item.a}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="support-bottom-cta" data-reveal-group>
|
||||
<div className="support-bottom-copy">
|
||||
<span className="support-label" data-reveal="fade">
|
||||
atmos SUPPORT
|
||||
<section className="support-cta" data-reveal-group data-on-accent>
|
||||
<div className="support-cta-copy">
|
||||
<span className="support-eyebrow" data-reveal="fade">
|
||||
atmos Support
|
||||
</span>
|
||||
<h2 data-reveal="lines">
|
||||
NICHT AUTOMATISIERT AUF DISTANZ. SONDERN PERSÖNLICH UND PRÄZISE.
|
||||
PERSÖNLICH STATT AUTOMATISIERT.
|
||||
</h2>
|
||||
<p data-reveal="fade">
|
||||
Wir möchten, dass sich auch der Service so anfühlt wie die Marke
|
||||
selbst: klar, hochwertig und sorgfältig.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="support-bottom-actions" data-reveal="fade">
|
||||
<a href="mailto:support@atmos.ch" className="support-btn support-btn--primary">
|
||||
<div className="atmos-btn-row atmos-btn-row--responsive" data-reveal="fade">
|
||||
<a href="mailto:support@atmos.ch" className="atmos-btn atmos-btn--primary">
|
||||
E-Mail senden
|
||||
</a>
|
||||
<Link to="/" className="support-btn support-btn--secondary">
|
||||
<Link to="/" className="atmos-btn atmos-btn--secondary">
|
||||
Zur Startseite
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
316
parfum-shop/src/style/buttons.css
Normal file
@ -0,0 +1,316 @@
|
||||
/**
|
||||
* Global Button System (atmos-btn)
|
||||
* ----------------------------------------------------------------------------
|
||||
* Single source of truth for every button & button-styled link in the app.
|
||||
* Mirrors the visual language used by Landing Hero and Product Detail
|
||||
* (hard edges, surface lift, accent stripe on hover).
|
||||
*
|
||||
* Usage:
|
||||
* <button class="atmos-btn atmos-btn--primary">…</button>
|
||||
* <a class="atmos-btn atmos-btn--secondary">…</a>
|
||||
*
|
||||
* Variants:
|
||||
* --primary accent fill, contrast text (key CTA, works on any bg)
|
||||
* --invert paper fill, accent-strong (CTA inside accent banners)
|
||||
* --secondary surface w/ blur, themed text (secondary CTA on dark/photo)
|
||||
* --outline transparent + strong border (utility CTA, theme-aware)
|
||||
* --ghost transparent, subtle hover (tertiary, link-style)
|
||||
* --solid neutral text-color fill (form submit / drawer primary)
|
||||
* --danger destructive, theme-aware (remove / cancel actions)
|
||||
*
|
||||
* Sizes:
|
||||
* default 48px min-height
|
||||
* --sm 40px min-height
|
||||
* --lg 56px min-height
|
||||
*
|
||||
* Modifiers:
|
||||
* --block width: 100%
|
||||
* --icon compact square (no text)
|
||||
*
|
||||
* GSAP-driven micro-interactions are bound globally by
|
||||
* useButtonInteractions() (see src/hooks/useButtonInteractions.js).
|
||||
* The CSS here keeps a graceful no-JS fallback (transitions only).
|
||||
*/
|
||||
|
||||
.atmos-btn {
|
||||
--btn-bg: transparent;
|
||||
--btn-bg-hover: transparent;
|
||||
--btn-fg: var(--theme-text);
|
||||
--btn-fg-hover: var(--theme-text);
|
||||
--btn-border: transparent;
|
||||
--btn-border-hover: transparent;
|
||||
--btn-stripe: var(--theme-accent);
|
||||
--btn-shadow-hover: var(--theme-shadow-soft);
|
||||
--btn-min-height: 48px;
|
||||
--btn-px: clamp(1rem, 2vw, 1.35rem);
|
||||
--btn-font: var(--text-sm);
|
||||
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.55rem;
|
||||
min-height: var(--btn-min-height);
|
||||
padding: 0 var(--btn-px);
|
||||
border: 1px solid var(--btn-border);
|
||||
border-radius: var(--radius-lg);
|
||||
background: var(--btn-bg);
|
||||
color: var(--btn-fg);
|
||||
font: inherit;
|
||||
font-size: var(--btn-font);
|
||||
line-height: 1;
|
||||
letter-spacing: 0.04em;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
transition:
|
||||
transform var(--duration-med) var(--ease-out),
|
||||
background-color var(--duration-med) var(--ease-out),
|
||||
border-color var(--duration-med) var(--ease-out),
|
||||
color var(--duration-med) var(--ease-out),
|
||||
box-shadow var(--duration-med) var(--ease-out),
|
||||
opacity var(--duration-med) var(--ease-out);
|
||||
}
|
||||
|
||||
/* Top accent stripe — same idiom as .size-card on the product page. */
|
||||
.atmos-btn::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: var(--btn-stripe);
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
transition: transform var(--duration-med) var(--ease-out);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.atmos-btn > * {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.atmos-btn:hover,
|
||||
.atmos-btn:focus-visible {
|
||||
background: var(--btn-bg-hover);
|
||||
border-color: var(--btn-border-hover);
|
||||
color: var(--btn-fg-hover);
|
||||
box-shadow: var(--btn-shadow-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.atmos-btn:hover::before,
|
||||
.atmos-btn:focus-visible::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.atmos-btn:active {
|
||||
transform: translateY(0) scale(0.985);
|
||||
transition-duration: var(--duration-fast);
|
||||
}
|
||||
|
||||
.atmos-btn:focus-visible {
|
||||
outline: 2px solid var(--theme-focus-ring);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.atmos-btn:disabled,
|
||||
.atmos-btn[aria-disabled="true"] {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.atmos-btn:disabled::before,
|
||||
.atmos-btn[aria-disabled="true"]::before {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
/* ----- Variants ---------------------------------------------------------- */
|
||||
|
||||
.atmos-btn--primary {
|
||||
--btn-bg: var(--theme-accent-fill);
|
||||
--btn-bg-hover: var(--theme-accent-fill-strong);
|
||||
--btn-fg: var(--theme-accent-contrast);
|
||||
--btn-fg-hover: var(--theme-accent-contrast);
|
||||
--btn-border: var(--theme-accent-fill);
|
||||
--btn-border-hover: var(--theme-accent-fill-strong);
|
||||
--btn-stripe: rgba(255, 255, 255, 0.85);
|
||||
}
|
||||
|
||||
.atmos-btn--invert {
|
||||
--btn-bg: #fff;
|
||||
--btn-bg-hover: #fff;
|
||||
--btn-fg: var(--theme-accent-fill-strong);
|
||||
--btn-fg-hover: var(--theme-accent-fill-strong);
|
||||
--btn-border: #fff;
|
||||
--btn-border-hover: #fff;
|
||||
--btn-stripe: var(--theme-accent-fill-strong);
|
||||
--btn-shadow-hover: 0 16px 36px rgba(0, 0, 0, 0.22);
|
||||
}
|
||||
|
||||
.atmos-btn--secondary {
|
||||
--btn-bg: color-mix(in srgb, var(--theme-surface) 72%, transparent);
|
||||
--btn-bg-hover: color-mix(in srgb, var(--theme-surface) 86%, transparent);
|
||||
--btn-fg: var(--theme-text);
|
||||
--btn-fg-hover: var(--theme-text);
|
||||
--btn-border: var(--theme-border-strong);
|
||||
--btn-border-hover: rgba(var(--theme-accent-rgb) / 0.55);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.atmos-btn--outline {
|
||||
--btn-bg: transparent;
|
||||
--btn-bg-hover: rgba(var(--theme-accent-rgb) / 0.06);
|
||||
--btn-fg: var(--theme-text);
|
||||
--btn-fg-hover: var(--theme-text);
|
||||
--btn-border: var(--theme-border);
|
||||
--btn-border-hover: var(--theme-accent);
|
||||
}
|
||||
|
||||
.atmos-btn--ghost {
|
||||
--btn-bg: transparent;
|
||||
--btn-bg-hover: rgba(var(--theme-accent-rgb) / 0.08);
|
||||
--btn-fg: var(--theme-text);
|
||||
--btn-fg-hover: var(--theme-text);
|
||||
--btn-border: transparent;
|
||||
--btn-border-hover: transparent;
|
||||
--btn-shadow-hover: none;
|
||||
}
|
||||
|
||||
.atmos-btn--solid {
|
||||
--btn-bg: var(--theme-text);
|
||||
--btn-bg-hover: var(--theme-text);
|
||||
--btn-fg: var(--theme-bg);
|
||||
--btn-fg-hover: var(--theme-bg);
|
||||
--btn-border: var(--theme-text);
|
||||
--btn-border-hover: var(--theme-text);
|
||||
--btn-stripe: var(--theme-accent);
|
||||
}
|
||||
|
||||
.atmos-btn--danger {
|
||||
--btn-bg: transparent;
|
||||
--btn-bg-hover: rgba(var(--theme-accent-rgb) / 0.1);
|
||||
--btn-fg: var(--theme-text);
|
||||
--btn-fg-hover: var(--theme-text);
|
||||
--btn-border: var(--theme-border);
|
||||
--btn-border-hover: var(--theme-accent);
|
||||
--btn-stripe: var(--theme-accent);
|
||||
--btn-shadow-hover: none;
|
||||
}
|
||||
|
||||
/* On any accent-filled banner, primary/secondary need different defaults so
|
||||
they remain readable. Apply by adding `data-on-accent` to a wrapper. */
|
||||
[data-on-accent] .atmos-btn--primary,
|
||||
.atmos-btn--primary[data-on-accent] {
|
||||
--btn-bg: #fff;
|
||||
--btn-bg-hover: #fff;
|
||||
--btn-fg: var(--theme-accent-fill-strong);
|
||||
--btn-fg-hover: var(--theme-accent-fill-strong);
|
||||
--btn-border: #fff;
|
||||
--btn-border-hover: #fff;
|
||||
--btn-stripe: var(--theme-accent-fill-strong);
|
||||
}
|
||||
|
||||
[data-on-accent] .atmos-btn--secondary,
|
||||
.atmos-btn--secondary[data-on-accent] {
|
||||
--btn-bg: rgba(255, 255, 255, 0.14);
|
||||
--btn-bg-hover: rgba(255, 255, 255, 0.22);
|
||||
--btn-fg: #fff;
|
||||
--btn-fg-hover: #fff;
|
||||
--btn-border: rgba(255, 255, 255, 0.32);
|
||||
--btn-border-hover: #fff;
|
||||
--btn-stripe: #fff;
|
||||
}
|
||||
|
||||
[data-on-accent] .atmos-btn--ghost,
|
||||
.atmos-btn--ghost[data-on-accent] {
|
||||
--btn-fg: rgba(255, 255, 255, 0.86);
|
||||
--btn-fg-hover: #fff;
|
||||
--btn-bg-hover: rgba(255, 255, 255, 0.12);
|
||||
}
|
||||
|
||||
/* ----- Sizes ------------------------------------------------------------- */
|
||||
|
||||
.atmos-btn--sm {
|
||||
--btn-min-height: 40px;
|
||||
--btn-px: clamp(0.7rem, 1.4vw, 0.95rem);
|
||||
--btn-font: var(--text-xs);
|
||||
}
|
||||
|
||||
.atmos-btn--lg {
|
||||
--btn-min-height: 56px;
|
||||
--btn-px: clamp(1.2rem, 2.6vw, 1.7rem);
|
||||
--btn-font: var(--text-base);
|
||||
}
|
||||
|
||||
/* ----- Modifiers --------------------------------------------------------- */
|
||||
|
||||
.atmos-btn--block {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.atmos-btn--icon {
|
||||
--btn-px: 0;
|
||||
width: var(--btn-min-height);
|
||||
min-width: var(--btn-min-height);
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.atmos-btn--uppercase {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
/* Group helper — consistent spacing wherever buttons cluster. */
|
||||
.atmos-btn-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--gap-xs);
|
||||
}
|
||||
|
||||
.atmos-btn-row--end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.atmos-btn-row--stretch {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-auto-columns: 1fr;
|
||||
gap: var(--gap-xs);
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.atmos-btn-row--responsive {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.atmos-btn-row--responsive > .atmos-btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.atmos-btn,
|
||||
.atmos-btn::before {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.atmos-btn:hover,
|
||||
.atmos-btn:focus-visible {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||