/* ============================================================
   NH HOUSE — nuruhouse.com
   Editorial noir design system.
   One stylesheet. No frameworks. Tokens first.
   ============================================================ */

/* ---------- Fonts (self-hosted woff2) ----------
   JLC formula: two geometric sans, no serif, NO italics anywhere -- elegance
   carried by tracking, case and space, never by slant or weight.
   DM Sans (display) + Montserrat (body).
   Bodoni/Archivo/Yeseva/Josefin files remain in /assets/fonts for rollback. */
@font-face {
  font-family: "Montserrat";
  src: url("/assets/fonts/montserrat-sub.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Sans";
  src: url("/assets/fonts/dm-sans-sub.woff2") format("woff2");
  font-weight: 100 1000;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Josefin Sans";
  src: url("/assets/fonts/josefin-sans-var.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Josefin Sans";
  src: url("/assets/fonts/josefin-sans-italic-var.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
/* Metric-matched fallbacks to kill FOUT layout shift */
@font-face {
  font-family: "Display-fb";
  src: local("Arial"), local("Helvetica Neue");
  size-adjust: 113%;
  ascent-override: 86%;
  descent-override: 22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Body-fb";
  src: local("Arial"), local("Helvetica Neue");
  size-adjust: 97%;
  ascent-override: 95%;
  descent-override: 21%;
  line-gap-override: 0%;
}

/* ---------- Tokens ---------- */
:root {
  /* palette — warm-shifted charcoal, violet dominant, amber tension */
  --ink-0: #0f0c13;
  --ink-1: #16121a;
  --ink-2: #1f1826;
  --ink-3: #2a2133;
  --ink-alt: #1a1520;

  /* Section grounds by temperature, not by brightness. Two dark neighbours
     top out near 1.25:1 of luminance — below what the eye reads as a break —
     but a hue shift at the same darkness reads as a change of material.
     These three sit within 0.006-0.008 luminance of each other. */
  --ground-plum: #16121a;
  --ground-warm: #1c1215;
  --ground-cool: #101620;
  --line: #322940;
  --bone: #efe9e7;
  --body: #b9b0c4;
  --muted: #877e94;
  --violet: #8f5bf2;
  --violet-deep: #5b2ea8;
  --violet-bright: #c7a9ff;
  --amber: #e5b26b;

  /* Celadon paper: the one pale surface on the site, complement of the violet
     ground. It carries the origin deck and the LINE card, and nothing else —
     the moment it spreads it stops meaning "an object laid on the room". */
  --paper-1: #dfe9e0;
  --paper-2: #cdd9d4;
  --paper-ink: #1d2b26;
  --paper-body: #3c4b45;
  --line-green: #05c756;

  --font-display: "DM Sans", "Display-fb", sans-serif;
  --font-serif: "Montserrat", "Body-fb", sans-serif;
  --font-body: "Montserrat", "Body-fb", sans-serif;
  --font-accent: "DM Sans", "Display-fb", sans-serif;

  --step--1: clamp(0.8rem, 0.78rem + 0.12vw, 0.875rem);
  --step-0: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --step-1: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);
  --step-2: clamp(1.6rem, 1.4rem + 1vw, 2.25rem);
  --step-3: clamp(2.1rem, 1.7rem + 2vw, 3.4rem);
  --step-4: clamp(2.8rem, 2rem + 4vw, 5.2rem);
  --step-5: clamp(3.2rem, 2.1rem + 4.4vw, 4.6rem);

  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.75rem;
  /* The step inside a block: a chapter label to its heading, one grid card to
     the next. Fluid on the same curve as --space-5 and always well under it,
     so the hierarchy between "inside a block" and "between blocks" survives
     down to a phone instead of flattening into one value. */
  --space-4: clamp(2rem, 1.35rem + 2.75vw, 3rem);
  /* The step that separates blocks: the deck from its intro, one facility band
     from the next, the post grid from its lede. Fluid, because 5rem of air
     between two blocks is right on a desktop and a hole on a phone. Reaches
     its 5rem ceiling around 1240px, so wide screens keep the airy layout. */
  --space-5: clamp(3rem, 1.6rem + 4.4vw, 5rem);
  --space-6: clamp(6rem, 4.5rem + 7vw, 12rem);

  --gutter: clamp(1.25rem, 4vw, 4rem);
  --measure: 68ch;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.7s;

  color-scheme: dark;
}

/* ---------- Base ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  /* the header is fixed: without this every anchor lands underneath it */
  scroll-padding-top: 8rem;
  -webkit-text-size-adjust: 100%;
}
em, i { font-style: normal; }
body {
  font-synthesis: none;
  margin: 0;
  background: var(--ink-1);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.7;
  overflow-x: clip;
}
h1, h2, h3, h4 {
  color: var(--bone);
  margin: 0 0 var(--space-3);
  text-wrap: balance;
}
/* Bodoni Moda carries the statement headings, set in sentence case:
   all-caps would hurt these long SEO headings, and readability comes first.
   The caps-plus-tracking treatment lives on the eyebrows and small labels. */
h1, h2 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: 0.01em;
  font-variation-settings: "opsz" 96;
}
/* Archivo handles every heading small enough to lose Bodoni's hairlines. */
h3, h4 {
  font-family: var(--font-serif);
  font-weight: 600;
  letter-spacing: -0.005em;
}
h1 { font-size: var(--step-5); }
h2 { font-size: var(--step-4); }
h3 { font-size: var(--step-2); line-height: 1.2; }
h4 { font-size: var(--step-1); line-height: 1.3; }
p { margin: 0 0 1.4em; max-width: var(--measure); }
img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: var(--violet-bright); text-decoration-color: color-mix(in srgb, var(--violet-bright) 40%, transparent); text-underline-offset: 0.2em; }
a:hover { color: var(--bone); }
::selection { background: var(--violet-deep); color: var(--bone); }
strong { color: var(--bone); font-weight: 600; }
:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--space-2);
  z-index: 200;
  background: var(--amber);
  color: var(--ink-0);
  font-weight: 600;
  padding: 0.7em 1.2em;
  text-decoration: none;
}
.skip-link:focus { top: var(--space-2); color: var(--ink-0); }

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

/* Film grain over everything */
body::after {
  content: "";
  position: fixed;
  inset: -50%;
  z-index: 120;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: 0.055;
  mix-blend-mode: overlay;
}

/* Layout primitives */
.wrap {
  width: min(100% - 2 * var(--gutter), 78rem);
  margin-inline: auto;
}
.section {
  position: relative;
  padding-block: var(--space-6);
  /* contains the decorative glows and ghost type; `clip` (not `hidden`)
     so sticky descendants keep working */
  overflow-x: clip;
}
.eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--amber);
  margin-bottom: var(--space-3);
}

/* ---------- Chapter opening ----------
   Eight sections used to start identically, with nothing to signal a new
   chapter on a page this long. A hairline plus a running number does it. */
.chapter {
  position: relative;
  z-index: 2;   /* the ghost display type is positioned, so it would paint over */
  max-width: none;
  margin: 0 0 var(--space-4);
  padding-left: 1.15rem;
  /* same voice as the hero kicker: one family, one size, uppercase */
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--amber);
}

/* ---------- Section grounds ---------- */
.ground--plum { background: var(--ground-plum); }
.ground--warm { background: var(--ground-warm); }
.ground--cool { background: var(--ground-cool); }

/* ---------- The seam ----------
   The old rule was inset to the text column, which made it read as decoration
   inside a section rather than the edge between two. Full-bleed, it cuts. */
.section::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 1px;
  background: var(--line);
  z-index: 1;
}

/* Guest Reviews is the one centred section: the bar would sit off to the left
   of centred text instead of leading it, so it goes, and the padding it made
   room for goes with it. */
.reviews .chapter { padding-left: 0; }
.reviews .chapter::before { content: none; }

.chapter::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.12em;
  bottom: 0.12em;
  width: 2px;
  background: linear-gradient(to bottom, var(--amber), transparent);
}

/* ---------- Current chapter, phones only ----------
   Desktop has the nav highlight for this; on mobile the nav is behind the
   burger, leaving thirty screens of scrolling with no sense of place. */
.section-cue {
  position: fixed;
  z-index: 95;
  top: calc(46px + 2.2rem + 0.55rem);
  left: var(--gutter);
  right: var(--gutter);
  margin: 0;
  max-width: none;
  display: none;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.section-cue.is-on { opacity: 1; }
@media (max-width: 860px) {
  .section-cue { display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .section-cue { transition: none; }
}

/* Atmosphere glows — pure decoration, transform-friendly */
.glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  pointer-events: none;
  z-index: 0;
}
.glow--violet { background: radial-gradient(closest-side, rgba(143, 91, 242, 0.28), transparent 70%); }
.glow--amber { background: radial-gradient(closest-side, rgba(229, 178, 107, 0.12), transparent 70%); }

/* Ghost display type drifting behind content */
.ghost-type {
  position: absolute;
  z-index: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(6rem, 18vw, 17rem);
  letter-spacing: -0.04em;
  white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1px rgba(199, 169, 255, 0.07);
  user-select: none;
  pointer-events: none;
}

/* ---------- Header ---------- */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  transition: border-color 0.4s ease;
  border-bottom: 1px solid transparent;
}
/* The scrolled background and blur live on a pseudo-element, never on the
   header itself: a backdrop-filter makes its element the containing block
   for position:fixed descendants, which trapped the full-screen mobile nav
   inside the 81px header once the page was scrolled. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: color-mix(in srgb, var(--ink-0) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
.site-header.is-scrolled::before { opacity: 1; }
.site-header.is-scrolled { border-bottom-color: var(--line); }
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: 1.1rem;
}
.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.55rem;
  text-decoration: none;
  color: var(--bone);
  font-family: var(--font-display);
  font-size: 1.45rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.brand em {
  font-family: var(--font-accent);
  font-style: normal;
  font-weight: 400;
  color: var(--violet-bright);
}
.brand img {
  height: clamp(26px, 3.5vw, 34px);
  width: auto;
  display: block;
}
/* the header holds only the logo and the burger on phones, so the mark
   can carry more weight there than on desktop */
@media (max-width: 860px) {
  .brand img { height: 42px; }
}
.site-nav ul {
  display: flex;
  gap: clamp(1rem, 2.5vw, 2.4rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.site-nav a {
  font-size: 0.92rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--body);
  padding-block: 0.4rem;
  position: relative;
}
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%;
  bottom: 0;
  height: 1px;
  background: var(--amber);
  transition: right 0.35s var(--ease-out);
}
.site-nav a:hover,
.site-nav a[aria-current="true"] { color: var(--bone); }
.site-nav a:hover::after,
.site-nav a[aria-current="true"]::after { right: 0; }


/* Burger */
.nav-toggle {
  display: none;
  background: none;
  border: 1px solid var(--line);
  color: var(--bone);
  width: 46px;
  height: 46px;
  cursor: pointer;
  position: relative;
  z-index: 110;
}
.nav-toggle span,
.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 12px;
  width: 20px;
  height: 2px;
  background: currentColor;
  transition: transform 0.35s var(--ease-out), opacity 0.25s;
}
.nav-toggle span { top: 22px; }
.nav-toggle span::before { left: 0; top: -6px; }
.nav-toggle span::after { left: 0; top: 6px; }
.nav-toggle[aria-expanded="true"] span { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] span::before { transform: rotate(-90deg) translateX(-6px); }
.nav-toggle[aria-expanded="true"] span::after { opacity: 0; }

/* The one solid element in the bar: the eye files it as the action */
.site-nav .nav-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34em 0.9em 0.34em 0.45em;
  border-radius: 999px;
  background: #05c756;
  color: #fff;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.05em;
}
.site-nav .nav-chip::after { display: none; }
.site-nav .nav-chip:hover { color: #fff; transform: translateY(-1px); }
.site-nav .nav-chip img { height: 22px; width: 22px; }
.nav-chip__sub { display: none; }

@media (max-width: 860px) {
  .nav-toggle { display: block; }
  .site-nav {
    position: fixed;
    inset: 0;
    z-index: 105;
    display: grid;
    align-content: center;
    justify-items: center;
    padding-inline: var(--gutter);
    background: color-mix(in srgb, var(--ink-0) 96%, transparent);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.4s ease, visibility 0s 0.4s;
  }
  .site-nav.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.4s ease;
  }

  /* A ruled list, not a floating stack: each entry gets its own row and its
     own hairline, so the eye counts six destinations instead of reading one
     column of words. */
  .site-nav ul {
    flex-direction: column;
    gap: 0;
    width: min(24rem, 100%);
    text-align: left;
  }
  .site-nav li { border-bottom: 1px solid var(--line); }
  .site-nav li:first-child { border-top: 1px solid var(--line); }

  .site-nav a {
    position: relative;
    display: flex;
    align-items: center;
    padding: 0.72em 0 0.72em 1.1rem;
    font-family: var(--font-display);
    font-style: normal;
    font-weight: 500;
    font-size: var(--step-2);
    line-height: 1.1;
    text-transform: none;
    letter-spacing: -0.01em;
    color: var(--bone);
    opacity: 0;
    transform: translateY(0.7rem);
    transition: opacity 0.45s var(--ease-out), transform 0.45s var(--ease-out), color 0.3s;
  }
  .site-nav.is-open a { opacity: 1; transform: none; }
  .site-nav.is-open li:nth-child(1) a { transition-delay: 0.05s; }
  .site-nav.is-open li:nth-child(2) a { transition-delay: 0.1s; }
  .site-nav.is-open li:nth-child(3) a { transition-delay: 0.15s; }
  .site-nav.is-open li:nth-child(4) a { transition-delay: 0.2s; }
  .site-nav.is-open li:nth-child(5) a { transition-delay: 0.25s; }
  .site-nav.is-open li:nth-child(6) a { transition-delay: 0.3s; }
  .site-nav.is-open li:nth-child(7) a { transition-delay: 0.35s; }

  /* the amber bar of the folds and the chapter marks, reused as the marker */
  .site-nav a::after {
    display: block;
    content: "";
    position: absolute;
    left: 0;
    top: 0.9em;
    bottom: 0.9em;
    right: auto;
    width: 2px;
    height: auto;
    background: var(--amber);
    transform: scaleY(0);
    transform-origin: 50% 50%;
    transition: transform 0.35s var(--ease-out);
  }
  .site-nav a[aria-current="true"] { color: var(--amber); border-bottom: 0; padding-bottom: 0.72em; }
  .site-nav a[aria-current="true"]::after { transform: scaleY(1); }

  /* the door, closing the list */
  .site-nav li.nav-line {
    display: grid;
    justify-items: center;
    gap: 0.55rem;
    margin-top: 1.7rem;
    padding-top: 0;
    border: 0;
    width: 100%;
  }
  .site-nav .nav-chip {
    font-style: normal;
    font-family: var(--font-body);
    font-size: 0.95rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    border-bottom: 0;
    padding: 0.5em 1.2em 0.5em 0.55em;
    opacity: 1;
    transform: none;
  }
  .site-nav .nav-chip::after { display: none; }
  .site-nav .nav-chip img { height: 28px; width: 28px; }
  .nav-chip__sub {
    display: block;
    font-size: 0.64rem;
    font-weight: 600;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: #a99fbb;
    text-align: center;
  }
  @media (prefers-reduced-motion: reduce) {
    .site-nav a { transition: none; }
    .site-nav a::after { transition: none; }
  }
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95em 1.9em;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.3s, color 0.3s, border-color 0.3s, transform 0.3s var(--ease-out);
  will-change: auto;
}
.btn--primary {
  background: var(--violet);
  color: #0f0c13;
}
.btn--primary:hover {
  background: var(--violet-bright);
  color: #0f0c13;
}
.btn--ghost {
  border-color: var(--line);
  color: var(--bone);
  background: transparent;
}
.btn--ghost:hover {
  border-color: var(--violet-bright);
  color: var(--violet-bright);
}
.btn svg { flex: none; }

/* Phones: keep the two hero CTAs on one row as equal columns. They need
   ~419px side by side but a 393px iPhone only offers 353px, so the padding,
   tracking and LINE icon tighten rather than the buttons stacking. */
@media (max-width: 520px) {
  .hero__ctas {
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0.6rem;
  }
  .hero__ctas > * {
    flex: 1 1 0;
    min-width: 0;
  }
  .hero__ctas .btn {
    padding: 0.95em 0.5em;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
    text-align: center;
  }
  .hero__ctas .btn-line {
    justify-content: center;
    padding-right: 0.8em;
    font-size: 0.8rem;
    letter-spacing: 0.02em;
  }
  .hero__ctas .btn-line img { height: 40px; }
}

/* Floating LINE FAB (mobile) */
.line-fab {
  position: fixed;
  right: 1.1rem;
  bottom: 1.1rem;
  z-index: 90;
  display: none;
  border-radius: 999px;
  filter: drop-shadow(0 10px 26px rgba(0, 0, 0, 0.55));
  transition: opacity 0.35s ease, transform 0.35s var(--ease-out);
}
/* Stand down while the hero's own booking button is on screen: it would sit
   on top of it, and a second LINE button there says nothing new. */
.line-fab.is-idle {
  opacity: 0;
  transform: translateY(0.75rem) scale(0.94);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .line-fab { transition: none; }
}
.line-fab img {
  height: 48px;
  width: auto;
  display: block;
}
@media (max-width: 860px) {
  .line-fab { display: block; }
}

/* Official LINE image button (header) */
.line-img-btn {
  display: inline-block;
  border-radius: 999px;
  transition: transform 0.3s var(--ease-out);
}
.line-img-btn:hover { transform: translateY(-2px); }
.line-img-btn img {
  height: 44px;
  width: auto;
  display: block;
}
.line-img-btn--lg img { height: 52px; }

/* LINE-styled action button (official green, custom label) */
.btn-line {
  display: inline-flex;
  align-items: center;
  background: #05c756;
  border-radius: 999px;
  overflow: hidden;
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding-right: 1.5em;
  transition: transform 0.3s var(--ease-out);
}
.btn-line img {
  height: 52px;
  width: auto;
  display: block;
}
.btn-line span { padding-left: 0.35em; }
.btn-line:hover {
  color: #fff;
  transform: translateY(-2px);
}

/* ---------- Hero ----------
   A typographic poster, not a photograph: every venue in this city opens on
   interchangeable flesh, so the original house opens on its name. Type paints
   at 0 ms, which also makes the H1 the LCP element. Photography, when the
   owner has it, joins BEHIND the type inside the arch. Mirror any change here
   into the critical CSS block of index.html. */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: end;
  /* every vertical value answers to viewport height so both CTAs hold above
     the fold on short laptops (1366x768); clamps keep tall screens as-is */
  padding-block: clamp(5.5rem, 24vh - 6rem, 7.5rem) clamp(1.5rem, 6vh - 1.5rem, 3rem);
  overflow: clip;
  isolation: isolate;
}

/* The arch: a suite doorway, lit and empty, bleeding off the right edge.
   The same shape will frame the rails, the video and the LINE door. */
.hero__arch {
  position: absolute;
  z-index: -1;
  right: max(-3rem, -5vw);
  bottom: 8vh;
  /* Sized by HEIGHT at the photograph's own 2:3 ratio, so object-fit: cover
     has nothing left to crop: the subject is always seen head to toe. */
  height: min(80vh, 46rem);
  width: auto;
  aspect-ratio: 2 / 3;
  border: 1px solid color-mix(in srgb, var(--amber) 32%, transparent);
  border-bottom: 0;
  border-radius: 999px 999px 0 0;
  pointer-events: none;
}
/* a flat 20% black veil over the arch, at every screen size */
.hero__arch > .hero__arch-veil {
  content: "";
  position: absolute;
  inset: 0.75rem 0.75rem 0;
  z-index: 1;
  border-radius: inherit;
  background: rgba(0, 0, 0, 0.2);
  pointer-events: none;
}
.hero__arch-img {
  /* the photograph lives BEHIND the type and UNDER the chromotherapy grade:
     the poster stays the first plane, the woman is the room behind it */
  position: absolute;
  inset: 0.75rem 0.75rem 0;
  width: calc(100% - 1.5rem);
  height: calc(100% - 0.75rem);
  object-fit: cover;
  object-position: 50% 26%;
  border-radius: inherit;
  filter: brightness(0.72) saturate(1);
  animation: hero-lights 1.4s var(--ease-out) both;
}
.hero__arch::before {
  /* chromotherapy: a violet field dying into ink, one low amber ember */
  content: "";
  position: absolute;
  inset: 0.75rem 0.75rem 0;
  border-radius: inherit;
  z-index: 1;
  background:
    /* the ink follows the copy band instead of sweeping the whole frame:
       she stays lit from the crown down to her face, the text sits on ink */
    linear-gradient(to bottom, transparent 26%, rgba(15, 12, 19, 0.5) 46%,
                    rgba(15, 12, 19, 0.66) 64%, rgba(15, 12, 19, 0.72)),
    radial-gradient(120% 90% at 50% 26%, rgba(143, 91, 242, 0.26), transparent 64%),
    radial-gradient(60% 34% at 50% 96%, rgba(229, 178, 107, 0.14), transparent 70%);
  animation:
    hero-lights 1.4s var(--ease-out) both,
    hero-breathe 8s ease-in-out 1.4s infinite alternate;
}

.hero__title {
  --hero-roman: min(var(--step-5), 11vh);
  max-width: 14ch;
  margin-bottom: var(--space-3);
  font-size: var(--hero-roman);
  line-height: 1.02;
}
.hero__title > span { display: block; }
.hero__kicker {
  margin-bottom: 0.9rem;
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--amber);
}
.hero__line--amp {
  /* the three lines of the H1 are one block: same family, size and colour */
  color: var(--bone);
}
.hero__place {
  color: var(--bone);
}

.hero__intro {
  max-width: 46ch;
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--bone);
}
.hero__sub { max-width: 52ch; }
.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: clamp(1.25rem, 4.5vh - 1.5rem, 1.75rem);
}

/* entrance: the H1 roman line never animates, so first paint IS the poster */
.hero__intro, .hero__sub, .hero__ctas {
  animation: hero-rise 0.7s var(--ease-out) both;
}
.hero__intro { animation-delay: 0.15s; }
.hero__sub { animation-delay: 0.25s; }
.hero__ctas { animation-delay: 0.4s; }

@keyframes hero-lights { from { opacity: 0; } to { opacity: 1; } }
@keyframes hero-breathe { from { opacity: 1; } to { opacity: 0.72; } }
@keyframes hero-rise { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }
/* On narrow screens the copy column crosses the arch; rather than crushing
   the exposure, the arch rises behind the title and dissolves into ink before
   the paragraph band begins. Geometry solves what filters could not. */
/* Desktop: the doorway sits beside the copy, not pinned to the far edge —
   a column of text and a lit doorway a few centimetres apart read as one
   composition; separated by half a screen they read as two accidents. */
@media (min-width: 1061px) {
  .hero__arch {
    right: auto;
    left: min(58rem, 61vw);
  }
}

/* Phones: the copy block is centred between the header and the foot of the
   hero rather than sitting on the floor, and the title breaks after Nuru. */
@media (max-width: 1060px) {
  .hero {
    align-items: center;
    padding-block: calc(46px + 2.2rem + 2vh) clamp(1.5rem, 6vh - 1.5rem, 3rem);
  }
  .hero__title { max-width: 9ch; }
}

/* The corridor, desktop only: two ghost doorways in plain hairline behind
   the lit one, and a floor line the arches stand on. Same shape, no new
   colour — structure, not decoration. */
.hero__floor { display: none; }
.arch-ring { display: none; }
@media (min-width: 1061px) {
  /* Concentric doorways radiating from the lit arch: same base line, same
     centre, growing and fading outward until they sweep the whole hero.
     They live inside the arch, so they follow it at every viewport. */
  .arch-ring {
    display: block;
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    z-index: -1;
    aspect-ratio: 2 / 3;
    border: 1px solid color-mix(in srgb, var(--violet-bright) 50%, transparent);
    border-bottom: 0;
    border-radius: 999px 999px 0 0;
    pointer-events: none;
  }
  .arch-ring:nth-of-type(1) { height: 116%; }
  .arch-ring:nth-of-type(2) { height: 138%; border-color: color-mix(in srgb, var(--violet-bright) 38%, transparent); }
  .arch-ring:nth-of-type(3) { height: 166%; border-color: color-mix(in srgb, var(--violet-bright) 27%, transparent); }
  .arch-ring:nth-of-type(4) { height: 204%; border-color: color-mix(in srgb, var(--violet-bright) 18%, transparent); }
  .arch-ring:nth-of-type(5) { height: 254%; border-color: color-mix(in srgb, var(--violet-bright) 11%, transparent); }

  .hero__floor {
    display: block;
    position: absolute;
    /* above the arch and its video, which reach the same baseline and were
       cutting the line wherever the doorway stood */
    z-index: 1;
    left: 0;
    right: 0;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg,
      transparent,
      color-mix(in srgb, var(--line) 90%, transparent) 28%,
      color-mix(in srgb, var(--amber) 80%, transparent) 76%,
      color-mix(in srgb, var(--amber) 40%, transparent));
    /* lifted glow so the line reads even when it sits on the last pixel row */
    box-shadow: 0 -6px 18px -6px color-mix(in srgb, var(--amber) 30%, transparent);
    pointer-events: none;
  }
}

/* Desktop: the doorway runs from its crown to the floor of the hero, so it
   reads as an opening in the wall rather than a framed object floating in it.
   Height drives the box; the 2:3 ratio widens it to match. */
@media (min-width: 1061px) {
  .hero__arch {
    bottom: 0;
    height: min(88vh, 54rem);
  }
}

@media (max-width: 1060px) {
  .hero__arch {
    /* only the very foot of the doorway dissolves into the section below;
       readability is carried by the ink veil, not by hiding her legs */
    height: min(62vh, 32rem);
    -webkit-mask-image: linear-gradient(to top, transparent 2%, #000 16%);
    mask-image: linear-gradient(to top, transparent 2%, #000 16%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero__arch-img,
  .hero__arch::before,
  .hero__intro, .hero__sub, .hero__ctas { animation: none; }
}

/* ---------- Story / origin section ---------- */
/* ---------- Pinned deck: scroll advances three cards in place ---------- */
/* ---------- The fan ----------
   The deck used to pin the viewport and spend the visitor's scroll on three
   marketing bullets. Now it is a hand of cards he deals himself: tap and the
   top card flies off, the next rises. The site's first interaction that the
   visitor causes. */
.fan {
  width: min(100%, 34rem);
  margin-top: var(--space-5);   /* a block under its intro, like every other */
  cursor: grab;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.fan__hint {
  margin: var(--space-2) 0 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}
@media (min-width: 1061px) and (pointer: fine) { .fan__hint { display: none; } }
.deck {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
}
.deck__card {
  grid-area: 1 / 1;
  transform-origin: 50% 120%;
  transition: transform 0.5s var(--ease-out), opacity 0.35s ease;
  touch-action: pan-y;   /* vertical scroll still belongs to the page */
}
.deck__card.is-top { z-index: 3; }
.deck__card.is-mid { z-index: 2; transform: rotate(-2.5deg) translate(-0.5rem, 0.5rem) scale(0.985); }
.deck__card.is-back { z-index: 1; transform: rotate(2.5deg) translate(0.5rem, 0.95rem) scale(0.97); }
/* while a finger is down the card follows it, so no transition fights the drag */
.deck__card.is-dragging { transition: none; z-index: 5; cursor: grabbing; }
.deck__card.is-out-right { z-index: 4; transform: translateX(130%) rotate(16deg); opacity: 0; }
.deck__card.is-out-left  { z-index: 4; transform: translateX(-130%) rotate(-16deg); opacity: 0; }
.deck__inner {
  /* Pastel celadon: the complement of the violet ground, so the hand of cards
     reads as paper laid on the room rather than another panel of the wall. */
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  background:
    radial-gradient(130% 100% at 88% -15%, rgba(255, 255, 255, 0.5), transparent 58%),
    linear-gradient(158deg, var(--paper-1), var(--paper-2));
  box-shadow:
    0 40px 70px -30px rgba(0, 0, 0, 0.75),
    0 0 60px -18px rgba(143, 91, 242, 0.3);
}
.deck__card h3 { color: var(--paper-ink); }
.deck__card p { color: var(--paper-body); }
.deck__card a { color: var(--violet-deep); }
.deck__rule { background: #b07d2a; }
.deck__rule {
  display: block;
  width: 2.4rem;
  height: 2px;
  background: var(--amber);
  margin-bottom: var(--space-3);
}
.deck__inner::before {
  content: "";
  position: absolute;
  top: -5rem;
  right: -5rem;
  width: 14rem;
  height: 14rem;
  border-radius: 50%;
  background: repeating-radial-gradient(circle,
    transparent 0 14px,
    rgba(29, 43, 38, 0.07) 14px 15px);
  pointer-events: none;
}
.deck__card h3 {
  font-size: var(--step-2);
  max-width: 14ch;
  margin-bottom: var(--space-2);
}
.deck__card p {
  margin: 0;
  color: var(--paper-body);   /* the cards are pastel paper, not the dark ground */
  line-height: 1.65;
  max-width: 46ch;
}
.fan__dots {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  margin: var(--space-3) 0 0;
}
.fan__dots i {
  width: 1.6rem;
  height: 2px;
  background: var(--line);
  transition: background 0.3s;
}
.fan__dots i.is-on { background: var(--amber); }

/* Desktop: the fan opens flat into three columns, nothing to tap */
/* Wide AND mouse-driven. Width alone was wrong: an iPad Pro is 1194px in
   landscape, 1366px on the 12.9", so tablets fell through to the flat grid and
   lost the swipe. A touch device keeps the hand of cards at any width. */
@media (min-width: 1061px) and (pointer: fine) {
  .fan { width: 100%; cursor: default; }
  .deck { grid-template-columns: repeat(3, 1fr); gap: var(--space-3); }
  .deck__card { grid-area: auto; transform: none !important; opacity: 1 !important; }
  .fan__dots { display: none; }
}
/* No JS: plain stacked cards */
html:not(.js) .deck { grid-template-columns: 1fr; gap: var(--space-3); }
html:not(.js) .deck__card { grid-area: auto; }
html:not(.js) .fan__dots { display: none; }
/* ---------- One-shot swipe hint ----------
   The top card begins a gesture and returns without being dealt, so a visitor
   who has never met a deck learns there is more than one card. The numbers are
   the real drag's own ratio, not invented: it tilts 12deg per 160px, so a 48px
   nudge is 3.6deg and opacity 0.895. What the finger would do, in miniature. */
@keyframes deck-hint {
  0%    { transform: translateX(0) rotate(0deg); opacity: 1; }
  24%   { transform: translateX(48px) rotate(3.6deg); opacity: 0.895; }
  32%   { transform: translateX(48px) rotate(3.6deg); opacity: 0.895; }
  74%   { transform: translateX(0) rotate(0deg); opacity: 1; }
  100%  { transform: translateX(0) rotate(0deg); opacity: 1; }
}
/* 760ms: the 560ms gesture then 200ms of stillness, so the two passes read
   as two separate nudges rather than one long wobble. */
.deck__card.is-top.is-hint {
  animation: deck-hint 760ms cubic-bezier(0.16, 1, 0.3, 1) 2 both;
  z-index: 4;
}

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


/* ---------- Pull quote ---------- */
.pull-quote {
  font-family: var(--font-accent);
  font-style: normal;
  font-variation-settings: "opsz" 36;
  font-weight: 400;
  font-size: var(--step-3);
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--bone);
  max-width: 24ch;
  margin: var(--space-5) auto;
  text-align: center;
  position: relative;
  z-index: 1;
}
.pull-quote::before {
  content: "“";
  color: var(--amber);
}
.pull-quote::after {
  content: "”";
  color: var(--amber);
}

/* ---------- Services ---------- */
.service-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* a tight gutter: the wrap is fixed, so every pixel it gives up goes
     straight into the width of the two cards */
  gap: var(--space-5) var(--space-4);
  align-items: start;
  margin-block: var(--space-5);
}
@media (max-width: 860px) {
  /* phones: one column, opened by the VIP suite loop (the wrapper divs
     dissolve so the figure can climb above the nuru card). The video and the
     two cards read as one stack, hence the tighter step between them; the
     block keeps the site's own step to the prose above and below. */
  .service-split {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }
  .service-split > div { display: contents; }
  .service-split .scene { order: -1; }
}
/* Service headings: Nuru Massage in Pattaya / Soapy Massage in Pattaya.
   Default h3 styling otherwise.

   "in Pattaya" is a span so the two headings break at the same word on narrow
   screens. Left to itself only the longer of the two wrapped, which left the
   pair sitting at different heights. */
.service-title__loc { white-space: nowrap; }
@media (max-width: 520px) {
  .service-title__loc { display: block; }
}
.service-tagline {
  /* same face as the 1. / 2. numerals, with the fold panels' side bar.
     opsz is pinned low so Bodoni's hairlines stay solid at this size. */
  position: relative;
  padding-left: 1.5rem;
  font-family: var(--font-accent);
  font-style: normal;
  font-variation-settings: "opsz" 12;
  font-weight: 400;
  font-size: var(--step-1);
  line-height: 1.45;
  letter-spacing: 0.005em;
  color: var(--amber);
  margin-bottom: var(--space-4);
}
.service-tagline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3rem;
  bottom: 0.3rem;
  width: 2px;
  background: linear-gradient(to bottom, var(--amber), var(--violet));
}

/* ---------- Fold disclosures (Services) ---------- */
.fold {
  border-top: 1px solid var(--line);
}
.fold:last-child { border-bottom: 1px solid var(--line); }
.fold__q {
  margin: 0;
  /* clearly subordinate to the h3 above it, still well clear of body size */
  font-size: clamp(1.05rem, 0.99rem + 0.3vw, 1.2rem);
  letter-spacing: 0;
}
.fold__btn {
  all: unset;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding: 1.05rem 0.2rem;
  font: inherit;
  color: var(--bone);
  cursor: pointer;
  transition: color 0.3s;
}
/* No hover treatment on the fold titles: violet read as a link, the amber
   underline was tried and dropped. The +/- mark carries the affordance. */
.fold__btn:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
  border-radius: 2px;
}
.fold__mark {
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
}
.fold__mark::before,
.fold__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  background: var(--amber);
  transition: transform 0.5s var(--ease-out);
}
.fold__mark::before { width: 14px; height: 1.5px; }
.fold__mark::after { width: 1.5px; height: 14px; }
.fold.is-open .fold__mark::before { transform: rotate(180deg); }
.fold.is-open .fold__mark::after { transform: rotate(90deg); }

/* closed by default only when JS is there to open it */
.js .fold__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.65s var(--ease-out);
}
.js .fold.is-open .fold__panel { grid-template-rows: 1fr; }
.fold__inner {
  overflow: hidden;
  min-height: 0;
  position: relative;
  padding-left: 1.5rem;
}
.fold__bar {
  position: absolute;
  left: 0;
  top: 0.35rem;
  bottom: 1.2rem;
  width: 2px;
  background: linear-gradient(to bottom, var(--amber), var(--violet));
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.8s var(--ease-out) 0.12s;
}
.fold.is-open .fold__bar { transform: scaleY(1); }
.fold__inner p {
  margin: 0.2rem 0 1.4rem;
  opacity: 0;
  transform: translateY(16px);
  filter: blur(5px);
  transition:
    opacity 0.55s ease 0.1s,
    transform 0.65s var(--ease-out) 0.1s,
    filter 0.55s ease 0.1s;
}
.fold.is-open .fold__inner p {
  opacity: 1;
  transform: none;
  filter: none;
}
html:not(.js) .fold__bar { transform: none; }
html:not(.js) .fold__inner p { opacity: 1; transform: none; filter: none; }

/* ---------- Curtains: sections that open on their own title ----------
   Closed on arrival, so the page reads as a short list of chapters instead of
   thirty screens of scrolling. Bare by default: the section keeps its chapter
   label and heading exactly where it had them, and the amber SHOW DETAILS door
   under the title carries the whole affordance. Nothing is removed from the
   document: crawlers still read the copy, only the scroll is spared. */
.curtain {
  position: relative;
  z-index: 2;                       /* clears the ghost display type */
}
.curtain__head { position: relative; cursor: pointer; }
.curtain__h { margin-bottom: 0; }
.curtain__btn {
  all: unset;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
/* the click target is the whole header, not just the words of the title */
.curtain__btn::after { content: ""; position: absolute; inset: 0; }
.curtain__btn:focus-visible::after {
  outline: 2px solid var(--amber);
  outline-offset: 4px;
  border-radius: 4px;
}

/* closed by default only when JS is there to open it again */
.js .curtain__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.7s var(--ease-out);
}
.js .curtain.is-open .curtain__panel { grid-template-rows: 1fr; }
/* no vertical padding here: with border-box a padding floor would hold the
   clipped panel open by its own padding height */
.curtain__inner {
  overflow: hidden;
  min-height: 0;
}
.curtain__inner > :first-child { margin-top: var(--space-3); }
/* inside a card the tagline is a header line, not a section opener: the
   space under it matches the 1.4rem above instead of the open-page 3rem */
.curtain__inner .service-tagline { margin-bottom: 1.4rem; }

/* These cards wear the journal's post-card clothes instead: same ground,
   hairline, 6px radius, and the amber SHOW DETAILS door. Closed they are the
   title and the door, nothing else; the rest waits inside the panel. */
.curtain--card {
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--ink-2);
  transition: transform 0.35s var(--ease-out), border-color 0.35s, box-shadow 0.35s;
}
.curtain--card:not(.is-open):hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--amber) 40%, transparent);
  box-shadow: 0 30px 54px -26px rgba(0, 0, 0, 0.95), 0 0 44px -26px rgba(143, 91, 242, 0.5);
}
.curtain--card + .curtain--card { margin-top: var(--space-3); }
.curtain--card .curtain__head { padding: var(--space-3); }
.curtain--card .curtain__inner { padding-inline: var(--space-3); }
.curtain--card.is-open .curtain__inner { border-top: 1px solid var(--line); }
.curtain--card .curtain__inner > :first-child { margin-top: 1.4rem; }
.curtain--card .curtain__inner > :last-child { margin-bottom: 1.6rem; }
.curtain--card .curtain__btn:focus-visible::after { outline-offset: -4px; border-radius: 6px; }
/* a card title is a card title whatever its rank: the h2 of The Setting comes
   down to the same step as the h3 titles of the service cards */
.curtain--card .curtain__h { font-size: var(--step-2); line-height: 1.15; }
.curtain__more {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin: var(--space-2) 0 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
}
.curtain__more-rule {
  width: 1.6rem;
  height: 1px;
  background: currentColor;
  transition: width 0.35s var(--ease-out);
}
.curtain--card:hover .curtain__more-rule { width: 2.4rem; }
.curtain__more-close { display: none; }
.curtain--card.is-open .curtain__more-open { display: none; }
.curtain--card.is-open .curtain__more-close { display: inline; }
@media (prefers-reduced-motion: reduce) {
  .curtain--card, .curtain__more-rule { transition: none; }
}
/* no JS, no folding: the door would be a lie */
html:not(.js) .curtain__more { display: none; }

/* ---------- The line-up call, treated as a small hero ----------
   This is where the reader decides to add us: the daily line-up is the one
   thing the site cannot show and LINE can. So it gets display type, its own
   ruled band and the button as the focal point, rather than a paragraph with
   a link buried in it. The two blog links stay, small, under the button. */
.cta-band {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: var(--space-3);
  margin-block: var(--space-5);
  padding-block: var(--space-4);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.cta-band__line {
  margin: 0;
  max-width: 22ch;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--step-3);
  line-height: 1.08;
  letter-spacing: 0.01em;
  color: var(--bone);
  text-wrap: balance;
}
/* The answer, in the amber the site uses for what it wants you to do. A block
   of its own, held off the question by the same step the band puts between
   the words and the button, so the two verses breathe alike. */
.cta-band__line em {
  display: block;
  margin-top: var(--space-3);
  font-style: normal;
  color: var(--amber);
}
.cta-band__note {
  margin: 0;
  max-width: none;
  font-size: var(--step--1);
  color: var(--muted);
}
.cta-band__note a { color: var(--body); }
.cta-band__note a:hover { color: var(--bone); }

/* ---------- Scene loop (phones only) ---------- */
/* Hidden above 860px and, crucially, given no sources there: main.js attaches
   them at runtime only when the query matches, so desktop downloads nothing. */
.scene { display: none; }
@media (max-width: 860px) {
  .scene {
    /* the frame, scrim and caption come from the shared rail-card treatment;
       no own margin: the service-split grid gap spaces it from the cards */
    display: block;
    width: 100%;
    max-width: var(--measure);
    margin: 0;
  }
  .scene video {
    width: 100%;
    height: auto;
    display: block;
  }
}

/* Price table */
.price-list {
  /* symmetric: the gap under the table matches the one above it */
  margin-block: var(--space-3);
  position: relative;
  z-index: 1;
}
.price-row {
  display: grid;
  /* name + price on one line, duration and room underneath, at every width */
  grid-template-columns: 1fr auto;
  gap: 0.4rem var(--space-3);
  align-items: baseline;
  padding: 1.3rem 1.1rem;
  border-top: 1px solid var(--line);
  position: relative;
  overflow: hidden;
  transition: transform 0.4s var(--ease-out);
}
.price-row:last-child { border-bottom: 1px solid var(--line); }
.price-row::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(60% 130% at var(--mx, 20%) 0%, rgba(143, 91, 242, 0.16), transparent 70%);
  opacity: 0;
  transition: opacity 0.4s, transform 0.6s var(--ease-out);
  pointer-events: none;
}
.price-row:hover { transform: translateY(-3px); }
.price-row:hover::before { opacity: 1; transform: translateX(8%); }
.price-row__name {
  font-family: var(--font-body);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--bone);
  letter-spacing: -0.01em;
}
.price-row__detail {
  grid-column: 1 / -1;
  grid-row: 2;
  color: var(--muted);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* always flush right, so descriptions of different lengths end on the
     same edge and wrapped lines stay aligned */
  text-align: right;
}
.price-row__price {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--step-1);
  line-height: inherit;
  letter-spacing: -0.01em;
  color: var(--amber);
  font-variant-numeric: tabular-nums;
}
/* the Signature keeps the display treatment: one price is the offer */
.price-row--signature .price-row__price {
  font-family: var(--font-accent);
  font-weight: 500;
  font-size: var(--step-2);
  line-height: 1;
}
/* The whisper: the one place the site sells the sessions, not the venue */
.price-row__whisper {
  display: block;
  margin-top: 0.4em;
  max-width: 34ch;
  font-family: var(--font-accent);
  font-style: normal;
  font-variation-settings: "opsz" 14;
  font-weight: 400;
  font-size: var(--step-0);
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--muted);
}
.price-row--signature .price-row__whisper { color: #a99fbb; }


.price-row__ask {
  grid-column: 1 / -1;
  justify-self: start;
  margin-top: 0.5rem;
  padding: 0.6em 1.2em;
  border: 1px solid color-mix(in srgb, var(--amber) 55%, transparent);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--amber);
  transition: border-color 0.3s, color 0.3s;
}
.price-row__ask:hover { border-color: var(--amber); color: var(--bone); }

/* Narrow screens: three columns leave ~90px each, which shreds both the
   name and the description. Stack instead: name and price on one line,
   description on its own line underneath, still flush right. */
@media (max-width: 760px) {
  .price-row {
    grid-template-columns: 1fr auto;
    gap: 0.4rem var(--space-2);
  }
  }

.price-row--signature {
  background: linear-gradient(120deg, rgba(91, 46, 168, 0.34), rgba(31, 24, 38, 0.6));
  border: 1px solid color-mix(in srgb, var(--violet) 45%, transparent);
  margin-block: -1px;
  padding-block: 1.9rem;
}

/* ---------- NH seal: the monogram assembling under the deck ----------
   Three concentric rings sit on their own layers so the scroll loop can drift
   them independently (depth) while the rings themselves run their entrance
   keyframes. Two elements per ring means the two transforms never collide. */
/* Its own beat in the scroll: the deck finishes, this arrives alone on
   screen, then the next section. Centred inside the block so the gap above
   and below reads the same. */
.seal-block {
  display: grid;
  place-items: center;
  padding-block: var(--space-3);
  margin-bottom: calc(-1 * var(--space-6));
}

/* The medal opens full screen and shrinks to its resting size as the visitor
   scrolls. The block is made tall and its content pinned, so the page holds
   still for the length of the zoom and then carries on. Only the medal is
   scaled; the rings and the orbit keep their own drift. */
.js .seal-block { height: 200vh; align-content: start; }
.js .seal-sticky {
  position: sticky;
  top: 0;
  min-height: 100vh;
  display: grid;
  place-items: center;
  align-content: center;
}
/* The reveal keyframes are declared later and more specifically, on
   .js .seal.is-in .seal__medal, and they run with fill: both. Their final frame
   writes transform: none, which outranks an inline style, so the zoom below
   would never show. This is the one place that earns an !important. */
.js .seal__medal { animation: none !important; opacity: 1 !important; will-change: transform; }
.seal__caption span { display: block; }
.seal__caption {
  margin: 0.9rem 0 0;
  line-height: 1.9;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}
.seal {
  --medal: clamp(48px, 6vw, 68px);
  display: grid;
  place-items: center;
  height: calc(var(--medal) * 3.2);
  isolation: isolate;
  pointer-events: none;
}
.seal > * { grid-area: 1 / 1; }
.seal__layer { display: grid; place-items: center; }
.seal__glow {
  width: calc(var(--medal) * 2.7);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(143, 91, 242, 0.45), transparent 70%);
  filter: blur(24px);
  z-index: 0;
}
.seal__ring {
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1px solid rgba(199, 169, 255, 0.3);
  z-index: 1;
}
.seal__ring--1 { width: calc(var(--medal) * 1.5); }
.seal__ring--2 {
  width: calc(var(--medal) * 2.15);
  border-style: dashed;
  border-color: rgba(199, 169, 255, 0.22);
}
.seal__ring--3 {
  width: calc(var(--medal) * 2.95);
  border-color: color-mix(in srgb, var(--amber) 30%, transparent);
}
/* a single amber point orbiting the middle ring: the small expensive detail */
.seal__orbit {
  position: relative;
  width: calc(var(--medal) * 2.15);
  aspect-ratio: 1;
  z-index: 2;
  animation: seal-orbit 16s linear infinite;
}
.seal__orbit i {
  position: absolute;
  top: -3px;
  left: 50%;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 12px var(--amber);
}
@keyframes seal-orbit { to { transform: rotate(360deg); } }
.seal__medal {
  width: var(--medal);
  aspect-ratio: 1;
  z-index: 3;
  border-radius: 50%;
  box-shadow: 0 0 34px -6px rgba(143, 91, 242, 0.75);
}
.seal__medal img { width: 100%; height: auto; border-radius: 50%; }

/* entrance: the medal lands first, the rings bloom outwards behind it */
.js .seal__medal,
.js .seal__ring,
.js .seal__glow { opacity: 0; }
.js .seal.is-in .seal__medal { animation: seal-medal 0.9s var(--ease-out) both; }
.js .seal.is-in .seal__glow { animation: seal-glow 1.4s ease both 0.1s; }
.js .seal.is-in .seal__ring { animation: seal-ring 1.2s var(--ease-out) both; }
.js .seal.is-in .seal__ring--2 { animation-delay: 0.14s; }
.js .seal.is-in .seal__ring--3 { animation-delay: 0.28s; }
@keyframes seal-medal {
  from { opacity: 0; transform: scale(0.42) rotate(-16deg); }
  to   { opacity: 1; transform: none; }
}
@keyframes seal-ring {
  from { opacity: 0; transform: scale(0.35); }
  to   { opacity: 1; transform: none; }
}
@keyframes seal-glow {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .seal__orbit { animation: none; }
  .js .seal__medal,
  .js .seal__ring,
  .js .seal__glow { opacity: 1; animation: none !important; }
  .seal__layer { transform: none !important; }
}

/* ---------- Team rail ---------- */
.rail-wrap { position: relative; }
.rail-sticky { position: relative; }
.rail-track {
  display: flex;
  gap: clamp(1rem, 2.5vw, 2rem);
  padding-inline: var(--gutter);
}
/* Photographs are treated as framed prints: raised off the ground with a
   diffuse shadow, matted by an inset hairline, and graded toward the brand
   violet so the blue-lit interiors sit inside the palette. Everything that
   moves is opacity or inset, never a transform, because the rail already
   writes transforms to these elements on every frame. */
.rail-card { flex: 0 0 auto; }
.rail-card,
.scene {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-2);
  box-shadow:
    0 34px 64px -30px rgba(0, 0, 0, 0.9),
    0 0 48px -22px rgba(143, 91, 242, 0.4),
    inset 0 1px 0 rgba(239, 233, 231, 0.12);
}
/* The doorway is earned, not uniform: only the rail whose photographs fit
   the crown carries the arch. */
.rail-wrap--arch .rail-card {
  border-radius: 999px 999px 0 0;
  border: 1px solid color-mix(in srgb, var(--amber) 26%, transparent);
}

/* Card format is a variable so a rail can carry a different one; the mobile
   height cap below reads the same numbers. */
.rail-wrap { --card-w: 3; --card-h: 4; }
.rail-wrap[data-rail-ratio="2:3"] { --card-w: 2; --card-h: 3; }
.rail-wrap[data-rail-ratio="4:5"] { --card-w: 4; --card-h: 5; }
.rail-card :is(img, video) {
  width: 100%;
  aspect-ratio: var(--card-w) / var(--card-h);
  object-fit: cover;
  /* --zoom / --ty are set inline per photo so each subject reads at the same
     scale with head and feet inside the frame. The rail rewrites this same
     transform every frame, keeping the two in sync. */
  transform: translateY(var(--ty, 0%)) scale(var(--zoom, 1.08));
}
/* violet grade + scrim that keeps the caption legible over any photo */
.rail-card::after,
.scene::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* darkest across the caption band only; the very bottom stays lighter so
     the feet still read now that the subjects are framed head to toe */
  background:
    linear-gradient(to top,
      rgba(15, 12, 19, 0.42) 0%,
      rgba(15, 12, 19, 0.82) 7%,
      rgba(15, 12, 19, 0.72) 17%,
      rgba(15, 12, 19, 0.3) 30%,
      transparent 55%),
    linear-gradient(155deg, rgba(143, 91, 242, 0.3), transparent 62%);
  transition: opacity 0.6s var(--ease-out);
}
/* the mat: a hairline held off the edge, drawing in on hover */
.rail-card::before,
.scene::before {
  content: "";
  position: absolute;
  inset: 0.75rem;
  z-index: 2;
  pointer-events: none;
  border: 1px solid rgba(239, 233, 231, 0.3);
  transition: inset 0.6s var(--ease-out), border-color 0.5s ease;
}
/* The one card holding a video, not a photograph. Its mat is gold and thick
   from the outset instead of waiting for a hover that never comes on a phone,
   so the eye is already on it when the loop turns up. The glow is the amber
   used everywhere else, not a new colour. */
.rail-card:has(video)::before {
  inset: 0.45rem;
  border-width: 2px;
  border-color: color-mix(in srgb, var(--amber) 92%, transparent);
  box-shadow:
    0 0 10px color-mix(in srgb, var(--amber) 55%, transparent),
    0 0 26px color-mix(in srgb, var(--amber) 28%, transparent),
    inset 0 0 14px color-mix(in srgb, var(--amber) 20%, transparent);
}
/* the mat is a rectangle by default; on the arched rail it has to take the
   crown or the glow gets sliced flat across the top */
.rail-wrap--arch .rail-card:has(video)::before { border-radius: 999px 999px 0 0; }
/* the card outline itself steps up to match */
.rail-wrap--arch .rail-card:has(video) {
  border-color: color-mix(in srgb, var(--amber) 55%, transparent);
}

/* The same reveal on both inputs: hover on desktop, tap on touch screens,
   where `hover: hover` never matches and the effect was simply unreachable. */
@media (hover: hover) {
  .rail-card:hover::after,
  .scene:hover::after { opacity: 0.55; }
  .rail-card:hover::before,
  .scene:hover::before {
    inset: 0.45rem;
    border-color: color-mix(in srgb, var(--amber) 70%, transparent);
  }
}
.rail-card.is-active::after,
.scene.is-active::after { opacity: 0.55; }
.rail-card.is-active::before,
.scene.is-active::before {
  inset: 0.45rem;
  border-color: color-mix(in srgb, var(--amber) 70%, transparent);
}
/* Artwork rails carry finished compositions with their own typography and a
   footer URL, so the scrim and caption are dropped: they would sit on top of
   the design. The frame, shadow and glow stay. */
.rail-wrap[data-rail-style="art"] .rail-card::after { content: none; }

.rail-card figcaption,
.scene figcaption {
  position: absolute;
  left: 1.5rem;
  right: 1.5rem;
  bottom: 1.35rem;
  z-index: 3;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  padding-top: 0.7rem;
  border-top: 1px solid color-mix(in srgb, var(--amber) 60%, transparent);
}
@media (prefers-reduced-motion: reduce) {
  .rail-card::before, .scene::before,
  .rail-card::after, .scene::after { transition: none; }
}

/* Vertical scroll drives horizontal travel — all devices (JS sets transforms).
   The sticky block hugs its content: identical --rail-gap above and below
   the cards on every screen size (JS centers it in the viewport while pinned). */
:root { --rail-gap: 2rem; }
.js .rail-wrap { height: 243vh; }   /* travel = height - 100vh. 100vh / 0.7 = 143vh,
                                        which is what makes the run 30% slower, not 130vh */
.js .rail-sticky {
  position: sticky;
  top: 15svh; /* refined by JS to true vertical center */
  padding-block: var(--rail-gap);
  overflow-x: clip;
}
#team > .wrap p:last-of-type { margin-bottom: 0; }
.rail-card { flex-basis: clamp(280px, 32vw, 440px); }
@media (max-width: 860px) {
  .js .rail-wrap { height: 214vh; }   /* 114vh of travel: 80vh / 0.7. Stretching the scroll
                                        by 30% only slows it by 23%, the inverse is needed */
  .rail-card {
    /* one card per screen, matched to the width of the text column above.
       The second term caps it so a landscape phone, where height is scarce,
       never makes the 3:4 card taller than the pinned block. */
    flex-basis: min(
      calc(100vw - 2 * var(--gutter)),
      calc((100svh - 9rem) * var(--card-w) / var(--card-h))
    );
  }
}

/* No-JS / reduced motion: native snap carousel */
.rail-track-scroller { overflow: visible; }
html:not(.js) .rail-track-scroller,
.rail-track-scroller.is-carousel {
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding-block: var(--space-2);
}
html:not(.js) .rail-track-scroller::-webkit-scrollbar,
.rail-track-scroller.is-carousel::-webkit-scrollbar { display: none; }
.rail-card { scroll-snap-align: start; }



/* ---------- The door ----------
   The corridor's last frame: the same arch, empty this time, with the LINE
   button standing in the doorway. Every arch before it held a preview; this
   one the visitor has to open himself. */
.door {
  /* The price list is meant to read as an ending, so the door stands as far
     off it as one section stands from the next: a section's bottom padding
     plus the next one's top padding, which is exactly twice --space-6. */
  margin-top: calc(2 * var(--space-6));
  text-align: center;
}
.door__title {
  font-family: var(--font-accent);
  font-style: normal;
  font-variation-settings: "opsz" 60;
  font-weight: 500;
  font-size: var(--step-3);
  color: var(--bone);
  margin-bottom: var(--space-4);
}
.door__list {
  list-style: none;
  margin: 0 auto var(--space-5);
  padding: 0;
  max-width: 44ch;
}
.door__list li {
  padding: 1.2rem 0;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
}
.door__list li:last-child { border-bottom: 1px solid var(--line); }
.door__list strong {
  display: block;
  margin-bottom: 0.3em;
  color: var(--bone);
  font-weight: 600;
  font-size: var(--step-1);
  letter-spacing: normal;
}
.door__arch {
  position: relative;
  justify-items: center;
  width: min(19rem, 78vw);
  aspect-ratio: 3 / 4;
  margin-inline: auto;
  display: grid;
  place-content: center;
  border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
  border-bottom: 0;
  border-radius: 999px 999px 0 0;
}
.door__arch::before {
  content: "";
  position: absolute;
  inset: 0.75rem 0.75rem 0;
  border-radius: inherit;
  background:
    radial-gradient(110% 80% at 50% 34%, rgba(143, 91, 242, 0.16), transparent 64%),
    radial-gradient(60% 30% at 50% 98%, rgba(229, 178, 107, 0.12), transparent 70%);
  pointer-events: none;
}
.door__arch .line-img-btn {
  justify-self: center;
  animation: door-breathe 4s ease-in-out infinite alternate;
}
.door__note { grid-column: 1; }
@keyframes door-breathe { from { opacity: 1; } to { opacity: 0.82; } }
.door__note {
  margin: 1.1rem 0 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #a99fbb;
}
@media (prefers-reduced-motion: reduce) {
  .door__arch .line-img-btn { animation: none; }
}

/* ---------- Facilities scissor bands ---------- */
.facility-band {
  display: flex;
  gap: var(--space-4);
  align-items: center;
  margin-block: var(--space-5);
}
.facility-band--reverse { flex-direction: row-reverse; }
@media (max-width: 860px) {
  .facility-band, .facility-band--reverse { flex-direction: column; align-items: flex-start; }
}
.facility-band__media {
  /* same framed-print treatment as the team rail cards */
  position: relative;
  flex: 0 0 54%;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-2);
  box-shadow:
    0 34px 64px -30px rgba(0, 0, 0, 0.9),
    0 0 48px -22px rgba(143, 91, 242, 0.4),
    inset 0 1px 0 rgba(239, 233, 231, 0.12);
}
.facility-band__media { margin: 0; }
.facility-band__media img { width: 100%; display: block; }
.facility-band__media figcaption {
  position: absolute;
  left: 1.5rem;
  right: 1.5rem;
  bottom: 1.35rem;
  z-index: 3;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  padding-top: 0.7rem;
  border-top: 1px solid color-mix(in srgb, var(--amber) 60%, transparent);
}
.facility-band__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(155deg, rgba(143, 91, 242, 0.3), transparent 62%);
}
.facility-band__media::before {
  content: "";
  position: absolute;
  inset: 0.75rem;
  z-index: 2;
  border: 1px solid rgba(239, 233, 231, 0.3);
  pointer-events: none;
  transition: inset 0.6s var(--ease-out), border-color 0.5s ease;
}
.facility-band__media:hover::before {
  inset: 0.5rem;
  border-color: color-mix(in srgb, var(--amber) 70%, transparent);
}
.facility-band__copy { flex: 1; }

/* ---------- Contact ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: var(--space-5);
  align-items: start;
  /* the same air the facility bands and the post grid leave under their intro */
  margin-top: var(--space-5);
}
@media (max-width: 860px) {
  .contact-grid { grid-template-columns: 1fr; }
}
.contact-list {
  list-style: none;
  margin: var(--space-3) 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}
.contact-list li {
  padding-left: 1.4rem;
  position: relative;
}
.contact-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 0.55rem;
  height: 1px;
  background: var(--amber);
}
.contact-list strong { color: var(--bone); }

/* ---------- The LINE card ----------
   This is where the visit is decided: everything below it is address and
   opening hours. So the block leaves the dark wall and takes the celadon paper
   of the origin deck, the site's one pale surface, which the eye has already
   learned means "pick this up". Its halo is LINE green where the deck's is
   violet, because what the paper is holding out is the button. */
.line-card {
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 4px;
  padding: clamp(1.7rem, 3.2vw, 2.6rem);
  background:
    radial-gradient(130% 100% at 88% -15%, rgba(255, 255, 255, 0.5), transparent 58%),
    linear-gradient(158deg, var(--paper-1), var(--paper-2));
  box-shadow:
    0 40px 70px -30px rgba(0, 0, 0, 0.75),
    0 0 60px -18px rgba(5, 199, 86, 0.35);
}
/* the deck's halftone corner, so the two papers are cut from one sheet */
.line-card::before {
  content: "";
  position: absolute;
  top: -5rem;
  right: -5rem;
  width: 14rem;
  height: 14rem;
  border-radius: 50%;
  background: repeating-radial-gradient(circle,
    transparent 0 14px,
    rgba(29, 43, 38, 0.07) 14px 15px);
  pointer-events: none;
}
.line-card > * { position: relative; }
#contact .line-card h3 {
  color: var(--paper-ink);
  margin: 0 0 var(--space-2);
}
.line-card p { color: var(--paper-body); }
.line-card__lede { font-weight: 600; }
.line-card__list {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
  color: var(--paper-body);
}
.line-card__list li {
  position: relative;
  padding-left: 1.9rem;
  line-height: 1.6;
}
/* a green tick per line, the button's own colour: four things already granted,
   and one button left to press */
.line-card__list li::before {
  content: "";
  position: absolute;
  left: 0.35rem;
  top: 0.28em;
  width: 0.42rem;
  height: 0.78rem;
  border: solid var(--line-green);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.line-card__cta {
  margin: var(--space-4) 0 0;
  text-align: center;
}

/* Breathing room before the secondary contact headings */
#contact .contact-grid h3:not(:first-of-type) { margin-top: var(--space-5); }
/* the card swallowed the column's first h3, so the next one has to ask */
#contact .contact-grid .line-card ~ h3 { margin-top: var(--space-5); }
#contact > .wrap > h3 { margin-top: var(--space-5); }

/* Maps facade */
.map-facade {
  position: relative;
  aspect-ratio: 4 / 3;
  background:
    radial-gradient(70% 60% at 60% 40%, rgba(143, 91, 242, 0.2), transparent 70%),
    linear-gradient(160deg, var(--ink-2), var(--ink-0));
  border: 1px solid var(--line);
  display: grid;
  place-content: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-3);
  overflow: hidden;
}
.map-facade::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(199, 169, 255, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(199, 169, 255, 0.06) 1px, transparent 1px);
  background-size: 44px 44px;
}
.map-facade > * { position: relative; }
.map-facade address {
  font-style: normal;
  color: var(--bone);
  max-width: 30ch;
  margin-inline: auto;
}
.map-facade iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ---------- FAQ ---------- */
.faq {
  border-top: 1px solid var(--line);
  max-width: var(--measure);
  /* no intro paragraph here, so the list takes the block step itself rather
     than hanging off the heading */
  margin-top: var(--space-5);
}
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  padding: 1.2rem 0.2rem;
  font-family: var(--font-serif);
  font-size: var(--step-1);
  font-weight: 600;
  color: var(--bone);
  letter-spacing: -0.005em;
}
/* The question is a heading now, so the FAQ has an outline of its own and each
   one reads as the query it answers. HTML allows a single heading element as
   the child of <summary>; the styling stays the summary's, so nothing moves. */
.faq summary h3 {
  margin: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
}

.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--amber);
  transition: transform 0.3s var(--ease-out);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq summary:hover { color: var(--violet-bright); }
.faq details p { padding: 0 0.2rem 1.4rem; }

/* ---------- Reviews ---------- */
.reviews {
  text-align: center;
}
.reviews p { margin-inline: auto; }

/* ---------- Blog teaser & archive cards ---------- */
.post-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  align-items: start;   /* cards keep their natural height: true masonry rows */
  gap: var(--space-4);
  margin-top: var(--space-5);
}
.post-card {
  /* a real card: its own ground, a hairline and a shadow that lifts it off
     the section instead of floating loose on it */
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: 0 0 var(--space-3);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 18px 38px -24px rgba(0, 0, 0, 0.9);
  transition: transform 0.45s var(--ease-out), box-shadow 0.45s var(--ease-out), border-color 0.45s;
}
.post-card:hover {
  transform: translateY(-4px);
  border-color: color-mix(in srgb, var(--amber) 40%, transparent);
  box-shadow: 0 30px 54px -26px rgba(0, 0, 0, 0.95), 0 0 44px -26px rgba(143, 91, 242, 0.5);
}
.post-card > :not(.post-card__media) { padding-inline: var(--space-3); }
.post-card__media {
  overflow: hidden;
  border: 0;
  border-bottom: 1px solid var(--line);
}
.post-card__media img {
  /* masonry: each card keeps its own image ratio instead of being cropped
     to a shared 16/9 -- the width/height attributes drive the box */
  width: 100%;
  height: auto;
  transition: transform 0.8s var(--ease-out);
}
.post-card:hover .post-card__media img { transform: scale(1.04); }
.post-card time {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
  /* the flex gap already gives space-2: top up to space-3 so the air under the
     photograph equals the padding down the card's sides */
  margin-top: calc(var(--space-3) - var(--space-2));
}
/* the card ends on its own door, in the same amber as the date */
.post-card__more {
  margin: auto 0 0;
  padding-top: var(--space-2);
}
.post-card__more a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--amber);
}
.post-card__more span {
  width: 1.6rem;
  height: 1px;
  background: currentColor;
  transition: width 0.35s var(--ease-out);
}
.post-card:hover .post-card__more span { width: 2.4rem; }
@media (prefers-reduced-motion: reduce) {
  .post-card, .post-card__more span { transition: none; }
}
.post-card h2,
.post-card h3 {
  font-size: var(--step-2);
  line-height: 1.15;
  margin-bottom: 0;
}
.post-card :is(h2, h3) a {
  color: var(--bone);
  text-decoration: none;
}
.post-card :is(h2, h3) a:hover { color: var(--violet-bright); }
.post-card--nolink :is(h2, h3) { color: var(--muted); }

/* ---------- Video slot ----------
   A composed plate, not an empty box: the arch, the house's light and a play
   mark. Swap the whole figure for the real <video> when the file is ready. */
.video-slot { margin: var(--space-4) 0; }
.video-slot__frame {
  position: relative;
  display: grid;
  place-items: center;
  gap: var(--space-2);
  aspect-ratio: 16 / 10;
  border: 1px solid color-mix(in srgb, var(--amber) 26%, transparent);
  border-radius: 6px;
  background:
    radial-gradient(120% 90% at 50% 28%, rgba(143, 91, 242, 0.24), transparent 64%),
    radial-gradient(70% 40% at 50% 104%, rgba(229, 178, 107, 0.14), transparent 70%),
    linear-gradient(160deg, var(--ink-2), var(--ink-0));
}
.video-slot__play {
  width: 4.4rem;
  height: 4.4rem;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--amber) 55%, transparent);
  display: grid;
  place-items: center;
}
.video-slot__play::after {
  content: "";
  border-style: solid;
  border-width: 0.62rem 0 0.62rem 1.05rem;
  border-color: transparent transparent transparent var(--amber);
  margin-left: 0.25rem;
}
.video-slot__note {
  margin: 0;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}
.video-slot figcaption {
  margin-top: 0.9rem;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
}

.video-slot__player {
  display: block;
  width: 100%;
  height: auto;
  max-height: 78vh;
  margin-inline: auto;
  background: var(--ink-0);
  border: 1px solid color-mix(in srgb, var(--amber) 26%, transparent);
  border-radius: 6px;
}

/* ---------- Crew gallery (Faces of Nuru House) ----------
   True masonry through CSS columns: each photo keeps its own height and the
   column fills itself, so portraits of different crops sit together without
   a single crop. Same framed treatment as the team rails. */
.crew-grid {
  columns: 2;
  column-gap: var(--space-2);
  margin: var(--space-4) 0;
}
@media (min-width: 900px) { .crew-grid { columns: 3; } }
.crew-shot {
  position: relative;
  break-inside: avoid;
  margin: 0 0 var(--space-2);
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-2);
  box-shadow:
    0 24px 48px -28px rgba(0, 0, 0, 0.9),
    0 0 40px -24px rgba(143, 91, 242, 0.4),
    inset 0 1px 0 rgba(239, 233, 231, 0.12);
}
.crew-shot img { width: 100%; height: auto; display: block; }
.crew-shot::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to top, rgba(15, 12, 19, 0.86) 0%, rgba(15, 12, 19, 0.2) 26%, transparent 46%),
    linear-gradient(155deg, rgba(143, 91, 242, 0.26), transparent 60%);
}
.crew-shot::before {
  content: "";
  position: absolute;
  inset: 0.6rem;
  z-index: 3;
  border: 1px solid rgba(239, 233, 231, 0.28);
  pointer-events: none;
  transition: inset 0.6s var(--ease-out), border-color 0.5s ease;
}
.crew-shot:hover::before {
  inset: 0.4rem;
  border-color: color-mix(in srgb, var(--amber) 70%, transparent);
}
.crew-shot figcaption {
  position: absolute;
  left: 1.1rem;
  right: 1.1rem;
  bottom: 1rem;
  z-index: 2;
  padding-top: 0.55rem;
  border-top: 1px solid color-mix(in srgb, var(--amber) 60%, transparent);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--bone);
}
@media (prefers-reduced-motion: reduce) { .crew-shot::before { transition: none; } }

/* the series label, on the article and on its preview card */
.tag {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
}
/* the paragraph keeps its 1.4em bottom margin on top of the card's flex gap:
   both are cancelled so the list reads as attached to its intro line */
.post-card p:has(+ .post-card__bullets),
.post-card p:has(+ .post-card__more) { margin-bottom: 0; }
.post-card__bullets {
  list-style: none;
  margin: calc(0.35rem - var(--space-2)) 0 0;
  padding: 0;
}
.post-card__bullets li {
  position: relative;
  padding-left: 1rem;
  color: var(--body);
}
.post-card__bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 5px;
  height: 5px;
  background: var(--amber);
}

.shot-box {
  border: 0;
  padding: 0;
  background: transparent;
  max-width: 100vw;
  max-height: 100vh;
}
.shot-box::backdrop { background: rgba(9, 7, 12, 0.95); }
.shot-box img {
  max-width: 94vw;
  max-height: 92vh;
  width: auto;
  height: auto;
  border-radius: 8px;
  cursor: zoom-out;
}

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--line);
  margin-top: var(--space-6);
  padding-block: var(--space-5) var(--space-3);
  background: var(--ink-0);
  position: relative;
  overflow: clip;
}
.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: var(--space-4);
}
@media (max-width: 860px) {
  .footer-grid { grid-template-columns: 1fr; }
}
.site-footer .footer-h {
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-3);
}
.site-footer address { font-style: normal; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.site-footer a { text-decoration: none; color: var(--body); }
.site-footer a:hover { color: var(--violet-bright); }
.footer-bottom {
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  justify-content: space-between;
  font-size: var(--step--1);
  color: var(--muted);
}
.footer-bottom p { margin: 0; }

/* ---------- Blog article pages ---------- */
.article-hero {
  padding-top: clamp(8rem, 14vh, 11rem);
}
.breadcrumb {
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: var(--space-3);
}
.breadcrumb ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
}
.breadcrumb li + li::before {
  content: "→";
  margin-right: 0.6rem;
  color: var(--line);
}
.breadcrumb a { color: var(--muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--violet-bright); }

.article-hero .standfirst {
  font-family: var(--font-accent);
  font-style: normal;
  font-variation-settings: "opsz" 16;
  font-weight: 400;
  font-size: var(--step-1);
  color: var(--violet-bright);
  max-width: 40ch;
}
.article-meta {
  display: flex;
  gap: var(--space-3);
  font-size: var(--step--1);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  margin-block: var(--space-3);
}
.article-body {
  max-width: var(--measure);
  margin-inline: auto;
}
.article-body > h2 {
  font-size: var(--step-2);
  margin-top: var(--space-5);
}
.article-body > h3 { margin-top: var(--space-4); }
.article-body .lede {
  /* contains the floated drop cap: on a one-line lede the letter used to
     overflow the paragraph and the next one wrapped around it */
  display: flow-root;
}
.article-body .lede::first-letter {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 3.6em;
  float: left;
  line-height: 0.8;
  padding: 0.08em 0.12em 0 0;
  color: var(--violet-bright);
}
.article-figure {
  margin: var(--space-4) 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  overflow: hidden;
}
/* the file's own ratio drives the box: swapping the placeholder for a real
   photo of any shape needs no CSS change and shifts nothing */
.article-figure img {
  width: 100%;
  height: auto;
  display: block;
  /* same ceiling as the video below it, so photo and film present alike */
  max-height: 78vh;
  object-fit: cover;
}
.article-cta {
  /* same rhythm as the blocks above it, instead of a 5rem hole */
  margin: var(--space-4) 0;
  text-align: center;
}

/* Reading progress */
.read-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 130;
  width: 100%;
  height: 3px;
  background: var(--amber);
  transform-origin: 0 50%;
  transform: scaleX(0);
}
@supports (animation-timeline: scroll()) {
  .read-progress {
    animation: growX linear both;
    animation-timeline: scroll(root);
  }
  @keyframes growX {
    from { transform: scaleX(0); }
    to { transform: scaleX(1); }
  }
}

/* Comparison component */
.compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--line);
  margin: var(--space-4) 0;
}
@media (max-width: 640px) {
  .compare { grid-template-columns: 1fr; }
}
.compare__col { padding: var(--space-3); }
.compare__col + .compare__col { border-left: 1px solid var(--line); }
@media (max-width: 640px) {
  .compare__col + .compare__col { border-left: 0; border-top: 1px solid var(--line); }
}
.compare__col h3 {
  font-size: var(--step-1);
  color: var(--violet-bright);
}
.compare__col--nh h3 { color: var(--amber); }
.compare__col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-2);
}
.compare__col li {
  padding-left: 1.4rem;
  position: relative;
}
.compare__col li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 0.55rem;
  height: 1px;
  background: currentColor;
  opacity: 0.6;
}

/* Post prev/next */
.post-nav {
  /* stacked, not side by side: BEFORE sits above NEXT, and the opposite
     alignments make the direction of travel legible at a glance */
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  border-top: 1px solid var(--line);
  margin-top: var(--space-5);
  padding-top: var(--space-4);
}
.post-nav a {
  text-decoration: none;
  color: var(--bone);
  font-family: var(--font-body);
  font-size: var(--step-1);
  letter-spacing: -0.01em;
  line-height: 1.3;
}
.post-nav a:hover { color: var(--violet-bright); }
.post-nav span {
  display: block;
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 0.6rem;
}
.post-nav__prev { text-align: left; justify-self: start; }
.post-nav__next { text-align: right; justify-self: end; }

/* ---------- Reveal choreography ---------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
}
.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
  transition-delay: var(--d, 0s);
}

/* ---------- Parallax (CSS scroll-driven where supported; JS rAF fallback) ---------- */
[data-plx] { --plx: -40; }
[data-plx="slow"] { --plx: -70; }
[data-plx="faint"] { --plx: -24; }
@supports (animation-timeline: view()) {
  .js [data-plx] {
    animation: plxY linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  @keyframes plxY {
    from { transform: translateY(calc(var(--plx) * -1px)); }
    to { transform: translateY(calc(var(--plx) * 1px)); }
  }
  .js [data-plx-x] {
    animation: plxX linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  .js [data-plx-x="left"] { --plxx: -5; }
  .js [data-plx-x="right"] { --plxx: 5; }
  @keyframes plxX {
    from { transform: translateX(calc(var(--plxx) * -1%)); }
    to { transform: translateX(calc(var(--plxx) * 1%)); }
  }
}

/* ---------- Reduced motion: kill it all ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    animation-timeline: auto !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .js [data-plx],
  .js [data-plx-x],
  .rail-track,
  .rail-card :is(img, video) { animation: none !important; transform: none !important; }
  .js .rail-wrap { height: auto; }
  .js .rail-sticky { position: relative; top: auto; }
  .rail-track-scroller {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }
  .read-progress { animation: none !important; }
}
