<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
<meta name="description" content="Gallery of Abstract Art & Music" />
<title>Gallery of Abstract Art & Music</title>
<style>
/* =========================================================
Mobile-first, fast-loading, single-column, vertical scroll
Sticky header + section snap-ish feel + subtle parallax
Client-editable content lives in the CONFIG object (bottom)
========================================================== */
:root{
--bg:#ffffff;
--surface:#ffffff;
--soft:#f5f7fb;
--ink:#0b1220;
--muted:#5b667a;
--line:#e7ecf3;
--brand:#2d4a78; /* primary */
--brand2:#203455; /* darker */
--accent:#e6b85c; /* warm highlight */
--radius:18px;
--shadow: 0 10px 26px rgba(11,18,32,.08);
--shadow2: 0 14px 34px rgba(11,18,32,.10);
--max: 1120px;
--pad: clamp(16px, 3.5vw, 28px);
--h: 68px; /* header height */
}
*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
body{
margin:0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";
color:var(--ink);
background:var(--bg);
line-height:1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
img{ max-width:100%; height:auto; display:block; }
a{ color:inherit; text-decoration:none; }
button{ font:inherit; }
.container{
width:100%;
max-width:var(--max);
margin:0 auto;
padding:0 var(--pad);
}
/* ---------- Sticky Header ---------- */
.header{
position:sticky;
top:0;
z-index:999;
height:var(--h);
background:rgba(255,255,255,.82);
backdrop-filter:saturate(1.2) blur(10px);
border-bottom:1px solid rgba(231,236,243,.9);
}
.header-inner{
height:100%;
display:flex;
align-items:center;
justify-content:space-between;
gap:14px;
}
.brand{
display:flex;
align-items:center;
gap:10px;
min-width:0;
}
.brand-mark{
width:38px; height:38px;
border-radius:10px;
background-color: #ebd9b9;
border:1px solid rgba(45,74,120,.22);
display:grid;
place-items:center;
overflow:hidden;
flex:0 0 auto;
}
.brand-mark img{ width:28px; height:28px; object-fit:contain; }
.brand-title{
display:flex;
flex-direction:column;
min-width:0;
}
.brand-title strong{
font-size:14px;
letter-spacing:.2px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.brand-title span{
font-size:12px;
color:var(--muted);
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.nav{
display:none; /* mobile-first: hidden, use hamburger */
align-items:center;
gap:18px;
}
.nav a{
font-size:14px;
color:var(--muted);
padding:10px 10px;
border-radius:12px;
transition: background .2s ease, color .2s ease;
}
.nav a:hover, .nav a[aria-current="page"]{
background:rgba(45,74,120,.08);
color:var(--brand2);
}
.header-actions{
display:flex;
align-items:center;
gap:10px;
}
.btn{
display:inline-flex;
align-items:center;
justify-content:center;
gap:10px;
padding:12px 14px;
border-radius:14px;
border:1px solid var(--line);
background:var(--surface);
color:var(--ink);
box-shadow: 0 1px 0 rgba(11,18,32,.03);
cursor:pointer;
transition: transform .12s ease, box-shadow .2s ease, border-color .2s ease;
user-select:none;
-webkit-tap-highlight-color: transparent;
}
.btn:active{ transform: translateY(1px); }
.btn-primary{
background:linear-gradient(135deg, var(--brand), var(--brand2));
color:#fff;
border-color: rgba(45,74,120,.2);
box-shadow: var(--shadow);
}
.btn-primary:hover{ box-shadow: var(--shadow2); }
.btn-ghost{
background:transparent;
border-color:transparent;
color:var(--brand2);
}
.btn-ghost:hover{ background:rgba(45,74,120,.08); }
/* hamburger */
.hamburger{
width:44px; height:44px;
border-radius:14px;
border:1px solid var(--line);
background:var(--surface);
display:grid;
place-items:center;
cursor:pointer;
-webkit-tap-highlight-color: transparent;
}
.hamburger span{
width:18px; height:2px;
background:var(--brand2);
position:relative;
display:block;
border-radius:2px;
}
.hamburger span:before,
.hamburger span:after{
content:"";
position:absolute;
left:0;
width:18px; height:2px;
background:var(--brand2);
border-radius:2px;
transition: transform .2s ease, top .2s ease, opacity .2s ease;
}
.hamburger span:before{ top:-6px; }
.hamburger span:after{ top:6px; }
/* open state */
.hamburger[aria-expanded="true"] span{ background:transparent; }
.hamburger[aria-expanded="true"] span:before{ top:0; transform: rotate(45deg); }
.hamburger[aria-expanded="true"] span:after{ top:0; transform: rotate(-45deg); }
/* mobile menu */
.mobile-menu{
position:fixed;
inset: calc(var(--h) + 10px) 10px auto 10px;
max-width: 520px;
margin: 0 auto;
background: rgba(255,255,255,.92);
backdrop-filter:saturate(1.2) blur(12px);
border: 1px solid rgba(231,236,243,.95);
border-radius: 20px;
box-shadow: var(--shadow2);
overflow:hidden;
transform: translateY(-10px);
opacity:0;
pointer-events:none;
transition: opacity .18s ease, transform .18s ease;
z-index:1000;
}
.mobile-menu.open{
transform: translateY(0);
opacity:1;
pointer-events:auto;
}
.mobile-menu a{
display:flex;
align-items:center;
justify-content:space-between;
padding:16px 16px;
border-bottom:1px solid rgba(231,236,243,.9);
color:var(--brand2);
font-weight:600;
}
.mobile-menu a small{
font-weight:600;
color:var(--muted);
}
.mobile-menu .cta{
padding:14px;
display:grid;
gap:10px;
background: linear-gradient(180deg, rgba(245,247,251,.8), rgba(255,255,255,.85));
}
.mobile-menu .cta .btn{ width:100%; padding:14px 14px; border-radius:16px; }
/* overlay behind menu */
.scrim{
position:fixed;
inset:0;
background:rgba(11,18,32,.22);
opacity:0;
pointer-events:none;
transition: opacity .18s ease;
z-index:999;
}
.scrim.open{
opacity:1;
pointer-events:auto;
}
/* ---------- Sections ---------- */
section{
padding: clamp(44px, 6.5vw, 84px) 0;
}
.hero{
padding-top: clamp(26px, 4vw, 44px);
background:
radial-gradient(800px 240px at 20% 10%, rgba(230,184,92,.20), transparent 60%),
radial-gradient(900px 260px at 80% 10%, rgba(45,74,120,.18), transparent 58%),
linear-gradient(180deg, rgba(245,247,251,.75), rgba(255,255,255,1));
}
.hero-grid{
display:grid;
gap:24px;
}
.kicker{
font-size:12px;
letter-spacing:.16em;
text-transform:uppercase;
color:var(--muted);
margin:0 0 10px 0;
}
h1{
font-size: clamp(34px, 5.2vw, 54px);
line-height:1.08;
margin:0 0 14px 0;
letter-spacing:-.02em;
color:var(--brand2);
}
.lead{
margin:0 0 18px 0;
color:var(--muted);
font-size: clamp(15px, 2.2vw, 18px);
max-width: 56ch;
}
.hero-actions{
display:flex;
flex-direction:column;
gap:12px;
margin-top:14px;
max-width: 420px;
}
.hero-actions .btn{
width:100%;
padding:14px 16px;
border-radius:16px;
}
/* "parallax" media block (lightweight) */
.hero-media{
position:relative;
border-radius: 22px;
overflow:hidden;
border:1px solid rgba(231,236,243,.95);
background: linear-gradient(135deg, rgba(45,74,120,.14), rgba(230,184,92,.18));
box-shadow: var(--shadow);
min-height: 280px;
}
.hero-media .layer{
position:absolute;
inset:0;
background-size:cover;
background-position:center;
transform: translate3d(0,0,0);
will-change: transform;
filter: saturate(1.02);
opacity:.92;
}
.hero-media .cards{
position:absolute;
inset:0;
display:grid;
place-items:center;
padding:24px;
}
.floating-card{
width:min(420px, 86%);
border-radius: 20px;
background: rgba(255,255,255,.86);
border: 1px solid rgba(231,236,243,.95);
box-shadow: var(--shadow2);
padding: 18px;
display:grid;
gap:10px;
}
.floating-card strong{
color:var(--brand2);
font-size: 16px;
}
.floating-card p{
margin:0;
color:var(--muted);
font-size: 14px;
}
/* Features */
.section-title{
text-align:center;
margin:0 0 10px 0;
font-size: clamp(26px, 3.6vw, 40px);
letter-spacing:-.02em;
color:var(--brand2);
}
.section-sub{
text-align:center;
margin:0 auto 28px auto;
color:var(--muted);
max-width: 66ch;
font-size: 15px;
}
.features{
display:grid;
gap:14px;
margin-top: 22px;
}
.card{
background:var(--surface);
border:1px solid var(--line);
border-radius: var(--radius);
padding:18px;
box-shadow: 0 1px 0 rgba(11,18,32,.03);
}
.card h3{
margin:10px 0 6px 0;
color:var(--brand2);
letter-spacing:-.01em;
}
.card p{
margin:0;
color:var(--muted);
font-size: 14px;
}
.icon{
width:44px; height:44px;
border-radius:14px;
display:grid;
place-items:center;
background: rgba(45,74,120,.09);
border:1px solid rgba(45,74,120,.12);
color:var(--brand2);
font-weight:900;
user-select:none;
}
/* Gallery */
.gallery-wrap{
margin-top: 24px;
display:grid;
gap:12px;
}
.gallery-strip{
display:grid;
grid-auto-flow:column;
grid-auto-columns: 88%;
gap:12px;
overflow-x:auto;
scroll-snap-type: x mandatory;
padding-bottom: 8px;
-webkit-overflow-scrolling: touch;
}
.gallery-strip::-webkit-scrollbar{ height: 10px; }
.gallery-strip::-webkit-scrollbar-thumb{
background: rgba(45,74,120,.18);
border-radius: 20px;
}
.art-tile{
scroll-snap-align: start;
border-radius: 22px;
overflow:hidden;
border: 1px solid rgba(231,236,243,.95);
background: var(--soft);
min-height: 240px;
position:relative;
box-shadow: var(--shadow);
}
.art-tile img{
width:100%;
height: 100%;
object-fit: cover;
}
.art-meta{
position:absolute;
left:14px; right:14px; bottom:14px;
background: rgba(255,255,255,.88);
border: 1px solid rgba(231,236,243,.95);
border-radius: 16px;
padding: 10px 12px;
display:flex;
align-items:center;
justify-content:space-between;
gap:10px;
backdrop-filter:saturate(1.2) blur(10px);
}
.art-meta strong{ font-size: 13px; color:var(--brand2); }
.art-meta span{ font-size: 12px; color:var(--muted); }
.gallery-controls{
display:flex;
align-items:center;
justify-content:space-between;
gap:10px;
margin-top: 8px;
}
.dots{
display:flex;
gap:8px;
align-items:center;
justify-content:center;
flex: 1;
}
.dot{
width:8px; height:8px;
border-radius:999px;
background: rgba(45,74,120,.20);
border: 1px solid rgba(45,74,120,.18);
}
.dot.active{
width:22px;
background: rgba(45,74,120,.55);
}
/* Testimonials */
.testimonials{
display:grid;
gap:12px;
margin-top: 22px;
}
.quote{
display:grid;
gap:10px;
padding:18px;
}
.quote-top{
display:flex;
align-items:center;
justify-content:space-between;
gap:12px;
}
.who{
display:flex;
align-items:center;
gap:10px;
min-width:0;
}
.avatar{
width:34px; height:34px;
border-radius: 12px;
background: rgba(230,184,92,.22);
border:1px solid rgba(230,184,92,.28);
flex:0 0 auto;
}
.who b{ font-size: 14px; color:var(--brand2); }
.who small{
display:block;
font-size: 12px;
color:var(--muted);
}
.stars{
font-size: 12px;
color: var(--brand2);
background: rgba(45,74,120,.08);
border:1px solid rgba(45,74,120,.12);
padding:8px 10px;
border-radius: 999px;
white-space:nowrap;
}
.quote p{
margin:0;
color:var(--muted);
font-size: 14px;
}
/* Contact CTA */
.cta-block{
background: linear-gradient(180deg, rgba(245,247,251,.85), rgba(255,255,255,1));
border-top: 1px solid rgba(231,236,243,.9);
border-bottom: 1px solid rgba(231,236,243,.9);
}
.cta-inner{
display:grid;
gap:14px;
align-items:start;
}
.cta-inner .btn{
width:100%;
padding:16px 16px;
border-radius: 18px;
}
.input{
width:100%;
border-radius: 16px;
border: 1px solid var(--line);
padding: 14px 14px;
background: #fff;
color: var(--ink);
outline: none;
box-shadow: 0 1px 0 rgba(11,18,32,.03);
}
.input:focus{
border-color: rgba(45,74,120,.35);
box-shadow: 0 0 0 4px rgba(45,74,120,.10);
}
/* Footer */
footer{
background: #eef2f7;
padding: 34px 0;
color: var(--muted);
}
.footer-grid{
display:grid;
gap:16px;
}
.fine{
font-size: 12px;
color: rgba(91,102,122,.95);
}
.footer-links{
display:flex;
gap:14px;
flex-wrap:wrap;
}
.footer-links a{
font-size: 13px;
color: var(--brand2);
padding: 10px 12px;
border-radius: 12px;
background: rgba(255,255,255,.55);
border: 1px solid rgba(231,236,243,.9);
}
/* ---------- Desktop enhancements (still single-column layout) ---------- */
@media (min-width: 860px){
.nav{ display:flex; }
.hamburger{ display:none; }
.hero-grid{
grid-template-columns: 1.1fr .9fr;
align-items:center;
gap:28px;
}
.hero-actions{
flex-direction:row;
}
.hero-actions .btn{ width:auto; }
.features{
grid-template-columns: repeat(3, 1fr);
}
.gallery-strip{
grid-auto-columns: 32%;
}
.testimonials{
grid-template-columns: repeat(3, 1fr);
}
.cta-inner{
grid-template-columns: 1.2fr .8fr;
align-items:center;
}
}
/* Reduced motion for accessibility */
@media (prefers-reduced-motion: reduce){
html{ scroll-behavior:auto; }
.hero-media .layer{ transform:none !important; }
.mobile-menu{ transition:none; }
.scrim{ transition:none; }
.btn{ transition:none; }
}
</style>
</head>
<body>
<!-- Sticky Header -->
<header class="header" id="top">
<div class="container">
<div class="header-inner">
<a class="brand" href="#home" aria-label="Home">
<div class="brand-mark">
<!-- Replace this logo path with your client’s logo file -->
<img id="logoImg" src="images/logo.png" alt="GOAAM logo" loading="eager" decoding="async" />
</div>
<div class="brand-title">
<strong id="brandName">Gallery of Abstract Art & Music</strong>
<span id="brandTagline">Art. Music. Community.</span>
</div>
</a>
<!-- Desktop Nav -->
<nav class="nav" aria-label="Primary navigation">
<a href="index.html" data-scroll>Home</a>
<a href="aboutus.html" data-scroll>About</a>
<a href="#contact" data-scroll>Contact</a>
<a href="#gallery" data-scroll>Gallery</a>
<a href="#featured" data-scroll>Featured</a>
<a href="#shop" data-scroll>Shop</a>
<a href="#give" data-scroll>Give</a>
</nav>
<div class="header-actions">
<a class="btn btn-ghost" href="#contact" data-scroll aria-label="Jump to contact">Contact</a>
<button class="hamburger" id="hamburger" aria-label="Open menu" aria-controls="mobileMenu" aria-expanded="false">
<span></span>
</button>
</div>
</div>
</div>
</header>
<!-- Mobile Menu + Scrim -->
<div class="scrim" id="scrim" aria-hidden="true"></div>
<div class="mobile-menu" id="mobileMenu" role="dialog" aria-modal="true" aria-label="Menu">
<a href="#home" data-scroll>Home <small>→</small></a>
<a href="#about" data-scroll>About Us <small>→</small></a>
<a href="#contact" data-scroll>Contact Us <small>→</small></a>
<a href="#gallery" data-scroll>Gallery <small>→</small></a>
<a href="#featured" data-scroll>Featured Artist <small>→</small></a>
<a href="#shop" data-scroll>Shop <small>→</small></a>
<a href="#give" data-scroll>Give <small>→</small></a>
<div class="cta">
<a class="btn btn-primary" href="#gallery" data-scroll>Explore the Gallery</a>
<a class="btn" href="#give" data-scroll>Support the Mission</a>
</div>
</div>
<!-- HERO -->
<main>
<section class="hero" id="home">
<div class="container">
<div class="hero-grid">
<div>
<p class="kicker" id="heroKicker">Welcome to our creative hub</p>
<h1 id="heroTitle">Highlighting the appreciation of art.</h1>
<p class="lead" id="heroLead">
Explore a world where every piece tells a story and every note resonates with passion.
Join us in celebrating the beauty of artistic expression.
</p>
<div class="hero-actions">
<a class="btn btn-primary" href="#gallery" data-scroll id="heroCta1">See the Gallery</a>
<a class="btn" href="#give" data-scroll id="heroCta2">Become a Patron</a>
</div>
</div>
<div class="hero-media" aria-label="Hero imagery">
<!-- Parallax layer (image path set by CONFIG.heroBg) -->
<div class="layer" id="heroLayer"></div>
<div class="cards">
<div class="floating-card">
<strong id="heroCardTitle">Art & Music, together.</strong>
<p id="heroCardText">A modern gallery experience designed to be simple, fast, and beautiful on any screen.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ABOUT / VALUE -->
<section id="about">
<div class="container">
<h2 class="section-title" id="aboutTitle">Art appreciation for all</h2>
<p class="section-sub" id="aboutSub">
A welcoming space for collectors, students, and curious minds—built to spotlight emerging talent and timeless craft.
</p>
<div class="features" id="featureGrid">
<!-- Filled by CONFIG.features -->
</div>
</div>
</section>
<!-- GALLERY -->
<section id="gallery">
<div class="container">
<h2 class="section-title">See our Gallery</h2>
<p class="section-sub">Swipe through curated pieces. Replace images in the folder, update titles in the config—done.</p>
<div class="gallery-wrap">
<div class="gallery-strip" id="galleryStrip" aria-label="Artwork carousel">
<!-- Filled by CONFIG.gallery -->
</div>
<div class="gallery-controls" aria-label="Carousel controls">
<button class="btn" id="prevBtn" type="button" aria-label="Previous">
←
</button>
<div class="dots" id="dots" aria-hidden="true">
<!-- dots -->
</div>
<button class="btn" id="nextBtn" type="button" aria-label="Next">
→
</button>
</div>
</div>
</div>
</section>
<!-- TRUST / TESTIMONIALS -->
<section id="featured">
<div class="container">
<h2 class="section-title">Trusted by Artists and Creative communities</h2>
<p class="section-sub">A few kind words—proof that good work still travels the old-fashioned way: from person to person.</p>
<div class="testimonials" id="testimonialGrid">
<!-- Filled by CONFIG.testimonials -->
</div>
</div>
</section>
<!-- SHOP (placeholder / CTA) -->
<section id="shop" class="cta-block">
<div class="container">
<div class="cta-inner">
<div>
<h2 class="section-title" style="text-align:left;margin-bottom:8px;">Shop prints, tickets, and releases</h2>
<p class="section-sub" style="text-align:left;margin:0 0 16px 0;">
Keep it simple: one tap to explore what’s new, one tap to support an artist.
</p>
<a class="btn btn-primary" href="#contact" data-scroll>Ask about availability</a>
</div>
<div class="card">
<h3 style="margin:0 0 8px 0;">Quick links</h3>
<p style="margin:0 0 12px 0;">Add your store link(s) in the config.</p>
<div style="display:grid;gap:10px;">
<a class="btn" id="shopLink1" href="#" target="_blank" rel="noopener">Shop Online</a>
<a class="btn" id="shopLink2" href="#" target="_blank" rel="noopener">Upcoming Events</a>
</div>
</div>
</div>
</div>
</section>
<!-- GIVE -->
<section id="give">
<div class="container">
<h2 class="section-title">Give</h2>
<p class="section-sub">
Your support sustains workshops, showcases, and opportunities for the next generation of creators.
</p>
<div class="card" style="max-width:760px;margin:0 auto;">
<h3 style="margin-top:0;">Support the mission</h3>
<p>Link your donation platform here (Stripe, PayPal, GiveButter, etc.).</p>
<a class="btn btn-primary" id="giveBtn" href="#" target="_blank" rel="noopener">Donate</a>
</div>
</div>
</section>
<!-- CONTACT -->
<section id="contact" class="cta-block">
<div class="container">
<div class="cta-inner">
<div>
<h2 class="section-title" style="text-align:left;margin-bottom:8px;">Contact Us</h2>
<p class="section-sub" style="text-align:left;margin:0 0 16px 0;">
For submissions, bookings, and collaborations—send a note. We’ll reply with care and clarity.
</p>
<div style="display:flex; gap:10px; flex-wrap:wrap;">
<a class="btn btn-primary" id="emailBtn" href="#">Email</a>
<a class="btn" id="phoneBtn" href="#">Call</a>
</div>
</div>
<!-- Simple contact form (client-editable action)
NOTE: For real email delivery, connect to a server endpoint or form tool. -->
<form class="card" id="contactForm" onsubmit="return handleContactSubmit(event)">
<h3 style="margin-top:0;">Send a message</h3>
<div style="display:grid; gap:10px;">
<input class="input" name="name" placeholder="Your name" required />
<input class="input" name="email" type="email" placeholder="Email address" required />
<textarea class="input" name="message" rows="4" placeholder="How can we help?" required style="resize:vertical;"></textarea>
<button class="btn btn-primary" type="submit">Send</button>
<p class="fine" style="margin:0;">
This demo form shows a success state. Wire it to a backend or form service when you’re ready.
</p>
</div>
</form>
</div>
</div>
</section>
</main>
<!-- FOOTER -->
<footer>
<div class="container">
<div class="footer-grid">
<div class="brand" style="gap:12px;">
<div class="brand-mark" style="width:44px;height:44px;border-radius:14px;">
<img id="footerLogoImg" src="images/logo.png" alt="GOAAM logo" loading="lazy" decoding="async" />
</div>
<div class="brand-title">
<strong id="footerName">GOAAM</strong>
<span id="footerText">At our art gallery, we aim to enrich your artistic experience.</span>
</div>
</div>
<div class="footer-links">
<a href="#top" data-scroll>Back to top</a>
<a href="#" id="privacyLink" target="_blank" rel="noopener">Privacy & Policy</a>
<a href="#" id="termsLink" target="_blank" rel="noopener">Terms & Conditions</a>
</div>
<div class="fine" id="copyrightText">© 2026 GOAAM. All rights reserved.</div>
</div>
</div>
</footer>
<script>
/* =========================================================
EDITING MODEL (Client-friendly)
1) Replace images inside /images/...
2) Update CONFIG paths + titles below
That’s it. No layout spelunking required.
========================================================== */
const CONFIG = {
brand: {
name: "Gallery of Abstract Art & Music",
tagline: "Art. Music. Community.",
footerName: "GOAAM",
footerText: "At our art gallery, we aim to enrich your artistic experience.",
logoPath: "images/logo.png" // put the logo file in /images/
},
contact: {
email: "hello@example.com",
phone: "+1 (000) 000-0000"
},
links: {
shop1: { label: "Shop Online", url: "https://example.com/shop" },
shop2: { label: "Upcoming Events", url: "https://example.com/events" },
donate: "https://example.com/donate",
privacy: "https://example.com/privacy",
terms: "https://example.com/terms"
},
hero: {
kicker: "Welcome to our creative hub",
title: "Highlighting the appreciation of art.",
lead:
"Explore a world where every piece tells a story and every note resonates with passion. Join us in celebrating the beauty of artistic expression.",
cta1: "See the Gallery",
cta2: "Become a Patron",
cardTitle: "Art & Music, together.",
cardText: "A modern gallery experience designed to be simple, fast, and beautiful on any screen.",
heroBg: "images/hero/hero-bg.jpg" // place in /images/hero/
},
about: {
title: "Art appreciation for all",
sub:
"A welcoming space for collectors, students, and curious minds—built to spotlight emerging talent and timeless craft."
},
features: [
{
icon: "🖼️",
title: "Art Galleries",
text: "Curated collections with clean navigation and fast-loading visuals—built to spotlight the work, not the chrome."
},
{
icon: "🎹",
title: "Music & artistic expression",
text: "A platform where exhibitions and sound meet—share releases, events, and collaborations in one place."
},
{
icon: "💡",
title: "Learning platform",
text: "Workshops, talks, and resources—simple calls-to-action that work beautifully on mobile."
}
],
// IMPORTANT: Static HTML cannot auto-list a folder on its own.
// So we treat this as a “manifest”: add/remove items here, and drop files into /images/gallery/
gallery: [
{ title: "Atmosphere Study", artist: "Featured Artist", src: "images/gallery/art-01.jpg" },
{ title: "Blue Motion", artist: "Featured Artist", src: "images/gallery/art-02.jpg" },
{ title: "Gold Rhythm", artist: "Featured Artist", src: "images/gallery/art-03.jpg" },
{ title: "Soft Geometry", artist: "Featured Artist", src: "images/gallery/art-04.jpg" },
{ title: "Night Notes", artist: "Featured Artist", src: "images/gallery/art-05.jpg" }
],
testimonials: [
{
name: "Vincent Van Gogh",
role: "Artist",
rating: "4.5",
quote: "Absolutely thrilled with this platform—clean, simple, and it lets the art do the talking."
},
{
name: "Michelangelo",
role: "Artist",
rating: "4.5",
quote: "Elegant presentation, easy navigation, and a modern feel—exactly what a gallery site needs."
},
{
name: "Rembrandt",
role: "Artist",
rating: "4.5",
quote: "Fast, clear, and beautifully spaced. Visitors can focus on the work without distraction."
}
]
};
/* ---------- Sticky + Scroll (offset for sticky header) ---------- */
function scrollToId(id){
const el = document.querySelector(id);
if(!el) return;
const y = el.getBoundingClientRect().top + window.pageYOffset - (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--h')) || 68);
window.scrollTo({ top: y, behavior: 'smooth' });
}
document.addEventListener('click', (e) => {
const a = e.target.closest('a[data-scroll]');
if(!a) return;
const href = a.getAttribute('href');
if(!href || !href.startsWith('#')) return;
e.preventDefault();
closeMenu();
scrollToId(href);
});
/* ---------- Mobile menu ---------- */
const hamburger = document.getElementById('hamburger');
const mobileMenu = document.getElementById('mobileMenu');
const scrim = document.getElementById('scrim');
function openMenu(){
hamburger.setAttribute('aria-expanded', 'true');
mobileMenu.classList.add('open');
scrim.classList.add('open');
document.body.style.overflow = 'hidden';
}
function closeMenu(){
hamburger.setAttribute('aria-expanded', 'false');
mobileMenu.classList.remove('open');
scrim.classList.remove('open');
document.body.style.overflow = '';
}
hamburger.addEventListener('click', () => {
const expanded = hamburger.getAttribute('aria-expanded') === 'true';
expanded ? closeMenu() : openMenu();
});
scrim.addEventListener('click', closeMenu);
document.addEventListener('keydown', (e) => {
if(e.key === 'Escape') closeMenu();
});
/* ---------- Parallax (lightweight, transform-based) ---------- */
const heroLayer = document.getElementById('heroLayer');
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
function onScrollParallax(){
if(prefersReducedMotion) return;
const rect = heroLayer.parentElement.getBoundingClientRect();
// Only animate when near viewport
if(rect.bottom < -200 || rect.top > window.innerHeight + 200) return;
const progress = (window.innerHeight - rect.top) / (window.innerHeight + rect.height);
const offset = (progress - 0.5) * 18; // subtle
heroLayer.style.transform = `translate3d(0, ${offset}px, 0) scale(1.04)`;
}
/* ---------- Render from CONFIG ---------- */
function applyConfig(){
// Brand
document.getElementById('brandName').textContent = CONFIG.brand.name;
document.getElementById('brandTagline').textContent = CONFIG.brand.tagline;
document.getElementById('footerName').textContent = CONFIG.brand.footerName;
document.getElementById('footerText').textContent = CONFIG.brand.footerText;
const logo = CONFIG.brand.logoPath;
document.getElementById('logoImg').src = logo;
document.getElementById('footerLogoImg').src = logo;
// Hero
document.getElementById('heroKicker').textContent = CONFIG.hero.kicker;
document.getElementById('heroTitle').textContent = CONFIG.hero.title;
document.getElementById('heroLead').textContent = CONFIG.hero.lead;
document.getElementById('heroCta1').textContent = CONFIG.hero.cta1;
document.getElementById('heroCta2').textContent = CONFIG.hero.cta2;
document.getElementById('heroCardTitle').textContent = CONFIG.hero.cardTitle;
document.getElementById('heroCardText').textContent = CONFIG.hero.cardText;
heroLayer.style.backgroundImage = `url("${CONFIG.hero.heroBg}")`;
// Preload hero image quickly (no blocking)
const pre = new Image();
pre.src = CONFIG.hero.heroBg;
// About
document.getElementById('aboutTitle').textContent = CONFIG.about.title;
document.getElementById('aboutSub').textContent = CONFIG.about.sub;
// Features
const featureGrid = document.getElementById('featureGrid');
featureGrid.innerHTML = CONFIG.features.map(f => `
<div class="card">
<div class="icon" aria-hidden="true">${f.icon}</div>
<h3>${escapeHtml(f.title)}</h3>
<p>${escapeHtml(f.text)}</p>
</div>
`).join('');
// Gallery
const strip = document.getElementById('galleryStrip');
strip.innerHTML = CONFIG.gallery.map((g, idx) => `
<article class="art-tile" data-idx="${idx}">
<img
src="${escapeAttr(g.src)}"
alt="${escapeAttr(g.title)} by ${escapeAttr(g.artist)}"
loading="lazy"
decoding="async"
/>
<div class="art-meta">
<div style="min-width:0;">
<strong>${escapeHtml(g.title)}</strong><br/>
<span>${escapeHtml(g.artist)}</span>
</div>
<span style="font-size:12px;color:var(--muted);white-space:nowrap;">View →</span>
</div>
</article>
`).join('');
// Dots
const dots = document.getElementById('dots');
dots.innerHTML = CONFIG.gallery.map((_, i) => `<span class="dot ${i===0?'active':''}" data-dot="${i}"></span>`).join('');
// Testimonials
const tGrid = document.getElementById('testimonialGrid');
tGrid.innerHTML = CONFIG.testimonials.map(t => `
<div class="card quote">
<div class="quote-top">
<div class="who">
<div class="avatar" aria-hidden="true"></div>
<div style="min-width:0;">
<b>${escapeHtml(t.name)}</b>
<small>${escapeHtml(t.role)}</small>
</div>
</div>
<div class="stars" aria-label="Rating">${escapeHtml(t.rating)} ★</div>
</div>
<p>"${escapeHtml(t.quote)}"</p>
</div>
`).join('');
// Links
const shop1 = document.getElementById('shopLink1');
const shop2 = document.getElementById('shopLink2');
shop1.textContent = CONFIG.links.shop1.label;
shop1.href = CONFIG.links.shop1.url;
shop2.textContent = CONFIG.links.shop2.label;
shop2.href = CONFIG.links.shop2.url;
document.getElementById('giveBtn').href = CONFIG.links.donate;
document.getElementById('privacyLink').href = CONFIG.links.privacy;
document.getElementById('termsLink').href = CONFIG.links.terms;
// Contact buttons
const email = CONFIG.contact.email;
const phone = CONFIG.contact.phone;
document.getElementById('emailBtn').href = `mailto:${email}`;
document.getElementById('phoneBtn').href = `tel:${phone.replace(/[^\d+]/g,'')}`;
// Copyright (keep traditional, update year if you like)
const year = new Date().getFullYear();
document.getElementById('copyrightText').textContent =
`© ${year} ${CONFIG.brand.footerName}. All rights reserved.`;
}
/* ---------- Gallery carousel helpers ---------- */
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const strip = document.getElementById('galleryStrip');
const dots = document.getElementById('dots');
function getTiles(){
return Array.from(strip.querySelectorAll('.art-tile'));
}
function scrollToIndex(i){
const tiles = getTiles();
if(!tiles[i]) return;
tiles[i].scrollIntoView({ behavior: 'smooth', inline: 'start', block: 'nearest' });
}
function setActiveDot(i){
Array.from(dots.querySelectorAll('.dot')).forEach(d => d.classList.remove('active'));
const dot = dots.querySelector(`[data-dot="${i}"]`);
if(dot) dot.classList.add('active');
}
prevBtn.addEventListener('click', () => {
const tiles = getTiles();
const idx = getClosestIndex(tiles);
scrollToIndex(Math.max(0, idx - 1));
});
nextBtn.addEventListener('click', () => {
const tiles = getTiles();
const idx = getClosestIndex(tiles);
scrollToIndex(Math.min(tiles.length - 1, idx + 1));
});
dots.addEventListener('click', (e) => {
const dot = e.target.closest('.dot');
if(!dot) return;
scrollToIndex(parseInt(dot.dataset.dot, 10));
});
function getClosestIndex(tiles){
const left = strip.getBoundingClientRect().left;
let best = 0, bestDist = Infinity;
tiles.forEach((t, i) => {
const r = t.getBoundingClientRect();
const dist = Math.abs(r.left - left);
if(dist < bestDist){ best = i; bestDist = dist; }
});
return best;
}
// Update active dot on scroll (throttled)
let raf = 0;
strip.addEventListener('scroll', () => {
cancelAnimationFrame(raf);
raf = requestAnimationFrame(() => {
const tiles = getTiles();
setActiveDot(getClosestIndex(tiles));
});
});
/* ---------- Contact form demo handler ---------- */
function handleContactSubmit(e){
e.preventDefault();
const form = e.target;
const btn = form.querySelector('button[type="submit"]');
btn.disabled = true;
btn.textContent = "Sent ✓";
setTimeout(() => {
btn.disabled = false;
btn.textContent = "Send";
form.reset();
alert("Message captured (demo). Connect this form to a backend or form service to send emails.");
}, 450);
return false;
}
/* ---------- Tiny escape helpers ---------- */
function escapeHtml(s){
return String(s).replace(/[&<>"']/g, (c) => ({
'&':'&','<':'<','>':'>','"':'"',"'":'''
}[c]));
}
function escapeAttr(s){
return escapeHtml(s).replace(/"/g, '"');
}
/* ---------- Init ---------- */
applyConfig();
window.addEventListener('scroll', () => {
onScrollParallax();
}, { passive:true });
onScrollParallax();
</script>
<!--
IMAGE FOLDER GUIDE (simple & client-proof)
/images/logo.png
/images/hero/hero-bg.jpg
/images/gallery/art-01.jpg ... art-05.jpg
Replace files in those folders and update CONFIG.gallery items as needed.
If your client truly needs “no-code” image additions/removals,
pair this front-end with:
- a lightweight CMS (Decap/Netlify CMS, Sanity, Contentful), or
- a simple JSON file editor panel on the server.
Static HTML alone can’t auto-read a folder listing for security reasons.
-->
</body>
</html>
GOAAM Art Highlight
Discover artwork worth living with.
Tap any piece to view details, pricing, medium, and a direct purchase option. The gallery stays fast, clean, and mobile-first—because art deserves a quiet stage.
About the book about freaky shit wit horns and womens
This exquisite compilation showcases a diverse array of photographs that capture the essence of different eras and cultures, reflecting the unique styles and perspectives of each artist. Fleckenstein’s evocative imagery, Strand’s groundbreaking modernist approach, and Kōno’s meticulous documentation of Japanese life come together in a harmonious blend that celebrates the art of photography. Each image in “The Stories Book” is accompanied by insightful commentary, providing historical context and revealing the stories behind the photographs. This collection is not only a visual feast but also a tribute to the power of photography to preserve and narrate the multifaceted experiences of humanity.


EXPERIENCE GOAAM
Where Art & Music Converge
A sanctuary for abstract expression and musical innovation. Discover curated collections that transcend traditional boundaries and celebrate creative freedom.
Art appreciation for all
A welcoming space for collectors, students, and curious minds—built to spotlight emerging talent and timeless craft.
Curated Collections
Experience our rotating exhibitions featuring abstract works that challenge perception and inspire conversation.
Trusted by Artists and Creative communities
A few kind words—proof that good work still travels the old-fashioned way: from person to person.
Shop prints, tickets, and releases
Keep it simple: one tap to explore what’s new, one tap to support an artist. Limited edition prints, exhibition tickets, and exclusive artist releases.
Ask about availabilitySupport Creative Vision
Your contribution sustains artist residencies, community workshops, and groundbreaking exhibitions that push creative boundaries.
Every donation directly funds artist grants, exhibition materials, and educational programs that make art accessible to all.
Subscribe to get unlimited access
- Get access to our paid articles and weekly newsletter.
- Join our IRL events.
- Get a free tote bag.
- An elegant addition of home decor collection.
- Join our forums.
Cancel or pause anytime.








