/*
 * This is a manifest file that'll be compiled into application.css.
 *
 * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
 * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
 * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
 * depending on specificity.
 *
 * Consider organizing styles into separate files for maintainability.
 */

/* --- Hero carousel: diagonal clip-path wipe -------------------------------
   Slides stack absolutely inside .carousel (Tailwind: relative/overflow-hidden).
   Dormant slides are clipped to nothing (hidden), so only the current photo —
   and, during a wipe, the one wiping in over it — is ever painted. This is what
   stops a stacked-but-inactive photo (the last DOM sibling) from poking through
   the un-wiped triangle. Driven by carousel_controller.js. */
.carousel__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
  /* Dormant: clipped to nothing so inactive photos never show. */
  clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%);
}

/* The settled photo on screen: fully shown, above the dormant slides. */
.carousel__slide.is-current {
  z-index: 2;
  /* Fully shown: rectangle whose right edge is slanted past the frame. */
  clip-path: polygon(0% 0%, 140% 0%, 100% 100%, 0% 100%);
}

/* First frame of a wipe: on top of everything, still clipped to nothing, and NOT
   animated — so the wipe below starts from the hidden state. */
.carousel__slide.is-entering {
  z-index: 3;
  clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%);
  transition: none;
}

/* The wipe itself: animates from .is-entering to fully shown, on top of the
   current photo. Both polygons have 4 points so clip-path interpolates smoothly —
   top-right sweeps 0%->140% and bottom-right 0%->100%, so a diagonal leading edge
   travels across. This 1100ms is purely visual; the JS no longer depends on it. */
.carousel__slide.is-wiping {
  z-index: 3;
  clip-path: polygon(0% 0%, 140% 0%, 100% 100%, 0% 100%);
  transition: clip-path 1100ms cubic-bezier(0.77, 0, 0.18, 1);
}

/* Respect users who prefer less motion: swap the wipe for a gentle crossfade. */
@media (prefers-reduced-motion: reduce) {
  .carousel__slide { clip-path: none; opacity: 0; }
  .carousel__slide.is-current { opacity: 1; }
  .carousel__slide.is-entering { clip-path: none; opacity: 0; transition: none; }
  .carousel__slide.is-wiping { clip-path: none; opacity: 1; transition: opacity 700ms ease; }
}

/* --- Gallery: diagonal scroll reveal --------------------------------------
   Deliberately the same clip-path geometry and easing as the carousel wipe
   above, so the mosaic rhymes with the hero rather than introducing a second
   motion language. Fired once per tile by gallery_controller.js as it scrolls in.

   Everything is gated on .is-armed, which only the controller adds: without it
   these rules don't apply at all, so tiles stay fully visible when JavaScript
   never runs. */
.gallery__tile.is-armed {
  /* Clipped to nothing until revealed. */
  clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%);
}

.gallery__tile.is-armed.is-revealed {
  /* Same 4-point polygon as .carousel__slide.is-current so clip-path interpolates
     smoothly: the right edge sweeps out past the frame on a diagonal. */
  clip-path: polygon(0% 0%, 140% 0%, 100% 100%, 0% 100%);
  transition: clip-path 900ms cubic-bezier(0.77, 0, 0.18, 1);
  /* Set per tile by the controller to stagger tiles revealed in the same batch. */
  transition-delay: var(--reveal-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .gallery__tile.is-armed { clip-path: none; opacity: 0; }
  .gallery__tile.is-armed.is-revealed {
    clip-path: none;
    opacity: 1;
    transition: opacity 500ms ease;
  }
}

/* --- Listing gallery: PhotoSwipe overrides ---------------------------------
   PhotoSwipe (vendored as photoswipe.css, linked on the listing page only)
   sizes each image box from the width and height it is given, and stretches
   the image to fill it. Plain CSS because these are its classes, not ours.

   The size is read from the upload's analysis, which runs in a job; until it
   has, PropertiesHelper#listing_photo_size hands over a 4:3 guess, and
   `contain` letterboxes a portrait photo in that box instead of squashing it.
   The placeholder — the 4:3 card crop shown while the full photo loads — is
   cropped into the box rather than stretched, for the same reason. */
.pswp__img { object-fit: contain; }
.pswp__img--placeholder { object-fit: cover; }
