web-design-skill/demo/demo2-with-skill.html
lishiqi.conard 2e214c5b76 Add initial project files including .gitignore, LICENSE, README, and skill definitions
- Created .gitignore to exclude unnecessary files.
- Added MIT License for project licensing.
- Introduced README.md and README.zh-CN.md for documentation in English and Chinese.
- Implemented web design engineer skill with detailed workflow and design principles.
- Included advanced patterns and code templates for reference in the skill.
- Added demo HTML files showcasing the skill's capabilities.
2026-04-21 19:53:49 +08:00

1810 lines
65 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mira Høst — Photographs from the quiet north</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=Instrument+Serif:ital@0;1&family=Space+Grotesk:wght@300;400;500&display=swap" rel="stylesheet">
<style>
:root {
--paper: #f2efe8;
--paper-soft: #e8e4d9;
--ink: #161513;
--ink-soft: #3a3631;
--ink-mute: #8a857d;
--rule: rgba(22, 21, 19, 0.18);
--rule-light: rgba(242, 239, 232, 0.28);
--display: 'Instrument Serif', 'Times New Roman', serif;
--ui: 'Space Grotesk', -apple-system, sans-serif;
--ease-soft: cubic-bezier(0.22, 1, 0.36, 1);
--ease-cinema: cubic-bezier(0.65, 0, 0.35, 1);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
background: var(--paper);
color: var(--ink);
font-family: var(--ui);
font-weight: 300;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
body {
min-height: 100vh;
min-height: 100dvh;
cursor: default;
}
::selection { background: var(--ink); color: var(--paper); }
/* ---------- Masthead ---------- */
.masthead {
position: fixed;
top: 0; left: 0; right: 0;
z-index: 50;
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
padding: 22px 48px;
font-family: var(--ui);
font-size: 11px;
font-weight: 500;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--paper);
mix-blend-mode: difference;
opacity: 0;
animation: fadeIn 1.4s var(--ease-soft) 0.2s forwards;
}
.masthead__brand {
display: flex;
align-items: center;
gap: 14px;
}
.masthead__mark {
width: 26px; height: 26px;
border: 1px solid var(--paper);
display: grid;
place-items: center;
font-family: var(--display);
font-size: 14px;
font-weight: 400;
letter-spacing: 0;
text-transform: none;
}
.masthead__center {
justify-self: center;
font-size: 10px;
letter-spacing: 0.32em;
color: var(--paper);
opacity: 0.78;
}
.masthead__nav {
justify-self: end;
display: flex;
gap: 38px;
}
.masthead__nav a {
color: inherit;
text-decoration: none;
position: relative;
padding: 4px 0;
transition: opacity 0.4s var(--ease-soft);
}
.masthead__nav a::after {
content: '';
position: absolute;
left: 0; right: 100%; bottom: 0;
height: 1px;
background: currentColor;
transition: right 0.5s var(--ease-soft);
}
.masthead__nav a:hover::after { right: 0; }
.masthead__nav a:not(:hover) { opacity: 0.7; }
/* ---------- Hero ---------- */
.hero {
position: relative;
width: 100%;
height: 100vh;
height: 100dvh;
overflow: hidden;
background: #1a1815;
}
.hero__media {
position: absolute;
inset: 0;
overflow: hidden;
}
.hero__img {
position: absolute;
inset: -4%;
width: 108%;
height: 108%;
object-fit: cover;
transform: scale(1.04);
opacity: 0;
transition: opacity 1.6s var(--ease-cinema);
animation: kenburns 24s ease-in-out 1.6s infinite alternate;
}
.hero__img.loaded { opacity: 1; }
@keyframes kenburns {
from { transform: scale(1.04) translate(0, 0); }
to { transform: scale(1.12) translate(-1.5%, -1%); }
}
/* Soft cinematic gradient — only where text sits */
.hero__veil {
position: absolute;
inset: 0;
background:
linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0) 22%, rgba(0,0,0,0) 55%, rgba(0,0,0,0.62) 100%),
linear-gradient(90deg, rgba(0,0,0,0.32) 0%, rgba(0,0,0,0) 45%);
pointer-events: none;
}
/* Subtle grain — adds analogue texture */
.hero__grain {
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0.08;
mix-blend-mode: overlay;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* ---------- Hero content ---------- */
.hero__content {
position: absolute;
inset: 0;
padding: 110px 48px 56px;
display: grid;
grid-template-rows: 1fr auto;
color: var(--paper);
}
.hero__lede {
align-self: end;
max-width: 920px;
}
.hero__eyebrow {
display: flex;
align-items: center;
gap: 14px;
font-family: var(--ui);
font-size: 11px;
font-weight: 500;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--paper);
opacity: 0;
transform: translateY(12px);
animation: rise 1.1s var(--ease-soft) 0.6s forwards;
}
.hero__eyebrow .num {
font-family: var(--display);
font-size: 14px;
letter-spacing: 0;
text-transform: none;
font-style: italic;
opacity: 0.8;
}
.hero__eyebrow .bar {
width: 36px;
height: 1px;
background: var(--paper);
opacity: 0.6;
}
.hero__title {
margin-top: 26px;
font-family: var(--display);
font-weight: 400;
font-size: clamp(54px, 9.2vw, 156px);
line-height: 0.94;
letter-spacing: -0.015em;
color: var(--paper);
}
.hero__title .word {
display: inline-block;
opacity: 0;
transform: translateY(28px);
animation: rise 1.2s var(--ease-cinema) forwards;
}
.hero__title .word:nth-child(1) { animation-delay: 0.75s; }
.hero__title .word:nth-child(2) { animation-delay: 0.85s; }
.hero__title .word:nth-child(3) { animation-delay: 0.95s; }
.hero__title .word:nth-child(4) { animation-delay: 1.05s; }
.hero__title .word:nth-child(5) { animation-delay: 1.15s; }
.hero__title .italic {
font-style: italic;
color: var(--paper);
opacity: 0.92;
}
.hero__byline {
margin-top: 28px;
display: flex;
align-items: baseline;
gap: 14px;
font-family: var(--ui);
font-size: 13px;
font-weight: 300;
letter-spacing: 0.02em;
color: var(--paper);
opacity: 0;
transform: translateY(14px);
animation: rise 1.1s var(--ease-soft) 1.35s forwards;
}
.hero__byline em {
font-family: var(--display);
font-style: italic;
font-size: 16px;
letter-spacing: 0;
}
.hero__byline .dot {
width: 3px; height: 3px;
background: var(--paper);
opacity: 0.55;
border-radius: 50%;
display: inline-block;
transform: translateY(-3px);
}
/* ---------- Bottom metadata strip ---------- */
.hero__meta {
margin-top: 60px;
border-top: 1px solid var(--rule-light);
padding-top: 18px;
display: grid;
grid-template-columns: 1.2fr 1fr 1fr auto;
gap: 32px;
align-items: end;
font-family: var(--ui);
font-size: 10.5px;
font-weight: 400;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--paper);
opacity: 0;
animation: fadeIn 1.2s var(--ease-soft) 1.6s forwards;
}
.hero__meta .cell {
display: flex;
flex-direction: column;
gap: 8px;
min-width: 0;
}
.hero__meta .label {
color: var(--paper);
opacity: 0.55;
font-size: 9.5px;
letter-spacing: 0.3em;
}
.hero__meta .value {
color: var(--paper);
font-family: var(--display);
font-size: 17px;
letter-spacing: 0;
text-transform: none;
font-weight: 400;
}
.hero__meta .value .em {
font-style: italic;
opacity: 0.85;
}
.hero__scroll {
justify-self: end;
display: flex;
align-items: center;
gap: 12px;
font-family: var(--ui);
font-size: 10px;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--paper);
opacity: 0.85;
cursor: pointer;
background: none;
border: none;
padding: 6px 2px;
transition: opacity 0.4s var(--ease-soft);
}
.hero__scroll:hover { opacity: 1; }
.hero__scroll-line {
position: relative;
width: 1px;
height: 38px;
background: rgba(242, 239, 232, 0.25);
overflow: hidden;
}
.hero__scroll-line::after {
content: '';
position: absolute;
top: -50%;
left: 0; right: 0;
height: 50%;
background: var(--paper);
animation: scrollLine 2.4s var(--ease-cinema) infinite;
}
@keyframes scrollLine {
0% { transform: translateY(0); }
100% { transform: translateY(300%); }
}
/* ---------- Side rails (issue / coords) ---------- */
.rail {
position: fixed;
z-index: 20;
font-family: var(--ui);
font-size: 10px;
font-weight: 500;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--paper);
mix-blend-mode: difference;
opacity: 0;
animation: fadeIn 1.2s var(--ease-soft) 1.4s forwards;
}
.rail--left {
left: 24px;
top: 50%;
transform: rotate(-90deg) translateX(50%);
transform-origin: left center;
display: flex;
align-items: center;
gap: 16px;
}
.rail--right {
right: 24px;
top: 50%;
transform: rotate(90deg) translateX(-50%);
transform-origin: right center;
display: flex;
align-items: center;
gap: 16px;
}
.rail .tick {
width: 18px; height: 1px;
background: currentColor;
opacity: 0.6;
}
/* ============================================================
SHARED — section frame, eyebrows, rules
============================================================ */
.section {
position: relative;
padding: clamp(80px, 12vw, 160px) 48px;
background: var(--paper);
color: var(--ink);
}
.section--ink {
background: var(--ink);
color: var(--paper);
}
.section__inner {
max-width: 1320px;
margin: 0 auto;
}
.section__head {
display: grid;
grid-template-columns: 1fr auto;
align-items: end;
gap: 32px;
padding-bottom: 28px;
border-bottom: 1px solid var(--rule);
margin-bottom: clamp(48px, 7vw, 96px);
}
.section--ink .section__head { border-bottom-color: var(--rule-light); }
.eyebrow {
display: inline-flex;
align-items: center;
gap: 14px;
font-family: var(--ui);
font-size: 11px;
font-weight: 500;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--ink-soft);
}
.section--ink .eyebrow { color: rgba(242,239,232,0.7); }
.eyebrow .num {
font-family: var(--display);
font-size: 14px;
letter-spacing: 0;
text-transform: none;
font-style: italic;
opacity: 0.85;
}
.eyebrow .bar {
width: 36px; height: 1px;
background: currentColor;
opacity: 0.5;
}
.section__title {
font-family: var(--display);
font-weight: 400;
font-size: clamp(40px, 6vw, 86px);
line-height: 1.0;
letter-spacing: -0.015em;
margin-top: 18px;
max-width: 18ch;
}
.section__title .it { font-style: italic; }
.section__aside {
font-family: var(--ui);
font-size: 11px;
letter-spacing: 0.28em;
text-transform: uppercase;
color: var(--ink-mute);
text-align: right;
line-height: 1.6;
}
.section--ink .section__aside { color: rgba(242,239,232,0.55); }
/* ============================================================
FEATURED SPREAD — Höfn series
============================================================ */
.spread__grid {
display: grid;
grid-template-columns: 5fr 7fr;
gap: clamp(40px, 6vw, 96px);
align-items: start;
}
.spread__copy {
position: sticky;
top: 110px;
}
.spread__pull {
font-family: var(--display);
font-style: italic;
font-size: clamp(28px, 3.4vw, 44px);
line-height: 1.18;
letter-spacing: -0.01em;
color: var(--ink);
margin-bottom: 36px;
}
.spread__body {
font-family: var(--ui);
font-size: 15px;
line-height: 1.7;
color: var(--ink-soft);
max-width: 38ch;
font-weight: 300;
}
.spread__body p + p { margin-top: 14px; }
.spread__meta {
margin-top: 44px;
padding-top: 22px;
border-top: 1px solid var(--rule);
display: grid;
grid-template-columns: 1fr 1fr;
gap: 18px 24px;
font-family: var(--ui);
font-size: 10.5px;
letter-spacing: 0.26em;
text-transform: uppercase;
color: var(--ink-mute);
}
.spread__meta .v {
color: var(--ink);
font-family: var(--display);
font-style: normal;
font-size: 16px;
letter-spacing: 0;
text-transform: none;
margin-top: 6px;
display: block;
}
.spread__meta .v em { font-style: italic; }
.spread__plates {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 18px;
}
.plate {
position: relative;
overflow: hidden;
background: var(--paper-soft);
}
.plate img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: transform 1.4s var(--ease-cinema);
}
.plate:hover img { transform: scale(1.04); }
.plate__cap {
position: absolute;
left: 14px; bottom: 12px;
font-family: var(--ui);
font-size: 10px;
letter-spacing: 0.24em;
text-transform: uppercase;
color: var(--paper);
mix-blend-mode: difference;
opacity: 0.85;
}
.plate--a { grid-column: 1 / span 4; aspect-ratio: 4/3; }
.plate--b { grid-column: 5 / span 2; aspect-ratio: 3/4; }
.plate--c { grid-column: 1 / span 2; aspect-ratio: 3/4; }
.plate--d { grid-column: 3 / span 4; aspect-ratio: 4/3; }
/* ============================================================
INDEX of WORKS — magazine table of contents
============================================================ */
.toc {
display: flex;
flex-direction: column;
}
.toc__row {
display: grid;
grid-template-columns: 80px 1fr 180px 120px 80px;
align-items: center;
gap: 28px;
padding: 22px 0;
border-bottom: 1px solid var(--rule);
color: var(--ink);
text-decoration: none;
position: relative;
transition: background 0.5s var(--ease-soft);
}
.toc__row:first-child { border-top: 1px solid var(--rule); }
.toc__num {
font-family: var(--display);
font-style: italic;
font-size: 22px;
color: var(--ink-mute);
}
.toc__title {
font-family: var(--display);
font-size: clamp(28px, 3.6vw, 48px);
line-height: 1.0;
letter-spacing: -0.01em;
transition: transform 0.6s var(--ease-soft), letter-spacing 0.6s var(--ease-soft);
}
.toc__title em { font-style: italic; opacity: 0.8; }
.toc__row:hover .toc__title {
transform: translateX(8px);
}
.toc__loc, .toc__count {
font-family: var(--ui);
font-size: 11px;
letter-spacing: 0.26em;
text-transform: uppercase;
color: var(--ink-mute);
}
.toc__loc .y {
display: block;
margin-top: 4px;
color: var(--ink);
font-size: 12px;
letter-spacing: 0.04em;
font-family: var(--display);
font-style: italic;
text-transform: none;
}
.toc__arrow {
justify-self: end;
font-family: var(--display);
font-size: 26px;
color: var(--ink);
transition: transform 0.5s var(--ease-soft);
}
.toc__row:hover .toc__arrow { transform: translateX(6px); }
.toc__thumb {
position: absolute;
top: 50%;
right: 220px;
width: 180px;
height: 120px;
transform: translateY(-50%) scale(0.94);
opacity: 0;
pointer-events: none;
overflow: hidden;
transition: opacity 0.5s var(--ease-soft), transform 0.6s var(--ease-soft);
z-index: 2;
}
.toc__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.toc__row:hover .toc__thumb { opacity: 1; transform: translateY(-50%) scale(1); }
/* ============================================================
STUDIO — about / statement
============================================================ */
.studio__grid {
display: grid;
grid-template-columns: 5fr 7fr;
gap: clamp(40px, 6vw, 96px);
align-items: start;
}
.studio__portrait {
position: relative;
aspect-ratio: 4 / 5;
background: var(--paper-soft);
overflow: hidden;
display: flex;
align-items: flex-end;
padding: 18px;
}
/* Tasteful placeholder — replace with real portrait in production */
.studio__portrait::before {
content: '';
position: absolute;
inset: 0;
background:
repeating-linear-gradient(
45deg,
rgba(22,21,19,0.04) 0px,
rgba(22,21,19,0.04) 1px,
transparent 1px,
transparent 12px
),
linear-gradient(160deg, #d8d2c4 0%, #c8c0ae 60%, #b8af9b 100%);
}
.studio__portrait::after {
content: 'Portrait — to be replaced';
position: absolute;
top: 18px; left: 18px;
font-family: var(--ui);
font-size: 9.5px;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--ink-soft);
opacity: 0.6;
}
.studio__portrait .pcap {
position: relative;
font-family: var(--ui);
font-size: 10px;
letter-spacing: 0.28em;
text-transform: uppercase;
color: var(--ink-soft);
opacity: 0.7;
z-index: 1;
}
.studio__copy {
padding-top: 8px;
}
.studio__quote {
font-family: var(--display);
font-style: italic;
font-size: clamp(32px, 4vw, 56px);
line-height: 1.12;
letter-spacing: -0.012em;
color: var(--ink);
margin-bottom: 36px;
text-wrap: pretty;
}
.studio__body {
font-family: var(--ui);
font-size: 15.5px;
line-height: 1.75;
color: var(--ink-soft);
max-width: 56ch;
font-weight: 300;
}
.studio__body p + p { margin-top: 16px; }
.studio__cv {
margin-top: 56px;
padding-top: 26px;
border-top: 1px solid var(--rule);
display: grid;
grid-template-columns: 160px 1fr;
gap: 20px 36px;
font-family: var(--ui);
font-size: 12.5px;
line-height: 1.7;
color: var(--ink-soft);
}
.studio__cv dt {
font-size: 10.5px;
letter-spacing: 0.28em;
text-transform: uppercase;
color: var(--ink-mute);
}
.studio__cv dd {
font-family: var(--display);
font-size: 16px;
color: var(--ink);
}
.studio__cv dd em { font-style: italic; opacity: 0.8; }
/* ============================================================
PRACTICE — services
============================================================ */
.practice__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0;
border-top: 1px solid var(--rule);
}
.practice__col {
padding: 44px 28px 36px;
border-right: 1px solid var(--rule);
display: flex;
flex-direction: column;
min-height: 360px;
}
.practice__col:last-child { border-right: none; }
.practice__num {
font-family: var(--display);
font-style: italic;
font-size: 22px;
color: var(--ink-mute);
margin-bottom: 32px;
}
.practice__title {
font-family: var(--display);
font-size: 32px;
line-height: 1.05;
letter-spacing: -0.01em;
margin-bottom: 16px;
}
.practice__title em { font-style: italic; }
.practice__body {
font-family: var(--ui);
font-size: 14px;
line-height: 1.65;
color: var(--ink-soft);
font-weight: 300;
margin-bottom: 28px;
}
.practice__list {
list-style: none;
padding: 0;
margin-top: auto;
font-family: var(--ui);
font-size: 11px;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--ink-mute);
}
.practice__list li {
padding: 10px 0;
border-top: 1px solid var(--rule);
display: flex;
justify-content: space-between;
gap: 12px;
}
.practice__list li:last-child { border-bottom: 1px solid var(--rule); }
.practice__list .v {
font-family: var(--display);
font-size: 13px;
color: var(--ink);
text-transform: none;
letter-spacing: 0;
font-style: italic;
}
/* ============================================================
JOURNAL — field notes
============================================================ */
.journal__grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: clamp(28px, 3vw, 48px);
}
.journal__entry {
text-decoration: none;
color: var(--ink);
display: flex;
flex-direction: column;
gap: 18px;
}
.journal__cover {
aspect-ratio: 4 / 3;
overflow: hidden;
background: var(--paper-soft);
}
.journal__cover img {
width: 100%; height: 100%;
object-fit: cover;
transition: transform 1.4s var(--ease-cinema);
}
.journal__entry:hover .journal__cover img { transform: scale(1.04); }
.journal__date {
font-family: var(--ui);
font-size: 10.5px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--ink-mute);
display: flex;
gap: 14px;
align-items: center;
}
.journal__date .dot {
width: 3px; height: 3px;
background: var(--ink-mute);
border-radius: 50%;
}
.journal__title {
font-family: var(--display);
font-size: clamp(22px, 2vw, 28px);
line-height: 1.18;
letter-spacing: -0.01em;
text-wrap: pretty;
}
.journal__title em { font-style: italic; }
.journal__excerpt {
font-family: var(--ui);
font-size: 13.5px;
line-height: 1.6;
color: var(--ink-soft);
font-weight: 300;
text-wrap: pretty;
}
.journal__more {
margin-top: clamp(48px, 6vw, 80px);
padding-top: 26px;
border-top: 1px solid var(--rule);
display: flex;
justify-content: space-between;
align-items: baseline;
font-family: var(--ui);
font-size: 11px;
letter-spacing: 0.28em;
text-transform: uppercase;
}
.journal__more a {
color: var(--ink);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 10px;
transition: gap 0.4s var(--ease-soft);
}
.journal__more a:hover { gap: 16px; }
/* ============================================================
CORRESPONDENCE — dark contact section
============================================================ */
.contact__inner {
max-width: 1320px;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr;
gap: 72px;
}
.contact__lede {
font-family: var(--display);
font-size: clamp(44px, 6vw, 96px);
line-height: 1.02;
letter-spacing: -0.018em;
color: var(--paper);
max-width: 18ch;
text-wrap: pretty;
}
.contact__lede em { font-style: italic; opacity: 0.88; }
.contact__rows {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 56px;
border-top: 1px solid var(--rule-light);
padding-top: 40px;
}
.contact__block .label {
display: block;
font-family: var(--ui);
font-size: 10.5px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: rgba(242,239,232,0.55);
margin-bottom: 14px;
}
.contact__block .value {
font-family: var(--display);
font-size: clamp(22px, 2.4vw, 34px);
line-height: 1.25;
color: var(--paper);
text-decoration: none;
display: inline-block;
position: relative;
}
.contact__block .value::after {
content: '';
position: absolute;
left: 0; right: 100%; bottom: -4px;
height: 1px;
background: var(--paper);
transition: right 0.6s var(--ease-soft);
}
.contact__block a.value:hover::after { right: 0; }
.contact__sub {
margin-top: 12px;
font-family: var(--ui);
font-size: 13px;
line-height: 1.6;
color: rgba(242,239,232,0.6);
max-width: 38ch;
font-weight: 300;
}
.contact__social {
display: flex;
gap: 22px;
flex-wrap: wrap;
}
.contact__social a {
font-family: var(--ui);
font-size: 12px;
letter-spacing: 0.24em;
text-transform: uppercase;
color: var(--paper);
text-decoration: none;
opacity: 0.75;
transition: opacity 0.4s var(--ease-soft);
padding: 6px 0;
border-bottom: 1px solid rgba(242,239,232,0.3);
}
.contact__social a:hover { opacity: 1; }
/* ============================================================
COLOPHON — footer
============================================================ */
.colophon {
background: var(--ink);
color: var(--paper);
padding: 56px 48px 36px;
border-top: 1px solid var(--rule-light);
}
.colophon__inner {
max-width: 1320px;
margin: 0 auto;
display: grid;
grid-template-columns: 1.6fr 1fr 1fr 1fr;
gap: 40px;
align-items: start;
}
.colophon__brand {
display: flex;
flex-direction: column;
gap: 16px;
}
.colophon__mark {
width: 32px; height: 32px;
border: 1px solid var(--paper);
display: grid;
place-items: center;
font-family: var(--display);
font-size: 18px;
color: var(--paper);
}
.colophon__name {
font-family: var(--display);
font-size: 22px;
line-height: 1.15;
}
.colophon__name em { font-style: italic; opacity: 0.85; }
.colophon__tag {
font-family: var(--ui);
font-size: 11px;
letter-spacing: 0.28em;
text-transform: uppercase;
color: rgba(242,239,232,0.55);
margin-top: 6px;
}
.colophon__col h4 {
font-family: var(--ui);
font-size: 10.5px;
font-weight: 500;
letter-spacing: 0.3em;
text-transform: uppercase;
color: rgba(242,239,232,0.55);
margin-bottom: 16px;
}
.colophon__col ul { list-style: none; }
.colophon__col li { margin-bottom: 8px; }
.colophon__col a {
font-family: var(--display);
font-size: 16px;
color: var(--paper);
text-decoration: none;
opacity: 0.9;
transition: opacity 0.4s var(--ease-soft);
}
.colophon__col a:hover { opacity: 1; }
.colophon__bottom {
max-width: 1320px;
margin: 56px auto 0;
padding-top: 22px;
border-top: 1px solid var(--rule-light);
display: flex;
justify-content: space-between;
gap: 24px;
flex-wrap: wrap;
font-family: var(--ui);
font-size: 10.5px;
letter-spacing: 0.24em;
text-transform: uppercase;
color: rgba(242,239,232,0.5);
}
.colophon__bottom em {
font-family: var(--display);
font-style: italic;
font-size: 12px;
letter-spacing: 0;
text-transform: none;
color: rgba(242,239,232,0.7);
}
/* ============================================================
SCROLL REVEAL
============================================================ */
.reveal {
opacity: 0;
transform: translateY(24px);
transition: opacity 1.1s var(--ease-soft), transform 1.1s var(--ease-soft);
}
.reveal.in {
opacity: 1;
transform: translateY(0);
}
.reveal-stagger > * {
opacity: 0;
transform: translateY(20px);
transition: opacity 0.9s var(--ease-soft), transform 0.9s var(--ease-soft);
}
.reveal-stagger.in > * { opacity: 1; transform: translateY(0); }
.reveal-stagger.in > *:nth-child(2) { transition-delay: 0.12s; }
.reveal-stagger.in > *:nth-child(3) { transition-delay: 0.24s; }
.reveal-stagger.in > *:nth-child(4) { transition-delay: 0.36s; }
.reveal-stagger.in > *:nth-child(5) { transition-delay: 0.48s; }
.reveal-stagger.in > *:nth-child(6) { transition-delay: 0.60s; }
/* ============================================================
Section-level responsive
============================================================ */
@media (max-width: 1100px) {
.toc__row { grid-template-columns: 60px 1fr 140px 60px; }
.toc__count { display: none; }
.toc__thumb { display: none; }
}
@media (max-width: 900px) {
.section { padding: 80px 22px; }
.spread__grid,
.studio__grid { grid-template-columns: 1fr; gap: 48px; }
.spread__copy { position: static; }
.spread__plates { grid-template-columns: 1fr 1fr; }
.plate--a, .plate--d { grid-column: span 2; }
.plate--b, .plate--c { grid-column: span 1; }
.toc__row { grid-template-columns: 44px 1fr 50px; padding: 18px 0; gap: 16px; }
.toc__loc, .toc__count { display: none; }
.toc__title { font-size: 32px; }
.practice__grid { grid-template-columns: 1fr; }
.practice__col { border-right: none; border-bottom: 1px solid var(--rule); min-height: auto; }
.practice__col:last-child { border-bottom: none; }
.journal__grid { grid-template-columns: 1fr; gap: 40px; }
.contact__rows { grid-template-columns: 1fr; gap: 40px; }
.colophon { padding: 48px 22px 28px; }
.colophon__inner { grid-template-columns: 1fr 1fr; gap: 32px; }
.colophon__brand { grid-column: span 2; }
.section__head { grid-template-columns: 1fr; align-items: start; }
.section__aside { text-align: left; }
.studio__cv { grid-template-columns: 120px 1fr; }
}
/* ---------- Animations ---------- */
@keyframes fadeIn {
to { opacity: 1; }
}
@keyframes rise {
to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
.hero__img { animation: none !important; }
.hero__scroll-line::after { animation: none !important; }
* { animation-duration: 0.001s !important; transition-duration: 0.001s !important; }
}
/* ---------- Responsive ---------- */
@media (max-width: 900px) {
.masthead { padding: 18px 22px; grid-template-columns: 1fr auto; }
.masthead__center { display: none; }
.masthead__nav { gap: 22px; font-size: 10px; }
.hero__content { padding: 90px 22px 28px; }
.hero__meta {
grid-template-columns: 1fr 1fr;
gap: 22px 18px;
}
.hero__meta .cell:nth-child(3) { display: none; }
.hero__scroll { grid-column: span 2; justify-self: start; margin-top: 8px; }
.hero__scroll-line { display: none; }
.rail { display: none; }
}
@media (max-width: 540px) {
.masthead__nav a:nth-child(2),
.masthead__nav a:nth-child(3) { display: none; }
.hero__title { font-size: clamp(46px, 13vw, 80px); }
.hero__byline { flex-wrap: wrap; }
}
</style>
</head>
<body>
<!-- ======================================================
MASTHEAD — thin top bar, mix-blend over the photograph
====================================================== -->
<header class="masthead">
<div class="masthead__brand">
<span class="masthead__mark">M</span>
<span>Mira&nbsp;Høst&nbsp;Studio</span>
</div>
<div class="masthead__center">Photography &nbsp;·&nbsp; Est. 2019</div>
<nav class="masthead__nav" aria-label="Primary">
<a href="#works">Works</a>
<a href="#studio">Studio</a>
<a href="#journal">Journal</a>
<a href="#contact">Contact</a>
</nav>
</header>
<!-- ======================================================
HERO — full-bleed photograph + editorial pull-quote
The image is a placeholder. Replace src with the
photographer's signature frame for production.
====================================================== -->
<section class="hero" aria-label="Hero">
<div class="hero__media">
<!-- Replace this image with a real selected work (1920px+ wide, landscape orientation) -->
<img class="hero__img"
src="https://images.unsplash.com/photo-1518562180175-34a163b1a9a6?auto=format&fit=crop&w=2400&q=85"
alt="Misted northern landscape"
onload="this.classList.add('loaded')">
<div class="hero__veil"></div>
<div class="hero__grain"></div>
</div>
<div class="hero__content">
<!-- top space intentionally empty — the photograph breathes -->
<div></div>
<div class="hero__lede">
<div class="hero__eyebrow">
<span class="num">N° 07</span>
<span class="bar"></span>
<span>Selected Works · 2019—2025</span>
</div>
<h1 class="hero__title">
<span class="word">Photographs</span>
<span class="word">from</span>
<span class="word">the</span>
<span class="word italic">quiet</span>
<span class="word italic">north.</span>
</h1>
<p class="hero__byline">
<em>Mira Høst</em>
<span class="dot"></span>
Independent photographer based in Reykjavík
<span class="dot"></span>
Available for commissions worldwide
</p>
<div class="hero__meta">
<div class="cell">
<span class="label">Featured Series</span>
<span class="value"><span class="em">Höfn</span>, in November light</span>
</div>
<div class="cell">
<span class="label">Location</span>
<span class="value">64°15N &nbsp; 15°12W</span>
</div>
<div class="cell">
<span class="label">Camera</span>
<span class="value">Hasselblad 907X</span>
</div>
<button class="hero__scroll" type="button" aria-label="Scroll to next section">
<span>Scroll</span>
<span class="hero__scroll-line" aria-hidden="true"></span>
</button>
</div>
</div>
</div>
</section>
<!-- ======================================================
02 FEATURED SPREAD — Höfn series detail
Magazine-style spread: statement on left (sticky),
asymmetric photo grid on right.
====================================================== -->
<section class="section" id="featured" aria-labelledby="featured-title">
<div class="section__inner">
<div class="section__head reveal">
<div>
<span class="eyebrow">
<span class="num">N° 07</span>
<span class="bar"></span>
<span>Featured Series</span>
</span>
<h2 class="section__title" id="featured-title">
<em>Höfn,</em><br>
in November light.
</h2>
</div>
<div class="section__aside">
Iceland<br>
2019&thinsp;&thinsp;2025<br>
24 plates
</div>
</div>
<div class="spread__grid">
<aside class="spread__copy reveal">
<p class="spread__pull">
Seven Novembers in a town at the edge of the world.
</p>
<div class="spread__body">
<p>Höfn is a fishing town on the southeastern coast of Iceland — three hours from anywhere, and shaped by the only weather it has.</p>
<p>I have returned in the same week of November every year since 2019, photographing a single peninsula and the light that visits it for forty minutes each afternoon.</p>
</div>
<dl class="spread__meta">
<div>
<span>Format</span>
<span class="v">Medium <em>format</em></span>
</div>
<div>
<span>Edition</span>
<span class="v">Of 12</span>
</div>
<div>
<span>First shown</span>
<span class="v"><em>Hverfisgata</em>, 2023</span>
</div>
<div>
<span>Print</span>
<span class="v">Hahnemühle Photo&nbsp;Rag</span>
</div>
</dl>
</aside>
<!-- Replace the four images below with real plates from the series -->
<div class="spread__plates reveal-stagger">
<figure class="plate plate--a">
<img src="https://images.unsplash.com/photo-1500534314209-a25ddb2bd429?auto=format&fit=crop&w=1600&q=85" alt="Plate I">
<figcaption class="plate__cap">Plate I</figcaption>
</figure>
<figure class="plate plate--b">
<img src="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?auto=format&fit=crop&w=1000&q=85" alt="Plate II">
<figcaption class="plate__cap">Plate II</figcaption>
</figure>
<figure class="plate plate--c">
<img src="https://images.unsplash.com/photo-1485470733090-0aae1788d5af?auto=format&fit=crop&w=1000&q=85" alt="Plate III">
<figcaption class="plate__cap">Plate III</figcaption>
</figure>
<figure class="plate plate--d">
<img src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?auto=format&fit=crop&w=1600&q=85" alt="Plate IV">
<figcaption class="plate__cap">Plate IV</figcaption>
</figure>
</div>
</div>
</div>
</section>
<!-- ======================================================
03 WORKS — Index of all series, magazine TOC
====================================================== -->
<section class="section" id="works" aria-labelledby="works-title">
<div class="section__inner">
<div class="section__head reveal">
<div>
<span class="eyebrow">
<span class="num">02</span>
<span class="bar"></span>
<span>Index of Works</span>
</span>
<h2 class="section__title" id="works-title">
Selected <em>series.</em>
</h2>
</div>
<div class="section__aside">
Six series<br>
2019&thinsp;&thinsp;2025<br>
Updated quarterly
</div>
</div>
<div class="toc reveal-stagger">
<a class="toc__row" href="#">
<span class="toc__num">01</span>
<span class="toc__title">Höfn, in November <em>light</em></span>
<span class="toc__loc">Iceland<span class="y">2019—2025</span></span>
<span class="toc__count">24 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1518562180175-34a163b1a9a6?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
<a class="toc__row" href="#">
<span class="toc__num">02</span>
<span class="toc__title">A field guide to <em>fog</em></span>
<span class="toc__loc">Lofoten, Norway<span class="y">2024</span></span>
<span class="toc__count">18 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1486870591958-9b9d0d1dda99?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
<a class="toc__row" href="#">
<span class="toc__num">03</span>
<span class="toc__title">Where the <em>cliffs</em> end</span>
<span class="toc__loc">Faroe Islands<span class="y">2023</span></span>
<span class="toc__count">21 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1495312040802-a929cd14a6ab?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
<a class="toc__row" href="#">
<span class="toc__num">04</span>
<span class="toc__title">Snow as a <em>verb</em></span>
<span class="toc__loc">Hokkaido, Japan<span class="y">2022—2023</span></span>
<span class="toc__count">16 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
<a class="toc__row" href="#">
<span class="toc__num">05</span>
<span class="toc__title">Long horizons, <em>brief</em> people</span>
<span class="toc__loc">Patagonia<span class="y">2021</span></span>
<span class="toc__count">14 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
<a class="toc__row" href="#">
<span class="toc__num">06</span>
<span class="toc__title">Coastlines I keep <em>returning</em> to</span>
<span class="toc__loc">Outer Hebrides<span class="y">2019—2020</span></span>
<span class="toc__count">19 plates</span>
<span class="toc__arrow"></span>
<span class="toc__thumb"><img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?auto=format&fit=crop&w=600&q=80" alt=""></span>
</a>
</div>
</div>
</section>
<!-- ======================================================
04 STUDIO — about / statement
====================================================== -->
<section class="section" id="studio" aria-labelledby="studio-title">
<div class="section__inner">
<div class="section__head reveal">
<div>
<span class="eyebrow">
<span class="num">03</span>
<span class="bar"></span>
<span>The Studio</span>
</span>
<h2 class="section__title" id="studio-title">
About <em>Mira.</em>
</h2>
</div>
<div class="section__aside">
Reykjavík · Iceland<br>
Working since 2014<br>
Solo practice
</div>
</div>
<div class="studio__grid">
<figure class="studio__portrait reveal">
<figcaption class="pcap">Portrait — Reykjavík, 2024</figcaption>
</figure>
<div class="studio__copy reveal">
<p class="studio__quote">
“I make photographs of places that hold their breath.”
</p>
<div class="studio__body">
<p>Mira Høst is a photographer working between Reykjavík and the wider North Atlantic. Her practice is rooted in slow looking — returning to the same coastlines through changing seasons, watching how light catalogues a place.</p>
<p>She works almost exclusively in available light, on medium format, and at a pace that the work itself dictates. A typical project takes three to seven years.</p>
<p>Her photographs have appeared in Cereal, Aperture, and the New York Times Magazine, and are held in private collections in Tokyo, London, and Oslo.</p>
</div>
<dl class="studio__cv">
<dt>Education</dt>
<dd>ICP, New York · <em>2012</em></dd>
<dt>Solo Shows</dt>
<dd>Hverfisgata Gallery (Reykjavík), Almine Rech Project Room (Brussels)</dd>
<dt>Editorial</dt>
<dd>Cereal · Aperture · NYT Magazine · Kinfolk · Monocle</dd>
<dt>Representation</dt>
<dd>Self-represented — direct enquiries only</dd>
</dl>
</div>
</div>
</div>
</section>
<!-- ======================================================
05 PRACTICE — services / commissions
====================================================== -->
<section class="section" id="practice" aria-labelledby="practice-title">
<div class="section__inner">
<div class="section__head reveal">
<div>
<span class="eyebrow">
<span class="num">04</span>
<span class="bar"></span>
<span>The Practice</span>
</span>
<h2 class="section__title" id="practice-title">
Working <em>together.</em>
</h2>
</div>
<div class="section__aside">
Three modes<br>
Of working<br>
Available 2026
</div>
</div>
<div class="practice__grid reveal-stagger">
<article class="practice__col">
<div class="practice__num">i</div>
<h3 class="practice__title"><em>Editorial</em><br>Commissions</h3>
<p class="practice__body">
Magazine and editorial assignments — location and studio, on medium format. I take on a small number of commissions each year and prefer briefs that allow time on the ground.
</p>
<ul class="practice__list">
<li>Min engagement <span class="v">3 days</span></li>
<li>Output <span class="v">Film + scan</span></li>
<li>Travel <span class="v">Worldwide</span></li>
</ul>
</article>
<article class="practice__col">
<div class="practice__num">ii</div>
<h3 class="practice__title">Brand &amp;<br><em>Long-form</em></h3>
<p class="practice__body">
Long-term partnerships with brands whose values align with quiet, considered work. Documentary campaigns, brand books, seasonal lookbooks — measured in years rather than weeks.
</p>
<ul class="practice__list">
<li>Min engagement <span class="v">2 quarters</span></li>
<li>Format <span class="v">Retainer</span></li>
<li>Spots / yr <span class="v">2</span></li>
</ul>
</article>
<article class="practice__col">
<div class="practice__num">iii</div>
<h3 class="practice__title">Prints &amp;<br><em>Editions</em></h3>
<p class="practice__body">
Limited archival pigment prints, signed and numbered. Released seasonally in editions of twelve, on Hahnemühle Photo Rag. Studio visits by appointment in Reykjavík.
</p>
<ul class="practice__list">
<li>Edition <span class="v">Of 12</span></li>
<li>Sizes <span class="v">A2 / A1 / A0</span></li>
<li>Next drop <span class="v"><em>Spring</em> 2026</span></li>
</ul>
</article>
</div>
</div>
</section>
<!-- ======================================================
06 JOURNAL — field notes
====================================================== -->
<section class="section" id="journal" aria-labelledby="journal-title">
<div class="section__inner">
<div class="section__head reveal">
<div>
<span class="eyebrow">
<span class="num">05</span>
<span class="bar"></span>
<span>Field Notes</span>
</span>
<h2 class="section__title" id="journal-title">
From the <em>journal.</em>
</h2>
</div>
<div class="section__aside">
Essays · Notes<br>
Process · Gear<br>
Roughly monthly
</div>
</div>
<div class="journal__grid reveal-stagger">
<a class="journal__entry" href="#">
<div class="journal__cover">
<img src="https://images.unsplash.com/photo-1486870591958-9b9d0d1dda99?auto=format&fit=crop&w=900&q=80" alt="">
</div>
<div class="journal__date">
<span>Nov 2025</span>
<span class="dot"></span>
<span>Essay · 8 min</span>
</div>
<h3 class="journal__title">On returning to <em>Höfn</em> for the seventh time</h3>
<p class="journal__excerpt">A peninsula I've photographed for seven Novembers running. Why repetition, in landscape work, is not stagnation — and what changes when nothing else does.</p>
</a>
<a class="journal__entry" href="#">
<div class="journal__cover">
<img src="https://images.unsplash.com/photo-1454496522488-7a8e488e8606?auto=format&fit=crop&w=900&q=80" alt="">
</div>
<div class="journal__date">
<span>Oct 2025</span>
<span class="dot"></span>
<span>Notes · 5 min</span>
</div>
<h3 class="journal__title">What a <em>Hasselblad</em> teaches a digital eye</h3>
<p class="journal__excerpt">A year on the 907X, and the small humilities of working with twelve frames a roll. Notes for anyone considering the switch — and a few for anyone considering not to.</p>
</a>
<a class="journal__entry" href="#">
<div class="journal__cover">
<img src="https://images.unsplash.com/photo-1495312040802-a929cd14a6ab?auto=format&fit=crop&w=900&q=80" alt="">
</div>
<div class="journal__date">
<span>Sep 2025</span>
<span class="dot"></span>
<span>Fieldnote · 3 min</span>
</div>
<h3 class="journal__title">Fieldnotes from the <em>Lofoten</em> ferry</h3>
<p class="journal__excerpt">Fragments written on the overnight crossing from Bodø — on weather, on solitude, and on the particular blue of an Arctic September.</p>
</a>
</div>
<div class="journal__more reveal">
<span>Further reading available in the journal archive.</span>
<a href="#">All entries <span aria-hidden="true"></span></a>
</div>
</div>
</section>
<!-- ======================================================
07 CORRESPONDENCE — dark contact section
====================================================== -->
<section class="section section--ink" id="contact" aria-labelledby="contact-title">
<div class="contact__inner">
<div class="section__head reveal" style="border-bottom: none; margin-bottom: 0; padding-bottom: 0;">
<div>
<span class="eyebrow">
<span class="num">06</span>
<span class="bar"></span>
<span>Correspondence</span>
</span>
</div>
<div class="section__aside">
Reykjavík<br>
Replies within<br>
five working days
</div>
</div>
<h2 class="contact__lede reveal" id="contact-title">
For commissions, prints, and the <em>slow correspondence</em> I'm always behind on.
</h2>
<div class="contact__rows reveal">
<div class="contact__block">
<span class="label">Direct</span>
<a class="value" href="mailto:hello@mirahost.studio">hello@mirahost.studio</a>
<p class="contact__sub">For commissions, prints, press requests, and quiet hellos. I read everything, even when I'm slow to reply.</p>
</div>
<div class="contact__block">
<span class="label">Studio</span>
<span class="value">Hverfisgata 12, 101 Reykjavík</span>
<p class="contact__sub">Studio visits by appointment only — usually Thursday afternoons when light is somewhere being interesting.</p>
</div>
<div class="contact__block" style="grid-column: 1 / -1;">
<span class="label">Elsewhere</span>
<div class="contact__social">
<a href="#">Instagram</a>
<a href="#">Are.na</a>
<a href="#">Substack</a>
<a href="#">Cargo</a>
</div>
</div>
</div>
</div>
</section>
<!-- ======================================================
08 COLOPHON — footer
====================================================== -->
<footer class="colophon" aria-label="Footer">
<div class="colophon__inner">
<div class="colophon__brand">
<span class="colophon__mark">M</span>
<span class="colophon__name">Mira <em>Høst</em><br>Studio</span>
<span class="colophon__tag">Photography · Est. 2019</span>
</div>
<div class="colophon__col">
<h4>Index</h4>
<ul>
<li><a href="#featured">Featured</a></li>
<li><a href="#works">Works</a></li>
<li><a href="#studio">Studio</a></li>
<li><a href="#journal">Journal</a></li>
</ul>
</div>
<div class="colophon__col">
<h4>Practice</h4>
<ul>
<li><a href="#practice">Editorial</a></li>
<li><a href="#practice">Brand</a></li>
<li><a href="#practice">Editions</a></li>
<li><a href="#contact">Enquire</a></li>
</ul>
</div>
<div class="colophon__col">
<h4>Elsewhere</h4>
<ul>
<li><a href="#">Instagram</a></li>
<li><a href="#">Are.na</a></li>
<li><a href="#">Substack</a></li>
<li><a href="#">Cargo</a></li>
</ul>
</div>
</div>
<div class="colophon__bottom">
<span>© MMXXV · Mira Høst Studio · All photographs by the artist</span>
<span>Set in <em>Instrument Serif</em> &amp; <em>Space Grotesk</em></span>
</div>
</footer>
<!-- ======================================================
SIDE RAILS — vertical issue / copyright marks
====================================================== -->
<div class="rail rail--left">
<span class="tick"></span>
<span>Issue 07 · MMXXV</span>
</div>
<div class="rail rail--right">
<span>© Mira Høst Studio</span>
<span class="tick"></span>
</div>
<script>
// The photograph is intentionally still — only the slow ken-burns plays.
const scrollToEl = (el) => {
if (!el) return;
const top = el.getBoundingClientRect().top + window.scrollY;
window.scrollTo({ top, behavior: 'smooth' });
};
document.querySelector('.hero__scroll').addEventListener('click', () => {
scrollToEl(document.getElementById('featured'))
|| window.scrollTo({ top: window.innerHeight, behavior: 'smooth' });
});
// Scroll-reveal: trigger fade-up once a section's head/grid enters view.
// Restrained — only the first appearance is animated, after that the
// page is calm and the photographs do the work.
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const reveals = document.querySelectorAll('.reveal, .reveal-stagger');
if (reduceMotion) {
reveals.forEach(el => el.classList.add('in'));
} else {
const io = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('in');
io.unobserve(entry.target);
}
});
}, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
reveals.forEach(el => io.observe(el));
}
// Smooth scroll for in-page nav links
document.querySelectorAll('a[href^="#"]').forEach(a => {
a.addEventListener('click', (e) => {
const id = a.getAttribute('href');
if (id.length > 1) {
const target = document.querySelector(id);
if (target) {
e.preventDefault();
scrollToEl(target);
}
}
});
});
</script>
</body>
</html>