/* ===========================================================================
   Base: reset, document defaults, page container, and the grain overlay.
   =========================================================================== */

/* --- Reset --------------------------------------------------------------- */

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

body {
  background: var(--mz-ink);
  color: var(--mz-text);
  font-family: var(--mz-font-sans);
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
  text-decoration: none;
}

img {
  display: block;
  max-width: 100%;
}

/* The build wraps images that have AVIF/WebP siblings in a <picture>. This
   keeps that wrapper out of layout entirely, so the <img> stays the flex or
   grid item it was and every existing selector still reaches it.

   `display: contents` promotes the picture's children into the parent's
   layout, and that includes the <source> elements. Nothing in the UA
   stylesheet hides them -- they are normally invisible only because <picture>
   itself renders them away -- so as flex items they each claimed a gap and
   pushed the mobile hero 80px taller. They have to be hidden explicitly. */
picture {
  display: contents;
}

picture > source {
  display: none;
}

button {
  font-family: inherit;
  cursor: pointer;
  border: none;
  background: none;
}

/* --- Page container ------------------------------------------------------
   Every section sits inside .mz-page, which caps the design at 1440px and
   centres it. Above that width the page is letterboxed against the dark
   background rather than stretching.
   ------------------------------------------------------------------------- */

.mz-page {
  max-width: var(--mz-page-max);
  margin: 0 auto;
}

/* --- Film grain -----------------------------------------------------------
   A single overlay, laid over every photograph on the site. It is the design
   system's `Image noise` effect: MONOTONE black at alpha 0.25 and density 0.7,
   so 0.25 x 0.7 = 0.175 of average coverage, in 1px grain.

   Figma's NOISE is a proprietary renderer with no CSS equivalent, so this is a
   calibrated approximation. What is matched is what reads: the colour, the
   grain size and the average coverage. Only the exact distribution differs.

   How: feTurbulence emits RGBA noise; the colour matrix throws its colour away,
   substitutes black, and drives alpha from the noise's red channel. That
   channel averages 0.5, the matrix scales it by 0.7 for a mean alpha of 0.35,
   and 0.5 opacity brings the mean coverage to the 0.175 above. `stitchTiles`
   makes the 128px tile repeat seamlessly.

   Do not drop the colour matrix: raw feTurbulence renders as full-colour RGB
   speckle, and this effect is monotone.
   ------------------------------------------------------------------------- */

/* Grain overlay for photographs. Absolutely positioned, so its container needs
   `position: relative`.

   It is a sibling of the image rather than a pseudo-element because several
   layouts stack it between the photo and a scrim, and DOM order is what
   decides that stacking — check each page's markup before reordering. */
.mz-img-grain {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.5;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='128' height='128' viewBox='0 0 128 128'%3E%3Cfilter id='n' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='1' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.7 0 0 0 0'/%3E%3C/filter%3E%3Crect width='128' height='128' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 128px 128px;
}
