/* ==========================================================================
   Infinity Room
   Palette: two neutrals + one pink. Everything else is photography.
   ========================================================================== */

@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-var-latin.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink:      #08080A;
  --well:     #050506;
  --pink:     #FF2AA7;
  --bone:     #F2EFEC;
  --bone-dim: rgba(242, 239, 236, 0.56);
  --hair:     rgba(242, 239, 236, 0.12);
  --hair-hot: rgba(255, 42, 167, 0.42);

  --gut:  clamp(1.25rem, 5vw, 5rem);   /* page gutter */
  --sec:  clamp(5rem, 12vw, 10rem);    /* section rhythm */

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --------------------------------------------------------------- reset -- */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* tells the UA to render scrollbars and native controls dark */
  color-scheme: dark;
  /* keeps in-page anchors clear of the fixed header */
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--bone);
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: clamp(1rem, 0.95rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }
ul, ol, dl, dd, figure { margin: 0; padding: 0; }
li { list-style: none; }
h1, h2, h3, p { margin: 0; }
address { font-style: normal; }

a { color: inherit; text-decoration: none; }

button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* no 300ms double-tap delay, no grey flash on tap */
a, button, [role="button"] {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3 { text-wrap: balance; }

:focus-visible {
  outline: 2px solid var(--pink);
  outline-offset: 3px;
  border-radius: 2px;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; top: 0; left: 50%;
  transform: translate(-50%, -120%);
  z-index: 200;
  padding: 0.75rem 1.25rem;
  background: var(--pink); color: var(--ink);
  font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 700;
}
.skip:focus { transform: translate(-50%, 0); }

/* ---------------------------------------------------------- typography -- */

.h2 {
  font-size: clamp(2.5rem, 7vw, 5.5rem);
  line-height: 0.95;
  letter-spacing: -0.035em;
  font-weight: 800;
  text-transform: uppercase;
}

.sec-head { margin-bottom: clamp(2.5rem, 6vw, 4.5rem); }

/* --------------------------------------------------------------- logos -- */
/* SVGs are masked so CSS `color` drives them; no inline markup needed.      */

.logo {
  display: block;
  background: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
}
.logo--word {
  aspect-ratio: 712 / 242;
  -webkit-mask-image: url('../assets/logo/wordmark.svg');
  mask-image: url('../assets/logo/wordmark.svg');
}
.logo--badge {
  aspect-ratio: 1;
  -webkit-mask-image: url('../assets/logo/mark.svg');
  mask-image: url('../assets/logo/mark.svg');
}

/* --------------------------------------------------------------- overlay --*/

.grain, .scan {
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 90;
}
.grain {
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.scan {
  opacity: 0.55;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255,255,255,0.018) 0 1px,
    transparent 1px 3px
  );
}

.trail {
  position: fixed; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 95;
  mix-blend-mode: screen;
}

/* ----------------------------------------------------------------- nav -- */

/*
   Hidden while the hero is on screen, revealed once it scrolls past (see the nav
   module in js/main.js).

   visibility — not just opacity — is what takes the links out of the tab order
   and out of the accessibility tree. Without it a keyboard user would tab into
   an invisible bar over the hero. It is transitioned with a delay on the way out
   so the slide-up finishes before the bar becomes unfocusable, and with no delay
   on the way in.
*/
.nav {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex; align-items: center; gap: 2rem;
  padding: 1.15rem max(var(--gut), env(safe-area-inset-right)) 1.15rem max(var(--gut), env(safe-area-inset-left));
  border-bottom: 1px solid transparent;

  transform: translateY(-100%);
  opacity: 0;
  visibility: hidden;
  transition:
    transform 0.45s var(--ease),
    opacity 0.3s var(--ease),
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    padding 0.4s var(--ease),
    visibility 0s linear 0.45s;
}

.nav.is-stuck {
  transform: none;
  opacity: 1;
  visibility: visible;
  background: rgba(8, 8, 10, 0.78);
  border-bottom-color: var(--hair);
  padding-block: 0.85rem;
  transition:
    transform 0.45s var(--ease),
    opacity 0.3s var(--ease),
    background 0.4s var(--ease),
    border-color 0.4s var(--ease),
    padding 0.4s var(--ease),
    visibility 0s linear 0s;
}
@supports (backdrop-filter: blur(1px)) {
  .nav.is-stuck { backdrop-filter: blur(14px) saturate(1.3); }
}

.nav__logo { color: var(--pink); flex: none; }
.nav__logo .logo { width: clamp(104px, 12vw, 140px); }

.nav__links {
  display: flex; gap: clamp(1.25rem, 2.5vw, 2.25rem);
  margin-inline: auto;
  font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600;
}
.nav__links a,
.nav__links .navlink { color: var(--bone-dim); transition: color 0.25s; font: inherit; letter-spacing: inherit; text-transform: inherit; padding: 0; }
.nav__links a:hover,
.nav__links .navlink:hover { color: var(--bone); }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--hair);
  font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 700;
  transition: border-color 0.3s, color 0.3s, background 0.3s;
}
.btn:hover { border-color: var(--pink); color: var(--pink); }

.btn--solid {
  background: var(--pink); border-color: var(--pink); color: var(--ink);
}
.btn--solid:hover { background: transparent; color: var(--pink); }

.nav__cta { flex: none; padding: 0.7rem 1.25rem; }
/* Below 860px the links are hidden, and with them the auto margin that was
   pushing the CTA across. Give the CTA its own auto margin so it stays hard
   right instead of sitting against the logo. */
@media (max-width: 860px) {
  .nav__links { display: none; }
  .nav__cta   { margin-left: auto; }
}

/* ---------------------------------------------------------------- hero -- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid; place-items: center;
  padding: 8rem max(var(--gut), env(safe-area-inset-right)) max(6rem, env(safe-area-inset-bottom)) max(var(--gut), env(safe-area-inset-left));
  overflow: hidden;
  isolation: isolate;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img {
  width: 100%; height: 100%; object-fit: cover;
  animation: drift 28s var(--ease) infinite alternate;
}
@keyframes drift { from { transform: scale(1.02); } to { transform: scale(1.12); } }

.hero::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(120% 80% at 50% 45%, transparent 30%, rgba(8,8,10,0.72) 100%),
    linear-gradient(to bottom, rgba(8,8,10,0.66) 0%, rgba(8,8,10,0.2) 32%, rgba(8,8,10,0.86) 100%);
}

.hero__inner { text-align: center; max-width: 46rem; position: relative; z-index: 1; }
.hero__inner > * { position: relative; z-index: 1; }

/* Soft halo so the badge stays legible over the bright ceiling bars. */
.hero__inner::before {
  content: '';
  position: absolute; z-index: 0;
  left: 50%; top: -22%;
  width: min(520px, 88vw); aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle,
    rgba(8,8,10,0.78) 0%,
    rgba(8,8,10,0.52) 42%,
    transparent 70%);
}

.hero__badge {
  width: clamp(160px, 26vw, 300px);
  margin: 0 auto clamp(2.5rem, 6vw, 4rem);
  color: var(--pink);
  filter: drop-shadow(0 0 44px rgba(255, 42, 167, 0.5));
}

.hero__cta {
  margin-top: clamp(2rem, 4vw, 3rem);
  display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap;
}
.hero__cta .btn {
  border-color: rgba(242,239,236,0.3);
  background: rgba(8,8,10,0.3);
}

.hero__cue {
  position: absolute; bottom: 2rem; left: 50%; transform: translateX(-50%);
  width: 1px; height: 56px; overflow: hidden;
  background: var(--hair);
}
.hero__cue span {
  display: block; width: 100%; height: 40%;
  background: var(--pink);
  animation: cue 2.4s var(--ease) infinite;
}
@keyframes cue { 0% { transform: translateY(-100%); } 100% { transform: translateY(250%); } }

/* ------------------------------------------------------------- marquee -- */

.marquee {
  --dir: -1;
  position: relative;
  border-block: 1px solid var(--hair-hot);
  padding-block: clamp(0.9rem, 2vw, 1.4rem);
  overflow: hidden;
  background: var(--well);
}
.marquee__track {
  display: flex; width: max-content;
  animation: slide 42s linear infinite;
  animation-direction: var(--marq-dir, normal);
}
.marquee--sm .marquee__track { animation-duration: 30s; }
.marquee__track span {
  font-size: clamp(1.75rem, 5vw, 3.75rem);
  font-weight: 800; text-transform: uppercase;
  letter-spacing: -0.02em;
  color: rgba(242, 239, 236, 0.14);
  white-space: nowrap;
  padding-right: 0.4em;
}
.marquee--sm .marquee__track span { font-size: clamp(0.9rem, 2vw, 1.5rem); letter-spacing: 0.1em; }
.marquee__track em { font-style: normal; color: var(--pink); }
@keyframes slide { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ---------------------------------------------------------------- room -- */

.room {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: center;
  padding: var(--sec) var(--gut);
}
.room__text p + p { margin-top: 1.25rem; }
.room__text > p { color: var(--bone-dim); max-width: 34rem; }
.room__text .h2 { margin-bottom: 2rem; }

.room__media { position: relative; }
.room__shot { overflow: hidden; }
.room__shot img { width: 100%; }
.room__shot--a { width: 82%; }
.room__shot--b {
  width: 54%;
  margin: -18% 0 0 auto;
  position: relative;
  border: 1px solid rgba(8,8,10,0.9);
}
@media (max-width: 900px) {
  .room { grid-template-columns: 1fr; }
}

/* -------------------------------------------------------------- nights -- */

.nights { padding: var(--sec) var(--gut); background: var(--well); }

.sub-head {
  font-size: 0.6875rem; letter-spacing: 0.2em; text-transform: uppercase;
  font-weight: 600;
  color: var(--bone-dim);
  padding-bottom: 1rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  border-bottom: 1px solid var(--hair);
}
.sub-head--gap { margin-top: clamp(3.5rem, 8vw, 6rem); }

/* weekly residencies -------------------------------------------------------- */

.weeklies {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

.weekly { display: grid; gap: 1.35rem; }

.weekly__art {
  position: relative;
  aspect-ratio: 1;
  isolation: isolate;
}
.weekly__art img {
  width: 100%; height: 100%; object-fit: cover;
  filter: saturate(0.92) contrast(1.03);
  transition: filter 0.5s var(--ease), transform 0.6s var(--ease);
}
.weekly__leak {
  position: absolute; inset: 0; z-index: -1;
  background-size: cover; background-position: center;
  filter: blur(40px) saturate(1.8);
  opacity: 0.45;
  transform: scale(1.12);
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease);
}
.weekly:hover .weekly__art img { filter: saturate(1.1) contrast(1); transform: scale(1.02); }
.weekly:hover .weekly__leak  { opacity: 0.8; transform: scale(1.2); }

.weekly__body { display: grid; gap: 0.4rem; }
.weekly__day {
  font-size: 0.6875rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--pink); font-weight: 700;
}
.weekly__name {
  font-size: clamp(1.35rem, 2.6vw, 1.85rem);
  font-weight: 800; letter-spacing: -0.025em; text-transform: uppercase;
  line-height: 1.05;
}
.weekly__meta {
  font-size: 0.8125rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--bone-dim);
  font-variant-numeric: tabular-nums;
}

.nights__note {
  margin-top: 2rem;
  font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--bone-dim);
}

/* ------------------------------------------------- booking embeds -- */
/* Mr. Black renders inside a cross-origin iframe, so its interior cannot be
   styled from here. We control the frame around it and let it size itself
   via the postMessage height handshake in js/main.js. */

/* Mr. Black's calendar views paint no background of their own, so the browser
   shows its white canvas — and `color-scheme` does not propagate into a
   cross-origin frame, so this cannot be darkened from here. Rather than leave a
   white block inside a dark border looking like a fault, the panel is presented
   as a deliberate light band with pink hairlines, echoing the marquee rules.
   If Mr. Black ever theme the calendar dark (their reserve-table view for this
   venue already is), delete this block and the iframe background below. */
.embed {
  position: relative;
  width: 100%;
  margin: 0 auto;
  overflow: hidden;
  border: 0;
  border-block: 1px solid var(--hair-hot);
  background: #fff;
}
.embed iframe {
  display: block;
  width: 100%;
  border: 0;
  background-color: #fff;
  transition: height 0.35s var(--ease);
}
.embed[hidden] { display: none; }
/* The reserve-table view is themed dark by the venue, so its panel stays dark. */
.embed--book { margin-top: clamp(2rem, 4vw, 3rem); background: #0d0d0f; }
.embed--book iframe { background-color: #0d0d0f; }

@media (prefers-reduced-motion: reduce) {
  .embed iframe { transition: none; }
}

/* full-screen checkout layer */
.embed-modal {
  position: fixed; inset: 0; z-index: 10000;
  display: grid; place-items: center;
  background: rgba(5, 5, 6, 0.96);
  overscroll-behavior: contain;
}
.embed-modal[hidden] { display: none; }
.embed-modal__box {
  position: relative;
  width: min(1100px, 96vw);
  height: 90svh;
}
.embed-modal__frame { width: 100%; height: 100%; border: 0; }
.embed-modal__close {
  position: absolute; top: 0.75rem; right: 0.75rem;
  width: 2.5rem; height: 2.5rem;
  display: grid; place-items: center;
  font-size: 1.75rem; line-height: 1;
  color: var(--bone);
  background: rgba(8, 8, 10, 0.85);
  border: 1px solid var(--hair);
  border-radius: 50%;
  transition: border-color 0.3s, color 0.3s;
}
.embed-modal__close:hover { border-color: var(--pink); color: var(--pink); }

/* ------------------------------------------------------------- gallery -- */
/* Continuously scrolling strip of portrait cards. The track holds two
   identical runs and translates by exactly -50%, so the loop is seamless. */

.gallery { padding: var(--sec) 0; }

.strip {
  position: relative;
  overflow: hidden;
  padding-block: clamp(1rem, 2vw, 2rem);
  /* fade the ends so cards enter and leave rather than being cut off */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
}

.strip__track {
  display: flex;
  gap: clamp(0.75rem, 1.5vw, 1.35rem);
  width: max-content;
  animation: strip var(--strip-duration, 90s) linear infinite;
}

@keyframes strip { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }

.strip__item { flex: none; }

.strip__frame {
  position: relative;
  display: block;
  width: clamp(190px, 22vw, 300px);
  aspect-ratio: 3 / 4;
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
}
.strip__frame img {
  width: 100%; height: 100%; object-fit: cover;
  object-position: 50% 32%;
  filter: saturate(0.88) contrast(1.05);
}

/* the light leak: the photograph itself, blurred, bleeding onto the page */
.strip__leak {
  position: absolute; inset: 0; z-index: -1;
  background-size: cover; background-position: center;
  filter: blur(26px) saturate(1.7);
  opacity: 0.42;
  transform: scale(1.15);
}

@media (max-width: 700px) {
  .strip__frame { width: min(58vw, 260px); }
}

@media (prefers-reduced-motion: reduce) {
  /* no auto-scroll — becomes a normal horizontal scroller the user drives */
  .strip { overflow-x: auto; scroll-snap-type: x proximity; }
  .strip__track { animation: none; }
  .strip__item { scroll-snap-align: center; }
}

/* -------------------------------------------------------- reservations -- */

.res { padding: var(--sec) var(--gut); background: var(--well); }

.link {
  font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 700;
  color: var(--pink);
  display: inline-flex; gap: 0.5rem; align-items: center;
  transition: gap 0.3s var(--ease);
}
.link:hover { gap: 0.85rem; }

/* --------------------------------------------------------------- visit -- */

.visit { padding: var(--sec) var(--gut); }

.visit__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(2rem, 5vw, 4rem);
}
.visit__label {
  font-size: 0.625rem; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--bone-dim);
  padding-bottom: 1rem; margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--hair);
  font-weight: 600;
}
.visit__block address,
.visit__block p { color: var(--bone-dim); }
.visit__block .link { margin-top: 1.25rem; }

.plain li {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.55rem 0;
  color: var(--bone-dim);
  font-size: 0.9375rem;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid rgba(242,239,236,0.06);
}
.plain li span:first-child { color: var(--bone); }
.visit__note {
  margin-top: 1.25rem;
  font-size: 0.8125rem;
  color: var(--bone-dim);
}

/* -------------------------------------------------------------- footer -- */

.foot {
  padding: clamp(3.5rem, 8vw, 6rem) var(--gut) max(3rem, env(safe-area-inset-bottom));
  border-top: 1px solid var(--hair);
  text-align: center;
  display: grid; justify-items: center; gap: 1.5rem;
  background: var(--well);
}
.foot__badge { width: 76px; color: var(--pink); }
.foot__links {
  display: flex; gap: 1.75rem; flex-wrap: wrap; justify-content: center;
  font-size: 0.6875rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600;
}
.foot__links a,
.foot__links .navlink { color: var(--bone-dim); transition: color 0.25s; font: inherit; letter-spacing: inherit; text-transform: inherit; padding: 0; }
.foot__links a:hover,
.foot__links .navlink:hover { color: var(--pink); }
.foot__legal { font-size: 0.6875rem; letter-spacing: 0.1em; color: rgba(242,239,236,0.32); }

/* --------------------------------------------------- corporate form -- */
/*
   Elfsight contact form, shown as a slide-out pane. We supply our own triggers
   in the nav and footer via data-elfsight-show-form, so the widget's built-in
   floating button is hidden — delete this rule to bring it back.

   The inner class names are Elfsight's own (styled-components), so this is
   matched on a substring rather than an exact hash. If an Elfsight update
   renames the component the button reappears; it does not break the form.
*/
/* Elfsight renders the floating button into a portal on <body>, NOT inside our
   mount div, so this rule cannot be scoped to .elf-mount. It is global because
   this page has exactly one Elfsight widget — if a second one is ever added and
   should show its own floating button, scope this to the widget id instead. */
[class*="FloatingButton__FloatingButtonContainer"] { display: none !important; }

/* The pane is portalled to <body>; keep it above our own fixed overlays
   (grain, scanlines, the cursor canvas). */
[class*="es-portal-root"] { z-index: 300; }

/* ------------------------------------------------------------- reveals -- */

[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* ----------------------------------------------------- reduced motion -- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .nav           { transform: none; }
  .hero__media img { animation: none; transform: scale(1.04); }
  .marquee__track  { animation: none; }
  .hero__cue       { display: none; }
  .trail           { display: none; }

  [data-reveal] { opacity: 1; transform: none; }
}
