:root { --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif; --sans: system-ui, -apple-system, "Segoe UI", sans-serif; }
/* Chrome sits on the artwork as frosted glass; the scene sets the theme for its lighting. */
:root, :root[data-theme="day"] { --pill: oklch(97% .012 85 / .6); --pill-line: oklch(100% 0 0 / .5); --pill-hover: oklch(100% 0 0 / .32); --text: oklch(23% .02 255); --muted: oklch(40% .02 255); --link: oklch(30% .05 250); --focus: oklch(45% .12 250); --ground: oklch(86% .02 240); }
:root[data-theme="night"] { --pill: oklch(17% .02 255 / .58); --pill-line: oklch(100% 0 0 / .14); --pill-hover: oklch(100% 0 0 / .12); --text: oklch(95% .012 90); --muted: oklch(78% .015 90); --link: oklch(88% .04 90); --focus: oklch(83% .09 87); --ground: oklch(12% .02 255); }
* { box-sizing: border-box; }
html, body { height: 100%; }
body { margin: 0; overflow: hidden; background: var(--ground); color: var(--text); font: 16px/1.5 var(--sans); }
[hidden] { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.skip-link { position: fixed; left: 16px; top: -60px; z-index: 6; padding: 8px 12px; border-radius: 6px; background: var(--pill); backdrop-filter: blur(14px); color: var(--text); }
.skip-link:focus { top: 12px; }
/* The scene fills the window and can be panned; the frame keeps the artwork's exact bounds, which every interaction reads. */
.viewport { position: fixed; inset: 0; overflow: auto; overscroll-behavior: none; scrollbar-width: none; }
.viewport::-webkit-scrollbar { display: none; }
.frame { position: relative; width: max(100vw, calc(100dvh * 1672 / 941)); aspect-ratio: 1672 / 941; container-type: inline-size; }
.frame img { display: block; width: 100%; height: 100%; }
#desk-hotspots { position: absolute; inset: 0; width: 100%; height: 100%; overflow: hidden; }
.hotspot { fill: transparent; stroke: none; cursor: pointer; pointer-events: fill; }
.hotspot:focus { outline: none; }
#hover-effect { opacity: 0; transition: opacity 110ms ease-out; pointer-events: none; }
#hover-effect.active { opacity: 1; }
#hover-image { filter: brightness(1.13); }
#hover-edge { fill: none; stroke: #ffe7bd; stroke-opacity: .82; stroke-width: 2.6; stroke-linejoin: round; }
#object-label { position: absolute; z-index: 2; pointer-events: none; max-width: calc(100% - 16px); padding: 6px 12px; border: 1px solid var(--pill-line); border-radius: 999px; background: var(--pill); backdrop-filter: blur(16px) saturate(1.2); color: var(--text); font: 14px/1.35 var(--serif); white-space: nowrap; box-shadow: 0 6px 24px -12px #0006; }
/* The monitor previews the portfolio. Sizes are hundredths of the screen's width, so the copy on the page
   and the copy inside the portfolio dialog's screen come out identical and the open reads as one motion. */
.desk-teaser { --u: 1cqw; position: absolute; display: grid; grid-template-rows: auto 1fr auto; gap: calc(var(--u) * 1.4); padding: calc(var(--u) * 2.6) calc(var(--u) * 3) calc(var(--u) * 2.4); color: #f6f3ec; font-family: var(--sans); pointer-events: none; }
.monitor-teaser { --u: calc(1cqw * 507 / 1672); left: 33.7919%; top: 47.6089%; width: 30.323%; height: 21.6791%; z-index: 1; }
.os-teaser { inset: 0; z-index: 5; }
.os-teaser .os-wallpaper { z-index: -1; }
.teaser-kicker { margin: 0; font: 600 calc(var(--u) * 2.5) / 1.2 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: #ece8df; text-shadow: 0 1px 3px #0009; }
.teaser-cards { display: grid; grid-template-columns: 1fr 1fr; gap: calc(var(--u) * 2); align-content: center; margin: 0; padding: 0; list-style: none; }
.teaser-cards li { min-width: 0; }
.teaser-card { display: grid; width: 100%; height: 100%; grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: calc(var(--u) * 1.8); align-items: center; padding: calc(var(--u) * 1.7) calc(var(--u) * 2.2); border: calc(var(--u) * .2) solid #ffffff2e; border-radius: calc(var(--u) * 2); background: #1a2230a0; background: oklch(18% .03 255 / .62); backdrop-filter: blur(10px); box-shadow: 0 calc(var(--u) * 1) calc(var(--u) * 3) calc(var(--u) * -1) #000a; }
button.teaser-card { appearance: none; margin: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; pointer-events: auto; }
button.teaser-card:hover, button.teaser-card:focus-visible { background: oklch(26% .045 255 / .78); border-color: #ffffff59; }
.teaser-cards svg { grid-row: 1 / 3; width: calc(var(--u) * 7); height: calc(var(--u) * 5.6); }
.teaser-cards strong { font: 600 calc(var(--u) * 3.1) / 1.25 var(--sans); letter-spacing: -.01em; }
.teaser-cards span { font: calc(var(--u) * 2.3) / 1.3 var(--sans); color: #dad6cc; }
.teaser-button { display: inline-block; box-sizing: border-box; width: calc(var(--u) * 31); justify-self: center; appearance: none; margin: 0; padding: calc(var(--u) * 1.3) 0; text-align: center; border: calc(var(--u) * .2) solid #ffffff59; border-radius: 999px; background: #f8f6f0f0; background: oklch(97% .01 85 / .94); color: #2b2f3a; color: oklch(22% .02 255); font: 600 calc(var(--u) * 2.6) / 1.25 var(--sans); text-decoration: none; cursor: pointer; pointer-events: auto; box-shadow: 0 calc(var(--u) * .8) calc(var(--u) * 2.4) calc(var(--u) * -.8) #000b; }
.teaser-button:hover { background: #fff; }
.teaser-button:active { transform: translateY(1px); }
.os-teaser .teaser-button { cursor: default; pointer-events: none; }
.brand, .site-nav, .desk-hint, .scene-line, #error { position: fixed; z-index: 3; margin: 0; }
.signature, .site-nav, .desk-hint, .scene-line, #error { background: var(--pill); border: 1px solid var(--pill-line); backdrop-filter: blur(16px) saturate(1.2); box-shadow: 0 6px 24px -12px #0006; }
.brand { left: 22px; top: 18px; }
.signature { display: inline-flex; flex-direction: column; padding: 10px 16px 11px; border-radius: 14px; color: var(--text); font: 600 22px/1.15 var(--serif); letter-spacing: -.01em; text-decoration: none; }
.signature span { margin-top: 2px; color: var(--muted); font: 14px/1.4 var(--serif); letter-spacing: 0; }
.site-nav { right: 22px; top: 18px; display: flex; align-items: center; gap: 2px; padding: 5px 6px; border-radius: 999px; }
.site-nav a, .site-nav button { appearance: none; margin: 0; padding: 8px 13px; border: 0; border-radius: 999px; background: transparent; color: var(--text); font: 16px/1.2 var(--serif); text-decoration: none; cursor: pointer; }
.site-nav a:hover, .site-nav button:hover { background: var(--pill-hover); }
.site-nav .quiet { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.site-nav .quiet:focus-visible { position: static; width: auto; height: auto; clip-path: none; }
.desk-hint { left: 50%; bottom: 20px; transform: translateX(-50%); padding: 8px 16px; border-radius: 999px; font: 15px/1.4 var(--serif); white-space: nowrap; }
.scene-line { right: 22px; bottom: 20px; padding: 7px 13px; border-radius: 999px; color: var(--muted); font: 14px/1.4 var(--serif); white-space: nowrap; }
.scene-actions { white-space: nowrap; }
.scene-line button { appearance: none; margin: -6px 0 -6px 2px; padding: 6px 4px; border: 0; background: none; color: var(--link); font: inherit; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.scene-line button:hover { color: var(--text); }
#error { left: 50%; top: 84px; transform: translateX(-50%); padding: 8px 14px; border-radius: 10px; color: #a0442a; color: oklch(40% .12 40); font-size: 14px; }
:root[data-theme="night"] #error { color: #f0b98a; color: oklch(86% .1 50); }
/* Middling widths: the centred hint and the right-hand status line would meet, so the hint takes the bottom-left corner. */
@media (max-width: 1280px) {
  .desk-hint { left: 20px; transform: none; }
}
/* Narrower still: the hint sits above a centred status line that hugs its text and wraps the actions onto their own line when it must. */
@media (max-width: 900px) {
  .desk-hint { left: 50%; bottom: 76px; transform: translateX(-50%); }
  .scene-line { left: 50%; right: auto; bottom: 14px; width: max-content; max-width: calc(100% - 24px); transform: translateX(-50%); text-align: center; white-space: normal; }
}
@media (max-width: 680px) {
  .brand { left: 12px; top: 12px; }
  .signature { padding: 8px 12px 9px; border-radius: 12px; font-size: 18px; }
  .signature span { font-size: 13px; }
  /* Too narrow for both pills on one row: the links sit under the name. */
  .site-nav { left: 12px; right: auto; top: 80px; padding: 3px 4px; }
  .site-nav a, .site-nav button { padding: 7px 9px; font-size: 15px; }
  .desk-hint { font-size: 14px; }
  #error { top: 132px; width: max-content; max-width: calc(100% - 24px); }
}
@media (prefers-reduced-transparency: reduce) {
  :root, :root[data-theme="day"] { --pill: oklch(97% .012 85); }
  :root[data-theme="night"] { --pill: oklch(17% .02 255); }
  .signature, .site-nav, .desk-hint, .scene-line, #error, .skip-link, #object-label { backdrop-filter: none; }
}
/* The chrome steps back while a dialog is open; the notebook's shade would otherwise show it dimmed behind the book. */
.brand, .site-nav, .desk-hint, .scene-line, .monitor-teaser, #object-label { transition: opacity 180ms ease; }
body:has(dialog[open]) :is(.brand, .site-nav, .desk-hint, .scene-line) { opacity: 0; pointer-events: none; }
/* The notebook and whiteboard shades are translucent, so the page's hover caption and the monitor teaser would otherwise show through them.
   The teaser stays put for the desktop dialog: its first frame mirrors the teaser, and the open reads as one motion. */
body:has(dialog[open]) :is(#hover-effect, #object-label) { opacity: 0; }
body:has(#desk-notebook[open], #desk-whiteboard[open]) .monitor-teaser { opacity: 0; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { #hover-effect, .brand, .site-nav, .desk-hint, .scene-line, .monitor-teaser, #object-label { transition: none; } .teaser-button:active { transform: none; } }
.noscript-note { position: fixed; left: 50%; bottom: 20px; z-index: 3; transform: translateX(-50%); max-width: calc(100% - 32px); margin: 0; padding: 8px 16px; border-radius: 16px; background: var(--pill); color: var(--text); font: 15px/1.4 var(--serif); text-align: center; }
/* Short landscape windows (a phone on its side): one-line name, links beside it, hint and status in the bottom corners. */
@media (max-height: 520px) {
  .brand { left: 12px; top: 10px; }
  .signature { flex-direction: row; align-items: baseline; gap: 10px; padding: 6px 12px 7px; border-radius: 12px; font-size: 17px; }
  .signature span { margin: 0; font-size: 13px; }
  .site-nav { left: auto; right: 12px; top: 10px; padding: 3px 4px; }
  .site-nav a, .site-nav button { padding: 6px 10px; font-size: 15px; }
  .desk-hint { left: 12px; bottom: 10px; transform: none; padding: 6px 12px; font-size: 14px; }
  .scene-line { left: auto; right: 12px; bottom: 10px; width: auto; max-width: none; transform: none; text-align: left; white-space: nowrap; }
  #error { top: 62px; }
}
/* Very wide windows: fit the room's height and leave quiet margins instead of cropping the diplomas and chair. */
@media (min-aspect-ratio: 2 / 1) { .frame { width: calc(100dvh * 1672 / 941); margin: 0 auto; } }
/* Older browsers: plain colours for the chrome, and the preview's unit from the viewport instead of the container. */
@supports not (color: oklch(50% 0 0)) {
  :root, :root[data-theme="day"] { --pill: #f7f5ef99; --pill-line: #ffffff80; --pill-hover: #ffffff52; --text: #262b36; --muted: #4b5262; --link: #33435c; --focus: #3b6fb0; --ground: #cfd6df; }
  :root[data-theme="night"] { --pill: #181c2694; --pill-line: #ffffff24; --pill-hover: #ffffff1f; --text: #f2efe6; --muted: #c2bfb4; --link: #e3dcc7; --focus: #e0c27a; --ground: #14181f; }
}
@supports not (width: 1cqw) {
  .monitor-teaser { --u: calc(100vw * 507 / 167200); }
  .os-teaser { --u: calc(min(100vw / 543, 100vh / 312) * 5.07); } /* the camera's frame in desktop.js */
}
@media (forced-colors: active) {
  .signature, .site-nav, .desk-hint, .scene-line, #error, .noscript-note, .teaser-cards li, .teaser-button, #object-label { border: 1px solid CanvasText; backdrop-filter: none; }
}
