:root {
  --accent: #4e02ff;
}

.figma-stage img {
  pointer-events: none;
}

/* ---- Home link (top-left) ---- */
.fx-home-hit {
  display: block;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-home-hit > * {
  position: absolute;
}

.fx-home-label {
  font-size: 21.951px;
  letter-spacing: 1.7561px;
  transition: color 180ms ease;
}

.fx-home-hit:hover .fx-home-label,
.fx-home-hit:focus-visible .fx-home-label {
  color: var(--accent);
}

.fx-home-hit:hover img,
.fx-home-hit:focus-visible img {
  transform: translateY(-4px);
  transition: transform 180ms ease;
}

/* ---- Top tab bar ---- */
.fx-welcome {
  font-size: 30px;
  letter-spacing: 2.4px;
}

.fx-tab-group {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.fx-tab-group > * {
  position: absolute;
}

.fx-tab-hit {
  display: block;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  pointer-events: auto;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-tab-icon {
  width: 100%;
  height: 100%;
  display: block;
  transition: transform 180ms ease;
}

.fx-tab-group[data-active-tab="photos"] [data-tab="photos"] .fx-tab-icon,
.fx-tab-group[data-active-tab="film"] [data-tab="film"] .fx-tab-icon,
.fx-tab-group[data-active-tab="design"] [data-tab="design"] .fx-tab-icon,
.fx-tab-group[data-active-tab="development"] [data-tab="development"] .fx-tab-icon,
.fx-tab-group[data-active-tab="contact"] [data-tab="contact"] .fx-tab-icon {
  transform: translateY(-4px) scale(1.08);
}

.fx-tab-label {
  position: absolute;
  left: 50%;
  top: calc(100% + 14px);
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: "Griun Simsimche", cursive;
  font-size: 21.951px;
  letter-spacing: 1.7561px;
  opacity: 0;
  transition: opacity 160ms ease;
  pointer-events: none;
  z-index: 1;
}

.fx-tab-group[data-active-tab="photos"] [data-label="photos"],
.fx-tab-group[data-active-tab="film"] [data-label="film"],
.fx-tab-group[data-active-tab="design"] [data-label="design"],
.fx-tab-group[data-active-tab="development"] [data-label="development"],
.fx-tab-group[data-active-tab="contact"] [data-label="contact"] {
  opacity: 1;
}

/* ---- Photo grid ---- */
.fx-photo-grid {
  position: absolute;
  left: 0;
  top: 339px;
  width: 2560px;
  /* Tall enough that a caption wrapping onto a second (or even third) line
     never needs to be clipped -- this used to be 860px, which left only
     68px below the caption's own top offset (792px), cropping line 2 of
     anything long enough to wrap. Can't fix that with overflow-y: visible
     instead: mixing 'visible' on one axis with a non-visible value on the
     other is invalid per the CSS overflow spec, and gets computed as
     'auto' instead -- which is exactly what was drawing the scrollbar. */
  height: 920px;
  overflow: hidden;
}

.fx-photo-track {
  display: flex;
  height: 100%;
  transition: transform 620ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

.fx-photo-page {
  position: relative;
  flex: 0 0 2560px;
  height: 100%;
}

.fx-photo-slot {
  position: absolute;
  top: 0;
  display: block;
  width: 547px;
  height: 920px;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  text-align: center;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-photo-frame {
  position: absolute;
  left: 0;
  top: 0;
  width: 547px;
  height: 762px;
  display: block;
  z-index: 2;
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1), filter 260ms ease;
  /* Match the mask's own layer promotion below (translateZ(0)) so both are
     composited together ahead of time. Without this, Safari/iPadOS could
     paint the mask's layer a frame or two before the frame's, so during the
     pager's translateX transition the raw (unframed) photo flashed on top
     before the frame layer caught up and visually "covered" it again. */
  transform: translateZ(0);
  will-change: transform;
}

.fx-photo-mask {
  position: absolute;
  width: 506.875px;
  height: 760.22px;
  z-index: 1;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-mode: alpha;
  mask-size: 506.443px 695.153px;
  -webkit-mask-size: 506.443px 695.153px;
  mask-position: 0px 27.734px;
  -webkit-mask-position: 0px 27.734px;
  /* These masks are large hand-drawn SVGs — pin each to its own
     compositor layer so paging the track doesn't re-rasterize them. */
  transform: translateZ(0);
  will-change: transform;
}

.fx-photo-mask img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.fx-photo-caption {
  position: absolute;
  top: 792px;
  left: 0;
  width: 547px;
  margin: 0;
  color: #242424;
  font-family: "Griun Simsimche", cursive;
  font-size: 30px;
  letter-spacing: 2.4px;
  text-align: center;
  transition: color 180ms ease;
}

.fx-photo-slot:hover .fx-photo-frame,
.fx-photo-slot:focus-visible .fx-photo-frame {
  transform: translateY(-6px);
  filter: drop-shadow(0 8px 10px rgba(0, 0, 0, 0.16));
}

.fx-photo-slot:hover .fx-photo-caption,
.fx-photo-slot:focus-visible .fx-photo-caption {
  color: var(--accent);
}

/* ---- Pagination arrows ---- */
.fx-pager-group {
  display: flex;
  align-items: center;
  gap: 56px;
  transform: translateX(-50%);
}

.fx-pager {
  display: block;
  width: 161px;
  height: 62px;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
  transition: transform 180ms ease;
}

.fx-pager:hover,
.fx-pager:focus-visible {
  transform: scale(1.06);
}

.fx-pager img {
  width: 100%;
  height: 100%;
  display: block;
}

/* ---- Lightbox ---- */
.fx-lightbox {
  position: fixed;
  inset: 0;
  z-index: 40;
  opacity: 0;
  visibility: hidden;
  transition: opacity 320ms ease, visibility 0s linear 320ms;
}

.fx-lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 320ms ease, visibility 0s linear 0s;
}

.fx-lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 20, 20, 0.88);
  backdrop-filter: blur(18px) saturate(120%);
  -webkit-backdrop-filter: blur(18px) saturate(120%);
}

/* Deliberately outside the Figma-scaled 2560x1440 canvas system (see
   .fx-site-footer in styles.css for the same rationale) -- the enlarged
   photo needs to fill whatever screen it's actually on rather than sitting
   inside a fixed-aspect box that leaves big unused margins on windows whose
   aspect ratio doesn't match the canvas. Real vw/vh units throughout.

   prev / photo / next sit in one flex row with a fixed `gap` -- so the nav
   arrows always sit a constant distance from the photo's actual edge
   instead of being pinned to the viewport edges (where a narrow portrait
   photo left them stranded far from the picture). The reserved-space
   calc() on the photo below keeps this row from ever overflowing the
   viewport on narrower windows. */
.fx-lightbox-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 32px;
}

/* Shrink-wraps to the actual rendered size of the (contain-fit) image
   inside it, so the caption and close button -- both absolutely positioned
   against this element -- track the photo's real edges rather than a fixed
   box, whether the photo ends up landscape or portrait. max-width reserves
   exactly the nav row's width (120px button + 32px gap, each side) so the
   full prev/photo/next row can never overflow the viewport. */
.fx-lightbox-photo {
  position: relative;
  display: inline-flex;
  margin: 0;
  max-width: calc(100vw - 304px);
  max-height: 88vh;
  opacity: 0;
  transform: scale(0.94) translateY(18px);
  transition: opacity 360ms cubic-bezier(0.22, 1, 0.36, 1), transform 420ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fx-lightbox.is-open .fx-lightbox-photo {
  opacity: 1;
  transform: scale(1) translateY(0);
}

.fx-lightbox-photo img {
  display: block;
  max-width: calc(100vw - 304px);
  max-height: 88vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}

.fx-lightbox-caption {
  position: absolute;
  left: 24px;
  bottom: 20px;
  right: 24px;
  margin: 0;
  color: rgba(255, 255, 255, 0.5);
  font-family: "Griun Simsimche", cursive;
  font-size: 26px;
  letter-spacing: 1.2px;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.7), 0 1px 3px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}

.fx-lightbox-nav {
  flex: 0 0 auto;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  width: 120px;
  height: 48px;
  opacity: 0;
  transition: opacity 320ms ease 120ms, transform 220ms ease;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-lightbox.is-open .fx-lightbox-nav {
  opacity: 1;
}

.fx-lightbox-nav:hover,
.fx-lightbox-nav:focus-visible {
  transform: scale(1.08);
}

.fx-lightbox-nav img {
  width: 100%;
  height: 100%;
  display: block;
}

/* Anchored to the photo's own corner (a child of .fx-lightbox-photo) so it
   moves with the photo at any size instead of sitting fixed in the
   viewport's corner, far from a narrower portrait photo. */
.fx-lightbox-close {
  position: absolute;
  top: -16px;
  right: -16px;
  width: 44px;
  height: 41px;
  border: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  opacity: 0;
  transition: opacity 320ms ease 120ms, transform 220ms ease;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-lightbox.is-open .fx-lightbox-close {
  opacity: 1;
}

.fx-lightbox-close:hover,
.fx-lightbox-close:focus-visible {
  transform: rotate(90deg);
}

.fx-lightbox-close img {
  width: 100%;
  height: 100%;
  display: block;
}

@media (prefers-reduced-motion: reduce) {
  .fx-photo-track,
  .fx-photo-frame,
  .fx-photo-caption,
  .fx-lightbox,
  .fx-lightbox-photo,
  .fx-lightbox-nav,
  .fx-lightbox-close,
  .fx-tab-icon,
  .fx-home-hit img {
    transition: none;
  }
}

/* ---- Mobile: torn-paper polaroid frame on the grid thumbnails ----
   Reuses the exact same slot mask/frame SVG pairs the desktop grid cycles
   through (see SLOT_ASSETS in photos.js) rather than the plain rounded
   square every other .fx-m-grid page (Design 2D/3D/Commission) still uses --
   scoped here via the --framed modifier so those other galleries, which
   share the base .fx-m-grid-thumb class, are unaffected. The desktop
   version pins the mask to fixed pixel offsets inside a fixed-size canvas;
   here the grid cell is fluid-width, so the mask is sized/positioned in
   percentages instead of copying those exact px values. */
.fx-m-grid-thumb--framed {
  position: relative;
  /* Overrides the base .fx-m-grid-thumb square (see mobile.css) with this
     slot's own 547:762 ratio, same percentage-padding technique for the
     same cross-WebView reliability -- 762/547 as a percentage. */
  height: 0;
  padding-top: 139.3053%;
  border-radius: 0;
  background: transparent;
  overflow: visible;
}

.fx-m-grid-thumb--framed .fx-m-photo-mask {
  position: absolute;
  left: 3.7%;
  top: 0;
  width: 92.6%;
  height: 100%;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-mode: alpha;
  /* Stretching the mask artwork to fill this box exactly (100% 100%) made
     the visible photo bigger than the torn-paper silhouette the frame
     overlay was drawn for, so the photo poked past the frame's ink line.
     Desktop's own fixed-px rule (mask-size: 506.443px 695.153px inside a
     506.875x760.22 div, position 0px 27.734px) leaves real breathing room
     the artwork wasn't meant to fill -- these percentages are that same
     ratio (695.153/760.22 and the resulting position offset) so the mask
     lands in the same place proportionally at any thumbnail size. */
  mask-size: 100% 91.4%;
  -webkit-mask-size: 100% 91.4%;
  mask-position: 0% 42.6%;
  -webkit-mask-position: 0% 42.6%;
}

.fx-m-grid-thumb--framed .fx-m-photo-mask img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.fx-m-grid-thumb--framed .fx-m-photo-frame-overlay {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---- Mobile: category filter toggle + chips ----
   Hidden outright on mobile -- with everything already visible in one long
   scroll on a phone, there's no real need to filter by category the way
   there is on desktop's fixed-window slide view (see photos.js's
   renderFilters, which still builds this markup; it's just never shown). */
.fx-m-photo-filters {
  display: none !important;
}

.fx-m-photo-filter-toggle {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
}

.fx-m-photo-filter-icon {
  display: block;
  width: 100%;
  height: 100%;
  background-color: #000;
  mask-image: url("assets/figma/category-icon.svg");
  -webkit-mask-image: url("assets/figma/category-icon.svg");
  mask-size: contain;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-position: center;
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fx-m-photo-filter-toggle[aria-expanded="true"] .fx-m-photo-filter-icon {
  transform: rotate(18deg) scale(1.08);
}

.fx-m-photo-filter-tooltip {
  position: absolute;
  left: 50%;
  top: calc(100% + 8px);
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: "Griun Simsimche", cursive;
  font-size: 12px;
  color: #242424;
  background: #fff;
  padding: 3px 8px;
  border-radius: 999px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
  opacity: 0;
  transition: opacity 160ms ease;
  pointer-events: none;
}

.fx-m-photo-filter-toggle:active .fx-m-photo-filter-tooltip {
  opacity: 1;
}

.fx-m-photo-chip {
  position: absolute;
  left: 0;
  bottom: 0;
  padding: 7px 16px;
  font-family: "Griun Simsimche", cursive;
  font-size: 14px;
  color: #6b6b6b;
  background: #fff;
  border: 2px solid #ddd;
  border-radius: 999px;
  white-space: nowrap;
  cursor: pointer;
  opacity: 0;
  transform: translate(0, 0);
  pointer-events: none;
  transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1), opacity 280ms ease,
    color 160ms ease, background 160ms ease, border-color 160ms ease;
}

.fx-m-photo-chip.is-active {
  color: #fff;
  background: #242424;
  border-color: #242424;
}

/* Hover feedback so it's clear each fanned-out chip is actually clickable
   before you commit to tapping one. */
.fx-m-photo-chip:hover:not(.is-active) {
  color: var(--m-accent, #4e02ff);
  border-color: var(--m-accent, #4e02ff);
  background: color-mix(in srgb, var(--m-accent, #4e02ff) 8%, #fff);
}

/* Each chip fades/rises straight out of the icon, cascading up-and-left one
   at a time (transition-delay staggered by --i) rather than all popping
   together. */
.fx-m-photo-filters.is-open .fx-m-photo-chip {
  opacity: 1;
  transform: translate(calc(var(--i) * -6px), calc((var(--i) + 1) * -46px));
  pointer-events: auto;
  transition-delay: calc(var(--i) * 55ms);
}

/* ---- Desktop: category filter toggle + chips ----
   Bottom-left corner of the canvas, macOS-"Stacks"-style: a plain doodle
   icon with no circle/border, and clicking it fans the category chips
   upward out of the icon instead of unfurling sideways. The container is a
   zero-size anchor point (left/bottom only) -- the toggle and every chip
   are absolutely positioned at that exact same origin, so collapsed they
   all sit invisibly stacked on the icon, and opening just transforms each
   chip to its own offset (see photos.js renderFilters(), which sets each
   chip's --i index). Needs an explicit z-index since the photo grid comes
   after this in the DOM and would otherwise paint over the fanned-out chips. */
.fx-photo-filters {
  position: absolute;
  left: 84px;
  bottom: 150px;
  width: 0;
  height: 0;
  z-index: 5;
}

.fx-photo-filter-toggle {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
}

.fx-photo-filter-icon {
  display: block;
  width: 100%;
  height: 100%;
  background-color: #000;
  mask-image: url("assets/figma/category-icon.svg");
  -webkit-mask-image: url("assets/figma/category-icon.svg");
  mask-size: contain;
  -webkit-mask-size: contain;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
  mask-position: center;
  -webkit-mask-position: center;
  transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.fx-photo-filter-toggle[aria-expanded="true"] .fx-photo-filter-icon {
  transform: rotate(18deg) scale(1.08);
}

.fx-photo-filter-tooltip {
  position: absolute;
  left: 50%;
  top: calc(100% + 10px);
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: "Griun Simsimche", cursive;
  font-size: 16px;
  letter-spacing: 0.5px;
  color: #242424;
  opacity: 0;
  transition: opacity 160ms ease;
  pointer-events: none;
}

.fx-photo-filter-toggle:hover .fx-photo-filter-tooltip,
.fx-photo-filter-toggle:focus-visible .fx-photo-filter-tooltip {
  opacity: 1;
}

.fx-photo-chip {
  position: absolute;
  left: 0;
  bottom: 0;
  padding: 12px 28px;
  font-family: "Griun Simsimche", cursive;
  font-size: 22px;
  color: #6b6b6b;
  background: #fff;
  border: 3px solid #ddd;
  border-radius: 999px;
  white-space: nowrap;
  cursor: url("assets/cursor/cursor-pointer.png") 23 28, pointer;
  opacity: 0;
  transform: translate(0, 0);
  pointer-events: none;
  transition: transform 340ms cubic-bezier(0.22, 1, 0.36, 1), opacity 300ms ease,
    color 160ms ease, background 160ms ease, border-color 160ms ease;
}

.fx-photo-chip.is-active {
  color: #fff;
  background: #242424;
  border-color: #242424;
}

/* Hover feedback so it's clear each fanned-out chip is actually clickable
   before you commit to clicking one. */
.fx-photo-chip:hover:not(.is-active) {
  color: var(--accent);
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, #fff);
}

/* Fanned open: each chip fades/rises straight out of the icon, cascading up
   and slightly left by its own index (--i, 0-based in filter-option order),
   with a per-item transition-delay so they reveal one after another instead
   of all at once. */
.fx-photo-filters.is-open .fx-photo-chip {
  opacity: 1;
  transform: translate(calc(var(--i) * -10px), calc((var(--i) + 1) * -64px));
  pointer-events: auto;
  transition-delay: calc(var(--i) * 55ms);
}
