/* ======================================================================
   DYNAMIC GALLERY — masonry grid + search + filters + lightbox for
   galerie.html. Self-contained: everything this page needs lives in this
   one file so it never has to share state with the Campus page's own
   gallery.css. Sharp corners throughout, matching the rest of the site —
   "premium" here comes from spacing, motion and restraint, not shape.
   ====================================================================== */

/* ---------- Intro ---------- */
.c-dg-hero {
  padding-top: calc(84px + var(--space-10));
  padding-bottom: var(--space-8);
  background: var(--white);
}

/* ---------- Search bar ---------- */
.c-dg-searchbar {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin-top: var(--space-8);
  padding: .85rem 1.1rem;
  max-width: 480px;
  border: 1px solid var(--gray-300);
  background: var(--white);
  color: var(--gray-400);
  transition: border-color .25s var(--ease-out);
}

.c-dg-searchbar:focus-within {
  border-color: var(--blue-900);
  color: var(--blue-900);
}

.c-dg-searchbar input {
  flex: 1;
  border: 0;
  outline: 0;
  font-family: var(--font-body);
  font-size: .95rem;
  color: var(--ink);
  background: none;
}

.c-dg-searchbar input::placeholder {
  color: var(--gray-400);
}

/* ---------- Filter bar ---------- */
.c-dg-filters {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin-top: var(--space-6);
}

.c-dg-filters button {
  padding: .6rem 1.1rem;
  font-family: var(--font-display);
  font-size: .85rem;
  font-weight: 500;
  color: var(--blue-900);
  border: 1px solid var(--gray-300);
  background: var(--white);
  transition: background .25s var(--ease-out), color .25s var(--ease-out), border-color .25s var(--ease-out);
}

.c-dg-filters button:hover {
  border-color: var(--blue-900);
}

.c-dg-filters button.is-active {
  background: var(--blue-900);
  border-color: var(--blue-900);
  color: var(--white);
}

.c-dg-filters button .c-dg-filter-count {
  color: var(--gray-400);
  margin-left: .4rem;
}

.c-dg-filters button.is-active .c-dg-filter-count {
  color: rgba(255, 255, 255, .6);
}

.c-dg-count {
  margin-top: var(--space-4);
  font-size: .82rem;
  color: var(--gray-400);
}

/* ---------- States ---------- */
.c-dg-state {
  padding-block: var(--space-16);
  text-align: center;
  color: var(--gray-600);
}

.c-dg-state[hidden] {
  display: none;
}

/* ---------- Masonry grid ----------
   True Pinterest-style masonry via CSS Grid: a small grid-auto-rows unit,
   and each item spans a JS-computed number of rows derived from its own
   width/height ratio (see dynamic-gallery.js). Because the box height is
   already sized to match the image's own aspect ratio, object-fit:cover
   never actually needs to crop anything — no distortion, no letterboxing. */
.c-dgallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  grid-auto-rows: 8px;
  gap: var(--space-5);
  padding-top: var(--space-8);
  padding-bottom: var(--space-6);
}

.c-dgallery__item {
  position: relative;
  grid-row-end: span var(--row-span, 30);
  overflow: hidden;
  cursor: zoom-in;
  background: var(--gray-50);
  border: 1px solid var(--gray-200);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .4s var(--ease-out), transform .4s var(--ease-out), border-color .3s var(--ease-out),
              box-shadow .3s var(--ease-out);
  /* Off-screen tiles skip layout/paint entirely until they scroll into
     view — this is what lets the grid stay smooth with thousands of photos. */
  content-visibility: auto;
  contain-intrinsic-size: 280px 320px;
}

.c-dgallery__item.is-visible {
  opacity: 1;
  transform: none;
}

/* Skeleton shimmer while the image itself hasn't loaded yet — replaces the
   flat gray placeholder with a moving sheen so waiting reads as "loading",
   not "broken". Removed the instant the <img> fires `load`. */
.c-dgallery__item:not(.is-visible)::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, var(--gray-50) 30%, var(--gray-100) 50%, var(--gray-50) 70%);
  background-size: 200% 100%;
  animation: dg-shimmer 1.6s ease-in-out infinite;
}

@keyframes dg-shimmer {
  from { background-position: 150% 0; }
  to { background-position: -50% 0; }
}

.c-dgallery__item:hover,
.c-dgallery__item:focus-visible {
  border-color: var(--gray-300);
  box-shadow: 0 12px 28px rgba(11, 37, 69, .14);
  outline: none;
}

.c-dgallery__item:focus-visible {
  outline: 2px solid var(--blue-900);
  outline-offset: 2px;
}

.c-dgallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform .5s var(--ease-out);
}

.c-dgallery__item:hover img,
.c-dgallery__item:focus-visible img {
  transform: scale(1.04);
}

.c-dgallery__caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: .9rem 1rem;
  font-size: .82rem;
  color: #fff;
  background: linear-gradient(0deg, rgba(8, 18, 38, .75), transparent);
  opacity: 0;
  transition: opacity .3s var(--ease-out);
  pointer-events: none;
}

.c-dgallery__item:hover .c-dgallery__caption,
.c-dgallery__item:focus-visible .c-dgallery__caption {
  opacity: 1;
}

/* Per-card actions (download / expand) — revealed on hover or keyboard
   focus; always shown at a lighter opacity on touch devices, since there's
   no hover state to reveal them there. */
.c-dgallery__actions {
  position: absolute;
  top: .6rem;
  right: .6rem;
  display: flex;
  gap: .4rem;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .25s var(--ease-out), transform .25s var(--ease-out);
}

.c-dgallery__item:hover .c-dgallery__actions,
.c-dgallery__item:focus-within .c-dgallery__actions {
  opacity: 1;
  transform: none;
}

@media (hover: none) {
  .c-dgallery__actions {
    opacity: 1;
    transform: none;
  }
}

.c-dgallery__action {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: rgba(8, 18, 38, .55);
  color: #fff;
  transition: background .2s var(--ease-out), transform .2s var(--ease-out);
}

.c-dgallery__action:hover {
  background: var(--blue-900);
  transform: scale(1.08);
}

/* ---------- Responsive column counts ---------- */
@media (max-width: 900px) {
  .c-dgallery {
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: var(--space-4);
  }
}

@media (max-width: 560px) {
  .c-dgallery {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3);
  }

  .c-dg-searchbar {
    max-width: none;
  }
}

/* ---------- Back to top ---------- */
.c-dg-top {
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 90;
  width: 46px;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--blue-900);
  color: #fff;
  box-shadow: 0 8px 20px rgba(11, 37, 69, .28);
  transition: background .25s var(--ease-out), transform .25s var(--ease-out);
}

.c-dg-top:hover {
  background: var(--blue-700);
  transform: translateY(-3px);
}

.c-dg-top[hidden] {
  display: none;
}

/* ---------- Lightbox ---------- */
.c-dg-lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(6, 12, 24, .94);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s var(--ease-out), visibility .3s;
}

.c-dg-lightbox.is-open {
  opacity: 1;
  visibility: visible;
}

.c-dg-lightbox__figure {
  position: relative;
  overflow: auto;
  transform: scale(.94) translateY(8px);
  transition: transform .3s var(--ease-out);
}

.c-dg-lightbox.is-open .c-dg-lightbox__figure {
  transform: scale(1) translateY(0);
}

/* The constraints live on the <img> itself (not as a % of the figure) —
   a figure sized only by max-width has no definite width of its own, so a
   child's max-width:100% would resolve against nothing and collapse to 0. */
.c-dg-lightbox__figure img {
  display: block;
  max-width: min(90vw, 1300px);
  max-height: 78vh;
  width: auto;
  height: auto;
  margin-inline: auto;
  cursor: zoom-in;
  transition: max-width .3s var(--ease-out), max-height .3s var(--ease-out);
}

.c-dg-lightbox__figure.is-zoomed {
  max-width: none;
  max-height: none;
}

.c-dg-lightbox__figure.is-zoomed img {
  max-width: none;
  max-height: none;
  width: auto;
  height: auto;
  cursor: zoom-out;
}

.c-dg-lightbox__info {
  margin-top: var(--space-3);
  text-align: center;
  color: rgba(255, 255, 255, .75);
  font-size: .85rem;
}

/* ---------- Top action bar ---------- */
.c-dg-lightbox__bar {
  position: fixed;
  top: var(--space-5);
  right: var(--space-5);
  z-index: 1;
  display: flex;
  gap: .5rem;
}

.c-dg-lightbox__bar-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .2);
  color: #fff;
  transition: background .25s, color .25s;
}

.c-dg-lightbox__bar-btn:hover {
  background: rgba(255, 255, 255, .18);
}

.c-dg-lightbox__bar-btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.c-dg-lightbox__bar-btn[data-lb-fav].is-active {
  background: var(--yellow-500);
  border-color: var(--yellow-500);
  color: var(--blue-950);
}

.c-dg-lightbox__prev,
.c-dg-lightbox__next {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .2);
  color: #fff;
  transition: background .3s, transform .3s;
}

.c-dg-lightbox__prev:hover,
.c-dg-lightbox__next:hover {
  background: rgba(255, 255, 255, .18);
  transform: translateY(-50%) scale(1.06);
}

.c-dg-lightbox__prev {
  left: var(--space-6);
}

.c-dg-lightbox__next {
  right: var(--space-6);
}

.c-dg-lightbox__counter {
  position: fixed;
  bottom: var(--space-6);
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, .6);
  font-size: .8rem;
  letter-spacing: .05em;
}

.c-dg-lightbox__toast {
  position: fixed;
  bottom: calc(var(--space-6) + 2rem);
  left: 50%;
  transform: translateX(-50%);
  padding: .6rem 1.1rem;
  background: var(--blue-900);
  color: #fff;
  font-size: .82rem;
}

.c-dg-lightbox__toast[hidden] {
  display: none;
}

@media (max-width: 768px) {
  .c-dg-lightbox__prev,
  .c-dg-lightbox__next {
    width: 40px;
    height: 40px;
  }

  .c-dg-lightbox__prev {
    left: 10px;
  }

  .c-dg-lightbox__next {
    right: 10px;
  }

  .c-dg-lightbox__bar {
    top: 10px;
    right: 10px;
  }

  .c-dg-lightbox__bar-btn {
    width: 38px;
    height: 38px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .c-dgallery__item {
    transition: none;
  }

  .c-dgallery__item::before {
    animation: none;
  }
}
