/* ============================================================
   TEMPLATE 10 — CINEMATIC RESIDENCE
   Dark ground, ivory type, gold as an accent only. The photograph is the
   visual hero; every gradient here exists to make it readable, never to
   replace it.

   Two rules carried from the rest of this library:
     1. Reveals drive the `translate` / `scale` / `clip-path` LONGHANDS and
        never `transform`. A `transform: none` reset on a revealed element
        out-ranks every hover rule and silently kills all of them.
     2. Every @media (hover: hover) rule has a .is-tapped twin, because
        these packs are consumed inside a mobile app where hover never
        fires.
   ============================================================ */

:root {
  /* ---- the reference palette ----
     #F7F3EB ground, #161411 type, #A77B2E champagne. Token NAMES are shared
     with the sibling templates so every rule downstream keeps working.
     --ivory is the primary TEXT colour here, not a background.

     One split is unavoidable: #A77B2E measures 3.44:1 on this ground, which
     is correct for the large display line and for icons and rules (3:1) and
     illegal for the 11px eyebrow (4.5:1). --gold-text is the same hue taken
     darker until it clears. */
  --bg: #f7f3eb;
  --bg-2: #f1ebe0;
  --bg-3: #e8e0d2;
  --ivory: #161411;
  --ink-on-dark: #fbf8f2;
  --muted: #5f584d;

  --gold: #a77b2e;
  --gold-display: #a77b2e;
  --gold-text: #876325;
  --gold-soft: #876325;

  --glass: rgba(255, 253, 249, 0.94);
  --glass-panel: rgba(255, 253, 249, 0.94);
  --line: rgba(22, 20, 17, 0.1);
  --line-2: rgba(22, 20, 17, 0.2);
  --gold-line: rgba(167, 123, 46, 0.34);
  --grid-line: rgba(255, 255, 255, 0.55);

  --sh-m: 0 14px 34px -18px rgba(70, 52, 24, 0.26);
  --sh-l: 0 28px 60px -28px rgba(70, 52, 24, 0.3);
  --sh-xl: 0 48px 96px -44px rgba(70, 52, 24, 0.34);

  --r-s: 10px;
  --r-m: 16px;
  --r-l: 22px;
  --r-xl: 30px;

  --gut: clamp(1.15rem, 4.5vw, 5rem);
  --maxw: 96rem;
  --e: cubic-bezier(0.22, 1, 0.36, 1);
  --e-out: cubic-bezier(0.16, 1, 0.3, 1);
  --serif: 'Cormorant Garamond', 'Iowan Old Style', Georgia, serif;
  --display: 'Playfair Display', 'Cormorant Garamond', Georgia, serif;
  --sans: 'Manrope', system-ui, -apple-system, sans-serif;

  --heading: var(--ivory);
  --border: var(--line);
  --font-heading: var(--display);
  --accent: var(--gold);
}

/* ============================================================
   RESPONSIVE MOTION
   Mobile is not the desktop with the motion removed: the same effects run
   at re-tuned amplitudes. Only an explicit reduced-motion request
   collapses them.
   ============================================================ */
:root {
  --mo-dist: 28px;
  --mo-dur: 0.9s;
  --mo-stagger: 90ms;
  --mo-par: 1;
  --mo-press: 0.975;
  --mo-zoom: 1.06;
}
@media (max-width: 768px) {
  :root {
    --mo-dist: 15px;
    --mo-dur: 0.65s;
    --mo-stagger: 55ms;
    --mo-par: 0.45;
    --mo-zoom: 1.08;
  }
}
@media (prefers-reduced-motion: reduce) {
  :root {
    --mo-dist: 0px;
    --mo-dur: 0.01s;
    --mo-stagger: 0ms;
    --mo-par: 0;
    --mo-press: 1;
    --mo-zoom: 1;
  }
}

/* ---------- reset ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--ivory);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* the guard against any full-bleed layer causing sideways scroll */
  overflow-x: hidden;
}
body.jp-locked {
  overflow: hidden;
}
img {
  display: block;
  max-width: 100%;
}
h1,
h2,
h3,
h4,
p,
figure,
figcaption,
blockquote,
ul,
ol {
  margin: 0;
}
ul,
ol {
  padding: 0;
  list-style: none;
}
a {
  color: inherit;
  text-decoration: none;
}
button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}
svg {
  display: block;
}
.rating svg {
  /* stars() emits a <path> with no fill, so SVG's default black would apply
     and every `color:` on .rating would be inert */
  fill: currentColor;
}
:focus-visible {
  outline: 2px solid var(--gold-soft);
  outline-offset: 3px;
}

/* ---------- boot ---------- */
.boot-screen {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.9rem;
  background: var(--bg);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--muted);
}
.boot-line {
  width: 2.2rem;
  height: 1px;
  background: var(--line-2);
  overflow: hidden;
  position: relative;
}
.boot-line::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--gold);
  animation: crBoot 1.1s var(--e) infinite;
}
@keyframes crBoot {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}
.boot-error {
  gap: 0.6rem;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.95rem;
  color: var(--ivory);
}
.boot-retry {
  margin-top: 0.4rem;
  min-height: 2.75rem;
  padding: 0.6rem 1.2rem;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  background: none;
  cursor: pointer;
}

/* ---------- shell + type ---------- */
.jp-wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gut);
  min-width: 0;
}
.jp-eyebrow {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  /* #c9a063 was inherited from the dark siblings and measured 2.16:1 on the
     ivory ground - invisible, and illegal for 11.5px text. Darkened along the
     same hue until it cleared 4.5:1 on the DARKER of the two section grounds,
     so one value works on both. */
  color: var(--gold-text);
}
.jp-eyebrow::before {
  content: '';
  width: clamp(24px, 3vw, 42px);
  height: 1px;
  background: var(--gold-line);
  flex: 0 0 auto;
}
.jp-eyebrow--hero {
  color: var(--gold-soft);
}
.jp-display {
  font-family: var(--serif);
  font-weight: 500;
  /* measured off the reference at 1536: cap height puts the face at ~82px */
  font-size: clamp(56px, 5.3vw, 86px);
  /* the two baselines are 96px apart there, so the leading is ~1.17 */
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin-top: clamp(0.5rem, 1.6vw, 1rem);
}
.jp-display .jp-l1 {
  color: var(--ivory);
}
/* Structural guarantee rather than an arithmetic one: each line is its own
   block and cannot wrap, so "Premium Living." / "Feels Like Home." stays two
   lines even if the real font metrics differ from my estimate. */
/* `white-space: nowrap` was added in the first version to guarantee two lines
   on a wide screen. In a 155px mobile column it makes wrapping impossible, so
   "Where Comfort" runs straight across the building. It was then limited to
   >=768px, on the assumption that a wide screen always has room.

   IT DOES NOT. Room depends on the COPY, not the viewport. app.js splits the
   headline on the owner's own separator; when there is no separator the whole
   line lands in .jp-l1 alone. "Not just a PG. A way of living." at 70px in a
   720px column is ~1100px of text that is forbidden to wrap, so it paints
   straight out of its box and across the photograph. Seen on a live site at
   1920px, and it gets worse the wider the screen, because the font scales with
   the viewport while the copy column stays at 45%.

   So: nowrap only when a SECOND line exists to make the guarantee meaningful.
   One line wraps normally, which is what it needed all along. Browsers without
   :has() simply wrap -- the safe direction, not the broken one. */
.jp-display .jp-l1,
.jp-display .jp-l2 {
  display: block;
}
@media (min-width: 768px) {
  .jp-display:has(.jp-l2) .jp-l1,
  .jp-display:has(.jp-l2) .jp-l2 {
    white-space: nowrap;
  }
}
.jp-display .jp-l1 {
  color: var(--ivory);
}
.jp-display--sm {
  font-size: clamp(2.1rem, 4.6vw, 4.6rem);
}
.jp-display .jp-l1,
.jp-display .jp-l2 {
  display: block;
}
.jp-l1 {
  color: var(--ivory);
}
.jp-l2 {
  color: var(--gold-display);
}
.jp-h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.9rem, 3.6vw, 3.2rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
  color: var(--ivory);
  text-wrap: balance;
}
/* the location heading is two deliberate lines */
.jp-h2--split {
  max-width: 18ch;
}
/* A decorative .jp-display::after gold rule used to live here. It is gone:
   this composition has no divider under the headline, and while a .jp-rule
   element briefly existed the two of them rendered together, which is the
   pair of gold lines that showed up in the screenshot. */
.jp-lede {
  margin-top: clamp(1rem, 2.2vw, 1.4rem);
  max-width: 480px;
  font-family: 'Inter', var(--sans);
  font-size: clamp(16px, 1.25vw, 20px);
  line-height: 1.6;
  color: var(--muted);
}
.jp-prose {
  margin-top: 1rem;
  color: var(--muted);
  line-height: 1.85;
  max-width: 44ch;
}
.jp-prose + .jp-prose {
  margin-top: 0.8rem;
}
.jp-head {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-bottom: clamp(1.6rem, 3.2vw, 2.6rem);
  padding-bottom: clamp(1rem, 2vw, 1.5rem);
  border-bottom: 1px solid var(--line);
  max-width: 44rem;
}
.jp-head--mid {
  margin-inline: auto;
  text-align: center;
  align-items: center;
}
.jp-head--mid {
  align-items: center;
  text-align: center;
}

/* ---------- buttons ---------- */
.jp-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 2.875rem;
  padding: 0.8rem 1.6rem;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  overflow: hidden;
  /* the magnetic offset lives on `translate`, leaving `transform` free for
     the hover lift so the two never overwrite each other */
  translate: var(--mag-x, 0px) var(--mag-y, 0px);
  transition:
    translate 0.35s var(--e),
    transform 0.4s var(--e),
    background 0.4s var(--e),
    border-color 0.4s var(--e),
    box-shadow 0.45s var(--e),
    color 0.4s var(--e);
}
.jp-btn--lg {
  /* §10 */
  min-height: 58px;
  padding: 0 34px;
  font-size: 15px;
  border-radius: 8px;
}
.jp-hero__acts .jp-btn--gold {
  background: var(--ivory);
}
/* --gold reads 5.09:1 on the ink pill and is brighter than --gold-display's
   4.33:1; both clear the 3:1 an icon needs, so take the brighter one. */
.jp-hero__acts .jp-btn--gold .jp-go {
  color: var(--gold);
}
/* In the reference the primary is a near-black pill with an ivory label and
   a gold arrow - the gold is the accent inside it, not the fill. */
.jp-btn--gold {
  background: var(--ivory);
  color: var(--ink-on-dark);
  box-shadow: 0 12px 28px -14px rgba(201, 150, 69, 0.6);
}
.jp-btn--glass {
  background: var(--glass);
  color: var(--ivory);
  border-color: var(--line-2);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.jp-btn--line {
  background: transparent;
  color: var(--gold-soft);
  border-color: var(--gold-line);
}
.jp-btn svg,
.jp-btn i {
  width: 0.95rem;
  height: 0.95rem;
}
.jp-go {
  display: inline-flex;
  transition: transform 0.4s var(--e);
}
/* the border sweep — a thin gold trace that runs the pill on hover */
.jp-btn--gold::after,
.jp-btn--glass::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(
    14rem circle at var(--gx, 50%) 50%,
    rgba(22, 19, 15, 0.2),
    transparent 60%
  );
  transition: opacity 0.45s var(--e);
}
.jp-round {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.875rem;
  height: 2.875rem;
  flex: 0 0 auto;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--ivory);
  cursor: pointer;
  transition:
    background 0.4s var(--e),
    border-color 0.4s var(--e),
    transform 0.4s var(--e);
}
.jp-round svg,
.jp-round i {
  width: 1rem;
  height: 1rem;
}

/* ============================================================
   02 NAVIGATION — transparent, then glass
   ============================================================ */
.jp-nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 500;
  /* The reference has no bar over the composition - the lockup inside the
     ivory panel is the branding. The bar is therefore absent at rest and
     arrives as a cream sheet once the hero has been scrolled past, so the
     seven section links are never unreachable. */
  background: transparent;
  border-bottom: 1px solid transparent;
  pointer-events: none;
  transition:
    background 0.5s var(--e),
    border-color 0.5s var(--e),
    box-shadow 0.5s var(--e);
}
.jp-nav:not(.is-stuck) .jp-nav__in > * {
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.4s var(--e),
    visibility 0.4s var(--e);
}
.jp-nav.is-stuck,
.jp-nav:focus-within {
  pointer-events: auto;
}
.jp-nav.is-stuck .jp-nav__in > *,
.jp-nav:focus-within .jp-nav__in > * {
  opacity: 1;
  visibility: visible;
}
/* ---- the bar shows at rest on mobile ----
   Two separate reasons the top of a phone screen came up empty.

   1. Only .nav-toggle was excepted from the hider, so the logo and the call
      button stayed hidden. On desktop that is fine - the ivory panel and its
      lockup are the first thing on screen. The mobile composition puts the
      PHOTOGRAPH first and the lockup below it, so there was no branding and
      no visible way into the menu until the visitor scrolled.

   2. The burger's bars are `background: var(--ivory)`, inherited from the
      dark siblings where --ivory means "light text". Here it is near-black
      ink, so the trigger rendered as dark bars on a dusk photograph -
      present, 44px, clickable, invisible. The same fault as template 10's
      burger, reached by a different route: there a stray is-lit rule, here
      the palette inversion.

   Giving the bar its cream ground at rest fixes both at once. Desktop keeps
   the reference behaviour and stays absent until scrolled. */
@media (max-width: 899.98px) {
  .jp-nav:not(.is-stuck) .jp-nav__in > * {
    opacity: 1;
    visibility: visible;
  }
  .jp-nav:not(.is-stuck) {
    pointer-events: auto;
    background: rgba(246, 242, 234, 0.9);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    backdrop-filter: blur(14px) saturate(1.1);
    border-bottom-color: var(--line);
  }
}
.jp-nav.is-stuck {
  background: rgba(246, 242, 234, 0.95);
  color: var(--ivory);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
  backdrop-filter: blur(22px) saturate(1.3);
  border-bottom-color: var(--line);
  box-shadow: var(--sh-m);
}
.jp-nav__in {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  min-height: 5rem;
  transition: min-height 0.55s var(--e);
}
.jp-nav.is-stuck .jp-nav__in {
  min-height: 4.1rem;
}
.jp-logo {
  display: inline-flex;
  min-width: 0;
  align-items: center;
  gap: 0.7rem;
  /* 0 1 auto, so a long name ellipsises rather than pushing the burger off */
  flex: 0 1 auto;
  min-width: 0;
}
.jp-logo__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  flex: 0 0 auto;
  border: 1px solid var(--gold-line);
  border-radius: 0.6rem;
  color: var(--gold);
  transition:
    transform 0.5s var(--e),
    border-color 0.5s var(--e);
}
.jp-logo__mark svg,
.jp-logo__mark i {
  width: 1.15rem;
  height: 1.15rem;
}
.jp-logo__tx {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.15;
}
.jp-logo__tx b {
  font-family: var(--serif);
  font-size: clamp(1.05rem, 2vw, 1.4rem);
  font-weight: 600;
  color: var(--ivory);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.jp-logo__tx i {
  font-style: normal;
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.jp-nav__links {
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: clamp(0.8rem, 1.7vw, 1.9rem);
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--muted);
}
.jp-nav__links a {
  position: relative;
  min-height: 2.75rem;
  display: inline-flex;
  align-items: center;
  transition: color 0.4s var(--e);
}
/* grows from the centre outward rather than wiping in from the left */
.jp-nav__links a::after {
  content: '';
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: 0.55rem;
  height: 1px;
  background: var(--gold);
  transition: right 0.45s var(--e);
}
.jp-nav__cta {
  flex: 0 0 auto;
}
/* ---- mobile nav trigger ----
   enhance.js injects its own stylesheet at runtime, so it always lands after
   this file and wins ties. Its rules are `.nav-toggle` (0,1,0) and
   `.navbar .nav-links` (0,2,0), both !important, both firing at 991.98px.
   This template collapses at 900px, not 992, so the overrides below are
   deliberately one class more specific in order to outrank them. */
/* `flex: 0 0 auto` matters more than it looks. .jp-logo and .jp-nav__cta are
   both 0 0 auto, so without this the burger is the ONLY shrinkable child of
   the nav row - at 333px the business name and the call button take the whole
   width and squeeze the drawer trigger to zero. Navigation must not lose a
   fight with a long business name. */
.nav-toggle {
  display: none;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  color: inherit;
}
.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--ivory);
}
/* There used to be a `.jp-nav.is-lit .nav-toggle span { background: var(--ink) }`
   rule here, written on the assumption that `is-lit` meant a light theme.
   It does not: in this template `is-lit` is the load-reveal hook, added to
   the nav by app.js a couple of frames after boot. So the rule fired on every
   page load and painted the burger bars near-black on a dark photograph - the
   button was there, 44px wide and clickable, just invisible. That is also why
   the call button never reached the right edge: the unseen burger held the
   space. The bars stay ivory. */

/* the injected drawer takes over below the desktop nav breakpoint */
@media (max-width: 899.98px) {
  .jp-nav__links {
    display: none;
  }
  /* logo ......... [burger][call], with the call pill on the outside edge */
  .jp-nav__cta {
    order: 2;
    margin-inline-start: 0;
  }
  .jp-nav .nav-toggle {
    display: inline-flex;
    order: 1;
    /* the auto margin moves to the first item of the right-hand group */
    margin-inline-start: auto;
  }
}
/* 900-991px: enhance.js would swap to the drawer here. This template still
   has room for the full bar, so both of its rules are reversed. */
@media (min-width: 900px) {
  .jp-nav .nav-toggle {
    display: none !important;
  }
  .jp-nav .jp-nav__in .jp-nav__links {
    display: flex !important;
  }
}
@media (max-width: 479.98px) {
  /* at phone widths the drawer button needs the room, so the pill loses
     its label rather than the layout losing its shape */
  .jp-nav__cta {
    padding: 0.7rem 0.95rem;
    font-size: 0;
    gap: 0;
  }
  .jp-nav__cta svg,
  .jp-nav__cta i {
    width: 1.05rem;
    height: 1.05rem;
  }
}

/* ============================================================
   01 HERO — cream copy left, the real building bleeding off the right
   ============================================================ */
.jp-hero {
  position: relative;
  width: 100%;
  max-width: none;
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 45%) minmax(0, 1fr);
  /* An explicit row, and stretch stated rather than relied on. The plate holds
     no in-flow content - its image is absolute - so anything that stops the
     row stretching leaves the building as a short strip at the top instead of
     a full-height column. */
  grid-template-rows: minmax(100svh, auto);
  align-items: stretch;
  min-height: 100svh;
  overflow: hidden;
  background: var(--bg);
  isolation: isolate;
  perspective: 1600px;
  perspective-origin: 30% 45%;
  --exit: 0;
  --edge: clamp(1.3rem, 4.2vw, 5rem);
  --panel-drop: 0px;
  /* How far the feather reaches BACK over the cream column. Declared once and
     consumed by both the feather's own offset and the copy column's right
     padding, so the panel can never again end up underneath it. */
  --feather-in: clamp(22px, 3vw, 64px);
}
.jp-hero__in {
  grid-column: 1;
  display: flex;
  align-items: center;
  padding-block: clamp(3rem, 8svh, 5.5rem) calc(var(--panel-drop) + clamp(1rem, 3svh, 2rem));
  /* The right padding must clear the feather, not just look like a gutter.
     The feather's first 24% is FULLY OPAQUE cream, and it starts --feather-in
     back from the column edge, while this padding was only ever
     clamp(0.8rem, 2vw, 1.6rem) - 25.6px against a 46px reach at 1536. The
     2x2 feature panel is the one element that uses the full column width, so
     its last 20px vanished under the feather: no right border, no rounded
     corners, a razor cut down one side, and only 4px of visible gap left
     beside the longest amenity line. It got worse with width - 12px at 1200,
     20px at 1536, 38px past 2133 - because the padding is capped and the
     reach is not. max() means whichever is larger wins, so the panel always
     ends before the opaque head. */
  padding-inline: var(--edge) max(clamp(0.8rem, 2vw, 1.6rem), var(--feather-in));
}
.jp-hero__copy {
  position: relative;
  z-index: 1;
  width: 100%;
  translate: var(--mx, 0px) var(--my, 0px);
  transition: translate 0.7s var(--e);
}

/* the photograph: a direct child, so the pointer tilt is really projected */
.jp-hero__plate {
  position: relative;
  grid-column: 2;
  grid-row: 1;
  align-self: stretch;
  min-height: 100%;
  overflow: hidden;
  margin-inline-start: -2px;
  transform: rotateY(var(--ry, 0deg)) rotateX(var(--rx, 0deg));
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change: transform;
}
.jp-hero__plate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focal, 50% 50%);
  /* the reference keeps the building's own warm lighting; no darkening */
  scale: calc(1.04 - var(--exit) * 0.03);
  transition: scale 1.8s var(--e-out);
}
.jp-hero__grade {
  position: absolute;
  inset: 0;
  background: linear-gradient(200deg, rgba(255, 226, 178, 0.1) 0%, rgba(255, 214, 150, 0) 55%);
}
/* cream -> transparent, so the two sides dissolve instead of butting */
.jp-hero__feather {
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: calc(45% - var(--feather-in));
  width: clamp(120px, 16vw, 300px);
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    var(--bg) 0%,
    var(--bg) 24%,
    rgba(247, 243, 235, 0.94) 38%,
    rgba(247, 243, 235, 0.76) 52%,
    rgba(247, 243, 235, 0.5) 66%,
    rgba(247, 243, 235, 0.24) 82%,
    rgba(247, 243, 235, 0) 100%
  );
}

/* ---------- hero type ---------- */
.jp-eyebrow--hero {
  color: var(--gold-text);
}
.jp-display {
  margin-top: clamp(0.9rem, 2.4vw, 1.4rem);
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(2.5rem, 4.4vw, 4.4rem);
  line-height: 1.04;
  letter-spacing: -0.02em;
  color: var(--ivory);
}
.jp-display .jp-l1 {
  display: block;
  color: var(--ivory);
}
.jp-display .jp-l2 {
  display: block;
  color: var(--gold-display);
}
/* the reference divider: a gold rule, a gap, then a shorter second rule */
.jp-orn {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: clamp(1rem, 2.4vw, 1.5rem);
}
.jp-orn::before {
  content: '';
  width: clamp(52px, 7vw, 96px);
  height: 1px;
  background: var(--gold);
}
.jp-orn::after {
  content: '';
  width: clamp(20px, 2.6vw, 34px);
  height: 1px;
  background: var(--gold-line);
}
.jp-lede {
  margin-top: clamp(1rem, 2.4vw, 1.5rem);
  max-width: 24rem;
  font-family: 'Inter', var(--sans);
  font-size: clamp(0.98rem, 1.05vw, 1.06rem);
  line-height: 1.62;
  color: var(--muted);
}
.jp-hero__acts {
  margin-top: clamp(1.4rem, 3.2vw, 2.1rem);
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
}

/* ---------- the floating feature panel ---------- */
/* The reference puts a 2x2 panel on the cream side under the description, not
   a four-across bar spanning the whole hero. */
.jp-card {
  position: relative;
  z-index: 3;
  margin-top: clamp(1.6rem, 3.4vw, 2.4rem);
  width: min(44rem, 100%);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  border: 1px solid var(--line);
  border-radius: 22px;
  background: var(--glass);
  -webkit-backdrop-filter: blur(14px) saturate(1.08);
  backdrop-filter: blur(14px) saturate(1.08);
  box-shadow: var(--sh-l);
  overflow: hidden;
  /* the icon box, the label size and the label's line-height are declared once
     here and consumed below, so the icon can be centred on the label's line
     arithmetically instead of by eye */
  --card-ic: 1.6rem;
  --card-lab: clamp(0.86rem, 1vw, 0.98rem);
  --card-lab-lh: 1.3;
  --card-gut: 0.85rem;
}
.jp-card li {
  display: grid;
  /* a FIXED icon track, not `auto`. Each li is its own grid, so with `auto`
     every cell sized its icon column from its own glyph and the labels could
     land on different x positions from row to row. */
  grid-template-columns: var(--card-ic) minmax(0, 1fr);
  align-items: start;
  /* no row gap: the icon no longer spans a phantom second row, so a row gap
     here only padded the cell out */
  gap: 0 var(--card-gut);
  padding: clamp(1rem, 2vw, 1.5rem);
  min-width: 0;
}
/* 2x2: only the right column takes a vertical rule, the second row a
   horizontal one. `li + li` would rule item 3, which starts a new row. */
.jp-card li:nth-child(2n) {
  border-inline-start: 1px solid var(--line);
}
.jp-card li:nth-child(n + 3) {
  border-block-start: 1px solid var(--line);
}
.jp-card__ic {
  display: grid;
  place-items: center;
  /* a fixed square box, so all four icons occupy identical space regardless of
     how much of its viewBox each glyph actually fills (lucide's bed-double
     inks 13px tall where utensils inks 17px) */
  inline-size: var(--card-ic);
  block-size: var(--card-ic);
  /* the icon is taller than one line of the label, so top-aligning the two put
     the icon's centre ~2px BELOW the label's - it read as sagging. This pulls
     the box up by exactly half the difference, so the two centres coincide. */
  margin-block-start: calc((var(--card-lab) * var(--card-lab-lh) - var(--card-ic)) / 2);
  color: var(--gold);
}
.jp-card__ic svg,
.jp-card__ic i {
  width: 100%;
  height: 100%;
  stroke-width: 1.25;
}
.jp-card__tx {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
  /* the label leads the cell, so its own line box governs the top edge */
  padding-block-start: 0;
}
.jp-card__tx b {
  font-size: var(--card-lab);
  font-weight: 600;
  line-height: var(--card-lab-lh);
  color: var(--ivory);
}
.jp-card__tx i {
  font-style: normal;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--muted);
}

/* the panel is in flow now, so the next section needs no extra clearance */

/* ---------- the floating contact rail ---------- */
.jp-rail {
  position: fixed;
  right: clamp(0.7rem, 1.4vw, 1.4rem);
  top: 50%;
  translate: 0 -50%;
  z-index: 480;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.jp-rail__a {
  display: grid;
  place-items: center;
  width: 2.9rem;
  height: 2.9rem;
  border: 1px solid var(--gold-line);
  border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--gold-text);
  box-shadow: var(--sh-m);
  transition:
    background 0.35s var(--e),
    color 0.35s var(--e),
    scale 0.35s var(--e);
}
.jp-rail__a svg,
.jp-rail__a i {
  width: 1.1rem;
  height: 1.1rem;
}

/* ============================================================
   07 THE STAGED ENTRANCE
   Longhands throughout: the reveal layer resets `transform: none`,
   which out-ranks every hover rule that uses the shorthand.
   ============================================================ */
.jp-anim .jp-hero .jp-lock,
.jp-anim .jp-hero .jp-display .jp-l1,
.jp-anim .jp-hero .jp-display .jp-l2,
.jp-anim .jp-hero .jp-orn,
.jp-anim .jp-hero .jp-lede,
.jp-anim .jp-hero .jp-card,
.jp-anim .jp-hero .jp-hero__acts {
  opacity: 0;
  translate: 0 22px;
  transition:
    opacity 0.85s var(--e-out),
    translate 0.95s var(--e-out);
}
/* the photograph arrives from the outer edge, not from below */
.jp-anim .jp-hero .jp-hero__plate {
  opacity: 0;
  translate: 40px 0;
  transition:
    opacity 1.1s var(--e-out),
    translate 1.2s var(--e-out);
}
.jp-anim .jp-nav {
  opacity: 0;
  translate: 0 -12px;
  transition:
    opacity 0.7s var(--e-out),
    translate 0.7s var(--e-out);
}
.jp-anim .jp-hero .jp-hero__plate {
  transition-delay: 0.1s;
}
.jp-anim .jp-hero .jp-lock {
  transition-delay: 0.22s;
}
.jp-anim .jp-hero .jp-display .jp-l1 {
  transition-delay: 0.36s;
}
.jp-anim .jp-hero .jp-display .jp-l2 {
  transition-delay: 0.48s;
}
.jp-anim .jp-hero .jp-orn {
  transition-delay: 0.6s;
}
.jp-anim .jp-hero .jp-lede {
  transition-delay: 0.7s;
}
.jp-anim .jp-hero .jp-card {
  transition-delay: 0.82s;
}
.jp-anim .jp-hero .jp-hero__acts {
  transition-delay: 0.96s;
}
.jp-anim .jp-nav {
  transition-delay: 0.08s;
}
.jp-anim .jp-hero.is-lit .jp-lock,
.jp-anim .jp-hero.is-lit .jp-display .jp-l1,
.jp-anim .jp-hero.is-lit .jp-display .jp-l2,
.jp-anim .jp-hero.is-lit .jp-orn,
.jp-anim .jp-hero.is-lit .jp-lede,
.jp-anim .jp-hero.is-lit .jp-card,
.jp-anim .jp-hero.is-lit .jp-hero__acts,
.jp-anim .jp-hero.is-lit .jp-hero__plate {
  opacity: 1;
  translate: none;
}
/* The navbar precedes the hero in the DOM, so no selector rooted at the hero
   can reach it. app.js sets the hook on the nav as well. */
.jp-anim .jp-nav.is-lit {
  opacity: 1;
  translate: none;
}
.jp-anim .jp-hero.is-lit .jp-hero__plate img {
  scale: calc(1 - var(--exit) * 0.03);
}

/* ---------- generic scroll reveal ----------
   I deleted these when the staged entrance was retargeted for this template,
   which meant [data-rv] added .is-in to every section and nothing listened -
   About, Amenities, Gallery, Reviews and Location simply appeared. Restored,
   with the reviews given their own longer stagger below. */
.jp-anim [data-rv] {
  opacity: 0;
  translate: 0 var(--mo-dist);
  transition:
    opacity var(--mo-dur) var(--e),
    translate var(--mo-dur) var(--e);
  transition-delay: calc(var(--i, 0) * var(--mo-stagger));
}
.jp-anim [data-rv].is-in {
  opacity: 1;
  translate: none;
}
/* the hero is driven by the entrance sequence, not by the observer */
.jp-anim .jp-hero [data-rv] {
  opacity: 1;
  translate: none;
}

/* ============================================================
   09 ABOUT — asymmetric editorial
   ============================================================ */
.jp-about {
  padding-block: clamp(4rem, 11vw, 9rem);
}
.jp-about__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 5vw, 4rem);
  align-items: center;
}
.jp-about__word {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2.6rem, 7vw, 5.5rem);
  line-height: 0.94;
  letter-spacing: -0.02em;
  color: var(--ivory);
}
.jp-about__word span {
  display: block;
}
/* A title too long for the stacked lockup is set as an ordinary heading:
   normal wrapping, a size that belongs to a sentence rather than a display
   word, and a measure so it does not run edge to edge. */
.jp-about__word--flow {
  font-size: clamp(1.65rem, 4.2vw, 2.9rem);
  line-height: 1.12;
  max-width: 18ch;
}
.jp-about__word--flow span {
  display: inline;
}

.jp-about__word span:nth-child(even) {
  color: var(--gold-soft);
  padding-inline-start: 0.5em;
}
.jp-about__shot {
  overflow: hidden;
  border-radius: var(--r-l);
  aspect-ratio: 4 / 5;
  background: var(--bg-3);
  translate: 0 var(--sy, 0px);
  box-shadow: var(--sh-l);
}
.jp-about__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.jp-about__stats {
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem 2rem;
}
.jp-about__stats b {
  display: block;
  font-family: var(--serif);
  font-size: 1.9rem;
  font-weight: 600;
  line-height: 1;
  color: var(--gold-soft);
}
.jp-about__stats span {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-about__copy .jp-btn {
  margin-top: 1.6rem;
}

/* ============================================================
   10 ROOMS — cinematic rail
   ============================================================ */
.jp-rooms {
  padding-block: clamp(3rem, 8vw, 6rem);
  overflow: hidden;
}
.jp-rooms__top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.jp-rooms__top .jp-head {
  margin-bottom: 0;
}
.jp-rail__nav {
  display: flex;
  gap: 0.5rem;
}
.jp-rooms__rail {
  margin-top: clamp(1.6rem, 4vw, 2.6rem);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 84%;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-inline: var(--gut);
  padding-bottom: 0.5rem;
  scrollbar-width: none;
}
.jp-rooms__rail::-webkit-scrollbar {
  display: none;
}
.jp-room {
  position: relative;
  scroll-snap-align: center;
  overflow: hidden;
  border-radius: var(--r-l);
  border: 1px solid transparent;
  background: var(--bg-2);
  min-width: 0;
  transition:
    transform 0.6s var(--e),
    border-color 0.5s var(--e),
    box-shadow 0.6s var(--e);
}
.jp-room__shot {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 5;
  background: var(--bg-3);
}
.jp-room__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.3s var(--e);
}
.jp-room__shot::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(6, 6, 6, 0.94) 0%, rgba(6, 6, 6, 0.12) 52%);
}
.jp-room__flag {
  position: absolute;
  top: 1rem;
  left: 1rem;
  z-index: 3;
  padding: 0.32rem 0.75rem;
  border-radius: 999px;
  background: var(--gold);
  color: #0b0b0b;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.jp-room__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: clamp(1.1rem, 2.6vw, 1.8rem);
}
.jp-room__body h3 {
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.6vw, 1.95rem);
  font-weight: 600;
  color: var(--ivory);
}
.jp-room__price {
  margin-top: 0.3rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.jp-room__price b {
  font-family: var(--serif);
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--gold-soft);
}
.jp-room__price i {
  font-style: normal;
}
.jp-room__avail {
  margin-top: 0.35rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.72rem;
  color: var(--ivory);
}
.jp-room__avail i {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: #6fbf7f;
}
/* the extra detail is revealed by hover on desktop and always shown on
   touch, where there is no hover to reveal it */
.jp-room__more {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition:
    max-height 0.55s var(--e),
    opacity 0.45s var(--e);
}
.jp-room__more p {
  margin-top: 0.7rem;
  font-size: 0.84rem;
  line-height: 1.6;
  color: var(--muted);
}
.jp-room__det {
  margin-top: 0.6rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.jp-room__det li {
  padding: 0.24rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.66rem;
  color: var(--ivory);
}
.jp-room__go {
  margin-top: 0.9rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-soft);
}
.jp-room__go i {
  display: inline-flex;
  transition: transform 0.4s var(--e);
}
.jp-room__go svg,
.jp-room__go i {
  width: 0.9rem;
  height: 0.9rem;
}

/* ============================================================
   11 AMENITIES WALL
   ============================================================ */
.jp-amen {
  padding-block: clamp(2.8rem, 5.5vw, 4.75rem);
  background: var(--bg-2);
}
.jp-wall {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.6rem, 4vw, 3rem);
  align-items: start;
}
/* Three things were wrong in this row.

   1. `align-items: baseline` aligned the icon's baseline with the title's.
      An inline-flex box has a synthesized baseline at its bottom edge, so a
      19px icon sat with its foot on a 21.6px serif baseline and its head
      about 5px ABOVE the cap height - reading as floating, not aligned.
   2. The icon column was 2rem holding a 1.2rem glyph, left-aligned, then a
      1rem gap: 29px of empty space between the icon and the word it labels.
   3. Every row carried a bottom rule including the last, so a divider sat
      between the list and the photographs below it. */
.jp-wall__list li {
  display: grid;
  grid-template-columns: 1.7rem minmax(0, 1fr);
  align-items: start;
  gap: 0.2rem 0.85rem;
  padding-block: clamp(0.9rem, 2vw, 1.35rem);
  border-bottom: 1px solid var(--line);
}
.jp-wall__list li:last-child {
  border-bottom: 0;
}
.jp-wall__list li:first-child {
  border-top: 1px solid var(--line);
}
/* The box is exactly as tall as the title's first line box and centres the
   glyph inside it, so the icon is optically centred on the word at every
   clamp step instead of hanging off a baseline.
   Longhands, not `transform`: the reveal layer resets `transform: none` and
   would out-rank the hover rules below. */
.jp-wall__ic {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 100%;
  block-size: calc(clamp(1.35rem, 3.2vw, 2.15rem) * 1.15);
  color: var(--gold);
  transition:
    translate 0.45s var(--e),
    scale 0.45s var(--e);
}
.jp-wall__ic svg,
.jp-wall__ic i {
  width: 1.35rem;
  height: 1.35rem;
  stroke-width: 1.4;
}
.jp-wall__list b {
  font-family: var(--serif);
  font-size: clamp(1.35rem, 3.2vw, 2.15rem);
  font-weight: 500;
  line-height: 1.15;
  color: var(--ivory);
  transition: color 0.4s var(--e);
}
.jp-wall__list i {
  grid-column: 2;
  font-style: normal;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--muted);
}
.jp-wall__art {
  display: grid;
  gap: clamp(0.8rem, 2vw, 1.2rem);
}
.jp-wall__art figure {
  overflow: hidden;
  border-radius: var(--r-m);
  aspect-ratio: 4 / 3;
  background: var(--bg-3);
  translate: 0 var(--sy, 0px);
}
.jp-wall__art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ============================================================
   12 GALLERY — editorial, unequal
   ============================================================ */
.jp-gal {
  padding-block: clamp(2.8rem, 5.5vw, 4.75rem);
  overflow: hidden;
}
.jp-gal__stage {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.55rem, 1.5vw, 1rem);
}
.jp-gal__f {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-m);
  background: var(--bg-3);
  aspect-ratio: 1 / 1;
  transition:
    transform 0.6s var(--e),
    box-shadow 0.6s var(--e);
}
.jp-gal__f > button {
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.jp-gal__f img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 1.35s var(--e);
}
.jp-gal__zoom {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  width: 2.75rem;
  height: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(6, 6, 6, 0.6);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: var(--ivory);
  opacity: 0;
  transition:
    opacity 0.4s var(--e),
    transform 0.4s var(--e);
}
.jp-gal__zoom svg,
.jp-gal__zoom i {
  width: 0.9rem;
  height: 0.9rem;
}
.jp-gal__f figcaption {
  position: absolute;
  left: 0.7rem;
  bottom: 0.7rem;
  padding: 0.28rem 0.65rem;
  border-radius: 0.35rem;
  background: rgba(6, 6, 6, 0.68);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ivory);
  pointer-events: none;
  transition: transform 0.45s var(--e);
}
/* the lead frame spans; only the first two get spans so the pattern
   cannot leave a hole in the MIDDLE at an arbitrary image count */
.jp-gal__f:nth-child(1) {
  grid-column: 1 / -1;
  aspect-ratio: 16 / 10;
}

/* lightbox */
.jp-lb {
  position: fixed;
  inset: 0;
  z-index: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(0.8rem, 3vw, 2rem);
  opacity: 0;
  transition: opacity 0.35s var(--e);
}
.jp-lb.is-open {
  opacity: 1;
}
.jp-lb[hidden] {
  display: none;
}
.jp-lb__scrim {
  position: absolute;
  inset: 0;
  background: rgba(4, 4, 4, 0.94);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  cursor: pointer;
}
.jp-lb__panel {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 70rem;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  scale: 0.97;
  transition: scale 0.4s var(--e-out);
}
.jp-lb.is-open .jp-lb__panel {
  scale: 1;
}
.jp-lb__x {
  align-self: flex-end;
  width: 2.875rem;
  height: 2.875rem;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: none;
  color: var(--ivory);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.jp-lb__stage figure[hidden] {
  display: none;
}
.jp-lb__stage img {
  width: 100%;
  max-height: 72svh;
  object-fit: contain;
  border-radius: var(--r-m);
}
.jp-lb__stage figcaption {
  margin-top: 0.7rem;
  text-align: center;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-lb__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.2rem;
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  color: var(--muted);
}

/* ============================================================
   Testimonials
   ============================================================ */
.jp-says {
  padding-block: clamp(2.8rem, 5.5vw, 4.75rem);
  background: var(--bg-2);
}
.jp-says__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(0.9rem, 2vw, 1.4rem);
}
.jp-say {
  padding: clamp(1.3rem, 3vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--bg);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  transition:
    border-color 0.5s var(--e),
    transform 0.5s var(--e);
}
.jp-say__q {
  font-family: var(--serif);
  font-size: 2.6rem;
  line-height: 0.5;
  color: var(--gold);
}
.jp-say blockquote {
  font-size: 0.95rem;
  line-height: 1.75;
  color: var(--ivory);
}
.jp-say__r {
  display: inline-flex;
  gap: 2px;
  color: var(--gold);
}
.jp-say__who {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.jp-say__av {
  width: 2.75rem;
  height: 2.75rem;
  flex: 0 0 auto;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-3);
}
.jp-say__av img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.jp-say__id {
  display: flex;
  flex-direction: column;
  min-width: 0;
  line-height: 1.3;
}
.jp-say__id b {
  font-size: 0.88rem;
  color: var(--ivory);
}
.jp-say__id i {
  font-style: normal;
  font-size: 0.72rem;
  color: var(--muted);
}

/* ============================================================
   13 LOCATION
   ============================================================ */
.jp-loc {
  padding-block: clamp(2.8rem, 5.5vw, 4.75rem);
}
.jp-loc__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 4vw, 3.5rem);
  align-items: center;
}
.jp-loc__copy .jp-h2 {
  margin-top: 0.8rem;
}
.jp-loc__addr {
  margin-top: 1.2rem;
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--muted);
}
.jp-loc__addr svg,
.jp-loc__addr i {
  width: 1rem;
  height: 1rem;
  flex: 0 0 auto;
  margin-top: 0.25rem;
  color: var(--gold);
}
.jp-loc__marks {
  margin-top: 1.5rem;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem 1.2rem;
}
.jp-loc__marks li {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding-inline-start: 0.8rem;
  border-inline-start: 1px solid var(--gold-line);
}
.jp-loc__marks b {
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ivory);
}
.jp-loc__marks span {
  font-size: 0.74rem;
  color: var(--gold-soft);
}
.jp-loc__copy .jp-btn {
  margin-top: 1.6rem;
}
/* the map, integrated rather than a bare iframe rectangle */
.jp-loc__map {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-l);
  border: 1px solid var(--line);
  aspect-ratio: 4 / 3;
  box-shadow: var(--sh-l);
}
.jp-loc__map iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  /* graded to sit in the dark palette instead of glowing white */
  filter: invert(0.92) hue-rotate(180deg) saturate(0.5) brightness(0.92) contrast(1.05);
}
.jp-loc__mapveil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 50%, rgba(0, 0, 0, 0) 55%, rgba(6, 6, 6, 0.55) 100%),
    linear-gradient(0deg, rgba(201, 150, 69, 0.08), rgba(201, 150, 69, 0));
}

/* ============================================================
   14 FINAL CTA
   ============================================================ */
/* 13vw resolved to 160px of padding BELOW the buttons, and the footer added
   another 80px on top of that - 240px of empty cream between the last thing
   you can click and the first thing you can read. */
.jp-final {
  position: relative;
  overflow: hidden;
  padding-block: clamp(3.2rem, 7vw, 5.5rem);
  background: var(--bg);
  text-align: center;
}
.jp-final__plate {
  position: absolute;
  inset: -6%;
  translate: 0 var(--sy, 0px);
}
.jp-final__plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focal, 50% 50%);
}
.jp-final__veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(6, 6, 6, 0.82) 0%, rgba(6, 6, 6, 0.9) 100%),
    radial-gradient(70% 50% at 50% 40%, rgba(225, 185, 103, 0.1), transparent 70%);
}
.jp-final__in {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}
.jp-final__in .jp-lede {
  margin-inline: auto;
  max-width: 34ch;
}
.jp-final__acts {
  margin-top: clamp(1.4rem, 3vw, 2.2rem);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
}

/* ============================================================
   15 FOOTER
   ============================================================ */
.jp-foot {
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  padding-block: clamp(2.6rem, 6vw, 4.5rem) 0;
}
.jp-foot__in {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 4vw, 3rem);
}
.jp-foot__brand p {
  margin-top: 1rem;
  font-size: 0.86rem;
  line-height: 1.7;
  color: var(--muted);
  max-width: 32ch;
}
/* This rule declared `color` twice: my --gold-text fix sat at the top and the
   original var(--gold) two lines below overrode it, so the 3.01:1 failure was
   never actually fixed. One declaration now. */
.jp-foot h4 {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold-text);
  margin-bottom: 1.1rem;
}
.jp-foot__col li + li {
  margin-top: 0.45rem;
}
.jp-foot__col a,
.jp-foot__addr {
  display: inline-block;
  min-height: 1.9rem;
  font-size: 0.86rem;
  color: var(--muted);
  transition: color 0.4s var(--e);
}
.social-icons {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.2rem;
}
.social-icon {
  width: 2.75rem;
  height: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  transition:
    background 0.4s var(--e),
    color 0.4s var(--e),
    border-color 0.4s var(--e),
    transform 0.4s var(--e);
}
.social-icon svg,
.social-icon i {
  width: 1rem;
  height: 1rem;
}
.jp-foot__base {
  margin-top: clamp(2rem, 5vw, 3.2rem);
  padding-block: 1.3rem;
  border-top: 1px solid var(--line);
  font-size: 0.74rem;
  color: var(--muted);
}

.back-to-top {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 420;
  width: 2.875rem;
  height: 2.875rem;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--ivory);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition:
    opacity 0.4s var(--e),
    transform 0.4s var(--e);
}
.back-to-top.is-on {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
.back-to-top svg,
.back-to-top i {
  width: 1rem;
  height: 1rem;
}

/* ============================================================
   INTERACTION — hover
   ============================================================ */
@media (hover: hover) {
  .jp-btn--gold:hover {
    transform: translateY(-2px);
    box-shadow: 0 18px 40px -16px rgba(201, 150, 69, 0.75);
  }
  .jp-btn--glass:hover {
    background: rgba(20, 20, 20, 0.72);
    border-color: var(--gold-line);
  }
  .jp-btn--line:hover {
    border-color: var(--gold-soft);
    color: var(--gold-soft);
  }
  .jp-btn:hover::after {
    opacity: 1;
  }
  .jp-btn:hover .jp-go {
    transform: translateX(4px);
  }
  .jp-logo:hover .jp-logo__mark {
    transform: rotate(-6deg);
    border-color: var(--gold-soft);
  }
  .jp-nav__links a:hover {
    color: var(--ivory);
  }
  .jp-nav__links a:hover::after {
    left: 0;
    right: 0;
  }
  .jp-feat li:hover .jp-feat__ic {
    translate: 0 -3px;
    scale: 1.08;
  }
  .jp-round:hover {
    background: rgba(28, 28, 28, 0.8);
    border-color: var(--gold-line);
    transform: scale(1.05);
  }
  .jp-room:hover {
    transform: translateY(-6px);
    border-color: var(--gold-line);
    box-shadow: var(--sh-xl);
  }
  .jp-room:hover .jp-room__shot img {
    transform: scale(var(--mo-zoom));
  }
  .jp-room:hover .jp-room__more {
    max-height: 14rem;
    opacity: 1;
  }
  .jp-room:hover .jp-room__go i {
    transform: translateX(5px);
  }
  .jp-wall__list li:hover .jp-wall__ic {
    translate: 3px 0;
    scale: 1.1;
  }
  .jp-wall__list li:hover b {
    color: var(--gold-soft);
  }
  .jp-gal__f:hover {
    translate: 0 -5px;
    box-shadow: var(--sh-l);
  }
  .jp-gal__f:hover img {
    scale: var(--mo-zoom);
  }
  .jp-gal__f:hover .jp-gal__zoom {
    opacity: 1;
    scale: 1.05;
  }
  .jp-gal__f:hover figcaption {
    opacity: 1;
    translate: 0 0;
  }
  .jp-say:hover {
    border-color: var(--gold-line);
    translate: 0 -4px;
    box-shadow: var(--sh-l);
  }
  .jp-foot__col a:hover {
    color: var(--gold-text);
  }
  .social-icon:hover {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--ink-on-dark);
    translate: 0 -3px;
  }
  .back-to-top.is-on:hover {
    background: rgba(28, 28, 28, 0.85);
    transform: translateY(-3px);
  }
}

/* ============================================================
   TOUCH MIRROR — one .is-tapped twin per hover rule, declarations copied
   verbatim. .is-tapped is set by the shared touch layer in app.js, which
   reads pointerType per event.
   ============================================================ */
@media (hover: none) {
  .jp-btn--gold.is-tapped {
    transform: translateY(-2px);
    box-shadow: 0 18px 40px -16px rgba(201, 150, 69, 0.75);
  }
  .jp-btn--glass.is-tapped {
    background: rgba(20, 20, 20, 0.72);
    border-color: var(--gold-line);
  }
  .jp-btn--line.is-tapped {
    border-color: var(--gold-soft);
    color: var(--gold-soft);
  }
  .jp-btn.is-tapped::after {
    opacity: 1;
  }
  .jp-btn.is-tapped .jp-go {
    transform: translateX(4px);
  }
  .jp-logo.is-tapped .jp-logo__mark {
    transform: rotate(-6deg);
    border-color: var(--gold-soft);
  }
  .jp-nav__links a.is-tapped {
    color: var(--ivory);
  }
  .jp-nav__links a.is-tapped::after {
    left: 0;
    right: 0;
  }
  .jp-feat li.is-tapped .jp-feat__ic {
    translate: 0 -3px;
    scale: 1.08;
  }
  .jp-round.is-tapped {
    background: rgba(28, 28, 28, 0.8);
    border-color: var(--gold-line);
    transform: scale(1.05);
  }
  .jp-room.is-tapped {
    transform: translateY(-6px);
    border-color: var(--gold-line);
    box-shadow: var(--sh-xl);
  }
  .jp-room.is-tapped .jp-room__shot img {
    transform: scale(var(--mo-zoom));
  }
  .jp-room.is-tapped .jp-room__more {
    max-height: 14rem;
    opacity: 1;
  }
  .jp-room.is-tapped .jp-room__go i {
    transform: translateX(5px);
  }
  .jp-wall__list li.is-tapped .jp-wall__ic {
    translate: 3px 0;
    scale: 1.1;
  }
  .jp-wall__list li.is-tapped b {
    color: var(--gold-soft);
  }
  .jp-gal__f.is-tapped {
    translate: 0 -5px;
    box-shadow: var(--sh-l);
  }
  .jp-gal__f.is-tapped img {
    scale: var(--mo-zoom);
  }
  .jp-gal__f.is-tapped .jp-gal__zoom {
    opacity: 1;
    scale: 1.05;
  }
  .jp-gal__f.is-tapped figcaption {
    opacity: 1;
    translate: 0 0;
  }
  .jp-say.is-tapped {
    border-color: var(--gold-line);
    translate: 0 -4px;
    box-shadow: var(--sh-l);
  }
  .jp-foot__col a.is-tapped {
    color: var(--gold-text);
  }
  .social-icon.is-tapped {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--ink-on-dark);
    translate: 0 -3px;
  }
  .back-to-top.is-on.is-tapped {
    background: rgba(28, 28, 28, 0.85);
    transform: translateY(-3px);
  }
  /* affordances that hover would reveal are permanent where there is no
     cursor: the room detail and the gallery zoom badge */
  .jp-room__more {
    max-height: 14rem;
    opacity: 1;
  }
  .jp-gal__zoom {
    opacity: 0.9;
  }
}
/* press feedback — a control must acknowledge a finger */
@media (hover: none) {
  .jp-btn.is-press,
  .jp-round.is-press,
  .social-icon.is-press,
  .back-to-top.is-press,
  .jp-gal__f.is-press,
  .jp-room__go.is-press {
    transform: scale(var(--mo-press));
  }
}
.jp-btn,
.jp-round,
.social-icon,
.back-to-top,
.jp-nav__links a,
.jp-gal__f > button,
.jp-room__go {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* ============================================================
   HERO — RESPONSIVE
   The split survives down to 900px, then the composition is rebuilt
   rather than squeezed: the photograph becomes a band above the panel,
   which is the only honest way to keep both legible on a phone.
   ============================================================ */

/* ---- 900-1199: the panel needs a larger share or the headline breaks ---- */
@media (min-width: 900px) and (max-width: 1199.98px) {
  .jp-hero {
    grid-template-columns: minmax(0, 50%) minmax(0, 1fr);
    /* the split is 50/50 in this band, and the feather has to start inside
       the panel here too or the seam comes back. Retuning the reach here
       carries the copy column's right padding with it automatically. */
    --feather-in: clamp(20px, 2.6vw, 56px);
  }
  .jp-hero__feather {
    left: calc(50% - var(--feather-in));
  }
  .jp-display {
    font-size: clamp(2.3rem, 4.6vw, 3.2rem);
  }
  .jp-card li {
    padding: 0.85rem;
  }
  .jp-card__tx i {
    font-size: 0.74rem;
  }
}

/* The stacking block that used to live here is gone.

   It came from an earlier mobile pass and set, below 900px:
     .jp-hero        grid-template-columns: 1fr; grid-template-rows: auto auto
     .jp-hero__plate grid-column: 1; grid-row: 1
     .jp-hero__panel grid-column: 1; grid-row: 2

   A later rule restored the two columns, but nothing overrode `grid-row: 1`
   on the photograph - so it kept the first row and the copy dropped beneath
   it. That is the stacked hero: building on top, text below. The reference
   keeps them side by side at every width, so the block is removed rather than
   patched, and the mobile rules further down carry the whole composition. */

/* ---- phones ---- */
@media (max-width: 599.98px) {
  .jp-card {
    grid-template-columns: minmax(0, 1fr);
  }
  /* one column: every rule is horizontal, and the 2n vertical rule must go */
  .jp-card li:nth-child(2n) {
    border-inline-start: 0;
  }
  .jp-card li:nth-child(n + 2) {
    border-block-start: 1px solid var(--line);
  }
  .jp-card li {
    padding: 0.85rem 1rem;
  }
  .jp-hero__acts .jp-btn {
    flex: 1 1 auto;
  }
  .jp-lock__mark {
    width: 2.6rem;
    height: 2.6rem;
    font-size: 1.15rem;
  }
}

@media (max-width: 379.98px) {
  .jp-hero__acts .jp-btn {
    width: 100%;
  }
  .jp-display {
    font-size: 1.95rem;
  }
}

/* ============================================================
   RESPONSIVE — a recomposition at every listed width
   ============================================================ */

/* 320–374: the tightest case. Nothing may overflow. */

/* 375–429 */
/* Four across needs about 74px an item to hold a two-word label; below
   560px it cannot get that, so the strip goes 2x2. */
/* ---- feature strip below 720: chips, not a ruled table ----
   Hairline dividers work on the desktop composition because they sit on the
   dark half of the scrim. Over a photograph on a phone they read as a broken
   table, and the quadrants leave the icons floating in dead space.

   Each feature becomes its own glass chip instead. That gives the label a
   guaranteed background - so contrast no longer depends on what happens to
   be behind it - and matches the statistics panel already on the page.
   `li + li` has to be named explicitly here: at 0,1,2 it outranks the
   `.jp-feat li` shorthand and its old border-inline-start would survive. */

/* Below 560 the cells are half the screen wide, so stacking a centred icon
   over a centred label wastes the width and orphans the second word -
   "24/7 Safety &" over "Security". Icon left, label right, ranged left. */

/* the stats panel: 2 across on phones, all cells in a row once there is
   room. It never scrolls horizontally — a swipeable panel hides data. */
/* Dividers belong to the four-column bar. Below 720px the panel is a swipe
   rail, where a leading border on a snapped card reads as a stray line. */
@media (min-width: 720px) {
  .jp-stat + .jp-stat {
    border-inline-start: 1px solid var(--line);
  }
}

/* 720, not 700, so the sections turn over on the same line as the hero -
   at 700-719 the page was showing a four-column gallery under a mobile hero */
@media (min-width: 720px) {
  .jp-gal__stage {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-auto-flow: row dense;
  }
  .jp-gal__f:nth-child(1) {
    grid-column: span 2;
    grid-row: span 2;
    aspect-ratio: 1 / 1;
  }
  .jp-gal__f:nth-child(2) {
    grid-column: span 2;
    aspect-ratio: 16 / 9;
  }
  .jp-gal__f:nth-child(n + 3) {
    aspect-ratio: 1 / 1;
  }
  /* The default spans - a 2x2 hero tile plus one double-wide - consume ten
     cells for six photographs, and ten does not divide by four, so the last
     row sits half empty. These counts get spans that tile exactly:
       5 -> 2x2 + four singles      = 8 cells, 2 rows
       6 -> two wides + four singles = 8 cells, 2 rows
       7 -> one wide + six singles   = 8 cells, 2 rows
     Eight or more keeps the original arrangement, which already fills. */
  .jp-gal__stage[data-n='6'] .jp-gal__f:nth-child(1),
  .jp-gal__stage[data-n='6'] .jp-gal__f:nth-child(2) {
    grid-column: span 2;
    grid-row: span 1;
    aspect-ratio: 16 / 9;
  }
  .jp-gal__stage[data-n='5'] .jp-gal__f:nth-child(2) {
    grid-column: span 1;
    aspect-ratio: 1 / 1;
  }
  .jp-gal__stage[data-n='7'] .jp-gal__f:nth-child(1) {
    grid-column: span 2;
    grid-row: span 1;
    aspect-ratio: 16 / 9;
  }
  .jp-gal__stage[data-n='7'] .jp-gal__f:nth-child(2) {
    grid-column: span 1;
    aspect-ratio: 1 / 1;
  }
  .jp-says__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .jp-foot__in {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1fr);
  }
  .jp-rooms__rail {
    grid-auto-columns: 46%;
  }
  .jp-wall {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  }
  .jp-wall__art {
    grid-template-columns: minmax(0, 1fr);
  }
  .jp-loc__in {
    grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  }
}

@media (min-width: 1000px) {
  .jp-about__in {
    /* the asymmetry the brief asks for: word, photograph, copy */
    grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.15fr) minmax(0, 0.95fr);
    align-items: center;
  }
  .jp-rooms__rail {
    grid-auto-columns: 31.5%;
  }
  .jp-gal__f:nth-child(3),
  .jp-gal__f:nth-child(6) {
    /* the deliberate offsets that make it a composition, not a grid.
       margin, not translate — a translated grid item leaves its cell and
       collides with its neighbour. */
    margin-block-start: clamp(1rem, 2vw, 2.2rem);
  }
}

/* ultra-wide: stop the line lengths running away */
@media (min-width: 1800px) {
  :root {
    --maxw: 108rem;
  }
  /* The 52rem cap that used to live here is gone: it predates the ratio
     column and broke the building share on ultrawide (64% at 2560px, outside
     the 55-62% band). The 42% share already holds the ratio at any width. */
  /* the brief fixes the description at 420px, so the old ultrawide
     override is gone */
}

/* ---- hero card hover, with its .is-tapped twin ---- */
@media (hover: hover) {
  .jp-card li:hover .jp-card__ic {
    translate: 2px 0;
    scale: 1.08;
  }
  .jp-card li:hover .jp-card__tx b {
    color: var(--gold-soft);
  }
}
@media (hover: none) {
  .jp-card li.is-tapped .jp-card__ic {
    translate: 2px 0;
    scale: 1.08;
  }
  .jp-card li.is-tapped .jp-card__tx b {
    color: var(--gold-soft);
  }
}
@media (prefers-reduced-motion: reduce) {
  .jp-hero__plate,
  .jp-hero__copy,
  .jp-dust,
  .jp-about__shot,
  .jp-final__plate,
  .jp-room,
  .jp-gal__f,
  .jp-say,
  .jp-btn,
  .jp-round,
  .jp-lb,
  .jp-lb__panel {
    transition: none;
  }
  .jp-dust,
  .boot-line::after {
    animation: none;
  }
  .jp-hero__plate img {
    scale: 1;
    transition: none;
  }
  .jp-hero__plate {
    transform: none;
  }
  .jp-card li:hover .jp-card__ic,
  .jp-card li.is-tapped .jp-card__ic {
    translate: none;
    scale: 1;
  }
  .jp-card__ic {
    transition: none;
  }
  /* the feature icons now animate on longhands, so reduced motion has to
     neutralise those rather than transform */
  .jp-feat__ic {
    transition: none;
  }
  .jp-feat li:hover .jp-feat__ic,
  .jp-feat li.is-tapped .jp-feat__ic,
  .jp-wall__list li:hover .jp-wall__ic,
  .jp-wall__list li.is-tapped .jp-wall__ic {
    translate: none;
    scale: 1;
  }
  .jp-wall__ic {
    transition: none;
  }
  /* vertical parallax on stacked items is what pulls them out of line */
  .jp-wall__art figure,
  .jp-gal__f,
  .jp-about__shot {
    translate: none;
  }
  /* detail that hover would reveal is simply always open */
  .jp-room__more {
    max-height: 14rem;
    opacity: 1;
    transition: none;
  }
}

/* ============================================================
   LUXURY PASS — everything below the hero
   Scoped strictly to section selectors. Nothing here touches
   .jp-hero, .jp-lock, .jp-display, .jp-orn, .jp-card or the
   hero's buttons.
   ============================================================ */

/* ---- amenities: the icon earns a gold ring, the row earns air ---- */
.jp-wall__list li {
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.35rem 1.15rem;
  padding-block: clamp(1.1rem, 2.4vw, 1.6rem);
  transition: background 0.4s var(--e);
}
.jp-wall__ic {
  display: grid;
  place-items: center;
  inline-size: clamp(2.6rem, 3.6vw, 3.2rem);
  block-size: clamp(2.6rem, 3.6vw, 3.2rem);
  border: 1px solid var(--gold-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--gold-soft);
}
.jp-wall__ic svg,
.jp-wall__ic i {
  width: 1.2rem;
  height: 1.2rem;
}
.jp-wall__list b {
  font-family: var(--display);
  font-size: clamp(1.15rem, 1.9vw, 1.5rem);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.jp-wall__list i {
  font-size: 0.86rem;
  line-height: 1.6;
}

/* ---- gallery: framed, with the caption arriving on hover ---- */
.jp-gal__f {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-m);
  background: var(--bg-3);
  box-shadow: var(--sh-m);
}
.jp-gal__f img {
  transition: scale 0.9s var(--e);
}
.jp-gal__f figcaption {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: 1.6rem 1.1rem 0.9rem;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-on-dark);
  background: linear-gradient(0deg, rgba(18, 14, 9, 0.82) 0%, rgba(18, 14, 9, 0) 100%);
  translate: 0 0.4rem;
  opacity: 0;
  transition:
    opacity 0.45s var(--e),
    translate 0.45s var(--e);
}

/* ---- reviews: quiet cards, serif quotes ---- */
.jp-says__grid {
  gap: clamp(1rem, 2vw, 1.6rem);
}
.jp-say {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding: clamp(1.6rem, 3vw, 2.4rem);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: rgba(255, 255, 255, 0.55);
  transition:
    translate 0.5s var(--e),
    box-shadow 0.5s var(--e);
}
.jp-say__q {
  font-family: var(--display);
  font-size: 3.4rem;
  line-height: 0.6;
  color: var(--gold-line);
}
.jp-say blockquote {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  line-height: 1.5;
  color: var(--ivory);
}
.jp-say__id i {
  font-style: normal;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-say__who {
  margin-top: auto;
  padding-top: 0.4rem;
  border-top: 1px solid var(--line);
}

/* ---- location: the map gets a frame ---- */
.jp-loc__map,
.jp-loc iframe {
  border-radius: var(--r-m);
  border: 1px solid var(--line);
  box-shadow: var(--sh-m);
  overflow: hidden;
}
.jp-loc__addr {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--muted);
}
.jp-loc__addr svg,
.jp-loc__addr i {
  color: var(--gold-soft);
  flex: 0 0 auto;
}

/* ---- closing statement ---- */
.jp-final {
  background: var(--bg-2);
  border-block: 1px solid var(--line);
}
.jp-final .jp-h2 {
  margin-inline: auto;
  max-width: 20ch;
}

/* ---- footer ---- */
.jp-foot__brand b {
  font-family: var(--display);
  font-weight: 600;
}
/* --gold-soft is 4.30:1 on the footer's raised ground - under the 4.5 these
   words need. --gold-text is 4.73:1 there. */
.jp-foot__col b {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--gold-text);
}

@media (hover: hover) {
  .jp-wall__list li:hover {
    background: rgba(255, 255, 255, 0.45);
  }
}
@media (hover: none) {
  .jp-wall__list li.is-tapped {
    background: rgba(255, 255, 255, 0.45);
  }
  /* a caption that only appears on hover is unreachable on touch, so on a
     touch device it is simply always visible */
  .jp-gal__f figcaption {
    opacity: 1;
    translate: 0 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .jp-gal__f img,
  .jp-say,
  .jp-gal__f figcaption {
    transition: none;
  }
  .jp-gal__f:hover img,
  .jp-gal__f.is-tapped img {
    scale: 1;
  }
  .jp-say:hover,
  .jp-say.is-tapped {
    translate: none;
  }
}

/* ---- the closing section, with and without something to say ---- */
.jp-final .jp-display--sm {
  /* the hero headline scale is far too large for a closing line */
  font-family: var(--display);
  font-size: clamp(1.9rem, 3.4vw, 3rem);
  line-height: 1.08;
  letter-spacing: -0.018em;
  max-width: 18ch;
  margin-inline: auto;
  color: var(--ivory);
}
.jp-final .jp-eyebrow {
  justify-content: center;
}
.jp-final__in {
  gap: 1rem;
}

/* No heading and no copy: a quiet strip, not a 560px void. */
.jp-final--bare {
  padding-block: clamp(2.2rem, 4vw, 3.2rem);
}
.jp-final--bare .jp-final__acts {
  margin-top: 0;
}

/* ============================================================
   HEADER + FOOTER
   ============================================================ */

/* ---- the mark, shared by the navbar and the footer ---- */
.jp-logo__mark {
  font-family: var(--display);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--gold-text);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
}
.jp-logo__tx b {
  font-family: var(--display);
  font-size: clamp(1rem, 1.5vw, 1.2rem);
  font-weight: 600;
  letter-spacing: -0.005em;
}
.jp-logo__tx i {
  font-style: normal;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---- navbar ---- */
.jp-nav__in {
  min-height: 4.6rem;
  gap: clamp(0.8rem, 2vw, 1.6rem);
}
.jp-nav.is-stuck .jp-nav__in {
  min-height: 4rem;
}
.jp-nav__links {
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2.2vw, 2rem);
  margin-inline: auto;
}
.jp-nav__links a {
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--muted);
  text-decoration: none;
}

/* ---- footer ---- */
.jp-foot {
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  padding-block: clamp(2.4rem, 4.5vw, 3.6rem) 0;
}
.jp-foot__in {
  gap: clamp(2.2rem, 5vw, 4rem);
}
.jp-foot__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.1rem;
  max-width: 30ch;
}
.jp-foot__brand p {
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--muted);
}
.jp-foot__col ul {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.jp-foot__col a,
.jp-foot__addr {
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.35s var(--e);
}
.jp-foot__addr {
  display: block;
  max-width: 26ch;
}
.jp-foot__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  margin-top: clamp(2.4rem, 5vw, 3.6rem);
  letter-spacing: 0.02em;
}
.social-icons {
  display: flex;
  gap: 0.6rem;
}
.social-icon {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  transition:
    color 0.35s var(--e),
    border-color 0.35s var(--e);
}

@media (min-width: 720px) {
  .jp-foot__in {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  .jp-nav__links a::after {
    transition: none;
  }
}

/* ============================================================
   REVIEWS — entrance, and the dialog
   ============================================================ */

/* the cards arrive on a longer stagger than the generic reveal, and the gold
   quote mark follows its own card in */
.jp-says__grid .jp-say {
  --mo-stagger: 110ms;
}
.jp-anim .jp-say .jp-say__q {
  opacity: 0;
  scale: 0.86;
  transition:
    opacity 0.6s var(--e-out),
    scale 0.6s var(--e-out);
  transition-delay: calc(var(--i, 0) * 110ms + 260ms);
  transform-origin: left top;
}
.jp-anim .jp-say.is-in .jp-say__q {
  opacity: 1;
  scale: 1;
}

.jp-say {
  position: relative;
}
.jp-say__open {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 2.75rem;
  padding: 0 0.2rem;
  border: 0;
  background: none;
  cursor: pointer;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-text);
  transition: gap 0.35s var(--e);
}
.jp-say__open svg,
.jp-say__open i {
  width: 0.85rem;
  height: 0.85rem;
}

/* ---- the dialog ---- */
/* `display: grid` here is an AUTHOR rule and the [hidden] attribute only sets
   display:none in the UA stylesheet, so the author rule wins and the dialog is
   never actually hidden. The result is a full-viewport fixed overlay at
   z-index 900 lying over the whole page - invisible, because the scrim sits at
   opacity 0, and swallowing every click beneath it. That is why Call Now and
   Get Directions stopped responding. .jp-lb has this guard; this did not. */
.jp-rev[hidden] {
  display: none;
}
.jp-rev {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
}
.jp-rev__scrim {
  position: absolute;
  inset: 0;
  background: rgba(22, 19, 15, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 0.4s var(--e);
}
.jp-rev.is-open .jp-rev__scrim {
  opacity: 1;
}
.jp-rev__panel {
  position: relative;
  width: min(46rem, 100%);
  padding: clamp(2rem, 5vw, 3.4rem);
  border: 1px solid var(--line);
  border-radius: var(--r-l);
  background: var(--bg);
  box-shadow: var(--sh-xl);
  opacity: 0;
  translate: 0 18px;
  scale: 0.98;
  transition:
    opacity 0.45s var(--e-out),
    translate 0.45s var(--e-out),
    scale 0.45s var(--e-out);
}
.jp-rev.is-open .jp-rev__panel {
  opacity: 1;
  translate: none;
  scale: 1;
}
.jp-rev__x {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: none;
  cursor: pointer;
  color: var(--muted);
}
.jp-rev__q {
  display: block;
  font-family: var(--display);
  font-size: 3.6rem;
  line-height: 0.5;
  color: var(--gold-line);
}
.jp-rev__stage blockquote {
  margin: 1.4rem 0 0;
  font-family: var(--serif);
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  line-height: 1.45;
  color: var(--ivory);
}
.jp-rev__stage figcaption {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-top: 1.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
}
.jp-rev__stage figcaption b {
  font-weight: 600;
  color: var(--ivory);
}
.jp-rev__stage figcaption i {
  font-style: normal;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-rev__bar {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: 1.8rem;
}
.jp-rev__bar p {
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  color: var(--muted);
}
.jp-rev__src {
  margin-inline-start: auto;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-text);
}
body.jp-locked {
  overflow: hidden;
}

@media (hover: hover) {
  .jp-say__open:hover {
    gap: 0.75rem;
  }
  .jp-rev__x:hover {
    color: var(--ivory);
    border-color: var(--gold-line);
  }
}
@media (hover: none) {
  .jp-say__open.is-tapped {
    gap: 0.75rem;
  }
  .jp-rev__x.is-tapped {
    color: var(--ivory);
    border-color: var(--gold-line);
  }
}
@media (prefers-reduced-motion: reduce) {
  .jp-rev__scrim,
  .jp-rev__panel,
  .jp-say__open,
  .jp-anim .jp-say .jp-say__q {
    transition: none;
  }
  .jp-anim .jp-say .jp-say__q {
    opacity: 1;
    scale: 1;
  }
  .jp-rev__panel {
    opacity: 1;
    translate: none;
    scale: 1;
  }
}

/* ---- footer list density ----
   The rows were set by an inherited `min-height: 1.9rem` plus a 0.7rem gap.
   Kept generous on touch, where 44px targets matter, and tightened for a
   pointer, where the airiness just reads as a gap in the layout. */
.jp-foot__col ul {
  gap: 0.5rem;
}
.jp-foot__col a {
  min-height: 2.75rem;
  display: flex;
  align-items: center;
}
/* `pointer: fine` alone, not `hover: hover`. This is a density adjustment for
   a precise pointer, not an interaction state - putting it in a hover block
   implied it needed an .is-tapped twin, which it does not. */
@media (pointer: fine) {
  .jp-foot__col ul {
    gap: 0.15rem;
  }
  .jp-foot__col a {
    min-height: 2rem;
  }
}
.jp-foot__brand p {
  max-width: 34ch;
}
.jp-foot__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
  margin-top: 0.2rem;
}
.jp-foot__meta span {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-foot__meta svg,
.jp-foot__meta i {
  width: 0.95rem;
  height: 0.95rem;
  color: var(--gold);
}

/* ============================================================
   BACKGROUND GRID
   ------------------------------------------------------------
   The lines LIGHTEN the ground rather than darkening it, and that
   is a contrast decision rather than a stylistic one. Gold text on
   the raised band sits at 4.73:1 with only 0.23 of headroom, and
   gold icons at 3.01:1 with 0.01. A dark hairline at even 3% alpha
   drops those to 4.46 and 2.84 - both below the line - for any word
   that happens to fall on one. A white hairline moves them the other
   way: 4.73 -> 5.25 and 3.01 -> 3.34.

   Six columns, measured off the content wrap rather than the
   viewport, so the lines land on the boundaries the layout already
   uses instead of cutting through it at random.
   ============================================================ */
:root {
  --grid-line: rgba(255, 255, 255, 0.55);
  --grid-col: calc(min(var(--maxw), 100vw - 2 * var(--gut)) / 6);
  --grid-row: 7.5rem;
}

.jp-amen,
.jp-gal,
.jp-says,
.jp-loc,
.jp-final,
.jp-foot {
  position: relative;
  isolation: isolate;
}
.jp-amen::before,
.jp-gal::before,
.jp-says::before,
.jp-loc::before,
.jp-final::before,
.jp-foot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
    linear-gradient(0deg, var(--grid-line) 1px, transparent 1px);
  background-size:
    var(--grid-col) 100%,
    100% var(--grid-row);
  background-position: center top;
  /* the horizontals fade out toward the section edges so the grid reads as
     texture rather than as a table drawn round the content */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
}

/* content sits above the grid */
.jp-wrap {
  position: relative;
  z-index: 1;
}

/* Below 720 the six columns land about 55px apart, which reads as hatching
   rather than structure. Verticals only, on a wider pitch. */
@media (max-width: 719.98px) {
  :root {
    --grid-col: calc((100vw - 2 * var(--gut)) / 3);
  }
  .jp-amen::before,
  .jp-gal::before,
  .jp-says::before,
  .jp-loc::before,
  .jp-final::before,
  .jp-foot::before {
    background-image: linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
    background-size: var(--grid-col) 100%;
  }
}

/* ============================================================
   MOBILE — the desktop composition rearranged, not replaced
   The reference keeps the cream/type on the left and the real building
   on the right at phone width too; it does not stack them.
   ============================================================ */
@media (max-width: 899.98px) {
  /* the header is cream, never black */
  .jp-nav:not(.is-stuck),
  .jp-nav.is-stuck {
    background: rgba(247, 243, 235, 0.94);
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    backdrop-filter: blur(14px) saturate(1.1);
    border-bottom-color: var(--line);
    color: var(--ivory);
  }
  .jp-nav:not(.is-stuck) .jp-nav__in > * {
    opacity: 1;
    visibility: visible;
  }
  .jp-nav:not(.is-stuck) {
    pointer-events: auto;
  }
  .jp-nav__in {
    min-height: 5.2rem;
  }
  .jp-nav.is-stuck .jp-nav__in {
    min-height: 4.6rem;
  }
  /* the call button reads as a soft champagne tile, as in the reference */
  .jp-nav__cta {
    order: 1;
    margin-inline-start: auto;
    width: 3rem;
    height: 3rem;
    padding: 0;
    display: grid;
    place-items: center;
    border-radius: 14px;
    background: rgba(167, 123, 46, 0.16);
    border: 1px solid var(--gold-line);
    color: var(--gold-text);
    font-size: 0;
    gap: 0;
  }
  .jp-nav__cta svg,
  .jp-nav__cta i {
    width: 1.3rem;
    height: 1.3rem;
  }
  .jp-nav .nav-toggle {
    order: 2;
    display: inline-flex;
  }
  .nav-toggle span {
    background: var(--ivory);
  }

  /* the split survives: copy ~42%, building the rest, bleeding right */
  .jp-hero {
    grid-template-columns: minmax(0, 42%) minmax(0, 1fr);
    min-height: auto;
    --panel-drop: clamp(3rem, 8svh, 5rem);
    /* the feature panel leaves the column here (grid-column: 1 / -1), so this
       reach only has the lede and the headline to clear */
    --feather-in: clamp(18px, 4vw, 40px);
  }
  .jp-hero__in {
    padding-block: clamp(1.6rem, 5svh, 2.6rem) calc(var(--panel-drop) + clamp(1rem, 3svh, 1.8rem));
  }
  .jp-hero__feather {
    left: calc(42% - var(--feather-in));
    width: clamp(80px, 22vw, 150px);
  }
  /* tall, and showing as much facade as the frame allows */
  .jp-hero__plate {
    min-height: 62svh;
    transform: none;
  }
  .jp-hero__plate img {
    object-position: 42% 42%;
  }
  .jp-display {
    /* large and dramatic, with controlled breaks rather than shrunk to fit */
    font-size: clamp(1.9rem, 8.4vw, 2.9rem);
    line-height: 1.03;
  }
  .jp-lede {
    max-width: none;
    font-size: 0.92rem;
    line-height: 1.55;
  }
  .jp-hero__acts .jp-btn {
    width: auto;
  }

  /* the panel drops below the hero as a 2x2 */
  .jp-card {
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    grid-column: 1 / -1;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin: calc(-1 * var(--panel-drop) / 2) var(--edge) 0;
    max-width: none;
  }
  /* `li + li` would rule item 3, which starts the second row */
  .jp-card li + li {
    border-inline-start: 0;
  }
  .jp-card li:nth-child(2n) {
    border-inline-start: 1px solid var(--line);
  }
  .jp-card li:nth-child(n + 3) {
    border-block-start: 1px solid var(--line);
  }
  .jp-hero + * {
    padding-top: clamp(2rem, 6vw, 3.5rem) !important;
  }

  /* the rail sits at the bottom edge, out of the thumb's way up the side */
  .jp-rail {
    top: auto;
    bottom: clamp(0.8rem, 2svh, 1.4rem);
    right: 50%;
    translate: 50% 0;
    flex-direction: row;
  }

  /* amenities become a swipe rail */
  .jp-wall__list {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 62%;
    grid-template-columns: none;
    gap: 0.7rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 0.4rem;
    margin-inline: calc(-1 * var(--gut));
    padding-inline: var(--gut);
  }
  .jp-wall__list::-webkit-scrollbar {
    display: none;
  }
  .jp-wall__list li {
    scroll-snap-align: start;
    border: 1px solid var(--line);
    border-radius: 20px;
    background: var(--glass);
  }
}

/* ---- small phones ----
   The reference does NOT stack: at phone width it keeps the copy on the left
   and the building on the right, with the headline breaking to four lines in a
   narrow column. Stacking would be "a basic stacked responsive layout", which
   is what the brief rules out. Measured: at 320px the copy column is 121px and
   "Comfort" at 34px needs about 119px, so the break holds all the way down. */
@media (max-width: 559.98px) {
  /* NOTE: the hero's grid, min-height and object-position used to be re-tuned
     here and none of it ever ran. The `max-width: 767.98px` block LATER in this
     file switches .jp-hero to `display: block` with an absolutely positioned
     plate, so there is no grid to re-column and no min-height to set, and its
     object-position wins on source order at equal specificity. Four rules that
     read like careful mobile tuning, including a comment about keeping the sign
     in frame, were dead the whole time. Removed rather than reordered: the
     values that do run are better than the ones that did not. */
  .jp-display {
    font-size: clamp(1.9rem, 10.5vw, 2.6rem);
    letter-spacing: -0.022em;
  }
  .jp-lede {
    font-size: 0.86rem;
    line-height: 1.5;
  }
  .jp-hero__acts .jp-btn--lg {
    min-height: 48px;
    padding: 0 18px;
    font-size: 0.86rem;
  }
  .jp-wall__list {
    grid-auto-columns: 74%;
  }
}

@media (max-width: 379.98px) {
  .jp-card {
    grid-template-columns: minmax(0, 1fr);
  }
  .jp-card li:nth-child(2n) {
    border-inline-start: 0;
  }
  .jp-card li:nth-child(n + 2) {
    border-block-start: 1px solid var(--line);
  }
  .jp-display {
    font-size: 1.85rem;
  }
}

@media (hover: hover) {
  .jp-rail__a:hover {
    background: var(--gold);
    color: var(--ink-on-dark);
    scale: 1.06;
  }
}
@media (hover: none) {
  .jp-rail__a.is-tapped {
    background: var(--gold);
    color: var(--ink-on-dark);
    scale: 1.06;
  }
}

/* ============================================================
   MOBILE HERO — the reference composition, to its own numbers
   ONE hero. Copy left, the real building absolutely placed on the
   right and bleeding past the edge, a cream fade between them, and
   the 2x2 panel floating over the bottom. Never stacked.

   Two of the supplied values are changed, and only these two:
     eyebrow  #A67C32 measures 3.45:1 at 10px, and 10px text needs
              4.5:1. Same hue taken darker to #8C682A (4.64:1).
     divider  #B68A42 measures 2.86:1; a rule is a graphic and needs
              3:1, so it takes #A77A2C (3.50:1).
   Everything else is as specified.
   ============================================================ */
@media (max-width: 767.98px) {
  .jp-nav__in {
    min-height: 64px;
    padding-inline: 16px;
    gap: 10px;
    align-items: center;
  }
  /* the logo takes the slack so the two controls sit flush right, the same
     size, on the same centre line */
  .jp-logo {
    flex: 1 1 auto;
    min-width: 0;
  }
  .jp-nav.is-stuck .jp-nav__in {
    min-height: 60px;
  }
  .jp-logo__mark {
    width: 2.4rem;
    height: 2.4rem;
    font-size: 0.9rem;
  }
  .jp-logo__tx b {
    font-size: 0.86rem;
    letter-spacing: 0.04em;
  }
  .jp-logo__tx i {
    font-size: 0.56rem;
    letter-spacing: 0.18em;
  }
  .jp-nav__cta {
    flex: 0 0 auto;
    order: 1;
    margin-inline-start: 0;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 13px;
  }
  .jp-nav .nav-toggle {
    flex: 0 0 auto;
    order: 2;
    margin-inline-start: 0;
    width: 44px;
    height: 44px;
  }

  /* one hero, tall enough to hold copy, building and panel together */
  .jp-hero {
    display: block;
    position: relative;
    min-height: 720px;
    overflow: hidden;
    background: var(--bg);
    /* was `none`, which silently killed the 3D on phones: the scroll handler
       writes --ry/--rx on coarse pointers and with no frustum those flatten to
       nothing. Nearer than desktop, because the plate is smaller here. */
    perspective: 900px;
    perspective-origin: 60% 45%;
    --edge: 22px;
    /* ONE number for the plate, the feather and the copy measure. It was 62%,
       and the copy was independently set to 43% -- 43 + 62 = 105, so the two
       overlapped by 5% of the viewport at every phone width and the text was
       printed onto the building. Declared here so the three can no longer
       disagree: widen the plate and the copy narrows to match, automatically. */
    --plate-w: 54%;
  }
  /* the building: absolute, right-anchored, bleeding past the edge */
  .jp-hero__plate {
    position: absolute;
    top: 0;
    right: 0;
    left: auto;
    width: var(--plate-w);
    /* Full hero height, and faded out at the bottom.
       A FIXED height -- 610px before, and briefly 470px -- ends the photograph
       partway down the page with a hard horizontal edge against the cream, and
       that seam cutting across the middle of the layout is more conspicuous
       than any crop. Shortening it to show more of the building made the seam
       worse, not better: it moved the cut further up, into the middle of the
       copy.
       So the plate now spans the whole hero and dissolves instead of stopping.
       The building reads as tall as the section allows, which is the point of
       this composition, and there is no line across the middle. */
    height: 100%;
    /* the dissolve. Without it the bottom of the photograph is a hard edge --
       the same reason .jp-hero__feather exists for the vertical seam. */
    -webkit-mask-image: linear-gradient(180deg, #000 0, #000 68%, transparent 97%);
    mask-image: linear-gradient(180deg, #000 0, #000 68%, transparent 97%);
    min-height: 0;
    max-height: none;
    z-index: 1;
    margin: 0;
    aspect-ratio: auto;
    transform: none;
    overflow: hidden;
  }
  .jp-hero__plate img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* The only object-position that reaches the screen below 768px. The
       narrower `max-width: 559.98px` block sits EARLIER in the file, so at
       equal specificity this one wins on source order and its tuning never
       ran -- that rule has been deleted rather than reordered, because 52%
       is the better value. Measured against 30/38/62% side by side: 52% is
       the only one that centres the facade and keeps the entrance glow in a
       narrow crop. */
    object-position: 52% center;
    scale: 1;
  }
  /* the cream fade, so there is no hard vertical line */
  .jp-hero__feather {
    top: 0;
    bottom: auto;
    left: auto;
    right: 0;
    /* MUST also track the plate's WIDTH, for the same reason it tracks the
       height: a feather narrower or wider than the photograph it is feathering
       leaves either a raw vertical edge or a cream band over the copy. */
    width: var(--plate-w);
    /* MUST track the plate's height. While the plate was a fixed 610px this
       matched by coincidence; the moment the plate became height:100% the
       feather stopped 110px short and the bottom of the photograph met the
       cream as a raw vertical edge — a dark line down the seam, which is
       exactly what the feather exists to prevent. Measured: the photograph
       sits 123-162 luminance below the cream at EVERY crop position, so no
       object-position hides this. The feather has to cover the full edge. */
    height: 100%;
    /* fade out with the plate, or the gradient outlives the thing it is
       softening and paints a cream column over bare page */
    -webkit-mask-image: linear-gradient(180deg, #000 0, #000 68%, transparent 97%);
    mask-image: linear-gradient(180deg, #000 0, #000 68%, transparent 97%);
    z-index: 2;
    translate: none;
    /* A SMOOTH fade, no flat section. Holding the cream at 100% for the first
       20% painted a 44px cream column over the photograph — visible as a white
       band with a hard left edge. The right fix is to keep the text off the
       translucent region, not to paint over the building; the headline measure
       below does that. */
    background: linear-gradient(
      90deg,
      #f8f4ec 0%,
      rgba(248, 244, 236, 0.92) 5%,
      rgba(248, 244, 236, 0.55) 14%,
      rgba(248, 244, 236, 0.12) 26%,
      transparent 40%
    );
  }
  /* the copy sits above the photograph, on the left */
  .jp-hero__in {
    position: relative;
    z-index: 4;
    display: block;
    /* the type column stays 43% as specified; the panel below breaks out of it */
    width: 100%;
    /* the bar is position:fixed and 64px tall, so 42px of padding put the
       eyebrow underneath it - only "WOMEN" was visible */
    padding: 106px 0 0 22px;
    min-height: 0;
  }
  /* MEASURED IN PRODUCTION, not reasoned about. At 412px the plate's left edge
     sits at 151.8px while this column ran to 199px, so EVERY line of copy was
     printed on top of the building:

       eyebrow  37.9px over    headline 18.5px over
       lede     20.2px over    buttons  37.9px over

     The copy is z-index 4 over a z-index 1 plate, so it was never hidden -- it
     was legible-ish dark text laid across a photograph of a wall, with only
     the feather's ~13px opaque head behind any of it.

     The headline alone got a `min(155px, 36vw)` measure when this was last
     touched; the eyebrow, lede, ornament and buttons never did, and 43% of the
     viewport is simply wider than the 38% of it that exists to the left of a
     62%-wide right-anchored plate. Tying the measure to the plate's own edge
     is what stops the two from ever being set independently again. */
  .jp-hero__copy > :not(.jp-card) {
    /* --plate-w is declared on .jp-hero__plate's own rule below. 34px is the
       22px gutter plus 12px of breathing room before the photograph. */
    max-width: calc(100% - var(--plate-w, 54%) - 34px);
  }
  .jp-hero__copy {
    width: 100%;
    translate: none;
  }
  .jp-eyebrow--hero {
    margin-top: 5px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 3px;
    color: #8c682a;
  }
  .jp-eyebrow--hero::before {
    display: none;
  }
  .jp-display {
    /* Scales with the viewport instead of a fixed 155px. The plate is 62%
       right-anchored, so the clear cream space to its left is 38vw minus the
       22px gutter; at a fixed 155px the headline pushed past that on every
       phone under 430px and ended up on ahalf-transparent fade. min() keeps the
       reference measure on large phones and pulls it in on small ones. */
    width: min(155px, 36vw);
    margin-top: 26px;
    font-family: 'Cormorant Garamond', 'Playfair Display', serif;
    font-size: clamp(39px, 10.8vw, 47px);
    font-weight: 500;
    line-height: 0.96;
    letter-spacing: -1.5px;
  }
  .jp-display .jp-l1 {
    color: #171511;
  }
  .jp-display .jp-l2 {
    color: #a97c2e;
  }
  .jp-orn {
    margin-top: 24px;
    gap: 6px;
  }
  .jp-orn::before {
    width: 72px;
    height: 1px;
    background: #a77a2c;
  }
  .jp-orn::after {
    width: 26px;
    height: 1px;
    background: rgba(167, 122, 44, 0.55);
  }
  .jp-lede {
    width: 150px;
    /* `max-width: none` was here, which opted the lede out of the shared copy
       measure above. 150px happens to fit today, but an opt-out is how the
       eyebrow/lede/buttons drifted onto the building in the first place: the
       cap has to apply to everything in the column or it guarantees nothing. */
    margin-top: 22px;
    font-size: 12px;
    line-height: 1.65;
    color: #665f56;
  }
  .jp-hero__acts {
    margin-top: 24px;
  }
  .jp-hero__acts .jp-btn {
    width: 145px;
    min-height: 52px;
    padding: 0 16px;
    justify-content: space-between;
    border-radius: 14px;
    font-size: 13px;
    /* space-between puts the label and the arrow at opposite ends of a fixed
       145px, so the label's box is whatever is left after the 32px padding and
       the 26px arrow — about 80px, and "Enquire now" needs ~85px at 13px. It
       wrapped to two lines the moment anything nudged the measure. The button
       is a single control with a two-word label; it should never wrap. */
    white-space: nowrap;
  }
  .jp-hero__acts .jp-btn--glass,
  .jp-hero__acts .jp-btn--gold {
    background: linear-gradient(100deg, #a87824, #c79b4a);
    border-color: transparent;
    color: #fffdf9;
  }
  .jp-hero__acts .jp-go {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 999px;
    background: rgba(255, 253, 249, 0.24);
    color: #fffdf9;
  }

  /* the floating panel, over the bottom of the hero */
  /* the panel is inside the copy column now, so on a phone it breaks out to
     the full width rather than being absolutely offset from the hero */
  .jp-card {
    position: relative;
    width: auto;
    /* .jp-hero__in pads 22px on the LEFT only, so a -22px right margin made the
       panel 440px wide inside a 440px viewport - it ran 22px off-screen and the
       right column lost its padding to the screen edge. A +22px right margin
       mirrors the left inset, so both columns are gutter-symmetric. */
    margin: 30px 22px 34px 0;
    z-index: 10;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    border: 1px solid rgba(50, 40, 30, 0.1);
    border-radius: 20px;
    background: rgba(255, 253, 249, 0.96);
    box-shadow: 0 20px 50px rgba(50, 35, 20, 0.1);
  }
  .jp-card li {
    /* was 128px + align-content:start, which left ~24px of dead space below
       row 2's text. Centred content with a smaller floor reads balanced. */
    min-height: 116px;
    padding: 20px 18px;
    align-content: center;
    row-gap: 0;
  }
  /* more air between the icon and its label at phone sizes */
  .jp-card {
    --card-gut: 0.95rem;
  }
  /* in a 2x2, `li + li` would rule item 3, which begins the second row */
  .jp-card li + li {
    border-inline-start: 0;
  }
  .jp-card li:nth-child(2n) {
    border-inline-start: 1px solid rgba(50, 40, 30, 0.1);
  }
  .jp-card li:nth-child(n + 3) {
    border-block-start: 1px solid rgba(50, 40, 30, 0.1);
  }
  .jp-card__ic {
    color: #a77a2c;
  }

  /* straight into amenities, same ground, no gap and no dark band */
  .jp-hero + * {
    padding-top: 0 !important;
  }
  .jp-amen {
    background: var(--bg);
    /* the panel above now ends in flow, so this only needs breathing room,
       not clearance for an overlap */
    padding: 40px 0 44px;
  }
  .jp-amen .jp-h2,
  .jp-head .jp-h2 {
    font-size: clamp(1.5rem, 6.6vw, 1.95rem);
    line-height: 1.1;
  }
  .jp-head {
    margin-bottom: 1.4rem;
    padding-bottom: 1rem;
  }
  .jp-eyebrow {
    font-size: 10px;
    letter-spacing: 0.26em;
  }
  .jp-amen .jp-wrap {
    padding-inline: 22px;
  }
  .jp-head {
    max-width: none;
    text-align: start;
    align-items: flex-start;
  }
  .jp-wall__list {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    margin-inline: -22px;
    padding-inline: 22px;
    padding-right: 22px;
  }
  .jp-wall__list::-webkit-scrollbar {
    display: none;
  }
  /* the cards carry the section on a phone, so they are given real presence:
     a defined size, a gold-ringed icon, and enough padding to breathe */
  .jp-wall__list li {
    flex: 0 0 200px;
    min-height: 0;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: start;
    gap: 0.85rem;
    padding: 22px 20px 24px;
    border: 1px solid var(--line);
    border-radius: 20px;
    background: rgba(255, 253, 249, 0.9);
    box-shadow: 0 10px 26px -18px rgba(70, 52, 24, 0.22);
  }
  .jp-wall__ic {
    display: grid;
    place-items: center;
    inline-size: 2.9rem;
    block-size: 2.9rem;
    border: 1px solid var(--gold-line);
    border-radius: 999px;
    background: rgba(167, 123, 46, 0.08);
    color: var(--gold);
  }
  .jp-wall__ic svg,
  .jp-wall__ic i {
    width: 1.35rem;
    height: 1.35rem;
    stroke-width: 1.25;
  }
  .jp-wall__list b {
    font-family: var(--display);
    font-size: 1.02rem;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.005em;
    color: var(--ivory);
  }
  .jp-wall__list i {
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--muted);
  }
  /* a hairline under the last card's edge would read as a stray rule */
  .jp-wall__list li:last-child {
    border-bottom: 1px solid var(--line);
  }
}

/* 320-379: the panel is the only thing that cannot hold two columns */
@media (max-width: 379.98px) {
  .jp-card li {
    min-height: 104px;
    padding: 16px 13px;
  }
  .jp-card {
    --card-gut: 0.72rem;
  }
}

/* ---- the hero lockup, as the reference shows it ---- */
.jp-lock {
  display: inline-flex;
  align-items: center;
  gap: 1rem;
  text-decoration: none;
  margin-bottom: clamp(1.6rem, 4vw, 2.6rem);
}
.jp-lock__mark {
  display: grid;
  place-items: center;
  width: clamp(3.2rem, 4.6vw, 4.4rem);
  height: clamp(3.2rem, 4.6vw, 4.4rem);
  border: 1px solid var(--gold-line);
  border-radius: 999px;
  font-family: var(--serif);
  font-size: clamp(1.2rem, 1.9vw, 1.7rem);
  font-weight: 600;
  color: var(--gold-text);
}
.jp-lock__tx {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-width: 0;
}
.jp-lock__tx b {
  font-size: clamp(0.95rem, 1.15vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ivory);
}
.jp-lock__tx i {
  font-style: normal;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
/* the fixed bar already carries the mark once the page scrolls, so the hero
   lockup is dropped on a phone where the two would collide */
@media (max-width: 767.98px) {
  .jp-lock {
    display: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   WEEK MENU — ivory table, gold rule, one dialog per day
   ═══════════════════════════════════════════════════════════════════════
   Styled as a printed menu card rather than a data table: the day is the
   display face, the meal names are small-caps labels, and the dish list is
   the body copy. Depth matches the hero — each day sits on its own plane and
   turns toward the pointer, so the section belongs to this template rather
   than looking bolted on. */

.jp-menu {
  padding: clamp(3rem, 6vw, 5.25rem) 0 clamp(3.2rem, 6.5vw, 5.5rem);
  background: var(--bg-2);
  border-block: 1px solid var(--line);
}
.jp-menu__type {
  display: inline-block;
  margin-top: 0.9rem;
  padding: 0.34rem 0.9rem;
  border: 1px solid var(--gold-line);
  border-radius: 999px;
  background: rgba(167, 123, 46, 0.07);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--gold-text);
}

/* ---- the seven-day strip ---- */
.jp-week {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(9.5rem, 100%), 1fr));
  gap: clamp(0.6rem, 1.4vw, 0.9rem);
  margin: 0;
  padding: 0;
  list-style: none;
  perspective: 1100px;
}
.jp-week__d {
  min-width: 0;
  transform-style: preserve-3d;
  transform: rotateX(calc(var(--tx, 0deg) + var(--stx, 0deg)))
    rotateY(calc(var(--ty, 0deg) + var(--sty, 0deg)));
  transition: transform 0.5s var(--e, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.jp-week__b {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3rem;
  width: 100%;
  min-height: 8.5rem;
  padding: 1.05rem 1rem 1.15rem;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--glass);
  box-shadow: 0 10px 26px -20px rgba(70, 52, 24, 0.3);
  font: inherit;
  text-align: start;
  color: inherit;
  cursor: pointer;
  transition:
    border-color 0.35s var(--e, ease),
    box-shadow 0.35s var(--e, ease),
    background 0.35s var(--e, ease);
}
.jp-week__abbr {
  font-family: var(--display);
  font-size: clamp(1.5rem, 2.6vw, 1.85rem);
  font-weight: 600;
  line-height: 1;
  color: var(--gold-display);
}
.jp-week__full {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--ivory);
}
.jp-week__n {
  margin-top: auto;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.jp-week__go {
  position: absolute;
  inset-block-start: 0.85rem;
  inset-inline-end: 0.85rem;
  display: grid;
  place-items: center;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  color: var(--gold);
  opacity: 0.55;
  transition:
    opacity 0.35s ease,
    translate 0.35s var(--e, ease);
}
.jp-week__go svg,
.jp-week__go i {
  width: 0.95rem;
  height: 0.95rem;
}
.jp-week__d {
  position: relative;
}

/* ---- a day with no published menu: visibly present, definitively inert ----
   Not a <button> in the markup, so it is unreachable by keyboard and by
   pointer alike; this only has to make that legible. */
.jp-week__d--off .jp-week__b {
  background: transparent;
  border-style: dashed;
  border-color: rgba(22, 20, 17, 0.14);
  box-shadow: none;
  cursor: default;
}
.jp-week__d--off .jp-week__abbr {
  color: rgba(22, 20, 17, 0.3);
}
.jp-week__d--off .jp-week__full {
  color: var(--muted);
}
.jp-week__n--none {
  font-size: 0.68rem;
  font-style: italic;
  color: rgba(95, 88, 77, 0.85);
}

/* Hover and tap are written against the SAME element — the <li> — so the two
   blocks are textual mirrors of each other. Hanging the hover off .jp-week__b
   and the tap off the li would still work, but it makes the pair impossible to
   diff mechanically, and an unmirrored hover is exactly the defect the touch
   audit is meant to catch. enhance.js hooks `li`, so .is-tapped lands here. */
@media (hover: hover) {
  .jp-week__d:hover .jp-week__b {
    border-color: var(--gold-line);
    background: rgba(255, 253, 249, 1);
    box-shadow: 0 18px 40px -24px rgba(70, 52, 24, 0.45);
  }
  .jp-week__d:hover .jp-week__go {
    opacity: 1;
    translate: 2px -2px;
  }
  /* the dashed day must not react — it is not actionable */
  .jp-week__d--off:hover .jp-week__b {
    border-color: rgba(22, 20, 17, 0.14);
    background: transparent;
    box-shadow: none;
  }
}
@media (hover: none) {
  .jp-week__d.is-tapped .jp-week__b {
    border-color: var(--gold-line);
    background: rgba(255, 253, 249, 1);
    box-shadow: 0 18px 40px -24px rgba(70, 52, 24, 0.45);
  }
  .jp-week__d.is-tapped .jp-week__go {
    opacity: 1;
    translate: 2px -2px;
  }
  .jp-week__d--off.is-tapped .jp-week__b {
    border-color: rgba(22, 20, 17, 0.14);
    background: transparent;
    box-shadow: none;
  }
}
.jp-week__b:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
}

/* ---- the per-day dialog ---- */
/* [hidden] only sets display:none in the UA stylesheet, so this author-level
   display:grid would otherwise win and leave a fixed full-viewport overlay
   swallowing every click on the page. Same trap the review dialog hit. */
.jp-menu-d[hidden] {
  display: none;
}
.jp-menu-d {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
  opacity: 0;
  transition: opacity 0.28s ease;
}
.jp-menu-d.is-open {
  opacity: 1;
}
.jp-menu-d__scrim {
  position: absolute;
  inset: 0;
  background: rgba(28, 22, 14, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.jp-menu-d__panel {
  position: relative;
  width: min(34rem, 100%);
  max-height: min(82vh, 44rem);
  overflow-y: auto;
  padding: clamp(1.6rem, 4vw, 2.4rem);
  border: 1px solid var(--gold-line);
  border-radius: 22px;
  background: var(--bg);
  box-shadow: 0 40px 90px -30px rgba(40, 28, 12, 0.55);
  scale: 0.97;
  transition: scale 0.28s var(--e, cubic-bezier(0.2, 0.8, 0.2, 1));
}
.jp-menu-d.is-open .jp-menu-d__panel {
  scale: 1;
}
.jp-menu-d__x {
  position: absolute;
  inset-block-start: 0.85rem;
  inset-inline-end: 0.85rem;
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--glass);
  color: var(--ivory);
  cursor: pointer;
}
.jp-menu-d__x svg,
.jp-menu-d__x i {
  width: 1.05rem;
  height: 1.05rem;
}
.jp-menu-d__h {
  margin: 0.35rem 0 0;
  font-family: var(--display);
  font-size: clamp(1.6rem, 4.5vw, 2.15rem);
  font-weight: 600;
  line-height: 1.1;
  color: var(--ivory);
}
.jp-menu-d__list {
  margin: 1.4rem 0 0;
}
.jp-menu-d__row {
  display: grid;
  gap: 0.2rem;
  padding-block: 0.85rem;
  border-block-start: 1px solid var(--line);
}
.jp-menu-d__row:first-child {
  border-block-start: 0;
  padding-block-start: 0;
}
.jp-menu-d__row dt {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-text);
}
.jp-menu-d__row dd {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--muted);
}
.jp-menu-d__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.6rem;
  padding-top: 1.1rem;
  border-block-start: 1px solid var(--line);
}
.jp-menu-d__bar p {
  margin: 0;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.jp-menu-d__nav {
  display: grid;
  place-items: center;
  inline-size: 44px;
  block-size: 44px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--ivory);
  cursor: pointer;
  transition:
    border-color 0.3s ease,
    color 0.3s ease;
}
.jp-menu-d__nav svg,
.jp-menu-d__nav i {
  width: 1.05rem;
  height: 1.05rem;
}
@media (hover: hover) {
  .jp-menu-d__nav:hover,
  .jp-menu-d__x:hover {
    border-color: var(--gold-line);
    color: var(--gold-text);
  }
}
@media (hover: none) {
  .jp-menu-d__nav.is-tapped,
  .jp-menu-d__x.is-tapped {
    border-color: var(--gold-line);
    color: var(--gold-text);
  }
}

/* ---- phones ---- */
@media (max-width: 767.98px) {
  .jp-menu {
    padding: 40px 0 44px;
  }
  .jp-week {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    perspective: 800px;
  }
  .jp-week__b {
    min-height: 7.25rem;
    padding: 0.9rem 0.85rem 1rem;
  }
  .jp-menu-d__panel {
    max-height: 86vh;
  }
}
@media (max-width: 359.98px) {
  .jp-week {
    grid-template-columns: minmax(0, 1fr);
  }
  .jp-week__b {
    min-height: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .jp-week__d,
  .jp-menu-d,
  .jp-menu-d__panel,
  .jp-week__go {
    transform: none;
    transition: none;
  }
}

/* Phones: the stacked about title is a wide-screen lockup. At 7vw a four-word
   title still eats most of a 412px screen before any content appears, so the
   words flow as a normal heading and only keep the alternating colour. */
@media (max-width: 767.98px) {
  .jp-about__word {
    font-size: clamp(1.7rem, 8vw, 2.4rem);
    line-height: 1.14;
  }
  .jp-about__word span {
    display: inline;
  }
  .jp-about__word span:nth-child(even) {
    padding-inline-start: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   HERO LIGHT RIG — champagne daylight, safe on ANY business photograph
   ═══════════════════════════════════════════════════════════════════════
   Peak alphas measured rather than eyeballed: at 0.32 the key lifted black to
   0.30 (haze); at 0.12 it lifts to 0.11 and the black point survives. The
   falloff, the only layer that can darken, costs a dim photo ~7% at the
   corners.

   Same rig as the cinematic pack, tuned for ivory rather than near-black:
   the key is champagne instead of amber, the bounce is warmer, and the corner
   falloff is roughly half as deep because this hero sits on a cream ground
   where a heavy vignette would read as dirt rather than depth.

   Every layer is additive (screen / soft-light) or a very low-alpha neutral —
   nothing multiplies. Published sites carry whatever photo the owner has, and
   a dim stairwell must come out lit, never darker. */

/* 1 — normalise the source. Gentle on purpose: this runs unattended against
   every business profile, and strong values ruin an already-good photo. */
.jp-hero__plate img {
  filter: brightness(1.02) contrast(1.05) saturate(1.06);
}

.jp-hero__grade {
  background: none;
  mix-blend-mode: normal;
  pointer-events: none;
}

/* 2 — key light, tracking the same pointer/scroll as the plate's rotation.
   `screen` can only lighten, so it cannot bruise a bright exterior shot. */
.jp-hero__grade::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    56% 60% at var(--lx, 30%) var(--ly, 24%),
    rgba(255, 236, 205, 0.12) 0%,
    rgba(255, 222, 176, 0.06) 36%,
    rgba(250, 214, 160, 0.02) 60%,
    transparent 78%
  );
  mix-blend-mode: screen;
  transition: background 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* 3 — warm bounce opposite the key, plus a light corner falloff. Half the
   depth of the dark pack: on cream, a strong vignette looks like grime. */
.jp-hero__grade::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(
      68% 68% at calc(100% - var(--lx, 30%)) calc(100% - var(--ly, 24%)),
      rgba(196, 168, 214, 0.06) 0%,
      transparent 60%
    ),
    radial-gradient(125% 105% at 50% 45%, transparent 58%, rgba(52, 38, 20, 0.1) 100%);
  mix-blend-mode: soft-light;
  transition: background 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* 4 — rim light along the top edge, and a soft seat at the base so the plate
   sits in the page instead of being pasted onto it. */
.jp-hero__plate {
  box-shadow:
    inset 0 1px 0 rgba(255, 245, 226, 0.3),
    inset 0 -70px 90px -70px rgba(52, 38, 20, 0.34);
}

@media (prefers-reduced-motion: reduce) {
  .jp-hero__grade::before,
  .jp-hero__grade::after {
    transition: none;
  }
}

/* ---- cinematic hero stage: this pack's lights ----
   The stage itself lives in the shared enhance.js. Only the colours are set
   here, so every template gets the same physics and none of them get the same
   look. champagne on ivory. */
.jp-hero__plate {
  --stage-warm: 167, 123, 46;
  --stage-cool: 196, 168, 214;
  --stage-ground: 52, 38, 20;
}

/* ── depth: the plate turns, the photograph inside it drifts the other way ──
   Rotation alone turns a flat card. Content moving at a different rate is what
   the eye reads as depth, so the image counter-moves via --ix/--iy, written by
   the same handler that sets the rotation.

   scale(1.035) is load-bearing, not decoration: at 7deg the rotated footprint
   no longer covers its own box and the hero background shows as a sliver down
   one edge. The image is inset -3% for the same reason against its drift. */
.jp-hero__plate {
  transform: rotateY(var(--ry, 0deg)) rotateX(var(--rx, 0deg)) scale(1.035);
}
.jp-hero__plate img {
  inset: -3%;
  width: 106%;
  height: 106%;
  translate: var(--ix, 0px) var(--iy, 0px);
  transition:
    translate 0.55s cubic-bezier(0.2, 0.8, 0.2, 1),
    scale 1.8s var(--e-out);
}
@media (prefers-reduced-motion: reduce) {
  .jp-hero__plate {
    transform: none;
  }
  .jp-hero__plate img {
    translate: none;
    transition: none;
  }
}

/* @brx-components:start — generated, do not edit */
:root {
  --brx-surface: var(--glass-panel); /* a card or panel background */
  --brx-surface2: var(--bg-2); /* a recessed band behind a section */
  --brx-ink: var(--ivory); /* body text */
  --brx-muted: var(--muted); /* secondary text */
  --brx-accent: var(--gold); /* icons, rules and fills (needs 3:1) */
  --brx-accent-ink: var(--gold-text); /* accent used as small text (needs 4.5:1) */
  --brx-accent-lit: var(--gold-display); /* a decorative second accent, never text */
  --brx-on-accent: var(--ink-on-dark); /* text placed on an accent fill */
  --brx-tint: rgba(167, 123, 46, 0.07); /* a wash of the accent at low alpha */
  --brx-line: var(--line); /* hairline */
  --brx-line2: var(--line-2); /* a stronger hairline */
  --brx-radius: var(--r-l); /* card radius */
  --brx-radius-sm: var(--r-s); /* control radius */
  --brx-shadow: var(--sh-m); /* resting elevation */
  --brx-shadow-l: var(--sh-l); /* raised elevation */
  --brx-font: var(--sans); /* body typeface */
}

/* ============================================================
   brx shared components — CANONICAL SOURCE. Edit this file; never edit a
   pack copy. Regenerate:  node scripts/sync-pack-components.mjs

   Not one colour, font or radius is written here. Every value is a --brx-*
   token, and sync-pack-components.mjs writes a per-pack bridge block above
   this one mapping those tokens onto that pack's OWN palette. So this file is
   byte-identical in all eleven packs and still renders eleven different
   looks: the espresso pack gets bronze on near-black with 2px corners, the
   champagne pack gets gold on ivory with 22px corners, from the same rules.

   The reason to do it this way rather than eleven hand-written copies is not
   brevity. It is that the terms section and the action dock are the two
   components where behaviour must not vary by skin — one is legal text, the
   other is the control that dials the owner. Eleven copies drift, and the
   drift is invisible until someone lands on the pack that broke.
   ============================================================ */

/* ---- shared section chrome ---- */
.brx-s {
  padding-block: clamp(2.4rem, 4.8vw, 4.2rem);
}
.brx-wrap {
  width: 100%;
  max-width: var(--maxw, 90rem);
  margin-inline: auto;
  padding-inline: var(--gut, clamp(1.15rem, 4.5vw, 5rem));
}
.brx-head {
  max-width: 44rem;
  margin-bottom: clamp(1.1rem, 2.2vw, 1.8rem);
}
.brx-eb {
  display: block;
  margin-bottom: 0.5rem;
  font-family: var(--brx-font);
  font-size: 0.69rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brx-accent-ink);
}
.brx-h2 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 3.2vw, 2.5rem);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: -0.01em;
  color: var(--heading);
}
.brx-note {
  margin: 1.1rem 0 0;
  max-width: 44rem;
  font-family: var(--brx-font);
  font-size: 0.78rem;
  line-height: 1.7;
  color: var(--brx-muted);
}

/* ---- quick information strip ---- */
.brx-qi {
  padding-block: clamp(1.4rem, 2.8vw, 2.2rem);
  border-bottom: 1px solid var(--brx-line);
}
.brx-qi__l {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.brx-qi__i {
  display: inline-flex;
  align-items: center;
  padding: 0.48rem 0.9rem;
  border: 1px solid var(--brx-line2);
  border-radius: 999px;
  background: var(--brx-surface);
  font-family: var(--brx-font);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--heading);
}
/* The owner's own emphasis, carried as an accent rule rather than a different
   size — a chip strip whose items disagree about height reads as a mistake. */
.brx-qi__i.is-key {
  border-color: var(--brx-accent);
  background: var(--brx-tint);
  color: var(--brx-accent-ink);
  font-weight: 700;
}

/* ---- pricing & the move-in amount ---- */
.brx-pr {
  background: var(--brx-surface2);
}
.brx-pr__g {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15.5rem, 1fr));
  gap: clamp(0.8rem, 1.8vw, 1.3rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.brx-pr__c {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: clamp(1rem, 2vw, 1.5rem);
  border: 1px solid var(--brx-line);
  border-radius: var(--brx-radius);
  background: var(--brx-surface);
  box-shadow: var(--brx-shadow);
  transition:
    translate 0.3s var(--e),
    box-shadow 0.3s var(--e),
    border-color 0.3s var(--e);
}
.brx-pr__c:hover {
  translate: 0 -3px;
  border-color: var(--brx-accent);
  box-shadow: var(--brx-shadow-l);
}
.brx-pr__n {
  margin: 0;
  font-family: var(--font-heading);
  font-size: clamp(1.1rem, 1.5vw, 1.35rem);
  font-weight: 500;
  color: var(--heading);
}
.brx-pr__r {
  margin: 0;
  font-family: var(--brx-font);
  font-size: 0.88rem;
  color: var(--brx-muted);
}
.brx-pr__r b {
  font-size: 1.45rem;
  font-weight: 700;
  color: var(--heading);
}
.brx-pr__r i {
  font-style: normal;
  font-size: 0.82rem;
}
/* The only filled element in the card, because the move-in figure is the
   point of the section and should be findable at a glance. */
.brx-pr__mv {
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--brx-accent);
  border-radius: var(--brx-radius-sm);
  background: var(--brx-tint);
}
.brx-pr__mvl {
  display: block;
  font-family: var(--brx-font);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--brx-accent-ink);
}
.brx-pr__mvt {
  display: block;
  margin-block: 0.12rem 0.45rem;
  font-family: var(--font-heading);
  font-size: clamp(1.45rem, 2.2vw, 1.9rem);
  font-weight: 600;
  color: var(--heading);
}
.brx-pr__ln {
  margin: 0;
  padding: 0.45rem 0 0;
  list-style: none;
  border-top: 1px solid var(--brx-line2);
}
.brx-pr__ln li {
  display: flex;
  justify-content: space-between;
  gap: 0.8rem;
  font-family: var(--brx-font);
  font-size: 0.765rem;
  line-height: 1.85;
  color: var(--brx-muted);
}
.brx-pr__ln em {
  font-style: normal;
  color: var(--heading);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.brx-pr__t {
  margin: auto 0 0;
  padding: 0;
  list-style: none;
}
.brx-pr__t li {
  position: relative;
  padding-left: 0.95rem;
  font-family: var(--brx-font);
  font-size: 0.78rem;
  line-height: 1.9;
  color: var(--brx-muted);
}
.brx-pr__t li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.82em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--brx-accent);
}

/* ---- nearby places ---- */
.brx-nb__g {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12.5rem, 1fr));
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.brx-nb__i {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  padding: 0.8rem 0.95rem;
  border: 1px solid var(--brx-line);
  border-radius: var(--brx-radius-sm);
  background: var(--brx-surface);
  transition:
    border-color 0.25s var(--e),
    translate 0.25s var(--e);
}
.brx-nb__i:hover {
  border-color: var(--brx-accent);
  translate: 0 -2px;
}
.brx-nb__i b {
  font-family: var(--brx-font);
  font-size: 0.87rem;
  font-weight: 600;
  color: var(--heading);
}
.brx-nb__d {
  display: flex;
  align-items: center;
  gap: 0.38rem;
  font-family: var(--brx-font);
  font-size: 0.77rem;
  color: var(--brx-accent-ink);
  font-variant-numeric: tabular-nums;
}
.brx-nb__d i {
  font-style: normal;
  opacity: 0.5;
}

/* ---- walkthrough video ---- */
.brx-vd__g {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  gap: clamp(0.65rem, 1.5vw, 1rem);
}
.brx-vd__g.is-one {
  grid-template-columns: minmax(0, 46rem);
  justify-content: center;
}
.brx-vd__f {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--brx-line);
  border-radius: var(--brx-radius);
  box-shadow: var(--brx-shadow);
  background: var(--brx-surface2);
}
.brx-vd__f video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* ---- house rules & FAQ ---- */
.brx-rl__l {
  max-width: 52rem;
  border-top: 1px solid var(--brx-line);
}
.brx-rl__q {
  border-bottom: 1px solid var(--brx-line);
}
.brx-rl__q summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.95rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--brx-font);
  font-size: 0.93rem;
  font-weight: 600;
  color: var(--heading);
}
.brx-rl__q summary::-webkit-details-marker {
  display: none;
}
.brx-rl__q summary:focus-visible {
  outline: 2px solid var(--brx-accent);
  outline-offset: 3px;
}
.brx-rl__c {
  flex: none;
  display: inline-flex;
  width: 16px;
  height: 16px;
  color: var(--brx-accent);
  transition: rotate 0.28s var(--e);
}
.brx-rl__c svg {
  width: 100%;
  height: 100%;
}
.brx-rl__q[open] .brx-rl__c {
  rotate: 180deg;
}
.brx-rl__a {
  padding-bottom: 1rem;
}
.brx-rl__a p {
  margin: 0;
  max-width: 46rem;
  font-family: var(--brx-font);
  font-size: 0.865rem;
  line-height: 1.78;
  color: var(--brx-muted);
}

/* ---- terms & conditions ---- */
.brx-terms {
  padding-block: clamp(2.6rem, 5vw, 4.5rem);
  background: var(--brx-surface2);
  border-top: 1px solid var(--brx-line);
}
.brx-terms__wrap {
  width: 100%;
  max-width: var(--maxw, 90rem);
  margin-inline: auto;
  padding-inline: var(--gut, clamp(1.15rem, 4.5vw, 5rem));
}
.brx-terms__head {
  max-width: 46rem;
  margin-bottom: clamp(1.2rem, 2.5vw, 2rem);
}
.brx-terms__eb {
  display: block;
  margin-bottom: 0.55rem;
  font-family: var(--brx-font);
  /* 11px uppercase is the size that fails contrast first, which is why the
     bridge points --brx-accent-ink at a deepened accent rather than the
     decorative one. Measured >= 4.5:1 on all eleven grounds. */
  font-size: 0.69rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brx-accent-ink);
}
.brx-terms__h2 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: clamp(1.6rem, 3.4vw, 2.7rem);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.01em;
  color: var(--heading);
}
.brx-terms__intro {
  margin: 0.85rem 0 0;
  font-family: var(--brx-font);
  font-size: 0.94rem;
  line-height: 1.7;
  color: var(--brx-muted);
}
.brx-terms__rev {
  margin: 0.75rem 0 0;
  font-family: var(--brx-font);
  font-size: 0.74rem;
  letter-spacing: 0.04em;
  color: var(--brx-muted);
}
.brx-terms__list {
  max-width: 54rem;
  border-top: 1px solid var(--brx-line);
}
.brx-terms__c {
  border-bottom: 1px solid var(--brx-line);
}
.brx-terms__c summary {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 0.9rem;
  padding: 1.05rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--brx-font);
}
.brx-terms__c summary::-webkit-details-marker {
  display: none;
}
.brx-terms__c summary:focus-visible {
  outline: 2px solid var(--brx-accent);
  outline-offset: 3px;
}
.brx-terms__n {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--brx-accent-ink);
}
.brx-terms__ct {
  font-size: 0.97rem;
  font-weight: 600;
  line-height: 1.4;
  color: var(--heading);
}
.brx-terms__chev {
  display: inline-flex;
  width: 16px;
  height: 16px;
  align-self: center;
  color: var(--brx-accent);
  transition: rotate 0.28s var(--e);
}
.brx-terms__chev svg {
  width: 100%;
  height: 100%;
}
.brx-terms__c[open] .brx-terms__chev {
  rotate: 180deg;
}
.brx-terms__b {
  padding: 0 0 1.15rem calc(0.9rem + 1.55em);
}
.brx-terms__b p {
  margin: 0;
  max-width: 44rem;
  font-family: var(--brx-font);
  font-size: 0.885rem;
  line-height: 1.78;
  color: var(--brx-muted);
}

/* ---- the expanding action dock ---- */
.brx-dock {
  position: fixed;
  z-index: 620;
  right: clamp(0.75rem, 1.6vw, 1.5rem);
  bottom: clamp(0.75rem, 1.6vw, 1.5rem);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
}
.brx-dock__list {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
  /* Collapsed state is inert, not merely invisible: pointer-events off and
     visibility hidden keep the links out of the tab order and out from under
     the cursor, which a bare opacity:0 would not. */
  opacity: 0;
  visibility: hidden;
  translate: 0 8px;
  pointer-events: none;
  transition:
    opacity 0.24s var(--e),
    translate 0.32s var(--e),
    visibility 0.24s;
}
.brx-dock.is-open .brx-dock__list {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
  pointer-events: auto;
}
.brx-dock__i {
  translate: 0 6px;
  opacity: 0;
  transition:
    translate 0.34s var(--e),
    opacity 0.26s var(--e);
  /* Staggered from the bottom up, so the row nearest the trigger arrives
     first and the eye follows the movement outward. */
  transition-delay: calc(var(--i, 1) * 32ms);
}
.brx-dock.is-open .brx-dock__i {
  translate: 0 0;
  opacity: 1;
}
.brx-dock__a {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.85rem 0.5rem 0.55rem;
  border: 1px solid var(--brx-line2);
  border-radius: 999px;
  background: var(--brx-surface);
  box-shadow: var(--brx-shadow);
  color: var(--heading);
  font-family: var(--brx-font);
  font-size: 0.82rem;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  backdrop-filter: blur(10px);
  transition:
    background 0.2s var(--e),
    color 0.2s var(--e),
    border-color 0.2s var(--e),
    translate 0.2s var(--e);
}
.brx-dock__a:hover,
.brx-dock__a:focus-visible {
  background: var(--brx-accent);
  border-color: var(--brx-accent);
  color: var(--brx-on-accent);
  translate: -2px 0;
}
.brx-dock__a:focus-visible {
  outline: 2px solid var(--brx-accent);
  outline-offset: 2px;
}
.brx-dock__ic {
  display: inline-flex;
  width: 30px;
  height: 30px;
  flex: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--brx-tint);
  color: var(--brx-accent-ink);
  transition:
    background 0.2s var(--e),
    color 0.2s var(--e);
}
.brx-dock__a:hover .brx-dock__ic,
.brx-dock__a:focus-visible .brx-dock__ic {
  background: var(--brx-on-accent);
  color: var(--brx-accent-ink);
}
.brx-dock__ic svg {
  width: 16px;
  height: 16px;
}

/* The trigger. Collapsed it reads as a labelled pill rather than a bare
   icon — an unlabelled floating circle is the single most common way this
   pattern fails, because nobody presses a button whose purpose they cannot
   guess. */
.brx-dock__t {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.62rem 1.05rem 0.62rem 0.72rem;
  border: 1px solid var(--brx-accent);
  border-radius: 999px;
  background: var(--brx-accent);
  color: var(--brx-on-accent);
  box-shadow: var(--brx-shadow-l);
  font-family: var(--brx-font);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition:
    scale 0.24s var(--e),
    box-shadow 0.24s var(--e);
}
.brx-dock__t:hover {
  scale: 1.03;
}
.brx-dock__t:focus-visible {
  outline: 2px solid var(--brx-accent);
  outline-offset: 3px;
}
.brx-dock__ti,
.brx-dock__tc {
  display: inline-flex;
  width: 22px;
  height: 22px;
  align-items: center;
  justify-content: center;
}
.brx-dock__ti svg,
.brx-dock__tc svg {
  width: 17px;
  height: 17px;
}
/* Open swaps the chat glyph for a close glyph in place, so the trigger keeps
   its width and the dock does not jump as it opens. */
.brx-dock__tc {
  display: none;
}
.brx-dock.is-open .brx-dock__ti {
  display: none;
}
.brx-dock.is-open .brx-dock__tc {
  display: inline-flex;
}
.brx-dock.is-open .brx-dock__t {
  background: var(--brx-surface);
  color: var(--heading);
  border-color: var(--brx-line2);
}

/* A soft pulse the first time only, to draw the eye once without becoming a
   permanently animated element in the corner of every page. */
@keyframes brx-dock-in {
  from {
    opacity: 0;
    translate: 0 14px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}
.brx-dock {
  animation: brx-dock-in 0.5s var(--e) 0.6s both;
}

/* Narrow screens: the label would crowd the thumb zone, so the trigger
   becomes a circle and the action labels stay — they are the part that
   carries meaning. */
@media (max-width: 479.98px) {
  .brx-dock__tx {
    display: none;
  }
  .brx-dock__t {
    padding: 0.68rem;
  }
}

/* Keep the pack's own back-to-top button clear of the dock. Scoped to the
   class brxMount() adds, so a pack rendering no dock is untouched. */
.brx-has-dock .back-to-top {
  bottom: clamp(4.3rem, 7vw, 5.4rem);
}

@media (prefers-reduced-motion: reduce) {
  .brx-dock,
  .brx-dock__list,
  .brx-dock__i,
  .brx-dock__a,
  .brx-dock__t,
  .brx-terms__chev {
    animation: none;
    transition: none;
    translate: none;
  }
}
/* @brx-components:end */
