/* CSS Custom Properties */
:root {
  --panel-bottom: 32px;
  --panel-height: 104px;
  --panel-radius: 56.5px;
  --panel-padding-edge: 57px;
  --panel-padding-center: 4.25rem;
  --close-btn-size: clamp(30px, 1.8vw, 38px); /* panel toggle: fluid, floor at 30px so it never looks tiny on small screens */
  --menu-width: 50px;
  --mobile-margin: 24px;
  --controls-gap: 50px;
  --menu-gap: 24px;
  --transition-fade: 0.3s ease;
  --transition-ui: 0.4s ease;
}

html, body {
  height: 100%;
  margin: 0;
  background: #000;
  color: #fff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
}

#app {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-rows: 1fr auto;
}

/* Base button reset — shared by all custom buttons */
.btn-reset {
  appearance: none;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 0;
  margin: 0;
}

#pano {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #333;
}

/* Bottom overlay (error messages) */
#bottom-overlay {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  transform: translateY(100%);
  transition: transform 240ms ease;
  background: rgba(0,0,0,0.6);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #fff;
  padding: 12px 16px;
  /* Above the catalog (z-index 300) so error toasts are visible while the
     catalog modal is open (e.g. catalog image 404 messages). */
  z-index: 400;
}

#bottom-overlay.show { transform: translateY(0%); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* Control Panel Overlay */
.control-panel {
  position: fixed;
  bottom: var(--panel-bottom);
  bottom: calc(var(--panel-bottom) + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  width: min(1688px, calc(100vw - var(--panel-bottom)));
  height: var(--panel-height);
  background: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--panel-radius);
  backdrop-filter: blur(25px);
  -webkit-backdrop-filter: blur(25px);
  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1),
              inset 0px 4px 4px 0px rgba(255, 255, 255, 0.12);
  z-index: 100;
  transition: transform var(--transition-ui), opacity var(--transition-ui);
  overflow: visible;
  display: flex;
  flex-direction: row;
}

/* Collapsed state */
.control-panel.collapsed {
  background: transparent;
  border: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
}

.control-panel.collapsed .col-2,
.control-panel.collapsed .col-4 {
  visibility: hidden;
}

/* Panel Columns */
.panel-column {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: white;
  font-family: 'Lato', sans-serif;
  font-size: 0.875rem;
  padding: 0 20px;
}

.col-1 {
  flex: 0 0 auto;
  padding-left: var(--panel-padding-edge);
  justify-content: flex-start;
}

/* col-3 is absolutely positioned at panel center so the close button never shifts
   when col-2 or col-4 content widths change (e.g., switching categories) */
.col-3 {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  flex: 0 0 auto;
  padding: 0;
}

/* col-2 and col-4 reserve space for the absolute close button via padding,
   so their content stays clear of the X button + 4.25rem gap on each side */
.col-2 {
  flex: 1;
  display: flex;
  gap: var(--controls-gap);
  justify-content: center;
  padding-right: calc(var(--close-btn-size) / 2 + var(--panel-padding-center));
}

.col-4 {
  flex: 1;
  justify-content: flex-start;
  padding-left: calc(var(--close-btn-size) / 2 + var(--panel-padding-center));
}

.col-5 {
  flex: 0 0 auto;
  padding-right: var(--panel-padding-edge);
  justify-content: flex-end;
}

/* Project Info */
.project-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.project-name {
  margin: 0;
  font-family: 'Lato', sans-serif;
  font-weight: 900;
  font-size: 1.625rem;
  line-height: 1.2;
  letter-spacing: 0.04em;
  color: #fff;
  white-space: nowrap;
}

.project-location {
  margin: 0;
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.2;
  letter-spacing: 0.04em;
  color: #fff;
  white-space: nowrap;
}

/* Control Buttons */
.control-btn {
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  transition: opacity 0.2s ease;
}

@media (hover: hover) {
  .control-btn:hover {
    opacity: 0.8;
  }
}

.control-btn .icon {
  height: 16px;
  display: block;
}

.control-btn .label {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  font-size: 0.875rem;
  font-style: normal;
  line-height: normal;
  letter-spacing: 0.035rem;
  color: #FFF;
  text-align: center;
  white-space: nowrap;
}

/* Close Button */
.close-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease;
  position: relative;
  width: var(--close-btn-size);
  height: var(--close-btn-size);
}

@media (hover: hover) {
  .close-btn:hover {
    opacity: 0.8;
  }
}

.close-x,
.close-arrow {
  position: absolute;
  top: 0;
  left: 0;
  width: var(--close-btn-size);
  height: var(--close-btn-size);
  transition: opacity var(--transition-fade);
}

/* Shared circular glass-chip used by .close-x and .catalog-close */
.close-x,
.catalog-close {
  border-radius: var(--close-btn-size);
  background: rgba(255, 255, 255, 0.20);
  border: 1px solid rgba(255, 255, 255, 0.40);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  box-shadow: 0 4px 4px 0 rgba(33, 33, 33, 0.12) inset,
              0 4px 4px 0 rgba(0, 0, 0, 0.10);
  padding: 8px;
  box-sizing: border-box;
}

.close-x {
  object-fit: contain;
}

.control-panel.collapsed .close-x,
.control-panel:not(.collapsed) .close-arrow {
  display: none;
}

/* Catalog + Perspective Hotspots (SVG provides full button visual) */
/* Both are self-contained chip SVGs (ic_catalog.svg / ic_nav_open.svg bake in
   their own glass-chip styling), so they share identical base styling and read
   as a visual pair. They diverge only in which body class hides them
   (icons-hidden vs navigation-hidden, below). */
.catalog-hotspot,
.perspective-hotspot,
.info-hotspot {
  position: absolute;
  width: 44px;
  height: 44px;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  user-select: none;
  transform: translate(-50%, -50%);
  opacity: 1;
  transition: opacity var(--transition-fade), visibility var(--transition-fade);
}

/* Hotspots are <button>s wrapping a decorative <img aria-hidden> —
   the img fills the 44px hit area. Fixed pixel size at every zoom level
   (Marzipano default): only their anchored positions track the scene. */
.catalog-hotspot img,
.perspective-hotspot img,
.info-hotspot img {
  width: 100%;
  height: 100%;
  display: block;
}

/* Keyboard focus must stay visible over arbitrary panorama imagery */
.catalog-hotspot:focus-visible,
.perspective-hotspot:focus-visible,
.info-hotspot:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.8);
  outline-offset: 4px;
  border-radius: 50%;
}


body.navigation-hidden .perspective-hotspot {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* The info hotspot hides together with the catalog: once info is hidden,
   the panel/mobile-menu "show info" buttons are the way to bring it back. */
body.icons-hidden .catalog-hotspot,
body.icons-hidden .info-hotspot,
body.icons-hidden .info-panel {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Info Text Panel (in-panorama)
   Anchored at the info chip; opens to its right, top-aligned. The chip
   itself becomes the close (X) while open. */
.info-anchor {
  position: absolute;
}

/* Inside the anchor wrapper the chip keeps the ORIGINAL top-left anchoring
   it had before the panel existed (the configured yaw/pitch was hand-tuned
   against that), so no centering transform here. */
.info-anchor .info-hotspot {
  left: 0;
  top: 0;
  transform: none;
}

.info-panel {
  position: absolute;
  left: 56px;   /* chip width (44px) + 12px gap */
  top: 0;       /* top-aligned with the chip */
  width: 20.375rem;   /* design: 20.375 x 14.5625rem — height stays auto so it adapts to the copy */
  padding: 1.75rem 1.875rem;
  border-radius: 0.3125rem;
  background: rgba(243, 243, 243, 0.20);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.info-panel[hidden] {
  display: none;
}

.info-panel p {
  margin: 0;
  color: #FFF;
  font-family: 'Lato', sans-serif;
  font-size: 0.9375rem;
  font-style: normal;
  font-weight: 300; /* body copy in Light; titles stay bold via <strong> */
  line-height: normal;
  letter-spacing: 0.0375rem;
}

.info-panel p strong {
  font-weight: 700;
}

/* Two blocks per panel (divider + bathtub) — breathing room between them */
.info-panel p + p {
  margin-top: 1.25rem;
}

/* Bath Icons Overlay (top-left area) */
.bath-icons-overlay {
  position: fixed;
  top: 242px;
  right: 100px;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 54px;
  opacity: 0;
  visibility: hidden; /* keep the hidden overlay's buttons out of the tab order */
  pointer-events: none;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.icons-row {
  display: flex;
  align-items: center;
  gap: 30px;
}

body.desktop-icons-visible .bath-icons-overlay {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.bath-option {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
  transition: opacity 0.2s ease;
}

.bath-icon {
  display: block;
  width: auto;
  max-height: 15.5px;
  flex-shrink: 0;
  opacity: 0.31;
  transition: opacity 0.2s ease;
}

.bath-option-name {
  font-family: 'Lato', sans-serif;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.56px;
  color: rgba(255, 255, 255, 0.72);
  white-space: nowrap;
  position: relative;
  padding-bottom: 8px;
  transition: color 0.2s ease;
}

/* Active state — always applied */
.bath-option.active .bath-icon { opacity: 1; }
.bath-option.active .bath-option-name { color: #fff; }
.bath-option.active .bath-option-name::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 45px;
  height: 0.5px;
  background: #fff;
}

/* Hover mirror — only on devices with real hover (avoid sticky tap on touch) */
@media (hover: hover) {
  .bath-option:hover .bath-icon { opacity: 1; }
  .bath-option:hover .bath-option-name { color: #fff; }
  .bath-option:hover .bath-option-name::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 45px;
    height: 0.5px;
    background: #fff;
  }
}

/* Material option (circular finish chip — Travertino, Madera, Onix) */
.material-option {
  display: flex;
  align-items: center;
  gap: 12px;
  position: relative;
  transition: opacity 0.2s ease;
}

.material-icon {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
  display: block;
  opacity: 0.31;
  transition: opacity 0.2s ease;
}

.material-option-name {
  font-family: 'Lato', sans-serif;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0.56px;
  color: rgba(255, 255, 255, 0.72);
  white-space: nowrap;
  transition: color 0.2s ease;
}

.material-option.active .material-icon { opacity: 1; }
.material-option.active .material-option-name { color: #fff; }

@media (hover: hover) {
  .material-option:hover .material-icon { opacity: 1; }
  .material-option:hover .material-option-name { color: #fff; }
}

/* Travertino: rotate texture 90° to align grain.
   The chip's box-shadow rotates with the img, so we offset the shadow on
   the X axis instead of Y — after a 90° clockwise rotation it lands visually
   below the chip again, matching the other materials.
   Uses higher specificity to win over .option-btn.icon-style-finish img. */
.option-btn.icon-style-finish[data-option-id="travertino"] img,
.material-option[data-option-id="travertino"] img {
  transform: rotate(90deg);
  box-shadow: 4px 0 4px rgba(0, 0, 0, 0.25);
}


/* Catalog Slideshow Overlay */
.catalog {
  /* Single source of truth for the prev/next side lane: buttons anchor at
     this offset and the image reserves the lane (offset + 48px button +
     12px gap) so they can never overlap. At full width everything renders
     exactly like the original design (buttons at 214px, image up to 80vw —
     in practice height-bound); the image only gives way when the window
     shrinks enough for the lane to collide. */
  --catalog-nav-offset: 214px;
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(217, 217, 217, 0.20);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 194px;
  padding-bottom: 194px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* visibility flips only after the fade-out finishes, so closing still
     animates while the closed dialog's buttons leave the tab order */
  transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}

/* The author display:flex above would otherwise beat the UA stylesheet's
   [hidden] { display: none } — restore it so the closed dialog (catalog.js
   toggles the hidden attribute) is truly removed from layout and tab order. */
.catalog[hidden] {
  display: none !important;
}

.catalog.open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.3s ease, visibility 0s; /* show immediately on open */
}

.catalog-body {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 0;
}

.catalog-stage {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.catalog-image {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  max-width: min(80vw, calc(100vw - 2 * (var(--catalog-nav-offset) + 48px + 12px)));
  max-height: 100%;
  object-fit: contain;
  display: block;
  box-shadow: 0 0 10px 3px rgba(255, 255, 255, 0.10),
              0 0 20px 6px rgba(255, 255, 255, 0.05);
  opacity: 0;
  transition: opacity 420ms ease;
  pointer-events: none;
  /* Prevent native HTML5 image drag — otherwise dragging the catalog image
     starts a browser drag operation that lingers after the modal closes
     and breaks subsequent interactions with the panorama. */
  -webkit-user-drag: none;
  user-drag: none;
  user-select: none;
  -webkit-user-select: none;
}

.catalog-image.active {
  opacity: 1;
  /* Intentionally NOT setting pointer-events: auto — keep the image
     non-interactive so the browser can't initiate native HTML5 image-drag.
     User interaction goes through prev/next/close buttons only. */
}

/* First-load skeleton: a softly pulsing block where the photo will land
   (catalog.js toggles .stage-loading around the initial image fetch). */
.catalog.stage-loading .catalog-stage::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  height: 82%;
  max-width: 88%;
  aspect-ratio: 3840 / 2865;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.08);
  animation: catalog-skeleton-pulse 1.4s ease-in-out infinite;
}

@keyframes catalog-skeleton-pulse {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 1; }
}

/* Prev / Next buttons */
.catalog-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.30);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease, background 0.2s ease;
  z-index: 2;
}

@media (hover: hover) {
  .catalog-nav:hover {
    background: rgba(255, 255, 255, 0.25);
  }
}

.catalog-prev { left: var(--catalog-nav-offset); }
.catalog-next { right: var(--catalog-nav-offset); }

/* Catalog — mobile scroll mode
   A vertical, momentum-scrolled list of all shots (no arrows). catalog.js
   adds .scroll-mode on the dialog root when opening at the mobile
   breakpoint and fills .catalog-scroll with one <img> per image. */
.catalog.scroll-mode .catalog-stage,
.catalog.scroll-mode .catalog-nav {
  display: none !important;
}

.catalog-scroll {
  flex: 1;
  align-self: stretch; /* .catalog-body centers children — fill its height */
  min-height: 0;
  width: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 4px 12px 28px;
  box-sizing: border-box;
  /* Every scroll settles with an image centered… */
  scroll-snap-type: y mandatory;
  /* Elegant: content scrolls, no visible scrollbar */
  scrollbar-width: none;
}

.catalog-scroll::-webkit-scrollbar {
  display: none;
}

.catalog-scroll[hidden] {
  display: none;
}

.catalog-scroll img {
  /* The slot exists BEFORE the bytes arrive: `auto W/H` uses the photo's
     natural ratio once loaded and this fallback meanwhile, so the list
     never collapses or jumps during a cold first load. The soft gray
     shows as a skeleton on the white sheet until the fade-in. */
  aspect-ratio: auto 3840 / 2865;
  background: rgba(0, 0, 0, 0.05);
  /* Soft entrance: each shot fades/settles in as it finishes loading
     (catalog.js adds .loaded on the img's load event). */
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.5s ease, transform 0.5s ease;
  display: block;
  /* Full container width; height follows the photo's aspect ratio, so a
     centered image always leaves the neighbors peeking above and below. */
  width: 100%;
  height: auto;
  /* …one image per swipe, centered, neighbors peeking at the edges */
  scroll-snap-align: center;
  scroll-snap-stop: always;
  border-radius: 6px;
  box-shadow: 0 0 10px 3px rgba(255, 255, 255, 0.10),
              0 0 20px 6px rgba(255, 255, 255, 0.05);
  user-select: none;
  -webkit-user-select: none;
  -webkit-user-drag: none;
  user-drag: none;
}
.catalog-scroll img.loaded {
  opacity: 1;
  transform: translateY(0);
}

.catalog-arrow {
  font-family: 'Lato', sans-serif;
  font-size: 32px;
  line-height: 1;
  color: #fff;
  display: block;
  padding-bottom: 4px; /* visual centering for chevron */
}

/* Inherits glass-chip styling from the shared .close-x/.catalog-close rule above */
.catalog-close {
  position: absolute;
  bottom: 70px;
  left: 50%;
  transform: translateX(-50%);
  /* Fixed: decoupled from the fluid panel-toggle size */
  width: 35px;
  height: 35px;
  border-radius: 35px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease;
}

@media (hover: hover) {
  .catalog-close:hover { opacity: 0.8; }
}

.catalog-close img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}

/* Category Selector (Col-4) — Two-Row */
.category-selector {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

/* Top row: option buttons */
.category-options {
  display: flex;
  align-items: center;
  gap: 44px;
  min-height: 42px;
}

/* Bottom row: category tabs */
.category-tabs {
  display: flex;
  align-items: center;
  gap: 7rem;
}

/* Option button (icon + name in a row) */
.option-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.option-btn img {
  max-height: 15.5px;
  display: block;
  opacity: 0.31;
  transition: opacity 0.2s ease;
}

.option-btn .option-name {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  font-size: 0.75rem;
  line-height: 1;
  letter-spacing: 0.035rem;
  color: rgba(255, 255, 255, 0.72);
  white-space: nowrap;
  text-align: left;
  padding-bottom: 4px;
  border-bottom: 0.5px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

/* Finish-style icons (textures: travertino, madera, onix) — circular chip */
.option-btn.icon-style-finish img {
  width: 28px;
  height: 28px;
  max-height: none;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
}

.option-btn.icon-style-finish .option-name {
  font-size: 14px;
  letter-spacing: 0.56px;
  padding-bottom: 0;
  border-bottom: none;
}

/* Disable underline on hover/active for finish style */
.option-btn.icon-style-finish.active .option-name {
  border-bottom-color: transparent;
}
@media (hover: hover) {
  .option-btn.icon-style-finish:hover .option-name {
    border-bottom-color: transparent;
  }
}

/* Active state — always */
.option-btn.active img { opacity: 1; }
.option-btn.active .option-name {
  color: #fff;
  border-bottom-color: #fff;
}

/* Hover mirror — only on real-hover devices to avoid sticky tap on touch */
@media (hover: hover) {
  .option-btn:hover img { opacity: 1; }
  .option-btn:hover .option-name {
    color: #fff;
    border-bottom-color: #fff;
  }
}

/* Category tab (plain italic text + underline SVG) */
.category-tab {
  font-family: 'Lato', sans-serif;
  font-weight: 400;
  font-size: 0.6875rem;
  font-style: italic;
  line-height: normal;
  letter-spacing: 0.0275rem;
  color: #fff;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  transition: opacity 0.2s ease;
}

.category-tab .tab-underline {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.category-tab.active .tab-underline {
  opacity: 1;
}

.category-tab:not(.active) {
  opacity: 0.5;
}

/* Fluint Brand */
.fluint-brand {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 96px;
  height: 36px;
}

.fluint-brand img {
  height: 20px;
  width: auto;
  filter: brightness(0) invert(1);
}

/* Focus-visible (keyboard accessibility) */
.control-btn:focus-visible,
.menu-control-btn:focus-visible,
.mobile-gyro-btn:focus-visible,
.bath-option:focus-visible,
.material-option:focus-visible,
.category-tab:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.8);
  outline-offset: 4px;
  border-radius: 4px;
}

.close-btn:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.8);
  outline-offset: 4px;
  border-radius: 50%;
}

/* Mobile Gyroscope Button */
/* Bottom-right corner — the spot the Fluint logo used to occupy (the logo
   now lives inside the project-info block, on the 2026 row). */
.mobile-gyro-container {
  display: none;
  position: fixed;
  right: var(--mobile-margin);
  bottom: var(--mobile-margin);
  right: calc(var(--mobile-margin) + env(safe-area-inset-right));
  bottom: calc(var(--mobile-margin) + env(safe-area-inset-bottom));
  z-index: 100;
}

.mobile-gyro-btn {
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition: opacity 0.2s ease;
}

@media (hover: hover) {
  .mobile-gyro-btn:hover {
    opacity: 0.8;
  }
}

.mobile-gyro-btn .gyro-icon {
  width: 40px;
  height: 40px;
  display: block;
}

.mobile-gyro-btn .gyro-label {
  font-family: 'Lato', sans-serif;
  font-weight: 300;
  font-size: 1rem;
  line-height: 1;
  letter-spacing: 0.04em;
  color: #fff;
  white-space: nowrap;
}

/* Top-Right Menu (Mobile) */
.top-right-menu {
  position: fixed;
  top: 12px;
  right: 16px;
  top: max(12px, env(safe-area-inset-top));
  right: max(16px, env(safe-area-inset-right));
  width: var(--menu-width);
  border-radius: var(--panel-radius);
  border: 1px solid rgba(255, 255, 255, 0.40);
  background: rgba(255, 255, 255, 0.20);
  box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.10),
              0 4px 4px 0 rgba(255, 255, 255, 0.12) inset;
  backdrop-filter: blur(12.5px);
  -webkit-backdrop-filter: blur(12.5px);
  z-index: 150;
  padding-bottom: var(--menu-gap);
  display: none;
  flex-direction: column;
  align-items: center;
  transition: background var(--transition-fade), border var(--transition-fade),
              box-shadow var(--transition-fade), backdrop-filter var(--transition-fade),
              padding var(--transition-fade);
}

.top-right-menu.collapsed {
  background: transparent;
  border: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  box-shadow: none;
  padding: 0;
}

.menu-controls,
.menu-separator,
.menu-baths,
.menu-walls {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--transition-fade), visibility var(--transition-fade);
}

.top-right-menu.collapsed .menu-controls,
.top-right-menu.collapsed .menu-separator,
.top-right-menu.collapsed .menu-baths,
.top-right-menu.collapsed .menu-walls {
  opacity: 0;
  visibility: hidden; /* keep collapsed-menu buttons out of the tab order */
  pointer-events: none;
}

/* Menu Close Button */
.menu-close-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 11px;
  transition: opacity 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) {
  .menu-close-btn:hover { opacity: 0.8; }
}

.menu-close-btn:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.8);
  outline-offset: 4px;
  border-radius: 50%;
}

.menu-icon-menu {
  display: none;
  height: 42px;
}

.menu-close-icon {
  font-family: 'Lato', sans-serif;
  font-size: 2rem;
  line-height: 1;
  color: #fff;
  letter-spacing: 0.04em;
  display: block;
}

.top-right-menu.collapsed .menu-icon-menu { display: block; }
.top-right-menu.collapsed .menu-close-icon { display: none; }

/* Menu Controls */
.menu-controls {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--menu-gap);
  margin-top: var(--menu-gap);
}

.menu-control-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.2s ease;
}

@media (hover: hover) {
  .menu-control-btn:hover { opacity: 0.8; }
}

.menu-control-btn img {
  height: 15px;
  display: block;
}

/* Menu Separator */
.menu-separator {
  margin-top: var(--menu-gap);
  display: flex;
  align-items: center;
  justify-content: center;
}

.menu-separator img {
  display: block;
}

/* Mobile menu — Bath options (icons-only column) */
.menu-baths {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-top: var(--menu-gap);
}

.menu-baths .bath-option {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 4px 0;
  /* override desktop overlay's gap (icon+text) — no text in menu */
  gap: 0;
}

.menu-baths .bath-icon {
  width: auto;
  max-width: 32px;   /* matches nature.svg's rendered width — keeps icons compact */
  max-height: 14px;
  /* opacity inherited from base .bath-icon (0.31 inactive → 1 active/hover) */
}

.menu-baths .bath-option-name { display: none; }

/* Mobile menu — Wall finishes (chip column) */
.menu-walls {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin-top: var(--menu-gap);
}

.menu-walls .material-option {
  padding: 2px 0;
  gap: 0;
}

.menu-walls .material-option-name { display: none; }

/* The .material-icon (28px circular chip with shadow) keeps its base styling */

/* Mobile-only Elements */
.mobile-project-info,
.mobile-fluint-brand {
  display: none;
}

/* Responsive — Mobile (<=1564px) */
@media (max-width: 1564px) {
  .control-panel {
    display: none;
  }

  .mobile-project-info {
    display: block;
    position: fixed;
    left: var(--mobile-margin);
    bottom: var(--mobile-margin);
    left: calc(var(--mobile-margin) + env(safe-area-inset-left));
    bottom: calc(var(--mobile-margin) + env(safe-area-inset-bottom));
    z-index: 100;
  }

  /* Block width = the project name's width, so the meta row below can
     right-align the Fluint logo exactly where "Serena Materia" ends. */
  .mobile-project-info .project-info {
    width: max-content;
  }

  /* Mobile shows NO year: just the Fluint logo, left-aligned under the
     project name. (Desktop panel keeps its own 2026.) */
  .mobile-project-info .project-location {
    display: none;
  }

  .project-meta-row {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    /* Don't let this row contribute to the block's intrinsic width: the
       block must size to the project NAME alone, and the row then
       stretches to exactly that width. */
    width: 0;
    min-width: 100%;
  }

  .mobile-fluint-brand {
    display: flex;
    align-items: center;
  }

  .mobile-project-info .project-name {
    font-size: clamp(14px, 4vw, 26px);
  }

  .mobile-project-info .project-location {
    font-size: clamp(12px, 3vw, 16px);
  }

  /* Real layout sizes (no transform: scale keeps the LAYOUT box at full
     size, which pushed the logo past the title's right edge). 15px =
     desktop 20px × 0.75. */
  .mobile-fluint-brand .fluint-brand {
    width: auto;
    height: auto;
  }

  .mobile-fluint-brand .fluint-brand img {
    height: 15px;
  }

  .mobile-gyro-btn .gyro-label {
    font-size: clamp(12px, 2.5vw, 16px);
  }

  .mobile-gyro-btn .gyro-icon {
    width: clamp(32px, 6vw, 40px);
    height: clamp(32px, 6vw, 40px);
  }

  .mobile-gyro-container {
    display: block;
  }

  .top-right-menu {
    display: flex;
  }

  /* Desktop bath/wall overlay lives inside the side menu on mobile */
  .bath-icons-overlay {
    display: none !important;
  }

  /* Catalog slideshow — nav lane hugs the edges on small screens, original
     values; image width follows automatically via --catalog-nav-offset */
  .catalog {
    --catalog-nav-offset: clamp(16px, 5vw, 214px);
    padding-top: clamp(60px, 15vh, 194px);
    padding-bottom: clamp(80px, 18vh, 194px);
  }

  /* Scroll mode: solid white sheet (no glass). The close moved to the
     top-left corner, so the sheet breathes the SAME amount above and
     below the image area. */
  .catalog.scroll-mode {
    background: #fff;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding-top: clamp(30px, 7.5vh, 97px);
    padding-bottom: calc(clamp(30px, 7.5vh, 97px) + env(safe-area-inset-bottom));
  }

  /* White glows are invisible on white — soft dark elevation instead */
  .catalog.scroll-mode .catalog-scroll img {
    box-shadow: 0 2px 14px rgba(0, 0, 0, 0.12);
  }

  /* +25% breathing room between shots (14px -> 17.5px) */
  .catalog.scroll-mode .catalog-scroll {
    gap: 17.5px;
  }

  /* Bare, elegant stock X at the top-left — no chip, no glass (catalog.js
     swaps the icon to ic_close_dark.svg in this mode). The X's VISUAL
     stroke must align with the images' left edge (12px, the scroll list's
     side padding): with the chip padding zeroed the 35px button renders
     the 20-viewBox icon at 1.75x, whose stroke starts 4 units in → 7px of
     internal inset. 12px − 7px = 5px. */
  .catalog.scroll-mode .catalog-close {
    top: calc(14px + env(safe-area-inset-top));
    /* The glyph hugs the button's LEFT edge (flex-start) and its stroke
       starts ~1px inside the half-size icon box, so 11px puts the visible
       X exactly on the images' 12px left edge. */
    left: calc(11px + env(safe-area-inset-left));
    bottom: auto;
    right: auto;
    transform: none;
    padding: 0;
    justify-content: flex-start;
    background: none;
    border: 0;
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  /* Reduced glyph (50% x 0.8 = 40%) — the full button stays as the tap target */
  .catalog.scroll-mode .catalog-close img {
    width: 40%;
    height: 40%;
  }
  .catalog-close {
    bottom: clamp(28px, 6vh, 70px);
    bottom: calc(clamp(28px, 6vh, 70px) + env(safe-area-inset-bottom));
  }

  /* Smooth extend/collapse for bath/wall sections + separator when toggled.
     Uses max-height + margin + opacity so the menu visibly grows downward
     instead of popping. */
  .menu-separator,
  .menu-baths,
  .menu-walls {
    overflow: hidden;
    max-height: 320px; /* generous upper bound — content fits well below this */
    transition: opacity var(--transition-fade),
                max-height var(--transition-fade),
                margin-top var(--transition-fade),
                visibility var(--transition-fade);
  }

  body:not(.mobile-icons-visible) .menu-separator,
  body:not(.mobile-icons-visible) .menu-baths,
  body:not(.mobile-icons-visible) .menu-walls {
    max-height: 0;
    margin-top: 0;
    opacity: 0;
    visibility: hidden; /* keep hidden sections' buttons out of the tab order */
    pointer-events: none;
  }
}

/* Reduced Motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    /* Effectively disable UI fades/slides and the catalog crossfade.
       Near-zero (not 0s) so transitionend semantics stay intact. */
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }
}
