/* DanceKut Gallery — the PARTS that belong to no single look (docs/GALLERY.md §3g), 2026-10-01.
   The page is a set of parts (gallery.js PARTS): every part is a class on <body> — bar-* ·
   menu-* · hl-* (layout) · hero-* · title-* · btn-* · days-* · wall-* · rv-* · hv-* · vw-* ·
   cur-* — and the four look sheets are scoped by those classes, so any wall can meet any
   hover, any bar any hero. This sheet is the glue: what two parts need when they meet, the
   centred header (the classic one, dressed by the parts) and the pieces that were born as
   options of the default page: the menu that opens UNDER the island, the display titles, the
   recap under the mark. Loaded last. */

/* ── the centred header under each bar ── */
body.hl-center.bar-island .gal-header { padding-top: calc(var(--barh) + 50px); }
body.hl-center.bar-clear .gal-header, body.hl-center.bar-line .gal-header { padding-top: calc(var(--barh) + 22px); }
.hx-sub.po-sub { justify-content: center; text-shadow: none; margin: 14px 0 2px; }
body.hl-center .gal-bio-zone { margin-top: 18px; }

/* ── title: a name set in display type (renderBodyLogo · heroIdentInto) ── */
.hx-name { display: flex; flex-direction: column; align-items: center; font-weight: 900; line-height: .9; letter-spacing: -0.05em; font-size: clamp(54px, 11.5vw, 176px); max-width: 100%; }
.hx-name .l1, .pr-name .l1 { white-space: nowrap; padding: 0 .06em; }   /* one line: fitHeroName scales the face to its column */
.hx-name .l2 { font-size: .17em; line-height: 1.2; letter-spacing: .36em; text-indent: .36em; text-transform: uppercase; font-weight: 700; color: var(--tx2); margin-top: 1.3em; }
.gal-hero-logo:has(.hx-name) { width: 100%; }
/* gradient: the name is lit by a light that travels through it */
body.title-gradient .hx-name .l1, body.title-gradient .pr-name .l1 {
  background: linear-gradient(100deg, var(--tx) 0%, var(--tx) 38%, var(--pink) 58%, var(--or) 74%, var(--tx) 100%); background-size: 260% 100%;
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: hxSheen 8s ease-in-out infinite alternate;
}
@keyframes hxSheen { from { background-position: 0% 0; } to { background-position: 100% 0; } }
/* split: a second layer of the same word behind it, one edge purple and the other orange */
body.title-split .hx-name .l1, body.title-split .pr-name .l1 { color: var(--tx); text-shadow: -.035em 0 0 rgba(168, 85, 247, .6), .035em 0 0 rgba(255, 123, 0, .55); }
body.title-split .hx-name .l2 { letter-spacing: .3em; }
body.title-split .pr-name .l2 { color: transparent; -webkit-text-stroke: 1.5px var(--tx); }
body.title-plain .pr-name .l1 { color: var(--tx); }

/* ── buttons: chips (bigger, and they lean toward the pointer — magnet()) ── */
body.btn-chips .gal-bio-zone { max-width: 980px; }
body.btn-chips .gal-links-row { gap: 10px; }
body.btn-chips .gal-bio-zone .gal-link-btn, body.btn-chips .gal-bio-zone .gal-contact-btn { min-height: 46px; padding: 8px 22px; border-radius: 999px; }

/* ── the recap under the mark: the night before the gallery ── */
.hx-recap { margin: 26px -16px 0; }
.hx-marquee .cl-hero { height: clamp(300px, 54vh, 600px); background: transparent; }
.hx-marquee .cl-hero-veil { background: linear-gradient(180deg, var(--bg) 0%, transparent 12%, transparent 84%, var(--bg) 100%); }
.hx-marquee .cl-hero-in { left: 50%; transform: translateX(-50%); }
.hx-recap .el { opacity: 0; }
body.gal-in .hx-recap .el { animation: popIn .6s var(--ease) both; animation-delay: var(--d, 0s); }
/* the rows arrive from opposite sides once the page is in */
.hx-marquee .cl-row { opacity: 0; transform: translateX(-12%); transition: transform 1.3s var(--ease), opacity .8s ease; }
.hx-marquee .cl-row.rev { transform: translateX(12%); }
body.gal-in .hx-marquee .cl-row { opacity: 1; transform: none; }
.hx-fan .fl-fan { flex: none; min-height: 0; height: calc(var(--cw) * 1.5 + 130px); margin-top: 0; }
.hx-fan .fl-fan-card { bottom: 56px; }
body.days-dock .hx-fan .fl-fan { height: calc(var(--cw) * 1.5 + 170px); }
body.days-dock .hx-fan .fl-fan-card { bottom: 96px; }
@media (max-width: 640px) {
  .hx-marquee .cl-hero { height: clamp(230px, 40vh, 360px); }
  .hx-fan .fl-fan { height: calc(var(--cw) * 1.5 + 96px); }
  .hx-fan .fl-fan-card, body.days-dock .hx-fan .fl-fan-card { bottom: 44px; }
}

/* ── days: chapters / numerals under a centred header sit in the middle ── */
body.hl-center.days-chapters .gal-nav-sticky, body.hl-center.days-numerals .gal-nav-sticky { align-items: center; padding-left: 14px; padding-right: 14px; background: transparent; border-bottom-color: transparent; margin-top: 14px; }
body.hl-center.days-chapters .gal-nav-sticky.stuck, body.hl-center.days-numerals .gal-nav-sticky.stuck { background: var(--glass); border-bottom-color: var(--gline); }
body.hl-center .gal-nav-sticky .po-chap-row { max-width: 100%; }
body.hl-center .gal-nav-sticky .po-filters { justify-content: center; }
body.hl-center .gal-nav-sticky .po-filters .spacer { display: none; }
body.hl-center .gal-nav-sticky .po-eds { justify-content: center; }
/* under an ISLAND the strip sticks below the capsule, and a band of the same glass fills the
   gap up to the top of the screen (a pseudo-element: nothing below it moves when it appears) */
body.bar-island { --sticktop: calc(var(--barh) + 22px); }
body.bar-island .gal-nav-sticky { top: var(--sticktop); }
body.bar-island .gal-nav-sticky::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: calc(var(--sticktop) + 2px); background: var(--glass); backdrop-filter: blur(16px) saturate(1.3); -webkit-backdrop-filter: blur(16px) saturate(1.3); opacity: 0; transition: opacity .25s; pointer-events: none; }
body.bar-island .gal-nav-sticky.stuck::before { opacity: 1; }
/* stuck, the chapters shrink to a line: the wall is what the visitor came for */
body.days-chapters .gal-nav-sticky.stuck .po-chap { padding: 5px 13px 5px 9px; }
body.days-chapters .gal-nav-sticky.stuck .po-chap .d { font-size: 22px; }
body.days-chapters .gal-nav-sticky.stuck .po-chap .n, body.days-chapters .gal-nav-sticky.stuck .po-chap .c { display: none; }
body.days-chapters .po-chap, body.days-chapters .po-chap .d { transition: padding .25s, font-size .25s, border-color .16s, transform .16s, background .16s, color .16s; }

/* ── walls that are not the classic masonry, under a centred header ── */
body.hl-center.wall-rows .gal-grid-wrap, body.hl-center.wall-mosaic .gal-grid-wrap { margin-top: 10px; }
/* a reveal that clips lets go once it has arrived, whatever the hover (the glow must not be cut) */
body.rv-wipe .gal-card.rv.in.rvd { clip-path: none; }
/* the pointer-following hovers need a card that does not clip its own shadow… and one that does clip its picture */
body.hv-lean .gal-card, body.hv-holo .gal-card, body.hv-focus .gal-card { overflow: hidden; }

/* ── menu: drop — the island makes room and the options arrive inside it ── */
body.menu-drop .gal-bar {
  flex-wrap: wrap; align-content: flex-start; height: auto; min-height: var(--barh); border-radius: 28px; padding-top: 8px; padding-bottom: 8px; row-gap: 0;
  min-width: 0; transition: transform .9s var(--spring), opacity .5s ease, min-width .55s var(--spring), box-shadow .3s;
}
body.menu-drop .gal-bar.open { min-width: min(420px, calc(100vw - 20px)); background: color-mix(in srgb, var(--card) 90%, transparent); box-shadow: 0 30px 80px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .08); }
body.menu-drop .gal-bar-right { margin-left: auto; }
.gal-bar-drop { display: none; }
body.menu-drop .gal-bar-drop { display: grid; flex: 0 0 100%; width: 0; min-width: 100%; grid-template-rows: 0fr; transition: grid-template-rows .55s var(--spring); }
body.menu-drop .gal-bar.open .gal-bar-drop { grid-template-rows: 1fr; }
.gal-bar-drop > .in { min-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: 8px; padding: 0 2px 0 0; margin-left: -8px; transition: padding .4s ease; }
body.menu-drop .gal-bar.open .gal-bar-drop > .in { padding: 12px 2px 6px 0; max-height: min(70vh, 560px); overflow-y: auto; scrollbar-width: thin; }
.gal-bar-drop > .in > * { opacity: 0; transform: translateY(-10px) scale(.97); transition: opacity .2s ease, transform .2s ease; }
body.menu-drop .gal-bar.open .gal-bar-drop > .in > * { opacity: 1; transform: none; transition: opacity .4s ease, transform .55s var(--spring); transition-delay: calc(90ms + var(--i, 0) * 45ms); }
.gal-bar-drop h3 { margin: 6px 4px 0; font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--tx2); font-weight: 700; }
.gal-bar-drop .gal-about { max-height: 26vh; overflow: auto; padding: 0 4px; text-align: left; }
.gal-bar-drop .gal-drawer-link { border-radius: 16px; }
body.menu-drop .gal-bar.open .gal-menu-btn { background: rgba(255, 255, 255, .1); transform: rotate(90deg); }
body.menu-drop .gal-menu-btn svg { transition: transform .3s; }

/* ══ OPENINGS (galintro.js · part `opening`) ═══════════════════════════════════════════
   classic · mosaic · strips · fan · ring live with their looks; these five were born as
   options of the default page. All of them put the night's photos behind the event's mark. */
.gi.gi-poster .gi-ev, .gi.gi-poster .gi-tag, .gi.gi-poster .gi-news { z-index: 5; }
/* «landing» and «deal»: the photos do not vanish — they travel to the page's recap */
.gi.gi-land.s-out { opacity: 1; clip-path: none; background: transparent; transition: background .55s ease; pointer-events: none; }
.gi.gi-land.s-out .gi-aur { opacity: 0; transition: opacity .4s ease; }
.gi.gi-land.s-out .gi-strips::after { opacity: 0; transition: opacity .4s ease; }
.gi.gi-land.s-out .gi-strips { transition: transform .9s cubic-bezier(.3, .7, .2, 1), opacity .3s ease .78s; opacity: 0; }
.gi.gi-land.s-out .gi-strip { height: 36vh; }
.gi.gi-land.s-out .gi-fan { transition: opacity .3s ease .8s; opacity: 0; }
.gi.gi-land.s-out .gi-fan img { transition: transform .85s cubic-bezier(.3, .7, .2, 1), transform-origin .85s cubic-bezier(.3, .7, .2, 1); }
/* «columns» */
.gi-cols { position: absolute; inset: -6vh 0; display: flex; gap: 1.2vw; padding: 0 1.2vw; pointer-events: none; }
.gi-cols::after { content: ''; position: absolute; inset: 0; background: radial-gradient(60% 50% at 50% 50%, rgba(7, 7, 12, .72), rgba(7, 7, 12, .4) 70%, rgba(7, 7, 12, .7)); }
.gi-col { flex: 1; min-width: 0; overflow: hidden; opacity: 0; transform: translateY(-40%); transition: transform 1.3s cubic-bezier(.2, .8, .2, 1), opacity .6s ease; transition-delay: var(--d, 0s); }
.gi-col.rev { transform: translateY(40%); }
.gi.s-cols .gi-col { opacity: 1; transform: none; }
.gi-col-track { display: flex; flex-direction: column; animation: giColUp 46s linear infinite; }
.gi-col.rev .gi-col-track { animation-direction: reverse; }
.gi-col-track img { width: 100%; aspect-ratio: 2 / 3; object-fit: cover; object-position: 50% 30%; border-radius: 12px; margin-bottom: 1.2vw; display: block; }
@keyframes giColUp { from { transform: translateY(0); } to { transform: translateY(-50%); } }
/* «burst» */
.gi-burst { position: absolute; inset: 0; pointer-events: none; background: #000; }
.gi-burst img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; opacity: 0; }
.gi-burst img.on { opacity: 1; animation: giPunch .5s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes giPunch { from { transform: scale(1.14); filter: brightness(1.6); } to { transform: scale(1); filter: brightness(1); } }
.gi-burst::after { content: ''; position: absolute; inset: 0; background: rgba(7, 7, 12, 0); transition: background .7s ease, backdrop-filter .7s ease; }
.gi.s-burstend .gi-burst::after { background: rgba(7, 7, 12, .62); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
/* «tunnel» */
.gi-tunnel { position: absolute; inset: 0; perspective: 900px; perspective-origin: 50% 50%; pointer-events: none; overflow: hidden; }
.gi-tunnel::after { content: ''; position: absolute; inset: 0; background: radial-gradient(40% 34% at 50% 50%, rgba(7, 7, 12, .75), rgba(7, 7, 12, 0) 100%); opacity: 0; transition: opacity .8s ease; }
.gi.s-ev .gi-tunnel::after { opacity: 1; }
.gi-tunnel img { position: absolute; left: 50%; top: 50%; width: clamp(120px, 17vmin, 220px); aspect-ratio: 2 / 3; margin: calc(clamp(120px, 17vmin, 220px) * -.75) 0 0 calc(clamp(120px, 17vmin, 220px) / -2); object-fit: cover; object-position: 50% 30%; border-radius: 12px; opacity: 0; box-shadow: 0 30px 80px rgba(0, 0, 0, .6); }
.gi.s-tunnel .gi-tunnel img { animation: giFly 2.7s cubic-bezier(.5, 0, .9, .6) infinite; animation-delay: var(--d, 0s); }
@keyframes giFly {
  0% { opacity: 0; transform: translate3d(calc(var(--x) * .25), calc(var(--y) * .25), -2600px) rotate(var(--r)); }
  18% { opacity: 1; }
  82% { opacity: 1; }
  100% { opacity: 0; transform: translate3d(calc(var(--x) * 2.6), calc(var(--y) * 2.6), 760px) rotate(var(--r)); }
}

/* ══ ROUND 3 (2026-10-01) ═════════════════════════════════════════════════════════════ */

/* ── the bar and the strip DARKEN as the page goes under them (updateSticky writes --sk, 0…1
      over the first 160 px): the photos must not show through the chips. An inset shadow is
      a coat of paint over the element's own background and under its content. ── */
.gal-bar { box-shadow: inset 0 0 0 100vmax rgba(var(--bgc), calc(var(--sk, 0) * .8)); }
body.bar-island .gal-bar { box-shadow: 0 18px 50px rgba(0, 0, 0, .35), inset 0 1px 0 rgba(255, 255, 255, .08), inset 0 0 0 100vmax rgba(var(--bgc), calc(var(--sk, 0) * .72)); }
.gal-nav-sticky.stuck { box-shadow: inset 0 0 0 100vmax rgba(var(--bgc), calc(var(--sk, 0) * .88)); }
body.bar-island .gal-nav-sticky::before { background: rgba(var(--bgc), calc(.3 + var(--sk, 0) * .62)); }

/* ── chips a third smaller (links, days, filters) on the centred page ── */
body.btn-chips .gal-links-row { gap: 7px; }
body.btn-chips .gal-bio-zone .gal-link-btn, body.btn-chips .gal-bio-zone .gal-contact-btn { min-height: 32px; padding: 5px 15px; font-size: 11.5px; gap: 6px; }
body.btn-chips .gal-bio-zone .gal-link-btn .ic { font-size: 12.5px; }
body.btn-chips .gal-bio-zone .gal-link-btn .sb { font-size: 9.5px; }
body.btn-chips .gal-bio-zone .gal-social { width: 28px; height: 28px; font-size: 12px; }
body.btn-chips .gal-bio-zone .gal-social.named { width: auto; min-width: 28px; padding: 0 11px 0 9px; gap: 6px; }
body.btn-chips .gal-bio-zone .gal-social.named .nm { font-size: 9.5px; }
body.hl-center.days-chapters .po-chap { min-width: 0; padding: 5px 12px 5px 8px; gap: 8px; border-radius: 11px; }
body.hl-center.days-chapters .po-chap .d { font-size: 21px; }
body.hl-center.days-chapters .po-chap .w { font-size: 9.5px; }
body.hl-center.days-chapters .po-chap .c { font-size: 10.5px; }
body.hl-center.days-chapters .po-chap .n { font-size: 9.5px; }
body.hl-center.days-chapters .po-chap.mix .d { font-size: 13px; }
body.hl-center.days-chapters .gal-nav-sticky.stuck .po-chap { padding: 4px 11px 4px 8px; }
body.hl-center.days-chapters .gal-nav-sticky.stuck .po-chap .d { font-size: 18px; }
body.hl-center .gal-nav-sticky .gal-seg { height: 25px; }
body.hl-center .gal-nav-sticky .gal-seg-btn { font-size: 10.5px; padding: 0 10px; }
body.hl-center .gal-nav-sticky .gal-pill.sm { height: 25px; font-size: 10.5px; }

/* ── a row of chips that can be scrolled with a mouse (wireRowScroll) ── */
.rs { cursor: grab; }
.rs.grab { cursor: grabbing; scroll-snap-type: none; }
.rs.grab * { pointer-events: none; }
.rs-a { position: sticky; z-index: 6; flex: 0 0 0; width: 0; align-self: stretch; display: flex; align-items: center; pointer-events: none; }
.rs-a.l { left: 0; }
.rs-a.r { right: 0; justify-content: flex-end; }
.rs-a button { flex: 0 0 auto; width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: var(--tx); background: var(--glass2); border: 1px solid var(--gline2); box-shadow: 0 6px 18px rgba(0, 0, 0, .4); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); opacity: 0; transform: scale(.7); transition: opacity .2s, transform .3s var(--spring), border-color .15s; pointer-events: none; }
.rs-a.l button { margin-left: 2px; }
.rs-a.r button { margin-right: 2px; }
.rs-a svg { width: 15px; height: 15px; stroke: currentColor; fill: none; stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.rs.can-l .rs-a.l button, .rs.can-r .rs-a.r button { opacity: 1; transform: none; pointer-events: auto; }
.rs-a button:hover { border-color: var(--hov-yellow); }
@media (hover: none) { .rs-a { display: none; } .rs { cursor: auto; } }

/* ── the viewer's actions together: the name, copy the link, download ── */
.gal-cp { flex: none; display: inline-flex; align-items: center; gap: 7px; height: 38px; padding: 0 15px; border-radius: 999px; font-weight: 700; font-size: 13px; color: #f4f4f6; background: rgba(255, 255, 255, .09); border: 1px solid rgba(255, 255, 255, .16); transition: background .18s, border-color .18s, color .18s, transform .16s; }
.gal-cp svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.gal-cp:hover { background: rgba(255, 255, 255, .17); transform: translateY(-1px); }
.gal-cp.ok { color: var(--hov-yellow); border-color: var(--hov-yellow); }
.gal-dlbar { gap: 6px; }
.gal-dlbar-nm { margin-right: 4px; }
@media (max-width: 620px) { .gal-cp { width: 38px; padding: 0; justify-content: center; } .gal-cp .tx { display: none; } }
/* the ✕ is ALWAYS the last thing of the top row: the top-right corner, in every viewer */
.gal-viewer-top .gal-viewer-close { margin-left: auto; order: 99; flex: 0 0 auto; }
body.vw-theatre .gal-viewer-close { display: inline-flex; }
body.vw-theatre .gal-dlbar { display: flex; }
body.vw-theatre .gal-arrow.next { right: 8px; }
body.vw-theatre .gal-viewer-stage { padding: 64px 64px 0; }
body.vw-theatre .gal-viewer-bottom { padding-top: 8px; }
@media (max-width: 640px) { body.vw-theatre .gal-viewer-stage { padding: 56px 8px 0; } }

/* ── the openings MELT into the page: one slow fade of the whole curtain while the photos
      drift toward the viewer — and the curtain is removed when the fade has ended ── */
.gi.gi-poster.s-out:not(.gi-land) { transition: opacity 1.15s cubic-bezier(.4, 0, .2, 1); }
.gi.gi-poster.s-out .gi-stage { transition: opacity .5s ease; }
.gi.gi-v-columns.s-out .gi-cols, .gi.gi-v-burst.s-out .gi-burst, .gi.gi-v-tunnel.s-out .gi-tunnel { transform: scale(1.1); transition: transform 1.25s cubic-bezier(.4, 0, .2, 1); }
.gi.s-burstend .gi-burst::after { backdrop-filter: none; -webkit-backdrop-filter: none; background: rgba(7, 7, 12, .66); }
/* the chip under an arrow fades into the ground instead of being cut by the button — and it has faded BEFORE
   the arrow, not under it (campo 2026-10-07: «las flechas suelen ponerse encima de los propios días a clicar»):
   the arrow stands on its own ground, the first day in sight starts after it */
.rs-a::before { content: ''; position: absolute; top: 0; bottom: 0; width: 60px; pointer-events: none; opacity: 0; transition: opacity .2s; }
.rs-a.l::before { left: 0; background: linear-gradient(90deg, rgba(var(--bgc), .97) 64%, rgba(var(--bgc), 0)); }
.rs-a.r::before { right: 0; background: linear-gradient(270deg, rgba(var(--bgc), .97) 64%, rgba(var(--bgc), 0)); }
.rs { scroll-padding-inline: 44px; }
.rs.can-l .rs-a.l::before, .rs.can-r .rs-a.r::before { opacity: 1; }
.rs-a button { position: relative; }
/* a zero-width flex child still takes a GAP: the arrows give it back, or the row rests 8 px scrolled */
.rs > .rs-a.l { margin-right: calc(-1 * var(--rs-gap, 8px)); }
.rs > .rs-a.r { margin-left: calc(-1 * var(--rs-gap, 8px)); }
.fl-dock .po-chap-row, body.days-numerals .po-chap-row { --rs-gap: 2px; }
/* 📅 the date index (gallery.js rowDateIndex): the icon alone, at the START of the days, and it stays there — a
   frozen column the days pass under (its ground only shows once they do). The left arrow stands after it. */
.rs-cal { position: sticky; left: 0; z-index: 7; flex: 0 0 auto; align-self: stretch; display: flex; align-items: center; }
.rs-cal::before { content: ''; position: absolute; top: 0; bottom: 0; left: -4px; right: -8px; background: rgba(var(--bgc), .97); opacity: 0; transition: opacity .2s; pointer-events: none; }
.rs.can-l .rs-cal::before { opacity: 1; }
.rs.has-cal > .rs-a.l { left: 40px; }
.rs.has-cal { scroll-padding-left: 84px; }
.gal-cal-btn { position: relative; flex: 0 0 auto; width: 34px; height: 34px; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center; color: var(--tx2); background: var(--glass); border: 1px solid var(--gline2); cursor: pointer; transition: color .16s, border-color .16s, background .16s, transform .16s; }
.gal-cal-btn:hover, .gal-cal-btn.open { color: var(--tx); border-color: var(--acc); background: rgba(var(--acc-w), .14); }
.gal-cal-btn:hover { transform: translateY(-1px); }
.gal-cal-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ══ ROUND 4 (2026-10-01) ═════════════════════════════════════════════════════════════ */
/* ── columns / strips arrive AS THEY ARE; the veil comes with the event's mark ── */
.gi-cols::after, .gi-strips::after { opacity: 0; transition: opacity .9s ease; }
.gi.s-ev .gi-cols::after, .gi.s-news .gi-cols::after, .gi.s-ev .gi-strips::after, .gi.s-news .gi-strips::after { opacity: 1; }
/* ── …and melt: a curtain that fades while five columns keep scrolling is a fade the
      compositor has to redo on every frame. Stop them, and it fades ONE still picture. ── */
.gi.s-out .gi-col-track, .gi.s-out .gi-strip-track, .gi.s-out .gi-ring-in, .gi.s-out .gi-tunnel img { animation-play-state: paused; }
.gi.gi-poster.s-out:not(.gi-land) { will-change: opacity; }
.gi.gi-v-columns.s-out .gi-cols { transform: none; transition: none; }
/* ── burst: a hard cut that settles (no brightness filter on a full screen, no empty frame) ── */
.gi-burst { background: transparent; }
.gi-burst.go { background: #000; }
.gi-burst img.on { animation: giPunch .42s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes giPunch { from { transform: scale(1.07); } to { transform: scale(1); } }

/* ── EVERY viewer has the row (cf*): drag sideways = next / previous, up or down = close ── */
.gal-viewer-stage { touch-action: none; }
.cf { top: var(--stop, 0px); }
.cf-it { transform: translateX(calc(var(--o) * 104%)); }
.cf-it img { border-radius: 12px; box-shadow: 0 30px 80px rgba(0, 0, 0, .6); }
@media (max-width: 640px) { .gal-viewer { --spad: 4px; } }
body.vw-theatre .gal-viewer { --spad: 64px; --stop: 64px; }
body.vw-theatre .cf-it img { border-radius: 4px; box-shadow: 0 40px 100px rgba(0, 0, 0, .8); }
body.vw-stories .gal-viewer { --stop: 6px; }
body.vw-stories .cf-it img { border-radius: 16px; }
body.vw-slide .gal-viewer { --stop: 4px; }
@media (max-width: 640px) {
  body.vw-theatre .gal-viewer { --spad: 8px; --stop: 56px; }
  body.vw-stories .gal-viewer { --spad: 6px; }
  body.vw-stories .cf-it img { border-radius: 10px; }
}
/* two sets of moving photos crossing (the columns going, the page's marquee coming) read as a
   glitch: the columns go dark first, and it is the DARK that melts into the page */
.gi.gi-v-columns.s-out .gi-col { opacity: 0; transition: opacity .5s ease; transition-delay: 0s; }
