/* photo — one full-bleed image, flush, screened by the tonality. */

/* The imageless posture is the LACK of a media element (lockup's rule), so the
   template renders no crop at all for an image that does not exist — trimmed,
   which a selector cannot do. What reaches here is a value that was written and
   still shows nothing: a row that climbs on one tells the bar a photograph is
   under it while showing none. */
.sk-component[data-sk="photo"]:has(> .sk-photo-media > .sk-art:not([src=""]):not([src*="{"])) {
  margin-block-start: calc(-1 * var(--sk-chrome-clear, 0px));
  --sk-chrome-member-stage: var(--sk-chrome-row-stage);
  --sk-chrome-ground: media;
}

.sk-photo {
  padding-block: 0;
}
/* The crop WINDOW (.sk-crop: the shared tier owns cover and true focal inside). */
.sk-photo-media {
  width: 100%;
  /* svh, not vh: stable under the mobile URL bar. */
  height: calc(var(--sk-photo-h, 46) * 1svh);
}
/* Boundary rule: the plate stands square; a bounded row's clip owns the corner. */
.sk-photo .sk-photo-media {
  --sk-media-radius: 0;
}

/* A fixed crop instead of a viewport ratio: a letterbox plate holds its
 * proportions on every display. */
.sk-photo:not([data-aspect="none"], [data-aspect=""]) .sk-photo-media {
  height: auto;
}
/* "none" leaves the token invalid, so the declaration falls back. */
.sk-photo[data-aspect] .sk-photo-media {
  aspect-ratio: var(--sk-aspect);
}

/* Scroll Motion: keyed on the page's data-scroll-motion, sized by its strength tokens.
   The picture moves, never the crop, which is the entrance's unit. */
@media screen and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) and (view-timeline: --sk-photo-scroll block) {
    body:is([data-scroll-motion="parallax"], [data-scroll-motion="zoom"]) .sk-photo {
      view-timeline: --sk-photo-scroll block;
      /* Not auto, which is the page's scroll-padding. */
      view-timeline-inset: 0px;
    }
    body:is([data-scroll-motion="parallax"], [data-scroll-motion="zoom"])
      .sk-photo
      .sk-photo-media
      > .sk-art {
      /* The crop's center in the picture's own box: the offset the shared crop rule gives a ratio-sized picture. */
      transform-origin: calc(50cqw - clamp(100cqw - 100%, 50cqw - var(--sk-focal-x, 50%), 0px))
        calc(50cqh - clamp(100cqh - 100%, 50cqh - var(--sk-focal-y, 50%), 0px));
    }
    body[data-scroll-motion="parallax"] .sk-photo .sk-photo-media > .sk-art {
      /* Twice the travel, once each way, and a hair more so a rounded pixel never shows an edge. */
      scale: calc(1 + 2 * var(--kit-scroll-travel) + 0.02);
      animation:
        sk-photo-enter linear both,
        sk-photo-leave linear both;
      animation-composition: add;
      animation-timeline: --sk-photo-scroll, --sk-photo-scroll;
      animation-range: entry, exit;
    }
    /* The first row is the hero: its bands open at rest and only leave. */
    body[data-scroll-motion="parallax"]
      :where(.sk-section:not(.sk-section ~ .sk-section))
      .sk-photo
      .sk-photo-media
      > .sk-art {
      animation: sk-photo-leave linear both;
      animation-composition: add;
      animation-timeline: --sk-photo-scroll;
      animation-range: exit;
    }
    body[data-scroll-motion="zoom"] .sk-photo .sk-photo-media > .sk-art {
      animation: sk-photo-zoom linear both;
      animation-timeline: --sk-photo-scroll;
      animation-range: exit;
    }
  }
}

@keyframes sk-photo-enter {
  from {
    translate: 0 calc(-100cqh * var(--kit-scroll-travel));
  }
  to {
    translate: 0 0;
  }
}
@keyframes sk-photo-leave {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 calc(100cqh * var(--kit-scroll-travel));
  }
}
@keyframes sk-photo-zoom {
  from {
    scale: 1;
  }
  to {
    scale: var(--kit-scroll-zoom);
  }
}
