/* Content styles: everything that styles the *contents* of a page — headings,
   body copy, the photo grid, the chrome frames and the lightbox.
   Kept separate from site.css because the homepage renders this same markup
   inside its panels, and loading site.css there would drag in the standalone
   page chrome with it: a body padding and a fixed background image that would
   shove the 3D scene off-centre and paint over the video. */

h1 {
  font-family: 'Ledlight';
  font-size: 42px;
  letter-spacing: 4px;
  text-transform: uppercase;
  color: #d3d3ff;
  text-shadow: 0 0 6px rgba(0, 85, 255, 0.639), 0 0 15px rgba(255, 44, 192, 0.595);
  margin-bottom: 30px;
}
p {
  line-height: 1.7;
  margin-bottom: 20px;
  font-size: 16px;
}
p strong {
  color: #ff42e6;
}
a {
  cursor: url('mouse-finger2-cursor.png') 9 1, pointer;
}
a:hover {
  color: #ff427b;
}
.about-photo {
  max-width: 320px;
  width: 100%;
  display: block;
  margin: 0 auto 30px;
  border-radius: 4px;
  box-shadow: 0 0 20px rgba(100, 100, 255, 0.3);
}


.photo-frame,
.lightbox-overlay {
  cursor: url('mouse-finger2-cursor.png') 9 1, pointer;
}

/* --- Gallery: Pinterest-style masonry --------------------------------------
   Images keep their own aspect ratio and are only scaled down to the column
   width. CSS multi-column does the packing (no JS layout pass) — items flow
   down each column in turn, so column heights stay close to even. */
:root {
  --frame-pad: 5px;         /* chrome thickness */
  --frame-radius: 10px;
  --frame-gap: 16px;
  --frame-hover-turn: 6deg;  /* lightbox.js reads this to match the flight */
  --frame-glow: rgba(120, 96, 255, 0.38);
  --frame-glow-hot: rgba(150, 110, 255, 0.6);
}

.photo-grid {
  /* A grid, not multi-column. Multi-column fills each column top to bottom and
     balances them by height, which is what grouped photos by size and threw
     away the order they appear in the HTML. Track width drives the count; the
     1600px cap keeps it to 5 columns, and narrow windows fall to 2. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  align-items: start;       /* each photo keeps its own height */
  gap: var(--frame-gap);
  max-width: 1600px;        /* 5 x 280px columns + gaps */
  margin: 0 auto;
}

/* lightbox.js measures each photo and spans it across this fine row unit, which
   is what packs the columns. Until that runs — or with JS off — the grid above
   still lays the photos out in order, just with even rows. */
.photo-grid.is-masonry {
  grid-auto-rows: 2px;
  row-gap: 0;               /* the frames carry the vertical gap instead */
}
.photo-grid.is-masonry .photo-frame {
  margin-bottom: var(--frame-gap);
}

/* Gallery pages need the full width; text pages stay at a readable measure. */
main:has(> .photo-grid) {
  max-width: 1600px;
}
/* Each image is wrapped in .photo-frame by lightbox.js. Bare <img> children
   are styled too so the gallery still reads correctly without JS. */
.photo-frame,
.photo-grid > img {
  display: block;
  width: 100%;
  margin: 0;
}

/* --- Pseudo-3D chrome frame --- */
.photo-frame {
  position: relative;
  padding: var(--frame-pad);
  border-radius: var(--frame-radius);
  /* Banded light/dark gradient = the classic faked chrome horizon reflection. */
  background: linear-gradient(
    157deg,
    #eef0f8 0%,
    #b9bed8 9%,
    #7d84a2 21%,
    #c8cde5 33%,
    #f2f4ff 43%,
    #868ca9 53%,
    #454b64 65%,
    #a1a7c3 77%,
    #dde1f2 89%,
    #8f95b4 100%
  );
  /* Concentric rings cut a light-dark-light bevel across the thickness —
     what actually sells thin chrome. Kept semi-transparent so the directional
     gradient above still reads through them. */
  box-shadow:
    inset 0 0 0 1px rgba(238, 240, 250, 0.8),
    inset 0 0 0 2px rgba(128, 134, 164, 0.6),
    inset 0 0 0 3px rgba(50, 55, 76, 0.6),
    inset 0 0 0 4px rgba(178, 184, 210, 0.5),
    inset 0 1px 0 rgba(232, 235, 248, 0.85),
    0 3px 8px rgba(0, 0, 0, 0.5),
    0 0 22px var(--frame-glow);
  transform: perspective(700px) rotateY(0deg);
  transition: transform 0.35s ease, box-shadow 0.3s ease;
}

/* Hairline separating chrome from photo — no inner shadow, just the edge. */
.photo-frame::after {
  content: '';
  position: absolute;
  inset: var(--frame-pad);
  border-radius: calc(var(--frame-radius) - var(--frame-pad) + 1px);
  pointer-events: none;
  box-shadow: 0 0 0 1px rgba(18, 14, 38, 0.55);
}

.photo-frame img,
.photo-grid > img {
  display: block;
  width: 100%;
  height: auto;              /* original aspect ratio, just scaled down */
  border-radius: calc(var(--frame-radius) - var(--frame-pad) + 1px);
}

.photo-frame:hover {
  /* Subtle turn on the Y axis, as if the photo pivots toward you. */
  transform: perspective(700px) rotateY(var(--frame-hover-turn));
  box-shadow:
    inset 0 0 0 1px rgba(246, 248, 255, 0.95),
    inset 0 0 0 2px rgba(128, 134, 164, 0.6),
    inset 0 0 0 3px rgba(50, 55, 76, 0.6),
    inset 0 0 0 4px rgba(178, 184, 210, 0.5),
    inset 0 1px 0 rgba(246, 248, 255, 1),
    0 6px 14px rgba(0, 0, 0, 0.55),
    0 0 30px var(--frame-glow-hot);
}

/* The frame a lifted photo came from: keeps its slot in the column while the
   levitating copy is in flight. */
.photo-frame.is-lifted {
  visibility: hidden;
}
/* --- Lightbox (click a photo to levitate it off the wall) --- */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  background: rgba(8, 5, 22, 0.4);
  backdrop-filter: blur(8px) saturate(0.9);
  -webkit-backdrop-filter: blur(8px) saturate(0.9);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s ease, visibility 0.28s;
  z-index: 1000;
}
.lightbox-overlay.open {
  opacity: 1;
  visibility: visible;
}

/* Flight layer sits above the blur so the lifted photo stays sharp and never
   fades — it only moves. */
.lightbox-stage {
  position: fixed;
  inset: 0;
  z-index: 1001;
  pointer-events: none;
}

.lightbox-flight {
  position: absolute;
  transform-origin: top left;   /* FLIP: translate + scale from the thumbnail */
  will-change: transform;
}
.lightbox-flight .photo-frame {
  margin: 0;
  transition: none;
  will-change: transform;
  box-shadow:
    inset 0 0 0 1px rgba(246, 248, 255, 0.95),
    inset 0 0 0 2px rgba(128, 134, 164, 0.6),
    inset 0 0 0 3px rgba(50, 55, 76, 0.6),
    inset 0 0 0 4px rgba(178, 184, 210, 0.5),
    inset 0 1px 0 rgba(246, 248, 255, 1),
    0 18px 45px rgba(0, 0, 0, 0.6),
    0 0 45px var(--frame-glow-hot);
}


@media (max-width: 768px) {
  :root {
    --frame-pad: 3px;
    --frame-radius: 8px;
    --frame-gap: 8px;
  }
  .photo-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* --- Dark chrome box -------------------------------------------------------
   The same pseudo-3D treatment as the photo frames — banded metal, a bevelled
   lip and the soft purple glow — but struck in deep blue-black so body copy
   stays legible on it. The sheen is layered over a near-solid base rather than
   being the background itself: a full-contrast gradient behind a paragraph
   makes the text swim. Used for the about/contact copy and for the header
   strip that sits above every gallery. */
.text-panel,
.section-header {
  position: relative;       /* the close bubble anchors to this corner */
  padding: 36px 40px 36px 52px;
  border-radius: 14px;
  background:
    linear-gradient(
      157deg,
      rgba(104, 124, 190, 0.30) 0%,
      rgba(28, 36, 62, 0.14) 12%,
      rgba(0, 0, 0, 0) 26%,
      rgba(76, 94, 150, 0.16) 40%,
      rgba(120, 140, 200, 0.20) 46%,
      rgba(0, 0, 0, 0) 58%,
      rgba(58, 72, 118, 0.12) 78%,
      rgba(112, 132, 194, 0.24) 100%
    ),
    #080b16;
  /* Same ring stack as .photo-frame, darkened: a dim blue lip, then black,
     then a faint inner highlight. */
  box-shadow:
    inset 0 0 0 1px rgba(126, 146, 205, 0.5),
    inset 0 0 0 2px rgba(38, 48, 78, 0.7),
    inset 0 0 0 3px rgba(6, 9, 18, 0.85),
    inset 0 0 0 4px rgba(74, 88, 132, 0.32),
    inset 0 1px 0 rgba(150, 168, 220, 0.45),
    0 6px 20px rgba(0, 0, 0, 0.6),
    0 0 26px var(--frame-glow);
}

.text-panel {
  max-width: 900px;
  margin: 0 auto;
}

/* Last paragraph should not push a gap against the bevel. */
.text-panel > :last-child {
  margin-bottom: 0;
}

/* --- Section header --------------------------------------------------------
   Title strip above a gallery. The description sits to the RIGHT of the title
   rather than under it, so the header costs one band of vertical space no
   matter how much copy it carries and the photos keep the rest of the page. */
.section-header {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 18px 24px 18px 52px;
  margin-bottom: 24px;
}
.section-header h1 {
  margin: 0;
  flex: none;
}
.section-desc {
  flex: 1;
  margin: 0;
  padding-left: 24px;
  border-left: 1px solid rgba(120, 140, 200, 0.22);
  font-size: 15px;
  line-height: 1.6;
  color: #b6b6d6;
}


/* --- Close bubble ---------------------------------------------------------
   Pinned to the top-left corner of whatever box it sits in, the way a window
   control is. Built from stacked radial gradients rather than the flat banded
   metal used elsewhere: a specular highlight up top, bounce light from below
   and a dark rim, which is what reads as a glossy sphere instead of a disc. */
.close-x {
  position: absolute;
  top: -7px;
  left: -7px;
  z-index: 3;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background:
    /* tight specular hotspot */
    radial-gradient(circle at 33% 25%,
      rgba(255, 255, 255, 1) 0%,
      rgba(255, 255, 255, 0.55) 7%,
      rgba(255, 255, 255, 0) 27%),
    /* light refracting round the lower edge — the tell for glass, not rubber */
    radial-gradient(circle at 50% 126%,
      rgba(255, 226, 242, 0.85) 0%,
      rgba(255, 150, 200, 0.28) 38%,
      rgba(255, 150, 200, 0) 60%),
    /* body, lit from the upper left and falling away to deep magenta */
    radial-gradient(circle at 38% 31%,
      #ff74f6 0%,
      #fb64a0 30%,
      #f735a7 56%,
      #ff00bb 79%,
      #720b5c 100%);
  /* Everything past the first three rings is the housing: a dark seat, then a
     bright chrome lip, a shadowed flank and a final dark edge — the same
     light-dark-light banding the photo frames use, wrapped into a circle so the
     bubble reads as seated in the panel rather than resting on top of it. */
  box-shadow:
    inset 0 0 0 1px rgba(255, 196, 226, 0.45),   /* bright rim */
    inset 0 3px 6px rgba(255, 224, 240, 0.3),
    inset 0 -6px 11px rgba(112, 6, 48, 0.55),    /* shaded underside */
    0 0 0 1px rgba(18, 14, 30, 0.9),             /* seat */
    0 0 0 3px rgba(206, 212, 236, 0.9),          /* chrome lip */
    0 0 0 4px rgba(120, 128, 158, 0.95),
    0 0 0 6px rgba(58, 64, 88, 0.95),            /* flank */
    0 0 0 7px rgba(198, 205, 232, 0.55),
    0 0 0 8px rgba(16, 19, 32, 0.9),             /* outer edge */
    0 3px 9px rgba(0, 0, 0, 0.6),
    0 0 18px rgba(255, 95, 160, 0.4);
  cursor: url('mouse-finger2-cursor.png') 9 1, pointer;
  transition: box-shadow 0.22s ease, transform 0.22s ease, filter 0.22s ease;
}

/* A thin, lit cross rather than a heavy glyph — it should read as something
   suspended inside the bubble. */
.close-x::before,
.close-x::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 11px;
  height: 1.5px;
  margin: -0.75px 0 0 -5.5px;
  border-radius: 1px;
  /* Solid, not translucent: the two bars overlap, and any transparency makes
     the crossing point composite twice and show as a brighter diamond. */
  background: #fff;
}
.close-x::before { transform: rotate(45deg); }
.close-x::after  { transform: rotate(-45deg); }

.close-x:hover {
  filter: brightness(1.16) saturate(1.1);
  box-shadow:
    inset 0 0 0 1px rgba(255, 214, 235, 0.7),
    inset 0 3px 7px rgba(255, 232, 244, 0.4),
    inset 0 -6px 12px rgba(122, 8, 52, 0.5),
    0 0 0 1px rgba(18, 14, 30, 0.9),
    0 0 0 3px rgba(226, 232, 252, 0.95),
    0 0 0 4px rgba(132, 140, 172, 0.95),
    0 0 0 6px rgba(64, 70, 96, 0.95),
    0 0 0 7px rgba(214, 221, 244, 0.6),
    0 0 0 8px rgba(16, 19, 32, 0.9),
    0 3px 11px rgba(0, 0, 0, 0.6),
    0 0 30px rgba(255, 105, 170, 0.85);
}

/* The lightbox's own close button, pinned to the top-left of the screen so it
   matches where the section headers put theirs. */
/* The lifted photo carries its own control, seated in the frame corner the
   same way. The stage ignores pointer events so the backdrop stays clickable;
   this one control has to opt back in. */
.lightbox-flight .close-x {
  pointer-events: auto;
}

/* Step arrows. Kept quiet so they do not compete with the photo — they lift to
   full strength on hover. */
.lightbox-nav {
  position: fixed;
  top: 50%;
  z-index: 1;
  width: 46px;
  height: 46px;
  margin-top: -23px;
  padding: 0;
  border: 0;
  background: none;
  opacity: 0.4;
  cursor: url('mouse-finger2-cursor.png') 9 1, pointer;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.lightbox-nav::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 15px;
  height: 15px;
  border-left: 2px solid rgba(228, 232, 255, 0.95);
  border-bottom: 2px solid rgba(228, 232, 255, 0.95);
  border-radius: 2px;
  filter: drop-shadow(0 0 5px rgba(0, 0, 0, 0.75));
}
.lightbox-nav.prev { left: 20px; }
.lightbox-nav.next { right: 20px; }
.lightbox-nav.prev::before { transform: translate(-35%, -50%) rotate(45deg); }
.lightbox-nav.next::before { transform: translate(-65%, -50%) rotate(-135deg); }

.lightbox-nav:hover {
  opacity: 1;
}
.lightbox-nav.prev:hover { transform: translateX(-3px); }
.lightbox-nav.next:hover { transform: translateX(3px); }
.lightbox-nav::before { transition: border-color 0.2s ease; }
.lightbox-nav:hover::before {
  border-color: #cdd6ff;
  filter: drop-shadow(0 0 6px rgba(140, 160, 255, 0.8));
}
