Photography — About Bio
A gallery-dark about page for a working photographer: a full-bleed portrait beside a lens-focused bio, an equipment shelf of camera bodies and glass, a scroll-revealed awards timeline, an as-seen-in press strip, and a booking CTA — with a copy-email action, a filterable gear shelf, and reveal-on-scroll micro-interactions.
MCP
Code
:root {
--ink: #0b0b0c;
--bg: #101012;
--surface: #17171b;
--surface-2: #1e1e23;
--paper: #f6f4ef;
--sand: #c9b79c;
--sand-d: #a8916f;
--muted: #9a9aa2;
--line: rgba(255, 255, 255, 0.10);
--line-2: rgba(255, 255, 255, 0.18);
--white: #fff;
--r-sm: 6px;
--r-md: 12px;
--r-lg: 18px;
--maxw: 1120px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
background: var(--bg);
color: var(--paper);
font-family: "Inter", system-ui, -apple-system, sans-serif;
font-size: 16px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
img { max-width: 100%; display: block; }
h1, h2, h3 {
font-family: "Fraunces", Georgia, serif;
font-weight: 600;
line-height: 1.08;
margin: 0;
letter-spacing: -0.01em;
}
em { font-style: italic; color: var(--sand); }
.eyebrow {
text-transform: uppercase;
letter-spacing: 0.22em;
font-size: 0.68rem;
font-weight: 600;
color: var(--sand-d);
margin: 0 0 1rem;
}
.eyebrow-light { color: var(--sand); }
/* subtle film grain overlay */
.grain {
position: fixed;
inset: 0;
z-index: 999;
pointer-events: none;
opacity: 0.04;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* ---------- Buttons ---------- */
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-family: inherit;
font-size: 0.92rem;
font-weight: 600;
letter-spacing: 0.01em;
padding: 0.72rem 1.3rem;
border-radius: 999px;
border: 1px solid transparent;
cursor: pointer;
text-decoration: none;
transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn-solid {
background: var(--sand);
color: var(--ink);
}
.btn-solid:hover { background: var(--white); transform: translateY(-2px); }
.btn-ghost {
background: transparent;
color: var(--paper);
border-color: var(--line-2);
}
.btn-ghost:hover { border-color: var(--sand); color: var(--sand); }
.btn-lg { padding: 0.95rem 1.7rem; font-size: 1rem; }
.copy-ico { color: var(--sand); }
:focus-visible {
outline: 2px solid var(--sand);
outline-offset: 3px;
border-radius: var(--r-sm);
}
/* ---------- Topbar ---------- */
.topbar {
position: sticky;
top: 0;
z-index: 50;
display: flex;
align-items: center;
gap: 1.5rem;
padding: 0.9rem clamp(1rem, 4vw, 2.4rem);
background: rgba(16, 16, 18, 0.72);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--line);
}
.brand {
display: flex;
align-items: center;
gap: 0.6rem;
font-family: "Fraunces", serif;
font-size: 1.1rem;
font-weight: 600;
color: var(--paper);
text-decoration: none;
white-space: nowrap;
}
.brand-mark {
width: 14px; height: 14px;
border-radius: 3px;
background: var(--sand);
box-shadow: 0 0 0 3px rgba(201, 183, 156, 0.18);
}
.topnav {
display: flex;
gap: 1.4rem;
margin-left: auto;
}
.topnav a {
color: var(--muted);
text-decoration: none;
font-size: 0.83rem;
letter-spacing: 0.06em;
text-transform: uppercase;
font-weight: 500;
transition: color 0.18s ease;
}
.topnav a:hover { color: var(--paper); }
.topbar-cta { margin-left: 0; padding: 0.55rem 1.1rem; }
/* ---------- Layout ---------- */
main { display: block; }
.hero, .section, .cta {
max-width: var(--maxw);
margin: 0 auto;
padding: clamp(3.5rem, 8vw, 6.5rem) clamp(1rem, 4vw, 2.4rem);
}
/* ---------- Hero ---------- */
.hero {
display: grid;
grid-template-columns: 0.85fr 1.15fr;
gap: clamp(2rem, 5vw, 4rem);
align-items: center;
}
.hero-portrait {
margin: 0;
position: relative;
border-radius: var(--r-lg);
overflow: hidden;
border: 1px solid var(--line);
}
.hero-portrait img {
width: 100%;
aspect-ratio: 4 / 5;
object-fit: cover;
filter: grayscale(0.15) contrast(1.03);
transition: transform 0.9s ease, filter 0.5s ease;
}
.hero-portrait:hover img { transform: scale(1.04); filter: grayscale(0); }
.hero-portrait figcaption {
position: absolute;
left: 1rem; bottom: 1rem;
font-size: 0.68rem;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--paper);
background: rgba(11, 11, 12, 0.55);
backdrop-filter: blur(6px);
padding: 0.4rem 0.7rem;
border-radius: 999px;
border: 1px solid var(--line);
}
.hero-text h1 {
font-size: clamp(2rem, 5.2vw, 3.6rem);
margin-bottom: 1.4rem;
}
.lede {
font-size: 1.12rem;
color: var(--paper);
max-width: 46ch;
margin: 0 0 1.8rem;
}
.bio-cols {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.4rem;
color: var(--muted);
font-size: 0.95rem;
margin-bottom: 2rem;
}
.bio-cols p { margin: 0; }
.stats {
display: flex;
gap: 2.4rem;
padding: 1.4rem 0;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
margin-bottom: 2rem;
flex-wrap: wrap;
}
.stat { display: flex; flex-direction: column; }
.stat-num {
font-family: "Fraunces", serif;
font-size: 2rem;
font-weight: 600;
color: var(--sand);
line-height: 1;
}
.stat-lbl {
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--muted);
margin-top: 0.5rem;
}
.hero-actions { display: flex; gap: 0.9rem; flex-wrap: wrap; }
/* ---------- Section heads ---------- */
.section-head { max-width: 640px; margin-bottom: 2.6rem; }
.section-head h2 {
font-size: clamp(1.7rem, 3.6vw, 2.6rem);
margin-bottom: 0.7rem;
}
.section-sub { color: var(--muted); margin: 0; font-size: 1rem; }
.section-dim { background: var(--surface); max-width: 100%; }
.section-dim > * { max-width: var(--maxw); margin-left: auto; margin-right: auto; }
/* ---------- Filters ---------- */
.filters {
display: flex;
gap: 0.6rem;
flex-wrap: wrap;
margin-bottom: 2rem;
}
.chip {
font-family: inherit;
font-size: 0.8rem;
font-weight: 600;
letter-spacing: 0.04em;
color: var(--muted);
background: var(--surface-2);
border: 1px solid var(--line);
padding: 0.5rem 1.05rem;
border-radius: 999px;
cursor: pointer;
transition: all 0.18s ease;
}
.chip:hover { color: var(--paper); border-color: var(--line-2); }
.chip.is-active {
background: var(--sand);
color: var(--ink);
border-color: var(--sand);
}
/* ---------- Gear grid ---------- */
.gear-grid {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
gap: 1rem;
}
.gear-card {
position: relative;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-md);
padding: 1.4rem;
transition: transform 0.22s ease, border-color 0.22s ease, background 0.22s ease;
}
.gear-card:hover {
transform: translateY(-4px);
border-color: var(--sand-d);
background: var(--surface-2);
}
.gear-card.is-hidden { display: none; }
.gear-tag {
display: inline-block;
font-size: 0.62rem;
text-transform: uppercase;
letter-spacing: 0.16em;
font-weight: 700;
color: var(--sand);
border: 1px solid var(--line-2);
padding: 0.2rem 0.55rem;
border-radius: 999px;
margin-bottom: 0.9rem;
}
.gear-card h3 { font-size: 1.15rem; margin-bottom: 0.5rem; }
.gear-card p { color: var(--muted); font-size: 0.9rem; margin: 0 0 1rem; }
.gear-meta {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--sand-d);
}
.gear-empty {
text-align: center;
color: var(--muted);
padding: 2rem 0;
font-style: italic;
}
/* ---------- Timeline ---------- */
.timeline {
list-style: none;
margin: 0;
padding: 0;
position: relative;
max-width: 720px;
}
.timeline::before {
content: "";
position: absolute;
left: 82px;
top: 6px;
bottom: 6px;
width: 1px;
background: var(--line-2);
}
.tl-item {
display: grid;
grid-template-columns: 72px 1fr;
gap: 1.6rem;
padding: 0 0 2rem;
position: relative;
}
.tl-item:last-child { padding-bottom: 0; }
.tl-year {
font-family: "Fraunces", serif;
font-size: 1.1rem;
font-weight: 600;
color: var(--sand);
text-align: right;
padding-top: 0.1rem;
}
.tl-body { position: relative; }
.tl-body::before {
content: "";
position: absolute;
left: -27px;
top: 6px;
width: 11px; height: 11px;
border-radius: 50%;
background: var(--bg);
border: 2px solid var(--sand);
box-shadow: 0 0 0 4px var(--surface);
}
.section-dim .tl-body::before { box-shadow: 0 0 0 4px var(--surface); }
.tl-body h3 { font-size: 1.2rem; margin-bottom: 0.4rem; }
.tl-body p { color: var(--muted); margin: 0; font-size: 0.95rem; }
/* ---------- Press logos ---------- */
.logo-strip {
list-style: none;
margin: 0;
padding: 2rem 0 0;
display: flex;
flex-wrap: wrap;
gap: clamp(1.5rem, 5vw, 3.5rem);
align-items: center;
border-top: 1px solid var(--line);
}
.logo-strip li {
font-family: "Fraunces", serif;
font-size: clamp(1.1rem, 2.5vw, 1.5rem);
font-weight: 600;
color: var(--muted);
opacity: 0.75;
transition: color 0.2s ease, opacity 0.2s ease;
cursor: default;
white-space: nowrap;
}
.logo-strip li:hover { color: var(--paper); opacity: 1; }
/* ---------- CTA ---------- */
.cta {
text-align: center;
border-top: 1px solid var(--line);
}
.cta h2 {
font-size: clamp(2rem, 5vw, 3.2rem);
margin-bottom: 1rem;
}
.cta-sub {
color: var(--muted);
max-width: 48ch;
margin: 0 auto 2rem;
font-size: 1.05rem;
}
.cta-actions {
display: flex;
gap: 0.9rem;
justify-content: center;
flex-wrap: wrap;
}
/* ---------- Footer ---------- */
.footer {
border-top: 1px solid var(--line);
padding: 1.8rem clamp(1rem, 4vw, 2.4rem);
display: flex;
gap: 0.8rem;
align-items: center;
justify-content: center;
flex-wrap: wrap;
color: var(--muted);
font-size: 0.82rem;
}
.footer a { color: var(--sand); text-decoration: none; }
.footer a:hover { color: var(--white); }
.footer-sep { color: var(--line-2); }
/* ---------- Toast ---------- */
.toast {
position: fixed;
left: 50%;
bottom: 2rem;
transform: translate(-50%, 140%);
background: var(--paper);
color: var(--ink);
font-size: 0.9rem;
font-weight: 600;
padding: 0.8rem 1.3rem;
border-radius: 999px;
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
z-index: 1000;
opacity: 0;
transition: transform 0.35s cubic-bezier(0.2, 0.9, 0.3, 1), opacity 0.35s ease;
pointer-events: none;
}
.toast.show { transform: translate(-50%, 0); opacity: 1; }
/* ---------- Reveal animation ---------- */
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
will-change: opacity, transform;
}
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
.reveal { opacity: 1; transform: none; transition: none; }
html { scroll-behavior: auto; }
}
/* ---------- Responsive ---------- */
@media (max-width: 900px) {
.hero { grid-template-columns: 1fr; }
.hero-portrait { max-width: 420px; }
.topnav { display: none; }
}
@media (max-width: 520px) {
body { font-size: 15px; }
.topbar { gap: 0.8rem; padding: 0.8rem 1rem; }
.topbar-cta { display: none; }
.hero, .section, .cta { padding: 3rem 1rem; }
.hero-text h1 { font-size: 2rem; }
.bio-cols { grid-template-columns: 1fr; gap: 1rem; }
.stats { gap: 1.4rem; }
.stat-num { font-size: 1.6rem; }
.hero-actions, .cta-actions { flex-direction: column; }
.hero-actions .btn, .cta-actions .btn { justify-content: center; }
.gear-grid { grid-template-columns: 1fr; }
.timeline::before { left: 54px; }
.tl-item { grid-template-columns: 48px 1fr; gap: 1.1rem; }
.tl-year { font-size: 0.95rem; }
.tl-body::before { left: -22px; }
.btn-lg { width: 100%; }
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2400);
}
/* ---------- Copy email ---------- */
function wireCopy(btn) {
if (!btn) return;
btn.addEventListener("click", function () {
var email = btn.getAttribute("data-email") || "";
var done = function () { toast("Copied " + email + " to clipboard"); };
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(email).then(done, function () { fallback(email, done); });
} else {
fallback(email, done);
}
});
}
function fallback(text, cb) {
var ta = document.createElement("textarea");
ta.value = text;
ta.setAttribute("readonly", "");
ta.style.position = "absolute";
ta.style.left = "-9999px";
document.body.appendChild(ta);
ta.select();
try { document.execCommand("copy"); cb(); } catch (e) { toast("Press Ctrl+C to copy"); }
document.body.removeChild(ta);
}
wireCopy(document.getElementById("copyEmail"));
wireCopy(document.getElementById("copyEmail2"));
/* ---------- Gear filter ---------- */
var chips = Array.prototype.slice.call(document.querySelectorAll(".chip"));
var cards = Array.prototype.slice.call(document.querySelectorAll(".gear-card"));
var emptyEl = document.getElementById("gearEmpty");
function applyFilter(type) {
var shown = 0;
cards.forEach(function (card) {
var match = type === "all" || card.getAttribute("data-type") === type;
card.classList.toggle("is-hidden", !match);
if (match) shown++;
});
if (emptyEl) emptyEl.hidden = shown !== 0;
}
chips.forEach(function (chip) {
chip.addEventListener("click", function () {
chips.forEach(function (c) {
c.classList.remove("is-active");
c.setAttribute("aria-selected", "false");
});
chip.classList.add("is-active");
chip.setAttribute("aria-selected", "true");
applyFilter(chip.getAttribute("data-filter"));
});
});
/* ---------- Reveal on scroll ---------- */
var revealEls = Array.prototype.slice.call(document.querySelectorAll(".reveal"));
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("is-in");
io.unobserve(entry.target);
}
});
}, { threshold: 0.15, rootMargin: "0px 0px -8% 0px" });
revealEls.forEach(function (el) { io.observe(el); });
} else {
revealEls.forEach(function (el) { el.classList.add("is-in"); });
}
/* ---------- Animated stat counters ---------- */
var statsSection = document.getElementById("stats");
var counted = false;
function runCounters() {
if (counted) return;
counted = true;
var nums = Array.prototype.slice.call(document.querySelectorAll(".stat-num"));
nums.forEach(function (el) {
var target = parseInt(el.getAttribute("data-to"), 10) || 0;
var start = performance.now();
var dur = 1400;
function tick(now) {
var p = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3);
el.textContent = Math.round(eased * target).toLocaleString();
if (p < 1) requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
});
}
if (statsSection && "IntersectionObserver" in window) {
var statObs = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) { runCounters(); statObs.disconnect(); }
});
}, { threshold: 0.4 });
statObs.observe(statsSection);
} else {
runCounters();
}
/* ---------- Active nav link on scroll ---------- */
var navLinks = Array.prototype.slice.call(document.querySelectorAll(".topnav a"));
var sections = navLinks
.map(function (a) { return document.querySelector(a.getAttribute("href")); })
.filter(Boolean);
if (sections.length && "IntersectionObserver" in window) {
var navObs = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
var id = entry.target.getAttribute("id");
navLinks.forEach(function (a) {
a.style.color = a.getAttribute("href") === "#" + id ? "var(--paper)" : "";
});
}
});
}, { threshold: 0.5 });
sections.forEach(function (s) { navObs.observe(s); });
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Mara Vinstad — Photographer, About</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=Inter:wght@400;500;600;700;800&family=Fraunces:wght@400;600&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="grain" aria-hidden="true"></div>
<header class="topbar">
<a class="brand" href="#top">
<span class="brand-mark" aria-hidden="true"></span>
Mara Vinstad
</a>
<nav class="topnav" aria-label="Primary">
<a href="#bio">About</a>
<a href="#gear">Gear</a>
<a href="#awards">Awards</a>
<a href="#press">Press</a>
</nav>
<a class="btn btn-ghost topbar-cta" href="#book">Book a shoot</a>
</header>
<main id="top">
<!-- HERO -->
<section class="hero" id="bio">
<figure class="hero-portrait reveal">
<img
src="https://images.unsplash.com/photo-1554151228-14d9def656e4?auto=format&fit=crop&w=900&q=80"
alt="Portrait of photographer Mara Vinstad in soft window light"
loading="eager"
/>
<figcaption>Reykjavík studio · 2026</figcaption>
</figure>
<div class="hero-text reveal">
<p class="eyebrow">About · Portrait & Landscape</p>
<h1>
I photograph the quiet<br />
seconds between<br />
<em>the ones people pose for.</em>
</h1>
<p class="lede">
Mara Vinstad is a Nordic-born photographer working across editorial portraiture and
wide, weather-heavy landscape. Fifteen years behind the viewfinder, still chasing the
same thing — honest light and the nerve to wait for it.
</p>
<div class="bio-cols">
<p>
I grew up on the coast where the sky changed its mind every ten minutes, and I learned
early that the best frame is usually the one you almost miss. My work has appeared in
galleries from Berlin to Kyoto, but I still shoot most of my personal projects alone,
on foot, before sunrise.
</p>
<p>
My approach is unhurried. I would rather spend an hour talking than rush a headshot,
and I would rather lose a sunset than fake one in post. Clients come for the polish;
they stay for the calm on set. Everything below is what I carry, where I've been shown,
and how to reach me.
</p>
</div>
<div class="stats" id="stats">
<div class="stat"><span class="stat-num" data-to="15">0</span><span class="stat-lbl">Years shooting</span></div>
<div class="stat"><span class="stat-num" data-to="480">0</span><span class="stat-lbl">Shoots delivered</span></div>
<div class="stat"><span class="stat-num" data-to="27">0</span><span class="stat-lbl">Magazine covers</span></div>
</div>
<div class="hero-actions">
<a class="btn btn-solid" href="#book">Start a project</a>
<button class="btn btn-ghost" id="copyEmail" type="button" data-email="[email protected]">
<span class="copy-ico" aria-hidden="true">✦</span> Copy email
</button>
</div>
</div>
</section>
<!-- GEAR -->
<section class="section" id="gear">
<div class="section-head reveal">
<p class="eyebrow">The kit</p>
<h2>What I carry into the field</h2>
<p class="section-sub">Two bodies, a small set of primes, and just enough support to stay light.</p>
</div>
<div class="filters reveal" role="tablist" aria-label="Filter equipment by type">
<button class="chip is-active" role="tab" aria-selected="true" data-filter="all">All</button>
<button class="chip" role="tab" aria-selected="false" data-filter="body">Bodies</button>
<button class="chip" role="tab" aria-selected="false" data-filter="lens">Lenses</button>
<button class="chip" role="tab" aria-selected="false" data-filter="support">Support</button>
</div>
<ul class="gear-grid" id="gearGrid">
<li class="gear-card reveal" data-type="body">
<span class="gear-tag">Body</span>
<h3>Leica SL3-M</h3>
<p>Primary. 60MP full-frame, weather-sealed to shrug off coastal spray.</p>
<span class="gear-meta">Daily driver · since 2024</span>
</li>
<li class="gear-card reveal" data-type="body">
<span class="gear-tag">Body</span>
<h3>Hasselblad 907X</h3>
<p>Medium-format for covers and print work when the file has to breathe.</p>
<span class="gear-meta">Studio · 100MP back</span>
</li>
<li class="gear-card reveal" data-type="lens">
<span class="gear-tag">Lens</span>
<h3>APO 35mm f/2</h3>
<p>The one that never leaves the bag. My default field of view.</p>
<span class="gear-meta">Reportage · environmental</span>
</li>
<li class="gear-card reveal" data-type="lens">
<span class="gear-tag">Lens</span>
<h3>Summicron 90mm f/2</h3>
<p>Portraits with air around them — creamy fall-off, honest skin.</p>
<span class="gear-meta">Headshots · beauty</span>
</li>
<li class="gear-card reveal" data-type="lens">
<span class="gear-tag">Lens</span>
<h3>Zeiss 21mm f/2.8</h3>
<p>Landscapes and interiors where the room itself is the subject.</p>
<span class="gear-meta">Wide · architecture</span>
</li>
<li class="gear-card reveal" data-type="support">
<span class="gear-tag">Support</span>
<h3>Gitzo Traveler Tri.</h3>
<p>Carbon, packs to 40cm. For blue-hour exposures on wet rock.</p>
<span class="gear-meta">Long exposure</span>
</li>
<li class="gear-card reveal" data-type="support">
<span class="gear-tag">Support</span>
<h3>Profoto B10X</h3>
<p>One light, one modifier — I keep lighting deliberately simple.</p>
<span class="gear-meta">Location strobe</span>
</li>
<li class="gear-card reveal" data-type="support">
<span class="gear-tag">Support</span>
<h3>Peak Design 45L</h3>
<p>Everything above, carried up a hill without complaint.</p>
<span class="gear-meta">Travel bag</span>
</li>
</ul>
<p class="gear-empty" id="gearEmpty" hidden>Nothing in this category yet.</p>
</section>
<!-- AWARDS -->
<section class="section section-dim" id="awards">
<div class="section-head reveal">
<p class="eyebrow">Recognition</p>
<h2>Awards & exhibitions</h2>
<p class="section-sub">A short, honest timeline — the shows and prizes I'm proud of.</p>
</div>
<ol class="timeline">
<li class="tl-item reveal">
<span class="tl-year">2026</span>
<div class="tl-body">
<h3>Sony World Photography — Shortlist</h3>
<p>Professional Landscape category, for the series <em>Low Tide, No Names</em>.</p>
</div>
</li>
<li class="tl-item reveal">
<span class="tl-year">2025</span>
<div class="tl-body">
<h3>Solo show · Fotografiska Berlin</h3>
<p>Twenty-eight prints across six weeks; sold-out limited edition run.</p>
</div>
</li>
<li class="tl-item reveal">
<span class="tl-year">2024</span>
<div class="tl-body">
<h3>Hasselblad Masters — Finalist</h3>
<p>Portrait discipline. First Nordic finalist in the category in three years.</p>
</div>
</li>
<li class="tl-item reveal">
<span class="tl-year">2022</span>
<div class="tl-body">
<h3>LensCulture Portrait Award — Juror's Pick</h3>
<p>For a single frame shot on a fishing boat off Vestmannaeyjar.</p>
</div>
</li>
<li class="tl-item reveal">
<span class="tl-year">2019</span>
<div class="tl-body">
<h3>Group exhibition · Kyotographie</h3>
<p>My first international show, and the reason I never stopped.</p>
</div>
</li>
</ol>
</section>
<!-- PRESS -->
<section class="section" id="press">
<div class="section-head reveal">
<p class="eyebrow">As seen in</p>
<h2>Work published with</h2>
</div>
<ul class="logo-strip reveal" aria-label="Publications featuring Mara Vinstad">
<li>Kinfolk</li>
<li>Aperture</li>
<li>Monocle</li>
<li>National Geo</li>
<li>It's Nice That</li>
<li>Cereal</li>
</ul>
</section>
<!-- CTA -->
<section class="cta reveal" id="book">
<p class="eyebrow eyebrow-light">Available Q3 2026</p>
<h2>Let's make something that lasts.</h2>
<p class="cta-sub">
Editorial commissions, brand campaigns, portrait sessions and fine-art prints.
Tell me the story — I'll bring the light.
</p>
<div class="cta-actions">
<a class="btn btn-solid btn-lg" href="mailto:[email protected]">Enquire about a booking</a>
<button class="btn btn-ghost btn-lg" id="copyEmail2" type="button" data-email="[email protected]">
[email protected]
</button>
</div>
</section>
</main>
<footer class="footer">
<span>© 2026 Mara Vinstad Studio</span>
<span class="footer-sep" aria-hidden="true">·</span>
<span>Reykjavík / Berlin</span>
<span class="footer-sep" aria-hidden="true">·</span>
<a href="#top">Back to top ↑</a>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>A dark, image-first about page for the fictional photographer Mara Vinstad. A full-bleed portrait anchors the hero next to a serif headline and a two-column bio written in warm, tactile prose. Thin uppercase labels and sand accents carry the gallery mood throughout.
Below the fold, an equipment shelf lists bodies, lenses, and support gear as filterable cards, a vertical awards timeline reveals each milestone as it scrolls into view, and an as seen in strip shows press logos rendered as clean wordmarks. A closing CTA invites bookings.
Interactions are all vanilla JS: filter chips narrow the gear shelf by category, a copy email
button drops a toast, timeline and section entries fade up via IntersectionObserver, and a live
stat counter tallies years, shoots, and covers on first view. Everything is keyboard-usable with
visible focus rings and works down to 360px.