/* All positions are in design pixels (main_page.jpg is 1920x1080) multiplied by --u,
   the size of one design pixel on screen.

   The scene keeps its full width and sits on the bottom of the window. Anything
   left over goes above it, where the design is plain wall. On windows wider than
   16:9 up to 180px of that empty wall at the top is cropped instead (the
   "photography" label starts at y=209), so a full-screen browser with its toolbar
   still fills edge to edge. */
:root {
  --wall: #f48d6a;
  --table: #003d4f;
  --ink: #def9c6;
  --u: calc(min(100vw, 100vh * 1920 / 900) / 1920);
}
@supports (height: 100dvh) {
  :root { --u: calc(min(100vw, 100dvh * 1920 / 900) / 1920); }
}

html, body { margin: 0; height: 100%; }

body {
  overflow: hidden;
  /* The table edge is at y=706 in the design: 374 design px above the bottom. */
  background: linear-gradient(to bottom, var(--wall) calc(100% - 374 * var(--u)), var(--table) 0);
  font-family: 'Kucin Handwriting', sans-serif;
  -webkit-tap-highlight-color: transparent;
}

.stage {
  position: fixed;
  bottom: 0;
  left: calc(50% - 960 * var(--u));
  width: calc(1920 * var(--u));
  height: calc(1080 * var(--u));
  user-select: none;
  -webkit-user-select: none;
}
.stage.pointer { cursor: pointer; }

/* The wall and table as part of the scene, so the table edge moves with the camera. It
   reaches well past the stage, so a turned or zoomed desk never shows an edge; at rest it
   paints exactly what the page background does. */
.backdrop {
  position: absolute;
  inset: calc(-500 * var(--u)) calc(-800 * var(--u));
  background: linear-gradient(to bottom, var(--wall) calc((500 + 706) * var(--u)), var(--table) 0);
}

.layer {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: auto;
  -webkit-user-drag: none;
}

.screen {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  pointer-events: none;
}
.screen > * {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* The player's movie area, 14,26 772x484 on its 800x610 drawing. */
.screen .qt-movie {
  left: 1.75%;
  top: 4.2623%;
  width: 96.5%;
  height: 79.3443%;
  object-fit: cover;
  background: #000;
}
/* A pause sign on the movie while it's paused (a category is open). */
.screen .qt-paused {
  left: 1.75%;
  top: 4.2623%;
  width: 96.5%;
  height: 79.3443%;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='48' fill='%23000' fill-opacity='.45'/%3E%3Crect x='33' y='29' width='12' height='42' rx='3' fill='%23fff'/%3E%3Crect x='55' y='29' width='12' height='42' rx='3' fill='%23fff'/%3E%3C/svg%3E") center / auto 24% no-repeat;
  opacity: 0;
  transition: opacity 0.3s;
}
html[data-focus] .screen .qt-paused { opacity: 1; }
.qt-time {
  font: 11px Monaco, Menlo, 'Courier New', monospace;
  fill: #1d2416;
}
.qt-playhead { fill: #1d2416; }

/* Same 1920-wide frame as the stage, but held to the top of the window. */
.nav {
  position: fixed;
  z-index: 3; /* above the moving desk */
  top: 0;
  right: 0;
  width: calc(1920 * var(--u));
  transition: opacity 0.2s;
}
/* While a category is open, about and contact give way to the home button. */
html[data-focus] .nav {
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s, visibility 0s 0.2s;
}

.label {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  font-size: calc(var(--size) * var(--u));
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
  color: var(--ink);
  text-decoration: none;
  outline: none;
}

.stage .label {
  opacity: 0;
  pointer-events: none; /* (no fade: like Felix's, the label is there the moment the pointer is) */
  /* Following the pointer, a label often lands on something light (the poster, the cap,
     the mug); a soft dark edge keeps the pale ink readable there. */
  text-shadow: 0 0 calc(2 * var(--u)) rgb(0 0 0 / 0.7), 0 0 calc(6 * var(--u)) rgb(0 0 0 / 0.45);
}
/* Set by scene.js while the label rides along with the pointer. */
.stage .label.at-pointer {
  position: fixed;
  left: var(--px);
  top: var(--py);
  transform: translate(var(--tx), var(--ty));
}
.stage .label.on,
.stage .label:focus-visible,
.all-labels .stage .label[data-design] {
  opacity: 1;
  pointer-events: auto;
}
/* While the mandarins are rolling, even with keyboard focus. */
.stage .label[aria-disabled='true'] {
  opacity: 0;
  pointer-events: none;
}

button.label {
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.label.two-lines { line-height: 1.1; }

/* --- Photography: the paper inside the frame (scene.js moves it with the frame) ------ */

/* Paper and cover are inside the stage, painted in the desk's own order (no z-index). */
.paper {
  position: fixed;
  left: 0;
  top: 0;
  container-type: size; /* everything inside is sized in cqw: a share of the paper's width */
  visibility: hidden;
  opacity: 0;
  transform-origin: 0 0;
  background: #fff; /* white, like the slides' own pages */
  color: #2a2724;
}
/* A soft shade along the edges, where the paper goes under the frame. */
.paper::after {
  content: '';
  position: absolute;
  inset: 0;
  box-shadow: inset 0 0 3cqw rgb(0 0 0 / 0.1);
  pointer-events: none;
}
.paper-content { position: absolute; inset: 0; }
.frame-cover {
  position: fixed;
  transform-origin: 0 0;
  visibility: hidden;
  pointer-events: none;
}
/* One page at a time, fitted whole above the controls: a slide fills the paper's width, a photo
   sits on it with a margin, like a print. */
.slide {
  position: absolute;
  inset: 1.5cqw 1.5cqw 11cqw;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s, visibility 0s 0.4s;
}
.slide.photo { inset: 8cqw 8cqw 17cqw; }
.slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.slide.current {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.4s 0.1s;
}
.paper-title { outline: none; }
.paper-controls {
  position: absolute;
  left: 7cqw;
  right: 7cqw;
  bottom: 3.5cqw;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font: 400 5.6cqw / 1 'Kucin Handwriting', sans-serif;
}
.prev, .next {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.prev:hover, .prev:focus-visible, .next:hover, .next:focus-visible { text-decoration: underline; text-underline-offset: 0.15em; outline: none; }
.count { color: #8a837b; font-size: 0.85em; }

/* --- Wingtra: the drone's spinning propellers and the page beside it ----------------- */

.props {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  visibility: hidden;
  pointer-events: none;
}

/* --- Motion Emotion: the cap turning over, and a magnifying glass over its label ------ */

/* The turn, drawn by scene.js where the cap lies (in its place in the desk's paint order). */
.cap-plane {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  visibility: hidden;
  pointer-events: none;
}
/* The label's print on the turned-over cap (scene.js maps it onto the label). */
.cap-print {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  mix-blend-mode: multiply;
  visibility: hidden;
  pointer-events: none;
}
html.cap-magnify .cap-print { visibility: visible; }
/* Where focus goes once the cap has turned over. */
.cap-page {
  position: fixed;
  inset: 0;
  pointer-events: none;
  outline: none;
}

/* Once the cap has turned over the pointer is a magnifying glass: over the label inside the cap it
   moves the big glass (below) across the text. */
html.cap-magnify, html.cap-magnify * {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg fill='none' stroke-linecap='round'%3E%3Ccircle cx='13' cy='13' r='9' stroke='%23000' stroke-opacity='.5' stroke-width='5'/%3E%3Cpath d='M20 20l8 8' stroke='%23000' stroke-opacity='.5' stroke-width='7'/%3E%3Ccircle cx='13' cy='13' r='9' stroke='%23fff' stroke-width='2.5'/%3E%3Cpath d='M20 20l8 8' stroke='%23fff' stroke-width='4'/%3E%3C/g%3E%3C/svg%3E") 13 13, zoom-in;
}
html.cap-magnify :is(.home, .cap-close) { cursor: pointer; }

/* Above the big glass, along its rim: how to read the label. */
.cap-hint {
  --z: min(68vmin, 640px);
  position: fixed;
  z-index: 4;
  left: calc(50% - var(--z) * 0.625);
  top: calc(50% - var(--z) * 0.625);
  width: calc(var(--z) * 1.25);
  height: calc(var(--z) * 1.25);
  overflow: visible;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, visibility 0s 0.3s;
}
html.cap-magnify .cap-hint {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s 0.15s;
}
/* In the style of home, about and contact (scene.js sets its size to home's). */
.cap-hint text {
  font: 400 48px 'Kucin Handwriting', sans-serif;
  fill: var(--ink);
}

/* Close, under the big glass. */
.cap-close {
  position: fixed;
  z-index: 4;
  left: 50%;
  top: calc(50% + min(68vmin, 640px) / 2 + max(8px, calc(16 * var(--u))));
  padding: 0.2em 0.3em;
  border: 0;
  background: none;
  color: var(--ink);
  font: 400 max(18px, calc(40 * var(--u))) / 1 'Kucin Handwriting', sans-serif;
  transform: translateX(-50%);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.2s, visibility 0s 0.2s;
}
html.cap-magnify .cap-close {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.2s;
}
.cap-close:hover, .cap-close:focus-visible { text-decoration: underline; text-underline-offset: 0.15em; outline: none; }

/* The label close up, through a big round glass in the middle of the window (open once the cap has
   turned over): magnified, and bent towards the rim (scene.js draws it on the canvas). */
.cap-zoom {
  --z: min(68vmin, 640px);
  position: fixed;
  z-index: 4;
  left: calc(50% - var(--z) / 2);
  top: calc(50% - var(--z) / 2);
  width: var(--z);
  height: var(--z);
  overflow: hidden;
  border-radius: 50%;
  background: var(--table);
  box-shadow: 0 calc(var(--z) * 0.03) calc(var(--z) * 0.09) rgb(0 0 0 / 0.45);
  visibility: hidden;
  opacity: 0;
  transform: scale(0.94);
  pointer-events: none;
  transition: opacity 0.2s, transform 0.2s, visibility 0s 0.2s;
}
.cap-zoom.on {
  visibility: visible;
  opacity: 1;
  transform: none;
  transition: opacity 0.2s, transform 0.2s;
}
.cap-zoom canvas {
  width: 100%;
  height: 100%;
}
/* The glass's rim, and light on it. */
.cap-zoom::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 calc(var(--z) * 0.011) #1c1c1c, inset 0 0 0 calc(var(--z) * 0.015) rgb(255 255 255 / 0.18),
    inset 0 0 calc(var(--z) * 0.05) rgb(0 0 0 / 0.3);
  background: radial-gradient(circle at 30% 24%, rgb(255 255 255 / 0.22), transparent 30%),
    radial-gradient(circle at 74% 82%, rgb(255 255 255 / 0.08), transparent 22%);
}
/* What is written on the label: drawn on it by scene.js in this style (px of the close-up photo),
   along it, centred, wrapped to fit inside its stitching (smaller if it would not). */
.cap-label-text {
  font: 500 36px / 1.34 'Helvetica Neue', Helvetica, Arial, sans-serif;
  letter-spacing: 0.01em;
  color: #1f2a44;
  opacity: 0.88;
}

/* --- Pocket Stories: a hologram of pocketstories.ch, projected from the mug ------------- */

/* The room almost black while the hologram is on (scene.js fades it in): a hologram is light added
   to the room, and its colours are at their fullest where the room is dark. Thinner over the mug,
   so it stays faintly lit and its logo reads under the beam (scene.js keeps --mug on it). */
.pocket-dim {
  --mug-at: 50% 120%;
  --mug-size: 0 0;
  position: fixed;
  z-index: 2;
  inset: 0;
  background: radial-gradient(ellipse 70% 80% at 50% 45%, rgb(6 4 2 / 0.92), rgb(6 4 2 / 0.97));
  -webkit-mask: radial-gradient(var(--mug-size) at var(--mug-at), rgb(0 0 0 / 0.78), rgb(0 0 0 / 0.84) 55%, #000);
  mask: radial-gradient(var(--mug-size) at var(--mug-at), rgb(0 0 0 / 0.78), rgb(0 0 0 / 0.84) 55%, #000);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
/* The beam and its specks of light (scene.js draws them). */
.pocket-beam {
  position: fixed;
  z-index: 2;
  inset: 0;
  width: 100%;
  height: 100%;
  mix-blend-mode: screen;
  visibility: hidden;
  pointer-events: none;
}
/* Pocket Stories' own type (as on pocketstories.ch), served from here: Montserrat, DM Mono. */
@font-face {
  font-family: 'Montserrat';
  font-weight: 500 700;
  font-display: swap;
  src: url('assets/fonts/Montserrat.woff2') format('woff2');
}
@font-face {
  font-family: 'DM Mono';
  font-weight: 400;
  font-display: swap;
  src: url('assets/fonts/DMMono-400.woff2') format('woff2');
}

/* The hologram: placed, sized and powered on by scene.js (its type is sized to its width: cqw).
   It is light, as a projected hologram is: added to the room (screen), so where it is dark it is not
   there at all; there is no panel and no frame, its body of light fades out into the air at its
   edges. It hangs in the air as a plane, leaning back a little over the beam and turning a little
   as the viewer moves (scene.js). In Pocket Stories' colours: white, the logo's yellow, and the blue
   of its film (its lake and trams: #1e596b, here as light). */
.pocket-holo {
  --y: 249 225 74; /* #f9e14a, the logo */
  --b: 122 214 245; /* #7ad6f5, the film's blue as light */
  position: fixed;
  z-index: 3;
  left: 0;
  top: 0;
  container-type: inline-size;
  transform-origin: 0 0;
  mix-blend-mode: screen;
  visibility: hidden;
  outline: none;
  pointer-events: none;
}
.pocket-glass {
  --c: 1; /* how far its content has come in */
  position: relative;
  padding: 6.5cqw 7cqw 7.5cqw;
  background: #000; /* (nothing, added as light) */
  color: #fff;
  font: 500 2.9cqw / 1.4 'Montserrat', 'Helvetica Neue', Arial, sans-serif;
  transform-origin: 50% 100%;
  -webkit-mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent), linear-gradient(transparent, #000 6%, #000 93%, transparent);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent), linear-gradient(transparent, #000 6%, #000 93%, transparent);
  mask-composite: intersect;
  pointer-events: auto;
}
.pocket-glass > :not(.pocket-grain, .pocket-field) { opacity: var(--c); }
/* Its body of light, filmed (tools/pocket_holo_plates.py), behind its content. */
.pocket-field {
  position: absolute;
  z-index: -1;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.6;
  /* The light dies away into the air: softly at the sides, most of all at the top (furthest from
     the beam); the beam comes in at the bottom. */
  -webkit-mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent), linear-gradient(transparent, #000 30%, #000 94%, transparent);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent), linear-gradient(transparent, #000 30%, #000 94%, transparent);
  mask-composite: intersect;
  pointer-events: none;
}
/* Film grain in its light, not on its words (scene.js makes the grain; it jumps about, as grain does). */
.pocket-grain {
  position: absolute;
  z-index: -1; /* (in the light, under the words) */
  inset: 0;
  background: var(--grain, none) 0 0 / 160px 160px;
  mix-blend-mode: multiply;
  animation: pocket-grain 0.4s steps(5) infinite;
  pointer-events: none;
}
@keyframes pocket-grain {
  0% { background-position: 0 0; }
  20% { background-position: -53px 31px; }
  40% { background-position: 71px -44px; }
  60% { background-position: -29px -87px; }
  80% { background-position: 92px 18px; }
  100% { background-position: 0 0; }
}
.pocket-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 3cqw;
}
.pocket-logo { margin: 0; line-height: 0; }
/* Light blooming off the logo, its edges split a hair into colours, as a projected image. */
.pocket-logo img {
  width: 22cqw;
  height: auto;
  filter: drop-shadow(-0.12cqw 0 0 rgb(255 70 90 / 0.35)) drop-shadow(0.12cqw 0 0 rgb(70 200 255 / 0.4)) drop-shadow(0 0 1cqw rgb(var(--y) / 0.5));
}
.pocket-source {
  margin: 0.6cqw 0 0;
  font: 400 2.1cqw / 1 'DM Mono', ui-monospace, monospace;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgb(var(--b));
}
/* Light blooms a little off everything bright, as light does. */
.pocket-tagline, .pocket-source, .pocket-sub, .pocket-button { text-shadow: 0 0 0.8cqw rgb(var(--b) / 0.55); }
/* The film in its own colours, no frame: its picture fades out at its edges into the hologram's light. */
.pocket-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: #000;
  -webkit-mask: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent), linear-gradient(transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-composite: source-in;
  mask: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent), linear-gradient(transparent, #000 8%, #000 92%, transparent);
  mask-composite: intersect;
}
.pocket-tagline {
  margin: 3.6cqw 0 1.4cqw;
  font-size: 4cqw;
  font-weight: 700;
  line-height: 1.22;
  color: #fff;
}
.pocket-sub {
  margin: 0 0 4cqw;
  font: 400 2.2cqw / 1.3 'DM Mono', ui-monospace, monospace;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #c4efff;
}
.pocket-links { display: flex; flex-wrap: wrap; gap: 1.8cqw; }
/* As on the site: the yellow button, and white outlined ones. */
.pocket-button {
  padding: 1.4cqw 2.4cqw;
  border: 1px solid rgb(255 255 255 / 0.7);
  background: rgb(255 255 255 / 0.04);
  color: #fff;
  font-size: 2.7cqw;
  font-weight: 500;
  text-decoration: none;
}
.pocket-button.watch { border-color: rgb(var(--y)); background: rgb(var(--y)); color: #000; box-shadow: 0 0 2cqw rgb(var(--y) / 0.45); }
.pocket-button:hover, .pocket-button:focus-visible { background: rgb(255 255 255 / 0.16); outline: none; }
.pocket-button.watch:hover, .pocket-button.watch:focus-visible { background: #fff3a0; }
@media (prefers-reduced-motion: reduce) {
  .pocket-grain { animation: none; }
}

/* Dust in the light, filmed (tools/pocket_holo_plates.py): over the beam and the hologram, added as
   light, fading out at its edges (scene.js places it). */
.pocket-dust {
  position: fixed;
  z-index: 4;
  left: 0;
  top: 0;
  object-fit: cover;
  transform-origin: 0 0;
  mix-blend-mode: screen;
  -webkit-mask: radial-gradient(closest-side, #000 55%, transparent);
  mask: radial-gradient(closest-side, #000 55%, transparent);
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}

/* Close, under the mug (scene.js places it), in the style of home. */
.pocket-close {
  position: fixed;
  z-index: 3;
  left: 0;
  top: 0;
  padding: 0.2em 0.3em;
  border: 0;
  background: none;
  color: var(--ink);
  font: 400 max(18px, calc(40 * var(--u))) / 1 'Kucin Handwriting', sans-serif;
  cursor: pointer;
  transform: translateX(-50%);
  visibility: hidden;
  opacity: 0;
}
.pocket-close:hover, .pocket-close:focus-visible { text-decoration: underline; text-underline-offset: 0.15em; outline: none; }

/* A 1920x1080 page, scaled to fit the window and centred, as in the example design. */
.wingtra {
  --p: min(100vw / 1920, 100vh / 1080);
  position: fixed;
  z-index: 2;
  left: calc((100vw - 1920 * var(--p)) / 2);
  top: calc((100vh - 1080 * var(--p)) / 2);
  width: calc(1920 * var(--p));
  height: calc(1080 * var(--p));
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  outline: none;
}
.wingtra-text {
  position: absolute;
  left: calc(186 * var(--p));
  top: calc(595 * var(--p));
  width: calc(1025 * var(--p));
  margin: 0;
  font: 400 calc(43.4 * var(--p)) / calc(46.8 * var(--p)) 'Kucin Handwriting', sans-serif;
  color: #fff;
}
.wingtra-video {
  position: absolute;
  left: calc(1312 * var(--p));
  top: calc(188 * var(--p));
  width: calc(436 * var(--p));
  height: calc(774 * var(--p));
  object-fit: cover;
  background: #2a2724;
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Video Life: the camcorder's turning panel, and its screen --------------------- */

/* The camcorder's panel turning over: frames of assets/camcorder-flip.webp, drawn by scene.js. */
.cam-turn {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  visibility: hidden;
  pointer-events: none;
}

/* The camcorder's screen and its frame (lcd-frame.webp, 796x559 at 2x), mapped onto its
   panel by scene.js. */
.lcd {
  position: fixed;
  left: 0;
  top: 0;
  width: 796px;
  height: 559px;
  transform-origin: 0 0;
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}
.lcd-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* On the iMac's screen: the camcorder's picture, over the FireWire cable. Laid out at its
   size in the close-up; scene.js maps it onto the iMac's screen and moves it in with the
   camera. It lies under the iMac's layer, whose bezel covers its edges. */
.mac-feed {
  position: fixed;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  visibility: hidden;
  opacity: 0;
  outline: none;
}

/* The camcorder's picture (.dv), on either screen: on the camcorder, the frame's opening
   (x 115, y 58, 582x426 of 796x559), a little bigger so its edges go under the frame; on
   the iMac, all of it. Everything inside is sized in cqw. */
.dv {
  position: absolute;
  overflow: hidden;
  container-type: size;
  background: radial-gradient(ellipse at 50% 45%, rgb(58 185 230), rgb(31 120 205) 60%, rgb(22 88 173));
  color: rgb(236 242 255);
}
.lcd .dv { left: 14.1%; top: 9.9%; width: 73.8%; height: 77.2%; }
.mac-feed .dv { inset: 0; }
.dv-picture {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  visibility: hidden;
  background: #000;
}
.dv.picture .dv-picture { visibility: inherit; } /* (hidden with its screen) */
.dv-thumb, .dv-picture iframe {
  grid-area: 1 / 1;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border: 0;
}
/* Tracking noise while the tape rewinds. */
.dv-noise {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, transparent 0 46%, rgb(255 255 255 / 0.5) 47%, rgb(0 0 0 / 0.55) 49%, transparent 51%),
    repeating-linear-gradient(to bottom, transparent 0 1.5cqh, rgb(255 255 255 / 0.12) 1.5cqh 1.8cqh);
  background-size: 100% 140%, 100% 100%;
  mix-blend-mode: screen;
}
.dv.rewinding .dv-noise { opacity: 1; animation: dv-tracking 0.42s steps(6) infinite; }
.dv.rewinding .dv-picture { animation: dv-jitter 0.14s steps(2) infinite; }
.dv.rewinding .osd-mode { animation: dv-blink 0.5s steps(1) infinite; }
@keyframes dv-tracking { from { background-position: 0 -40%, 0 0; } to { background-position: 0 140%, 0 6cqh; } }
@keyframes dv-jitter { 50% { transform: translateX(0.6cqw) skewX(-1.5deg); } }
@keyframes dv-blink { 50% { opacity: 0; } }

/* The camcorder's on-screen display: white letters with a dark edge, like the reference. */
.dv-osd, .dv-ui, .osd-button {
  font: 700 4cqw / 1.1 'Courier New', Courier, monospace;
  letter-spacing: 0.04em;
  text-shadow: 0 0 0.25cqw rgb(0 26 60), 0.12cqw 0.12cqw 0 rgb(0 26 60), -0.12cqw -0.12cqw 0 rgb(0 26 60);
}
.dv-osd { position: absolute; inset: 0; pointer-events: none; }
.osd-mode { position: absolute; left: 5cqw; top: 4cqw; }
.osd-tc { position: absolute; left: 5cqw; bottom: 4cqw; }
.osd-icons { position: absolute; right: 5cqw; top: 4.3cqw; display: flex; gap: 2.5cqw; align-items: center; }
.osd-tape {
  width: 5cqw;
  height: 3cqw;
  border: 0.45cqw solid currentColor;
  border-radius: 0.6cqw;
  background: radial-gradient(circle at 30% 50%, currentColor 0 0.5cqw, transparent 0.6cqw), radial-gradient(circle at 70% 50%, currentColor 0 0.5cqw, transparent 0.6cqw);
  box-shadow: 0 0 0.3cqw rgb(0 26 60);
}
.osd-battery {
  position: relative;
  width: 6.5cqw;
  height: 3cqw;
  border: 0.45cqw solid rgb(82 201 137);
  border-radius: 0.5cqw;
  background: linear-gradient(to right, transparent 0 40%, rgb(82 201 137) 40%);
  box-shadow: 0 0 0.3cqw rgb(0 26 60);
}
.osd-battery::after { content: ''; position: absolute; right: -1.2cqw; top: 0.6cqw; width: 0.6cqw; height: 1cqw; background: rgb(82 201 137); }

/* Browsing the portfolio, on the iMac once the camera has arrived: smaller than the
   camcorder's own display, the iMac's screen being so much bigger. */
.dv-ui {
  position: absolute;
  left: 5cqw;
  right: 5cqw;
  bottom: 9cqw;
  display: none;
  font-size: 2.8cqw;
}
.dv.ready .dv-ui { display: block; }
.dv.ready .osd-tc { display: none; }
.dv-title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.dv-video-title { margin: 0 0 1.8cqw; font-size: 2.6cqw; }
.dv-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 1.5cqw; }
.dv-count { min-width: 7cqw; text-align: center; }
.osd-button {
  padding: 0.5cqw 1.2cqw;
  border: 0.3cqw solid currentColor;
  border-radius: 0.5cqw;
  background: rgb(0 30 70 / 0.35);
  color: inherit;
  font-size: 2.6cqw;
  text-decoration: none;
  cursor: pointer;
}
.osd-button:hover, .osd-button:focus-visible { background: rgb(255 255 255 / 0.22); outline: none; }
.dv-vimeo { margin-left: auto; font-size: 2.2cqw; }
.dv-stop { position: absolute; left: 4cqw; top: 3.5cqw; display: none; }
.dv.watching .dv-stop { display: block; }
.dv.watching :is(.dv-osd, .dv-ui) { display: none; }
@media (prefers-reduced-motion: reduce) {
  .dv.rewinding :is(.dv-noise, .dv-picture, .osd-mode) { animation: none; }
}

/* Back to the desk, shown while a category is open. Small, top left. */
.home {
  position: fixed;
  z-index: 3;
  top: calc(30 * var(--u));
  left: calc(40 * var(--u));
  display: inline-flex;
  align-items: center;
  gap: 0.25em;
  padding: 0.2em 0.3em;
  border: 0;
  background: none;
  color: var(--ink);
  font: 400 max(18px, calc(40 * var(--u))) / 1 'Kucin Handwriting', sans-serif;
  cursor: pointer;
  visibility: hidden;
  opacity: 0;
}
.home svg { width: 0.85em; height: 0.85em; }
.home:hover, .home:focus-visible { text-decoration: underline; text-underline-offset: 0.15em; outline: none; }

/* --- About: Mac OS 9 on the iMac's screen, and the portrait taped onto its bezel ----- */

/* Like .mac-feed: laid out at its size once the camera has arrived, and moved and scaled
   onto the iMac's screen by scene.js. Inside, an 800x610 grid like the QuickTime player:
   --g is one unit; the outer 4 units sit under the bezel. Mac OS 9's Platinum look, drawn
   from period screenshots (ATPM's AppleWorks 6 review, 2000). data-state says what shows:
   "quicktime" nothing (QuickTime, underneath, shows), "desktop" the Finder, "appleworks"
   AppleWorks with the about text open. */
.mac-doc {
  position: fixed;
  left: 0;
  top: 0;
  transform-origin: 0 0;
  container-type: size;
  visibility: hidden;
  outline: none;
}
.aw {
  --g: calc(100cqw / 800);
  position: absolute;
  inset: 0;
  overflow: hidden;
  color: #111;
  font: 700 calc(12 * var(--g)) / 1 Charcoal, 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  cursor: default;
  user-select: none;
  -webkit-user-select: none;
}
.aw > * { visibility: hidden; }
.mac-doc[data-state='desktop'] :is(.os-desktop, .aw-menubar.finder),
.mac-doc[data-state='appleworks'] :is(.os-desktop, .aw-menubar.appleworks, .aw-buttonbar, .aw-window),
.mac-doc[data-state='mail'] :is(.os-desktop, .aw-menubar.oe, .oe-window) { visibility: inherit; }
/* While about or contact is open QuickTime keeps playing until it quits: no pause sign on it. */
html:is([data-focus='about'], [data-focus='contact']) .screen .qt-paused { opacity: 0; }

/* The desktop: a smoky Graphite picture, as Mac OS 9 matched the desktop to an iMac's case,
   with the hard disk top right and the Trash bottom right. */
.os-desktop {
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(45deg, rgb(255 255 255 / 0.035) 0 calc(1 * var(--g)), transparent 0 calc(3 * var(--g))),
    radial-gradient(ellipse 75% 70% at 45% 38%, #969ca4, #6a7077 60%, #4f5359);
}
.os-icon {
  position: absolute;
  left: calc(700 * var(--g));
  width: calc(76 * var(--g));
  padding-top: calc(38 * var(--g));
  text-align: center;
  color: #fff;
  font: 400 calc(10 * var(--g)) / 1.2 Geneva, Helvetica, Arial, sans-serif;
  background: center top / calc(34 * var(--g)) calc(34 * var(--g)) no-repeat;
}
.os-disk {
  top: calc(28 * var(--g)); /* its name clear of AppleWorks' window */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 34'%3E%3Crect x='2.5' y='9.5' width='29' height='16' rx='1.5' fill='%23d9d9d9' stroke='%23222'/%3E%3Crect x='3' y='19' width='28' height='6' fill='%23a8a8a8'/%3E%3Cpath d='M3 19h28' stroke='%23555'/%3E%3Crect x='6' y='21' width='3' height='2' fill='%2312c412'/%3E%3Cpath d='M12 22h16' stroke='%23666'/%3E%3C/svg%3E");
}
.os-trash {
  top: calc(520 * var(--g));
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 34 34'%3E%3Crect x='13' y='3.5' width='8' height='3' rx='1' fill='%23cfcfcf' stroke='%23222'/%3E%3Crect x='6.5' y='6.5' width='21' height='4' rx='1' fill='%23e0e0e0' stroke='%23222'/%3E%3Cpath d='M8.5 10.5h17l-1.5 20h-14z' fill='%23c9c9c9' stroke='%23222'/%3E%3Cpath d='M12.5 13v15M17 13v15M21.5 13v15' stroke='%23777'/%3E%3C/svg%3E");
}

.aw-menubar {
  position: absolute;
  inset: 0 0 auto;
  height: calc(24 * var(--g));
  display: flex;
  align-items: flex-end;
  gap: calc(15 * var(--g));
  padding: 0 calc(20 * var(--g)) calc(6 * var(--g));
  box-sizing: border-box;
  background: #dedede;
  border-bottom: calc(1 * var(--g)) solid #8e8e8e;
}
.os-clock { margin-left: auto; font-weight: 400; }

/* AppleWorks: its button bar, a palette under the menu bar, and the document window, a little
   smaller than the screen so the desktop shows around it. */
.aw-buttonbar {
  position: absolute;
  left: calc(30 * var(--g));
  top: calc(30 * var(--g));
  width: calc(392 * var(--g));
  height: calc(40 * var(--g));
  background: #dddddd;
  border: calc(1 * var(--g)) solid #555;
  box-sizing: border-box;
  box-shadow: calc(2 * var(--g)) calc(2 * var(--g)) 0 rgb(0 0 0 / 0.35);
}
.aw-bar-title {
  height: calc(11 * var(--g));
  display: grid;
  place-items: center;
  background: repeating-linear-gradient(#fafafa 0 calc(1 * var(--g)), #a3a3a3 calc(1 * var(--g)) calc(2 * var(--g))) center / 100% calc(7 * var(--g)) no-repeat, #dddddd;
  border-bottom: calc(1 * var(--g)) solid #888;
}
.aw-bar-title span {
  padding: 0 calc(6 * var(--g));
  background: #dddddd;
  font-size: calc(9 * var(--g));
}
.aw-buttons {
  display: flex;
  align-items: center;
  gap: calc(3 * var(--g));
  height: calc(27 * var(--g));
  padding: 0 calc(8 * var(--g));
}
.aw-btn {
  display: grid;
  place-items: center;
  width: calc(26 * var(--g));
  height: calc(22 * var(--g));
  border: calc(1 * var(--g)) solid #8a8a8a;
  border-radius: calc(3 * var(--g));
  box-sizing: border-box;
  background: linear-gradient(#f8f8f8, #d2d2d2);
  font: 700 calc(17 * var(--g)) / 1 Times, 'Times New Roman', serif;
}
.aw-i { font-style: italic; font-weight: 400; }
.aw-u { font-weight: 400; text-decoration: underline; text-underline-offset: calc(2 * var(--g)); }
.aw-sep { width: calc(1 * var(--g)); height: calc(18 * var(--g)); margin: 0 calc(5 * var(--g)); background: #999; }
/* Alignment: four lines each, drawn as gradients over the button's own. */
.aw-align {
  --l: linear-gradient(#222, #222);
  background: var(--l), var(--l), var(--l), var(--l), linear-gradient(#f8f8f8, #d2d2d2);
  background-repeat: no-repeat;
  background-size: calc(14 * var(--g)) calc(1.6 * var(--g)), calc(9 * var(--g)) calc(1.6 * var(--g)), calc(14 * var(--g)) calc(1.6 * var(--g)), calc(7 * var(--g)) calc(1.6 * var(--g)), 100% 100%;
  background-position: calc(5 * var(--g)) calc(4 * var(--g)), calc(5 * var(--g)) calc(8 * var(--g)), calc(5 * var(--g)) calc(12 * var(--g)), calc(5 * var(--g)) calc(16 * var(--g)), 0 0;
}
.aw-align.centre { background-position: calc(5 * var(--g)) calc(4 * var(--g)), calc(7.5 * var(--g)) calc(8 * var(--g)), calc(5 * var(--g)) calc(12 * var(--g)), calc(8.5 * var(--g)) calc(16 * var(--g)), 0 0; }
.aw-align.right { background-position: calc(5 * var(--g)) calc(4 * var(--g)), calc(10 * var(--g)) calc(8 * var(--g)), calc(5 * var(--g)) calc(12 * var(--g)), calc(12 * var(--g)) calc(16 * var(--g)), 0 0; }
.aw-align.justify { background-size: calc(14 * var(--g)) calc(1.6 * var(--g)), calc(14 * var(--g)) calc(1.6 * var(--g)), calc(14 * var(--g)) calc(1.6 * var(--g)), calc(14 * var(--g)) calc(1.6 * var(--g)), 100% 100%; }
.aw-spell span { font: 400 calc(9 * var(--g)) / 1 Helvetica, Arial, sans-serif; }
.aw-spell::after { content: '\2713'; position: absolute; margin: calc(-6 * var(--g)) 0 0 calc(12 * var(--g)); color: #d0121b; font-size: calc(13 * var(--g)); }
.aw-para { font-weight: 400; }

.aw-window {
  position: absolute;
  left: calc(30 * var(--g));
  right: calc(30 * var(--g));
  top: calc(80 * var(--g));
  bottom: calc(22 * var(--g));
  background: #fff;
  border: calc(1 * var(--g)) solid #333;
  box-sizing: border-box;
  box-shadow: calc(3 * var(--g)) calc(3 * var(--g)) 0 rgb(0 0 0 / 0.35);
}
.aw-title {
  position: absolute;
  inset: 0 0 auto;
  height: calc(20 * var(--g));
  display: flex;
  align-items: center;
  gap: calc(6 * var(--g));
  padding: 0 calc(7 * var(--g));
  background: repeating-linear-gradient(#fafafa 0 calc(1 * var(--g)), #a3a3a3 calc(1 * var(--g)) calc(2 * var(--g))) center / 100% calc(12 * var(--g)) no-repeat, #dddddd;
  border-bottom: calc(1 * var(--g)) solid #555;
  box-sizing: border-box;
}
.aw-name { margin: 0 auto; padding: 0 calc(8 * var(--g)); background: #dddddd; }
.aw-box {
  width: calc(11 * var(--g));
  height: calc(11 * var(--g));
  border: calc(1 * var(--g)) solid #444;
  box-sizing: border-box;
  background: linear-gradient(135deg, #8a8a8a, #f2f2f2);
}
.aw-box.zoom, .aw-box.shade { background: #ececec; box-shadow: inset calc(2 * var(--g)) calc(2 * var(--g)) 0 #fff; }
.aw-box.shade { background: linear-gradient(#444, #444) center / 70% calc(2 * var(--g)) no-repeat, #ececec; }
/* The text ruler: an eighth-inch scale (72 units to the inch) from the page's left margin. */
.aw-ruler {
  position: absolute;
  inset: calc(20 * var(--g)) 0 auto;
  height: calc(24 * var(--g));
  background:
    repeating-linear-gradient(90deg, #444 0 calc(1 * var(--g)), transparent 0 calc(72 * var(--g))) calc(56 * var(--g)) 100% / 100% calc(12 * var(--g)) no-repeat,
    repeating-linear-gradient(90deg, #444 0 calc(1 * var(--g)), transparent 0 calc(36 * var(--g))) calc(56 * var(--g)) 100% / 100% calc(7 * var(--g)) no-repeat,
    repeating-linear-gradient(90deg, #444 0 calc(1 * var(--g)), transparent 0 calc(9 * var(--g))) calc(56 * var(--g)) 100% / 100% calc(4 * var(--g)) no-repeat,
    #f1f1f1;
  border-bottom: calc(1 * var(--g)) solid #888;
  font: 400 calc(9 * var(--g)) / 1 Geneva, Helvetica, Arial, sans-serif;
}
.aw-ruler span { position: absolute; top: calc(3 * var(--g)); left: calc((56 + 72 * var(--i) - 3) * var(--g)); }
/* The page, and the text in Helvetica 19, its insertion point blinking at the end. */
.aw-page {
  position: absolute;
  inset: calc(44 * var(--g)) calc(14 * var(--g)) calc(14 * var(--g)) 0;
  background: #fff;
}
.aw-text {
  position: absolute;
  left: calc(56 * var(--g));
  right: calc(50 * var(--g));
  top: calc(22 * var(--g));
  font: 400 calc(19 * var(--g)) / 1.3 Helvetica, Arial, sans-serif;
  color: #000;
  cursor: text;
  user-select: text;
  -webkit-user-select: text;
}
.aw-text p { margin: 0 0 calc(12 * var(--g)); }
.aw-caret {
  display: inline-block;
  width: calc(1.6 * var(--g));
  height: 1.15em;
  margin-left: calc(0.6 * var(--g));
  vertical-align: -0.22em;
  background: #000;
  animation: aw-blink 1.06s steps(1) infinite;
}
@keyframes aw-blink { 50% { opacity: 0; } }
.aw-vscroll, .aw-hscroll { position: absolute; background: #eeeeee; box-sizing: border-box; }
.aw-vscroll { right: 0; top: calc(44 * var(--g)); bottom: calc(14 * var(--g)); width: calc(14 * var(--g)); border-left: calc(1 * var(--g)) solid #888; }
.aw-hscroll {
  inset: auto 0 0;
  height: calc(14 * var(--g));
  display: flex;
  justify-content: flex-end;
  border-top: calc(1 * var(--g)) solid #888;
  font: 400 calc(9 * var(--g)) / calc(13 * var(--g)) Geneva, Helvetica, Arial, sans-serif;
}
.aw-zoom, .aw-pageno { padding: 0 calc(6 * var(--g)); border-left: calc(1 * var(--g)) solid #888; background: #dddddd; }

/* Mac OS's zoom rectangles, as a window opens or closes: outlines that invert what's under them. */
.os-zoom { position: absolute; inset: 0; }
.os-zoom span {
  position: absolute;
  border: calc(1.5 * var(--g)) solid #fff;
  mix-blend-mode: difference;
  visibility: hidden;
}

/* Outlook Express 5: a new message, filling the screen under the menu bar. Its fields are real; the
   text in them is a little bigger than Mac OS 9's 12 px so it reads on any screen. */
.oe-window {
  position: absolute;
  left: calc(24 * var(--g));
  right: calc(24 * var(--g));
  top: calc(34 * var(--g));
  bottom: calc(20 * var(--g));
  display: flex;
  flex-direction: column;
  margin: 0;
  background: #dddddd;
  border: calc(1 * var(--g)) solid #333;
  box-shadow: calc(3 * var(--g)) calc(3 * var(--g)) 0 rgb(0 0 0 / 0.35);
}
.oe-window .aw-title { position: relative; flex: none; }
.oe-toolbar {
  flex: none;
  display: flex;
  gap: calc(6 * var(--g));
  padding: calc(6 * var(--g)) calc(10 * var(--g));
  border-bottom: calc(1 * var(--g)) solid #999;
  background: linear-gradient(#ececec, #d4d4d4);
}
.oe-tool {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: calc(3 * var(--g));
  min-width: calc(74 * var(--g));
  padding: calc(4 * var(--g)) calc(6 * var(--g));
  border: calc(1 * var(--g)) solid transparent;
  border-radius: calc(3 * var(--g));
  background: none;
  color: #6d6d6d;
  font: 400 calc(11 * var(--g)) / 1 Geneva, Helvetica, Arial, sans-serif;
}
/* Send Now: the window's main button, marked as Mac OS 9 marked a default button: raised, with a
   thick dark ring round it, its label bold. */
.oe-send {
  min-width: calc(92 * var(--g));
  margin: calc(1 * var(--g)) calc(8 * var(--g)) calc(1 * var(--g)) calc(4 * var(--g));
  border-color: #6b6b6b;
  border-radius: calc(5 * var(--g));
  background: linear-gradient(#ffffff, #d6d6d6);
  box-shadow: 0 0 0 calc(2 * var(--g)) #dcdcdc, 0 0 0 calc(4.5 * var(--g)) #1b1b1b;
  color: #111;
  font: 700 calc(12.5 * var(--g)) / 1 Charcoal, 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  cursor: pointer;
}
.oe-send:hover, .oe-send:focus-visible { background: linear-gradient(#ffffff, #c9d6ee); outline: none; }
.oe-send:active { background: linear-gradient(#9d9d9d, #c6c6c6); }
.oe-send .oe-icon { width: calc(32 * var(--g)); height: calc(22 * var(--g)); }
/* Toolbar icons: an envelope with its flap (Send Now), the others greyed out as they would be. */
.oe-icon {
  width: calc(26 * var(--g));
  height: calc(18 * var(--g));
  border: calc(1.5 * var(--g)) solid currentColor;
  border-radius: calc(2 * var(--g));
  background:
    linear-gradient(to bottom right, transparent calc(50% - 1px), currentColor 50%, transparent calc(50% + 1px)) left top / 50% 70% no-repeat,
    linear-gradient(to bottom left, transparent calc(50% - 1px), currentColor 50%, transparent calc(50% + 1px)) right top / 50% 70% no-repeat;
}
.oe-send .oe-icon { color: #1f5fbf; background-color: #fff; }
.oe-icon.later { border-radius: 50%; width: calc(18 * var(--g)); background: linear-gradient(currentColor, currentColor) 50% 30% / calc(1.5 * var(--g)) 40% no-repeat; }
.oe-icon.draft { background: repeating-linear-gradient(currentColor 0 calc(1 * var(--g)), transparent 0 calc(4 * var(--g))) 50% 50% / 70% 60% no-repeat; }
.oe-icon.attach { border-radius: calc(9 * var(--g)); width: calc(12 * var(--g)); }
.oe-headers {
  flex: none;
  padding: calc(8 * var(--g)) calc(12 * var(--g)) calc(6 * var(--g));
  border-bottom: calc(1 * var(--g)) solid #999;
}
.oe-row {
  display: grid;
  grid-template-columns: calc(78 * var(--g)) 1fr;
  align-items: center;
  margin-bottom: calc(5 * var(--g));
  font: 700 calc(12 * var(--g)) / 1 Charcoal, 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.oe-row > span:first-child { text-align: right; padding-right: calc(8 * var(--g)); }
.oe-row input, .oe-to, .oe-body {
  font: 400 max(13px, calc(17 * var(--g))) / 1.35 Geneva, Helvetica, Arial, sans-serif;
  color: #000;
}
.oe-row input {
  min-width: 0;
  padding: calc(3 * var(--g)) calc(5 * var(--g));
  border: calc(1 * var(--g)) solid #777;
  border-color: #555 #bbb #bbb #555;
  background: #fff;
  outline: none;
  user-select: text;
  -webkit-user-select: text;
}
.oe-row input:focus { box-shadow: 0 0 0 calc(2 * var(--g)) #7c9ad6; }
.oe-to { padding: calc(3 * var(--g)) calc(5 * var(--g)); }
.oe-body {
  flex: 1;
  min-height: 0;
  margin: 0;
  padding: calc(10 * var(--g)) calc(14 * var(--g));
  border: 0;
  border-top: calc(1 * var(--g)) solid #555;
  background: #fff;
  resize: none;
  outline: none;
  user-select: text;
  -webkit-user-select: text;
}
.oe-status {
  position: absolute;
  left: calc(12 * var(--g));
  right: calc(12 * var(--g));
  bottom: calc(8 * var(--g));
  margin: 0;
  font: 400 calc(12 * var(--g)) / 1.3 Geneva, Helvetica, Arial, sans-serif;
  color: #444;
  text-align: right;
  pointer-events: none;
}

/* The iMac's power light: green, softly, through the button's translucent face, with a faint halo
   on the plastic round it (light added: screen). */
.power-led {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  pointer-events: none;
}
.power-led span { position: absolute; border-radius: 50%; mix-blend-mode: screen; }
.led-halo { background: radial-gradient(closest-side, rgb(90 255 120 / 0.2), rgb(90 255 120 / 0.07) 55%, rgb(90 255 120 / 0) 100%); }
.led-face { background: radial-gradient(closest-side, rgb(120 255 150 / 0.34), rgb(70 235 105 / 0.26) 70%, rgb(70 235 105 / 0) 100%); }

/* Steam from the mug's coffee: white wisps on black (tools/mug_steam.py), screen-blended, so the black
   drops out and only the wisps lighten the wall. On the desk only (scene.js: .on). */
.steam {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  object-fit: fill;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.7s ease;
}
.steam.on { opacity: 1; }
.steam::-webkit-media-controls-start-playback-button { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  .steam { display: none; }
}

/* Keys pressed on the keyboard in the photo (contact): over the iMac's image, moved with it. Each
   pressed key is its own face cut from the photo (.key-face: the whole image, lined up with the
   one under it), moved down a little inside the key's outline and dimmed, as a key going down. */
.keys {
  position: absolute;
  left: calc(var(--x) * var(--u));
  top: calc(var(--y) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  pointer-events: none;
}
.key-press {
  position: absolute;
  overflow: hidden;
  border-radius: 10% / 14%;
  visibility: hidden;
  transition: visibility 0s 0.09s; /* (shown until the key is back up) */
}
.key-face {
  position: absolute;
  background: url(assets/Mac-4x.webp) 0 0 / 100% 100% no-repeat;
  transition: translate 0.09s ease-out, filter 0.09s ease-out;
}
.key-press.down { visibility: visible; transition-delay: 0s; }
.key-press.down .key-face { translate: 0 0.3%; filter: brightness(0.93); transition-duration: 0.03s; }

/* The portrait taped onto the iMac's bezel: part of the desk, moved with the iMac. */
.taped {
  position: absolute;
  left: calc((var(--x) - var(--w) / 2) * var(--u));
  top: calc((var(--y) - var(--h) / 2) * var(--u));
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  margin: 0;
  transform: rotate(var(--r));
  pointer-events: none;
}
.taped img:not(.tape) {
  display: block;
  width: 100%;
  height: 100%;
  box-shadow: 0 calc(1.2 * var(--u)) calc(3 * var(--u)) rgb(0 0 0 / 0.35);
}
/* One strip of masking tape across its top edge, onto the bezel: half on the photo, half on
   the frame. Photographed tape (Nano Banana Pro, cut out by tools/about_tape.py: any strip,
   in its own proportions), a touch see-through like real crepe tape, with a soft shadow.
   Its middle sits on the edge, at --at along it. */
.tape {
  position: absolute;
  left: var(--at);
  top: 0;
  width: calc(38 * var(--u));
  height: auto;
  opacity: 0.95;
  filter: drop-shadow(0 calc(0.5 * var(--u)) calc(0.8 * var(--u)) rgb(0 0 0 / 0.35));
  transform: translate(-50%, -50%) rotate(var(--a));
}

/* about / contact: empty wall for now. */
body.page { background: var(--wall); }

.debug-hits {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
