/* ── GALERIA PAGE ── (.gl- prefix; shared pieces live in ../portfolio.css) */

/* The page is its pictures: a shorter head than the other pages', and the
   rows close together, so the photos start within the first screen. */
.gl-page-head {
  padding: calc(var(--nav-h) + env(safe-area-inset-top, 0px) + clamp(28px, 4vw, 52px)) 0 clamp(20px, 2.6vw, 32px);
}
.gl-page-head .divider { margin: 18px auto; }
.gl-section.section-compact { padding: clamp(28px, 3.6vw, 48px) 0; }
/* The page head already opens the page, so the first row follows it closely. */
.page-head + .gl-section.section-compact { padding-top: 8px; }

/* A row's head is just its label, and sits close to its row. */
.section-compact .gl-head { margin-bottom: clamp(16px, 2vw, 24px); }
.gl-head .eyebrow { margin-bottom: 0; }

/* ── ROWS ──
   Each row runs the full width of the window and scrolls sideways with
   native snapping. Its side padding lines the first card up with the page
   content (.container: 1120px wide, gutter clamp(20px, 5vw, 48px)), so at
   rest the row looks like part of the page and the cards slide out past
   its edges when it moves; on a phone the next card peeks in at the edge.
   --card-w and the ratio size every card in the row, skeletons included. */
.gl-rail {
  --row-pad: calc(max(0px, (100% - 1120px) / 2) + clamp(20px, 5vw, 48px));
  --card-w: clamp(150px, 42vw, 260px);
  --card-ratio: 4 / 5;
  --card-h: calc(var(--card-w) * 5 / 4);
  position: relative;
}
.gl-rail[data-kind="video"] {
  --card-w: clamp(150px, 42vw, 260px);
  --card-ratio: 9 / 16;
  --card-h: calc(var(--card-w) * 16 / 9);
}
/* The photos keep their own shape: one height for the whole row, and each
   card as wide as its photo is at that height (--ratio, width over height,
   set by galeria.js), so nothing is cropped. --card-w and --card-ratio
   stay for the placeholder's empty frames. */
.gl-rail[data-kind="photo"] { --card-h: clamp(256px, 66vw, 400px); }
.gl-card.gl-card-photo {  /* doubled: .gl-card's own width comes later */
  width: calc(var(--card-h) * var(--ratio, .8));
  height: var(--card-h);
}
/* The Instagram card at the end stands as tall as the photos, at their
   most common shape (3:4). */
.gl-rail[data-kind="photo"] .gl-card.gl-card-more {
  width: calc(var(--card-h) * .75);
  height: var(--card-h);
}
.gl-card-photo > img { opacity: 0; }
.gl-card-photo.is-loaded > img { opacity: 1; }

/* The edge fades: on wide screens only, and only on a side the row can still
   scroll towards. Registered so they ease in rather than snap. */
@property --fade-l { syntax: '<length>'; inherits: true; initial-value: 0px; }
@property --fade-r { syntax: '<length>'; inherits: true; initial-value: 0px; }

.gl-row {
  display: flex; gap: 12px;
  list-style: none;
  padding: 6px var(--row-pad) 10px;
  overflow-x: auto; overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--row-pad);
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent);
  transition: --fade-l .4s ease, --fade-r .4s ease;
}
.gl-row::-webkit-scrollbar { display: none; }
.gl-row[hidden] { display: none; }
.gl-item { flex: none; scroll-snap-align: start; }

/* Each fade spans its side's margin (--row-pad, written in vw because a
   registered length can't hold a percentage), so the cards there have
   faded out under the arrow sitting in it. */
@media (min-width: 960px) {
  .gl-row { gap: 16px; }
  .gl-rail.can-prev { --fade-l: calc(max(0px, (100vw - 1120px) / 2) + 48px); }
  .gl-rail.can-next { --fade-r: calc(max(0px, (100vw - 1120px) / 2) + 48px); }
}

/* ── CARDS ──
   The frame of the placeholder mosaic, now holding a picture: a hairline
   that warms on hover while the picture leans in. */
.gl-card {
  position: relative;
  display: block;
  width: var(--card-w); aspect-ratio: var(--card-ratio);
  padding: 0;
  border: 1px solid rgba(201,169,110,0.16); border-radius: 10px;
  background: linear-gradient(150deg, rgba(250,247,242,0.05), rgba(250,247,242,0.01));
  overflow: hidden;
  color: inherit; font: inherit; text-decoration: none;
  cursor: pointer;
  -webkit-appearance: none; appearance: none;
  transition: border-color .45s ease;
}
.gl-card > img,
.gl-card > video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .8s cubic-bezier(.16, 1, .3, 1), opacity .4s ease;
}
.gl-card:focus { outline: none; }
.gl-card:focus-visible { outline: 1px solid var(--gold); outline-offset: 3px; border-color: rgba(201,169,110,0.4); }
@media (hover: hover) {
  .gl-card:hover { border-color: rgba(201,169,110,0.4); }
  .gl-card:hover > img,
  .gl-card:hover > video { transform: scale(1.07); }
}

/* The caption rises in over a shadow on hover; on touch it waits for the
   viewer. */
.gl-card-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 40px 14px 12px;
  background: linear-gradient(180deg, transparent, rgba(18,15,12,0.88));
  font-family: var(--font-display);
  font-size: 13.5px; font-weight: 300;
  line-height: 1.45; text-align: left;
  color: var(--ivory);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s ease, transform .5s cubic-bezier(.16, 1, .3, 1);
  pointer-events: none;
}
@media (hover: hover) {
  .gl-card:hover .gl-card-cap,
  .gl-card:focus-visible .gl-card-cap { opacity: 1; transform: none; }
}

/* A video card: its play ring, which steps aside once the muted preview
   (hover, desktop) is actually playing. */
.gl-play {
  position: absolute; left: 50%; top: 50%;
  width: 50px; height: 50px; margin: -25px 0 0 -25px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(201,169,110,0.55); border-radius: 50%;
  background: rgba(26,20,16,0.55);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  color: var(--gold);
  transition: opacity .35s ease, transform .5s cubic-bezier(.16, 1, .3, 1), background .3s, color .3s, border-color .3s;
  pointer-events: none;
}
.gl-play .icon { width: 18px; height: 18px; margin-left: 2px; }
.gl-card-preview { opacity: 0; }
.gl-card.is-previewing .gl-card-preview { opacity: 1; }
.gl-card.is-previewing .gl-play { opacity: 0; transform: scale(.85); }
@media (hover: hover) {
  .gl-card:hover .gl-play { background: var(--gold); border-color: var(--gold); color: var(--deep); }
}

/* The last card of each row: on to Instagram. */
.gl-card-more {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px;
  border-style: dashed; border-color: rgba(201,169,110,0.32);
  background: rgba(201,169,110,0.03);
  text-align: center;
}
.gl-more-icon {
  width: 52px; height: 52px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(201,169,110,0.3); border-radius: 50%;
  background: rgba(201,169,110,0.07);
  color: var(--gold);
  transition: background .3s, color .3s, border-color .3s;
}
.gl-more-icon .icon { width: 22px; height: 22px; }
.gl-more-text {
  padding-left: 3.5px;
  font-size: 10px; font-weight: 300;
  letter-spacing: 3.5px; text-transform: uppercase; line-height: 2;
  color: var(--gold);
}
.gl-card-more:hover,
.gl-card-more:focus-visible { border-style: solid; border-color: rgba(201,169,110,0.5); }
.gl-card-more:hover .gl-more-icon,
.gl-card-more:focus-visible .gl-more-icon { background: var(--gold); border-color: var(--gold); color: var(--deep); }

/* The row's arrows, wide screens only: round, in the margin beside the
   cards, gone at either end. */
.gl-arrow { display: none; }
@media (min-width: 960px) {
  .gl-arrow {
    position: absolute; z-index: 2;
    top: calc(6px + var(--card-h) / 2);
    width: 44px; height: 44px;
    display: flex; align-items: center; justify-content: center;
    padding: 0;
    border: 1px solid rgba(201,169,110,0.35); border-radius: 50%;
    background: rgba(26,20,16,0.6);
    -webkit-backdrop-filter: blur(10px);
            backdrop-filter: blur(10px);
    color: var(--gold);
    cursor: pointer;
    transition: opacity .3s ease, background .3s, color .3s, border-color .3s, visibility 0s;
  }
  .gl-arrow-prev { left:  calc(var(--row-pad) / 2); transform: translate(-50%, -50%); }
  .gl-arrow-next { right: calc(var(--row-pad) / 2); transform: translate(50%, -50%); }
  .gl-arrow-prev .icon { transform: scaleX(-1); }
  .gl-arrow:hover,
  .gl-arrow:focus-visible { background: var(--gold); border-color: var(--gold); color: var(--deep); outline: none; }
  .gl-arrow:disabled {
    opacity: 0; visibility: hidden;
    transition: opacity .3s ease, visibility 0s .3s;
  }
}

/* ── PHOTO PLACEHOLDER ──
   In the Fotos row's place until the photos arrive: a strip of the row's
   own empty frames, fading out towards the sides, with a card resting in
   its middle. The two share one grid cell, so whichever is taller (the
   frames on a wide screen, the card on a phone) sets the height. */
.gl-photo-empty {
  display: grid;
  align-items: center; justify-items: center;
  padding: 6px 0 10px;
}
.gl-photo-empty[hidden] { display: none; }
.gl-photo-empty > * { grid-area: 1 / 1; }
.gl-empty-frames {
  justify-self: stretch;
  display: flex; justify-content: center; gap: 12px;
  overflow: hidden;
  list-style: none;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  pointer-events: none;
}
.gl-empty-frames li {
  flex: none;
  width: var(--card-w); aspect-ratio: var(--card-ratio);
  border: 1px solid rgba(201,169,110,0.16);
  border-radius: 10px;
  background: linear-gradient(150deg, rgba(250,247,242,0.05), rgba(250,247,242,0.01));
}
@media (min-width: 960px) {
  .gl-empty-frames { gap: 16px; }
}
.gl-empty {
  position: relative;
  width: calc(100% - 2 * clamp(20px, 5vw, 48px)); max-width: 460px;
  padding: clamp(30px, 4vw, 40px) clamp(24px, 4vw, 40px);
  text-align: center;
  background: rgba(18,15,12,0.78);
  border: 1px solid rgba(201,169,110,0.22);
  border-radius: 16px;
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  box-shadow: 0 40px 80px -40px rgba(0,0,0,0.8);
}
.gl-empty::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(201,169,110,0.5), transparent);
}
.gl-empty-icon {
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  margin-bottom: 18px;
  border: 1px solid rgba(201,169,110,0.3); border-radius: 50%;
  background: rgba(201,169,110,0.07);
  color: var(--gold);
}
.gl-empty-icon .icon { width: 20px; height: 20px; }
.gl-empty-title {
  font-family: var(--font-display);
  font-size: clamp(24px, 3vw, 30px);
  font-weight: 300;
  line-height: 1.1;
  color: var(--ivory);
}
.gl-empty-text {
  max-width: 400px;
  margin: 12px auto 0;
  font-size: 15px; font-weight: 300;
  line-height: 1.8; letter-spacing: 0.3px;
  color: rgba(250,247,242,0.66);
}
.gl-empty-link { margin-top: 22px; }

/* ── VIEWER ──
   A modal <dialog> over the whole window (the top layer, so the nav's
   backdrop-filter can't trap it), holding a track of slides that scrolls
   sideways. --media-h is what a picture may use once the bar above and the
   caption below have their room. Photos and clips are shown alike: each
   slide hugs its picture's frame (a clip's 9:16, a photo's own shape), so
   the ones either side of it show (see HINTS). */
html.doc:has(.gl-viewer[open]) { overflow: hidden; }

.gl-viewer {
  --v-top: 64px;
  --v-bottom: 92px;
  --media-w: calc(100vw - 32px);
  --media-h: calc(100dvh - var(--v-top) - var(--v-bottom) - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
  --gap: 14px;   /* between two slides */
  --peek: 28px;  /* the least of each neighbour left in sight */
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0;
  background:
    radial-gradient(ellipse 80% 40% at 50% 100%, rgba(107,45,62,0.22) 0%, transparent 70%),
    linear-gradient(180deg, #1A1410 0%, #0F0C0A 100%);
  color: var(--ivory);
  overflow: hidden;
  -webkit-user-select: none; user-select: none;
}
.gl-viewer::backdrop { background: rgba(12,10,8,0.7); }
/* A tap on a hint focuses the dialog itself, and a key pressed after it
   would draw the focus ring round the whole screen. */
.gl-viewer:focus { outline: none; }
/* When not one slide has a caption, the room kept for it goes back, and
   the picture sits in the middle of the screen. (One caption keeps the
   room for them all, so no frame jumps between slides.) */
.gl-viewer:not(:has(.gl-slide-cap > *)) { --v-bottom: var(--v-top); }
.gl-viewer:not(:has(.gl-slide-cap > *)) .gl-slide { padding-bottom: calc(var(--v-bottom) + env(safe-area-inset-bottom, 0px)); }
.gl-viewer:not(:has(.gl-slide-cap > *)) .gl-slide-cap { display: none; }
/* From tablet width the side arrows sit in the margin, so a wide photo
   keeps clear of them. */
@media (min-width: 720px) {
  .gl-viewer { --media-w: calc(100vw - 176px); --peek: 76px; }
}
@media (prefers-reduced-motion: no-preference) {
  .gl-viewer[open]          { animation: fsax-fade-in .3s ease both; }
  .gl-viewer[open] .gl-v-track { animation: fsax-rise-in .5s cubic-bezier(.16, 1, .3, 1) both; }
}

.gl-v-track {
  position: absolute; inset: 0;
  display: flex;
  overflow-x: auto; overflow-y: hidden;
  overscroll-behavior: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* Up and down is galeria.js's to draw, not the browser's to pan (the
     second line, where pinch-zoom is understood, keeps pinching). */
  touch-action: pan-x;
  touch-action: pan-x pinch-zoom;
}
.gl-v-track::-webkit-scrollbar { display: none; }
/* Room either side, so the first and last slides can reach the middle
   (half the track is enough for a slide of any width). */
.gl-v-track::before,
.gl-v-track::after { content: ''; flex: 0 0 50%; }
/* A slide is as wide as its picture is when it is as tall as it may be
   (--ratio, width over height: 9:16 for a clip, set by galeria.js for a
   photo), unless that leaves too little of the neighbours in sight. So
   photos' slides differ in width, and galeria.js finds the current one by
   its middle. */
.gl-slide {
  --ratio: .5625;
  --slide-w: min(100% - 2 * var(--peek), var(--media-h) * var(--ratio) + var(--gap));
  flex: 0 0 var(--slide-w); min-width: 0;
  display: flex; align-items: center; justify-content: center;
  padding: calc(var(--v-top) + env(safe-area-inset-top, 0px)) calc(var(--gap) / 2) calc(12px + env(safe-area-inset-bottom, 0px));
  scroll-snap-align: center; scroll-snap-stop: always;
}
.gl-slide-fig {
  width: 100%;
  display: flex; flex-direction: column; align-items: center;
  gap: 14px;
}

/* The picture's frame fills its slide, which is sized to fit it: rounded
   like the site's other panels, lifted by a soft shadow with a faint warm
   halo. */
.gl-media {
  position: relative;
  width: 100%; aspect-ratio: var(--ratio);
  isolation: isolate;  /* Safari otherwise lets a playing video escape the rounded corners */
  border-radius: 16px;
  overflow: hidden;
  background: rgba(250,247,242,0.03);
  box-shadow:
    0 2px 6px rgba(0,0,0,0.3),
    0 36px 80px -28px rgba(0,0,0,0.85),
    0 0 100px -36px rgba(201,169,110,0.22);
}
/* A gold hairline drawn over the picture, so its edge stays crisp against
   a bright sky as well as a dark room. */
.gl-media::after {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(201,169,110,0.28);
  pointer-events: none;
}
/* A photo shows the row's copy of itself until the full one lands. */
.gl-still {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  background: center / cover no-repeat;
}
.gl-still-video,
.gl-v-player {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
}
/* A clip either side is already loading in its slide (galeria.js keeps
   three players), but its still shows until it is the current one. */
.gl-slide:not(.is-current) .gl-v-player { opacity: 0; }
.gl-media.is-video { cursor: pointer; }

/* Play ring in the middle while a clip is paused (or not yet started). */
.gl-v-state {
  position: absolute; left: 50%; top: 50%;
  width: 64px; height: 64px; margin: -32px 0 0 -32px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(201,169,110,0.6); border-radius: 50%;
  background: rgba(26,20,16,0.55);
  -webkit-backdrop-filter: blur(8px);
          backdrop-filter: blur(8px);
  color: var(--gold);
  opacity: 0; transform: scale(.9);
  transition: opacity .3s ease, transform .4s cubic-bezier(.16, 1, .3, 1);
  pointer-events: none;
}
.gl-v-state .icon { width: 22px; height: 22px; margin-left: 3px; }
.gl-media.is-paused .gl-v-state { opacity: 1; transform: none; }

/* ── HINTS ──
   The photos or clips either side of the current one: smaller and dimmed,
   and shrunk towards it, so the strip of them in sight is the edge nearest
   it. Any further out stay hidden (only the current one and its neighbours
   are ever fetched). A tap on one goes to it.
   Shrunk about the middle and moved in by (1 − .84) / 2 = 8% of their
   width: the same as shrinking about the near edge, but, unlike a moving
   transform-origin, it runs on the compositor, away from the clip swap. */
.gl-v-track { cursor: pointer; }
.gl-slide.is-current { cursor: auto; }
.gl-slide-fig {
  opacity: 0; scale: .84;
  transition: opacity .4s ease, scale .55s cubic-bezier(.16, 1, .3, 1), translate .55s cubic-bezier(.16, 1, .3, 1);
}
.is-before .gl-slide-fig { opacity: .32; translate: 8% 0; }
.is-after  .gl-slide-fig { opacity: .32; translate: -8% 0; }
.is-current .gl-slide-fig { opacity: 1; scale: none; }
.gl-slide:not(.is-current) .gl-v-state { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .gl-slide-fig { transition: opacity .4s ease; }
}
/* While an up-or-down swipe swaps the slide they step out at once, and
   come back beside the new one. */
.gl-viewer.is-swapping .gl-slide:not(.is-current) .gl-slide-fig { opacity: 0; transition: none; }

.gl-slide-cap {
  max-width: min(560px, var(--media-w));
  min-height: calc(var(--v-bottom) - 26px);
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
  text-align: center;
}
.gl-slide-cap p {
  font-family: var(--font-display);
  font-size: 15px; font-weight: 300;
  line-height: 1.5;
  color: rgba(250,247,242,0.86);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}

/* The bar above: the counter, in the numerals of the Serviços steps, and
   the close ring. */
.gl-v-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  height: calc(var(--v-top) + env(safe-area-inset-top, 0px));
  padding: env(safe-area-inset-top, 0px) 16px 0 22px;
  display: flex; align-items: center; justify-content: space-between;
  pointer-events: none;
}
.gl-v-top > * { pointer-events: auto; }
.gl-v-count {
  font-family: 'Cinzel', serif;
  font-size: 13px; font-weight: 300; letter-spacing: 2px;
  color: var(--gold);
}
.gl-v-sep { margin: 0 8px; opacity: 0.5; }
/* Photos and clips go without it (hidden, not removed, so the close ring
   keeps its place on the right); each slide still names its place to a
   screen reader. */
.gl-v-count { visibility: hidden; }

.gl-v-btn {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  border: 1px solid rgba(201,169,110,0.35); border-radius: 50%;
  background: rgba(26,20,16,0.6);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  color: var(--gold);
  cursor: pointer;
  transition: opacity .3s ease, background .3s, color .3s, border-color .3s, visibility 0s;
}
.gl-v-btn:focus { outline: none; }
.gl-v-btn:hover,
.gl-v-btn:focus-visible { background: var(--gold); border-color: var(--gold); color: var(--deep); }

/* Side arrows from tablet width up; on a phone the swipe does it. */
.gl-v-nav { display: none; }
@media (min-width: 720px) {
  .gl-v-nav {
    position: absolute; top: 50%; z-index: 2;
    display: flex;
    margin-top: -22px;
  }
  .gl-v-prev { left: 24px; }
  .gl-v-next { right: 24px; }
  .gl-v-prev .icon { transform: scaleX(-1); }
  .gl-v-nav:disabled {
    opacity: 0; visibility: hidden;
    transition: opacity .3s ease, visibility 0s .3s;
  }
}
