/**
 * Fluid Framework - Gallery + Lightbox
 * @layer components
 *
 * A grid of photos for portfolios (architects, interior designers, landscape
 * architects, builders, photographers) and a full-screen viewer.
 *
 * Progressive enhancement: without JavaScript every thumbnail is a plain link
 * to the full-size image. With assets/js/lightbox.js the links open in a
 * native <dialog> with previous / next, arrow keys, Escape, swipe, a counter
 * and the caption, and focus returns to the thumbnail on close.
 *
 * Usage:
 *   <ul class="gallery" role="list" data-lightbox>
 *     <li>
 *       <figure class="gallery__figure">
 *         <a class="gallery__link" href="photos/kitchen-2400.jpg">
 *           <img class="gallery__image" src="photos/kitchen-800.jpg" alt="Kitchen with walnut island"
 *                width="800" height="600" loading="lazy">
 *         </a>
 *         <figcaption class="gallery__caption">Kitchen · Photo: A. Smith</figcaption>
 *       </figure>
 *     </li>
 *   </ul>
 *   <script src="assets/js/lightbox.js" defer></script>
 *
 * Options on .gallery:
 *   data-aspect="square|landscape|portrait|video"  crop of the thumbnails (default: natural ratio)
 *   data-size="sm|lg"                                      thumbnail width (default 24rem: three across an
 *                                                          80rem column, a body of work, not a catalogue;
 *                                                          --gallery-min on :root sets it, sm 11rem, lg 32rem)
 *   data-captions="overlay"                                captions over the image instead of below
 * Per image: style="--focus-x: 30%; --focus-y: 60%" keeps the subject in the crop.
 * Captions: write dimensions with no-break spaces (40&nbsp;×&nbsp;50&nbsp;cm), so
 * they never break inside.
 *
 * The hang line: each item spans two rows of a subgrid with its image at
 * the bottom of the first, so image bottoms and caption tops share one
 * line across a row, whatever each image's ratio.
 */

@layer components {
  /* ========================================
     GRID
     ======================================== */

  .gallery {
    --_gallery-min: var(--gallery-min, 24rem);

    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(var(--_gallery-min), 100%), 1fr));
    gap: var(--space-m);
    list-style: none;
    padding: 0;
    margin: 0;
  }

  .gallery[data-size="sm"] { --_gallery-min: 11rem; }
  .gallery[data-size="lg"] { --_gallery-min: 32rem; }

  .gallery[data-aspect="square"] { --_gallery-aspect: 1; }
  .gallery[data-aspect="landscape"] { --_gallery-aspect: 4 / 3; }
  .gallery[data-aspect="portrait"] { --_gallery-aspect: 3 / 4; }
  .gallery[data-aspect="video"] { --_gallery-aspect: 16 / 9; }

  .gallery > *,
  .gallery > * > .gallery__figure {
    display: grid;
    grid-row: span 2;
    grid-template-rows: subgrid;
    row-gap: var(--space-xs);
    min-inline-size: 0;
    margin: 0;
  }

  /* The hang line: the image (or its link) sits at the bottom of row one. */
  .gallery__figure > :is(.gallery__image, picture) { align-self: end; }

  /* Firefox sizes the grid too tall when a bare <img> is a subgrid item
     (each row +142px at 390px once the images load; Firefox 157). Those
     figures leave the subgrid there; a link or <picture> wrapper keeps it. */
  @supports (-moz-appearance: none) {
    .gallery > :has(> .gallery__figure > img) { display: block; }
    .gallery__figure:has(> img) { block-size: 100%; grid-template-rows: 1fr auto; }
  }

  .gallery__link {
    display: block;
    align-self: end;
    background: var(--color-surface);
    transition: opacity var(--duration-fast) var(--ease-fluid);
  }

  .gallery__link:hover { opacity: 0.9; }

  .gallery__link:focus-visible {
    outline: 3px solid var(--color-focus);
    outline-offset: 2px;
  }

  .gallery__image {
    display: block;
    inline-size: 100%;
    block-size: auto;
    object-fit: cover;
    object-position: var(--focus-x, 50%) var(--focus-y, 50%);
  }

  /* Only a crop sets the ratio: a bare `auto` here replaced the width and
     height attributes' ratio, so a lazy image was only as tall as its alt
     text until it loaded, and the page grew under the reader. */
  .gallery[data-aspect] .gallery__image { aspect-ratio: var(--_gallery-aspect); }

  .gallery__caption {
    margin: 0;
    overflow-wrap: anywhere;
  }

  /* Captions over the image */
  .gallery[data-captions="overlay"] .gallery__figure { position: relative; }

  .gallery[data-captions="overlay"] .gallery__caption {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    padding: var(--space-6) var(--space-3) var(--space-3);
    background: linear-gradient(to top, oklch(0% 0 0 / 0.75), transparent);
    color: oklch(100% 0 0);
    max-inline-size: none;
    pointer-events: none;
  }


  /* ========================================
     LIGHTBOX (built by assets/js/lightbox.js)
     ======================================== */

  .lightbox {
    border: none;
    padding: 0;
    margin: 0;
    max-inline-size: none;
    max-block-size: none;
    inline-size: 100%;
    block-size: 100%;
    background: oklch(12% 0 0 / 0.96);
    color: oklch(96% 0 0);
    overflow: hidden;
  }

  .lightbox::backdrop {
    background: oklch(0% 0 0 / 0.6);
  }

  .lightbox[open] {
    display: grid;
    grid-template-rows: auto 1fr auto;
    grid-template-areas: "bar" "stage" "caption";
  }

  .lightbox__bar {
    grid-area: bar;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
  }

  .lightbox__counter {
    font-size: var(--font-size-sm);
    font-variant-numeric: tabular-nums;
  }

  .lightbox__stage {
    grid-area: stage;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-block-size: 0;
    padding-inline: var(--space-3);
    touch-action: pan-y;
  }

  .lightbox__image {
    display: block;
    max-inline-size: 100%;
    max-block-size: 100%;
    object-fit: contain;
    border-radius: var(--radius-sm);
  }

  .lightbox__caption {
    grid-area: caption;
    padding: var(--space-3) var(--space-4) var(--space-5);
    text-align: center;
    font-size: var(--font-size-sm);
    line-height: var(--leading-snug);
    max-inline-size: 60ch;
    margin-inline: auto;
    overflow-wrap: anywhere;
  }

  .lightbox .lightbox__button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 2.75rem;
    min-block-size: 2.75rem;
    padding: var(--space-2);
    border: var(--border-width) solid oklch(100% 0 0 / 0.35);
    border-radius: var(--radius-full);
    background: oklch(0% 0 0 / 0.55);
    color: oklch(100% 0 0);
    font-size: var(--font-size-lg);
    line-height: 1;
    cursor: pointer;
    box-shadow: none;
  }

  .lightbox .lightbox__button:hover {
    background: oklch(0% 0 0 / 0.8);
    border-color: oklch(100% 0 0 / 0.7);
  }

  .lightbox .lightbox__button:focus-visible {
    outline: 3px solid oklch(100% 0 0);
    outline-offset: 2px;
  }

  .lightbox__prev,
  .lightbox__next {
    position: absolute;
    inset-block-start: 50%;
    translate: 0 -50%;
  }

  .lightbox__prev { inset-inline-start: var(--space-3); }
  .lightbox__next { inset-inline-end: var(--space-3); }

  .lightbox__prev[hidden],
  .lightbox__next[hidden] {
    display: none;
  }

  /* Keep the page still behind an open lightbox */
  :root:has(.lightbox[open]) {
    overflow: hidden;
  }

}
