/* Variant A, "The Workshop". Pale sage-grey surfaces under the House's overcast,
   graphite type, cobalt only for what you are pointing at or about to press.
   Radius rule: one small radius (--r) for everything; only the phone screenshots keep a
   device corner. Surfaces are solid; nothing is frosted or translucent. */
@font-face{font-family:Schibsted;src:url(schibsted-grotesk-latin-wght-normal.woff2) format("woff2");font-weight:400 900;font-display:swap}

/* Each colour is written once for day and night; data-theme (set in the page head and by
   the lamp) picks the scheme, and without JavaScript the device setting does. */
:root{
  color-scheme:light dark;
  --day:light-dark(#e9ece8,#171b20);--surface:light-dark(#f4f6f3,#20252c);--line:light-dark(#cdd2cb,#333a43);
  --ink:light-dark(#1f252c,#e7eaee);--muted:light-dark(#56606a,#a4adb7);
  --cobalt:light-dark(#2f4fd0,#8ea2ff);--on-cobalt:light-dark(#f4f6f3,#171b20);
  --panel:light-dark(#D9C4A6,#4A3828);--on-panel:light-dark(#2B2118,#F2E8DA); /* About panels and the Contact block: light latte by day, walnut at night */
  --shadow:0 24px 60px -32px light-dark(rgba(40,52,44,.45),rgba(0,0,0,.7));
  --r:8px;--lift:0 18px 34px -22px light-dark(rgba(40,52,44,.5),rgba(0,0,0,.75));--max:1360px;--pad:clamp(20px,4vw,56px);
  --ease:cubic-bezier(.22,1,.36,1); /* one ease-out for every interaction: quick start, soft landing */
  --img-line:light-dark(oklch(0 0 0/.1),oklch(1 0 0/.1)); /* image edge: pure black or white, never a tint */
}
:root[data-theme=light]{color-scheme:light}
:root[data-theme=dark]{color-scheme:dark}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent}
body{margin:0;background:var(--day);color:var(--ink);font:400 1.0625rem/1.6 Schibsted,system-ui,sans-serif}
@media (prefers-reduced-motion:no-preference){body,.contact,.case-facts dl,.object-view{transition:background-color .6s ease,color .6s ease}}
img{max-width:100%;height:auto;display:block}
a{color:inherit;text-underline-offset:.22em;text-decoration-thickness:1px;transition:color .2s var(--ease),text-decoration-color .2s var(--ease),text-decoration-thickness .2s var(--ease)}
:focus-visible{outline:3px solid var(--cobalt);outline-offset:3px}
h1,h2,h3{margin:0;font-weight:800;letter-spacing:-.03em;line-height:1.05;text-wrap:balance}
p{margin:0;text-wrap:pretty}
[hidden]{display:none!important}

.button{display:inline-flex;align-items:center;min-height:48px;padding:12px 22px;border-radius:var(--r);border:0;background:var(--ink);color:var(--day);
  font:700 1rem/1 Schibsted,sans-serif;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .2s var(--ease),color .2s var(--ease),transform .15s var(--ease)}
.button:active:not(:disabled){transform:scale(.96)}
.button-small{min-height:44px;padding:8px 16px;font-size:.9375rem}
/* Plain links keep their look; padding and min-height give them a thumb-sized hit area. */
.text-link,.site-footer a,:is(.contact-actions,.enquiry-actions,.resume-actions) a:not(.button),.index-page>p>a,.case-head p>a{display:inline-flex;align-items:center;min-height:44px}
.text-link{font-weight:700}

.site-nav{max-width:var(--max);margin:0 auto;padding:18px var(--pad);display:flex;align-items:center;gap:clamp(12px,2.4vw,28px);position:relative;z-index:3}
.brand{font-weight:800;font-size:1.125rem;text-decoration:none;letter-spacing:-.02em;white-space:nowrap}
.site-nav nav,.nav-actions{display:flex;align-items:center;gap:clamp(12px,2.4vw,28px)}
.site-nav nav{margin-left:auto}
.site-nav nav a:not(.button){text-decoration:none;font-weight:600;transition:color .2s var(--ease)}
/* Night is a switch: pressed means the lights are off. */
.theme-toggle{min-height:44px;padding:6px 14px;border:0;border-radius:var(--r);background:none;box-shadow:inset 0 0 0 1.5px var(--line);color:var(--ink);font:600 .9375rem Schibsted,sans-serif;cursor:pointer;white-space:nowrap}
.theme-toggle{display:inline-flex;align-items:center;gap:8px}
.theme-toggle::before{content:"";width:9px;height:9px;border-radius:50%;box-shadow:inset 0 0 0 1.5px currentColor}
.theme-toggle[aria-pressed=true]::before{background:#ffc68a;box-shadow:0 0 0 3px color-mix(in srgb,#ffc68a 30%,transparent)}
.no-js .theme-toggle{display:none}
.cta-short{display:none}
/* Phones: name, lamp switch and a short contact button on the first row; the links get
   their own row underneath, so all of them stay visible. */
@media (max-width:640px){
  .site-nav{display:grid;grid-template-columns:1fr auto;row-gap:2px;padding-bottom:6px}
  .site-nav nav{grid-row:2;grid-column:1/-1;margin-left:0;gap:24px}
  .site-nav nav a{padding:9px 0}
  .nav-actions{gap:16px}
  .cta-long{display:none}.cta-short{display:inline}.theme-toggle{padding:6px 10px;font-size:.875rem}
}

main{max-width:var(--max);margin:0 auto;padding:0 var(--pad)}
.skip{position:absolute;left:12px;top:-60px;z-index:10;padding:10px 16px;border-radius:var(--r);background:var(--ink);color:var(--day);font-weight:700;text-decoration:none}
.skip:focus{top:12px}
::selection{background:color-mix(in srgb,var(--cobalt) 28%,transparent)}
input,textarea,select{caret-color:var(--cobalt)}
input,select{accent-color:var(--cobalt)}

/* Sky: the hero is one scene. Two light layers fade with the lamp switch:
   daylight from the window side by day, a warm lamp glow and moonlight at night. */
.sky{position:relative;isolation:isolate;overflow:clip;background:linear-gradient(light-dark(#f2f4ef,#0f141d),var(--day))}
.sky::before,.sky::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;transition:opacity .7s ease;mask-image:linear-gradient(#000 55%,transparent)}
.sky::before{background:radial-gradient(70% 80% at 12% 18%,rgba(255,238,205,.75),transparent 62%),radial-gradient(60% 60% at 90% 90%,rgba(214,226,236,.55),transparent 70%)}
.sky::after{opacity:0;background:radial-gradient(38% 46% at 72% 52%,rgba(255,178,104,.2),transparent 70%),radial-gradient(50% 60% at 10% 10%,rgba(126,146,255,.12),transparent 70%)}
:root[data-theme=dark] .sky::before{opacity:0}
:root[data-theme=dark] .sky::after{opacity:1}
@media (prefers-reduced-motion:reduce){.sky::before,.sky::after{transition:none}}

.bench{position:relative;display:flex;align-items:center;min-height:calc(100svh - 76px)}
.bench-stage{position:absolute;inset:0}
.bench-stage canvas{position:absolute;inset:0;width:100%;height:100%}
.bench-poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.bench-poster-phone,.bench-stage.is-live .bench-poster{display:none}
[data-room=phone] .bench-poster-phone{display:block}
[data-room=phone] .bench-poster-wide{display:none}
/* A veil keeps the copy readable where the back wall of the room reaches behind it. */
.bench::after{content:"";position:absolute;inset:-90px 0 0;pointer-events:none;background:radial-gradient(62% 85% at 6% 55%,color-mix(in srgb,var(--day) 88%,transparent) 30%,transparent 100%);transition:opacity .4s}
.bench-copy{position:relative;z-index:1;width:100%;max-width:var(--max);margin:0 auto;padding:clamp(24px,5vh,64px) var(--pad);pointer-events:none;transition:opacity .35s ease,visibility .35s}
.bench-panel{pointer-events:auto;max-width:31rem}
.bench.is-touring .bench-copy,.bench.is-touring::after{opacity:0;visibility:hidden}
.bench-copy h1{font-size:clamp(2.2rem,3.6vw,3.4rem);max-width:15ch}
.bench-panel>p:not(.actions){margin-top:20px;font-size:1.1875rem;color:var(--muted);max-width:40ch}
.actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px 24px;margin-top:28px}
.bench-index{margin-top:clamp(28px,5vh,48px)}
.bench-index p{font-size:.9375rem;color:var(--muted)}
.bench-index ul{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-wrap:wrap;gap:8px}
.bench-index a{display:inline-flex;align-items:center;min-height:44px;padding:6px 14px;border-radius:var(--r);background:var(--surface);box-shadow:inset 0 0 0 1.5px var(--line);text-decoration:none;font-weight:600;font-size:.9375rem;transition:box-shadow .2s var(--ease),color .2s var(--ease),transform .15s var(--ease)}
.bench-index a[aria-current]{box-shadow:inset 0 0 0 2px var(--cobalt);color:var(--cobalt)}


/* Stacked hero: narrow screens, and any portrait screen (a phone in desktop mode reports a
   desktop width, but the full-bleed hero needs a landscape stage). room.js uses the same query. */
@media (max-width:899px),(orientation:portrait){
  .bench{display:block;min-height:0}
  .bench::after{display:none}
  .bench-stage{position:relative;height:35svh;min-height:240px}
  .bench-copy{padding-top:8px;padding-bottom:48px}
}

section>h2,.about h2,.work-door h2{font-size:clamp(1.9rem,3.4vw,2.75rem)}

/* What I can do: a stop per service (its Room's doorway), then each of its projects told in stops at its object */
.work{padding:clamp(64px,9vw,120px) 0 0}
.stops{margin-top:28px}
.stop{position:relative;display:grid;grid-template-columns:minmax(200px,1fr) minmax(0,2.6fr);gap:20px clamp(24px,4vw,56px);padding:clamp(24px,3vw,36px) 0;border-top:1px solid var(--line)}
.stop-panel{display:contents} /* the head and the cards (or note) are the grid's two columns; [data-room] makes the panel a box again */
.stop>*{min-width:0} /* a grid item's min-content would widen the column past a phone screen */
.stop-head h3{font-size:1.5rem;letter-spacing:-.02em}
.stop-head p{margin-top:8px;color:var(--muted);max-width:34ch}
.stop-note{align-self:center;max-width:58ch;font-size:1.125rem}
.stop-action{margin-top:20px}
.stop-note a{font-weight:700}
.stop-all{margin-top:8px}
/* A Room's stops: a project told at its object (page.cjs projectStops). Without the House each is a plain section with its screenshots. */
.stop-head h4{margin:0;font-size:1.375rem;letter-spacing:-.02em}
.stop-project .stop-note{align-self:start;font-size:1.0625rem}
.stop-project .stop-note>*+*{margin-top:12px}
.stop-kind{font-weight:600}
.stop-list{margin:0;padding-left:1.25em;display:grid;gap:6px}
.stop-small{font-size:.9375rem;color:var(--muted)}
.stop-shots{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;margin-top:20px}
.stop-shots img{display:block;width:100%;height:auto;border-radius:var(--r);outline:1px solid var(--img-line);outline-offset:-1px}
@media (max-width:640px){.stop-shots{grid-template-columns:1fr}}
@media (max-width:900px){.stop{grid-template-columns:1fr}}

/* /projects/: an uneven grid of every object render */
.work-grid{list-style:none;margin:32px 0 0;padding:0;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:20px}
.work-grid li{grid-column:span 2}
.work-procura,.work-pims,.work-map,.work-yen{grid-column:span 3!important}
.work-grid a{display:grid;align-content:start;gap:14px;height:100%;padding:0 0 18px;border-radius:var(--r);background:var(--surface);text-decoration:none;transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
.work-img{position:relative;display:block;overflow:hidden;border-radius:var(--r) var(--r) 0 0} /* the image runs to the card's top and side edges, so its corners share the card's radius */
.work-img::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px var(--img-line);pointer-events:none} /* the hairline stays on the frame while the image zooms */
.work-img img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover}
.work-grid :is(.work-procura,.work-pims,.work-map,.work-yen) .work-img img{aspect-ratio:16/10}
.work-text{display:grid;gap:2px;padding:0 18px}
.work-object{font-size:.875rem;color:var(--muted);font-weight:600}
.work-text strong{font-size:1.375rem;letter-spacing:-.02em;transition:color .2s var(--ease)}
.work-text span:last-child{color:var(--muted)}
@media (max-width:1000px){.work-grid li{grid-column:span 3}.work-yen{grid-column:1/-1!important}}
@media (max-width:620px){.work-grid{grid-template-columns:1fr}.work-grid li,.work-yen{grid-column:auto!important}}

/* Object renders exist for day and night; the theme shows one. A hidden lazy image is never fetched. */
.thumb-night{display:none!important}
:root[data-theme=dark] .thumb-night{display:block!important}
:root[data-theme=dark] .thumb-day{display:none!important}

/* About: the colonnade. Without JavaScript every chapter is open, side by side (stacked on phones).
   With it, one column is open and wide; hover or focus moves the cobalt panel up into the next one
   while the old one leaves upward (about.js sets .is-open and .is-leaving). */
.about{padding:clamp(64px,9vw,120px) 0 clamp(24px,4vw,48px)}
@media (max-width:640px){.about{padding-bottom:48px}} /* with Contact's top margin, clear air between the two sections on a phone */
.colonnade{list-style:none;margin:32px 0 0;padding:0;display:flex;border-block:1px solid var(--line)}
.chapter{flex:1 1 0;min-width:0;display:flex;flex-direction:column}
.chapter+.chapter{border-left:1px solid var(--line)}
.chapter-tab{display:flex;gap:10px;align-items:center;width:100%;min-height:52px;padding:0 16px;border:0;background:var(--surface);color:var(--ink);font:700 .8125rem/1.2 Schibsted,sans-serif;letter-spacing:.08em;text-transform:uppercase;text-align:left;cursor:pointer;box-shadow:inset 0 -3px 0 transparent;transition:box-shadow .3s var(--ease)}
.chapter-tab span{color:var(--muted);font-variant-numeric:tabular-nums}
.chapter-view{position:relative;overflow:hidden;height:clamp(380px,56svh,520px);background:var(--surface)}
.chapter-view img{position:absolute;inset:0;width:100%;height:100%;aspect-ratio:auto;object-fit:cover;border-radius:0}
.chapter-view .portrait{object-position:50% 22%}
.chapter-panel{position:absolute;inset:auto 0 0;padding:24px 24px 28px;background:var(--panel);color:var(--on-panel)}
.chapter-panel h3{font-size:clamp(1.5rem,2.4vw,2.25rem)}
.chapter-panel p{margin-top:12px}
.js .chapter-tab:focus-visible{outline-offset:-3px}
.js .chapter.is-open .chapter-tab{box-shadow:inset 0 -3px 0 var(--cobalt)}
.js .chapter-panel{width:max(100%,24rem)} /* keeps its wrap while the column grows */
.js .chapter:not(.is-open){flex-grow:1}
.js .chapter.is-open{flex-grow:3.2}
.js .chapter:not(.is-open) .chapter-panel{transform:translateY(100%)}
.js .chapter.is-leaving .chapter-panel{transform:translateY(-100%)}
.js .chapter.is-open .chapter-panel{transform:none}
@media (prefers-reduced-motion:no-preference){
  .js .chapter{transition:flex-grow .6s cubic-bezier(.2,.8,.2,1)}
  .js :is(.is-open,.is-leaving) .chapter-panel{transition:transform .6s cubic-bezier(.2,.8,.2,1)}
}
/* Desktop, Background Chapter wide enough (open, or the no-JS columns): the whole 4:5 portrait on the left,
   the caption beside it, never over it. Narrower (closed) it stays a cropped cover with the caption over it. */
@media (min-width:900px) and (orientation:landscape){
  .chapter:has(.portrait){container-type:inline-size}
  @container (min-width:560px){
    .chapter-view:has(.portrait){display:flex}
    .chapter-view .portrait{position:static;flex:none;width:auto;aspect-ratio:4/5}
    .chapter-view .portrait+.chapter-panel{position:static;flex:1;width:auto;display:flex;flex-direction:column;justify-content:flex-end}
  }
}
@media (max-width:899px),(orientation:portrait){
  .colonnade{flex-direction:column}
  .chapter+.chapter{border-left:0;border-top:1px solid var(--line)}
  .chapter-tab{min-height:56px}
  /* The image first, the caption below it, never over it. 3:2 shows the same 387px band of the
     portrait at any phone width: hair to collar, so the whole face stays in. */
  .chapter-view{height:auto;interpolate-size:allow-keywords}
  .chapter-view img{position:static;display:block;height:auto;aspect-ratio:3/2;max-height:520px}
  .chapter-view .portrait{object-position:50% 14%}
  .chapter-panel{position:static}
  .js .chapter .chapter-panel{width:100%;transform:none!important}
  .js .chapter-tab::after{content:"+";margin-left:auto;font-size:1.25rem}
  .js .chapter.is-open .chapter-tab::after{content:"\2212"}
  .js .chapter:not(.is-open) .chapter-view{height:0}
  .js .chapter,.js .chapter.is-open{flex-grow:0}
  @media (prefers-reduced-motion:no-preference){.js .chapter-view{transition:height .5s cubic-bezier(.2,.8,.2,1)}}
}
.hiring{color:var(--muted)}
.hiring a{color:var(--ink);font-weight:700;display:inline-block;padding-block:10px;margin-block:-10px}
.contact{margin:clamp(24px,4vw,48px) 0 clamp(48px,7vw,96px);padding:clamp(28px,5vw,64px);border-radius:var(--r);background:var(--surface)}
.contact h2{font-size:clamp(1.9rem,3.6vw,3rem);max-width:16ch}
.contact>p{margin-top:14px;color:var(--muted);max-width:52ch}
.contact .contact-actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px 24px;margin-top:28px;color:var(--ink);font-weight:700}
/* Home contact: a cobalt block with the address set large, no form. */
.contact-block{background:var(--panel);color:var(--on-panel)}
.contact-lede>p{margin-top:14px;max-width:52ch}
.contact-block .hiring a{color:var(--on-panel)}
.contact-lede .contact-mail{margin-top:20px}
.contact-block :focus-visible{outline-color:var(--on-panel)}
.contact-mail{display:inline-block;font-size:clamp(1.5rem,4.2vw,2.5rem);font-weight:800;letter-spacing:-.03em;line-height:1.15;overflow-wrap:anywhere}
@media (min-width:900px) and (orientation:landscape){.contact-block{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);gap:0 clamp(32px,6vw,96px);grid-template-rows:auto 1fr;align-items:start}.contact-block>h2,.contact-lede{grid-column:1}.contact-reach{grid-column:2;grid-row:1/span 2}.contact-reach>:is(.enquiry,.enquiry-sent){margin-top:0}.contact-lede .contact-mail{font-size:clamp(1.5rem,2.4vw,2.125rem)}}
/* Enquiry form: a few choices and one line, plus a name and email, sent to the portfolio API. */
.contact-block{--muted:light-dark(#4a3c2e,#d6c8b4);--flag:light-dark(#8a1f18,#ff8a7e)}
.enquiry{display:grid;gap:22px;margin-top:28px;max-width:760px}
.enquiry fieldset{border:0;margin:0;padding:0;min-width:0}
.enquiry legend,.enquiry .field label{font-weight:700;margin-bottom:10px;padding:0}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chip{position:relative;display:inline-flex;align-items:center;min-height:44px;padding:8px 16px;border-radius:var(--r);box-shadow:inset 0 0 0 1.5px var(--on-panel);font-weight:600;font-size:.9375rem;cursor:pointer;transition:box-shadow .2s var(--ease),color .2s var(--ease),background-color .2s var(--ease),transform .15s var(--ease)}
.chip input{position:absolute;opacity:0;inset:0;margin:0;cursor:pointer}
.chip:has(input:checked){background:var(--cobalt);color:var(--on-cobalt);box-shadow:none}
.chip:has(input:focus-visible){outline:3px solid var(--on-panel);outline-offset:3px}
.enquiry .field{display:grid;gap:6px;align-content:start}
.enquiry .field label{margin:0}
.enquiry .field :is(input,textarea){font:inherit;color:var(--ink);background:var(--day);border:1.5px solid var(--muted);border-radius:var(--r);padding:12px 14px;min-height:48px;width:100%;box-sizing:border-box}
.enquiry textarea{resize:vertical;min-height:96px}
.enquiry .field [aria-invalid]{border-color:var(--flag)}
.enquiry-who{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,15rem),1fr));gap:16px}
.enquiry-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.field-help{font-size:.875rem;color:var(--muted)}
.field-error{color:var(--flag);font-size:.9375rem;font-weight:700}
.enquiry-actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px 24px;font-weight:700}
.enquiry-actions .button:disabled{opacity:.6;cursor:progress}
.enquiry-failed{display:grid;gap:12px}
.enquiry-failed>p:not(.field-error):not(.enquiry-copy){color:var(--muted)}
.enquiry-failed a:not(.button){color:var(--ink);font-weight:700}
.enquiry-failed textarea{font:inherit;font-size:.9375rem;color:var(--ink);background:var(--day);border:1.5px solid var(--muted);border-radius:var(--r);padding:12px 14px;resize:vertical}
.enquiry-copy{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;font-weight:700;color:var(--ink)}
.enquiry-sent{margin-top:28px;max-width:760px;font-size:clamp(1.25rem,2.6vw,1.75rem);font-weight:700;line-height:1.3;overflow-wrap:anywhere}
.enquiry-sent:focus{outline:0}
.site-footer{max-width:var(--max);margin:0 auto;padding:24px var(--pad) 40px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;color:var(--muted);font-size:.9375rem;border-top:1px solid var(--line)}
.site-footer p:last-child{display:flex;flex-wrap:wrap;gap:0 20px}

/* Case pages */
.case-head{display:grid;grid-template-columns:minmax(0,1fr) minmax(220px,420px);gap:clamp(24px,4vw,64px);align-items:center;padding:clamp(20px,4vw,48px) 0 clamp(32px,5vw,64px)}
.case-head h1{font-size:clamp(2.6rem,6vw,4.75rem);margin-top:18px}
.case-head .kind{color:var(--muted);font-weight:600;margin-top:8px}
.case-lede{margin-top:16px;font-size:1.25rem;max-width:44ch}
.case-proof{margin-top:14px;font-weight:700;max-width:44ch}
.object-view{position:relative;aspect-ratio:4/3;width:100%;border-radius:var(--r);background:var(--surface);overflow:hidden}
.object-view img{width:100%;height:100%;object-fit:cover}
.object-view canvas{position:absolute;inset:0;width:100%;height:100%;cursor:ew-resize;touch-action:pan-y}
.object-view.is-live img{visibility:hidden}
.object-view+.object-hint{margin-top:8px;font-size:.875rem;color:var(--muted);visibility:hidden}
.object-view.is-live+.object-hint{visibility:visible}
@media (max-width:760px){.case-head{grid-template-columns:1fr}}
.gallery,.outline{margin:0}
.gallery-tabs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:16px}
.gallery-tabs button{min-height:44px;padding:6px 14px;border-radius:var(--r);border:0;background:none;box-shadow:inset 0 0 0 1.5px var(--line);color:var(--ink);font:600 .9375rem Schibsted,sans-serif;cursor:pointer}
.gallery-tabs button[aria-selected=true]{box-shadow:inset 0 0 0 2px var(--cobalt);color:var(--cobalt)}
.no-js .gallery-panel[hidden]{display:block}
.gallery-panel img{border-radius:var(--r);box-shadow:var(--shadow)}
.gallery-panel.is-phone img{width:min(320px,80%);border-radius:28px}
.gallery-panel p,.gallery figcaption{margin-top:12px;color:var(--muted);font-size:.9375rem}
.outline{max-width:720px;padding:clamp(20px,3vw,32px);border-radius:var(--r);background:var(--surface)}
.outline figcaption{color:var(--muted);font-weight:600;margin-bottom:12px}
.outline ol,.steps{margin:0;padding-left:24px;display:grid;gap:8px}
.case-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:clamp(28px,5vw,72px);margin-top:clamp(48px,7vw,96px);align-items:start}
@media (max-width:860px){.case-grid{grid-template-columns:1fr}}
.case-body{display:grid;gap:36px;max-width:64ch}
.case-body h2{font-size:1.5rem;margin-bottom:10px}
.case-facts dl{margin:0;display:grid;gap:20px;padding:22px;border-radius:var(--r);background:var(--surface)}
.case-facts dt{font-weight:700;font-size:.875rem;color:var(--muted)}
.case-facts dd{margin:4px 0 0}
.case-facts ul{margin:0;padding-left:18px}
.case-facts a{overflow-wrap:anywhere}
.next{margin:clamp(56px,8vw,112px) 0 clamp(24px,4vw,48px)}
.next a{display:inline-grid;grid-template-columns:120px auto;gap:20px;align-items:center;text-decoration:none}
.next img{border-radius:var(--r)}
.next span{display:grid;color:var(--muted);font-weight:600}
.next strong{font-size:clamp(1.75rem,4vw,2.75rem);color:var(--ink);letter-spacing:-.03em}

/* render-stills.cjs: the stage alone, filling the viewport */
.still body>*:not(.tour),.still .site-nav,.still .bench-copy,.still .bench::after,.still .sky::before,.still .sky::after{display:none}
.still .sky{background:var(--day)}
.still .bench{display:block;min-height:0}
.still .bench-stage{position:fixed;inset:0;height:100%;margin:0}

/* Try it: the playable demos on case pages. Cobalt is the approval stamp (ink on paper);
   --flag marks real problems only (low stock, a count that does not balance, a failed upload). */
:root{--flag:light-dark(#b3302a,#ff8a7e);--flag-wash:light-dark(#f6e3e1,#3a2228)}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.try{margin:0 0 clamp(48px,7vw,88px);max-width:820px}
.try>h2{font-size:clamp(1.6rem,2.6vw,2.1rem)}
.try>p{margin:6px 0 18px;color:var(--muted);max-width:62ch}
.sheet{position:relative;background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow);padding:clamp(18px,2.6vw,28px);overflow:hidden}
.sheet:has(.stamp.is-on){padding-bottom:80px}
.sheet-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px}
.sheet-head h3{margin:0;font-size:1.125rem;font-weight:800;letter-spacing:-.02em}
.tag{flex:none;font-size:.8125rem;font-weight:600;color:var(--muted);box-shadow:inset 0 0 0 1.5px var(--line);border-radius:var(--r);padding:2px 10px}
.hint{margin-top:4px;color:var(--muted);font-size:.9375rem;max-width:62ch}
.sheet-foot{display:flex;flex-wrap:wrap;align-items:center;gap:12px 16px;margin-top:18px}
.no-js .sheet-foot,.no-js .field-row button,.no-js .stepper button{visibility:hidden}
.link-button{background:none;border:0;padding:10px 4px;min-height:44px;color:var(--ink);font:600 1rem Schibsted,sans-serif;text-decoration:underline;text-underline-offset:.2em;cursor:pointer}
.sheet table{width:100%;border-collapse:collapse;margin-top:14px;font-size:.9375rem}
.sheet td,.sheet output{font-variant-numeric:tabular-nums} /* not on names: tabular punctuation opens a gap before commas */
.sheet th,.sheet td{text-align:left;padding:10px 8px;vertical-align:middle}
.sheet thead th{font-weight:600;color:var(--muted);font-size:.8125rem;border-bottom:1px solid var(--line)}
.sheet tbody tr+tr{border-top:1px solid color-mix(in srgb,var(--line) 60%,transparent)}
.sheet tbody th{font-weight:500}
@media (max-width:560px){.wide-only{display:none}.sheet th,.sheet td{padding:8px 4px}}
.stepper{display:inline-flex;align-items:center;border-radius:var(--r);background:var(--day);box-shadow:inset 0 0 0 1.5px var(--line)}
.stepper button{width:40px;height:40px;border:0;background:none;color:var(--ink);font:700 1.125rem/1 Schibsted,sans-serif;cursor:pointer;border-radius:var(--r)}
.stepper output{min-width:3ch;text-align:center;font-weight:700}
tr.is-low th::after{content:"Below reorder point";display:block;font-size:.8125rem;font-weight:700;color:var(--flag)}
tr.is-low .stepper{box-shadow:inset 0 0 0 2px var(--flag)}
.result{margin-top:16px;padding:14px 16px;border-radius:var(--r);background:var(--day);font-size:.9375rem}
.result p{margin:0}.result ul{margin:2px 0 10px;padding-left:18px}
.stamp{position:absolute;right:clamp(16px,3vw,28px);bottom:clamp(16px,3vw,24px);pointer-events:none;color:var(--cobalt);border:3px solid currentColor;border-radius:var(--r);padding:6px 14px;font:800 1.125rem/1 Schibsted,sans-serif;transform:rotate(-7deg);opacity:0}
.stamp:empty{display:none}
/* A rubber stamp lands with a small overshoot, once, on the visitor's own action. */
.stamp.is-on{opacity:.92;animation:stamp .38s cubic-bezier(.2,1.4,.4,1) both}
@keyframes stamp{from{opacity:0;transform:rotate(-7deg) scale(1.6)}to{opacity:.92;transform:rotate(-7deg) scale(1)}}
@media (prefers-reduced-motion:reduce){.stamp.is-on{animation:none}}
.track,.pipeline{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin:18px 0 0;padding:0}
.track{counter-reset:s}
.track li,.pipeline li{padding:10px 12px;border-radius:var(--r);box-shadow:inset 0 0 0 1.5px var(--line);color:var(--muted);font-weight:600;font-size:.9375rem;transition:background-color .2s,color .2s,box-shadow .2s}
.track li{counter-increment:s}
.track li::before{content:counter(s)". "}
.track li.is-done{box-shadow:inset 0 0 0 2px var(--ink);color:var(--ink);background:var(--day)}
.pipeline li.is-active{box-shadow:inset 0 0 0 2px var(--cobalt);color:var(--cobalt)}
.pipeline li.is-done{box-shadow:inset 0 0 0 2px var(--ink);color:var(--ink)}
.pipeline li.is-fail{box-shadow:inset 0 0 0 2px var(--flag);color:var(--flag);background:var(--flag-wash)}
@media (max-width:560px){.track,.pipeline{grid-template-columns:1fr 1fr}}
.log{margin:16px 0 0;padding-left:18px;color:var(--muted);font-size:.9375rem}
.log:empty{display:none}
.count{margin-top:16px;display:grid;gap:8px}
.count label,.reason label{font-weight:600;font-size:.9375rem}
.field-row{display:flex;gap:10px;flex-wrap:wrap}
.sheet input,.sheet select{font:inherit;color:var(--ink);background:var(--day);border:1.5px solid var(--muted);border-radius:var(--r);min-height:44px;padding:8px 12px}
.sheet input[type=number]{width:7ch}
.sheet input[aria-invalid=true]{border-color:var(--flag)}
.field-error{color:var(--flag);font-size:.9375rem;font-weight:700}
.reason{display:grid;gap:8px;margin-top:6px;justify-items:start}
.reason select{max-width:100%}
.ledger caption{text-align:left;font-weight:600;font-size:.8125rem;color:var(--muted);padding-top:6px}
.ledger tr.is-flag td{color:var(--flag);font-weight:700}
.agent-steps{margin:16px 0 0;padding-left:22px;display:grid;gap:6px}
.agent-steps li{color:var(--muted)}
.agent-steps li.is-active{color:var(--ink);font-weight:700}
.agent-steps li.is-done{color:var(--ink)}
.agent-steps li.is-done::after{content:" done";color:var(--muted);font-weight:400}
.draft{margin-top:16px;padding:14px 16px;border-radius:var(--r);background:var(--day)}
.draft p{margin:0}
.draft-label{font-weight:700;font-size:.875rem;color:var(--muted);margin-bottom:4px!important}
.check{display:inline-flex;align-items:center;gap:8px;font-size:.9375rem;min-height:44px;cursor:pointer}
.check input{width:20px;min-height:20px;accent-color:var(--cobalt)}
.channels{display:flex;gap:6px;margin-top:16px;flex-wrap:wrap}
.channels button{min-height:40px;padding:6px 14px;border:0;border-radius:var(--r);background:none;box-shadow:inset 0 0 0 1.5px var(--line);color:var(--ink);font:600 .9375rem Schibsted,sans-serif;cursor:pointer}
.channels button[aria-pressed=true]{background:var(--ink);color:var(--day);box-shadow:none}
.conv{margin-top:12px;font-size:.875rem;color:var(--muted)}
.thread{list-style:none;margin:10px 0 14px;padding:0;display:grid;gap:8px;max-height:260px;overflow:auto}
.thread li{padding:8px 12px;border-radius:var(--r);background:var(--day);font-size:.9375rem;max-width:88%}
.thread li.is-agent{justify-self:end;background:color-mix(in srgb,var(--cobalt) 14%,var(--surface))}
.thread span{display:block;font-size:.75rem;font-weight:700;color:var(--muted)}
.field-row input:not([type]){flex:1;min-width:0}

/* /projects/ and /resume/ (main keeps its side padding) */
.index-page,.resume-page{padding-top:clamp(20px,4vw,48px)}
.index-page h1,.resume-page h1{font-size:clamp(2.6rem,6vw,4.5rem);margin-top:18px}
.index-intro{margin-top:14px;font-size:1.1875rem;color:var(--muted);max-width:56ch}
.index-page .work-grid{margin-top:40px}
.resume-actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px 24px;margin-top:24px;font-weight:700}

/* The résumé reader: still a white page of paper (it is the PDF's text), set in the site's
   type and colours. Section numbers and capitalised labels from the print layout are dropped. */
.resume-page .resume-paper{margin-bottom:clamp(48px,7vw,96px);box-shadow:var(--shadow);border-radius:var(--r);color:#1f252c}
.resume-page .resume-paper,.resume-page .resume-paper *,.resume-page .resume-paper .mono{font-family:Schibsted,system-ui,sans-serif;letter-spacing:normal}
.resume-page .resume-paper .secno{display:none}
.resume-page .resume-paper :is(.sectitle,.kind,.sklabel){display:inline-block;letter-spacing:0;text-transform:lowercase}
.resume-page .resume-paper :is(.sectitle,.kind,.sklabel)::first-letter{text-transform:uppercase}
.resume-page .resume-paper .sectitle{font-size:1.125rem;font-weight:800;letter-spacing:-.02em}
.resume-page .resume-paper :is(.certline b,.sklabel),.resume-page .resume-paper td.sysname .kind{color:#2f4fd0}
/* Status lines start with a separator dot, so they stay all lower case. */
.resume-page .resume-paper td.sysname .kind{display:block;font-weight:600;letter-spacing:0}
.resume-page .resume-paper :is(p,li,td.jt,td.sk,.profile,.sysdesc,.jdesc){max-width:62ch}
.resume-page .resume-paper td.sysname .kind::first-letter{text-transform:none}

/* Hover only where there is a pointer that hovers, so a tap on a phone leaves nothing lit. */
@media (hover:hover){
  .button:hover{background:var(--cobalt);color:var(--on-cobalt)}
  .chip:hover{box-shadow:inset 0 0 0 2px var(--on-panel)}
  .site-nav nav a:not(.button):hover{color:var(--cobalt)}
  .theme-toggle:hover{box-shadow:inset 0 0 0 2px var(--cobalt);color:var(--cobalt)}
  .bench-index a:hover{box-shadow:inset 0 0 0 2px var(--cobalt);color:var(--cobalt)}
  .work-grid a:hover{transform:translateY(-3px);box-shadow:var(--lift)}
  .site-footer a:hover,.hiring a:hover,.stop-note a:hover,.text-link:hover,.case-head p>a:hover,.index-page>p>a:hover{color:var(--cobalt)}
  .contact-block a:not(.button):hover{text-decoration-thickness:2px}
  .enquiry .field :is(input,textarea):hover,.enquiry-failed textarea:hover{border-color:var(--on-panel)}
  .work-grid a:hover strong{color:var(--cobalt)}
  @media (pointer:fine) and (prefers-reduced-motion:no-preference){
    .work-img img{transition:transform .55s var(--ease),opacity .5s var(--ease)}
    .work-grid a:hover .work-img img{transform:scale(1.03)}
  }
  .next a:hover strong{color:var(--cobalt)}
  .stepper button:hover{color:var(--cobalt)}
}

/* Wordmark: the name across the foot of every page. */
.wordmark{max-width:var(--max);margin:clamp(40px,6vw,80px) auto clamp(14px,2.5vw,28px);padding:0 var(--pad);font-weight:800;font-size:clamp(3.5rem,14.5vw,13.5rem);line-height:.9;letter-spacing:-.055em;white-space:nowrap;overflow:clip}
.w{display:inline-block;overflow:clip;padding-bottom:.08em;margin-bottom:-.08em;vertical-align:top}
.w>span{display:inline-block}

/* Below the room the page keeps moving with the scroll, the way the room does: section titles
   sweep in large and settle while their words rise, the stops stack like a deck (wide
   screens), the portrait unrolls and
   drifts, the contact panel rises in and the name rises letter by letter at the foot. Every
   animation is tied to scroll position (no JavaScript), so it runs backwards on the way up and an
   anchor jump lands on the finished state. Reduced motion gets the page as it was; so do browsers
   without scroll timelines, apart from the deck, which is plain sticky positioning. */
@media (prefers-reduced-motion:no-preference){
  /* The deck: each stop pins near the top and the next slides over it. Wide, tall screens only,
     where a stop fits on screen; every stop is as tall as the tallest so each covers the last. */
  @media (min-width:901px) and (min-height:700px){
    .stop{position:sticky;top:clamp(16px,6vh,64px);min-height:min(480px,80vh);align-content:start;background:var(--day);
      box-shadow:0 -30px 44px -38px light-dark(rgba(40,52,44,.55),rgba(0,0,0,.85))}
  }
}
@supports (animation-timeline:view()){@media (prefers-reduced-motion:no-preference){
  main{overflow-x:clip} /* titles start wider than the page */
  .rise{view-timeline:--rise;transform-origin:0 100%;animation:sweep linear both;animation-timeline:view();animation-range:entry 0% cover 45%}
  @keyframes sweep{from{transform:translateY(40%) scale(1.9)}to{transform:none}}
  /* On a phone a title at 1.9x is wider than the screen, so it entered as clipped letters. */
  @media (max-width:640px){@keyframes sweep{from{transform:translateY(40%) scale(1.2)}to{transform:none}}}
  .rise .w>span{animation:rise linear both;animation-timeline:--rise;animation-range:cover calc(2% + var(--i) * 1.5%) cover calc(30% + var(--i) * 1.5%)}
  @keyframes rise{from{transform:translateY(110%) rotate(6deg)}to{transform:none}}
  .wordmark{view-timeline:--mark}
  .wordmark .w>span{animation:rise linear both;animation-timeline:--mark;animation-range:entry calc(var(--i) * 4%) entry calc(45% + var(--i) * 4%)}

  .stop{border-top-color:transparent}
  .stop::before{content:"";position:absolute;inset:-1px 0 auto;height:1px;background:var(--line);transform-origin:left;animation:draw linear both;animation-timeline:view();animation-range:entry 0% cover 20%}
  @keyframes draw{from{transform:scaleX(0)}to{transform:none}}
  .stop-head,.stop-note,.contact>p,.contact-lede>p{animation:lift linear both;animation-timeline:view();animation-range:entry 0% cover 22%}
  @keyframes lift{from{opacity:0;transform:translateY(110px)}to{opacity:1;transform:none}}
  .contact{animation:settle linear both;animation-timeline:view();animation-range:entry 0% entry 60%}
  @keyframes settle{from{border-radius:48px;transform:translateY(80px)}to{border-radius:var(--r);transform:none}}
}}

/* The House is the page. While room.js runs it keeps html[data-room] set ("wide" or "phone"; the
   head script sets it before first paint). The canvas is one fixed full-screen background and the
   page is a run of steps, about a screen tall each, with its panel at the bottom (phone) or to one side
   (wide) and the House showing in the rest: the hero across the lake, the sliding glass, a doorway per service, the balcony
   for teaching, then the goodbye. About and Contact follow it as plain page. Scroll snapping (mandatory) rests every step in place and room.js keys the camera to that same position,
   so the panel and the view it names arrive together.
   Without the attribute (no JavaScript, reduced motion, no WebGL, ?still= renders) none of this applies
   and the page keeps its static layout. */
[data-room]{--nav-h:76px;--edge:max(var(--pad),calc((100% - var(--max)) / 2 + var(--pad)));--scrim-a:94%;--scrim-hold:75%;--scrim-fade:24px;--scrim-c:color-mix(in srgb,var(--day) var(--scrim-a),transparent);--scrim:linear-gradient(to top,transparent,var(--scrim-c) var(--scrim-fade),var(--scrim-c) var(--scrim-hold),transparent);scroll-snap-type:y mandatory}
/* Fades to nothing below the step's foot (the scrim runs --scrim-fade into the next step), so one step's meets the next with no hard edge. Phones show more room: lighter, and a project's scrim is solid for less of the screen;
   a stop's caption is taller than that and has small muted text, so its scrim is sized to its text and denser. */
@media (max-width:640px){[data-room]{--nav-h:100px}}
[data-room=phone]{--scrim-a:86%;--scrim-hold:30%;--scrim-fade:64px}
[data-room] :is(.bench-copy,[data-stop],.about,.contact){scroll-snap-align:start}
[data-room] .site-footer{scroll-snap-align:end} /* mandatory snapping must still let the page reach its foot */
/* Only the panels take pointer events, so a tap between them reaches the room. */
[data-room] :is(.tour,.sky,.bench,.bench-copy,main,.work,.stop){pointer-events:none}
[data-room] :is(canvas,.bench-panel,.site-nav,.work-door h2,.stop-panel,.about,.contact,.wordmark,.site-footer){pointer-events:auto}
/* The bar sits in the House, not over it: no ground of its own, only a mist that thins down from the screen's top edge,
   enough to read the links over the darkest of the room. */
[data-room] .site-nav{position:fixed;inset:0 0 auto;z-index:7;max-width:none;margin:0;background:none;transition:transform .3s ease;
  padding-inline:max(var(--pad),calc((100% - var(--max)) / 2 + var(--pad)))}
[data-room] .site-nav::before{content:"";position:absolute;inset:0 0 -40px;z-index:-1;pointer-events:none;
  background:linear-gradient(color-mix(in srgb,var(--day) 84%,transparent),color-mix(in srgb,var(--day) 66%,transparent) 55%,transparent)}
/* Scrolling down tucks the bar away so it does not eat the room; scrolling up brings it back. */
[data-room].nav-away .site-nav:not(:focus-within){transform:translateY(-100%)}
[data-room] .sky{position:static;isolation:auto;overflow:visible;background:none}
[data-room] .sky::before,[data-room] .sky::after{display:none}
[data-room] .bench{display:block;min-height:0}
[data-room] .bench-stage{position:fixed;inset:0 0 auto;height:100lvh;z-index:0;
  background:radial-gradient(70% 80% at 12% 18%,light-dark(rgba(255,238,205,.75),rgba(126,146,255,.12)),transparent 62%),
    radial-gradient(60% 60% at 90% 90%,light-dark(rgba(214,226,236,.55),rgba(255,178,104,.14)),transparent 70%),
    linear-gradient(light-dark(#f2f4ef,#0f141d),var(--day))}
[data-room=wide] .bench::after{display:block;inset:-90px 0 auto;height:calc(100svh + 90px)}

/* Hero: the headline panel. Wide: copy on the left over a veil. Phone: a solid card at the bottom. */
[data-room] .bench-copy{z-index:1;min-height:100svh;display:flex;flex-direction:column;justify-content:center;align-items:flex-start;padding-top:calc(var(--nav-h) + clamp(8px,3vh,40px))}
[data-room=phone] .bench-copy{justify-content:flex-end;padding:var(--nav-h) 12px 12px}
[data-room=phone] .bench-panel{max-width:none;width:100%;background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow);padding:16px 18px 18px}
[data-room=phone] .bench-copy h1{font-size:1.95rem}
[data-room=phone] .bench-panel>p:not(.actions){margin-top:10px;font-size:1rem}
[data-room=phone] .actions{margin-top:16px}
[data-room=phone] .bench-index{display:none}

/* Services: "What I can do for you" is a small label that stays under the bar while the stops pass;
   each stop has its caption on the House while the camera shows what it names, over a soft scrim (--scrim) that keeps
   the text readable. */
[data-room] main{position:relative;z-index:1;max-width:none;padding:0}
[data-room] .work{padding:0}
/* The doorway: "What I can do for you" is the stop where the camera stands at the sliding glass, its heading a panel like a stop's. */
[data-room] .work-door{min-height:100svh;display:flex;align-items:flex-end;padding:0 var(--edge) 12px}
[data-room] .work-door h2{width:100%;margin:0;padding:16px 18px;font-size:1.5rem;letter-spacing:-.02em;background:var(--surface);border-radius:var(--r);box-shadow:var(--shadow)}
[data-room=wide] .work-door{padding-bottom:clamp(24px,6svh,72px)}
[data-room=wide] .work-door h2{width:min(30rem,42vw)}
[data-room] .stops{margin:0}
[data-room] .stop{position:relative;top:auto;min-height:100svh;display:flex;flex-direction:column;justify-content:flex-end;padding:0 var(--edge) 12px;
  background:none;box-shadow:none;border:0;grid-template-columns:1fr}
[data-room] .stop::before{display:none}
[data-room] .stop-panel{display:grid;gap:12px;padding:0 18px}
[data-room] .stop-head :is(h3,h4){font-size:1.375rem}
[data-room] .stop-shots{display:none} /* the House shows the screens on the project's own object */
[data-room] .stop-project .stop-note{font-size:1rem}
[data-room] .stop-head p{margin-top:6px;max-width:none}
[data-room] .stop-note{font-size:1rem}
[data-room] .stop-action{margin-top:14px}

/* The room is the animation now: the captions do not also fly in. */
[data-room] :is(.rise,.rise .w>span,.stop-head,.stop-note,.contact>p,.contact){animation:none}
[data-room] :is(.wordmark,.site-footer){position:relative;z-index:1;max-width:none;margin:0;background:var(--surface);border:0;
  padding-inline:max(var(--pad),calc((100% - var(--max)) / 2 + var(--pad)))}
/* The goodbye: the name fills the screen's foot over the room, the camera pulls back here. */
[data-room] .wordmark{padding-top:calc(100svh - 1em);padding-bottom:clamp(8px,1.5vw,20px);background:none}
/* The scrim is a layer behind each caption (z -1 inside its own stacking context): a screen-high fade for
   the captions, a shorter one under the goodbye's name so the room still shows above it. */
[data-room] :is(.stop,.wordmark){isolation:isolate}
[data-room] .stop::after{content:"";position:absolute;inset:0 0 calc(var(--scrim-fade) * -1);z-index:-1;background:var(--scrim)}
/* Wide: the stop's captions sit at the foot of the left side and its objects on the right, so the scrim lies behind the
   caption only, feathered at its top and right, and the room shows everywhere else. */
[data-room=wide] .stop::after{display:none}
[data-room=wide] .stop-panel{position:relative}
[data-room=wide] .stop-panel::before{content:"";position:absolute;inset:-64px -72px calc(-1 * clamp(24px,6svh,72px)) -100vw;z-index:-1;background:color-mix(in srgb,var(--day) 85%,transparent);
  mask:linear-gradient(to right,#000 calc(100% - 120px),transparent),linear-gradient(transparent,#000 64px);mask-composite:intersect}
[data-room=wide] .stop-head p{color:color-mix(in srgb,var(--muted) 70%,var(--ink))} /* the scrim lets the room through, so the muted line darkens a little to stay at 4.5:1 */
[data-room=phone] .stop::after{display:none}
[data-room=phone] .stop-panel{position:relative;--stop-c:color-mix(in srgb,var(--day) 94%,transparent)}
[data-room=phone] .stop-panel::before{content:"";position:absolute;inset:-24px calc(-18px - var(--edge)) calc(-12px - var(--scrim-fade));z-index:-1;background:linear-gradient(transparent,var(--stop-c) 24px,var(--stop-c) calc(100% - var(--scrim-fade)),transparent)}
[data-room] .wordmark::after{content:"";position:absolute;inset:auto 0 0;height:32%;z-index:-1;background:linear-gradient(to top,color-mix(in srgb,var(--day) 92%,transparent) 80%,transparent)}
/* About and Contact are plain page below the goodbye, on a solid ground so the room does not show through. */
/* Each starts its own stop: it is at least a screen tall, rests with its top at the screen's top (the bar covers its
   own top padding, so nothing of the section above shows behind or beside it), and cannot be skipped over. lvh, not svh:
   with a phone's address bar hidden the section must still fill the screen, so the next one never peeks in below. */
[data-room] :is(.about,.contact){min-height:100lvh;scroll-snap-stop:always}
[data-room] .about{background:var(--day);padding:max(clamp(64px,9vw,120px),calc(var(--nav-h) + 16px)) var(--edge) clamp(48px,7vw,96px)}
[data-room] .contact{margin:0;padding:calc(var(--nav-h) + clamp(28px,5vw,64px)) var(--edge) clamp(28px,5vw,64px);border-radius:0;box-shadow:none}

/* Wide: captions sit at the foot of their stop, the room fills the rest. */
[data-room=wide] .stop{justify-content:flex-end;padding:0 var(--edge) clamp(24px,6svh,72px)}
[data-room=wide] .stop-panel{width:min(30rem,42vw)}

/* Polish: small details that make the page feel finished. Every transition names its properties and
   shares one ease (--ease); motion that plays by itself is behind no-preference. */
.contact-mail{text-wrap:balance}
:is(li,dd,figcaption,.hint,.field-help){text-wrap:pretty}
/* Image edges and the gallery, the thumbnails and the next-project card: a hairline keeps pale renders from melting into pale cards. */
.next img,.gallery-panel img,.object-view img{outline:1px solid var(--img-line);outline-offset:-1px}
.enquiry .field :is(input,textarea),.enquiry-failed textarea{transition:border-color .2s var(--ease)}
.enquiry .field :is(input,textarea):focus,.enquiry-failed textarea:focus{border-color:var(--on-panel)}
.theme-toggle,.gallery-tabs button,.stepper button,.channels button,.link-button{transition:color .2s var(--ease),background-color .2s var(--ease),box-shadow .2s var(--ease),transform .15s var(--ease)}
.theme-toggle::before{transition:background-color .3s var(--ease),box-shadow .3s var(--ease)}
:is(.theme-toggle,.bench-index a,.chip,.gallery-tabs button,.stepper button,.channels button):active{transform:scale(.96)}
@media (prefers-reduced-motion:no-preference){
  /* The first screen of every page arrives in order, a beat apart, instead of all at once. */
  @keyframes enter{from{opacity:0;transform:translateY(14px);filter:blur(4px)}}
  :is(.bench-panel,.case-head>div:first-child)>*,.index-page>:is(p,h1,.index-intro){animation:enter .7s var(--ease) both;animation-delay:calc(var(--k,0) * 90ms)}
  :is(.bench-panel,.case-head>div:first-child,.index-page)>:nth-child(2){--k:1}
  :is(.bench-panel,.case-head>div:first-child,.index-page)>:nth-child(3){--k:2}
  :is(.bench-panel,.case-head>div:first-child,.index-page)>:nth-child(4){--k:3}
  :is(.case-head>div:first-child,.index-page)>:nth-child(5){--k:4}
  .case-head>div:last-child{animation:enter .8s var(--ease) .25s both}
  /* Screenshot tabs: the new panel settles in rather than swapping. */
  .gallery-panel{animation:enter .35s var(--ease) both}
  /* Pictures arrive softly (main.js marks the ones still loading). */
  img{transition:opacity .5s var(--ease)}
  img.is-arriving{opacity:0}
  /* Moving between pages cross-fades; the bar stays put. */
  @view-transition{navigation:auto}
  .site-nav{view-transition-name:site-nav}
  ::view-transition-old(root),::view-transition-new(root){animation-duration:.25s}
}
