/* Monty Marsh: Darkroom motion.
   The moves from a darkroom, a film set or a photo shoot. The design system sets every timing in
   Imagery and motion. motion.js sets data-motion="on" or "off" on the html element. Loops run unless motion is off.
   One-time moves run only when motion is on, so without script everything shows finished.
   Colors are design system tokens. The value after each token is its Darkroom value, used only if the token is missing. */

/* Focus pull: a headline pulls from soft to sharp as it arrives, like a lens finding focus.
   Every section headline, once. Centered headlines take transform-origin: 50% 50%. */
.mm-focus { transform-origin: 0 50%; }
:root[data-motion="on"] .mm-focus:not(.is-in) { opacity: 0; }
:root[data-motion="on"] .mm-focus.is-in { animation: mm-focus 1.5s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
@keyframes mm-focus {
  0% { opacity: 0; filter: blur(16px); transform: scale(1.02); }
  35% { opacity: 0.7; }
  100% { opacity: 1; filter: blur(0); transform: none; }
}

/* Aperture: film opens from a thin slit to its full frame. One reveal per collection.
   The first film tile, a Darkroom section's lead film and the Crenshaw Forward title card. Never every tile.
   The hero runs its own, faster version in hero.css.
   Add data-mm-after-focus when the headline above pulls focus at the same moment. motion.js then waits for the
   Focus pull to land, so the Aperture opens about 1.6 s after it starts. */
:root[data-motion="on"] .mm-aperture:not(.is-in) { clip-path: inset(49.4% 0 49.4% 0); }
:root[data-motion="on"] .mm-aperture.is-in { animation: mm-aperture 1.7s linear both; }
@keyframes mm-aperture {
  0% { clip-path: inset(49.4% 0 49.4% 0); }
  22% { clip-path: inset(49.4% 0 49.4% 0); animation-timing-function: cubic-bezier(0.72, 0, 0.18, 1); }
  100% { clip-path: inset(0 0 0 0); }
}

/* Flash: a studio strobe fires once, and a set of cards comes up out of the overexposure, like a frame shot on set.
   The card set in In front of the camera and the red carpet row in Press, each once. One flash for the whole set.
   Put mm-flash on the set, mm-flash__card on each card and mm-flash__img on each image.
   The strobe spreads 120px past each side of the set, so give its section overflow-x: clip. It must never widen the page. */
.mm-flash { position: relative; }
.mm-flash::after {
  content: "";
  position: absolute;
  z-index: 2;
  inset: -80px -120px;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0));
  opacity: 0;
  pointer-events: none;
}
:root[data-motion="on"] .mm-flash:not(.is-in) .mm-flash__card { opacity: 0; }
:root[data-motion="on"] .mm-flash.is-in::after { animation: mm-strobe 0.7s linear both; }
:root[data-motion="on"] .mm-flash.is-in .mm-flash__card { animation: mm-flash-card 0.9s ease both; }
:root[data-motion="on"] .mm-flash.is-in .mm-flash__img { animation: mm-flash-expose 0.9s cubic-bezier(0.1, 0.6, 0.3, 1) both; }
@media (max-width: 767px) { .mm-flash::after { inset: -48px -16px; } }
@keyframes mm-strobe {
  0% { opacity: 0; }
  10% { opacity: 0.9; animation-timing-function: ease-out; }
  100% { opacity: 0; }
}
@keyframes mm-flash-card {
  0% { opacity: 0; transform: scale(1.012); }
  13.33% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@keyframes mm-flash-expose {
  0% { filter: brightness(2.3) contrast(0.7) saturate(0.4); }
  100% { filter: none; }
}

/* Safelight: a wine glow breathes behind a Darkroom headline, like the red light in a darkroom.
   Put the class on the block that holds the headline, never on one that holds a button.
   The glow spreads past the headline block, so its section clips overflow, as mm-grain does. */
.mm-safelight { position: relative; isolation: isolate; }
.mm-safelight::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -70% -12%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--voice, #8A2A3D) 56%, transparent), transparent);
  opacity: 0.6;
  pointer-events: none;
  animation: mm-breathe 8s ease-in-out infinite;
}
@keyframes mm-breathe {
  0%, 100% { opacity: 0.32; }
  50% { opacity: 0.9; }
}

/* Grain: film grain under the content of every Darkroom section, jumping 24 times a second like film.
   Never over the 27 photographs, including the full screen view. */
.mm-grain { position: relative; isolation: isolate; overflow: clip; }
.mm-grain::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -180px;
  background: url("media/grain.png") 0 0 / 180px 180px;
  opacity: 0.16;
  mix-blend-mode: screen;
  pointer-events: none;
  animation: mm-grain 1s steps(1, end) infinite;
}
@keyframes mm-grain {
  0% { transform: translate(0px, 0px); }
  4.1667% { transform: translate(-36px, -138px); }
  8.3333% { transform: translate(-144px, 12px); }
  12.5% { transform: translate(120px, -120px); }
  16.6667% { transform: translate(90px, 102px); }
  20.8333% { transform: translate(6px, -12px); }
  25% { transform: translate(114px, -48px); }
  29.1667% { transform: translate(-174px, 174px); }
  33.3333% { transform: translate(-96px, -132px); }
  37.5% { transform: translate(-24px, -72px); }
  41.6667% { transform: translate(-138px, -24px); }
  45.8333% { transform: translate(84px, -156px); }
  50% { transform: translate(42px, 174px); }
  54.1667% { transform: translate(102px, -144px); }
  58.3333% { transform: translate(-30px, 66px); }
  62.5% { transform: translate(-144px, -36px); }
  66.6667% { transform: translate(-42px, 6px); }
  70.8333% { transform: translate(96px, 96px); }
  75% { transform: translate(30px, -138px); }
  79.1667% { transform: translate(-96px, -6px); }
  83.3333% { transform: translate(-24px, 84px); }
  87.5% { transform: translate(-156px, -60px); }
  91.6667% { transform: translate(-24px, 156px); }
  95.8333% { transform: translate(-138px, 42px); }
  100% { transform: translate(0px, 0px); }
}

/* Rolling: a film tile plays its muted trailer, or shows its still, and slowly pushes closer.
   Desktop only, once the pointer rests on the tile for 0.25 s, or on keyboard focus. Phones never roll. */
.mm-roll { position: relative; overflow: hidden; }
.mm-roll > video,
.mm-roll > img { display: block; width: 100%; height: 100%; object-fit: cover; transform: scale(1); transition: transform 0.7s ease-out; }
.mm-roll.is-rolling > video,
.mm-roll.is-rolling > img { transform: scale(1.07); transition: transform 10s linear; }

/* Cue mark: the gold cue mark from the film sits over the current section's name in the menu.
   motion.js sets aria-current on that link and flashes the mark once each time it moves.
   In a stacked phone menu, add mm-cue--side to set the mark beside the name. */
.mm-cue { position: relative; }
.mm-cue[aria-current="true"]::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 50%;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--gold, #C9962A);
}
.mm-cue--side[aria-current="true"]::before { top: 50%; left: -14px; margin: -3px 0 0; }
:root[data-motion="on"] .mm-cue.is-flash::before { animation: mm-cue 0.5s ease-out; }
@keyframes mm-cue {
  0% { transform: scale(2.4); opacity: 0.2; }
  30% { transform: scale(1.4); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* The cue mark once, on the Crenshaw Forward title card: it flashes after the Aperture opens the card.
   Put mm-cue-once inside the element that carries mm-aperture. */
.mm-cue-once { position: absolute; z-index: 2; width: 9px; height: 9px; border-radius: 50%; background: var(--gold, #C9962A); box-shadow: 0 0 10px rgba(201, 150, 42, 0.55); }
:root[data-motion="on"] .mm-cue-once:not(.is-flash) { opacity: 0; }
:root[data-motion="on"] .mm-cue-once.is-flash { animation: mm-cue-once 0.5s ease-out both; }
@keyframes mm-cue-once {
  0% { opacity: 0; transform: scale(2.4); }
  12% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}

/* Caption: a line arrives like a subtitle, the way the hero speaks. Pull quotes and the first line of a section. */
.mm-caption { transition: opacity 0.28s ease-out, transform 0.28s ease-out; }
:root[data-motion="on"] .mm-caption:not(.is-in) { opacity: 0; transform: translateY(6px); }

/* GUAPY's breath: a cyan glow breathes inside the GUAPY card, and nowhere else. */
.mm-guapy-breath { position: relative; isolation: isolate; overflow: hidden; }
.mm-guapy-breath::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -20%;
  background: radial-gradient(50% 60% at 50% 50%, color-mix(in srgb, var(--guapy-cyan, #1EC1CB) 26%, transparent), transparent 70%);
  opacity: 0.6;
  pointer-events: none;
  animation: mm-breathe 6s ease-in-out infinite;
}

/* The Motion switch, in the footer. A real switch: role="switch" and aria-checked carry its state.
   It reads Motion, then the track, then On or Off. On takes gold, the way gold marks every selected state.
   Off takes the control-line outline. The word beside the track means the state never rests on color alone. */
.mm-motion-switch {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-m, 10px);
  background: transparent;
  color: var(--ink, #F6E6EA);
  font: 600 14px / 20px var(--font-body, "Outfit", system-ui, sans-serif);
  cursor: pointer;
}
.mm-motion-switch__track {
  position: relative;
  flex: none;
  box-sizing: border-box;
  width: 44px;
  height: 24px;
  border: 1px solid var(--control-line, #76626B);
  border-radius: 999px;
  background: transparent;
}
.mm-motion-switch__track::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 3px;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  border-radius: 50%;
  background: var(--ink-mute, #9A8891);
  transition: transform 0.15s ease-out;
}
.mm-motion-switch[aria-checked="true"] .mm-motion-switch__track { border: 1.5px solid var(--gold, #C9962A); background: var(--gold-tint, #2E2210); }
.mm-motion-switch[aria-checked="true"] .mm-motion-switch__track::after { transform: translateX(19px); background: var(--gold, #C9962A); }
.mm-motion-switch__state { min-width: 24px; font-weight: 500; color: var(--ink-soft, #C9B6BC); }
.mm-motion-switch:focus-visible { outline: 2px solid var(--focus, #C9962A); outline-offset: 3px; }

/* Motion off: the loops hold still and the one-time moves show finished. */
:root[data-motion="off"] .mm-safelight::before,
:root[data-motion="off"] .mm-grain::after,
:root[data-motion="off"] .mm-guapy-breath::before { animation-play-state: paused; }
:root[data-motion="off"] .mm-roll > video,
:root[data-motion="off"] .mm-roll > img { transform: none; transition: none; }
:root[data-motion="off"] .mm-motion-switch__track::after { transition: none; }

/* Reduced Motion: the same, unless the reader turned motion on with the switch. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="on"]) .mm-safelight::before,
  :root:not([data-motion="on"]) .mm-grain::after,
  :root:not([data-motion="on"]) .mm-guapy-breath::before { animation: none; }
  :root:not([data-motion="on"]) .mm-roll > video,
  :root:not([data-motion="on"]) .mm-roll > img,
  :root:not([data-motion="on"]) .mm-caption,
  :root:not([data-motion="on"]) .mm-motion-switch__track::after { transition: none; }
}
