:root{color-scheme:light;--pink:#ff2398;--header-height:144px;--logo-width:164px;--viewer-logo:#000;--placeholder:#f8f8f7;--backdrop:rgb(255 255 255 / .84);--ink:#171715;--muted:#6d6d68;--paper:#fff;--gutter:26px;--gallery-width:min(28vw,430px,48svh);font-family:Georgia,'Times New Roman',serif;color:var(--ink);background:var(--paper)}
/* Interface labels share the lowercase page-title style. */
h1,h2,nav,.edition,.footer,footer,.endnote,.contact-detail summary,.viewer button,.viewer-cursor-caption{text-transform:lowercase}
/* JS maintains an off-screen buffer in both directions using the real frames. */
html:has(.gallery-loop){overflow-anchor:none;scroll-behavior:auto}
.gallery-loop .gallery{overflow-anchor:none}
.gallery-loop:not(.index-mode) .endnote{display:none}
main#stills{position:relative}
.loop-edge{position:absolute;left:0;width:1px;height:1px;pointer-events:none}
.loop-edge-start{top:0}.loop-edge-end{bottom:0}
.index-mode .loop-edge{display:none}
/* Bound photograph repaints to their own boxes; index captions remain outside. */
.image-button{contain:layout paint}
.frame.nearby .image-button{will-change:transform}
*{box-sizing:border-box}html{scrollbar-gutter:stable}body{margin:0}button,a{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}a:hover,button:hover{color:var(--pink);text-decoration:none}button:disabled{opacity:.35;cursor:default;text-decoration:none}:focus-visible{outline:1px solid currentColor;outline-offset:6px}::selection{background:#dddcd6}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.skip-link{position:fixed;top:-100px;left:20px;background:var(--paper);padding:15px;z-index:100}.skip-link:focus{top:12px}
.masthead{position:fixed;inset:24px var(--gutter) auto;z-index:5;display:flex;justify-content:space-between;align-items:start;pointer-events:none}.masthead a{pointer-events:auto}.wordmark{font-size:32px;letter-spacing:-1.4px;line-height:1}.edition{font-size:12px;line-height:1.5;text-align:right}.navigation{font-size:14px;position:fixed;inset:50% var(--gutter) auto;transform:translateY(-50%);z-index:6;pointer-events:none;display:flex;justify-content:space-between}.nav-left,.nav-right{display:flex;align-items:center;gap:clamp(12px,2vw,36px);pointer-events:auto}.nav-right{gap:22px}.nav-item{white-space:nowrap;min-height:44px;display:inline-flex;align-items:center;gap:7px}.nav-right a{padding:14px 0}.email-link{font-size:13px}.footer{position:fixed;inset:auto var(--gutter) 22px;z-index:5;display:flex;justify-content:space-between;font-size:12px;pointer-events:none}.image-count{position:absolute;left:50%;transform:translateX(-50%);font-variant-numeric:tabular-nums;color:var(--muted)}
.gallery{width:var(--gallery-width);margin:0 auto;padding-top:18vh;padding-bottom:12vh;display:flex;flex-direction:column;gap:clamp(28px,5svh,60px)}.frame{margin:0;aspect-ratio:var(--ratio);width:100%;position:relative;scroll-margin-top:14vh}.image-button{display:block;width:100%;height:100%;transform-origin:center;cursor:zoom-in}.image-button:hover{text-decoration:none}.image-button picture,.image-button img{display:block;width:100%;height:auto}.image-button img{aspect-ratio:var(--ratio);object-fit:contain;background:var(--placeholder)}.endnote{text-align:center;font-size:13px;line-height:2.3;padding:0 20px 120px;display:flex;flex-direction:column;color:var(--muted)}.endnote a{color:var(--ink)}
body.index-mode .gallery{width:min(1160px,calc(100% - 80px));display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:65px 45px;padding-top:140px}body.index-mode .frame{aspect-ratio:var(--ratio);align-self:center}body.index-mode .image-button{transform:none!important;will-change:auto}body.index-mode .image-count{display:none}body.index-mode .footer{background:var(--paper);padding-top:12px}body.index-mode .frame::after{content:attr(data-number);display:block;font-size:12px;color:var(--muted);margin-top:10px;text-align:center}
dialog{color:var(--ink);border:0;margin:0;padding:0;max-width:none;max-height:none;background:var(--paper)}dialog::backdrop{background:var(--backdrop)}body:has(dialog[open]){overflow:hidden}.close{display:flex;gap:18px;align-items:center;min-height:44px;font-size:14px}.contact-dialog{inset:0 0 0 auto;width:min(650px,100%);height:100dvh;overflow:auto;border-left:1px solid #eee;padding:24px 40px}.contact-dialog>.close{margin-left:auto}.contact-content{padding:clamp(36px,12vh,120px) 0 40px;max-width:460px;margin:auto}.eyebrow{font-size:13px;color:var(--muted);margin:0 0 35px}.contact-content h2{font-size:clamp(45px,6vw,72px);font-weight:400;letter-spacing:-2.5px;margin:0 0 30px}.bio{font-size:25px;line-height:1.45;max-width:380px}.contact-content dl{margin:48px 0}.contact-content dl>div{margin-top:26px}.contact-content dt{font-size:13px;color:var(--muted);margin-bottom:7px}.contact-content dd{margin:0;font-size:18px;overflow-wrap:anywhere}.copyright{font-size:12px;color:var(--muted)}
.viewer{inset:0;width:100%;height:100dvh;overflow:hidden;padding:16px var(--gutter);display:none;grid-template-rows:48px minmax(0,1fr) 54px}.viewer[open]{display:grid}.viewer-top,.viewer-bottom{display:flex;align-items:center;justify-content:space-between;gap:20px;font-size:14px}.viewer-top>span{font-size:22px;letter-spacing:-.6px}.viewer-bottom button{min-height:44px;min-width:70px}.viewer-stage{display:flex;align-items:center;justify-content:center;min-height:0;padding:12px 0}.viewer-stage picture{display:contents}.viewer-stage img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}.viewer-bottom #viewer-count{font-size:13px;color:var(--muted);font-variant-numeric:tabular-nums}
@media(min-width:701px) and (max-width:1100px){.nav-left,.nav-right{flex-direction:column;align-items:flex-start;gap:0}.nav-right{align-items:flex-end}.nav-item{min-height:36px}.nav-right a{padding:10px 0}.email-link{font-size:12px}}
@media(max-width:700px){:root{--gutter:18px;--gallery-width:82vw}.masthead{top:20px}.wordmark{font-size:29px}.edition{font-size:12px}.navigation{top:66px;transform:none;display:block;background:var(--paper);padding:0 0 10px;margin:0 calc(-1 * var(--gutter));padding-inline:var(--gutter)}.nav-left{justify-content:space-between;gap:8px}.nav-item{min-height:40px;font-size:14px}.nav-right{display:none}.gallery{padding-top:145px;gap:48px;padding-bottom:50px}.footer{inset:auto 0 0;background:var(--paper);padding:14px 18px;font-size:12px}.image-count{display:none}.endnote{padding-bottom:100px}.contact-dialog{padding:14px 24px}.contact-content{padding-top:45px}.bio{font-size:23px}body.index-mode .gallery{width:calc(100% - 36px);grid-template-columns:repeat(2,minmax(0,1fr));gap:32px 18px;padding-top:145px}body.index-mode .navigation{inset:66px var(--gutter) auto}.viewer{padding:12px 16px}.viewer-top>span{font-size:22px}.viewer-stage{padding:8px 0}}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.image-button{transform:none!important;will-change:auto}}

/* Keep the identity clear as photographs pass beneath the mobile header. */
@media(max-width:700px){.masthead{inset:0 0 auto;padding:20px var(--gutter) 12px;background:var(--paper);height:66px}.footer{gap:12px}.footer>span:last-child{text-align:right}}
.image-count{left:220px;transform:none}

/* Shared theme tokens; mobile navigation keeps its readable surface. */
:root[data-theme="dark"]{color-scheme:dark;--ink:#f3f2ee;--muted:#aaa9a3;--paper:#000;--placeholder:#111;--backdrop:rgb(0 0 0 / .88)}
body,dialog,.masthead,.navigation,.footer{transition:background-color 180ms ease,color 180ms ease}
a,button{transition:color 140ms ease}
.masthead{inset:0 0 auto;height:var(--header-height);padding:18px var(--gutter);background:var(--paper);z-index:7;align-items:center;pointer-events:auto}
.wordmark{display:block;width:var(--logo-width);line-height:0;color:var(--pink);flex-shrink:0;transform-origin:left center}
.wordmark svg{display:block;width:100%;height:auto}
.header-tools{display:flex;align-items:center;gap:30px}
.theme-toggle{display:flex;align-items:center;gap:9px;min-height:44px;font-size:14px;white-space:nowrap}
.theme-icon{width:13px;height:13px;display:block;border:1px solid currentColor;border-radius:50%;background:linear-gradient(90deg,currentColor 50%,transparent 50%)}
body.index-mode .gallery{padding-top:164px}
/* Keep photographs at a steady scale throughout native scrolling. */
.viewer{grid-template-rows:64px minmax(0,1fr) 54px}
.viewer::backdrop{background:transparent}
.viewer .viewer-wordmark{width:var(--logo-width);letter-spacing:normal;color:#000;line-height:0}

.contact-dialog{border-color:var(--placeholder)}
@media(max-width:700px){
 :root{--header-height:84px;--logo-width:136px}
 .masthead{height:var(--header-height);padding:16px var(--gutter)}
 .header-tools .edition{display:none}
 .header-tools{gap:0}
 .theme-toggle{font-size:13px;gap:7px}
 .navigation{top:var(--header-height)}
 .gallery,body.index-mode .gallery{padding-top:160px}
 body.index-mode .navigation{inset:var(--header-height) var(--gutter) auto}
}
@media(prefers-reduced-motion:reduce){
 *,*::before,*::after{animation:none!important;transition:none!important}
 .frame.nearby .image-button{will-change:auto;transform:none!important}
}

.viewer-stage{--viewer-image-height:calc(100dvh - 174px)}
.viewer-stage picture{display:block;width:min(100%,calc(var(--viewer-image-height) * var(--photo-ratio)));aspect-ratio:var(--photo-ratio);max-height:100%}
.viewer-stage img{display:block;width:100%;height:100%;object-fit:contain}
@media(max-width:700px){.viewer-stage{--viewer-image-height:calc(100dvh - 158px)}}

/* A single opaque photograph moves above a separately fading modal surface. */
.viewer{background:transparent;transition:none}
.viewer-surface{position:absolute;inset:0;background:var(--paper);pointer-events:none}
.viewer-top,.viewer-bottom,.viewer-stage{position:relative;z-index:1}
.viewer-source picture{visibility:hidden}
.viewer-active .masthead .wordmark{visibility:hidden}

/* Icon-only mode switch sits immediately beside Contact. */
.nav-left{column-gap:clamp(10px,1.3vw,24px)}
.theme-toggle{width:32px;min-width:32px;height:44px;min-height:44px;display:inline-flex;align-items:center;justify-content:center;padding:0;flex-shrink:0}
.theme-icon{width:12px;height:12px;transition:transform 300ms cubic-bezier(.25,1,.5,1);transform:rotate(0deg)}
:root[data-theme="dark"] .theme-icon{transform:rotate(180deg)}
@media(min-width:701px) and (max-width:1100px){
 .nav-left{display:grid;grid-template-columns:max-content 32px;gap:0 8px}
 .nav-left>#stills-link,.nav-left>#index-toggle{grid-column:1 / -1}
 .nav-left>[data-contact]{grid-column:1}
 .nav-left>.theme-toggle{grid-column:2;min-height:36px;height:36px}
}
@media(max-width:700px){.nav-left{gap:8px}.nav-left>.theme-toggle{margin-left:-2px}.header-tools .edition{display:block}}
/* Images use the entire viewport; controls float above instead of reserving rows. */
.viewer,.viewer[open]{padding:0;display:none;grid-template-rows:none}
.viewer[open]{display:block}
.viewer-stage{position:absolute;inset:0;padding:0;--viewer-image-height:100dvh}
.viewer-top,.viewer-bottom{position:absolute;left:var(--gutter);right:var(--gutter);z-index:2;pointer-events:none}
.viewer-top{top:16px}
.viewer-bottom{bottom:12px}
.viewer-top>* , .viewer-bottom>*{pointer-events:auto}
.viewer-top .close,.viewer-bottom button,.viewer-bottom #viewer-count{background:var(--paper);color:var(--ink);padding:0 12px;min-height:44px;display:flex;align-items:center;justify-content:center}
.viewer-top .close:hover,.viewer-bottom button:hover{color:var(--pink)}
.viewer .viewer-wordmark{background:transparent;padding:0;color:var(--ink)}
@media(prefers-reduced-motion:reduce){.theme-icon{transition:none}}

/* Let desktop photography pass behind the identity and navigation. */
@media(min-width:701px){
 .masthead,body.index-mode .navigation,body.index-mode .footer{background:transparent}
}
.masthead{pointer-events:none}
.masthead a,.masthead button{pointer-events:auto}
.viewer-stage{cursor:zoom-out}
/* Retain the image layer while open so closing does not have to allocate it again. */
.viewer[open] .viewer-stage img{will-change:transform}
.viewer-moving .viewer-surface,.viewer-moving .viewer-bottom,.viewer-moving .viewer-top .close{will-change:opacity}

/* Native scroll snapping: gallery frames settle at the viewport centre. */
html:has(body:not(.index-mode):not(.gallery-loop)){scroll-snap-type:y mandatory}
body:not(.index-mode) .gallery{
 padding-top:max(0px,calc((100dvh - var(--gallery-width) * var(--first-height-factor)) / 2));
 padding-bottom:max(0px,calc((100dvh - var(--gallery-width) * var(--last-height-factor)) / 2));
}
body:not(.index-mode) .frame{scroll-snap-align:center;scroll-margin:0}
body:not(.index-mode) .endnote{scroll-snap-align:end}

/* White source text + difference renders black on white and white on black.
   Blend the overlay groups themselves so their stacking contexts do not
   isolate their text from the photographs behind them. */
:root{--blend-hover:#00dc67}
:root[data-theme="dark"]{--blend-hover:var(--pink)}
.header-tools{position:fixed;top:0;right:var(--gutter);height:var(--header-height);z-index:8;pointer-events:none}
.header-tools,.navigation,.footer,.viewer-top,.viewer-bottom,.endnote,.contact-content,.contact-dialog>.close{
 mix-blend-mode:difference;color:#fff;background:transparent;
}
body.index-mode .footer{background:transparent}
.image-count,.endnote a,.viewer-top .close,.viewer-bottom button,.viewer-bottom #viewer-count,
.contact-content .eyebrow,.contact-content dt,.contact-content .copyright{color:#fff;background:transparent}
.navigation a:hover,.navigation button:hover,.endnote a:hover,.viewer-top .close:hover,.viewer-bottom button:hover,
.contact-content a:hover,.contact-dialog>.close:hover{color:var(--blend-hover)}
body.index-mode .frame::after{color:#fff;mix-blend-mode:difference}

/* Keep the image count at the same screen coordinates in both views. */
.viewer-bottom #viewer-count{
 position:fixed;left:calc(var(--gutter) + 220px);bottom:22px;
 display:block;min-height:0;padding:0;font-size:12px;line-height:normal;
 color:#fff;background:transparent;
}
.viewer-active .footer .image-count{visibility:hidden}
@media(max-width:700px){
 .footer .image-count{display:block;left:calc(var(--gutter) + 122px);bottom:14px}
 .viewer-bottom #viewer-count{left:calc(var(--gutter) + 122px);bottom:14px}
}

.viewer-cursor-caption{position:fixed;left:0;top:0;z-index:4;pointer-events:none;font-size:12px;line-height:1.2;color:#fff;mix-blend-mode:difference;white-space:nowrap}
.viewer-cursor-caption[hidden]{display:none}
.viewer-stage[data-edge]{cursor:pointer}
@media(hover:none){.viewer-cursor-caption{display:none}}

/* Programmatic modal focus must not leave rings after a pointer interaction. */
:root:not([data-input="keyboard"]) :focus{outline:none}
dialog:focus{outline:none}

/* One opening composition: photograph first, then the surrounding details.
   Only the entrance animates the image's inner picture. */
:root{--ease-out-quart:cubic-bezier(.25,1,.5,1)}
@media(prefers-reduced-motion:no-preference){
 html[data-intro] #image-01 picture{opacity:0;transform:scale(.90);transform-origin:center;will-change:transform,opacity}
 html[data-intro] .frame:not(#image-01),
 html[data-intro] .masthead .wordmark,html[data-intro] .header-tools .edition,
 html[data-intro] .nav-left>*,html[data-intro] .nav-right>*,html[data-intro] .footer>*,html[data-intro] .endnote{opacity:0}
 html[data-intro="playing"] #image-01 picture{animation:intro-photo-scale 1000ms var(--ease-out-quart) both,intro-photo-fade 1000ms linear both}
 html[data-intro="playing"] .masthead .wordmark,
 html[data-intro="playing"] .header-tools .edition,
 html[data-intro="playing"] .nav-left>*,html[data-intro="playing"] .nav-right>*,
 html[data-intro="playing"] .footer>*{animation:intro-detail 300ms var(--ease-out-quart) both;animation-delay:var(--intro-delay);transform-origin:center top;will-change:transform,opacity}
 .masthead .wordmark{--intro-delay:1000ms}
 .header-tools .edition{--intro-delay:1040ms}
 .nav-left>:nth-child(1){--intro-delay:1080ms}
 .nav-left>:nth-child(2){--intro-delay:1120ms}
 .nav-left>:nth-child(3){--intro-delay:1160ms}
 .nav-left>:nth-child(4){--intro-delay:1200ms}
 .nav-right>*{--intro-delay:1240ms}
 .footer>*{--intro-delay:1280ms}
 html[data-intro="playing"] .frame:not(#image-01),html[data-intro="playing"] .endnote{opacity:1}
 html[data-intro="playing"] .frame.nearby:not(#image-01){animation:intro-fade 300ms var(--ease-out-quart) 1280ms both}
 @keyframes intro-photo-scale{from{transform:scale(.90)}to{transform:scale(1)}}
 @keyframes intro-photo-fade{from{opacity:0}to{opacity:1}}
 @keyframes intro-detail{from{opacity:0;transform:translate3d(0,6px,0) scaleY(1.5)}to{opacity:1;transform:translate3d(0,0,0) scaleY(1)}}
 @keyframes intro-fade{from{opacity:0}to{opacity:1}}
}

/* A stationary logo: same geometry as the masthead, colour-only handoff. */
:root[data-theme="dark"]{--viewer-logo:#fff}
.viewer-brand-slot{position:absolute;inset:0 0 auto;height:var(--header-height);padding:18px var(--gutter);display:flex;align-items:center;pointer-events:none;z-index:3}
.viewer .viewer-wordmark{width:var(--logo-width);color:var(--viewer-logo);background:transparent;padding:0;mix-blend-mode:normal}
.viewer-top{justify-content:flex-end}
@media(max-width:700px){.viewer-brand-slot{padding:16px var(--gutter)}}

/* Desktop controls share the gallery's corner anchors and text baselines. */
@media(min-width:701px){
 .viewer-top{top:0;height:var(--header-height);align-items:center}
 .viewer-top .close{position:relative;display:block;min-height:36px;padding:0;font-size:12px;line-height:1.5;text-align:right}
 .viewer-bottom{bottom:22px;font-size:12px;line-height:normal;align-items:baseline}
 .viewer-bottom button{position:relative;display:block;min-width:0;min-height:0;padding:0;font-size:12px;line-height:normal}
 .viewer-bottom #previous{text-align:left}
 .viewer-bottom #next{text-align:right}
 .viewer-top .close::before,.viewer-bottom button::before{content:"";position:absolute;inset:-14px -12px}
}

/* Keep the identity transparent at every viewport size. */
.masthead{background:transparent}

/* Hover ink is rendered outside difference groups so brand pink stays exact. */
.solid-hover-source{color:transparent!important}
.solid-hover-ink{position:fixed!important;z-index:30;pointer-events:none!important;mix-blend-mode:normal!important;color:var(--pink)!important;opacity:1!important;transform:none!important;transition:none!important;animation:none!important;margin:0!important;outline:none!important;background:transparent!important}
.navigation a:hover,.navigation button:hover,.endnote a:hover,.viewer-top .close:hover,.viewer-bottom button:hover,
.contact-content a:hover,.contact-dialog>.close:hover{color:#fff}

/* Minimal Contact view, anchored below its navigation label. */
.contact-panel{position:fixed;z-index:7;margin:0;padding:0;overflow:auto;overscroll-behavior:contain;font-size:14px;line-height:1.6;color:var(--ink);background:transparent}
.contact-panel[hidden]{display:none}
.contact-panel p{margin:0 0 22px;font:inherit}
.contact-links{display:flex;flex-direction:column;align-items:flex-start;gap:7px}
.contact-panel a{font:inherit;color:inherit;overflow-wrap:anywhere;max-width:100%}
.contact-panel a:hover{color:inherit}
.contact-line{transform-origin:center top}
body.contact-mode{overflow:hidden}
body.contact-mode .footer .image-count{visibility:hidden}
body.contact-mode .endnote{visibility:hidden}
body.contact-gallery-hidden .gallery{visibility:hidden}

@media(min-width:701px){
 .viewer-top .close{align-self:flex-start;margin-top:calc((var(--header-height) - 36px) / 2);min-height:0;height:18px;line-height:18px}
}

/* Mobile opening composition: tighter header, with a safe image height. */
@media(max-width:700px){
 :root{--header-height:128px;--mobile-nav-top:120px;--mobile-image-top:178px}
 .navigation,body.index-mode .navigation{top:var(--mobile-nav-top)}
 .gallery{--gallery-width:min(76vw,max(120px,calc((100svh - 300px) / var(--first-height-factor))));gap:clamp(28px,5svh,44px)}
 body:not(.index-mode) .gallery{padding-top:max(var(--mobile-image-top),calc((100svh - var(--gallery-width) * var(--first-height-factor)) / 2))}
 body.index-mode .gallery{padding-top:140px}
}

/* Compact credentials keep the first Contact view quiet. */
.contact-credentials{margin-top:22px;display:flex;flex-direction:column;gap:12px}
.contact-detail summary{display:flex;align-items:baseline;gap:12px;list-style:none;cursor:pointer;font:inherit}
.contact-detail summary::-webkit-details-marker{display:none}
.contact-detail summary::marker{content:""}
.disclosure-indicator::before{content:"+"}
.contact-detail[open] .disclosure-indicator::before{content:"−"}
.contact-panel .contact-detail-body{margin:12px 0 6px;font:inherit}
.credentials-list{padding:0;list-style:none;display:flex;flex-direction:column;gap:10px}
.credentials-list li{display:grid;grid-template-columns:4ch 1fr;gap:14px}
@media(prefers-reduced-motion:no-preference){.contact-detail[open] .contact-detail-body{animation:intro-fade 180ms var(--ease-out-quart) both}}

/* Outgoing labels leave immediately, before gallery text shows through. */
.viewer-closing .viewer-top,.viewer-closing .viewer-bottom,.viewer-closing .solid-hover-ink,.viewer-closing .viewer-cursor-caption{visibility:hidden}

/* The counter never fades with the controls: both views hand it over in place. */
.viewer-count{position:fixed;z-index:2;left:calc(var(--gutter) + 220px);bottom:22px;display:block;padding:0;margin:0;font-size:12px;line-height:normal;font-variant-numeric:tabular-nums;color:#fff;background:transparent;mix-blend-mode:difference;pointer-events:none}
@media(max-width:700px){.viewer-count{left:calc(var(--gutter) + 122px);bottom:14px}}
