/* photo — one photograph, flush and full by default, 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. */
/* Plain is an answer: without it the serve pass's picture stamp speaks over this arm. */
.sk-component[data-sk="photo"] {
  --sk-chrome-ground: plain;
}
.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;
}

/* The crop WINDOW (.sk-crop: the shared tier owns cover and true focal inside). */
.sk-photo-media {
  width: 100%;
  height: calc(var(--sk-photo-h, 46) * var(--sk-screen-block) / 100);
}
/* Content Rail: the plate sits inside the copy's side margins. Flush (the
   default) stays edge to edge. Padding on the band, not a margin on the
   plate, so Width and Align still seat the photograph inside the rail. */
.sk-photo[data-inset="rail"] {
  padding-inline: var(--sk-page-rail-start) var(--sk-page-rail-end);
}
/* Width is the measure only. Narrow is about a third of the band, Medium
   half of it. Full (the default) keeps the pane. A full-height row grows a
   figure's payload to the band; these opt that growth off so a crop keeps
   its ratio. */
.sk-photo:is([data-width="narrow"], [data-width="medium"]) > .sk-photo-media {
  flex: none;
  max-width: 100%;
}
.sk-photo[data-width="narrow"] > .sk-photo-media {
  width: calc(100% / 3);
}
.sk-photo[data-width="medium"] > .sk-photo-media {
  width: 50%;
}
/* Align is the seat, at any width. An omitted align keeps the seat each
   width already had: Narrow at the start, Medium centered. An explicit
   data-align overrides that. Full is the pane, so a seat does not move it. */
.sk-photo[data-width="narrow"]:not([data-align="left"], [data-align="center"], [data-align="right"])
  > .sk-photo-media {
  margin-inline: 0 auto;
  align-self: flex-start;
}
.sk-photo[data-width="medium"]:not([data-align="left"], [data-align="center"], [data-align="right"])
  > .sk-photo-media {
  margin-inline: auto;
  align-self: center;
}
.sk-photo[data-align="left"] > .sk-photo-media {
  margin-inline: 0 auto;
  align-self: flex-start;
}
.sk-photo[data-align="center"] > .sk-photo-media {
  margin-inline: auto;
  align-self: center;
}
.sk-photo[data-align="right"] > .sk-photo-media {
  margin-inline: auto 0;
  align-self: flex-end;
}
/* 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);
}
/* Narrow or Medium with Crop None would be a tall sliver: the viewport
   height on a third or a half of the band. Fall back to 3:2, the still
   photograph the crop list already offers. Full width keeps the viewport. */
.sk-photo:is([data-width="narrow"], [data-width="medium"]):is(
    [data-aspect="none"],
    [data-aspect=""],
    :not([data-aspect])
  )
  .sk-photo-media {
  height: auto;
  aspect-ratio: 3 / 2;
}

/* 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);
  }
}
