/* ============================================================================
   LAYOUT — shared header + footer. Reads only from tokens.css.
   ========================================================================== */

/* ============================ HEADER ==================================== */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-height);
  display: flex;
  align-items: center;
  background: transparent;
  transition: background var(--transition), box-shadow var(--transition), height var(--transition);
}
/* solid state once the page is scrolled (toggled by site.js) */
.site-header.is-scrolled {
  background: var(--header-bg-scrolled);
  backdrop-filter: blur(var(--header-blur));
  -webkit-backdrop-filter: blur(var(--header-blur));   /* Safari */
  box-shadow: 0 1px 0 var(--color-border);
  height: calc(var(--header-height) - var(--space-6));
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  width: 100%;
}
.site-header__logo { flex: none; }
.site-header__logo img {
  width: var(--logo-size); height: var(--logo-size);
  object-fit: contain;
  transition: width var(--transition), height var(--transition);
}
/* shrink the mark in step with the bar when the header condenses */
.site-header.is-scrolled .site-header__logo img {
  width: calc(var(--logo-size) - var(--space-6));
  height: calc(var(--logo-size) - var(--space-6));
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  list-style: none;
  padding: 0;
}
.site-nav__list a {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  font-weight: var(--fw-medium);
  font-size: 0.875rem;              /* 14px, per the live site */
  color: var(--color-heading);
  position: relative;
  padding: 13px 10px;
  transition: color var(--transition);
}
/* --- Curs CTA ---------------------------------------------------------------
   The one nav item that is a button, not a link: it appears only for a signed-in
   user with an unexpired pass, so it should read as an action rather than as
   another destination. Solid accent, and no snake-draw border (the fill is the
   affordance) — hence the ::before/::after reset below. */
.site-nav__list a.site-nav__cta {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border-radius: var(--radius);
  padding: 10px 18px;
  transition: background var(--transition), color var(--transition);
}
.site-nav__list a.site-nav__cta::before,
.site-nav__list a.site-nav__cta::after { content: none; }
.site-nav__list a.site-nav__cta:hover,
.site-nav__list a.site-nav__cta:focus-visible {
  background: var(--color-heading);
  color: #000;
}
/* Active page: the CTA is already solid, so keep it solid rather than letting
   the shared aria-current rule repaint it accent-on-transparent. */
.site-nav__list a.site-nav__cta[aria-current="page"] {
  background: var(--color-heading);
  color: #000;
}

/* --- "Snake draw" border (Elementor-style) ---------------------------------
   Two pseudo-elements, each drawing two adjacent sides. Staggered transition
   delays make a single line travel the perimeter: top → right → bottom → left,
   like the border is being sketched by hand.
   Per-side draw duration is 0.16s (kept in sync across the rules below). */
.site-nav__list a::before,
.site-nav__list a::after {
  content: '';
  position: absolute;
  width: 0; height: 0;
  box-sizing: border-box;
  border: 2px solid transparent;
  pointer-events: none;
  transition: all 0.16s ease;
}
.site-nav__list a::before { top: 0; left: 0; }       /* draws top, then right */
.site-nav__list a::after  { bottom: 0; right: 0; }   /* draws bottom, then left */

.site-nav__list a:hover::before,
.site-nav__list a:focus-visible::before {
  width: 100%; height: 100%;
  border-top-color: var(--color-accent);
  border-right-color: var(--color-accent);
  transition: width 0.16s ease-out, height 0.16s ease-out 0.16s;
}
.site-nav__list a:hover::after,
.site-nav__list a:focus-visible::after {
  width: 100%; height: 100%;
  border-bottom-color: var(--color-accent);
  border-left-color: var(--color-accent);
  transition: border-color 0s ease-out 0.32s, width 0.16s ease-out 0.32s, height 0.16s ease-out 0.48s;
}

/* Active page = the completed square, plus accent text. It is a state, not a
   gesture, so it must appear instantly: the border-draw transition above is for
   the hover only. site.js sets aria-current a tick after the header loads, so
   without this the square would animate itself in from the corners on every
   page load ("drawing" itself in). transition:none pins it in place. */
.site-nav__list a[aria-current="page"] { color: var(--color-accent); }
.site-nav__list a[aria-current="page"]::before,
.site-nav__list a[aria-current="page"]::after {
  width: 100%; height: 100%;
  border-color: var(--color-accent);
  transition: none;
}

.site-header__actions { display: flex; align-items: center; gap: var(--space-5); }
.site-header__phone {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-weight: var(--fw-bold);
  color: var(--color-accent);
  white-space: nowrap;
}
.site-header__phone:hover { color: var(--color-accent-hover); }

/* Burger (hidden on desktop) */
.site-header__burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 44px;
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 8px;
}
.site-header__burger span {
  display: block; height: 2px; width: 100%;
  background: var(--color-heading);
  transition: transform var(--transition), opacity var(--transition);
}

/* The backdrop must sit BELOW the header: .site-header creates its own stacking
   context (it is positioned with a z-index), so the slide-out nav inside it can
   never rise above a sibling painted higher — a backdrop above the header would
   veil the panel and mute every link in it. */
.site-menu-backdrop {
  position: fixed; inset: 0;
  background: var(--color-overlay);
  z-index: calc(var(--z-header) - 1);
  opacity: 0; pointer-events: none;
  transition: opacity var(--transition);
}
.site-menu-backdrop.is-open { opacity: 1; pointer-events: auto; }

/* While the viewport is being resized, crossing the breakpoint would otherwise
   animate the panel's transform from "none" to "off-screen" — reading as the
   menu flashing open and sliding shut. Transitions belong to user actions, not
   to layout switching, so they're suppressed for the duration of the resize
   (site.js sets data-resizing on <html>). */
[data-resizing] .site-nav,
[data-resizing] .site-menu-backdrop,
[data-resizing] .site-header,
[data-resizing] .site-header__logo img { transition: none; }

/* ---- Mobile ---- */
@media (max-width: 900px) {
  .site-header { height: var(--header-height-sm); }
  .site-header.is-scrolled { height: calc(var(--header-height-sm) - var(--space-5)); }
  .site-header__logo img { width: var(--logo-size-sm); height: var(--logo-size-sm); }
  .site-header.is-scrolled .site-header__logo img {
    width: calc(var(--logo-size-sm) - var(--space-5));
    height: calc(var(--logo-size-sm) - var(--space-5));
  }

  /* keep the burger above the slide-out panel so the close (X) stays clickable */
  .site-header__burger { display: flex; position: relative; z-index: calc(var(--z-modal) + 1); }
  /* WhatsApp lives in the floating action button on mobile, not the bar */
  .site-header__phone { display: none; }

  .site-nav {
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(82vw, 340px);
    background: var(--color-surface-1);
    border-left: 1px solid var(--color-border);
    z-index: var(--z-modal);
    padding: calc(var(--header-height-sm) + var(--space-4)) 0 var(--space-6);
    transform: translateX(100%);
    transition: transform var(--transition);
    box-shadow: var(--shadow-lg);
    overflow-y: auto;
  }
  .site-nav.is-open { transform: translateX(0); }

  .site-nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .site-nav__list a {
    display: block;
    font-size: var(--fs-lg);
    padding: var(--space-4) var(--space-6);
    color: var(--color-heading);
    border-bottom: 1px solid var(--color-border);
  }
  /* The drawn-border hover belongs to the desktop bar; rows read better as
     full-width fills on a narrow panel. */
  .site-nav__list a::before,
  .site-nav__list a::after { content: none; }
  .site-nav__list a:hover,
  .site-nav__list a:focus-visible { background: var(--color-surface-3); color: var(--color-accent); }
  /* Active page = solid accent row, mirroring the live site's mobile menu. */
  .site-nav__list a[aria-current="page"] {
    background: var(--color-accent);
    color: var(--color-on-accent);
  }

  body.menu-open .site-header__burger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  body.menu-open .site-header__burger span:nth-child(2) { opacity: 0; }
  body.menu-open .site-header__burger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

/* Scroll lock, shared by every overlay (mobile menu, video modal, lightbox).
   It has to live outside the mobile media query — the lightbox and the video
   modal open on desktop too, and the page used to keep scrolling behind them. */
body.is-locked { overflow: hidden; }

/* ========================= PRICING CARD (shared) =======================
   Lives here, not in the site's page CSS, because the app sells the same two
   courses and must render the identical card. Layout is a column with the CTA
   pinned to the bottom, so two cards side by side line up whatever the copy.
   ====================================================================== */
.price-card {
  display: flex; flex-direction: column;
  background: var(--color-surface-1);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  transition: border-color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}
.price-card:hover {
  border-color: var(--color-accent);
  transform: translateY(-4px);
  box-shadow: var(--glow-accent);
}
.price-card__name {
  font-size: var(--fs-xl);
  color: var(--color-text-muted);
  letter-spacing: var(--tracking-wide);
}
.price-card__price {
  font-family: var(--font-heading);
  font-size: var(--fs-price);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  color: var(--color-heading);
  margin-top: var(--space-2);
}
.price-card__list {
  list-style: none; padding: 0;
  margin: var(--space-5) 0 var(--space-6);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.price-card__list li {
  display: flex; align-items: center; gap: var(--space-3);
  font-size: var(--fs-sm);
}
.check-icon { flex: none; width: 20px; height: 20px; }
.check-icon circle { fill: var(--color-accent); }
.check-icon path  { stroke: var(--color-on-accent); }

/* The CTA is pushed to the bottom so a card with more features stays aligned
   with a shorter one next to it. */
.price-card__cta { margin-top: auto; width: 100%; }
.btn__chevron { width: 18px; height: 18px; flex: none; }

/* ======================== SLIDER (shared) =============================
   A scroll-snap track with arrow buttons. Native scrolling does the work, so
   touch, trackpad and keyboard all behave without a line of JS layout maths —
   site.js only wires the arrows and hides them when nothing overflows.
   How many slides fit is set per use with --slider-visible.
   ====================================================================== */
.slider { position: relative; --slider-visible: 3; }
.slider__track {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100% - (var(--slider-visible) - 1) * var(--space-4)) / var(--slider-visible));
  gap: var(--space-4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;                     /* the arrows are the affordance */
  overscroll-behavior-x: contain;
  /* Smoothness comes from CSS, not from scrollTo({behavior:'smooth'}): the
     arrows set scrollLeft directly, so if a browser (or a reduced-motion
     setting) refuses to animate, the slider still moves instead of dying. */
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) { .slider__track { scroll-behavior: auto; } }
.slider__track::-webkit-scrollbar { display: none; }
.slider__slide { scroll-snap-align: start; display: flex; }
.slider__slide > * { width: 100%; }

.slider__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-pill); cursor: pointer;
  background: transparent; color: var(--color-heading);
  transition: color var(--transition), background var(--transition);
}
.slider__nav:hover { color: var(--color-accent); }
.slider__nav svg { width: 26px; height: 26px; }
.slider__nav--prev { right: 100%; }
.slider__nav--next { left: 100%; }
/* Nothing to scroll (every slide already fits) — the arrows would be dead. */
.slider.is-static .slider__nav { display: none; }
/* Narrow screens: there is no room beside the track, and arrows laid over the
   card sit on top of the words. They drop underneath it instead, centred. */
@media (max-width: 900px) {
  .slider { --slider-visible: 2; padding-bottom: calc(44px + var(--space-4)); }
  .slider__nav {
    top: auto; bottom: 0; transform: none;
    background: var(--color-surface-3);
  }
  .slider__nav--prev { right: 50%; left: auto; margin-right: var(--space-2); }
  .slider__nav--next { left: 50%; right: auto; margin-left: var(--space-2); }
  .slider.is-static { padding-bottom: 0; }
}
@media (max-width: 620px) { .slider { --slider-visible: 1; } }

/* ========================= REVIEW CARD (shared) ======================= */
.review-card {
  display: flex; flex-direction: column; gap: var(--space-4);
  background: var(--color-surface-3);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: 0;
}
.review-card__head { display: flex; align-items: center; gap: var(--space-3); }
.review-card__avatar {
  flex: none; width: 36px; height: 36px;
  border-radius: var(--radius-pill); object-fit: cover;
}
.review-card__name { color: var(--color-heading); }
.review-card__quote-icon {
  margin-left: auto; flex: none;
  width: 20px; height: 20px; color: var(--color-accent);
}
.review-card__quote { margin: 0; line-height: var(--lh-snug); }

/* ============================ FOOTER ====================================
   Mirrors the live site: the workshop photo runs behind the whole footer under
   a dark scrim, with the top of the scrim fully black so the footer melts out
   of whatever section precedes it (full-bleed CTA artwork included) and no
   strip of dead black appears. No top margin — every section already carries
   its own bottom padding.
   ====================================================================== */
.site-footer {
  position: relative;
  isolation: isolate;
  background: var(--color-bg) url('/shared/assets/images/footer-bg.webp') center / cover no-repeat;
}
/* Scrim: solid black at the very top (seamless join), easing to a readable
   wash over the photo, then darkening again into the copyright bar. */
.site-footer::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(
    to bottom,
    var(--color-bg) 0%,
    var(--color-overlay-strong) 18%,
    rgba(0, 0, 0, 0.84) 62%,
    rgba(0, 0, 0, 0.92) 100%
  );
}

/* ---- Top block: brand + link columns --------------------------------- */
.site-footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--space-7);
  padding-block: var(--space-8) var(--space-7);
  align-items: start;
}
.site-footer__brand { display: flex; flex-direction: column; gap: var(--space-4); }
.site-footer__logo {
  width: clamp(130px, 14vw, 190px); height: auto;
  object-fit: contain;
}
.site-footer__tagline {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  max-width: 34ch;
  margin: 0;
}

.site-footer__title {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-semibold);
  color: var(--color-accent);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin: 0 0 var(--space-5);
}

.site-footer__links,
.site-footer__contact,
.site-footer__social,
.site-footer__badges {
  list-style: none; padding: 0; margin: 0;
}
.site-footer__links,
.site-footer__contact {
  display: flex; flex-direction: column; gap: var(--space-3);
}
.site-footer__links a,
.site-footer__contact a {
  display: inline-flex; align-items: center; gap: var(--space-3);
  color: var(--color-text);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  transition: color var(--transition);
}
.site-footer__links a:hover,
.site-footer__contact a:hover { color: var(--color-accent); }
/* The icon carries the accent by default; the label lights up on hover. */
.site-footer__icon { width: 20px; height: 20px; flex: none; color: var(--color-accent); }

/* ---- Social: cyan tiles, as on the live site ------------------------- */
.site-footer__social {
  display: flex; flex-wrap: wrap; gap: var(--space-3);
  margin-top: var(--space-5);
}
.site-footer__social a {
  display: grid; place-items: center;
  width: 42px; height: 42px;
  border-radius: var(--radius);
  background: var(--color-accent);
  color: var(--color-heading);
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.site-footer__social svg { width: 21px; height: 21px; }
.site-footer__social a:hover {
  background: var(--color-accent-hover);
  transform: translateY(-2px);
  box-shadow: var(--glow-accent);
}
.site-footer__social a:active { background: var(--color-accent-press); transform: none; }

/* ---- Legal links + trust badges -------------------------------------- */
.site-footer__legal {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-3) var(--space-6);
  padding-block: var(--space-5);
  border-top: 1px solid var(--color-border);
  text-align: center;
}
.site-footer__legal a {
  color: var(--color-text-muted);
  font-size: var(--fs-sm);
  transition: color var(--transition);
}
.site-footer__legal a:hover { color: var(--color-accent); }

.site-footer__badges {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--space-4) var(--space-5);
  padding-bottom: var(--space-7);
}
.site-footer__badges img {
  display: block;
  height: 52px; width: auto; max-width: 100%;
  opacity: 0.9;
  transition: opacity var(--transition);
}
.site-footer__badges a:hover img { opacity: 1; }

/* ---- Copyright bar ---------------------------------------------------- */
.site-footer__bottom {
  border-top: 1px solid var(--color-border);
  background: var(--color-overlay);
}
.site-footer__bottom-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-2) var(--space-4); padding-block: var(--space-5);
  font-family: var(--font-ui); font-size: var(--fs-xs); color: var(--color-text-faint);
  flex-wrap: wrap;
}
.site-footer__bottom-inner p { margin: 0; }
.site-footer__credit a { color: var(--color-text-muted); transition: color var(--transition); }
.site-footer__credit a:hover { color: var(--color-accent); }

/* ---- Responsive ------------------------------------------------------- */
/* Tablets: the brand block spans the full width above the two link columns,
   so neither column has to squeeze. */
@media (max-width: 900px) {
  .site-footer__top {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-6);
    padding-block: var(--space-7) var(--space-6);
  }
  .site-footer__brand { grid-column: 1 / -1; align-items: center; text-align: center; }
  .site-footer__tagline { max-width: 46ch; }
  /* The photo is cropped much tighter on a narrow, tall footer, so a brighter
     part of it can end up behind the copy — darken the scrim to compensate. */
  .site-footer::before {
    background: linear-gradient(
      to bottom,
      var(--color-bg) 0%,
      rgba(0, 0, 0, 0.88) 14%,
      rgba(0, 0, 0, 0.90) 60%,
      rgba(0, 0, 0, 0.94) 100%
    );
  }
}
/* Phones: one column, everything centred — matches how the live site stacks. */
@media (max-width: 600px) {
  .site-footer__top { grid-template-columns: minmax(0, 1fr); text-align: center; }
  .site-footer__col { display: flex; flex-direction: column; align-items: center; }
  .site-footer__contact a { max-width: 100%; }
  .site-footer__contact span { overflow-wrap: anywhere; }
  .site-footer__social { justify-content: center; }
  .site-footer__bottom-inner { justify-content: center; text-align: center; }
  .site-footer__badges img { height: 42px; }
}

@media (prefers-reduced-motion: reduce) {
  .site-footer__social a:hover { transform: none; }
}

/* ======================== VIDEO MODAL (shared) ========================= */
/* Injected once by site.js; opened by any [data-video="<youtube-id>"] element.
   Add data-video-portrait on the trigger for a vertical (9:16) player. */
.video-modal {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid; place-items: center;
  /* extra room at the top so the close button sits clear ABOVE the player and
     never collides with YouTube's own volume / CC / settings controls */
  padding: clamp(56px, 9vh, 84px) var(--space-5) var(--space-5);
  background: rgba(0, 0, 0, 0.9);
  opacity: 0; pointer-events: none;
  transition: opacity var(--transition);
  /* height budget for the player, after the modal padding and the strip the
     close button occupies above it */
  --video-max-h: 78vh;
}
.video-modal.is-open { opacity: 1; pointer-events: auto; }
.video-modal__dialog {
  position: relative;                  /* anchors the close button */
  /* The dialog owns the sizing: capped by viewport width AND by the height
     budget, so the player always fits in both orientations. */
  width: min(92vw, 960px, calc(var(--video-max-h) * 16 / 9));
  transform: scale(0.96);
  transition: transform var(--transition);
}
.video-modal--portrait .video-modal__dialog {
  width: min(92vw, calc(var(--video-max-h) * 9 / 16));
}
.video-modal.is-open .video-modal__dialog { transform: scale(1); }
.video-modal__frame {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-radius: var(--radius-lg);
  overflow: hidden;                    /* clips the iframe to the radius */
  box-shadow: var(--shadow-lg);
}
.video-modal--portrait .video-modal__frame { aspect-ratio: 9 / 16; }
.video-modal__frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.video-modal__close {
  position: absolute; bottom: calc(100% + var(--space-3)); right: 0; z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-pill); cursor: pointer;
  background: var(--color-accent); color: var(--color-on-accent);
  box-shadow: var(--shadow);
  transition: background var(--transition), transform var(--transition);
}
.video-modal__close:hover { background: var(--color-accent-hover); transform: scale(1.06); }
.video-modal__close svg { width: 22px; height: 22px; }
@media (max-width: 560px) {
  .video-modal { padding-inline: var(--space-3); }
}

/* ========================= LIGHTBOX (shared) ===========================
   One instance, created on first use by site.js and reused by any gallery.

   Height chain matters here: `max-height: 100%` on the image only constrains
   anything if every ancestor above it has a DEFINITE height. .lightbox is
   fixed to the viewport, the dialog fills it, and the stage is the 1fr row of
   the dialog's grid — so the image finally has a real height to measure
   against. Each step also needs min-height: 0, or the grid rows refuse to
   shrink below their content and the picture spills off screen.
   ====================================================================== */
.lightbox {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid;
  grid-template-rows: minmax(0, 1fr);        /* one definite row for the dialog */
  place-items: stretch;
  padding: clamp(var(--space-4), 3vw, var(--space-6));
  background: rgba(0, 0, 0, 0.92);
  /* visibility, not just opacity: a transparent overlay still holds its
     buttons in the tab order and exposes them to screen readers. */
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity var(--transition), visibility var(--transition);
}
.lightbox.is-open { opacity: 1; pointer-events: auto; visibility: visible; }

.lightbox__dialog {
  position: relative;
  width: 100%; height: 100%;
  min-width: 0; min-height: 0;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;   /* picture, then the counter */
  justify-items: center;
  gap: var(--space-3);
}

.lightbox__stage {
  grid-row: 1;
  margin: 0;
  min-width: 0; min-height: 0;               /* let the row actually shrink */
  width: 100%; height: 100%;
  /* Flex, not grid: the image's `max-height: 100%` has to resolve against a
     definite height. In a grid the image sits in an auto-sized row, so the row
     is sized *by* the image and the percentage is circular — it resolved to
     `none` and a tall photo overflowed the viewport. A flex container with a
     definite height gives the percentage something real to measure against. */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;                          /* belt and braces */
}
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  min-width: 0; min-height: 0;               /* flex items don't shrink otherwise */
  width: auto; height: auto;
  object-fit: contain;
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  user-select: none; -webkit-user-drag: none;
}

.lightbox__counter {
  grid-row: 2;
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  letter-spacing: var(--tracking-wide);
  color: var(--color-text-muted);
  margin: 0;
}

.lightbox__close {
  position: absolute; top: 0; right: 0; z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-pill); cursor: pointer;
  background: var(--color-accent); color: var(--color-on-accent);
  box-shadow: var(--shadow);
  transition: background var(--transition), transform var(--transition);
}
.lightbox__close:hover { background: var(--color-accent-hover); transform: scale(1.06); }
.lightbox__close svg { width: 22px; height: 22px; }

.lightbox__nav {
  position: absolute; z-index: 2;
  top: calc(50% - var(--space-5));           /* centre of the picture row */
  transform: translateY(-50%);
  width: 52px; height: 52px; display: grid; place-items: center;
  border: 0; border-radius: var(--radius-pill); cursor: pointer;
  background: rgba(255, 255, 255, 0.1);
  color: var(--color-heading);
  transition: background var(--transition), color var(--transition);
}
.lightbox__nav:hover { background: var(--color-accent); color: var(--color-on-accent); }
.lightbox__nav svg { width: 26px; height: 26px; }
.lightbox__nav--prev { left: 0; }
.lightbox__nav--next { right: 0; }

/* Phones: arrows drop beside the counter so they never sit over the photo.
   They sit at the outer edges, the counter stays centred — no overlap. */
@media (max-width: 620px) {
  .lightbox { padding: var(--space-6) var(--space-3) var(--space-4); }
  .lightbox__nav {
    top: auto; bottom: 0; transform: none;
    width: 46px; height: 46px;
  }
  .lightbox__nav--prev { left: var(--space-2); }
  .lightbox__nav--next { right: var(--space-2); }
  .lightbox__dialog { grid-template-rows: minmax(0, 1fr) 46px; }
  .lightbox__counter { align-self: center; }
}
