Pages Hard
Art Gallery — Atelier Blanc
White museum-aesthetic art gallery with Cormorant Garamond serif and DM Mono. Full clip-path lightbox expand for artwork detail view, masonry grid with hover reveals, timeline history section, and keyboard navigation.
Open in Lab
MCP
gsap scrolltrigger lenis clip-path lightbox cormorant-garamond
Targets: JS HTML
Code
/* ── Demo 53: Art Gallery — Contemporary White Museum ── */
:root {
--white: #ffffff;
--off-white: #f8f7f5;
--light: #f0eeea;
--border: #e0ddd8;
--text: #1a1714;
--muted: #8a8580;
--taupe: #c8c4be;
--gold: #b8960c;
--gold-light: #f0d060;
}
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: "Cormorant Garamond", Georgia, serif;
background: var(--white);
color: var(--text);
-webkit-font-smoothing: antialiased;
line-height: 1.6;
overflow-x: hidden;
}
.section-label {
display: block;
font-family: "DM Mono", monospace;
font-size: 0.62rem;
font-weight: 400;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 1rem;
}
.btn-dark {
display: inline-block;
padding: 0.85rem 2rem;
background: var(--text);
color: var(--white);
font-family: "DM Mono", monospace;
font-size: 0.72rem;
letter-spacing: 0.1em;
text-transform: uppercase;
text-decoration: none;
border-radius: 2px;
transition: background 0.2s, transform 0.2s;
}
.btn-dark:hover {
background: var(--gold);
transform: translateY(-2px);
}
/* Nav */
.nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
display: flex;
align-items: center;
justify-content: space-between;
padding: 1.25rem 3rem;
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
}
.nav-logo {
font-size: 1rem;
font-weight: 300;
font-style: italic;
color: var(--text);
text-decoration: none;
letter-spacing: 0.05em;
}
.nav-links {
display: flex;
gap: 2.5rem;
list-style: none;
}
.nav-links a {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--muted);
text-decoration: none;
transition: color 0.2s;
}
.nav-links a:hover {
color: var(--text);
}
.nav-tickets {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
letter-spacing: 0.1em;
color: var(--gold);
text-decoration: none;
border-bottom: 1px solid rgba(184, 150, 12, 0.4);
padding-bottom: 1px;
}
/* Hero */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
padding: 7rem 3rem 5rem;
background: var(--off-white);
}
.hero-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
max-width: 1200px;
margin: 0 auto;
width: 100%;
}
.hero-season {
font-family: "DM Mono", monospace;
font-size: 0.65rem;
letter-spacing: 0.15em;
text-transform: uppercase;
color: var(--muted);
display: block;
margin-bottom: 2rem;
}
.hero-h1 {
font-size: clamp(3rem, 6vw, 5.5rem);
font-weight: 300;
line-height: 1.15;
margin-bottom: 1.5rem;
}
.hero-h1 em {
font-style: italic;
color: var(--gold);
}
.hero-text p {
font-size: 1rem;
color: var(--muted);
line-height: 1.85;
max-width: 380px;
margin-bottom: 2.5rem;
}
.hero-artwork {
position: relative;
}
.ha-frame {
position: absolute;
border-radius: 2px;
}
.ha-frame--main {
top: 0;
left: 0;
right: 15%;
bottom: 20%;
background: linear-gradient(145deg, #c8c0b4 0%, #a8a094 40%, #888078 100%);
min-height: 400px;
}
.ha-frame--accent {
bottom: 0;
right: 0;
width: 40%;
height: 50%;
background: linear-gradient(135deg, #e0d8cc 0%, #c8c0b4 100%);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.1);
}
.ha-label {
position: absolute;
bottom: 60%;
left: 0;
right: 15%;
padding: 0.75rem 1rem;
background: rgba(255, 255, 255, 0.9);
display: flex;
flex-direction: column;
gap: 0.2rem;
}
.ha-label span:first-child {
font-size: 0.8rem;
font-weight: 600;
}
.ha-label span:last-child {
font-family: "DM Mono", monospace;
font-size: 0.62rem;
color: var(--muted);
letter-spacing: 0.05em;
}
.hero-artwork {
min-height: 500px;
}
/* Works */
.works-section {
padding: 5rem 3rem;
background: var(--white);
border-top: 1px solid var(--border);
}
.works-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.works-count {
font-family: "DM Mono", monospace;
font-size: 0.72rem;
color: var(--muted);
}
.works-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--border);
border: 1px solid var(--border);
}
.work-item {
background: var(--white);
overflow: hidden;
cursor: pointer;
position: relative;
}
.work-item--tall {
grid-row: span 2;
}
.work-item--wide {
grid-column: span 2;
}
.wi-art {
min-height: 240px;
transition: transform 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.work-item--tall .wi-art {
min-height: 500px;
}
.work-item--wide .wi-art {
min-height: 240px;
}
.work-item:hover .wi-art {
transform: scale(1.04);
}
.wi-art--1 {
background: linear-gradient(145deg, #d8d0c8, #b0a89c, #888078);
}
.wi-art--2 {
background: linear-gradient(160deg, #c8c8c0, #a0a098, #787880);
}
.wi-art--3 {
background: radial-gradient(ellipse at 40% 40%, #e0d0c0 0%, #c0b0a0 40%, #a09080 100%);
}
.wi-art--4 {
background: linear-gradient(135deg, #c0c8d0, #a0a8b0, #808890);
}
.wi-art--5 {
background: radial-gradient(ellipse at 60% 60%, #e0e0d8, #b8b8b0, #909088);
}
.wi-art--6 {
background: linear-gradient(170deg, #d8c8c0, #b8a8a0, #988880);
}
.wi-art--7 {
background: linear-gradient(145deg, #c8d0d8, #a0a8b0, #808890, #606870);
}
.wi-art--8 {
background: linear-gradient(135deg, #d0d0c8, #b0b0a8, #909088);
}
.wi-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 1rem 1.25rem;
background: linear-gradient(transparent, rgba(255, 255, 255, 0.95));
display: flex;
align-items: flex-end;
gap: 0.75rem;
opacity: 0;
transform: translateY(4px);
transition: opacity 0.35s, transform 0.35s;
}
.work-item:hover .wi-caption,
.work-item:focus .wi-caption {
opacity: 1;
transform: translateY(0);
}
.wi-num {
font-family: "DM Mono", monospace;
font-size: 0.6rem;
color: var(--gold);
flex-shrink: 0;
}
.wi-caption strong {
font-size: 0.88rem;
font-weight: 600;
display: block;
}
.wi-caption em {
font-size: 0.72rem;
font-family: "DM Mono", monospace;
color: var(--muted);
font-style: normal;
display: block;
letter-spacing: 0.04em;
}
/* Artists */
.artists-section {
padding: 5rem 3rem;
border-top: 1px solid var(--border);
}
.artists-list {
display: flex;
flex-direction: column;
border-top: 1px solid var(--border);
margin-top: 1.5rem;
}
.artist-row {
display: grid;
grid-template-columns: 40px 1fr 160px 160px 100px;
align-items: center;
gap: 1.5rem;
padding: 1.5rem 0;
border-bottom: 1px solid var(--border);
transition: background 0.2s;
}
.artist-row:hover {
background: var(--off-white);
padding-left: 0.5rem;
}
.ar-num {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
color: var(--taupe);
}
.ar-name {
font-size: 1.25rem;
font-weight: 300;
font-style: italic;
}
.ar-origin,
.ar-medium {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
color: var(--muted);
letter-spacing: 0.05em;
}
.ar-link {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
color: var(--gold);
text-decoration: none;
text-align: right;
transition: letter-spacing 0.2s;
}
.ar-link:hover {
letter-spacing: 0.08em;
}
/* Visit */
.visit-section {
padding: 5rem 3rem;
background: var(--off-white);
border-top: 1px solid var(--border);
}
.visit-inner {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
max-width: 1100px;
margin: 0 auto;
}
.visit-left h2 {
font-size: clamp(2.5rem, 5vw, 4rem);
font-weight: 300;
line-height: 1.2;
margin-bottom: 2rem;
}
.visit-left h2 em {
font-style: italic;
color: var(--gold);
}
.visit-details {
display: flex;
flex-direction: column;
margin-bottom: 2.5rem;
border-top: 1px solid var(--border);
}
.vd-item {
display: flex;
justify-content: space-between;
padding: 0.9rem 0;
border-bottom: 1px solid var(--border);
font-size: 0.88rem;
}
.vd-item span:first-child {
font-family: "DM Mono", monospace;
font-size: 0.68rem;
color: var(--muted);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.visit-map {
position: relative;
height: 350px;
background: var(--light);
border: 1px solid var(--border);
border-radius: 2px;
overflow: hidden;
}
.vm-inner {
width: 100%;
height: 100%;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 40px,
var(--border) 40px,
var(--border) 41px
),
repeating-linear-gradient(
90deg,
transparent,
transparent 40px,
var(--border) 40px,
var(--border) 41px
);
}
.vm-pin {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.5rem;
color: var(--gold);
}
/* Lightbox */
.lightbox {
position: fixed;
inset: 0;
z-index: 500;
display: grid;
grid-template-columns: 1fr 360px;
background: var(--text);
}
.lightbox[hidden] {
display: none;
}
.lb-artwork {
height: 100%;
}
.wi-art--1.lb-art {
background: linear-gradient(145deg, #d8d0c8, #b0a89c, #888078);
}
.lb-panel {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 2.5rem;
border-left: 1px solid rgba(255, 255, 255, 0.1);
overflow: auto;
background: var(--text);
color: var(--white);
}
.lb-close {
align-self: flex-end;
background: none;
border: none;
color: rgba(255, 255, 255, 0.5);
font-size: 1rem;
cursor: pointer;
font-family: "DM Mono", monospace;
font-size: 0.72rem;
letter-spacing: 0.1em;
padding: 0.5rem;
transition: color 0.2s;
}
.lb-close:hover {
color: white;
}
.lb-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.lb-num {
font-family: "DM Mono", monospace;
font-size: 0.6rem;
letter-spacing: 0.15em;
color: var(--gold);
margin-bottom: 1rem;
display: block;
}
.lb-title {
font-size: 2.2rem;
font-weight: 300;
font-style: italic;
line-height: 1.2;
margin-bottom: 0.5rem;
}
.lb-artist {
font-size: 0.85rem;
color: rgba(255, 255, 255, 0.55);
margin-bottom: 0.3rem;
}
.lb-medium {
font-family: "DM Mono", monospace;
font-size: 0.65rem;
color: rgba(255, 255, 255, 0.3);
letter-spacing: 0.08em;
margin-bottom: 1.5rem;
}
.lb-desc {
font-size: 0.92rem;
color: rgba(255, 255, 255, 0.6);
line-height: 1.85;
}
.lb-nav {
display: flex;
justify-content: space-between;
gap: 0.5rem;
}
.lb-nav button {
flex: 1;
padding: 0.75rem;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.6);
font-family: "DM Mono", monospace;
font-size: 0.68rem;
letter-spacing: 0.08em;
cursor: pointer;
transition: all 0.2s;
}
.lb-nav button:hover {
background: rgba(255, 255, 255, 0.1);
color: white;
}
/* Responsive */
@media (max-width: 1024px) {
.hero-inner {
grid-template-columns: 1fr;
}
.visit-inner {
grid-template-columns: 1fr;
}
.works-grid {
grid-template-columns: 1fr 1fr;
}
.work-item--tall {
grid-row: auto;
}
.lightbox {
grid-template-columns: 1fr;
}
.lb-panel {
max-height: 40vh;
}
}
@media (max-width: 768px) {
.nav {
padding: 1.25rem 1.5rem;
}
.nav-links {
display: none;
}
.works-section,
.artists-section,
.visit-section {
padding: 4rem 1.5rem;
}
.artist-row {
grid-template-columns: 1fr 1fr;
}
.ar-num,
.ar-origin,
.ar-medium {
display: none;
}
}
html.reduced-motion .work-item:hover .wi-art {
transform: none;
}
html.reduced-motion * {
transition-duration: 0.01ms !important;
}if (!window.MotionPreference) {
const __mql = window.matchMedia("(prefers-reduced-motion: reduce)");
const __listeners = new Set();
const MotionPreference = {
prefersReducedMotion() {
return __mql.matches;
},
setOverride(value) {
const reduced = Boolean(value);
document.documentElement.classList.toggle("reduced-motion", reduced);
window.dispatchEvent(new CustomEvent("motion-preference", { detail: { reduced } }));
for (const listener of __listeners) {
try {
listener({ reduced, override: reduced, systemReduced: __mql.matches });
} catch {}
}
},
onChange(listener) {
__listeners.add(listener);
try {
listener({
reduced: __mql.matches,
override: null,
systemReduced: __mql.matches,
});
} catch {}
return () => __listeners.delete(listener);
},
getState() {
return { reduced: __mql.matches, override: null, systemReduced: __mql.matches };
},
};
window.MotionPreference = MotionPreference;
}
function prefersReducedMotion() {
return window.MotionPreference.prefersReducedMotion();
}
function initDemoShell() {
// No-op shim in imported standalone snippets.
}
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import Lenis from "lenis";
gsap.registerPlugin(ScrollTrigger);
initDemoShell({
title: "Atelier Blanc — Art Gallery",
category: "pages",
tech: ["gsap", "scroll-trigger", "lenis", "clip-path", "cormorant"],
});
const reduced = prefersReducedMotion();
if (reduced) document.documentElement.classList.add("reduced-motion");
const lenis = new Lenis({ lerp: 0.08, smoothWheel: true });
lenis.on("scroll", ScrollTrigger.update);
gsap.ticker.add((time) => lenis.raf(time * 1000));
gsap.ticker.lagSmoothing(0);
// Hero entrance
if (!reduced) {
gsap.set([".hero-season", ".hero-h1", ".hero-text p", ".btn-dark"], { opacity: 0, y: 20 });
gsap.set([".ha-frame--main", ".ha-frame--accent"], { opacity: 0, scale: 1.03 });
gsap.set(".ha-label", { opacity: 0 });
gsap
.timeline({ delay: 0.4, defaults: { ease: "expo.out" } })
.to(".hero-season", { opacity: 1, y: 0, duration: 0.7 })
.to(".hero-h1", { opacity: 1, y: 0, duration: 1.2 }, "-=0.4")
.to(".hero-text p", { opacity: 1, y: 0, duration: 0.9 }, "-=0.6")
.to(".btn-dark", { opacity: 1, y: 0, duration: 0.7 }, "-=0.5")
.to(".ha-frame--main", { opacity: 1, scale: 1, duration: 1.4, ease: "power2.out" }, 0.5)
.to(".ha-frame--accent", { opacity: 1, scale: 1, duration: 1.1, ease: "power2.out" }, 0.8)
.to(".ha-label", { opacity: 1, duration: 0.8 }, 1.2);
}
// Works counter update
const worksCount = document.getElementById("works-count");
const workItems = document.querySelectorAll(".work-item");
workItems.forEach((item, i) => {
if (!reduced) {
gsap.set(item, { opacity: 0 });
gsap.to(item, {
opacity: 1,
duration: 0.8,
ease: "power1.out",
delay: (i % 3) * 0.12,
scrollTrigger: {
trigger: ".works-grid",
start: "top 80%",
toggleActions: "play none none none",
},
});
}
});
// Artist rows reveal
if (!reduced) {
document.querySelectorAll(".artist-row").forEach((row, i) => {
gsap.set(row, { opacity: 0, x: -20 });
gsap.to(row, {
opacity: 1,
x: 0,
duration: 0.7,
ease: "expo.out",
delay: i * 0.1,
scrollTrigger: {
trigger: ".artists-list",
start: "top 75%",
toggleActions: "play none none reverse",
},
});
});
}
// Lightbox data
const artworkData = [
{
num: "01",
title: "Luminous Void",
artist: "Elias Vorne",
medium: "Oil on canvas, 200×300cm",
artClass: "wi-art--1",
},
{
num: "02",
title: "Still Point",
artist: "Mara Solis",
medium: "Photography, 80×120cm",
artClass: "wi-art--2",
},
{
num: "03",
title: "Threshold Study",
artist: "Jun Aoki",
medium: "Mixed media, 150×150cm",
artClass: "wi-art--3",
},
{
num: "04",
title: "Erosion Series I–III",
artist: "Petra Novak",
medium: "Sculpture (bronze), variable dimensions",
artClass: "wi-art--4",
},
{
num: "05",
title: "Frequency",
artist: "Yuki Tanaka",
medium: "Digital print, 100×100cm",
artClass: "wi-art--5",
},
{
num: "06",
title: "Residue",
artist: "Camille Dubois",
medium: "Watercolor, 60×80cm",
artClass: "wi-art--6",
},
{
num: "07",
title: "Meridian",
artist: "Elias Vorne",
medium: "Acrylic, 180×280cm",
artClass: "wi-art--7",
},
{
num: "08",
title: "Archive (after Borges)",
artist: "Jun Aoki",
medium: "Installation, site-specific",
artClass: "wi-art--8",
},
];
const lightbox = document.getElementById("lightbox");
const lbArtwork = document.getElementById("lb-artwork");
const lbNum = document.getElementById("lb-num");
const lbTitle = document.getElementById("lb-title");
const lbArtist = document.getElementById("lb-artist");
const lbMedium = document.getElementById("lb-medium");
let currentIdx = -1;
function openLightbox(idx) {
const d = artworkData[idx];
const item = workItems[idx];
const rect = item.getBoundingClientRect();
const vw = window.innerWidth;
const vh = window.innerHeight;
currentIdx = idx;
lbNum.textContent = d.num;
lbTitle.textContent = d.title;
lbArtist.textContent = d.artist;
lbMedium.textContent = d.medium;
lbArtwork.className = "lb-artwork wi-art " + d.artClass;
worksCount.textContent = `${d.num} / 08`;
lightbox.removeAttribute("hidden");
if (!reduced) {
gsap.set(lightbox, {
clipPath: `inset(${rect.top}px ${vw - rect.right}px ${vh - rect.bottom}px ${rect.left}px round 2px)`,
});
gsap.to(lightbox, {
clipPath: "inset(0px 0px 0px 0px round 0px)",
duration: 0.6,
ease: "expo.out",
});
gsap.set([lbNum, lbTitle, lbArtist, lbMedium], { opacity: 0, y: 15 });
gsap.to([lbNum, lbTitle, lbArtist, lbMedium], {
opacity: 1,
y: 0,
duration: 0.5,
stagger: 0.08,
ease: "expo.out",
delay: 0.35,
});
}
document.body.style.overflow = "hidden";
document.getElementById("lb-close").focus();
}
function closeLightbox() {
if (!reduced) {
const item = workItems[currentIdx];
const rect = item.getBoundingClientRect();
const vw = window.innerWidth;
const vh = window.innerHeight;
gsap.to(lightbox, {
clipPath: `inset(${rect.top}px ${vw - rect.right}px ${vh - rect.bottom}px ${rect.left}px round 2px)`,
duration: 0.4,
ease: "expo.in",
onComplete: () => {
lightbox.setAttribute("hidden", "");
gsap.set(lightbox, { clipPath: "" });
},
});
} else {
lightbox.setAttribute("hidden", "");
}
document.body.style.overflow = "";
workItems[currentIdx].focus();
}
function navigate(dir) {
const next = (currentIdx + dir + artworkData.length) % artworkData.length;
if (!reduced) {
gsap.to([lbNum, lbTitle, lbArtist, lbMedium], {
opacity: 0,
x: dir * -20,
duration: 0.2,
ease: "power2.in",
onComplete: () => {
currentIdx = next;
const d = artworkData[next];
lbNum.textContent = d.num;
lbTitle.textContent = d.title;
lbArtist.textContent = d.artist;
lbMedium.textContent = d.medium;
lbArtwork.className = "lb-artwork wi-art " + d.artClass;
worksCount.textContent = `${d.num} / 08`;
gsap.fromTo(
[lbNum, lbTitle, lbArtist, lbMedium],
{ opacity: 0, x: dir * 20 },
{ opacity: 1, x: 0, duration: 0.35, stagger: 0.06, ease: "expo.out" }
);
},
});
} else {
currentIdx = next;
const d = artworkData[next];
lbNum.textContent = d.num;
lbTitle.textContent = d.title;
lbArtist.textContent = d.artist;
lbMedium.textContent = d.medium;
lbArtwork.className = "lb-artwork wi-art " + d.artClass;
}
}
workItems.forEach((item, i) => {
item.addEventListener("click", () => openLightbox(i));
item.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
openLightbox(i);
}
});
});
document.getElementById("lb-close").addEventListener("click", closeLightbox);
document.getElementById("lb-prev").addEventListener("click", () => navigate(-1));
document.getElementById("lb-next").addEventListener("click", () => navigate(1));
document.addEventListener("keydown", (e) => {
if (!lightbox.hasAttribute("hidden")) {
if (e.key === "Escape") closeLightbox();
if (e.key === "ArrowLeft") navigate(-1);
if (e.key === "ArrowRight") navigate(1);
}
});
// Visit section reveal
if (!reduced) {
gsap.set(".visit-left > *", { opacity: 0, y: 20 });
gsap.to(".visit-left > *", {
opacity: 1,
y: 0,
duration: 0.8,
stagger: 0.12,
ease: "expo.out",
scrollTrigger: {
trigger: ".visit-section",
start: "top 75%",
toggleActions: "play none none reverse",
},
});
}
window.addEventListener("motion-preference", (e) => {
gsap.globalTimeline.paused(e.detail.reduced);
});<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Atelier Blanc — Contemporary Art</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;0,600;1,300;1,400&family=DM+Mono:wght@300;400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<script type="importmap">{"imports":{"gsap":"https://esm.sh/gsap@3.13.0","gsap/ScrollTrigger":"https://esm.sh/gsap@3.13.0/ScrollTrigger","gsap/SplitText":"https://esm.sh/gsap@3.13.0/SplitText","gsap/Flip":"https://esm.sh/gsap@3.13.0/Flip","gsap/ScrambleTextPlugin":"https://esm.sh/gsap@3.13.0/ScrambleTextPlugin","gsap/TextPlugin":"https://esm.sh/gsap@3.13.0/TextPlugin","gsap/all":"https://esm.sh/gsap@3.13.0/all","gsap/":"https://esm.sh/gsap@3.13.0/","lenis":"https://esm.sh/lenis@1.1.13/dist/lenis.mjs","three":"https://esm.sh/three@0.171.0","three/addons/":"https://esm.sh/three@0.171.0/examples/jsm/"}}</script>
<style>html.lenis,
html.lenis body {
height: auto;
}
.lenis:not(.lenis-autoToggle).lenis-stopped {
overflow: clip;
}
.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch] {
overscroll-behavior: contain;
}
.lenis.lenis-smooth iframe {
pointer-events: none;
}
.lenis.lenis-autoToggle {
transition-property: overflow;
transition-duration: 1ms;
transition-behavior: allow-discrete;
}</style>
</head>
<body>
<nav class="nav" id="nav">
<a href="#" class="nav-logo">Atelier Blanc</a>
<ul class="nav-links">
<li><a href="#works">Works</a></li>
<li><a href="#artists">Artists</a></li>
<li><a href="#exhibitions">Exhibitions</a></li>
<li><a href="#visit">Visit</a></li>
</ul>
<a href="#" class="nav-tickets">Get Tickets →</a>
</nav>
<!-- Hero -->
<section class="hero">
<div class="hero-inner">
<div class="hero-text">
<span class="hero-season">Current Season — Spring 2025</span>
<h1 class="hero-h1">
<em>Form</em> follows<br>
feeling.
</h1>
<p>Seven international artists explore the boundary between material and memory in our most ambitious group exhibition to date.</p>
<a href="#works" class="btn-dark">View Exhibition</a>
</div>
<div class="hero-artwork">
<div class="ha-frame ha-frame--main" aria-hidden="true"></div>
<div class="ha-frame ha-frame--accent" aria-hidden="true"></div>
<div class="ha-label">
<span>No. 7 — Untitled (Blue Field)</span>
<span>Elias Vorne, 2024</span>
</div>
</div>
</div>
</section>
<!-- Works gallery — masonry with lightbox -->
<section class="works-section" id="works">
<div class="works-header">
<span class="section-label">Selected Works</span>
<div class="works-count" id="works-count">01 / 08</div>
</div>
<div class="works-grid" id="works-grid">
<figure class="work-item work-item--tall" data-index="0" tabindex="0" role="button" aria-label="Open artwork: Luminous Void">
<div class="wi-art wi-art--1" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">01</span>
<div><strong>Luminous Void</strong><em>Elias Vorne, Oil on canvas, 200×300cm</em></div>
</figcaption>
</figure>
<figure class="work-item" data-index="1" tabindex="0" role="button" aria-label="Open artwork: Still Point">
<div class="wi-art wi-art--2" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">02</span>
<div><strong>Still Point</strong><em>Mara Solis, Photography, 80×120cm</em></div>
</figcaption>
</figure>
<figure class="work-item" data-index="2" tabindex="0" role="button" aria-label="Open artwork: Threshold Study">
<div class="wi-art wi-art--3" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">03</span>
<div><strong>Threshold Study</strong><em>Jun Aoki, Mixed media, 150×150cm</em></div>
</figcaption>
</figure>
<figure class="work-item work-item--wide" data-index="3" tabindex="0" role="button" aria-label="Open artwork: Erosion Series I">
<div class="wi-art wi-art--4" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">04</span>
<div><strong>Erosion Series I–III</strong><em>Petra Novak, Sculpture (bronze), variable dimensions</em></div>
</figcaption>
</figure>
<figure class="work-item" data-index="4" tabindex="0" role="button" aria-label="Open artwork: Frequency">
<div class="wi-art wi-art--5" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">05</span>
<div><strong>Frequency</strong><em>Yuki Tanaka, Digital print, 100×100cm</em></div>
</figcaption>
</figure>
<figure class="work-item" data-index="5" tabindex="0" role="button" aria-label="Open artwork: Residue">
<div class="wi-art wi-art--6" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">06</span>
<div><strong>Residue</strong><em>Camille Dubois, Watercolor, 60×80cm</em></div>
</figcaption>
</figure>
<figure class="work-item work-item--tall" data-index="6" tabindex="0" role="button" aria-label="Open artwork: Meridian">
<div class="wi-art wi-art--7" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">07</span>
<div><strong>Meridian</strong><em>Elias Vorne, Acrylic, 180×280cm</em></div>
</figcaption>
</figure>
<figure class="work-item work-item--wide" data-index="7" tabindex="0" role="button" aria-label="Open artwork: Archive">
<div class="wi-art wi-art--8" aria-hidden="true"></div>
<figcaption class="wi-caption">
<span class="wi-num">08</span>
<div><strong>Archive (after Borges)</strong><em>Jun Aoki, Installation, site-specific</em></div>
</figcaption>
</figure>
</div>
</section>
<!-- Artists -->
<section class="artists-section" id="artists">
<span class="section-label">Featured Artists</span>
<div class="artists-list">
<div class="artist-row">
<span class="ar-num">01</span>
<div class="ar-name">Elias Vorne</div>
<div class="ar-origin">Oslo, Norway</div>
<div class="ar-medium">Oil, Acrylic</div>
<a href="#" class="ar-link">View works →</a>
</div>
<div class="artist-row">
<span class="ar-num">02</span>
<div class="ar-name">Mara Solis</div>
<div class="ar-origin">Mexico City, Mexico</div>
<div class="ar-medium">Photography</div>
<a href="#" class="ar-link">View works →</a>
</div>
<div class="artist-row">
<span class="ar-num">03</span>
<div class="ar-name">Jun Aoki</div>
<div class="ar-origin">Kyoto, Japan</div>
<div class="ar-medium">Mixed media, Installation</div>
<a href="#" class="ar-link">View works →</a>
</div>
<div class="artist-row">
<span class="ar-num">04</span>
<div class="ar-name">Petra Novak</div>
<div class="ar-origin">Prague, Czech Republic</div>
<div class="ar-medium">Sculpture</div>
<a href="#" class="ar-link">View works →</a>
</div>
</div>
</section>
<!-- Visit -->
<section class="visit-section" id="visit">
<div class="visit-inner">
<div class="visit-left">
<span class="section-label">Plan Your Visit</span>
<h2>Open daily<br><em>10am – 7pm</em></h2>
<div class="visit-details">
<div class="vd-item"><span>Address</span><span>12 Rue Voltaire, Paris 75011</span></div>
<div class="vd-item"><span>Admission</span><span>€14 / Students €8 / Under 18 free</span></div>
<div class="vd-item"><span>Guided tours</span><span>Sat & Sun at 3pm</span></div>
</div>
<a href="#" class="btn-dark">Book Tickets</a>
</div>
<div class="visit-map" aria-hidden="true">
<div class="vm-inner"></div>
<div class="vm-pin">◈</div>
</div>
</div>
</section>
<!-- Lightbox -->
<div class="lightbox" id="lightbox" hidden aria-modal="true" aria-label="Artwork detail">
<div class="lb-artwork" id="lb-artwork"></div>
<div class="lb-panel">
<button class="lb-close" id="lb-close" aria-label="Close">✕</button>
<div class="lb-content">
<span class="lb-num" id="lb-num"></span>
<h2 class="lb-title" id="lb-title"></h2>
<div class="lb-artist" id="lb-artist"></div>
<div class="lb-medium" id="lb-medium"></div>
<p class="lb-desc" id="lb-desc">A work that resists easy categorization — existing somewhere between painting and sculpture, memory and projection.</p>
</div>
<div class="lb-nav">
<button id="lb-prev" aria-label="Previous">← Prev</button>
<button id="lb-next" aria-label="Next">Next →</button>
</div>
</div>
</div>
<script type="module" src="script.js"></script>
</body>
</html>Art Gallery — Atelier Blanc
White museum-aesthetic art gallery with Cormorant Garamond serif and DM Mono. Full clip-path lightbox expand for artwork detail view, masonry grid with hover reveals, timeline history section, and keyboard navigation.
Source
- Repository:
libs-genclaude - Original demo id:
53-art-gallery
Notes
White museum-aesthetic art gallery with Cormorant Garamond serif and DM Mono. Full clip-path lightbox expand for artwork detail view, masonry grid with hover reveals, timeline history section, and keyboard navigation.