/* ------------------------------------------------------------
   PhotoSite — VSCO-inspired styles.
   White canvas, black sidebar, masonry grid.
   ------------------------------------------------------------ */

/* Self-hosted DM Sans (weights 400 + 500 — the only two the site uses). Served
   from our own origin so there's no round-trip to Google Fonts before text can
   render. Files in fonts/ are the exact woff2s Google serves for v17; both
   subsets share one file per weight axis. */
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/dmsans-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;
}
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/dmsans-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;
}
@font-face {
  font-family: 'DM Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/dmsans-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: 'DM Sans'; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/dmsans-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;
}

:root {
  --bg: #ffffff;
  --fg: #111111;
  --muted: #8a8a8a;
  --rule: #ececec;
  --topbar-bg: #000000;
  --topbar-fg: #ffffff;
  --topbar-height: 44px;
  --footer-height: 28px;            /* fixed bottom bar */
  /* Gap and side padding scale with the viewport so photo proportions stay
     consistent whether the window is fullscreen or split. clamp(min, fluid, max). */
  --gap: clamp(4px, 0.5vw, 8px);              /* vertical gap between stacked tiles */
  --col-gap: clamp(12px, 1.5vw, 24px);        /* horizontal gap between columns */
  --grid-side-pad: clamp(96px, 18vw, 360px);  /* whitespace at left/right of page */
  --max-width: none;                          /* let the grid fill available width */
  --font-sans: 'DM Sans', -apple-system, BlinkMacSystemFont, "Helvetica Neue",
               Helvetica, Arial, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

html {
  /* Always reserve the scrollbar's space so the viewport width can't shift when
     the (tall) grid makes the scrollbar appear. Otherwise the grid renders at the
     no-scrollbar width, then the classic Windows/desktop scrollbar narrows the
     page ~15px — images reflow but the masonry row-spans don't, throwing the
     gutters and photo bottoms off. Mobile already looked perfect because it uses
     overlay scrollbars (no width shift). */
  scrollbar-gutter: stable;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

/* ---------- Top navigation bar ---------- */

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* Grow to cover the top safe area (notch / Dynamic Island) so the black bar
     runs edge-to-edge, then pad the content clear of it. env() is 0 wherever
     there's no safe area (desktop), so this is a no-op there. */
  height: calc(var(--topbar-height) + env(safe-area-inset-top));
  background: var(--topbar-bg);
  color: var(--topbar-fg);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: env(safe-area-inset-top)
           max(clamp(20px, 4vw, 48px), env(safe-area-inset-right))
           0
           max(clamp(20px, 4vw, 48px), env(safe-area-inset-left));
}

.topbar-brand {
  /* Reset native button styling so it reads as plain text — then make it
     clickable (returns to the top of the photo view; wired in script.js). */
  background: none;
  border: 0;
  padding: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: #ffffff;
  white-space: nowrap;
  cursor: pointer;
}

.topbar-nav {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Top-right nav buttons: plain white text on the black bar, no outline.
   Enlarged a little for an obvious affordance; they swell on hover. */
.nav-link {
  background: none;
  border: 0;
  padding: 6px 12px;
  margin: 0;
  font-family: var(--font-sans);
  font-size: 15px;
  letter-spacing: 0.04em;
  text-align: center;
  cursor: pointer;
  color: rgba(255, 255, 255, 0.62);
  transition: color 200ms ease;
}

.nav-link span { pointer-events: none; }

/* Hover: brighten only (no swell). Active (current view): full white. */
.nav-link:hover { color: #ffffff; }
.nav-link.is-active { color: #ffffff; }

/* ---------- Main page area (push down below the fixed topbar) ---------- */

.page {
  padding-top: calc(var(--topbar-height) + env(safe-area-inset-top));
  /* Reserve space so content can scroll clear of the fixed footer. */
  padding-bottom: calc(var(--footer-height) + env(safe-area-inset-bottom));
}

/* ---------- View switching (pics / about) ---------- */

.view { display: none; }
.view.is-active { display: block; animation: viewReveal 0.5s ease-out backwards; }

/* When a view (Photos / About) becomes active, reveal its contents with a
   seamless top-to-bottom fade instead of snapping in. `backwards` fill applies
   the start frame at t=0 but leaves no clip-path lingering afterwards (so tile
   hover effects aren't clipped). Reduced-motion users get it near-instant via
   the global prefers-reduced-motion rule. */
@keyframes viewReveal {
  from { opacity: 0; clip-path: inset(0 0 100% 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}

/* ---------- About panel ---------- */

.about-panel {
  /* No max-width — the panel now uses the same horizontal footprint as the
     photo grid (identical var(--grid-side-pad) padding on each side).
     The old max-width: 640px was smaller than 2 × --grid-side-pad on wide
     screens, squashing the content to near-zero width. */
  margin: 8px 0 64px;
  padding: 0 var(--grid-side-pad);
  color: var(--fg);
  line-height: 1.6;
  font-size: 15px;
}

.about-title {
  font-size: 15px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #3d3d3d;
  text-align: center;
  margin: 32px 0 28px;
  font-weight: 500;
}

.about-block { margin: 0; }
.about-block:last-child { margin-bottom: 0; }

/* Contact section: centred label + content (blurb and email). */
.about-block--contact { text-align: center; }

/* Thin section-divider rule. Default inset matches the grid/hero side padding;
   inside the about panel it spans the (already padded) content width. */
.section-divider {
  border: 0;
  border-top: 1px solid #dddddd;   /* fine line */
  height: 0;
  /* hero rule overhangs the hero photo's edges a little; raised 30px (top -4 vs 26) */
  margin: -4px calc(var(--grid-side-pad) - 32px) 26px;
}
.about-panel .section-divider {
  width: 60%;            /* 40% shorter, centred */
  margin: 28px auto;
}
/* GEAR/CONTACT rules match the hero rule's length (overhang past the content edges). */
.about-panel .section-divider--full {
  width: auto;
  margin-left: -32px;
  margin-right: -32px;
}

.about-subhead {
  font-size: 12.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #565656;
  font-weight: 500;
  margin: 0 0 12px;
  text-align: center;
}

.about-text { margin: 0 0 12px; }
.about-text:last-child { margin-bottom: 0; }
/* Contact copy sits a touch smaller than the rest of the About text (15px). */
.about-block--contact .about-text { font-size: 14px; }

.about-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.about-list li {
  padding: 6px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 14px;
}

.about-list li:last-child { border-bottom: 0; }

/* Gear grid: three side-by-side device columns, each with its lenses underneath.
   Collapses to a single column on narrow viewports (see mobile media query). */
.gear-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-bottom: 24px;
}

.gear-col { min-width: 0; text-align: center; }
/* Titles stay aligned across columns (top of the cell); only the videos are
   nudged (below) so the clips sit at matched heights. */

.gear-device {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.01em;
  color: var(--fg);
  margin: 0 0 2px;       /* sit close above its video */
}

/* Looping gear demo video (e.g. the spinning lens) under a device heading.
   The clip's backdrop is whitened in the file itself; this feathers the four
   edges so the frame melts fully into the white page with no visible rectangle. */
.gear-video {
  display: block;
  width: 100%;
  height: auto;
  margin: 4px auto 0;    /* centred, tight under its title */
  -webkit-mask-image:
    linear-gradient(to right,  transparent 0, #000 3%, #000 97%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 3%, #000 97%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right,  transparent 0, #000 3%, #000 97%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 3%, #000 97%, transparent 100%);
  mask-composite: intersect;
}

/* The square camera-body clips display smaller (centred) so their height
   roughly matches the widescreen lens clip, each nudged down slightly. */
.gear-video--r10 { width: 55%; transform: translateY(5px); }
.gear-video--scl { width: 60%; transform: translateY(20px); }

/* Lower the single-line camera-body titles so they sit level with the middle
   of the Sigma entry's two-line title. */
.gear-col--r10 .gear-device,
.gear-col--scl .gear-device { transform: translateY(13px); }

.about-link {
  color: var(--fg);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  transition: border-color 120ms ease;
}

.about-link:hover { border-bottom-color: var(--fg); }

/* ---------- Site footer (copyright) ---------- */

.site-footer {
  /* Pinned to the bottom of the window, mirroring the fixed topbar. */
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  /* Grow to cover the bottom safe area (home indicator); content padded clear. */
  min-height: calc(var(--footer-height) + env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px
           max(clamp(18px, 5vw, 64px), env(safe-area-inset-right))
           calc(6px + env(safe-area-inset-bottom))
           max(clamp(18px, 5vw, 64px), env(safe-area-inset-left));
  background: var(--topbar-bg);
  text-align: center;
  color: rgba(255, 255, 255, 0.7);
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* Version tag on the left, copyright on the right (flex space-between above). */
.footer-version {
  color: rgba(255, 255, 255, 0.5);
  font-size: 11px;
  letter-spacing: 0.06em;
}


/* ---------- Hero slideshow ---------- */

.hero-section {
  /* Same horizontal margins as the collage grid below. */
  margin: 22px auto 0;
  padding: 0 var(--grid-side-pad);
}

/* Crossfade container.
   The first .hero-img stays in normal flow to give the container its height;
   all subsequent .hero-img elements are stacked absolutely on top of it. */
.hero-slideshow {
  position: relative;
  line-height: 0;       /* collapse any inline whitespace between images */
  cursor: zoom-in;      /* click to open the hero in the lightbox */
}

.hero-img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity 700ms ease, transform 220ms ease;
}

/* Hover swell — the visible slide physically grows the same subtle amount as the
   grid tiles (no overflow clip on the slideshow, so it expands past its frame
   rather than zooming in place). */
.hero-slideshow:hover .hero-img.is-active {
  transform: scale(1.012);
}

/* 2nd+ images out of flow — stacked on top of the first. */
.hero-img ~ .hero-img {
  position: absolute;
  top: 0;
  left: 0;
}

.hero-img.is-active {
  opacity: 1;
  z-index: 1;
}

/* Dot row — sits directly below the hero photo. */
.hero-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  padding: 14px 0 20px;
}

.hero-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1.5px solid var(--muted);
  background: transparent;
  cursor: pointer;
  padding: 0;
  transition: transform 200ms ease, background 200ms ease, border-color 200ms ease;
}

.hero-dot:hover {
  transform: scale(1.5);
  border-color: var(--fg);
}

.hero-dot.is-active {
  background: var(--fg);
  border-color: var(--fg);
  transform: scale(1.2);
}

/* ---------- Masonry grid ----------
   CSS Grid masonry simulation: grid-auto-rows is set to a fine unit (4px)
   and each tile's grid-row-end is computed by script.js from its aspect
   ratio, so tiles pack tightly without explicit column divs.
   row-gap is 0 — the tile spacing is baked into each tile's row span.
   --cols is set inline by script.js to match the breakpoint column count. */

.grid {
  max-width: var(--max-width);
  margin: 24px auto 64px;
  padding: 0 var(--grid-side-pad);
  display: grid;
  grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  grid-auto-rows: 1px;
  grid-auto-flow: row dense;
  row-gap: 0;
  column-gap: var(--col-gap);
}

.tile {
  display: flex;
  flex-direction: column;
  margin: 0;          /* override the browser's default figure margin */
  cursor: zoom-in;
  align-self: start;  /* top-align: tile tops at shared row boundaries are flush;
                         photos display at natural size with spacing below */
}

.tile img {
  width: 100%;
  height: auto;              /* natural aspect ratio — no cropping */
  flex: 0 0 auto;            /* don't grow/shrink; photo displays at its true size */
  display: block;
  background: #f4f4f4;       /* placeholder colour while loading */
  transition: opacity 180ms ease, transform 220ms ease;
  transform-origin: center;
}

.tile:hover img {
  transform: scale(1.012);
}

/* Looping tile — two stacked frames that cross-fade (see buildLoopTile). The
   wrapper carries the aspect ratio (set inline from the frames); the two images
   stack absolutely and cross-fade via opacity. The more-specific selector beats
   the `.tile img { height:auto }` rule above. */
.loop-frames {
  position: relative;
  width: 100%;
}
.tile--loop .loop-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Video tiles in the masonry grid.
   Displayed at 3:2 to match the half-photo tiles — the footage is squished
   vertically (object-fit: fill) rather than cropped, so no bars are removed. */

.video-crop-wrapper {
  position: relative;
  aspect-ratio: 3 / 2;
  width: 100%;
  /* overflow visible so the hover swell grows the frame outward like the photos
     (the video fills the wrapper exactly at rest, so nothing spills until hover). */
  overflow: visible;
}

/* The clips have the pillarbox bars cropped out (5:4) by build.py; the site
   stretches them to the 3:2 tile with object-fit:fill. fill NEVER clips (it
   stretches to fit exactly), so there's no overflow edge for a sub-pixel dark
   seam to live on — and the full frame height is shown (no vertical trim),
   matching the original look (incl. its slight horizontal stretch). */
.tile--video .video-crop-wrapper video {
  position: absolute;        /* out of flow, so the 5:4 video can't grow the 3:2 wrapper */
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
  transition: opacity 180ms ease, transform 220ms ease;
}

.tile--video:hover .video-crop-wrapper video {
  transform: scale(1.012);
}

/* ---------- Lightbox ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(15, 15, 15, 0.94);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 32px;
  cursor: zoom-out;
  /* The viewer handles its own pinch-zoom/pan (see script.js), so stop the
     browser's native touch gestures from interfering on mobile. */
  touch-action: none;
}

.lightbox.is-open { display: flex; }

.lightbox-figure {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: default;
}

.lightbox-figure img {
  max-width: 100%;
  max-height: calc(100vh - 120px);
  object-fit: contain;
  display: block;
}

/* Video wrapper in the lightbox — matches the 3:2 grid tiles. */
.lightbox-video-wrap {
  position: relative;
  display: none;
  overflow: hidden;
  /* Width: whichever is smaller — full available width, or the width that
     would result from using the full available height at 3:2.
     64px accounts for lightbox padding (32px × 2). */
  width: min(calc(100vw - 64px), calc((100vh - 120px) * 1.5));
  aspect-ratio: 3 / 2;
}

.lightbox-video-wrap.is-active { display: block; }

.lightbox-video-wrap video {
  /* Clips are 5:4 (bars cropped); stretch to the 3:2 wrapper with fill (no clip). */
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
}

.lightbox-caption {
  margin-top: 14px;
  color: #d9d9d9;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.lightbox-title {
  font-size: 14px;
  letter-spacing: 0.02em;
  color: #ffffff;
}

.lightbox-title:empty { display: none; }   /* hide gap when no title */

.lightbox-exif {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: #d9d9d9;
}

.lightbox-close {
  position: absolute;
  z-index: 2;            /* stay clickable above the video wrapper */
  top: 16px;
  right: 20px;
  background: none;
  border: 0;
  color: #ffffff;
  font-size: 32px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 120ms ease;
}

.lightbox-close:hover { opacity: 1; }

/* Prev / next chevrons on the lightbox edges. */
.lightbox-nav {
  position: absolute;
  z-index: 2;            /* paint above the video wrapper so clicks land on a video too */
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: 0;
  color: #ffffff;
  font-size: 56px;
  line-height: 1;
  padding: 12px 18px;
  cursor: pointer;
  opacity: 0.5;
  transition: opacity 120ms ease;
  font-family: inherit;
  user-select: none;
}

.lightbox-nav:hover { opacity: 1; }
.lightbox-nav:disabled,
.lightbox-nav.is-hidden { opacity: 0; pointer-events: none; }

.lightbox-nav--prev { left: 16px; }
.lightbox-nav--next { right: 16px; }

/* ---------- Mobile: compact topbar ---------- */

@media (max-width: 700px) {
  /* Wide side margins keep the 2-column grid from filling the screen
     edge-to-edge on phones. */
  :root {
    --topbar-height: 37px;
    --footer-height: 37px;
    --grid-side-pad: 35px;
  }

  /* The hero ignores the grid margins and runs nearly full-width. */
  .hero-section { padding: 0 16px; }
  /* Clip the manual swipe-slide to the frame (desktop stays overflow:visible so
     the hover swell can grow outward — there's no hover/slide on mobile). */
  .hero-slideshow { overflow: hidden; }
  /* Roomier spacing above and below the nav dots (dots keep their default size). */
  .hero-dots { padding: 16px 0 16px; }

  .topbar {
    padding: env(safe-area-inset-top) max(16px, env(safe-area-inset-right))
             0 max(16px, env(safe-area-inset-left));
  }
  .topbar-brand { font-size: 13px; }
  .nav-link { padding: 5px 9px; font-size: 13.5px; }

  /* Collapse the three-column gear grid to a single stack on narrow screens. */
  .gear-grid {
    grid-template-columns: 1fr;
    gap: 24px;
    margin-bottom: 14px;   /* tighter gap to the divider below the gear stack */
  }

  /* Gear clips in the stack; drop the desktop nudges. The square camera-body
     clips are narrower than the widescreen Sigma so they don't tower over it. */
  .gear-video { width: 72%; transform: none; }
  .gear-video--r10,
  .gear-video--scl { width: 52%; transform: none; }
  .gear-col--r10 .gear-device,
  .gear-col--scl .gear-device { transform: none; }

  /* Stack-spacing tweaks: more room above the R10 entry, and tighten the R10
     label-to-clip gap. The R10 clip has ~33% empty white space on top (camera
     sits low in frame), so we clip that top region away and pull the clip up by
     the same proportion — the camera rises toward its label, while the cropped
     (transparent) top no longer covers the label. Proportional units so it
     holds as the clip scales with screen width. */
  .gear-col--r10 { margin-top: 5px; }
  .gear-video--r10 { margin-top: -13%; clip-path: inset(30% 0 0 0); }
  .gear-video--scl { margin-top: -1px; }   /* nudge the SCL clip up toward its title */

  /* GEAR / CONTACT labels: match the gear-title size and sit closer to the
     divider above them. */
  .about-subhead { font-size: 16px; margin-top: -8px; }

  /* About: show the Sigma lens first in the single-column stack, then the R10. */
  .gear-col--sigma { order: 1; }
  .gear-col--r10   { order: 2; }
  .gear-col--scl   { order: 3; }

  /* Hero divider: pull in slightly so it's just a touch longer than the hero
     photo (not edge-to-edge), and sit a bit closer to the grid below. */
  #view-pics .section-divider { margin: -4px 10px 8px; }
  /* About full-width rules stay edge-to-edge (avoid h-overflow). */
  .about-panel .section-divider--full { margin-left: 0; margin-right: 0; }

  /* 2-column grid + 1px auto-rows now come from the base .grid rule (used on
     every screen). Phones just want a smaller bottom margin. */
  .grid { margin-top: 12px; margin-bottom: 24px; }
  .tile { min-width: 0; }

  /* Desktop stretches the 5:4 clips to 3:2; on mobile keep the no-stretch look
     instead — crop to the 3:2 slot, anchored to the bottom so the timestamp (and
     watermark) stay in view. */
  .tile--video .video-crop-wrapper video {
    object-fit: cover;
    object-position: center bottom;
  }

  /* Lightbox on phones: keep the prev/next arrows OFF the photo (portrait or
     landscape) by reserving a margin each side, and pull the arrows to the very
     edges into that margin. (Swipe-to-cycle is wired in script.js.) */
  .lightbox-figure img { max-width: calc(100vw - 84px); }
  .lightbox-video-wrap { width: min(calc(100vw - 84px), calc((100vh - 120px) * 1.5)); }
  .lightbox-nav { font-size: 40px; padding: 10px 6px; }
  .lightbox-nav--prev { left: 2px; }
  .lightbox-nav--next { right: 2px; }
}

/* ---------- Reduced motion ----------
   For visitors who've enabled the OS "reduce motion" accessibility setting:
   collapse transition/animation timing and drop the hover-zoom on photos and
   videos alike. (The hero auto-advance is also paused in script.js.) */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
  .tile:hover img { transform: none; }
  .tile--video:hover .video-crop-wrapper video { transform: none; }
  .hero-slideshow:hover .hero-img.is-active { transform: none; }
}
