/* AUTOMATIC — weareautomatic.co
   Architectural visualization studio
   Super-ultra-minimalist styles */

/* Adobe Fonts kit — Bio Sans (body) + Motor (headlines), used
   site-wide. Imported here rather than <link>-ed per page so every
   page that loads style.css gets the fonts with no per-file markup.
   Must stay above all other rules (@import ordering requirement). */
@import url("https://use.typekit.net/ynr4wbw.css");

/* ===== Self-hosted Roboto Mono =====
   Sourced once from Google Fonts and cached locally so the site
   keeps rendering even when fonts.googleapis.com is flaking, and
   so the page works fully offline. The files in /assets/fonts/
   are unmodified Google Fonts variable-font woff2 binaries.
   Six subsets, one @font-face each — the browser only fetches
   the subsets whose unicode-ranges contain glyphs on the page.
   Weight range 300-500 covers every weight the site uses. */
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-cyrillic-ext.woff2) format('woff2');
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-cyrillic.woff2) format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-greek.woff2) format('woff2');
  unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-vietnamese.woff2) format('woff2');
  unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Roboto Mono';
  font-style: normal;
  font-weight: 300 500;
  font-display: swap;
  src: url(assets/fonts/robotomono-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


:root {
  --bg: #FAFAFA;
  --fg: #111111;
  --muted: #777777;
  --rule: #E5E5E5;
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 2rem;
  --space-4: 4rem;
  --space-5: 8rem;
  --type-xs: 0.6875rem;   /* 11px */
  --type-sm: 0.75rem;     /* 12px */
  --type-md: 0.8125rem;   /* 13px */
  --type-lg: 1rem;        /* 16px */
  --type-xl: 1.25rem;     /* 20px */
  --tracking: 0.08em;
  /* Logo blend behavior — flips per theme so the wire reads correctly. */
  --logo-blend: multiply;
  --logo-filter: none;
}

/* Dark theme — inverts palette and switches the logo blend so the
   dark-on-white wire video reads as light-on-dark. */
:root[data-theme="dark"] {
  --bg: #111111;
  --fg: #FAFAFA;
  --muted: #888888;
  --rule: #2A2A2A;
  --logo-blend: screen;
  --logo-filter: invert(1);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Theme crossfade — when the light/dark toggle flips
   :root[data-theme], color-bearing properties ease between the two
   palettes instead of snapping. Applied broadly so the whole page
   transitions as one. This only animates on an actual theme change;
   the initial page load paints straight to the active palette (no
   property change means no transition fires). Elements that declare
   their own `transition` (links, reel arrows, the home-page slide
   panels) keep theirs — those already transition `color` where it
   matters. */
*, *::before, *::after {
  transition: background-color 320ms ease, color 320ms ease,
              border-color 320ms ease, fill 320ms ease;
}

html, body {
  height: 100%;
}

body {
  background: var(--bg);
  color: var(--fg);
  /* Site-wide body type — Bio Sans (Adobe Fonts kit, @import above).
     The home page overrides this via its own --body-font variable,
     and video.html sets Bio Sans explicitly on its .va-toggle
     buttons (buttons don't inherit font-family). */
  font-family: 'bio-sans', sans-serif;
  font-weight: 400;
  /* Body text bumped 25% above the base caption size — footer overrides
     this and stays at the smaller --type-xs. */
  font-size: calc(var(--type-md) * 1.25);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  /* Hide the lateral overflow created by the BANGIN' slide transition so
     no horizontal scrollbar appears mid-animation. */
  overflow-x: hidden;
}

a {
  color: inherit;
  text-decoration: none;
  transition: opacity 120ms ease, color 120ms ease;
}

a:hover {
  opacity: 0.55;
}

/* ---------- Header ---------- */

.site-header {
  display: flex;
  justify-content: space-between;
  /* Center the nav against the 100x100 logo on inner pages — and against
     the matching-height text wordmark on the home page. */
  align-items: center;
  padding: var(--space-3) var(--space-3);
  /* Nav links sit at the small caption size — matches the reel-button
     text on the home page. (The home page's own .alt-shell .site-header
     rule is more specific and still wins there.) */
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

/* Lock the wordmark slot to a 100px row so the header height — and the
   nav's vertical position — stays identical on every page, text or logo. */
.wordmark {
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  min-height: 100px;
}

/* Inner pages swap the AUTOMATIC text wordmark for the same animated
   logo used on the home page, scaled down to fit the header row. */
.wordmark-logo {
  display: inline-flex;
  align-items: center;
  /* Strip the link's hover dim — the logo's blend mode handles legibility. */
  transition: none;
}

.wordmark-logo:hover {
  opacity: 1;
}

.wordmark-video {
  /* Fixed 100x100 in the header — does not scale with header type. */
  width: 100px;
  height: 100px;
  display: block;
  /* Show the logo at its full native aspect ratio inside the 100x100
     slot (the source webms aren't square, so without this they get
     cropped along the top edge). The blend mode handles any letterbox
     space because the source is transparent outside the wire. */
  object-fit: contain;
  /* Same theme-aware blend behavior as the home page hero logo. */
  filter: var(--logo-filter);
  mix-blend-mode: var(--logo-blend);
}

.nav {
  display: flex;
  gap: var(--space-3);
}

.nav a[aria-current="page"] {
  border-bottom: 1px solid var(--fg);
  padding-bottom: 2px;
}

/* Light/Dark toggle in the nav. Sun and moon icons sit inside a 1px
   bordered box; the active mode is rendered in --fg, the inactive in
   --muted. */
.theme-toggle {
  background: none;
  border: 1px solid var(--rule);
  padding: 0.35em 0.55em;
  margin: 0;
  font: inherit;
  font-size: 0.5em;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  line-height: 1;
}

.theme-toggle .theme-light,
.theme-toggle .theme-dark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 120ms ease;
  color: var(--muted);
}

.theme-toggle .theme-icon {
  width: 1em;
  height: 1em;
  display: block;
}

/* Default (no data-theme set) treats Light as active. */
.theme-toggle .theme-light { color: var(--fg); }

[data-theme="dark"] .theme-toggle .theme-light { color: var(--muted); }
[data-theme="dark"] .theme-toggle .theme-dark { color: var(--fg); }

.theme-toggle:hover {
  border-color: var(--fg);
}

.theme-toggle:hover .theme-light,
.theme-toggle:hover .theme-dark {
  opacity: 0.55;
}

.theme-toggle:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 4px;
}

/* ---------- Main ---------- */

main {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Home page — reels and logo on one horizontal row,
   center-aligned vertically.  Layout: ← ATMOSPHERIC | LOGO | BANGIN' → */
.home-main {
  flex-direction: row;
  align-items: center;
  justify-content: center;
  padding: var(--space-4) var(--space-3);
  gap: var(--space-4);
}

.logo-mark {
  /* The video is the only flow child; the headline/tagline block sits
     absolutely above it. This keeps the video vertically centered with
     the reel labels on either side. */
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

.logo-text {
  position: absolute;
  bottom: 100%;
  left: 50%;
  /* -110px = the previous -10px nudge plus the requested 100px of extra
     breathing room between the tagline and the logo video. */
  transform: translate(-50%, -110px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}

.headline {
  margin: 0;
  /* 2.5x the previous --type-xl size — the dominant line on the home page. */
  font-size: calc(var(--type-xl) * 2.5);
  font-weight: 500;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  white-space: nowrap;
}

.tagline {
  margin: 0;
  /* Sits at the headline's pre-bump size so it reads as a quieter
     subordinate line beneath "We are automatic." */
  font-size: var(--type-xl);
  font-weight: 500;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  white-space: nowrap;
  /* 50% transparent — visually subordinate to the headline. */
  opacity: 0.5;
}

.logo-mark video {
  /* Use the file's native dimensions — no scaling. */
  width: auto;
  height: auto;
  display: block;
  /* Blend mode + filter flip with the active theme so the wire video
     (dark-on-white source) reads correctly on either palette. */
  filter: var(--logo-filter);
  mix-blend-mode: var(--logo-blend);
}

/* Showreel links flanking the logo */
.reel {
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  white-space: nowrap;
}

.reel .arrow {
  color: var(--muted);
  transition: transform 160ms ease, color 160ms ease;
}

.reel-left:hover .arrow {
  transform: translateX(-3px);
  color: var(--fg);
}

.reel-right:hover .arrow {
  transform: translateX(3px);
  color: var(--fg);
}

/* Inner pages — generous left margin, single column */
.page-main {
  padding: var(--space-4) var(--space-3) var(--space-4);
  max-width: 880px;
  width: 100%;
  margin: 0 auto;
}

.page-label {
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--space-3);
}

.page-content {
  /* Inherits the body's bumped size (25% larger than --type-md). */
  line-height: 1.7;
}

.page-content p + p {
  margin-top: var(--space-2);
}

.page-content p {
  max-width: 56ch;
}

/* The last paragraph in a .page-content reads as a footnote/closer:
   25% smaller than the surrounding body type, and dimmed to 50% so it
   recedes from the main copy. The max-width is divided by 0.75 so the
   container matches the *pixel* width of the larger paragraphs above
   (otherwise the smaller `ch` unit would shrink the column too). */
.page-content p:last-child {
  font-size: 0.75em;
  max-width: calc(56ch / 0.75);
  opacity: 0.5;
}

/* Inline prose links — give them a hairline underline so they read as
   links without breaking the minimalist tone. */
.page-content a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--muted);
}

.page-content a:hover {
  text-decoration-color: var(--fg);
  opacity: 1;
}

/* Trailing fade list — about page client types fade from full opacity
   on the first item to 10% on the last, walking the comma list. */
.fade-list {
  display: inline;
}
.fade-list > span {
  /* Each segment carries its own opacity inline. */
}

/* Lists used on inner pages */
.plain-list {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-1);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.two-col-list {
  list-style: none;
  /* Multi-column layout so the alphabetical list flows top-to-bottom
     of column 1, then column 2 — not row-by-row across both. */
  columns: 2;
  column-gap: var(--space-3);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.two-col-list li {
  break-inside: avoid;
  padding: 0;
  margin-bottom: var(--space-1);
}

/* ---------- Work / endless image feed ---------- */

.work-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* 200px of gutter on each side pulls the feed off the page edges. */
  padding: var(--space-3) 200px var(--space-4);
  width: 100%;
}

.work-label {
  /* Same caption treatment as .page-label but lives inside .work-main. */
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--space-3);
}

.work-feed {
  /* Masonry-style packing via CSS columns: each item flows into the
     shortest column, break-inside keeps the figure intact. The 20px
     column-gap pairs with each item's 20px bottom margin to give an
     even 20px rhythm between every neighbor. */
  display: block;
  column-count: 3;
  column-gap: 20px;
}

.work-item {
  position: relative;
  margin: 0 0 20px 0;
  break-inside: avoid;
  /* Helps Chromium-family browsers honor break-inside: avoid more
     consistently across columns. */
  page-break-inside: avoid;
  -webkit-column-break-inside: avoid;
}

.work-image {
  /* Width fills the column; height tracks the natural aspect ratio
     unless that would exceed 620px, in which case we cap the rendered
     height and use object-fit: cover to crop instead of stretch. */
  display: block;
  width: 100%;
  height: auto;
  max-height: 620px;
  object-fit: cover;
}

.work-caption {
  position: absolute;
  left: var(--space-2);
  bottom: var(--space-2);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--bg);
  /* Pill of fg-color behind the title so it stays legible against any
     image. Reveals on hover with a soft fade + small upward nudge. */
  background: var(--fg);
  padding: 0.5em 0.75em;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 200ms ease, transform 200ms ease;
  pointer-events: none;
}

.work-item:hover .work-caption,
.work-item:focus-within .work-caption {
  opacity: 1;
  transform: translateY(0);
}

.work-sentinel {
  /* Invisible IntersectionObserver target near the end of the feed —
     when it enters the viewport (with rootMargin), another batch loads. */
  height: 1px;
  width: 100%;
}

.work-grid {
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  margin-top: var(--space-3);
}

.work-grid li {
  border-top: 1px solid var(--rule);
  padding: var(--space-2) 0;
  display: grid;
  grid-template-columns: 3rem 1fr 1fr 8rem;
  gap: var(--space-2);
  align-items: baseline;
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.work-grid li:last-child {
  border-bottom: 1px solid var(--rule);
}

.work-grid .num {
  color: var(--muted);
}

.work-grid .meta {
  color: var(--muted);
}

.work-grid .year {
  text-align: right;
  color: var(--muted);
}

/* Contact specifics */
.contact-block {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: var(--space-1) var(--space-3);
  font-size: var(--type-sm);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
}

.contact-block dt {
  color: var(--muted);
}

/* ---------- BANGIN' showreel slide ---------- */

/* The home page is wrapped in .home-stage so it can be transformed as a
   single unit when the BANGIN' link is clicked. The default state takes
   over the body's flex column behavior the unwrapped layout used to. */
.home-stage {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  flex: 1;
  width: 100%;
  /* Solid bg inside the stage so the logo's mix-blend-mode (multiply in
     light theme, screen in dark) has something to blend against — the
     stage's transform creates its own stacking context. */
  background: var(--bg);
  transform: translateX(0);
  transition: transform 700ms cubic-bezier(0.7, 0, 0.2, 1);
  will-change: transform;
}

/* The home stage slides off in the opposite direction from the panel
   that's coming in — bangin' panel comes from the right, so home goes
   left; atmospheric panel comes from the left, so home goes right. */
[data-view="bangin"] .home-stage {
  transform: translateX(-100%);
}

[data-view="atmospheric"] .home-stage {
  transform: translateX(100%);
}

/* Full-viewport panel for either showreel. Side is set per-instance via
   data-side, which controls the off-screen starting transform. */
.video-panel {
  position: fixed;
  inset: 0;
  background: var(--bg);
  transition: transform 700ms cubic-bezier(0.7, 0, 0.2, 1);
  will-change: transform;
  z-index: 50;
  display: flex;
  flex-direction: column;
  padding: var(--space-3);
  gap: var(--space-3);
}

.video-panel[data-side="right"] {
  transform: translateX(100%);
}

.video-panel[data-side="left"] {
  transform: translateX(-100%);
}

[data-view="bangin"] .video-panel[data-reel="bangin"],
[data-view="atmospheric"] .video-panel[data-reel="atmospheric"] {
  transform: translateX(0);
}

.video-close {
  align-self: flex-start;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: var(--fg);
  font-size: calc(var(--type-sm) * 1.5);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  cursor: pointer;
  display: inline-flex;
  align-items: baseline;
  gap: var(--space-1);
  transition: opacity 120ms ease;
}

/* Atmospheric (left) panel: 'Back' sits at the right edge, arrow → home. */
.video-panel[data-side="left"] .video-close {
  align-self: flex-end;
}

.video-close .arrow {
  color: var(--muted);
  transition: transform 160ms ease, color 160ms ease;
}

.video-close:hover {
  opacity: 0.55;
}

/* Right-panel back arrow points left toward home; nudges left on hover. */
.video-panel[data-side="right"] .video-close:hover .arrow {
  transform: translateX(-3px);
  color: var(--fg);
}

/* Left-panel back arrow points right toward home; nudges right on hover. */
.video-panel[data-side="left"] .video-close:hover .arrow {
  transform: translateX(3px);
  color: var(--fg);
}

.video-close:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 4px;
}

.video-frame {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;
}

/* Replay overlay — hidden during playback, surfaces when the video ends.
   Click restarts the reel from frame 0 (handled in JS). */
.video-replay {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.96);
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 1px solid var(--fg);
  background: var(--bg);
  color: var(--fg);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease, transform 220ms ease, background 160ms ease, color 160ms ease;
}

.video-frame.is-ended .video-replay {
  opacity: 1;
  pointer-events: auto;
  transform: translate(-50%, -50%) scale(1);
}

.video-replay:hover {
  background: var(--fg);
  color: var(--bg);
}

.video-replay:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 4px;
}

.video-replay-icon {
  width: 38px;
  height: 38px;
  /* Optical-center the triangle in the circle (the glyph's mass sits
     slightly left of center). */
  margin-left: 4px;
  display: block;
}

.reel-video {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
}

/* Showreel videos capped at 960x540, while still shrinking to fit smaller
   viewports (the min() picks whichever is more restrictive). */
.video-panel[data-reel="bangin"] .reel-video,
.video-panel[data-reel="atmospheric"] .reel-video {
  max-width: min(100%, 960px);
  max-height: min(100%, 540px);
}

/* ---------- Video page grid + lightbox ---------- */

/* 3-column grid for the Video page. Smaller GIF thumbnails sit in a
   contact-sheet layout, distinct from the masonry Images feed. The
   explicit display: grid re-establishes grid layout because .work-feed
   is now display: block (masonry via CSS columns). */
.video-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 60px;
}

/* Video items should not inherit the masonry tile's bottom margin —
   the grid handles spacing via gap. */
.video-grid .work-item {
  margin-bottom: 0;
}

/* And the gif thumbnails want their natural aspect ratio with no crop. */
.video-grid .work-image {
  max-height: none;
  object-fit: fill;
}

/* Click targets on video.html and images.html — same visual treatment
   as a regular feed item, but signal interactivity with a pointer
   cursor and a focus ring. */
.video-item,
.image-item {
  cursor: pointer;
}

.video-item:focus-visible,
.image-item:focus-visible {
  outline: 1px solid var(--fg);
  outline-offset: 6px;
}

/* Full-viewport overlay; iframe is injected on open and removed on close
   so the Vimeo player fully tears down. */
.video-lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.92);
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
}

.video-lightbox[aria-hidden="false"] {
  display: flex;
}

.video-lightbox-frame {
  position: relative;
  width: min(100%, 960px);
  aspect-ratio: 16 / 9;
  max-height: min(100%, 540px);
  background: #000;
  /* Clip the iframe so Vimeo's bottom branding/recommendations strip
     falls outside the visible area. */
  overflow: hidden;
}

.video-lightbox-frame iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  /* Slightly taller than the visible frame; the extra height pushes
     Vimeo's bottom branding past the clip line. */
  height: calc(100% + 64px);
  border: 0;
  display: block;
}

/* Full-viewport overlay for images.html. The clicked image is sized to
   fit within the viewport with a 40px margin on every edge — `padding`
   on the overlay provides the gutter, and the image's max-width/height
   100% + object-fit: contain takes care of letterboxing without crop. */
.image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.92);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 40px;
}

.image-lightbox[aria-hidden="false"] {
  display: flex;
}

.image-lightbox-img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}

/* Shared close button for both lightboxes — always light against the
   dark backdrop, regardless of theme. */
.video-lightbox-close,
.image-lightbox-close {
  position: absolute;
  top: var(--space-2);
  left: var(--space-3);
  background: none;
  border: 0;
  padding: 0.5em 0;
  margin: 0;
  font: inherit;
  color: #f5f3ee;
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  font-size: var(--type-sm);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
}

.video-lightbox-close .arrow,
.image-lightbox-close .arrow {
  color: rgba(245, 243, 238, 0.55);
  transition: transform 160ms ease, color 160ms ease;
}

.video-lightbox-close:hover .arrow,
.image-lightbox-close:hover .arrow {
  transform: translateX(-3px);
  color: #f5f3ee;
}

.video-lightbox-close:focus-visible,
.image-lightbox-close:focus-visible {
  outline: 1px solid #f5f3ee;
  outline-offset: 4px;
}

/* Lock background scroll while the lightbox is open. */
body.has-lightbox {
  overflow: hidden;
}

/* ---------- Footer ---------- */

.site-footer {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: var(--space-3);
  font-size: var(--type-xs);
  letter-spacing: var(--tracking);
  text-transform: uppercase;
  color: var(--muted);
  border-top: 1px solid var(--rule);
  margin-top: var(--space-4);
}

.home-main + .site-footer {
  border-top: none;
  margin-top: 0;
}

.site-footer a:hover {
  color: var(--fg);
  opacity: 1;
}

/* ---------- Responsive ---------- */

@media (max-width: 700px) {
  .site-header {
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-2);
    /* Drop header type back closer to body size on narrow screens
       so the toggle and four links can still sit on one row. */
    font-size: var(--type-md);
  }
  .site-footer {
    padding: var(--space-2);
  }
  .nav {
    gap: var(--space-2);
    flex-wrap: wrap;
  }
  .home-main {
    flex-direction: column;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-2);
  }
  .logo-mark {
    /* On phones, the reels stack above and below the logo, so the
       absolute-positioned text would overlap the upper reel. Drop the
       text back into normal flow as a column above the video. */
    flex-direction: column;
  }
  .logo-text {
    position: static;
    transform: none;
    margin-bottom: var(--space-2);
  }
  .logo-mark video {
    /* On narrow screens, allow the native logo to scale down if it would
       otherwise overflow — but never scale it up beyond its native size. */
    max-width: 90vw;
    height: auto;
  }
  .work-grid li {
    grid-template-columns: 2.5rem 1fr;
    gap: 0.25rem var(--space-1);
  }
  .work-grid .meta,
  .work-grid .year {
    grid-column: 2;
    text-align: left;
  }
  .two-col-list {
    columns: 1;
  }
  .work-main {
    /* The 200px desktop gutters would eat the whole viewport on narrow
       screens — fall back to the standard page padding here. */
    padding: var(--space-2) var(--space-2) var(--space-3);
  }
  .work-feed {
    /* Masonry collapses to a single column on phones; one image fills
       the feed, 20px between neighbors. */
    column-count: 1;
    column-gap: 0;
  }
  .video-grid {
    /* 3 columns is too tight at phone widths; collapse to a single
       column so each GIF gets the full feed width. */
    grid-template-columns: 1fr;
    gap: 40px;
  }
  .contact-block {
    grid-template-columns: 1fr;
    gap: 0;
  }
  .contact-block dd {
    margin-bottom: var(--space-1);
  }
}

/* Reduce motion */
@media (prefers-reduced-motion: reduce) {
  .logo-mark video {
    animation: none;
  }
  .home-stage,
  .video-panel {
    transition: none;
  }
}
