/* jas.black — home page. Dark by design: the work sits on black, as in the archive.
   Type direction "Gallery": Syne 500 for display (its heavier weights are drawn wider) with a faint white bloom (0.5),
   Martian Mono for everything small. No colour accent; the work brings colour. */
:root {
  --bg: #0b0b0b;
  --bg-2: #141414;
  --ink: #f4f4f2;
  --dim: #8f8f8a;
  --faint: #4a4a46;
  --line: rgba(244, 244, 242, .12);
  --accent: #d6d6d0;
  --display: "Syne", "Helvetica Neue", Arial, sans-serif;
  --util: "Martian Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* Gallery bloom at 0.5: a tight white core and two faint halos */
  --caps-track: -.005em; /* headings: each word starts with a capital */
  --bloom: 0 0 .3px #fff, 0 0 2.5px rgba(255, 255, 255, .45), 0 0 8px rgba(255, 255, 255, .26), 0 0 22px rgba(255, 255, 255, .12);   /* softer glow */
  --bloom-soft: 0 0 2px rgba(255, 255, 255, .36), 0 0 7px rgba(255, 255, 255, .15);
  --pad: clamp(16px, 4vw, 56px);
  color-scheme: dark;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 64px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 13px/1.7 var(--util);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
body.ov-open { overflow: hidden; }
body.ov-open .bar { visibility: hidden; }

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }

::selection { background: var(--accent); color: var(--bg); }

:focus-visible { outline: 1px solid var(--accent); outline-offset: 3px; }

/* ---------- top bar ---------- */

.bar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px var(--pad);
  font: 500 11px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
}
.bar nav { display: flex; gap: clamp(14px, 2.6vw, 34px); }
/* past the hero the bar sits on the page colour so it never overprints text */
.bar.solid {
  /* an eased fade, so the bar's edge doesn't read as a line over bright tiles */
  background: linear-gradient(
    var(--bg) 46%,
    rgba(11, 11, 11, .94) 54%,
    rgba(11, 11, 11, .82) 62%,
    rgba(11, 11, 11, .64) 70%,
    rgba(11, 11, 11, .44) 78%,
    rgba(11, 11, 11, .25) 86%,
    rgba(11, 11, 11, .1) 93%,
    rgba(11, 11, 11, 0));
  padding-bottom: 52px;
  pointer-events: none; /* the fade mustn't block clicks on what's under it */
}
.bar.solid a { pointer-events: auto; }
.bar a { color: #fff; opacity: .8; transition: opacity .2s; }
/* the label logo is the site's only name mark */
.bar .mark { display: block; opacity: 1; }
.bar .mark img {
  height: 34px;
  width: auto;
  filter: drop-shadow(0 4px 10px rgba(0, 0, 0, .6)) drop-shadow(0 0 1px rgba(244, 244, 242, .25));
}
@media (max-width: 560px) {
  .bar .mark img { height: 24px; }
  .bar nav { gap: 12px; }
}
.bar a:hover { opacity: 1; }

/* ---------- hero ---------- */

.hero {
  position: relative;
  height: 100svh;
  min-height: 520px;
  overflow: hidden;
  isolation: isolate;
}
.hero { cursor: none; touch-action: pan-y; background: var(--bg); }
@media (hover: none) { .hero { cursor: auto; } }
#screen {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
/* without WebGL (and in link-preview screenshots): a still of the hero itself, CRT and all, filling it */
.hero-fallback { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: none; }
.no-gl .hero-fallback { display: block; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.hero-cap {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 22px;
  z-index: 2;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px 16px;
  flex-wrap: wrap;
  pointer-events: none;
  font: 400 11px/1.4 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.hero-status[hidden] { display: none; }
.hero-count { color: var(--ink); opacity: .7; }
.hero-count[hidden] { display: none; }
/* a level's countdown: a glowing line along the foot of the hero that shrinks as the time runs out (red near the end) */
.hero-timer {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 12px;
  z-index: 2;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .07);
  pointer-events: none;
}
.hero-timer[hidden] { display: none; }
.hero-timer i {
  display: block;
  height: 100%;
  width: calc(var(--left, 1) * 100%);
  border-radius: inherit;
  background: rgb(var(--c, 200, 190, 255));
  box-shadow: 0 0 8px rgb(var(--c, 200, 190, 255)), 0 0 22px rgba(var(--c, 200, 190, 255), .55);
  transition: width .25s linear, background-color .4s, box-shadow .4s;
}

/* the small sliders: pixel size, brightness, theme colour */
.hero-tune {
  position: absolute;
  right: var(--pad);
  bottom: 50px;
  z-index: 3;
  display: grid;
  gap: 6px;
  width: 196px;
  padding: 10px 12px;
  cursor: auto;
  background: rgba(11, 11, 11, .55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.hero-tune[hidden] { display: none; }
.hero-tune label {
  display: grid;
  grid-template-columns: 52px 1fr;
  align-items: center;
  gap: 8px;
  font: 400 9px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.hero-tune input[type=range] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 14px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.hero-tune input[type=range]::-webkit-slider-runnable-track { height: 2px; border-radius: 2px; background: rgba(244, 244, 242, .25); }
.hero-tune input[type=range]::-moz-range-track { height: 2px; border-radius: 2px; background: rgba(244, 244, 242, .25); }
.hero-tune input[type=range].hue::-webkit-slider-runnable-track { background: linear-gradient(to right, hsl(0 80% 70%), hsl(60 80% 70%), hsl(120 80% 70%), hsl(180 80% 70%), hsl(240 80% 70%), hsl(300 80% 70%), hsl(360 80% 70%)); }
.hero-tune input[type=range].hue::-moz-range-track { background: linear-gradient(to right, hsl(0 80% 70%), hsl(60 80% 70%), hsl(120 80% 70%), hsl(180 80% 70%), hsl(240 80% 70%), hsl(300 80% 70%), hsl(360 80% 70%)); }
.hero-tune input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 10px; height: 10px; margin-top: -4px;
  border-radius: 50%;
  background: var(--tune-accent, var(--ink));
  box-shadow: 0 0 8px var(--tune-accent, #fff);
}
.hero-tune input[type=range]::-moz-range-thumb {
  width: 10px; height: 10px; border: 0;
  border-radius: 50%;
  background: var(--tune-accent, var(--ink));
  box-shadow: 0 0 8px var(--tune-accent, #fff);
}
.tune-toggle {
  /* barely there until you look for it */
  position: absolute;
  right: calc(var(--pad) - 6px);
  bottom: 14px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  color: var(--ink);
  background: none;
  border: 0;
  border-radius: 6px;
  opacity: .2;
  cursor: pointer;
  transition: opacity .2s;
}
.tune-toggle svg { width: 16px; height: 16px; display: block; }
.tune-toggle:hover, .tune-toggle:focus-visible, .tune-toggle[aria-expanded="true"] { opacity: .85; }
.hero-cap { padding-right: 36px; } /* room for the icon */

/* ---------- sections ---------- */

.sec {
  --sec-top: clamp(80px, 12vw, 160px);
  padding: var(--sec-top) var(--pad) 0;
  /* a nav link lands on the heading, just below the bar, not on the empty top padding */
  scroll-margin-top: calc(36px - var(--sec-top));
}
/* the first section follows the hero closely */
#work { --sec-top: clamp(40px, 5vw, 72px); }
.sec-h {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0 16px;
  padding-bottom: 18px;
  margin-bottom: clamp(28px, 4vw, 48px);
  border-bottom: 1px solid var(--line);
}
.sec-h h2 {
  margin: 0;
  font: 500 clamp(36px, 5vw, 52px)/.95 var(--display);   /* phones unchanged; desktops a size smaller (was 64px) */
  text-transform: capitalize;
  letter-spacing: var(--caps-track);
  text-shadow: var(--bloom);
}
.sec-h .more, .sec-note {
  font: 400 11px/1.5 var(--util);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
}
.sec-h .more:hover { color: var(--ink); }
/* a small link at the foot of a section, at the right (Films: "More films") */
.sec-foot { margin: clamp(28px, 3.5vw, 44px) 0 0; text-align: right; }
.sec-foot .more { font: 400 11px/1.5 var(--util); letter-spacing: .12em; text-transform: uppercase; color: var(--dim); }
.sec-foot .more:hover { color: var(--ink); }
.sec-note { margin: 0; max-width: 34ch; text-align: right; }

@media (max-width: 720px) {
  .sec-h .more { text-align: right; white-space: nowrap; }
  .sec-h .more-below { grid-column: 1 / -1; text-align: right; margin-top: 10px; }   /* Selected work: on its own line under the heading, at the right */
  .sec-note { text-align: left; margin-top: 10px; grid-column: 1 / -1; }
}

/* small caption used under pieces and films */
.meta {
  display: flex;
  gap: 10px;
  align-items: baseline;
  justify-content: space-between;
  padding-top: 10px;
  font: 400 11px/1.4 var(--util);
  letter-spacing: .06em;
  color: var(--dim);
}
.meta b { font-weight: 400; color: var(--ink); }

/* ---------- selected work ---------- */

/* four pieces: a row of four on a desktop, two by two on tablets and phones */
.feat {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0 clamp(14px, 2vw, 28px);
  align-items: start;
}
@media (max-width: 1000px) { .feat { grid-template-columns: repeat(2, 1fr); } }

.piece {
  display: block;
  width: 100%;
  break-inside: avoid;
  margin: 0 0 clamp(26px, 3vw, 44px);
  padding: 0;
  text-align: left;
  background: none;
  border: 0;
  cursor: zoom-in;
}
.frame {
  --lqip: none;
  position: relative;
  overflow: hidden;
  background: var(--bg-2);
}
/* blurred placeholder until the real image fades in over it */
.frame::before {
  content: "";
  position: absolute;
  inset: -8%;
  background: var(--lqip) center/cover no-repeat;
  filter: blur(16px);
}
.frame img, .frame .anim {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .5s ease, transform 1.2s cubic-bezier(.2,.7,.3,1);
}
.frame img.loaded, .frame .anim.on { opacity: 1; }
.frame .anim { z-index: 1; }
.frame mux-video.anim { display: block; --media-object-fit: cover; }
@media (hover: hover) {
  .piece:hover .frame img, .film:hover .frame img { transform: scale(1.025); }
}
/* a thumbnail that never arrived: show the title instead of a hole */
.frame.noimg::after {
  content: attr(data-title);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 24px;
  text-align: center;
  font: 500 clamp(20px, 2.2vw, 30px)/1.1 var(--display);
  letter-spacing: var(--caps-track);
  color: var(--faint);
}
.play {
  position: absolute;
  left: 12px; bottom: 12px;
  z-index: 2;
  font: 500 10px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  padding: 6px 8px;
  background: rgba(11, 11, 11, .7);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: var(--ink);
}

.empty {
  padding: 40px 0;
  font: 400 12px/1.7 var(--util);
  color: var(--faint);
}

/* ---------- films ---------- */

.films {
  /* two by two: each film's frame with its title underneath */
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 4vw, 56px) clamp(18px, 2.4vw, 32px);
}
.film {
  display: grid;
  gap: 0;
  align-content: start;
  width: 100%;
  padding: 0;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.film-info { padding-bottom: 4px; }
.film-info { min-width: 0; }
.film-info h3 {
  margin: 14px 0 10px;
  font: 500 clamp(22px, 2.2vw, 32px)/1 var(--display);
  letter-spacing: var(--caps-track);
  text-shadow: var(--bloom);
  text-wrap: balance;
  overflow-wrap: break-word;
}
.film-info p {
  margin: 0;
  max-width: 42ch;
  color: var(--dim);
  font-size: 12.5px;
}
.film-info .meta { justify-content: flex-start; padding-top: 0; margin-bottom: 14px; }
.film-info .watch {
  display: inline-block;
  margin-top: 14px;
  font: 500 11px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  border-bottom: 1px solid var(--accent);
  padding-bottom: 4px;
}
.film-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
.film-head h3 { margin-bottom: 0; }
.film-head .year { margin-left: .7em; font: 400 11px/1 var(--util); letter-spacing: .06em; color: var(--dim); text-shadow: none; }
.film-head .watch { margin-top: 0; flex: none; }
@media (max-width: 720px) {
  .films { grid-template-columns: 1fr; }
}

/* ---------- tools: a wall of CRT screens ---------- */

.sec-lead {
  margin: calc(-1 * clamp(10px, 2vw, 24px)) 0 clamp(28px, 4vw, 44px);
  max-width: 62ch;
  color: var(--dim);
}

.wall {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(40px, 5vw, 64px) clamp(18px, 2.4vw, 32px);
}
@media (max-width: 1000px) { .wall { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px)  { .wall { grid-template-columns: 1fr; } }

.tool { display: grid; gap: 10px; align-content: start; min-width: 0; }
.tool-icon {
  width: .9em;
  height: .9em;
  flex: none;
  border-radius: 22%;
  box-shadow: 0 0 14px rgba(200, 85, 245, .25);
}
.tool-name {
  display: flex;
  align-items: center;
  gap: .4em;
  margin: 0;
  font: 500 clamp(26px, 2.6vw, 38px)/1 var(--display);
  text-transform: capitalize;
  letter-spacing: var(--caps-track);
  text-shadow: var(--bloom-soft);
}
.tool-line { margin: 0; color: var(--dim); font-size: 12px; line-height: 1.7; max-width: 46ch; }
.tool-links {
  display: flex;
  gap: 18px;
  margin-top: 4px;
  font: 500 11px/1 var(--util);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.tool-links a { color: var(--dim); padding: 6px 0; white-space: nowrap; transition: color .2s; }
.tool-links a:hover { color: var(--ink); }
.tool-links .tool-go { color: var(--ink); border-bottom: 1px solid var(--ink); padding-bottom: 4px; }
#toolWall .tool-go { border-bottom: 0; padding-bottom: 6px; }   /* no underline on the home page */
.tool-links .tool-more { margin-left: auto; }

/* the monitor: the tool's card at full brightness, no frame. On
   hover (or when scrolled into view on a phone) a small white light
   runs round its edge. */
.screen {
  position: relative;
  display: block;
  aspect-ratio: 1200 / 630; /* the tools' share cards */
  max-width: 100%;
  overflow: hidden;
  isolation: isolate;
  border-radius: 14px / 12px;
  background: #050505;
  transition: box-shadow .4s;
}
.screen img, .screen canvas, .screen video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* a tool's loop is the right half of its card, so the name and text never re-render */
.screen video { left: auto; width: 50%; opacity: 0; transition: opacity .4s; }
.screen.on video.ready { opacity: 1; }
/* a small white light that runs round the screen's edge while it's on */
@property --edge-spin { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.screen-edge {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  opacity: 0;
  transition: opacity .3s;
  filter: drop-shadow(0 0 2px #fff) drop-shadow(0 0 6px rgba(214, 200, 255, .9));
}
.screen-edge::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 2px; /* the width of the light's path */
  background: conic-gradient(from var(--edge-spin),
    transparent 0deg 318deg,
    rgba(214, 200, 255, .5) 340deg,
    #fff 356deg,
    transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.screen.on { box-shadow: 0 0 40px rgba(214, 200, 255, .12); }
/* the moving artwork sits over the card's right half and fades in at its edge */
.screen .screen-fx {
  left: auto;
  right: 0;
  width: 50%;
  z-index: 1;
  opacity: 0;
  transition: opacity .3s; /* tools.js fades its left edge itself */
}
.screen .screen-fx.live { opacity: 1; }
.screen.on .screen-edge { opacity: 1; }
.screen.on .screen-edge::before { animation: edge-run 3.6s linear infinite; }
@keyframes edge-run { to { --edge-spin: 360deg; } }
/* Phones: the same running light, done cheaply. Animating the gradient's angle, masking it to the border and
   blurring two glows meant repainting the whole card every frame, and phones stuttered. Here the light is
   painted once on a big square behind a fixed border-shaped mask, and only that square turns (a transform,
   which the graphics chip does on its own). No blur filters: a brighter, slightly wider line stands in. */
@media (hover: none), (pointer: coarse) {
  .screen-edge {
    filter: none;
    overflow: hidden;
    padding: 2.5px;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  }
  .screen-edge::before {
    inset: auto;
    left: 50%; top: 50%;
    width: 160%; aspect-ratio: 1;
    padding: 0;
    border-radius: 0;
    transform: translate(-50%, -50%);
    background: conic-gradient(transparent 0deg 300deg, rgba(214, 200, 255, .55) 335deg, #fff 355deg, transparent 360deg);
    -webkit-mask: none; mask: none;
    will-change: transform;
  }
  .screen.on .screen-edge::before { animation: edge-turn 3.6s linear infinite; }
}
@keyframes edge-turn { to { transform: translate(-50%, -50%) rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .screen.on .screen-edge { opacity: 0; }
  .screen.on .screen-edge::before { animation: none; }
  .screen img, .screen canvas, .screen video { transition: none; }
}

/* ---------- tools page ---------- */

.page-head {
  padding: clamp(104px, 12vw, 150px) var(--pad) 0;
  display: grid;
  gap: 18px;
}
.page-head h1 {
  /* the same size as the home page's section headings */
  margin: 0;
  font: 500 clamp(36px, 5vw, 52px)/.95 var(--display);   /* phones unchanged; desktops a size smaller (was 64px) */
  text-transform: capitalize;
  letter-spacing: var(--caps-track);
  text-shadow: var(--bloom);
}
.page-head p { margin: 0; max-width: 58ch; color: var(--dim); font-size: 13px; }
/* the body of a page under its heading (About) */
.page-body { padding: clamp(40px, 5vw, 72px) var(--pad) 0; }
/* the About page: a faint line under its heading, spaced like the home page's section headings */
.page-head + .page-body { padding-top: 18px; }
.page-head + .page-body > .about { border-top: 1px solid var(--line); padding-top: clamp(28px, 4vw, 48px); }
.page-head nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-top: 12px;
  font: 500 11px/1 var(--util);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.page-head nav a { color: var(--dim); padding: 6px 0; }
.page-head nav a:hover { color: var(--ink); }

.tool-rows { padding: clamp(36px, 5vw, 70px) var(--pad) 0; display: grid; gap: clamp(36px, 5vw, 70px); }
.tool-row { border-top: 1px solid var(--line); padding-top: clamp(36px, 5vw, 70px); }   /* a line above every tool, the first included (under the intro) */
.tool-row {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  grid-template-rows: auto 1fr;
  grid-template-areas: "screen name" "screen info";
  gap: 16px clamp(24px, 4vw, 64px);
  align-items: start;
  scroll-margin-top: 90px;
}
.tool-row .tool-name { font-size: clamp(40px, 5vw, 72px); }
.tool-row .tool-lead { margin: 0; font: 500 clamp(19px, 1.8vw, 24px)/1.3 var(--display); color: var(--ink); max-width: 36ch; text-wrap: balance; }
.tool-row .tool-about { margin: 0; color: var(--dim); font-size: 12.5px; line-height: 1.8; max-width: 64ch; }
.tool-info { display: grid; gap: 16px; min-width: 0; grid-area: info; }
.tool-row > .screen { grid-area: screen; }
.tool-row > .tool-name { grid-area: name; margin: 0; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.tags li {
  font: 400 10px/1 var(--util);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  border: 1px solid var(--line);
  padding: 6px 8px;
  border-radius: 999px;
}
.buttons { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  font: 500 11px/1 var(--util);
  letter-spacing: .12em;
  text-transform: uppercase;
  border: 1px solid var(--line);
  color: var(--ink);
  transition: background .2s, border-color .2s, box-shadow .2s;
}
.btn:hover { border-color: rgba(244, 244, 242, .4); }
.btn-main { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn-main:hover { box-shadow: 0 0 18px rgba(255, 255, 255, .25); }
/* phones: the card already carries the tool's name, so the heading above it is left to screen readers */
@media (max-width: 860px) {
  .tool-row { grid-template-columns: 1fr; grid-template-rows: auto; grid-template-areas: "screen" "info"; }
  .tool-row > .tool-name { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}

/* ---------- about ---------- */

.about {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
  gap: clamp(28px, 6vw, 96px);
}
.about-text p {
  margin: 0 0 .9em;
  max-width: 32ch;
  font: 500 clamp(22px, 2.5vw, 34px)/1.25 var(--display); /* sentences: no capitalising here */
  text-shadow: var(--bloom-soft);
}
.about-text p + p { max-width: 60ch; font: 400 13px/1.8 var(--util); color: var(--dim); text-shadow: none; }
.links {
  list-style: none;
  margin: 0;
  padding: 0;
  font: 400 12px/1 var(--util);
  letter-spacing: .1em;
  text-transform: uppercase;
}
.links li { border-top: 1px solid var(--line); }
.links li:last-child { border-bottom: 1px solid var(--line); }
.links a { display: flex; justify-content: space-between; padding: 16px 0; color: var(--dim); transition: color .2s; }
.links a:hover { color: var(--ink); }
.link-name { display: inline-flex; align-items: center; gap: 12px; }
/* the icons glow softly, like the headings */
.link-icon {
  width: 18px;
  height: 18px;
  flex: none;
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--ink);
  filter: drop-shadow(0 0 2px rgba(255, 255, 255, .55)) drop-shadow(0 0 6px rgba(255, 255, 255, .25));
  transition: filter .2s;
}
.links a:hover .link-icon { filter: drop-shadow(0 0 3px rgba(255, 255, 255, .8)) drop-shadow(0 0 10px rgba(255, 255, 255, .35)); }
@media (max-width: 720px) { .about { grid-template-columns: 1fr; } }

/* ---------- contact ---------- */

.contact {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 24px;
  max-width: 900px;
}
.contact-lead { grid-column: 1 / -1; margin: 0 0 6px; color: var(--dim); max-width: 60ch; }
.contact label { display: grid; gap: 8px; min-width: 0; }
.contact label.wide { grid-column: 1 / -1; }
.contact label > span {
  font: 400 10px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
}
.contact input, .contact textarea {
  width: 100%;
  font: 400 14px/1.6 var(--util);
  color: var(--ink);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 12px 14px;
  resize: vertical;
  transition: border-color .2s, box-shadow .2s;
}
.contact input:focus, .contact textarea:focus { outline: none; border-color: rgba(244, 244, 242, .45); box-shadow: 0 0 14px rgba(214, 200, 255, .12); }
.contact .trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.contact-send { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; }
.contact-send .btn { cursor: pointer; font-family: var(--util); }
.contact-send .btn:disabled { opacity: .5; cursor: default; }
.contact-status { margin: 0; font: 400 12px/1.5 var(--util); color: var(--dim); }
.contact-status[data-kind="ok"] { color: var(--ink); text-shadow: var(--bloom-soft); }
.contact-status[data-kind="err"] { color: #ff9b9b; }
@media (max-width: 600px) { .contact { grid-template-columns: 1fr; } }

/* ---------- footer ---------- */

.foot {
  display: flex;
  justify-content: space-between;
  margin-top: clamp(100px, 14vw, 200px);
  padding: 22px var(--pad) max(22px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  font: 400 11px/1 var(--util);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ---------- viewer overlay ---------- */

.ov {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #060606;   /* solid, so nothing shows through from the page */
  opacity: 0;
  transition: opacity .2s ease;
}
.ov[hidden] { display: none; }
.ov.show { opacity: 1; }
.ov-stage {
  position: absolute;
  inset: 56px clamp(0px, 6vw, 80px) 64px;   /* clear of the arrows at the sides */
  display: flex;                              /* (a grid set an image off-centre: its <picture> wrapper has no box) */
  align-items: center;
  justify-content: center;
}
/* the <picture> wrapper takes no box of its own, so the image itself is fitted */
.ov-stage picture { display: contents; }
.ov-stage img, .ov-stage video {
  display: block;
  max-width: 100%;
  max-height: 100%;
  min-width: 0;
  min-height: 0;
  object-fit: contain;
}
.ov-stage mux-player {
  width: min(100%, calc((100dvh - 120px) * var(--ar, 1.7778)));
  aspect-ratio: var(--ar, 1.7778);
  --media-object-fit: contain;
  --controls-backdrop-color: transparent;
}
.ov-cap {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  bottom: 22px;
  display: flex;
  gap: 14px;
  align-items: baseline;
  font: 400 12.5px/1.4 var(--util);
  letter-spacing: .06em;
  color: var(--dim);
}
.ov-cap b { font: 500 24px/1 var(--display); letter-spacing: var(--caps-track); color: var(--ink); text-shadow: var(--bloom-soft); }
.ov-x {
  position: absolute;
  top: 14px;
  right: var(--pad);
  padding: 6px 0;
  background: none;
  border: 0;
  font: 500 11px/1 var(--util);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
  cursor: pointer;
}
.ov-x:hover { color: var(--ink); }
.ov-nav {
  position: absolute;
  top: 56px;
  bottom: 64px;
  width: 16vw;
  max-width: 140px;
  background: none;
  border: 0;
  cursor: pointer;
  opacity: .4;
  transition: opacity .2s;
}
.ov-nav:hover { opacity: 1; }
.ov-nav[hidden] { display: none; }
.ov-nav::before {
  content: "";
  position: absolute;
  top: 50%;
  width: 12px; height: 12px;
  border-left: 1px solid var(--ink);
  border-bottom: 1px solid var(--ink);
}
.ov-prev { left: 0; }
.ov-next { right: 0; }
.ov-prev::before { left: 26px; transform: rotate(45deg); }
.ov-next::before { right: 26px; transform: rotate(-135deg); }
@media (max-width: 720px) { .ov-nav { display: none; } }

/* a film's subtitle: after the title, the same face but lighter, thinner and dimmer */
.sub {
  margin-left: .5em;
  font-weight: 400;
  font-size: .78em;
  letter-spacing: 0;
  color: var(--dim);
  text-shadow: none;
  opacity: .85;
}

/* phones: films and pictures as big as the screen allows, edge to edge; turned sideways, the full screen */
@media (max-width: 720px) {
  .ov-stage { inset: 52px 0 70px; }
  .ov-stage mux-player { width: min(100vw, calc((100dvh - 122px) * var(--ar, 1.7778))); }
}
@media (max-height: 520px) and (orientation: landscape) {
  .ov-stage { inset: 0; }
  /* the film leaves a 40px strip at each side, and Close shrinks to a small × in the top-right corner of it,
     so it never sits over the picture */
  .ov-stage mux-player { width: min(calc(100vw - 80px), calc(100dvh * var(--ar, 1.7778))); }
  .ov-stage img, .ov-stage video { max-width: calc(100vw - 80px); }
  .ov-cap { display: none; }
  .ov-x { z-index: 3; top: 4px; right: 4px; width: 32px; height: 32px; padding: 0; font-size: 0; letter-spacing: 0; display: grid; place-items: center; }
  .ov-x::after { content: "✕"; font: 400 15px/1 var(--util); color: var(--dim); }
}

/* phones: Previous and Next along the bottom of the viewer, the title and year just above them */
.vbar { display: none; }
@media (max-width: 720px) {
  .vbar {
    position: absolute;
    left: 0; right: 0;
    bottom: max(10px, env(safe-area-inset-bottom));
    z-index: 4;
    display: flex;
    justify-content: space-between;
    padding: 0 12px;
  }
  .vbar[hidden] { display: none; }
  .vbar button {
    padding: 10px 6px;
    background: none;
    border: 0;
    color: rgba(244, 244, 242, .7);
    font: 500 11px/1 "Martian Mono", ui-monospace, Menlo, monospace;
    letter-spacing: .12em;
    text-transform: uppercase;
    -webkit-tap-highlight-color: transparent;
  }
  .vbar button:active { color: #fff; }
}
@media (max-height: 520px) and (orientation: landscape) { .vbar { display: none !important; } }
@media (max-width: 720px) {
  .ov-cap { bottom: calc(max(10px, env(safe-area-inset-bottom)) + 44px); z-index: 4; }
  .ov-stage { inset: 52px 0 96px; }
  .ov-stage mux-player { width: min(100vw, calc((100dvh - 148px) * var(--ar, 1.7778))); }
}

.cap-line { display: none; }
@media (max-width: 720px) {
  .ov-cap {
    left: 16px; right: 16px; bottom: auto;
    flex-direction: column; align-items: center; gap: 8px; text-align: center;
  }
  .ov-cap > b .sub, .ov-cap > span:not(.cap-line) { display: none; }
  .ov-cap > b { font-size: 22px; }
  .ov-cap .cap-line { display: block; font-size: 11px; letter-spacing: .06em; color: rgba(244, 244, 242, .55); }
  .vbar { bottom: auto; }
}

/* Phones held upright: the stage is a column. A spacer, the piece, Previous / Next, then the caption,
   centred in what's left below; the spacer and the caption's space share the room equally, so the piece
   and its buttons sit in the middle. The buttons follow the piece by layout, whatever size it turns out
   to be (placeUnder() moves them in). The piece leaves at least 150px for them. */
@media (max-width: 720px) and (orientation: portrait) {
  .ov-stage.docked {
    inset: 52px 0 env(safe-area-inset-bottom);
    flex-direction: column; justify-content: flex-start; align-items: center;
    container-type: size;
  }
  .ov-stage.docked::before { content: ''; flex: 0.35 1 0;   /* a third of the room below the piece: wide pieces sit between the middle and the top */ order: -1; min-height: 0; }
  .ov-stage.docked img, .ov-stage.docked video { flex: none; max-width: 100%; max-height: calc(100% - 150px); }
  .ov-stage.docked mux-player { flex: none; width: min(100%, calc((100cqh - 150px) * var(--ar, 1.7778))); }
  .ov-stage.docked > .vbar { position: static; order: 1; flex: none; align-self: stretch; }
  .ov-stage.docked > .ov-cap { position: static; order: 2; flex: 1 1 0; min-height: 0; display: flex; justify-content: center; }
  .ov-stage.docked > .ov-cap[hidden] { display: flex; visibility: hidden; }
}


/* home page tools: "Try it" starts in line with the text on the card above (the cards inset it 6.6% of their width) */
#toolWall .tool-links { padding-left: 6.6%; }

/* home page About: the bio after its first paragraph is for desktops; phones get the short version */
@media (max-width: 720px) { .about-text[data-intro] p.more { display: none; } }

/* Selected work: captioned like the film cards, the title a size down (four sit side by side) */
.piece .film-info h3 { font-size: clamp(18px, 1.5vw, 24px); }
.piece .film-head .year { display: inline-block; }
