/*==================================================================
  Χ.Α.Ν.Θ. — COMPONENTS & SECTIONS
  ------------------------------------------------------------------
  Built from the design handoff. Every value comes from a token in
  css/styles.css — no literals here except structural zeros/100%.
  Responsive overrides live in css/media-queries.css.
  ------------------------------------------------------------------
  1.  PAGE SHELL
  2.  BACKDROP
  3.  HEADER / NAV
  4.  MOBILE MENU
  5.  FOOTER
  6.  TYPOGRAPHY BLOCKS
  7.  PAGE TITLE LOZENGE
  8.  SPLIT SECTION
  9.  PROSE PANEL
  10. DARK CARD
  11. LINK LIST
  12. PHOTO PAIR
  13. VIDEO GRID
  14. PLAYER MODAL
  15. LEGAL
  16. LIGHTBOX
==================================================================*/

/*------ 1. PAGE SHELL ------*/
.page {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.page__inner {
  position: relative;
  z-index: var(--z-content);
  display: flex;
  flex-direction: column;
  flex: 1;
}

.main {
  padding-top: var(--main-pd-top);
  padding-bottom: var(--main-pd-bottom);
}

.main--home {
  padding-top: var(--main-pd-top-home);
  display: flex;
  flex-direction: column;
  gap: var(--sp-66);
}

/*------ 2. BACKDROP ------*/
/* The wedges are sized from the space the content leaves them, so they never
   reach a line of text — no scrim over the copy, nothing behind it.

   ONE SIZE, EVERY PAGE. Each page could take a different wedge — the
   inner-column pages leave much more room than Αρχική does — but a backdrop
   that changes size as you move through the site reads as five backdrops. So
   every page is measured against every page's content, and takes the smallest
   result: identical wedges throughout, set by whichever page has the least to
   give at that viewport (usually Αρχική).

   Two things give a wedge room, and it takes both:

   - the clear zone: what remains of the page once a column has taken its
     width. Percentages here resolve against the backdrop box, which is the
     page, so this tracks the real gutter at every viewport with no breakpoints
     of its own.
   - the empty height it crosses on the way in. A wedge enters at its widest
     and narrows as it travels, so every pixel of clear height between its
     leading edge and the first line of copy buys it another --tri-lift px of
     reach: by the time it arrives at that line it has narrowed back to the
     clear zone exactly. At the top that height is the strip under the
     transparent header before the copy starts — --tri-head on Αρχική, and
     --tri-head-title on the four pages that open with a title lozenge. At the
     bottom it is --tri-foot: the empty strip above the footer plus the footer
     itself, which is opaque and paints over the wedge, so the wedge passes
     behind it rather than stopping on top of it.

   --tri-reach-* is the result: the wedge's on-screen half-width. The other
   half hangs off the page edge, as the handoff draws it. */
.backdrop {
  position: absolute;
  inset: 0;
  z-index: var(--z-backdrop);
  overflow: hidden;
  pointer-events: none;

  --tri-gutter: max(var(--gutter), (100% - var(--w-content)) / 2);
  /* Αρχική's strip: its opening section starts at --main-pd-top-home */
  --tri-head: var(--main-pd-top-home);
  /* the strip on the four pages that open with a title lozenge. The lozenge
       is a short inline block on the left, so the wedge crosses its band too,
       down to the top of the column under it */
  --tri-head-title: calc(
    var(--main-pd-top) + var(--h-page-title) + var(--sp-46)
  );
  --tri-foot: calc(var(--main-pd-bottom) + var(--footer-h));

  /* Three content edges bind the top wedge. All three are read on every
       page, which is what keeps the wedge the same size across the site. */
  --tri-reach-tr: min(
    /* 1. Αρχική's opening section — left-aligned, so the room is what is
              left of the page column to the right of it */
    calc(
        max(var(--gutter), 100% - var(--tri-gutter) - var(--w-lead)) +
          var(--tri-head) * var(--tri-lift)
      ),
    /* 2. the full page column, which resumes below that section: the wedge
              has to have narrowed back to its gutter by the time it drops
              past the section's floor */
    calc(
        var(--tri-gutter) + (var(--tri-head) + var(--h-lead-min)) *
          var(--tri-lift)
      ),
    /* 3. Σεμινάρια's inner column, under its lozenge. The widest inner
              column on the site, so of the four lozenge pages it is the one
              that leaves the least */
    calc(
        max(var(--gutter), (100% - var(--w-col-mid)) / 2) +
          var(--tri-head-title) * var(--tri-lift)
      )
  );
  /* the floor runs the full page column on every page, so the bottom wedge
       is the same everywhere by construction */
  --tri-reach-bl: calc(var(--tri-gutter) + var(--tri-foot) * var(--tri-lift));
  --tri-rule: max(var(--tri-rule-min), var(--tri-rule-w));
}

.backdrop__tri {
  position: absolute;
  /* half hangs off the page edge, as in the handoff, so the on-screen
       half is exactly the reach */
  width: calc(var(--tri-reach) * 2);
  aspect-ratio: 2 / 1.732; /* equilateral */
}

/* The wedge used to dissolve into the header behind a white scrim. It stops
   short of the nav now, so the dissolve moved onto its own top edge — same
   soft entry under the navigation, without going near the links. */
.backdrop__tri--tr {
  --tri-reach: var(--tri-reach-tr);
  right: calc(var(--tri-reach) * -1);
  top: var(--header-h);
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0,
    var(--black) var(--tri-fade-in)
  );
  mask-image: linear-gradient(
    to bottom,
    transparent 0,
    var(--black) var(--tri-fade-in)
  );
}

/* anchored to the page floor: the rule runs on behind the opaque footer
   rather than stopping dead on top of it */
.backdrop__tri--bl {
  --tri-reach: var(--tri-reach-bl);
  left: calc(var(--tri-reach) * -1);
  bottom: 0;
}

.backdrop__photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: var(--tri-opacity);
}

/* base at top, apex down */
.backdrop__tri--tr .backdrop__photo {
  clip-path: polygon(0 0, 100% 0, 50% 100%);
}

/* base at bottom, apex up */
.backdrop__tri--bl .backdrop__photo {
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}

.backdrop__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--tri-filter);
}

.backdrop__tri--tr .backdrop__photo img {
  width: var(--tri-photo-w-tr);
}

.backdrop__rule {
  position: absolute;
  /* proportional so the rule keeps its weight as the wedge resizes, with
       a floor so it stays a line at the narrowest gutters */
  width: var(--tri-rule);
  /* the wedge's side — its own width, read off its height */
  height: 115.47%;
  transform-origin: top left;
}

.backdrop__tri--tr .backdrop__rule {
  left: 0;
  top: 0;
  background: var(--xanth-blue);
  transform: rotate(-30deg);
}

.backdrop__tri--bl .backdrop__rule {
  left: calc(100% - var(--tri-rule));
  bottom: 0;
  background: var(--xanth-red);
  transform-origin: bottom left;
  transform: rotate(-30deg);
}

/*------ 3. HEADER / NAV ------*/
.header {
  position: relative;
  z-index: var(--z-content);
  background: transparent;
}

.header__inner {
  position: relative;
  height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.header__logo {
  display: flex;
  flex-shrink: 0;
}

.header__logo img {
  width: var(--logo-header-w);
  height: var(--logo-header-h);
  object-fit: contain;
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--sp-30);
}

.nav__link {
  font-family: var(--font-display);
  font-size: var(--size-15);
  font-weight: var(--weight-bold);
  line-height: var(--lh-20);
  letter-spacing: var(--track-nav);
  color: var(--text-nav);
  text-decoration: none;
  padding-bottom: var(--sp-4);
  border-bottom: 2px solid transparent;
  opacity: 0.8;
  transition: opacity var(--duration-base) var(--ease-standard);
}

.nav__link:hover {
  color: var(--text-nav);
  text-decoration: none;
  opacity: 1;
}

.nav__link._active {
  font-weight: var(--weight-extrabold);
  border-bottom-color: var(--xanth-red);
  opacity: 1;
}

/*------ 4. MOBILE MENU ------*/
/* not in the handoff — added for the responsive pass, same tokens */
.mobile-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--sp-44);
  height: var(--sp-44);
  color: var(--text-nav);
}

.mobile-toggle svg {
  width: var(--sp-26);
  height: var(--sp-26);
}

.mobile-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-dropdown);
  background: var(--scrim-modal);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--duration-base) var(--ease-standard),
    visibility var(--duration-base);
}

.mobile-overlay._active {
  opacity: 1;
  visibility: visible;
}

.mobile-menu {
  position: fixed;
  top: 0;
  right: 0;
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  gap: var(--sp-30);
  width: min(320px, 85vw);
  height: 100vh;
  padding: var(--sp-30) var(--sp-40);
  background: var(--surface-card);
  box-shadow: var(--shadow-popup);
  transform: translateX(100%);
  transition: transform var(--duration-slow) var(--ease-standard);
  overflow-y: auto;
}

.mobile-menu._active {
  transform: translateX(0);
}

.mobile-menu__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.mobile-menu__top img {
  width: var(--logo-header-w);
  height: var(--logo-header-h);
  object-fit: contain;
}

.mobile-menu__close {
  display: flex;
  color: var(--text-nav);
}

.mobile-menu__close svg {
  width: var(--sp-20);
  height: var(--sp-20);
}

.mobile-menu__nav {
  display: flex;
  flex-direction: column;
  gap: var(--sp-20);
}

.mobile-menu__nav .nav__link {
  display: inline-block;
  align-self: flex-start;
  font-size: var(--size-18);
}

/*------ 5. FOOTER ------*/
.footer {
  position: relative;
  z-index: var(--z-content);
  background: var(--surface-page);
  border-top: 1px solid var(--brand-primary);
  padding: var(--footer-pd-y) 0;
  /* the bottom wedge is sized to hide this much of itself behind the footer
       (§ 2), so the footer has to be at least that tall — otherwise the wedge
       would surface above it */
  min-height: var(--footer-h);
}

.footer__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.footer__logo img {
  width: var(--logo-footer);
  height: var(--logo-footer);
  object-fit: contain;
}

.footer__links {
  display: flex;
  gap: var(--sp-26);
}

.footer__links a {
  font-family: var(--font-sans);
  font-size: var(--size-16);
  font-weight: var(--weight-medium);
  line-height: var(--lh-1);
  color: var(--text-nav);
}

/*------ 6. TYPOGRAPHY BLOCKS ------*/
/* Αρχική's opening section, capped short of the column so the top wedge has
   room to read. Left-aligned — it keeps the same left edge as the full-width
   sections below it, and gives up only the space on the wedge's side. The
   wedge is sized from its height too (§ 2), so min-height holds the room open
   even if the copy is later cut short. */
.lead-block {
  max-width: var(--w-lead);
  min-height: var(--h-lead-min);
}

/* h2 — section heading, 42px */
.section-title {
  font-family: var(--font-sans);
  font-size: var(--size-42);
  font-weight: var(--weight-extrabold);
  line-height: var(--lh-60);
  letter-spacing: var(--track-snug);
  color: var(--brand-primary);
}

/* h2 — group heading, 34px */
.group-title {
  font-family: var(--font-sans);
  font-size: var(--size-34);
  font-weight: var(--weight-extrabold);
  line-height: var(--lh-44);
  letter-spacing: var(--track-snug);
  color: var(--brand-primary);
}

/* lead paragraph, 20px */
.lead {
  font-family: var(--font-sans);
  font-size: var(--size-20);
  font-weight: var(--weight-regular);
  line-height: var(--lh-34);
  color: var(--text-body);
  text-wrap: pretty;
}

/* body paragraph, 18px */
.prose {
  font-family: var(--font-sans);
  font-size: var(--size-18);
  font-weight: var(--weight-regular);
  line-height: var(--lh-30);
  color: var(--text-body);
  text-wrap: pretty;
}

.prose--invert {
  color: var(--text-inverse);
}

.prose--justify {
  text-align: justify;
}

/* inline person-name highlight */
.name-hl {
  font-weight: var(--weight-bold);
  color: var(--brand-primary);
}

/*------ 7. PAGE TITLE LOZENGE ------*/
.page-title {
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-4);
  margin-bottom: var(--sp-46);
}

.page-title h1 {
  font-family: var(--font-sans);
  font-size: var(--size-34);
  font-weight: var(--weight-regular);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-wide);
  color: var(--text-muted);
}

.page-title__brush {
  width: 100%;
  height: var(--brush-h);
  background: url("../images/brush-underline.png") center / 100% 100% no-repeat;
}

/* Λήμματα uses a fixed-width brush */
.page-title--fixed-brush {
  align-items: flex-start;
  gap: var(--sp-6);
}

.page-title--fixed-brush .page-title__brush {
  width: var(--brush-w-lemmata);
  background-size: contain;
}

/*------ 8. SPLIT SECTION ------*/
.split {
  display: flex;
  gap: var(--panel-column-gap);
  align-items: flex-start;
}

.split--reverse {
  flex-direction: row-reverse;
}

.split__media {
  position: relative;
  flex: 0 0 var(--w-split-media);
}

.split__media img {
  width: 100%;
  height: var(--split-img-h);
  object-fit: cover;
  border-radius: var(--radius-md);
  box-shadow: 0 15px 35px 0 rgba(153, 168, 202, 0.35);
}

.split__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-20);
  padding-top: var(--sp-6);
}

/*------ 9. PROSE PANEL (two-column) ------*/
.prose-panel {
  background: var(--surface-panel);
  border-radius: var(--radius-xl);
  padding: var(--panel-pd);
  column-count: 2;
  column-gap: var(--panel-column-gap);
  column-rule: 1px solid var(--border-column-rule);
}

.prose-panel p {
  break-inside: avoid;
}

.prose-panel p + p {
  margin-top: var(--sp-20);
}

/*------ 10. DARK CARD ------*/
.card-row {
  display: flex;
  gap: var(--sp-40);
  align-items: center;
  justify-content: center;
}

.card-row--home {
  padding-top: var(--sp-14);
  align-items: flex-start;
}

.card {
  position: relative;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-16);
  padding: var(--card-pd);
  background: var(--surface-card-dark);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* the YMCA triangle watermark */
.card__watermark {
  position: absolute;
  right: var(--card-watermark-right);
  bottom: var(--card-watermark-bottom);
  width: var(--card-watermark);
  height: var(--card-watermark);
  opacity: var(--watermark-opacity);
  pointer-events: none;
}

.card__title {
  position: relative;
  font-family: var(--font-sans);
  font-size: var(--size-34);
  font-weight: var(--weight-extrabold);
  line-height: var(--lh-44);
  letter-spacing: var(--track-snug);
  color: var(--text-inverse);
}

.card__body {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-16);
}

/*------ 11. LINK LIST (dark card variant) ------*/
.card--links {
  gap: var(--sp-20);
  width: 100%;
  /* caps at the rendered width of the .photo-pair images elsewhere on the
     page, so the two-column link list stays visually consistent with them */
  max-width: calc(var(--photo-pair-w) * 2 + var(--sp-40));
  margin-inline: auto;
}

.card--links .card__title {
  margin-bottom: var(--sp-10);
  font-size: var(--size-26);
  line-height: var(--lh-34);
}

.link-list {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: var(--sp-40);
  row-gap: var(--sp-9);
  padding-left: var(--sp-16);
  list-style: none;
}

.link-list li {
  display: flex;
  gap: var(--sp-12);
  align-items: baseline;
}

.link-list__bullet {
  width: 0;
  height: 0;
  flex-shrink: 0;
  border-left: calc(var(--bullet-w) / 2) solid transparent;
  border-right: calc(var(--bullet-w) / 2) solid transparent;
  border-top: var(--bullet-h) solid var(--red-600);
  transform: translateY(-2px);
}

.link-list a,
.link-list p {
  font-family: var(--font-sans);
  font-size: var(--size-17);
  font-weight: var(--weight-regular);
  line-height: var(--lh-24);
  color: var(--text-inverse);
  text-decoration: none;
}

.link-list a:hover {
  color: var(--text-inverse);
  text-decoration: underline;
}

/*------ 12. PHOTO PAIR ------*/
.photo-pair {
  display: flex;
  gap: var(--sp-40);
  justify-content: center;
  margin-top: 20px;
  margin-bottom: 30px;
}

/* Drupal's text format wraps the buttons in a <p>; drop that box so the
   buttons stay direct flex items of .photo-pair */
.photo-pair > p,
.photo-pair > div {
  display: contents;
}

.photo-pair img {
  width: var(--photo-pair-w);
  height: var(--photo-pair-h);
  object-fit: cover;
  border-radius: var(--radius-md);
}

/*------ 13. VIDEO GRID ------*/
.video-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-44) var(--sp-40);
}

.video-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-14);
  padding: 0;
  text-align: left;
  background: none;
}

.video-card__thumb {
  position: relative;
  display: block;
  height: var(--thumb-h);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-muted);
}

/* dedicated class, not `.video-card__thumb > img` — the corner mark is
   also a direct img child and would inherit the 100%/100% sizing */
.video-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(var(--thumb-brightness));
  transition: filter var(--duration-base) var(--ease-standard);
}

/* corner flag with the ΧΑΝΘ mark */
.video-card__flag {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--corner-flag-w);
  height: var(--corner-flag-h);
  background: var(--surface-card-dark);
  opacity: 0.9;
  clip-path: polygon(0 0, 100% 0, 0 100%);
}

.video-card__mark {
  position: absolute;
  left: var(--sp-10);
  top: var(--sp-8);
  width: var(--logo-mark-w);
  height: var(--logo-mark-h);
  object-fit: contain;
}

.play-badge {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: var(--play-badge);
  height: var(--play-badge);
  border-radius: var(--radius-round);
  background: var(--red-600);
  box-shadow: var(--shadow-badge);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform var(--duration-base) var(--ease-standard);
}

.play-badge::after {
  content: "";
  width: 0;
  height: 0;
  margin-left: var(--sp-6);
  border-top: 15px solid transparent;
  border-bottom: 15px solid transparent;
  border-left: var(--play-badge-arrow) solid var(--white);
}

/* hover states — flagged in the handoff as needing sign-off */
.video-card:hover .video-card__img {
  filter: brightness(0.9);
}

.video-card:hover .play-badge {
  transform: translate(-50%, -50%) scale(1.06);
}

.video-card__duration {
  position: absolute;
  right: var(--sp-12);
  bottom: var(--sp-12);
  padding: var(--sp-6) var(--sp-9);
  background: var(--scrim-pill);
  color: var(--text-inverse);
  font-family: var(--font-sans);
  font-size: var(--size-14);
  font-weight: var(--weight-medium);
  line-height: var(--lh-1);
  border-radius: var(--radius-xs);
}

.video-card__caption {
  font-family: var(--font-sans);
  font-size: var(--size-18);
  font-weight: var(--weight-medium);
  line-height: var(--lh-26);
  letter-spacing: var(--track-snug);
  color: var(--text-body);
}

/*------ 14. PLAYER MODAL ------*/
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--scrim-modal);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--duration-base) var(--ease-standard),
    visibility var(--duration-base);
}

.modal._active {
  opacity: 1;
  visibility: visible;
}

.modal__dialog {
  position: relative;
  width: min(var(--w-modal), 100% - (2 * var(--sp-16)));
  background: var(--surface-dark);
  border-radius: var(--radius-md);
  overflow: hidden;
}

/* pinned to the scrim rather than to the dialog: over the stage it sat in the
   same corner as YouTube's own controls, so it read as one of theirs. Like
   .lightbox__close it carries a disc, since the scrim shows the page through */
.modal__close {
  position: absolute;
  right: var(--sp-16);
  top: var(--sp-16);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--close-disc);
  height: var(--close-disc);
  border-radius: var(--radius-round);
  background: var(--scrim-pill);
  color: var(--text-inverse);
}

.modal__close svg {
  width: var(--sp-14);
  height: var(--sp-14);
}

/* 980 × 552 is already 16:9, so the embed fills the stage exactly */
.modal__stage {
  position: relative;
  height: var(--modal-stage-h);
  background: var(--black);
}

.modal__player iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.modal__caption {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-20);
  padding: var(--sp-20) var(--sp-26);
}

.modal__title {
  font-family: var(--font-sans);
  font-size: var(--size-20);
  font-weight: var(--weight-medium);
  line-height: var(--lh-28);
  color: var(--text-inverse);
}

.modal__duration {
  flex-shrink: 0;
  font-family: var(--font-sans);
  font-size: var(--size-16);
  font-weight: var(--weight-regular);
  line-height: var(--lh-1);
  color: var(--text-on-dark-faded);
}

/*------ 15. LEGAL ------*/
.legal {
  display: flex;
  flex-direction: column;
  gap: var(--sp-18);
}

.legal h2 {
  padding-top: var(--sp-22);
  font-family: var(--font-sans);
  font-size: var(--size-26);
  font-weight: var(--weight-extrabold);
  line-height: var(--lh-34);
  letter-spacing: var(--track-snug);
  color: var(--brand-primary);
}

.legal > h2:first-child {
  padding-top: 0;
}

.legal p {
  font-family: var(--font-sans);
  font-size: var(--size-17);
  font-weight: var(--weight-regular);
  line-height: var(--lh-29);
  color: var(--text-body);
  text-wrap: pretty;
}

/*------ 16. LIGHTBOX ------*/
/* The photos on the page are cropped to fit their slot (object-fit: cover), so
   there is always more picture than the layout shows. The zoom button is what
   gives it back: it wraps the image in place, changes no box of its own, and
   opens the whole frame over a scrim.

   A button rather than a click handler on the image, so it is reachable by
   keyboard and announced as an action — the same choice .video-card makes. */
.zoom {
  display: block;
  width: 100%;
  padding: 0;
  cursor: zoom-in;
}

.zoom img {
  transition: opacity var(--duration-fast) var(--ease-standard);
}

.zoom:hover img,
.zoom:focus-visible img {
  opacity: var(--zoom-hover-opacity);
}

/* the lightbox returns focus here on close, which would otherwise trip the
   global :focus-visible ring in styles.css § 3 right at the image edge */
.zoom:focus-visible {
  outline: none;
}

/* the pair's images size themselves, so the buttons must not stretch */
.photo-pair .zoom {
  width: auto;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--lightbox-pd);
  background: var(--scrim-modal);
  opacity: 0;
  visibility: hidden;
  transition:
    opacity var(--duration-base) var(--ease-standard),
    visibility var(--duration-base);
}

.lightbox._active {
  opacity: 1;
  visibility: visible;
}

.lightbox__dialog {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-16);
  max-width: min(var(--w-lightbox), 100%);
}

/* The point of the whole component: the frame uncropped, as large as it can be
   shown. Four ceilings, whichever comes first —

     the viewport's width, its height (via the aspect ratio, which is why the
     height cap is expressed as a width), the --w-lightbox ceiling, and
     --zoom-max-scale × the photo's own pixels.

   That last one is what stops an enlargement from being a blur-up, and it is
   also why this is not simply `max-width: 100%`: two of the site's photos are
   smaller than the slot they are shown in, so a lightbox that refused to
   upscale at all would open them *smaller* than the page does.

   --nw / --nh are the natural pixel size, handed over by the script — the only
   two numbers CSS cannot know on its own. The arithmetic stays here. */
.lightbox__img {
  width: min(
    calc(100vw - 2 * var(--lightbox-pd)),
    var(--w-lightbox),
    calc(var(--nw, 1) * var(--zoom-max-scale) * 1px),
    calc(var(--lightbox-img-h) * var(--nw, 1) / var(--nh, 1))
  );
  height: auto;
  max-height: var(--lightbox-img-h);
  border-radius: var(--radius-md);
  cursor: zoom-out;
}

/* the modal's faded grey is for a second line beside a title; here the caption
   is the only text over the scrim, so it takes the readable one */
.lightbox__caption {
  font-family: var(--font-sans);
  font-size: var(--size-17);
  font-weight: var(--weight-regular);
  line-height: var(--lh-24);
  color: var(--text-on-dark-muted);
  text-align: center;
  text-wrap: pretty;
}

/* same disc as .modal__close, but anchored to the photo rather than to the
   scrim: nothing of the site's own sits in that corner to be confused with */
.lightbox__close {
  position: absolute;
  top: var(--sp-12);
  right: var(--sp-12);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--close-disc);
  height: var(--close-disc);
  border-radius: var(--radius-round);
  background: var(--scrim-pill);
  color: var(--text-inverse);
}

.lightbox__close svg {
  width: var(--sp-14);
  height: var(--sp-14);
}