/* gallery.css — page 4 lower half, extension magazine gallery (js/sections/gallery.js). */

.gallery {
  position: relative;
  padding-bottom: clamp(48px, 10vh, 120px);
}

.gallery__field {
  position: relative;
  height: min(78vh, 760px);
  min-height: 460px;
  overflow: hidden;
  outline: none;
  touch-action: pan-y;
}

.gallery__field:focus-visible {
  box-shadow: inset 0 0 0 2px var(--c-c);
}

/* The point light's pool. It sits off the gallery's top-right corner (the
   same spot the shadow maths in gallery.js uses: field top − 32% of the field
   height) and is not clipped by the field. The box is centred on the light and
   is taller than the glow's reach in both directions (gradient ends at 72% of
   a 130vh radius ≈ 94vh), so the glow fades to nothing inside the box — it
   crosses up into the stacked titles with no edge anywhere. */
.gallery__light {
  --field-h: min(78vh, 760px);
  --glow: radial-gradient(150% 130vh at 102% 105vh, rgb(255 255 255 / 0.15), rgb(255 255 255 / 0.06) 40%, transparent 72%);
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--field-h) * -0.32 - 105vh);
  height: 210vh;
  background: var(--glow);
  pointer-events: none;
  /* behind the titles above it, so it lights the page rather than covering text */
  z-index: -1;
}

:root[data-theme='light'] .gallery__light {
  --glow: radial-gradient(150% 130vh at 102% 105vh, rgb(255 255 255 / 0.95), rgb(255 255 255 / 0.4) 40%, transparent 72%);
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme='dark']) .gallery__light {
    --glow: radial-gradient(150% 130vh at 102% 105vh, rgb(255 255 255 / 0.95), rgb(255 255 255 / 0.4) 40%, transparent 72%);
  }
}

/* shadows darken whatever is underneath — overlaps compound (multiply) */
.gallery__shadows {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* shadows run on past the field's lower edge: fade them out there */
.gallery__shadows {
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent);
  mask-image: linear-gradient(to bottom, #000 72%, transparent);
}

/*
 * Edge fades. The rails bleed off both sides and every new icon is pressed in
 * from outside the field's top (or bottom) edge, so nothing leaves through a
 * hard edge: a gradient dissolves whatever is crossing one, where
 * `overflow: hidden` would cut it off square. Two nested elements carry one
 * gradient each — crossing two masks on a single element needs
 * `mask-composite`, whose support is patchier than plain nesting.
 *   .gallery__stage         top / bottom, the press-in
 *   .gallery__icons         left / right, the shove-off
 *   .gallery__shadows-clip  left / right, for the shadows those icons cast
 */
.gallery__stage {
  position: absolute;
  inset: 0;
  --gal-fade-y: 18%;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--gal-fade-y), #000 calc(100% - var(--gal-fade-y)), transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 var(--gal-fade-y), #000 calc(100% - var(--gal-fade-y)), transparent);
}

.gallery__shadows-clip {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.gallery__shadows-clip,
.gallery__icons {
  /* --gal-fade-x is set by gallery.js, scaled to the rail spacing: wide enough
     for an icon to dissolve over its last stretch, narrow enough to leave the
     feeding chamber (0.7 slots in) untouched */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--gal-fade-x, 96px), #000 calc(100% - var(--gal-fade-x, 96px)), transparent);
  mask-image: linear-gradient(to right, transparent, #000 var(--gal-fade-x, 96px), #000 calc(100% - var(--gal-fade-x, 96px)), transparent);
}

.gallery__icons {
  position: absolute;
  inset: 0;
}

.gallery__icon {
  position: absolute;
  left: 0;
  top: 0;
  width: 64px;
  height: 64px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  will-change: transform, opacity;
  transition: filter 0.25s ease;
}

.gallery__icon img {
  width: 100%;
  height: 100%;
  image-rendering: auto;
  transition: transform 0.35s var(--ease-brand);
  -webkit-user-drag: none;
  user-select: none;
}

.gallery__icon:hover img,
.gallery__icon:focus-visible img {
  transform: translateY(-6px) scale(1.12);
}

/* tag bubble on the top-right corner */
.gallery__bubble {
  position: absolute;
  left: 62%;
  bottom: 88%;
  padding: 5px 14px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  color: var(--fg-muted);
  font-size: 15px;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translateY(6px) scale(0.9);
  transform-origin: 0 100%;
  transition: opacity 0.35s ease, transform 0.45s var(--ease-brand);
}

.gallery__icon.has-bubble .gallery__bubble {
  opacity: 1;
  transform: none;
}

/* details panel */
.gallery__panel {
  position: absolute;
  z-index: 5;
  display: grid;
  gap: 10px;
  padding: 10px 10px 14px;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: var(--bg-elev);
  box-shadow: 0 30px 80px var(--shadow);
  pointer-events: none;
  opacity: 0;
  transform: translateY(-6px) scale(0.96);
  transform-origin: 50% 0;
}

.gallery__panel.is-above {
  transform-origin: 50% 100%;
  transform: translateY(6px) scale(0.96);
}

.gallery__panel.is-open {
  opacity: 1;
  transform: none;
  transition: opacity 0.2s ease, transform 0.35s var(--ease-brand);
}

.gallery__preview {
  aspect-ratio: 16 / 10;
  border-radius: 8px;
  overflow: hidden;
  background: var(--bg-sunk);
  display: grid;
  place-items: center;
}

.gallery__preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top left;
}

.gallery__preview img.is-icon {
  width: 40%;
  height: auto;
  object-fit: contain;
}

.gallery__meta {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 4px;
}

.gallery__panel p {
  padding: 0 4px;
  color: var(--fg-muted);
  font-size: 13.5px;
  line-height: 1.5;
}

.gallery__hint {
  position: absolute;
  left: var(--gutter);
  bottom: 14px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-faint);
  pointer-events: none;
}

.gallery__notes {
  display: flex;
  justify-content: flex-end;
}

.gallery__spec {
  width: min(100%, 760px);
}

.gallery__spec .spec__row dt {
  font-size: 13px;
}

.gallery__spec .spec__row dd {
  font-size: 13px;
}

@media (max-width: 640px) {
  .gallery__bubble {
    font-size: 12px;
    padding: 3px 10px;
  }
}
