/*!*************************************************************************************************************************************************************************************************************************************************************!*\
  !*** css ./node_modules/next/dist/build/webpack/loaders/css-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[2]!./node_modules/next/dist/build/webpack/loaders/postcss-loader/src/index.js??ruleSet[1].rules[14].oneOf[10].use[3]!./app/project.css ***!
  \*************************************************************************************************************************************************************************************************************************************************************/
/* =========================================================================
   Project detail page — /projects/<id>
   -------------------------------------------------------------------------
   Loaded only by components/project/ProjectDetail.jsx. Namespaced under
   .projectPage and short section prefixes so it cannot leak into the shared
   sheets:

     .pd    hero and shared detail-page primitives
     .am    amenities        .sp    space planning
     .pr    pricing          .emi   loan calculator
     .spec  specifications   .cn    connectivity
     .sg    site progress    .pg    gallery rail

     .pi    intro band

   Motion inputs, and which hook writes them:
     --pdp   useScrollScrub   hero parallax progress (0–1)
     --pip   useScrollScrub   intro-band parallax progress (0–1)
     --amp   useScrollScrub   amenities watermark drift (0–1)
     --spcp  useScrollScrub   specifications watermark drift (0–1)
   ========================================================================= */

.projectPage {
  background: var(--paper);
}

/* Visually hidden but read aloud — the hero lockup is artwork, so the
   accessible name has to come from text beside it. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  -webkit-clip-path: inset(50%);
          clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* =========================================================================
   Shared detail-page primitives
   ========================================================================= */

.pdHeading {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  text-align: center;
}

.pdHeading em {
  font-style: normal;
}

.pdHeading .is-gold {
  color: var(--gold-500);
}

.pdHeading .is-navy {
  color: var(--navy-500);
}

.pdHeading .is-light {
  color: #fff;
}

/* Outstanding-content note. Deliberately conspicuous — it is a build-time
   marker, not a design element, and should be impossible to ship by accident. */
.pdPending {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 0.75rem;
  max-width: 70ch;
  margin: clamp(1.5rem, 3vw, 2.5rem) auto 0;
  padding: clamp(0.9rem, 1.8vw, 1.25rem) clamp(1rem, 2vw, 1.5rem);
  border: 1px dashed var(--gold-500);
  border-radius: var(--radius);
  background: rgba(248, 166, 25, 0.08);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--ink-700);
  display: none;
}

.pdPending__tag {
  padding: 0.2em 0.7em;
  border-radius: var(--radius-pill);
  background: var(--gold-500);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--navy-900);
}

.pdPending code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
}

.pdMissing {
  padding-block: clamp(6rem, 18vw, 14rem);
  text-align: center;
}

/* =========================================================================
   Hero — full-screen render
   -------------------------------------------------------------------------
   The header floats over this, so the image runs edge to edge behind the
   navigation and the headline is anchored to the foot rather than centred.
   ========================================================================= */

.pdHero {
  --pdp: 0;
 position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 100svh;
  padding-bottom: 40px;
  overflow: hidden;
  background: var(--navy-900);
  color: #fff;
}

/* The render sits in its own layer rather than as a background image, so it
   can be overscaled and moved without dragging the scrim with it. */
.pdHero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* Two movements on one element. The load animation eases it down from an
   overscale — a slow settle rather than a hard cut — and the scroll parallax
   rides on top through the custom property, which the keyframes leave alone.

   116% of height against 12% of travel leaves 4% of margin, so no edge is
   ever exposed at either end of the range. */
.pdHero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: inherit;
  will-change: transform;
  animation: pdSettle 1.8s var(--ease) both;
}

@keyframes pdSettle {
  from {
    scale: 1.12;
    opacity: 0;
  }
  to {
    scale: 1;
    opacity: 1;
  }
}

/* Weighted to the foot, where the type sits, and barely present at the top so
   the render reads clean behind the header. */
.pdHero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    0deg,
    rgba(4, 16, 36, 0.88) 0%,
    rgba(4, 16, 36, 0.45) 28%,
    rgba(4, 16, 36, 0) 62%,
    rgba(4, 16, 36, 0.35) 100%
  );
}

.pdHero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  text-align: center;
}

.pdHero__title {
  font-family: var(--font-display);
  font-size: 80px;
  font-weight: 700;
  line-height: 1.02;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.55);
}

/* Block, so .maskUp wipes each line on its own delay. */
.pdHero__line {
  display: block;
}

.pdHero__line em {
  font-style: normal;
}

.pdHero__line .is-gold {
  color: var(--gold-500);
}

.pdHero__line .is-light {
  color: #fff;
}

/* --- Background video ---------------------------------------------------
   A 16:9 YouTube iframe scaled to *cover* the hero at any aspect ratio:
   it is at least as wide as the hero and at least as tall, then centred and
   cropped. Non-interactive — it is decoration behind the headline. */
.pdHero__media--video {
  overflow: hidden;
  background: var(--navy-900);
}

.pdHero__video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, calc(100svh * 16 / 9));
  height: max(100%, calc(100vw * 9 / 16));
  min-height: 100%;
  translate: -50% -50%;
  border: 0;
  pointer-events: none;
  animation: pdVideoIn 1.8s var(--ease) 0.4s both;
}

/* A self-hosted file covers the hero natively — no 16:9 oversizing needed. */
.pdHero__video--file {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  min-height: 0;
  translate: none;
  object-fit: cover;
}

@keyframes pdVideoIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* --- Scroll cue ---------------------------------------------------------- */

/* A link, not a button — it moves the reader to the next band, which is
   navigation, and it should work with JavaScript off. */
.pdCue {
  position: relative;
  display: inline-flex;
  align-items: center;
  overflow: hidden;
  margin-top: 30px;
  padding: 8px 20px;
  border-radius: var(--radius-pill);
  background:linear-gradient(to right, #f6800e, #f9a51a, #f6800e);
  font-size: clamp(0.68rem, 0.8vw, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
  box-shadow: 0 16px 34px rgba(4, 20, 45, 0.4);
  /* A slow bob, so the cue reads as an invitation rather than a static pill. */
  animation: pdBob 3.2s var(--ease) 1.2s infinite;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease),
    letter-spacing 0.45s var(--ease);
}

@keyframes pdBob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(5px); }
}

/* Hover stops the bob — the animation and the hover transform are the same
   property, so leaving it running would fight the lift. */
.pdCue:hover {
  animation-play-state: paused;
  transform: translateY(-2px);
  letter-spacing: 0.18em;
  box-shadow: 0 22px 44px rgba(4, 20, 45, 0.5);
}

/* The site's standard button sheen — see "Two-action button" in globals.css. */
.pdCue__sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 35%,
    rgba(255, 255, 255, 0.3) 50%,
    transparent 65%
  );
  transform: translateX(-100%);
  transition: transform 0.7s var(--ease);
}

.pdCue:hover .pdCue__sheen {
  transform: translateX(100%);
}

.pdCue__label {
  position: relative;
}

/* --- Down arrow ---------------------------------------------------------
   Same arrow and nudge as the home banner's "Scroll to explore" cue
   (cueNudge in components.css). The sheen also sweeps by itself every few
   seconds. */

.pdCue {
  gap: 0.8em;
}

.pdCue__arrow {
  position: relative;
  flex: none;
  width: 18px;
  height: 18px;
  animation: pdCueNudge 2.2s var(--ease) infinite;
}

@keyframes pdCueNudge {
  0%, 100% { transform: translateY(-3px); opacity: 0.5; }
  50% { transform: translateY(3px); opacity: 1; }
}

.pdCue__sheen {
  animation: pdCueSheen 4.5s var(--ease) 2s infinite;
}

@keyframes pdCueSheen {
  0% { transform: translateX(-100%); }
  30%, 100% { transform: translateX(100%); }
}

.pdCue:hover .pdCue__sheen {
  animation: none;
}

/* The cue sits in the bottom 12% of a phone screen, which the shared reveal
   observer ignores (rootMargin -12%), so it would stay hidden until the
   reader scrolled. It gets its own entrance on load instead. */
.pdHero .pdCue[data-reveal] {
  opacity: 1;
  animation: pdCueIn 0.9s var(--ease) 0.5s both, pdBob 3.2s var(--ease) 1.6s infinite;
}

@keyframes pdCueIn {
  from { opacity: 0; translate: 0 18px; }
  to { opacity: 1; translate: 0 0; }
}

/* Phones: keep the cue clear of the floating "+" contact button
   (60px, bottom-right) and fit the label + arrow on one line. */
@media (max-width: 900px) {
  .pdHero {
    padding-bottom: calc(100px + env(safe-area-inset-bottom, 0px));
  }
}

@media (max-width: 640px) {
  .pdCue {
    padding-left: 1.4em;
    font-size: 0.68rem;
    letter-spacing: 0.08em;
    white-space: nowrap;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pdCue__arrow,
  .pdCue__sheen {
    animation: none;
  }

  .pdHero .pdCue[data-reveal] {
    animation: none;
    transform: none;
  }
}

/* =========================================================================
   Intro band
   -------------------------------------------------------------------------
   On a light field, not the navy of the hero — the comp switches ground here.

   --pip is a 0–1 scroll progress written by ProjectIntro. The two renders
   read it at different rates, so the pair shears apart slightly as the band
   crosses the viewport rather than travelling as one block.
   ========================================================================= */

.pi {
  --pip: 0.5;

  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(2.5rem, 6vw, 5rem);
  background: linear-gradient(180deg, #fdfdfe 0%, #eef3f8 100%);
  color: var(--ink-900);
  text-align: center;
}

/* The copy and the composite render share one grid cell: whichever is taller
   sets the height, so the render is never cropped and the copy is never
   clipped, at any width. Both hang from the top — the render carries its own
   sky, and that empty sky is what the lede and the meta row sit on. */
.pi__stage {
  display: grid;
  grid-template-areas: "stage";
}

.pi__stageBody,
.pi__render {
  grid-area: stage;
  align-self: start;
  position: relative;
}

/* The copy comes first in the DOM for reading order, so its stacking order
   has to be stated rather than left to paint order. The padding drops the
   lede clear of the render's top edge, as on the comp. */
.pi__stageBody {
  z-index: 1;
  padding-top: clamp(0.75rem, 2.5vw, 2rem);
}

/* Full-bleed: the render runs the width of the band while the copy over it
   stays inside the shell. */
.pi__render {
  width: 100%;
}

.pi__render img {
  display: block;
  width: 100%;
  height: auto;
  transform: translate3d(0, calc((var(--pip) - 0.5) * -18px), 0);
  will-change: transform;
}

.pi__lede {
  margin-inline: auto;
  font-family: var(--font-display);
  font-size: 55px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--navy-500);
  margin: 0;
}

.pi__body {
    margin: clamp(0.9rem, 2vw, 1.4rem) auto 0;
    font-size: clamp(0.88rem, 1vw, 1.15rem);
    line-height: 1.65;
    color: var(--ink-700);
    max-width: 80%;
}

.pi__body--repeat {
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
}

/* --- Place / lockup / price ---------------------------------------------- */

/* Three equal columns so the lockup lands dead centre whatever the place name
   or price beside it happen to be. */
.pi__meta {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: center;
  grid-gap: clamp(1rem, 3vw, 2.5rem);
  gap: clamp(1rem, 3vw, 2.5rem);
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
   border-bottom: 1px solid var(--line);
   padding-bottom: 20px;
}

.piPlace {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: auto auto;
  justify-content: center;
  align-items: center;
  grid-column-gap: 0.5rem;
  column-gap: 0.5rem;
}

/* Spans both rows so the name and city stack beside it. */
.piPlace__pin {
  grid-row: span 2;
  width:65px;
  height: auto;
  color: var(--gold-500);
}

.piPlace__name {
  font-family: var(--font-display);
  font-size:55px;
  font-weight: 500;
  line-height: 1.1;
  color: var(--navy-500);
  text-align: left;
}

.piPlace__city {
  font-size: clamp(0.6rem, 0.7vw, 0.8rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-500);
  text-align: left;
}

.piLockup {
  display: flex;
  justify-content: center;
}

/* The phone-only lockup at the head of the band. Off above 767px; switched on
   below it for every project, where the meta row's own copy is switched off so
   the mark is not drawn twice. */
.piLockup--mobile {
  display: none;
}

.piLockup .lockup--art {
  width: clamp(150px, 17vw, 300px);
  height: auto;
}

/* Column of label over figure — its own box so the [data-reveal] can move it. */
.piPrice {
  min-width: 0;
}

.piPrice__label {
  display: block;
  font-size: clamp(0.6rem, 0.72vw, 0.85rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-500);
}

.piPrice__value {
  font-family: var(--font-display);
  font-size: 100px;
  font-weight: 500;
  line-height: 1.05;
  color: var(--navy-500);
}

.piPrice__value i {
  font-style: normal;
  font-size: 0.4em;
  vertical-align: super;
  color: var(--ink-500);
}

/* --- Renders + figures ---------------------------------------------------- */

.pi__body2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-gap: clamp(1.25rem, 3vw, 2.5rem);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: start;
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
  text-align: left;
}

/* The tall block occupies the left half of the render, so the figures take the
   right column and the left one is deliberately left empty. */
.pi__specs {
  grid-column: 2;
  display: grid;
  grid-gap: clamp(1rem, 2.4vw, 2rem);
  gap: clamp(1rem, 2.4vw, 2rem);
}

.pi__figs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-gap: clamp(1rem, 2.4vw, 2rem);
  gap: clamp(1rem, 2.4vw, 2rem);
  text-align: center;
}

.piFig {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}

.piFig__label,
.piFig__unit {
     font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #24292d;
}

.piFig__value {
  font-family: var(--font-display);
    font-size: 55px;
    font-weight: 500;
  line-height: 1;
  color: var(--navy-500);
}

/* The top pair caption their figure from above; the pair below the CTA
   caption from below, which the markup order already reflects. */
.pi__figs--top {
  align-items: end;
}
.pi__figs.pi__figs--top .piFig .piFig__value { font-size: 120px}

/* --- CTA ------------------------------------------------------------------ */

/* A full pill rather than the shared squared-right duo shape. */
.pi__cta {
  --duo-radius: var(--radius-pill);
  width: 100%;
  margin: 0 auto;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right, #f6800e, #f9a51a, #f6800e);
  box-shadow: 0 18px 32px rgba(6, 34, 74, 0.2);
      border: solid 5px #d8e6f2;
}

 

.pi__cta > .btn + .btn {
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, 0.28);
}

.pi__cta--foot {
  width: min(100%, 34rem);
  margin: clamp(1.5rem, 3vw, 2.5rem) auto 0;
}

/* --- Blocks --------------------------------------------------------------- */

.pi__blocks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-gap: clamp(1rem, 2.4vw, 2rem);
  gap: clamp(1rem, 2.4vw, 2rem);
  text-align: center;
}

.piBlock {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
      line-height: 1;
    color: #2e3337;
      font-size: 20px;
  
}

.piBlock__name {
 font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
 
}

.piBlock__detail {
   
}

/* =========================================================================
   Utility strip
   ========================================================================= */

/* Three unequal columns, proportioned as the comp sets them: the links read
   narrowest, the countdown needs the most room for four figures and their
   separators, and the RERA block sits between the two. */
.pi__strip {
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.1fr) minmax(0, 1.04fr);
  /* No gap — the cells carry symmetric inline padding instead, so each
     hairline sits centred in open space rather than hard against the content
     that follows it. */
  grid-gap: 0;
  gap: 0;
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
  padding-block: clamp(1.25rem, 2.5vw, 2rem);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* Hairlines between the cells, drawn as borders on the cells themselves so
   they disappear along with a cell that is omitted. */
.piCell {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(0.6rem, 1.4vw, 1rem);
  padding-inline: clamp(1rem, 2.6vw, 2.5rem);
}

/* The outer edges align to the shell, so only the inner sides are inset. */
.piCell:first-child {
  padding-left: 0;
}

.piCell:last-child {
  padding-right: 0;
}

.piCell + .piCell {
  border-left: 1px solid var(--line);
}

/* --- Experience links ----------------------------------------------------- */

/* The pair is centred in its cell as a block, not individually: the two labels
   are different lengths, so centring each one would step their icons out of
   line. Sizing the wrapper to its widest child keeps the icons in one column
   and centres the group as a whole. */
.piLinks {
  display: flex;
  flex-direction: column;
  gap: clamp(0.75rem, 1.6vw, 1.35rem);
  width: -moz-fit-content;
  width: fit-content;
  margin-inline: auto;
}

.piLink {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: clamp(0.95rem, 1.15vw, 1.25rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #031f47;
  text-align: left;
  line-height: 1;
  transition: transform 0.35s var(--ease);
}

.piLink:hover {
  transform: translateX(3px);
}

.piLink__text small {
    display: block;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0;
    color: #031f47;
}

.piLink__icon {
    flex: none;
    width: 70px;
    aspect-ratio: 1;
    border-radius: 8px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 45px;
    height: 43px;
}

/* Inline SVG data URIs — two small marks, not worth two extra requests. */
.piLink__icon--tour {
     background: url(/images/theresixty-icon.png) no-repeat center #ffd47d;
    padding: 13px 30px;
    text-align: center;
    background-size: 40px;
}

.rotemapbtn .piLink__icon--tour {
     background: url(/images/routemap-icon.png) no-repeat center #ffd47d;
     
}

.degreebtn .piLink__icon { background: url(/images/theresixty-icon.png) no-repeat center #ffd47d;}

.piLink__icon--play {
  background-color: #e8232a;
  border-radius: 8px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='M9 7.5v9l8-4.5z'/%3E%3C/svg%3E");
}

/* --- Extra walkthrough row ------------------------------------------------
   Additional walkthrough films, added on their own centred row beneath the
   strip. The chips are the shared .piLink — only the axis changes, so the
   strip's own pair is untouched by anything here. */
.piLinks--row {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(1.25rem, 4vw, 3.5rem);
  margin-top: clamp(1.25rem, 2.6vw, 2rem);
}

/* The walkthrough is a <button> (it opens the popup player, not a page), so
   the UA button chrome is stripped back to the shared .piLink look. */
button.piLink {
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  cursor: pointer;
}

/* The walkthrough popup itself is the shared player — see .vModal in
   components.css and components/VideoModal.jsx. */

/* --- Countdown ------------------------------------------------------------ */

/* The widest share of the strip is allotted on .pi__strip's track sizing —
   four figures plus their separators is the most crowded of the three cells.
   This cell only has to centre what it holds. */
.piCell--count {
  align-items: center;
}

.piCount {
  min-width: 0;
}

.piCount__label {
  font-size: clamp(0.68rem, 0.9vw, 1.05rem);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-500);
  text-align: center;
}

.piCount__row {
  display: flex;
  justify-content: center;
  gap: 26px;
  margin-top: 0.5rem;
}

.piCount__cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.piCount__sep {
  position: absolute;
    left: -18px;
    top: -12px;
    font-size: 47px;
  color: #0f3d6a;
}

/* Tabular figures, or the row jitters sideways every second as the digits
   change width. */
.piCount__value {
   font-size: 55px;
  font-weight: 500;
  line-height: 1;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  color: #0f3d6a;
      letter-spacing: -4px;
}

.piCount__unit {
  font-size: clamp(0.55rem, 0.65vw, 0.75rem);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-500);
}

/* --- RERA ----------------------------------------------------------------- */

.piCell--rera {
  flex-direction: row;
  align-items: center;
  gap: clamp(0.75rem, 1.8vw, 1.5rem);
}

.piQr {
  margin: 0;
  text-align: center;
}

.piQr img {
  width: clamp(64px, 6vw, 104px);
  height: auto;
}

.piQr figcaption {
  margin-top: 0.4rem;
  font-size: clamp(0.58rem, 0.68vw, 0.78rem);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* Navy in the comp, not the muted ink the other captions use. */
  color: var(--navy-500);
  display: none;
}

.piRera {
  font-size: clamp(0.82rem, 1.05vw, 1.2rem);
  line-height: 1.45;
  color: #313131;
  text-align: left;
}

.piRera__label {
  /* The comp breaks after the label, so the number starts its own line. */
  display: block;
  font-weight: 600;
  color: #313131;
}

/* =========================================================================
   Amenities
   -------------------------------------------------------------------------
   Four ruled columns over a ghosted word, with a drag-scrollable rail of
   photography along the foot. --amp is a 0–1 scroll progress the watermark
   drifts against.
   ========================================================================= */

.am {
  --amp: 0.5;

  position: relative;
  overflow: hidden;
  padding-top: clamp(3rem, 7vw, 6rem);
  background: #051b41;
  color: #fff;
}

/* Oversized and barely there, sitting behind the lists. Tracked out so it
   spans the shell rather than sitting as a word in the middle. */
.am__watermark {
  position: absolute;
  top: clamp(6rem, 14vw, 12rem);
  left: 50%;
  z-index: 0;
  font-family: var(--font-display);
  font-size: clamp(6rem, 19vw, 20rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(255, 255, 255, 0.045);
  transform: translate3d(-50%, calc((var(--amp) - 0.5) * -40px), 0);
  pointer-events: none;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
}

.am__head,
.am__columns {
  position: relative;
  z-index: 1;
}

.am__sub {
  max-width: 62ch;
  margin: clamp(0.75rem, 1.6vw, 1.2rem) auto 0;
  font-size: clamp(0.85rem, 1vw, 1.15rem);
  color: rgba(255, 255, 255, 0.6);
  text-align: center;
}

/* --- Columns -------------------------------------------------------------- */

.am__columns {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  grid-gap: clamp(1.25rem, 3vw, 2.75rem);
  gap: clamp(1.25rem, 3vw, 2.75rem);
  margin-top: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}

.amCol {
  display: grid;
  /* Content height, not row height: without this the column's rows stretch to
     fill whatever the tallest sibling column set, and the extra space lands
     between the groups as a gap. */
  align-content: start;
  grid-gap: clamp(1.25rem, 2.5vw, 2rem);
  gap: clamp(1.25rem, 2.5vw, 2rem);
  min-width: 0;
}

.amGroup {
  min-width: 0;
}

.amGroup__title {
  font-family: var(--font-body);
  font-size: clamp(0.8rem, 0.95vw, 1.1rem);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gold-500);
}

/* The hairline runs down the list, not the whole column — it should stop
   where the items stop, so a two-item group gets a short rule. */
.amGroup__list {
  margin-top: 0.6rem;
  padding-left: clamp(0.65rem, 1.2vw, 1rem);
  border-left: 1px solid rgba(255, 255, 255, 0.28);
  list-style: none;
}

.amGroup__list li {
  font-size: clamp(0.82rem, 0.95vw, 1.1rem);
  line-height: 1.9;
  color: rgba(255, 255, 255, 0.92);
}

/* Rows arrive in sequence within their column. The [data-reveal] delay
   offsets each column; --i staggers the rows inside it. */
.amGroup__list li.is-visible {
  transition-delay: calc(var(--i, 0) * 45ms);
}

/* --- Photography rail ----------------------------------------------------- */

/* grab/grabbing rather than a scrollbar — the rail is dragged, and the cursor
   is the only affordance saying so. */
.am__rail {
  position: relative;
  z-index: 1;
  margin-top: clamp(2rem, 5vw, 4rem);
  overflow: hidden;
  cursor: -webkit-grab;
  cursor: grab;
}

.am__rail:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.am__track {
  display: flex;
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
  width: max-content;
  /* Room for the deepest tile to hang into without clipping the rail. */
  padding-bottom: 0;
  will-change: transform;
}

.am__set {
  display: flex;
  align-items: flex-start;
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
}

/* Each tile hangs by a fraction of its own height, so the stagger holds at
   any tile size rather than being pinned to a pixel offset. */
.amTile {
  flex: 0 0 auto;
  margin: 0;
  width: clamp(200px, 21vw, 380px);
  transform: translateY(calc(var(--drop, 0) * 100%));
  transition: transform 0.5s var(--ease);
}

.amTile:hover {
  transform: translateY(calc(var(--drop, 0) * 100% - 8px));
}

/* Above the image, per the comp — so it reads as a caption to what follows
   rather than a label sitting on the picture. */
.amTile__label {
  margin-bottom: 0.6rem;
  font-size: clamp(0.62rem, 0.78vw, 0.9rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #fff;
}

.amTile img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  transition: filter 0.5s var(--ease);
  filter: saturate(0.92);
}

.amTile:hover img {
  filter: saturate(1.05);
}

/* =========================================================================
   Space planning
   ========================================================================= */

.sp {
  padding-block: clamp(3rem, 7vw, 6rem);
  background: #fff;
}

.sp__blurb {
  max-width: 46rem;
  margin: clamp(0.6rem, 1.4vw, 1rem) auto 0;
  text-align: center;
  color: var(--ink-500);
}

.sp__body {
  display: grid;
  grid-template-columns: minmax(0, 0.26fr) minmax(0, 1fr);
  grid-gap: clamp(1.5rem, 3.5vw, 3rem);
  gap: clamp(1.5rem, 3.5vw, 3rem);
  align-items: start;
  margin-top: clamp(1.75rem, 4vw, 3rem);
}

/* Vertical rail. The gold rule is drawn on the rail, not on each tab, so it
   runs unbroken past every entry the way the comp has it. */
.sp__rail {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: clamp(0.4rem, 1vw, 0.9rem);
  padding-right: clamp(0.75rem, 1.6vw, 1.25rem);
}

.sp__rail::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 2px;
  background: var(--gold-500);
}

.spTab {
  display: grid;
  grid-gap: 0.1rem;
  gap: 0.1rem;
  padding: clamp(0.5rem, 1.1vw, 0.8rem) clamp(0.75rem, 1.6vw, 1.1rem);
  text-align: right;
  color: var(--navy-500);
  transition: background-color 0.45s var(--ease), color 0.45s var(--ease),
    transform 0.45s var(--ease);
}

.spTab__name {
  font-family: var(--font-display);
  font-size: 35px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}

.spTab__kind {
  font-size: 18px;
  font-weight: 600;
   text-transform: uppercase;
  opacity: 0.85;
}

.spTab:hover {
  transform: translateX(-3px);
}

/* The gold block reaches the rule, so the active plan and the rule read as
   one shape rather than a chip sitting near a line. */
.spTab.is-active {
  margin-right: calc(clamp(0.75rem, 1.6vw, 1.25rem) * -1);
  padding-right: clamp(0.75rem, 1.6vw, 1.25rem);
  background: var(--gold-500);
  color: #fff;
  transform: none;
}

/* ---- Unit types along the top ---------------------------------------- */
.sp__variants {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.5rem, 2vw, 2rem);
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--navy-500);
      max-width: max-content;
    margin: 0 auto;
}

.spVar {
  position: relative;
  padding-bottom: 0.75rem;
  margin-bottom: -0.75rem;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--ink-500);
  transition: color 0.4s var(--ease);
}

/* Underline grows from the centre out on selection — the rule beneath is the
   track it slides along. */
.spVar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  background: var(--navy-500);
  transform: scaleX(0);
  transition: transform 0.45s var(--ease);
}

.spVar:hover {
  color: var(--navy-500);
}

.spVar.is-active {
  font-weight: 700;
  color: var(--navy-900);
}

.spVar.is-active::after {
  transform: scaleX(1);
}

/* ---- The unit-type slider -------------------------------------------- */

/* The window the track moves behind. `touch-action` keeps vertical scrolling
   native while the component claims horizontal drags for the swipe. */
.sp__viewport {
  overflow: hidden;
  margin-top: clamp(1.25rem, 3vw, 2.5rem);
  touch-action: pan-y;
}

/* All the variants side by side, moved a whole panel at a time. --i is the
   active index, set inline by the component. */
.sp__track {
  --i: 0;

  display: flex;
  align-items: start;
  transform: translate3d(calc(var(--i) * -100%), 0, 0);
  transition: transform 0.62s var(--ease);
  /* Promoted up front, or the first slide hitches while the layer is made. */
  will-change: transform;
}

.sp__panel {
  /* Never shrink to fit its siblings — each slide is exactly the viewport. */
  flex: 0 0 100%;
  min-width: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
  grid-gap: clamp(1.25rem, 3vw, 2.5rem);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: start;
}

#sp-track-master-master .sp__panel {
  /* Never shrink to fit its siblings — each slide is exactly the viewport. */
 grid-template-columns: minmax(0, 1.85fr) minmax(0, 0.15fr);
 }

 #sp-track-typical-typical .sp__panel {
  /* Never shrink to fit its siblings — each slide is exactly the viewport. */
 grid-template-columns: minmax(0, 1.85fr) minmax(0, 0.15fr);
 }

/* The off-stage panels still set the track's height, so the stage does not
   jump between a tall drawing and a short one — they are just faded back so
   nothing bleeds visibly at the edges mid-slide. */
.sp__panel.is-off {
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}

/* Retained for .sg__media, which still fades in on arrival — the plan panels
   slide instead, but the site-gallery media does not. */
@keyframes spFade {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.sp__plan {
  overflow: hidden;
  margin: 0;
}

.sp__plan img {
  width: 100%;
  height: auto;
  /* Settles in behind the panel fade rather than arriving with it. */
  animation: spPlan 1s var(--ease) 0.1s both;
}

@keyframes spPlan {
  from {
    opacity: 0;
    transform: scale(1.03);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.sp__plan--empty {
  aspect-ratio: 16 / 10;
  background: repeating-linear-gradient(
    45deg,
    #fff 0 12px,
    var(--paper-blue) 12px 24px
  );
  opacity: 0.5;
}

.sp__side {
  display: grid;
  grid-gap: clamp(1.25rem, 3vw, 2.5rem);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding-top: clamp(0.5rem, 2vw, 2rem);
}

/* Label and value on one line — "Block : B", as drawn. */
.sp__facts {
  display: grid;
  grid-gap: clamp(0.35rem, 0.9vw, 0.6rem);
  gap: clamp(0.35rem, 0.9vw, 0.6rem);
}

.sp__facts > div {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  animation: spFact 0.5s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 80ms + 150ms);
}

@keyframes spFact {
  from {
    opacity: 0;
    transform: translateX(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.sp__facts dt {
  font-size: var(--fs-body-sm);
  font-weight: 700;
  color: var(--navy-900);
}

.sp__facts dt::after {
  content: " :";
  font-weight: 400;
  color: var(--ink-500);
}

.sp__facts dd {
  font-size: var(--fs-body-sm);
  color: var(--ink-500);
}

/* ---- Prev / next ------------------------------------------------------ */
.sp__nav {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.spNav {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border: 1px solid rgba(11, 32, 64, 0.25);
  border-radius: 50%;
  color: var(--navy-900);
  transition: background-color 0.4s var(--ease), border-color 0.4s var(--ease),
    color 0.4s var(--ease);
}

.spNav svg {
  width: 1.1rem;
  height: 1.1rem;
  transition: transform 0.4s var(--ease);
}

.spNav svg[data-dir="prev"] {
  transform: scaleX(-1);
}

.spNav:hover {
  background: var(--navy-900);
  border-color: var(--navy-900);
  color: #fff;
}

.spNav:hover svg {
  transform: translateX(3px);
}

.spNav:hover svg[data-dir="prev"] {
  transform: scaleX(-1) translateX(3px);
}

/* The comp's rule, doubling as the position readout: a hairline the full width
   with a navy segment filled to --p (0–1), so how far through the drawings you
   are is legible without adding a counter the comp doesn't have. */
.sp__navRule {
  --p: 1;

  position: relative;
  flex: 1 1;
  height: 1px;
  background: rgba(11, 32, 64, 0.25);
}

.sp__navRule::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 100%;
  background: var(--navy-900);
  transform: scaleX(var(--p));
  transform-origin: left;
  transition: transform 0.62s var(--ease);
}

/* ---- Enlarge trigger --------------------------------------------------- */

/* The whole drawing is the hit area. `display: block` so the button does not
   sit on a text baseline and leave a gap under the image. */
.sp__zoom {
  display: block;
  position: relative;
  width: 100%;
  overflow: hidden;
  cursor: zoom-in;
}

.sp__zoom img {
  display: block;
}

/* The cue is held back until the drawing is hovered — on the page the plan
   should read as a drawing, not as a control. It stays visible on focus, or
   keyboard users get no indication the plan opens. */
.sp__zoomCue {
  position: absolute;
  right: clamp(0.5rem, 1.4vw, 1rem);
  bottom: clamp(0.5rem, 1.4vw, 1rem);
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  padding: 0.5em 0.9em;
  border-radius: 999px;
  background: rgba(11, 32, 64, 0.88);
  color: #fff;
  font-size: clamp(0.62rem, 0.72vw, 0.78rem);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
}

.sp__zoomCue svg {
  width: 1.15em;
  height: 1.15em;
}

.sp__zoom:hover .sp__zoomCue,
.sp__zoom:focus-visible .sp__zoomCue {
  opacity: 1;
  transform: none;
}

/* =========================================================================
   Plan viewer — the enlarged drawing
   -------------------------------------------------------------------------
   A zoom-and-pan surface, not a plain lightbox: room dimensions are the
   reason to open a floor plan at all, and they are set small.
   ========================================================================= */

.pv {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  padding: clamp(0.75rem, 2.5vw, 2rem);
  animation: pvIn 0.35s var(--ease) both;
}

@keyframes pvIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.pv__scrim {
  position: absolute;
  inset: 0;
  background: rgba(3, 16, 38, 0.86);
  /* Sits behind the drawing but still takes the click that closes. */
  cursor: zoom-out;
}

.pv__body {
  position: relative;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  grid-gap: clamp(0.5rem, 1.5vw, 1rem);
  gap: clamp(0.5rem, 1.5vw, 1rem);
  width: min(1200px, 100%);
  height: min(92vh, 100%);
  padding: clamp(0.75rem, 2vw, 1.25rem);
  border-radius: var(--radius-lg);
  background: #fff;
  box-shadow: 0 30px 90px rgba(3, 16, 38, 0.45);
  animation: pvRise 0.45s var(--ease) both;
}

@keyframes pvRise {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.pv__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: clamp(0.5rem, 1.2vw, 0.85rem);
  border-bottom: 1px solid var(--line);
}

.pv__title {
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 1.4vw, 1.35rem);
  font-weight: 700;
  color: var(--navy-900);
}

.pv__tools,
.pv__nav {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.pvBtn {
  display: grid;
  place-items: center;
  min-width: 2.3rem;
  height: 2.3rem;
  padding-inline: 0.55rem;
  border: 1px solid rgba(11, 32, 64, 0.25);
  border-radius: 999px;
  color: var(--navy-900);
  font-size: 0.72rem;
  font-weight: 600;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease),
    color 0.35s var(--ease), opacity 0.35s var(--ease);
}

.pvBtn svg {
  width: 1.05rem;
  height: 1.05rem;
}

.pvBtn:hover:not(:disabled) {
  background: var(--navy-900);
  border-color: var(--navy-900);
  color: #fff;
}

.pvBtn:disabled {
  opacity: 0.35;
  cursor: default;
}

.pvBtn--level {
  min-width: 3.6rem;
}

.pvBtn--close {
  margin-left: 0.35rem;
  background: var(--navy-900);
  border-color: var(--navy-900);
  color: #fff;
}

.pvBtn--close:hover {
  background: var(--gold-500);
  border-color: var(--gold-500);
}

/* The window the drawing is scaled and dragged inside. `touch-action: none`
   hands pinch and drag to the component — the page behind is locked anyway. */
.pv__frame {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  min-height: 0;
  background: var(--paper-blue);
  border-radius: var(--radius-sm);
  cursor: zoom-in;
  touch-action: none;
}

.pv__frame.is-zoomed {
  cursor: -webkit-grab;
  cursor: grab;
}

.pv__frame.is-zoomed:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.pv__img {
  max-width: 100%;
  max-height: 100%;
  /* Transformed from the centre, which is what the zoom-about-cursor maths in
     PlanViewer assumes when it corrects the offset. */
  transform-origin: center;
  transition: transform 0.16s linear;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  -webkit-user-drag: none;
}

.pv__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-top: clamp(0.4rem, 1.2vw, 0.75rem);
  border-top: 1px solid var(--line);
}

/* The schedule reads as a row here rather than the column it forms on the
   page — the viewer is wide and short of vertical room. */
.pv__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem clamp(0.9rem, 2.5vw, 2rem);
}

.pv__facts > div {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  font-size: clamp(0.72rem, 0.9vw, 0.95rem);
}

.pv__facts dt {
  font-weight: 700;
  color: var(--navy-900);
}

.pv__facts dt::after {
  content: " :";
}

.pv__facts dd {
  color: var(--ink-700);
}

/* ---- Key plan --------------------------------------------------------- */
.sp__key {
  margin: 0;
}

.sp__key figcaption {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--navy-900);
}

.sp__keyBody {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  margin-top: 0.75rem;
  width: 100%;
}

.sp__keyBody img {
  width: 100%;
  height: auto;
}

.spCompass {
  width: clamp(64px, 7vw, 104px);
  height: auto;
  color: var(--navy-900);
  /* Turns a few degrees as it settles, so the rose feels like an instrument. */
  animation: spCompass 1.2s var(--ease) 0.3s both;
  display: none;
}

.spCompass text {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  fill: currentColor;
}

.spCompass__n {
  fill: #c02b1c;
}

@keyframes spCompass {
  from {
    opacity: 0;
    transform: rotate(-12deg);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ---- Paired call to action -------------------------------------------- */
.sp__ctas {
   --duo-radius: var(--radius-pill);
    width: min(100%, 30rem);
    margin: clamp(1.75rem, 4vw, 3.5rem) auto 0;
    border-radius: var(--radius-pill);
    background: linear-gradient(to right, #f6800e, #f9a51a, #f6800e);
    box-shadow: 0 18px 32px rgba(6, 34, 74, 0.2);
   margin: 0 auto;
    display: flex;
    margin-top: 45px;
 
}
 
/* =========================================================================
   Pricing
   ========================================================================= */

.pr {
  padding-block: clamp(3rem, 7vw, 6rem);
  background: var(--paper-alt);
}

/* Title and blurb hang off the left edge of the card rather than centring, so
   the eye lands on the same rule the first column starts on. */
.pr__title {
  text-align: left;
  margin-inline: 0;
}

.pr__blurb {
  margin-top: 0.6rem;
  max-width: 72ch;
  font-size: var(--fs-body-sm);
  color: var(--ink-500);
}

/* The card is the gold-outlined white plate the table sits on. The border and
   the radius live here — not on .pr__scroll — so that clipping the scroll box
   cannot eat the outline on a narrow viewport. */
.pr__card {
  margin-top: clamp(1.75rem, 4vw, 3rem);
  background: #fff;
  border: 1px solid var(--gold-500);
  border-radius: 16px;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

/* The table can outgrow a phone, so it scrolls inside its own box rather than
   forcing the page sideways. */
.pr__scroll {
  
}

.pr__table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  font-size: var(--fs-body-sm);
}

/* One inset value drives both the cell padding and the width of the row
   hairlines, so the rules always start and stop exactly on the text. */
.pr__table {
  --pr-pad: clamp(1.1rem, 3vw, 3.5rem);
}

.pr__table th,
.pr__table td {
  padding: clamp(0.85rem, 1.7vw, 1.25rem) clamp(1rem, 2.2vw, 1.75rem);
  text-align: left;
  white-space: nowrap;
}

.pr__table th:first-child,
.pr__table td:first-child {
  padding-left: var(--pr-pad);
}

.pr__table th:last-child,
.pr__table td:last-child {
  padding-right: var(--pr-pad);
}

.pr__table thead th {
  background: var(--gold-500);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #513301;
  padding-block: clamp(0.9rem, 1.8vw, 1.15rem);
}

/* Hairlines between rows only — the header sits on its own gold field. Drawn
   as an inset background stripe rather than a cell border, because a border
   would run edge to edge under the padding instead of stopping short of it. */
.pr__table tbody tr + tr {
  background-image: linear-gradient(rgba(12, 58, 108, 0.12), rgba(12, 58, 108, 0.12));
  background-repeat: no-repeat;
  background-position: var(--pr-pad) top;
  background-size: calc(100% - var(--pr-pad) * 2) 1px;
}

 

.pr__table tbody td {
    color: #434444;
    font-size: 17px;
    font-weight: 600;
}

.pr__table tbody tr {
  transition: background-color 0.3s var(--ease);
}

/* background-color, not the shorthand — the shorthand would wipe the hairline
   drawn as a background-image above. */
.pr__table tbody tr:hover {
  background-color: rgba(248, 166, 25, 0.08);
}

/* The card closes on a rule and a band of quiet space below the last row,
   matching the comp. */
.pr__card::after {
  content: "";
  display: block;
  height: clamp(2rem, 4vw, 3.25rem);
  border-top: 1px solid rgba(12, 58, 108, 0.12);
  margin-inline: clamp(1.1rem, 3vw, 3.5rem);
}

.pr__note {
  margin-top: clamp(0.9rem, 2vw, 1.4rem);
  font-size: var(--fs-body-sm);
  color: var(--ink-500);
}

/* Asterisk that pairs the note with the starred "Starting From" price. */
.pr__note::before {
  content: "*";
  margin-right: 0.15em;
}

@media (max-width: 640px) {
  .pr__table th,
  .pr__table td {
    padding-inline: 1rem;
  }
}

/* =========================================================================
   EMI calculator
   ========================================================================= */

/* The section is now a slim navy band — a title, a line of copy and one
   button. The calculator itself sits in .emiModal, opened by that button. */
.emi {
  padding-block: clamp(2.5rem, 5.5vw, 4.5rem);
  background: var(--grad-navy);
  color: #fff;
}

/* Two blocks meeting at the centre: the title ranged right against the copy
   ranged left, as in the comp. */
.emi__band {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 4vw, 3.5rem);
}

.emi__title {
  flex: 0 1 auto;
  margin-inline: 0;
  text-align: right;
}

/* Each tone run takes its own line, so "Home Loan" sits above
   "EMI Calculator" without the data carrying a line break. */
.emi__title em {
  display: block;
}

.emi__copy {
  flex: 0 1 34rem;
  min-width: min(100%, 18rem);
  text-align: left;
}

.emi__blurb {
  max-width: 34ch;
  font-size: clamp(1rem, 1.5vw, 1.35rem);
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.9);
}

.emi__cta {
  margin-top: clamp(1.1rem, 2.2vw, 1.8rem);
  background: linear-gradient(to right, #f6800e, #f9a119);
  color: #fff;
  box-shadow: 0 14px 34px rgba(2, 14, 34, 0.45);
}

.emi__cta:hover {
transform: none;
    background-size: 100% 100%;
    color:#000;
   
}

@media (max-width: 780px) {
  .emi__band {
    justify-content: flex-start;
    gap: 0;
  }

  .emi__title {
    flex-basis: 100%;
    text-align: left;
  }
 
}
 

/* --- Modal --------------------------------------------------------------- */

/* A native <dialog>: showModal() puts it in the top layer, so no z-index here
   has to win against anything else on the page. */
.emiModal {
  /* The global `* { margin: 0 }` reset wipes the UA's `margin: auto` on
     <dialog>, which is what normally centres a modal — so centre it here
     explicitly rather than letting it pin to the top-left corner. */
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(56rem, calc(100vw - 2rem));
  max-height: min(90vh, 52rem);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--grad-navy-panel);
  color: #fff;
  box-shadow: 0 40px 90px rgba(2, 12, 30, 0.55);
  overflow: auto;
  overscroll-behavior: contain;
}

.emiModal::-webkit-backdrop {
  background: rgba(3, 14, 32, 0.72);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.emiModal::backdrop {
  background: rgba(3, 14, 32, 0.72);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.emiModal__inner {
  padding: clamp(1.25rem, 3vw, 2.25rem);
}

.emiModal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: clamp(1rem, 2.4vw, 1.75rem);
}

.emiModal__title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.6vw, 2rem);
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  color: var(--gold-500);
}

.emiModal__close {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.6rem;
  line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  cursor: pointer;
  transition: background-color 0.25s var(--ease);
}

.emiModal__close:hover {
  background: rgba(255, 255, 255, 0.2);
}

.emiModal__note {
  margin-top: clamp(0.9rem, 2vw, 1.4rem);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.66);
}

.emi__panel {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  grid-gap: clamp(1.5rem, 3vw, 2.5rem);
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
  padding: clamp(1.25rem, 2.6vw, 2.25rem);
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

@media (max-width: 700px) {
  .emi__panel {
    grid-template-columns: minmax(0, 1fr);
  }
}

.emi__fields {
  display: grid;
  grid-gap: clamp(1rem, 2.2vw, 1.75rem);
  gap: clamp(1rem, 2.2vw, 1.75rem);
}

.emiField {
  min-width: 0;
}

.emiField__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.66);
}

.emiField__label output {
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.6vw, 1.5rem);
  font-weight: 700;
  letter-spacing: 0;
  color: #fff;
}

/* The filled portion is a background gradient driven by --fill, because a
   range input gives no hook for styling the track left of the thumb. */
.emiField__input {
  width: 100%;
  height: 6px;
  margin-top: 0.7rem;
  border-radius: var(--radius-pill);
  background: linear-gradient(
    90deg,
    var(--gold-500) 0 var(--fill, 50%),
    rgba(255, 255, 255, 0.2) var(--fill, 50%) 100%
  );
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  cursor: pointer;
}

.emiField__input::-webkit-slider-thumb {
  -webkit-appearance: none;
          appearance: none;
  width: 20px;
  height: 20px;
  border: 3px solid var(--gold-500);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 4px 12px rgba(4, 20, 45, 0.4);
  -webkit-transition: transform 0.25s var(--ease);
  transition: transform 0.25s var(--ease);
}

.emiField__input::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border: 3px solid var(--gold-500);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 4px 12px rgba(4, 20, 45, 0.4);
}

.emiField__input:active::-webkit-slider-thumb {
  transform: scale(1.15);
}

/* --- Result -------------------------------------------------------------- */

.emi__result {
  display: grid;
  justify-items: center;
  grid-gap: clamp(0.6rem, 1.4vw, 1rem);
  gap: clamp(0.6rem, 1.4vw, 1rem);
  text-align: center;
}

.emiDonut {
  width: clamp(110px, 12vw, 160px);
  height: auto;
  fill: none;
  transform: rotate(-90deg);
}

.emiDonut__track {
  stroke: rgba(255, 255, 255, 0.16);
  stroke-width: 10;
}

/* No keyframes: the dash offset is recomputed on every render from the
   interest share, and the transition carries it there. */
.emiDonut__arc {
  stroke: var(--gold-500);
  stroke-width: 10;
  stroke-linecap: round;
  transition: stroke-dashoffset 0.5s var(--ease);
}

.emi__figureLabel {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.66);
}

.emi__figure strong {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 3.4vw, 3rem);
  font-weight: 700;
  line-height: 1;
  color: #fff;
}

.emi__totals {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-gap: 0.75rem 1.25rem;
  gap: 0.75rem 1.25rem;
  width: 100%;
  padding-top: clamp(0.6rem, 1.4vw, 1rem);
  border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.emi__totals dt {
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

.emi__totals dd {
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--gold-400);
}

/* =========================================================================
   Specifications
   -------------------------------------------------------------------------
   A numbered accordion on a light field, over a ghosted tower render.
   --spcp is a 0–1 scroll progress the watermark drifts against.
   ========================================================================= */

.spec {
  --spcp: 0.5;

  position: relative;
  overflow: hidden;
  padding-block: clamp(3rem, 7vw, 6rem);
  background: linear-gradient(180deg, #ffffff 0%, #f4f7fb 100%);
  color: var(--ink-900);
}

/* Barely there, and masked away at the foot so it fades out rather than
   ending on a hard edge. */
.spec__watermark {
  position: absolute;
  top: 8%;
  left: 0;
  z-index: 0;
  width: 100%;
  opacity:0;
 pointer-events: none;
}

.spec__watermark img {
  width: 100%;
  height: auto;
}

.spec__head,
.spec .shell {
  position: relative;
  z-index: 1;
}

.spec__sub {
  max-width: 62ch;
  margin: clamp(0.75rem, 1.6vw, 1.2rem) auto 0;
  font-size: clamp(0.85rem, 1vw, 1.15rem);
  color: var(--ink-500);
  text-align: center;
}

/* --- Rows ----------------------------------------------------------------- */

.spec__list {
  margin-top: clamp(1.75rem, 4vw, 3.5rem);
  border-top: 1px solid var(--line);
  list-style: none;
}

.specItem {
  border-bottom: 1px solid var(--line); opacity: 1;
  transform: inherit;  
   transition: inherit;
}

.specItem.is-open{opacity: 1;}

.specItem__h {
  margin: 0;
}

/* Three columns: number, title, sign. The title track takes the slack so the
   sign stays pinned right however long the heading runs. */
.specItem__q {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  grid-gap: 15px;
  gap: 15px;
  width: 100%;
  padding: clamp(0.95rem, 2vw, 1.5rem) 0;
  text-align: left;
  color: var(--navy-500);
  transition: color 0.35s var(--ease);
}

.specItem__num {
  font-size: 20px;
  font-weight: 500;
  font-feature-settings: "tnum";
  font-variant-numeric: tabular-nums;
  color: #3e3e3e;
  transition: color 0.35s var(--ease);
}

.specItem__title {
  font-family: var(--font-display);
  font-size: 35px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  /* Nudges right as the row opens or is pointed at — a small acknowledgement
     that costs nothing and makes the list feel live. */
  transition: transform 0.4s var(--ease);
}

.specItem__q:hover .specItem__title,
.specItem.is-open .specItem__title {
  transform: translateX(6px);
}

.specItem__q:hover .specItem__num,
.specItem.is-open .specItem__num {
  color: var(--gold-500);
}

/* A plus that becomes a minus: two bars, the upright one collapsing and
   turning as it goes. */
.specItem__sign {
  position: relative;
  flex: none;
  width: clamp(14px, 1.4vw, 20px);
  aspect-ratio: 1;
  color: var(--navy-500);
}

.specItem__sign::before,
.specItem__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 2px;
  background: currentColor;
  transform: translateY(-50%);
  transition: transform 0.45s var(--ease), opacity 0.45s var(--ease);
}

.specItem__sign::after {
  transform: translateY(-50%) rotate(90deg);
}

.specItem.is-open .specItem__sign::after {
  transform: translateY(-50%) rotate(0deg);
  opacity: 0;
}

/* --- Panel ---------------------------------------------------------------- */

/* Height cannot animate to `auto`; a grid row from 0fr to 1fr can, and needs
   no measurement of the content inside it.

   visibility is switched alongside, and that is not cosmetic: a collapsed
   panel is only clipped, so without it the links and text inside stay in the
   tab order and the accessibility tree while invisible. Delaying the change
   to `hidden` by the length of the transition lets the panel finish closing
   before it disappears; opening switches it back with no delay so the content
   is present for the whole of the open. */
.specItem__a {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows 0.5s var(--ease), visibility 0s linear 0.5s;
}

.specItem.is-open .specItem__a {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows 0.5s var(--ease), visibility 0s;
}

/* min-height: 0 is what actually lets the 0fr track collapse. A grid item's
   automatic minimum size is its content, not zero, so without this the row
   never shrinks below the panel's natural height and every group renders
   permanently open. overflow: hidden usually zeroes that minimum on its own,
   but only once the item is a genuine grid item — stating it is the reliable
   form and costs nothing. */
.specItem__aIn {
  overflow: hidden;
  min-height: 0;
}

.specItem__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  grid-gap: clamp(1.25rem, 3vw, 3rem);
  gap: clamp(1.25rem, 3vw, 3rem);
  align-items: start;
  padding: clamp(0.5rem, 1.2vw, 1rem) 0 clamp(1.5rem, 3.5vw, 3rem);
}

/* Definition rows arrive in sequence once the panel is open. `both` holds the
   from-state while the row waits its turn, so nothing flashes in first. */
.specItem__defs > div {
  padding-left: 65px;
}

.specItem__defs > div + div {
  margin-top: clamp(0.9rem, 1.8vw, 1.4rem);
}

.specItem.is-open .specItem__defs > div {
  animation: specRow 0.5s var(--ease) both;
  animation-delay: calc(140ms + var(--n, 0) * 70ms);
}

@keyframes specRow {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.specItem__defs dt {
     font-size: 20px;
    font-weight: 700;
    color: #3e3e3e;
    line-height: 1.2;
}

.specItem__defs dd {
  margin-top: 0.15rem;
  color: #3e3e3e;
}

/* Plain bulleted list — groups whose rows are single lines with no term
   (e.g. Structure). Same indent and stagger as the definition rows. */
.specItem__points {
  list-style: none;
  padding-left: 65px;
  color: #3e3e3e;
}

.specItem__points li {
  position: relative;
  padding-left: 1.1em;
}

.specItem__points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.specItem__points li + li {
  margin-top: clamp(0.6rem, 1.2vw, 1rem);
}

.specItem.is-open .specItem__points li {
  animation: specRow 0.5s var(--ease) both;
  animation-delay: calc(140ms + var(--n, 0) * 70ms);
}

.specItem__empty {
  padding-left: clamp(0.5rem, 1.6vw, 1.5rem);
  font-size: var(--fs-body-sm);
  line-height: 1.7;
  color: var(--ink-500);
}

.specItem__empty code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
  color: var(--navy-500);
}

/* Eases up and out of a slight overscale as the panel opens, so the picture
   arrives with the copy rather than being revealed by the clip. */
.specItem__media {
  margin: 0;
  overflow: hidden;
}

.specItem.is-open .specItem__media {
  animation: specMedia 0.7s var(--ease) 0.12s both;
}

@keyframes specMedia {
  from {
    opacity: 0;
    transform: scale(1.06) translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.specItem__media img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* --- CTA ------------------------------------------------------------------ */

.spec__cta {
  --duo-radius: var(--radius-pill);

  width: min(100%, 30rem);
  margin: clamp(1.75rem, 4vw, 3.5rem) auto 0;
  border-radius: var(--radius-pill);
  background: linear-gradient(to right, #f6800e, #f9a119);
  box-shadow: 0 18px 32px rgba(6, 34, 74, 0.2);
}

 

/* =========================================================================
   Connectivity
   ========================================================================= */

.cn {
  position: relative;
  isolation: isolate;
  padding-top:80px;
  /* The category rail runs flush to the bottom edge, as on the comp. */
  padding-bottom: 0;
  background: var(--grad-navy-panel);
  color: #fff;
  overflow: hidden;
}

/* Locality aerial, dropped back behind a navy wash so the type stays readable
   and the section still reads as one navy field. */
.cn__backdrop {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.cn__backdrop img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  
}

 

.cn__place {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin-top: clamp(0.75rem, 1.6vw, 1.2rem);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
}

/* "Google Map View | Location Map" — one pill, the divider drawn between. */
.cn__links {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.55em 1.4em;
  letter-spacing: 0.14em;
  margin-top: 14px;
}

.cn__links > * + *::before {
  content: "|";
  margin-right: 0.9rem;
  color: rgba(255, 255, 255, 0.4);
}

.cn__links a {
  color: inherit;
  transition: color 0.35s var(--ease);
      text-transform: uppercase;
       font-size: 15px;
}
.cn__links button {
  color: inherit;
  transition: color 0.35s var(--ease);
   text-transform: uppercase;
    font-size: 15px;
}

.cn__links a:hover {
  color: var(--gold-500);
}

/* A button, because it opens the map in place rather than navigating — but it
   sits in a row of links, so it has to read as one. */
.cn__linkBtn {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  transition: color 0.35s var(--ease);
}
.cn__links a:hover {  color: #000; }
.cn__linkBtn:hover {  color: #000; }

/* --- Location map modal --------------------------------------------------- */

.cnMap {
  /* The global `* { margin: 0 }` reset wipes the UA's `margin: auto` on
     <dialog>, which is what normally centres a modal. */
  position: fixed;
  inset: 0;
  margin: auto;
  width: min(64rem, calc(100vw - 2rem));
  max-height: min(92vh, 56rem);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--grad-navy-panel);
  color: #fff;
  box-shadow: 0 40px 90px rgba(2, 12, 30, 0.55);
  overflow: auto;
  overscroll-behavior: contain;
}

.cnMap::-webkit-backdrop {
  background: rgba(3, 14, 32, 0.72);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.cnMap::backdrop {
  background: rgba(3, 14, 32, 0.72);
  -webkit-backdrop-filter: blur(4px);
          backdrop-filter: blur(4px);
}

.cnMap__inner {
  padding: clamp(1rem, 2.4vw, 1.75rem);
}

.cnMap__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: clamp(0.75rem, 1.8vw, 1.25rem);
}

.cnMap__title {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.4vw, 1.9rem);
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  color: var(--gold-500);
}

.cnMap__close {
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  font-size: 1.6rem;
  line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  transition: background-color 0.25s var(--ease);
}

.cnMap__close:hover {
  background: rgba(255, 255, 255, 0.2);
}

.cnMap__img {
  width: 100%;
  height: auto;
  border-radius: 12px;
  background: #fff;
}

.cn__placeName {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-display);
  font-size: 45px;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: none;
  color: #fff;
}

.cn__placeName svg {
  width: 1.1em;
  height: 1.1em;
  color: var(--gold-500);
}

/* The development is already in the backdrop aerial, so the left column is
   deliberately empty — it is the render's room, not a missing element. The
   min-height keeps that room open whatever the shorter list happens to need. */
.cn .cn__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.8fr);
  grid-gap: clamp(1.5rem, 3.5vw, 3rem);
  gap: clamp(1.5rem, 3.5vw, 3rem);
  align-items: flex-start;
  min-height: clamp(320px, 40vw, 600px);
  margin-top: clamp(1.75rem, 4vw, 3rem);
  padding-bottom: clamp(2rem, 5vw, 4rem);
  padding-top:0;
}
.cn__rail{position: absolute; bottom: 0;}
 
.cn__panel {
  grid-column: 2;
}

 

/* The panel is keyed on the category, so React remounts it on every switch:
   the whole list fades up once and the rows arrive in sequence off --i. */
.cn__panel {
  animation: cnPanel 0.5s var(--ease) both;
}

@keyframes cnPanel {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Two columns, each its own list: the split is made in the markup so the left
   column always holds the same two entries. CSS `columns` would rebalance them
   as the count changed, which is not what the comp does. */
.cn__places {
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 1fr));
  grid-gap: clamp(1.5rem, 3vw, 3rem);
  gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
  list-style: none;
      grid-gap: 15px;
      gap: 15px;
    align-items: start;
    list-style: none;
    padding: 0 0 0 45%;
}

.Twocol .cn__places {
  grid-template-columns: repeat(2, minmax(0, 1fr)); 
    gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
  list-style: none;
   padding: 0;
}


.cn__column,
.cn__columnList {
  display: grid;
  align-content: start;
  grid-gap: clamp(0.5rem, 1.4vw, 1.25rem);
  gap: clamp(0.5rem, 1.4vw, 1.25rem);
  list-style: none;
}


.cnPlace {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr);
  align-items: center;
  grid-gap: 0 clamp(0.6rem, 1.2vw, 1rem);
  gap: 0 clamp(0.6rem, 1.2vw, 1rem);
  animation: cnRow 0.5s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 70ms + 120ms);
  background: url(/images/loc-icon.png) no-repeat;
      padding: 0 0 6px 58px;
      background-size: 40px;
}

.cnPlace__pin {
  width: clamp(20px, 2vw, 28px);
  height: auto;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35));
  display: none;
}

@keyframes cnRow {
  from {
    opacity: 0;
    transform: translateX(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.cnPlace__name {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
}

.cnPlace__distance {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: -0.01em;
  color: #fff;
}

/* ---- Category marquee -------------------------------------------------
   Full-bleed rail that drifts on its own and can be dragged; each card is a
   real tab button. useDragMarquee needs the set rendered twice. */
.cn__rail {
  /* Cards grow upward out of a shared baseline, so the rail is as tall as an
     open card from the start — otherwise the section would jump on hover. */
  --cn-card: clamp(72px, 8vw, 104px);
  --cn-card-open: clamp(170px, 19vw, 265px);
  height: var(--cn-card-open);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  cursor: -webkit-grab;
  cursor: grab;
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent,
    #000 6%,
    #000 94%,
    transparent
  );
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.cn__rail.is-dragging,
.cn__rail:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.cn__track {
  display: flex;
  align-items: flex-end;
  gap: clamp(0.6rem, 1.2vw, 1rem);
  width: max-content;
  will-change: transform;
}

.cn__set {
  display: flex;
  align-items: flex-end;
  gap: clamp(0.6rem, 1.2vw, 1rem);
}

.cnCard {
  position: relative;
  isolation: isolate;
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: 1.4rem;
  min-width:max-content;
  /* Explicit heights on both states so the growth animates rather than snaps. */
  height: var(--cn-card, 104px);
  padding: clamp(0.85rem, 1.6vw, 1.15rem) clamp(1rem, 2vw, 1.5rem);
  overflow: hidden;
  border-radius: 4px 4px 0 0;
  background: #fff;
  color: var(--navy-900);
  text-align: left;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  transition: height 0.6s var(--ease), color 0.5s var(--ease),
    box-shadow 0.5s var(--ease);
}

.cnCard:hover,
.cnCard.is-active {
  height: var(--cn-card-open, 265px);
}

/* No lift: the rail sits flush to the section's bottom edge, so raising a card
   would open a gap beneath it. */
.cnCard:hover {
  box-shadow: var(--shadow-lg);
}

/* Photograph fill. Scrimmed so the label keeps its contrast whatever the
   picture is, and held open by .is-active as well as :hover. */
.cnCard__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0;
  transition: opacity 0.55s var(--ease);
}

.cnCard__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    0deg,
    rgba(8, 24, 48, 0.78) 0%,
    rgba(8, 24, 48, 0.42) 38%,
    rgba(8, 24, 48, 0) 68%
  );
}

.cnCard__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.08);
  transition: transform 1.2s var(--ease);
}

.cnCard:hover .cnCard__media,
.cnCard.is-active .cnCard__media {
  opacity: 1;
}

.cnCard:hover .cnCard__media img,
.cnCard.is-active .cnCard__media img {
  transform: scale(1);
}

.cnCard:hover,
.cnCard.is-active {
  color: #fff;
}

.cnCard__text {
  flex: 1 1;
  display: grid;
  grid-gap: 0.15rem;
  gap: 0.15rem;
}

.cnCard__eyebrow {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.8);
  /* Collapsed until the card is lit, so the label sits centred at rest. */
  max-height: 0;
  opacity: 0;
  transform: translateY(-4px);
  transition: max-height 0.45s var(--ease), opacity 0.45s var(--ease),
    transform 0.45s var(--ease);
}

.cnCard:hover .cnCard__eyebrow,
.cnCard.is-active .cnCard__eyebrow {
  max-height: 1.4em;
  opacity: 1;
  transform: none;
}

.cnCard__label {
  font-family: var(--font-display);
  font-size: 37px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* One pin in every state — the selected card is simply the hover state held
   open, so nothing about it should read as a second, different treatment. */
.cnCard__pin {
  flex: 0 0 auto;
  width: clamp(20px, 2vw, 28px);
  height: auto;
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.35));
  transition: transform 0.5s var(--ease);
}

.cnCard:hover .cnCard__pin,
.cnCard.is-active .cnCard__pin {
  transform: scale(1.08);
}

/* =========================================================================
   Site progress
   ========================================================================= */

.sg {
  padding-block: clamp(3rem, 7vw, 6rem);
  background: #fff;
}

.sg__blurb {
  margin-top: 0.75rem;
  max-width: 70ch;
  margin-inline: auto;
  font-size: var(--fs-body-sm);
  color: var(--ink-500);
  text-align: center;
}

.sg__body {
  display: grid;
  grid-template-columns: minmax(0, 0.28fr) minmax(0, 1fr);
  grid-gap: clamp(1.5rem, 3.5vw, 3rem);
  gap: clamp(1.5rem, 3.5vw, 3rem);
  align-items: start;
  margin-top: clamp(1.75rem, 4vw, 3rem);
}

/* The rail hangs off a gold line on its right edge — the dates read inward,
   towards the photograph they belong to. */
.sg__rail {
  display: grid;
  list-style: none;
  border-right: 2px solid var(--gold-500);
}

.sgDate {
  position: relative;
  width: 100%;
  padding: 0.7em 1.1em 0.7em 1em;
  font-size: clamp(0.95rem, 1.2vw, 1.15rem);
  font-weight: 500;
  text-align: right;
  color: var(--ink-500);
  transition: color 0.3s var(--ease), background-color 0.3s var(--ease);
}

.sgDate:hover {
  color: var(--navy-500);
}

/* The active month is a solid gold bar spanning the rail, not a dot. */
.sgDate.is-active {
  background: var(--gold-500);
  font-weight: 700;
  color: #fff;
}

/* --- Stage --------------------------------------------------------------- */

/* The arrows sit against the photograph's edges, so the stage is the
   positioning context — not the figure, which is re-keyed on every change and
   would take its children's focus with it. */
.sg__stage {
  text-align: center;
}

.sg__frame {
  position: relative;
}

/* A fixed aspect box: the shots are stacked absolutely, so without it the
   figure would collapse to nothing and the layout would jump on every change. */
.sg__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  margin: 0;
  background: #0b1b30;
  box-shadow: var(--shadow);
  animation: spFade 0.55s var(--ease) both;
}

/* Every shot of the month sits in the same box; only opacity moves, which is
   what makes the change a dissolve rather than a blink. */
.sgShot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.03);
  transition: opacity 0.6s var(--ease), transform 0.9s var(--ease);
  pointer-events: none;
}

.sgShot.is-active {
  opacity: 1;
  transform: scale(1);
}

/* The caption fades up with its photograph. */
.sg__caption {
  animation: spFade 0.5s var(--ease) both;
}

@media (prefers-reduced-motion: reduce) {
  .sgShot {
    transition-duration: 0.001s;
    transform: none;
  }

  .sgShot.is-active {
    transform: none;
  }
}

.sgArrow {
  position: absolute;
  top: 50%;
  margin-top: calc(clamp(2.5rem, 3.4vw, 3.4rem) / -2);
  display: grid;
  place-items: center;
  width: clamp(2.5rem, 3.4vw, 3.4rem);
  height: clamp(2.5rem, 3.4vw, 3.4rem);
  font-size: 1.25rem;
  color: #fff;
  background: var(--navy-500);
  cursor: pointer;
  transition: background-color 0.3s var(--ease), transform 0.3s var(--ease);
}

.sgArrow:hover {
  background: #063b73;
  transform: scale(1.06);
}

/* Half-overlapping the photograph on each side, as in the comp. */
.sgArrow--prev {
  left: 0;
  transform: translateX(-50%);
}

.sgArrow--prev:hover {
  transform: translateX(-50%) scale(1.06);
}

.sgArrow--next {
  right: 0;
  transform: translateX(50%);
}

.sgArrow--next:hover {
  transform: translateX(50%) scale(1.06);
}

.sg__caption {
  margin-top: clamp(1rem, 2.2vw, 1.6rem);
  font-size: clamp(1rem, 1.4vw, 1.25rem);
  font-weight: 700;
  color: var(--navy-500);
}

.sg__count {
  margin-top: 0.4rem;
  font-size: var(--fs-body-sm);
  color: var(--ink-500);
}

.sg__pdf {
  margin-top: clamp(1rem, 2.2vw, 1.6rem);
  background: linear-gradient(to right, #f6800e, #f9a51a, #f6800e);
  color: #fff;
  box-shadow: 0 14px 30px rgba(6, 34, 74, 0.3);
}

/* =========================================================================
   Gallery rail
   ========================================================================= */

.pg {
  padding-block: clamp(3rem, 7vw, 6rem);
  background: var(--navy-900);
  color: #fff;
  overflow: hidden;
}

/* Left, not centred: the comp hangs the heading off the shell gutter while the
   rail below runs full-bleed past both edges. The offset between the two is
   what makes the rail read as continuing beyond the page. */
.pg__head {
  text-align: left;
}

.pg__title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
}

.pg__title span {
  display: block;
}

.pg__blurb {
  max-width: 62ch;
  margin: clamp(0.9rem, 2vw, 1.4rem) 0 0;
  font-size: var(--fs-body-sm);
  color: rgba(255, 255, 255, 0.74);
}

/* grab/grabbing rather than a scrollbar — the rail is dragged, and the cursor
   is the only affordance saying so. */
.pg__rail {
  margin-top: clamp(1.75rem, 4vw, 3rem);
  overflow: hidden;
  cursor: -webkit-grab;
  cursor: grab;
}

.pg__rail:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.pg__track {
  display: flex;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
  width: max-content;
  will-change: transform;
}

.pg__set {
  display: flex;
  gap: clamp(0.75rem, 1.5vw, 1.25rem);
}

.pgTile {
  flex: 0 0 auto;
  overflow: hidden;
  margin: 0;
  width:650px;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius);
}

.pgTile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  transition: transform 0.8s var(--ease);
}

.pgTile:hover img {
  transform: scale(1.05);
}

/* ---- Rail controls ----------------------------------------------------- */

/* Centred under the rail, the rule running between the two arrows — the comp
   uses it to tie the pair together rather than to report a position. */
.pg__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.75rem, 2vw, 1.5rem);
  margin-top: clamp(1.5rem, 3.5vw, 3rem);
}

.pgNav {
  flex: none;
  display: grid;
  place-items: center;
  width: clamp(2.75rem, 3.6vw, 3.5rem);
  aspect-ratio: 1;
  border-radius: 50%;
  color: #fff;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease),
    transform 0.4s var(--ease);
}

.pgNav svg {
  width: 42%;
  height: 42%;
  transition: transform 0.4s var(--ease);
}

.pgNav svg[data-dir="prev"] {
  transform: scaleX(-1);
}

/* The pair is weighted as the comp weights it — back is the quieter of the
   two, so the eye is pushed forward through the images. */
.pgNav--prev {
  background: rgba(255, 255, 255, 0.14);
}

.pgNav--next {
  background: var(--navy-500);
}

.pgNav:hover {
  background: var(--gold-500);
  color: var(--navy-900);
}

.pgNav:hover svg {
  transform: translateX(3px);
}

.pgNav:hover svg[data-dir="prev"] {
  transform: scaleX(-1) translateX(3px);
}

.pgNav:active {
  transform: scale(0.94);
}

.pg__navRule {
  width: clamp(90px, 11vw, 210px);
  height: 1px;
  background: rgba(255, 255, 255, 0.32);
}

/* Per-section heading hooks. They inherit everything from .pdHeading; each
   exists so a section can adjust its own without reaching for a descendant
   selector, and so no class in the markup is left dangling. */
.am__title,
.sp__title,
.spec__title,
.cn__title,
.sg__title {
  margin-inline: auto;
}

/* =========================================================================
   Quality band — closes the passport on the project page
   ========================================================================= */

.qband {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
   background: #063b73;
  color: #fff;
  overflow: hidden;
  padding: 130px 0 120px;
}

/* ---- Photography behind the wash ----------------------------------------
   Same marquee as the gallery and connectivity rails, but this one is scenery:
   aria-hidden, no links, and dropped so far behind the scrim that it reads as
   texture in the navy rather than as pictures to look at. */
/* The rail is its own stacking context (z-index), so it needs the navy on
   itself: a luminosity blend composites against the backdrop inside that
   context, and against a transparent one the photographs would come out grey
   rather than blue. */
.qband__rail {
  position: absolute;
  inset: 0;
  z-index: -1;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: #063b73;
  cursor: -webkit-grab;
  cursor: grab;
}

.qband__rail.is-dragging,
.qband__rail:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

/* A light wash only — the photographs are meant to be legible through it. The
   tiles do the colour work themselves (see the blend below), so this is just
   enough to soften the top and bottom edges and hold the type. */
.qband__rail::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(6, 59, 115, 0.35) 20%,
    #0c2262 100%
  );
  pointer-events: none;
}

.qband__track,
.qband__set {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
}

.qband__track {
  width: max-content;
  will-change: transform;
}

.qband__tile {
  flex: 0 0 auto;
  overflow: hidden;
  margin: 0;
  width: clamp(180px, 17vw, 360px);
  aspect-ratio: 1 / 1;
}

/* Luminosity blend: the photograph keeps its lights and darks but takes the
   band's blue for its colour, which is what makes the row read as one tinted
   field rather than as snapshots behind a filter. */
.qband__tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  mix-blend-mode: luminosity;
  opacity: 0.2;
}

/* ---- Type over the top ---- */
.qband__inner {
  position: relative;
  text-align: center;
}

.qband__inner h2.display {
 color: #faa61c;
}

.qband__sub {
  margin-top: clamp(0.4rem, 1.2vw, 0.9rem);
  font-size: clamp(1rem, 1.7vw, 1.6rem);
  font-weight: 400;
  color: rgba(255, 255, 255, 0.94);
}

.qband__sub--gold {
  font-weight: 700;
  color: var(--gold-500);
}

.qband__cta {
  margin-top: clamp(1.25rem, 2.5vw, 2rem);
}

/* =========================================================================
   Stories — the project page's centred carousel
   ========================================================================= */

.st {
  padding-block: clamp(3rem, 7vw, 6rem);
  background: var(--paper-alt);
  overflow: hidden;
}

.st__head {
  text-align: center;
}

.st__title {
  color: var(--navy-500);
}

.st__sub {
  margin-top: 0.2rem;
}

/* The lockup is left-aligned inside itself, so it is centred as a block. */
.st .rating {
  width: max-content;
  margin-inline: auto;
}

/* ---- Stage -------------------------------------------------------------
   The marquee of thumbnails runs the full width; the quote card is laid over
   the middle of it and never moves. */
/* Both children share one grid cell, so the stage is as tall as whichever is
   taller — the card, usually — and the marquee centres itself in that. */
.st__stage {
  display: grid;
  margin-top: clamp(1.75rem, 4vw, 3rem);
}

.st__stage > * {
  grid-area: 1 / 1;
}

/* Same marquee as the gallery and the connectivity cards: useDragMarquee
   drifts the track, pauses it under the cursor and lets it be dragged. The set
   is rendered twice so the loop can wrap without a seam. */
.st__rail {
  overflow: hidden;
  cursor: -webkit-grab;
  cursor: grab;
  -webkit-mask-image: linear-gradient(
    90deg,
    transparent,
    #000 12%,
    #000 88%,
    transparent
  );
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}

.st__rail.is-dragging,
.st__rail:active {
  cursor: -webkit-grabbing;
  cursor: grabbing;
}

.st__track,
.st__set {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
}

.st__track {
  width: max-content;
  will-change: transform;
  position: relative;
  top: 0;
}


/* ---- Quote card ----------------------------------------------------------
   Pinned to the middle of the stage. Only its contents change, so its own box
   has to stay put — the marquee passes behind it. */
.stQuote {
  position: relative;
  z-index: 1;
  place-self: center;
  isolation: isolate;
  overflow: hidden;
  width: min(46rem, 78vw);
  padding: clamp(1.5rem, 3.5vw, 3.25rem);
  background: #fff;
  /* Barely there — the card reads as a flat plate on the grey, not a raised
     panel, so the shadow only has to separate it from the thumbnails. */
  box-shadow: 0 24px 60px rgba(6, 34, 74, 0.07);
  display: none;
}

/* Oversized G, cropped by the card on three sides — a watermark, not a logo,
   which is why it sits off to the left rather than centred behind the text. */

.stQuote::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 55%;
    height: 100%;
    aspect-ratio: 1;
    pointer-events: none;
    background: url(/media/story-c-bg.png) no-repeat;
    filter: grayscale(100%) opacity(0.9);
    background-size: 100%;
}

 .stQuote__mark {
  position: absolute;
  top: 50%;
  left: 4%;
  z-index: -1;
  font-family: var(--font-display);
  font-size: clamp(20rem, 34vw, 34rem);
  font-weight: 700;
  line-height: 0.68;
  color: rgba(6, 34, 74, 0.045);
  transform: translateY(-48%);
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  display: none;
}
 
.stQuote__all {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  float: right;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-900, var(--navy-900));
  transition: color 0.35s var(--ease);
}

.stQuote__all .arrowIcon {
  width: 1.2rem;
  height: 1.2rem;
  transition: transform 0.35s var(--ease);
}

.stQuote__all:hover {
  color: var(--gold-500);
}

.stQuote__all:hover .arrowIcon {
  transform: translateX(4px);
}

/* The whole block is keyed on the story index, so React replaces it and this
   fade runs from the start on every change. */
.stQuote__body {
  clear: both;
  animation: stFade 0.7s var(--ease) both;
}

@keyframes stFade {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.stQuote__quote {
  margin: clamp(1.25rem, 3vw, 2.25rem) 0 0;
  font-size:30px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--navy-900);
  margin-bottom: 20px;
}

.stQuote__text {
 position: relative;
    color: #12121d;
    max-width: 46ch;
    line-height: 1.3;
}

.stQuote__by {
  display: flex;
  align-items: center;
  gap: clamp(0.75rem, 1.6vw, 1.1rem);
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.stQuote__avatar {
  display: grid;
  place-items: center;
  overflow: hidden;
  flex: none;
  width: clamp(48px, 4vw, 62px);
  height: clamp(48px, 4vw, 62px);
  background: var(--paper-blue);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--navy-500);
}

.stQuote__avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stQuote__by strong {
    display: block;
    font-family: var(--font-body);
    font-weight: 800;
    font-size: 25px;
    color: #0f3d6a;
    line-height: 1;
}

.stQuote__by em {
     font-weight: 500;
    font-style: normal;
    font-size: 16px;
    letter-spacing: 0;
    text-transform: uppercase;
    color: #1c1414;
}


/* ---- Video tile ---- */
.stVideo {
  position: relative;
  overflow: hidden;
  width: clamp(200px, 20vw, 345px);
  margin: 0;
  aspect-ratio: 6 / 5;
  background: var(--paper-blue);
  cursor: pointer;
}

.stVideo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.8s var(--ease);
}

.stVideo:hover img {
  transform: scale(1.05);
}

.stVideo .storyVideo__play {
  right: 50%;
  bottom: 50%;
  transform: translate(50%, 50%);
}

.stVideo:hover .storyVideo__play {
  transform: translate(50%, 50%) scale(1.08);
}

.pi.singleImg { background: #fff;}
.singleImg .pi__render {  margin: 235px 0 0; }


/* =========================================================================
   Responsive
   ========================================================================= */

@media (max-width: 1100px) {
  /* Four amenity columns will not fit; two of two keeps the ruled lists
     readable rather than squeezing them to a couple of words a line. */

  .cn .cn__body {  grid-template-columns: 0;}
    .piCount__sep {  left: -21px;  top: -18px;}
}

@media (max-width: 900px) {
  .spTab__name { font-size: 24px;  }
  .spTab__kind { font-size: 15px;}
  .singleImg .pi__render {
    margin: 59px 0 0;
}
  /* The three-up meta row and the render/figures split both stack. */
  .pi__meta,
  .pi__body2,
  .pi__strip {
    grid-template-columns: minmax(0, 1fr);
  }

  .pi__strip {
    gap: 0;
  }

  /* Stacked, so the divider moves from the left edge to the top one. */
  .piCell + .piCell {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-top: clamp(1rem, 2.5vw, 1.5rem);
  }

  .piCell {
    padding-inline: 0;
    padding-bottom: clamp(1rem, 2.5vw, 1.5rem);
  }

  /* Stacked, so the figures no longer keep to the render's right half. */
  .pi__specs {
    grid-column: 1;
  }

  /* Too narrow for copy over the render — it would land on the buildings
     rather than the sky, so the two go back to stacking, render last. */
  .pi__stage {
    display: block;
  }

  .pi__render {
    margin-top: clamp(1.5rem, 4vw, 2.5rem);
  }

  .sp__body,
  .emi__inner,
  .emi__panel,
  .cn__body,
  .sg__body {
    grid-template-columns: minmax(0, 1fr);
  }

  /* One column: the aerial no longer has a half to itself, so the list takes
     the full width and the reserved height goes with it. */
  .cn__body {
    min-height: 0;
  }

  .cn__panel {
    grid-column: 2;
  }

   .Twocol .cn__panel {
    grid-column: 2;
  }
  .cn .cn__body {  grid-template-columns: 0;}
  .Twocol .cn__places {
    grid-template-columns: repeat(1, minmax(0, 1fr));}
  .cn__places{padding: 0;}


  .emi__title {
    text-align: center;
  }

  /* Horizontal on a narrow screen: a vertical rail of dates would push the
     photograph right off the fold. */
  .sp__rail,
  .sg__rail {
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    flex-direction: row;
    overflow-x: auto;
    border-left: 0;
    padding-bottom: 0.5rem;
  }

  /* The gold rule follows the rail: along the bottom once it lies flat. */
  .sp__rail {
    padding-right: 0;
  }

  .sp__rail::after {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    height: 2px;
  }

  .spTab {
    text-align: left;
  }

  .spTab.is-active {
    margin-right: 0;
    padding-right: clamp(0.75rem, 1.6vw, 1.1rem);
  }

  /* Drawing over its schedule — side by side leaves the plan unreadable. */
  .sp__panel {
    grid-template-columns: minmax(0, 1fr);
  }

  /* A vertical rail of dates would push the photograph off the fold, so the
     months become a scrolling row of chips above it. */
  .sg__rail {
    grid-auto-flow: column;
    grid-auto-columns: max-content;
    gap: 0.5rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
    border-right: 0;
    border-bottom: 2px solid var(--gold-500);
  }

  .sgDate {
    padding: 0.6em 1em;
    text-align: center;
    white-space: nowrap;
  }

  .specItem__body {
    grid-template-columns: minmax(0, 1fr);
  }
    .am__columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

}

@media (max-width: 620px) {

  .emi__totals {
    grid-template-columns: minmax(0, 1fr);
  }

  /* Two distance columns leave the landmark names two words a line. */
  .cn__places {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* =========================================================================
   Reduced motion
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  .pdHero__media img,
  .pdCue,
  .pi__render img,
  .am__watermark,
  .spec__watermark,
  .specItem.is-open .specItem__defs > div,
  .specItem.is-open .specItem__points li,
  .specItem.is-open .specItem__media,
  .cnPlace,
  .cn__panel,
  .stQuote__body,
  .sp__panel,
  .sp__plan img,
  .sp__facts > div,
  .spCompass,
  .sg__media {
    animation: none;
  }

  /* The plan slider jumps to the selected unit rather than travelling to it.
     The panels still change, so nothing becomes unreachable — only the motion
     between them is dropped. */
  .sp__track,
  .sp__panel.is-off,
  .sp__navRule::after {
    transition: none;
  }

  /* The viewer still opens and still zooms — only the travel is dropped. */
  .pv,
  .pv__body {
    animation: none;
  }

  .pv__img {
    transition: none;
  }

  .pdHero__media img,
  .pgTile img,
  .cnCard:hover {
    transform: none;
  }

  .emiDonut__arc,
  .stVideo img,
  .cnCard,
  .cnCard__media,
  .cnCard__media img,
  .cnCard__eyebrow {
    transition: none;
  }
}

@media (max-width: 1680px) { 

.cn__placeName {
     font-size: 40px;
}
.pi__figs.pi__figs--top .piFig .piFig__value {
    font-size: 110px;
}
.piFig__value {  font-size: 50px;}
.piBlock {  font-size: 18px;}
.pi__render img {  padding-top: 60px; }
.passport__watermark {  top: 3%;  font-size: 160px;}
.pdHero__title { font-size: 65px;}
.emi__blurb {  font-size: 18px;}
.specItem__title {  font-size: 30px;}
.piLink__text small {  font-size: 14px;}
.cn { padding-top: 70px;}
.specItem__points li {  font-size: 17px; }
.cn .cn__body { min-height:490px;}
.cnPlace {  padding: 0 0 6px 47px;  background-size: 34px;}
 .cnPlace__distance {  font-size: 34px;}
 .cnCard__label{font-size: 34px;}
 .pr__table thead th {   font-size: 18px;}

}
@media (max-width: 1480px) { 
  .pdHero__title { font-size: 60px;}
 .pdHero__title{font-size: 68px;}
 .piBlock {  font-size: 16px;  }
 .piLink__text small { font-size: 14px; }
 .piPlace__name {  font-size: 36px; }
.piPrice__value {   font-size: 82px; }
.spTab__name {  font-size: 30px;}
.cnPlace__name {  font-size: 14px;}
.cnCard__label{  font-size: 35px;}
.pgTile{ width: 540px;}
.stQuote__quote{font-size: 25px;}
.pr__table thead th {  font-size: 17px;}
.pr__table tbody td {  font-size: 15px;}
.btn {  font-size: 14px;}
}

@media (max-width: 1380px) { 
   .pi__figs.pi__figs--top .piFig .piFig__value {
        font-size: 88px;
    }
        .piFig__value {
        font-size: 43px;
    }
    .piFig__label, .piFig__unit {
    font-size: 14px;}
    .piCount__value {  font-size: 50px;}
  }


@media (max-width: 1200px) { 
  .specItem__points li {  font-size: 15px; }
  .singleImg .pi__render {
    margin: 318px 0 0;
}
  .cn__backdrop img {
     opacity: 0.1;
}
.cn__places {
     padding: 0;
}
.pi__render img {
        padding-top: 269px;
    }
   .singleImg .pi__render img {
        padding-top: 50px;
    }
        .piPrice__value {
        font-size: 68px;
    }
    .piCount__value {  font-size: 46px;}
    .piLink__text small {
        font-size: 12px;
    }
    .specItem__title {  font-size: 30px;}
    .specItem__defs > div {  padding-left: 50px; }
    .specItem__defs dt {  font-size: 22px;} 
    .specItem__defs dd {    font-size: 15px; }
    .cn .cn__body { padding-top: 51px; }
    
  }

@media (max-width: 1000px) { 
 .cn{padding-bottom: 0;}
  .cn__rail{position: absolute; bottom: 0;}
     .cn__places {  display: flex; }
  .pi {  background: #fff;}
   .pi__lede { font-size: 45px;}
   .pdHero__title {     font-size: 35px;  }
   .singleImg .pi__render {
        margin: 903px 0 0;
        width: 100%;
    }
    .header__nav {
    gap: 4px;
}
    .zero__track{gap: 20px;}
  .specItem__points {  padding-left: 0;}
 .pr__table {
    display: block;
    width: 100%;
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
  }
  .emi__copy {
    text-align: center;
}
.emi__blurb {
    max-width: 100%;}
 
    .pi__render img {  margin: -563px 0 0; }


     .eternityIntro .pi__render {   width: 100%;  }
   .eternityIntro .pi__render img {  margin: 0; }
  }


  @media (max-width: 900px) { 
       .singleImg .pi__render {
        margin: 62px 0 0;  width: 197%;
    }
        .pi__render img {
        margin: -150px 0 0;
    }
   .pi__render img {
        padding-top: 0;
    }
    .specItem__title {
        font-size: 22px;
    }
    /* Two amenity columns on phones, flowed rather than gridded.

       As a grid the four data columns wrapped to two rows, and the row height
       is the tallest column in it — which left a tall blank under the shorter
       one before the next pair started (and `.amCol`, being a grid itself,
       stretched its own rows to fill that height). Multi-column layout has no
       rows: the groups simply flow on into the next column, so the two
       columns stay level and there is no gap to explain. `break-inside`
       keeps a group's heading with its list. */
    .am__columns {
      display: block;
      column-count: 2;
      column-gap: 1rem;
    }

    .amCol {
      display: block;
    }

    .amGroup {
      /* inline-block + full width is what stops Safari splitting a group
         across the column break. */
      display: inline-block;
      width: 100%;
      margin-bottom: 1.25rem;
      page-break-inside: avoid;
      break-inside: avoid;
      -webkit-column-break-inside: avoid;
    }
    .specItem__defs dt {   font-size: 18px;  }
    .cn__backdrop img {  opacity: 0.1; }
    .cn .cn__body {  grid-template-columns: inherit;}
    .cnPlace { padding: 0 0 6px 38px;   background-size: 30px;  grid-template-columns: inherit; }
    .cnPlace__distance{   font-size: 32px;  }
.cn .pdHeading { text-align: left; }
.cn .cn__place { justify-content: flex-start;} 
.cn .cn__body {   padding-top: 0;  }
.qband {  padding: 40px 0 60px; }
.pr__note {   font-size: 9px;}
.maskUp[data-reveal] {  margin: 0 0 20px;  }
.pr__table thead th { font-size: 15px;}
.pr__table tbody td {  font-size: 13px;} 
      .piCount__sep {  left: -17px;   top: -18px;}
   .piCount__value {  font-size: 40px; }
   .pgTile{width: 300px;}
   .pdHero {  min-height: 70svh;}
   .spTab__name { font-size: 25px; }
   
  }

  @media (max-width: 500px) { 
    
        .pTab {  font-size: 30px;  }
    .cn__rail {
     -webkit-mask-image: inherit;  
     mask-image: inherit; 
}
  .cn__links a {   font-size: 11px; }
.cn__links button {  font-size: 11px; }
.spTab {  width: 286px;   max-width: 250px; }
    .piFig__value {   font-size: 30px;  }
    .piBlock { font-size: 13px;  }
        .pi__figs.pi__figs--top .piFig .piFig__value { font-size: 65px;  }
            .piFig__label, .piFig__unit {      font-size: 12px;  }
            .pi__body {   max-width: 100%; }
            .pi__blocks {  grid-template-columns: repeat(1, minmax(0, 1fr));}
                .singleImg .pi__render {   width: 240%;  }
                .pdHero {  min-height: 100svh; }
                   .emi .maskUp[data-reveal] {  margin: 0;  }
                   .stQuote__quote {   font-size: 18px; }
                   .stQuote__by em { font-size: 13px;}
                   .stQuote__by strong {  font-size: 22px;}
  .faq__title span {  display: inline-block;   padding-right: 9px; }
  .sg__pdf{padding: 8px 18px;}
  }
/* ---- Connectivity distances: horizontal scroll on phones ----------------
   The two markup columns flatten (display: contents) so every place becomes
   one swipeable item, laid out in two rows. The row bleeds to the screen edges and
   snaps item by item; the next item peeks in to show there is more. */
@media (max-width: 767px) {
  /* The body grid sizes its column to content, which would let the row grow
     to its full length instead of scrolling — pin it to the screen width. */
  .cn .cn__body {
    grid-template-columns: minmax(0, 1fr);
  }

  .cn__panel,
  .Twocol .cn__panel {
    grid-column: 1;
    min-width: 0;
  }

  /* Two rows that fill column by column, so the row scrolls sideways
     with places stacked in pairs. */
  .cn__places,
  .Twocol .cn__places {
    display: grid;
    grid-auto-flow: column;
    grid-template-rows: repeat(2, auto);
    grid-template-columns: none;
    grid-auto-columns: min(72vw, 260px);
    align-items: start;
    grid-gap: 18px 14px;
    gap: 18px 14px;
    margin-inline: calc(-1 * var(--gutter));
    padding: 4px var(--gutter) 10px;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
  }

  .cn__places::-webkit-scrollbar {
    display: none;
  }

  .cn__column,
  .cn__columnList {
    display: contents;
  }

  .cnPlace {
    min-width: 0;
    scroll-snap-align: start;
  }
}

/* --- Lockup leads the intro band on phones -------------------------------
   Every project, not just Eternity: the mark sits at the head of the band and
   the meta row's copy of it is switched off, so it is only ever drawn once.
   The meta row keeps its place and price. */
@media (max-width: 767px) {
  .pi .piLockup--mobile {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: clamp(1rem, 4vw, 1.75rem);
  }

  .pi .piLockup--mobile .lockup--art {
    width: min(62vw, 260px);
  }

  .pi .pi__meta .piLockup:not(.piLockup--mobile) {
    display: none;
  }
}

/* ---- Connectivity: category accordion on phones -------------------------
   Above 767px the marquee rail and its two-column panel are the section, and
   the accordion is off. Below it the pair swaps: the rail (a sideways drag on
   a phone) and the panel are hidden, and every category is an expandable row
   instead, one open at a time. */
.cnAcc {
  display: none;
}

@media (max-width: 767px) {
  .cn .cn__body,
  .cn .cn__rail {
    display: none;
  }

  .cnAcc {
    display: block;
    margin-top: clamp(1.25rem, 5vw, 2rem);
    padding-bottom: clamp(1.5rem, 6vw, 2.5rem);
    border-top: 1px solid rgba(255, 255, 255, 0.18);
  }

  .cnAcc__item {
    border-bottom: 1px solid rgba(255, 255, 255, 0.18);
  }

  .cnAcc__title {
    margin: 0;
  }

  .cnAcc__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: 16px 2px;
    background: none;
    border: 0;
    cursor: pointer;
    text-align: left;
    color: #fff;
  }

  .cnAcc__label {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
  }

  /* Plus that becomes a minus — the vertical bar is the pseudo-element, so
     the rule needs no second element in the markup. */
  .cnAcc__icon {
    position: relative;
    flex: none;
    width: 14px;
    height: 14px;
  }

  .cnAcc__icon::before,
  .cnAcc__icon::after {
    content: "";
    position: absolute;
    inset: 50% 0 auto 0;
    height: 1.5px;
    background: var(--gold-500);
    transform: translateY(-50%);
    transition: transform 0.3s var(--ease, ease), opacity 0.3s ease;
  }

  .cnAcc__icon::after {
    transform: translateY(-50%) rotate(90deg);
  }

  .cnAcc__item.is-open .cnAcc__icon::after {
    transform: translateY(-50%) rotate(0deg);
    opacity: 0;
  }

  /* 0fr -> 1fr animates the height without measuring the content. */
  .cnAcc__panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.35s var(--ease, ease);
  }

  .cnAcc__item.is-open .cnAcc__panel {
    grid-template-rows: 1fr;
  }

  .cnAcc__panelInner {
    overflow: hidden;
  }

  .cnAcc__places {
    display: grid;
    grid-gap: 14px;
    gap: 14px;
    margin: 0;
    padding: 2px 0 20px;
    list-style: none;
  }

  /* The row keeps the section's pin-and-distance styling; only the stagger is
     dropped, since the rows now appear on a tap rather than on reveal. */
  .cnAcc__places .cnPlace {
    animation: none;
  }
}

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

/* ---- Space planning: prev/next arrows on the rail, phones only -----------
   Above 900px the wrapper is transparent to layout, so the rail is still the
   grid item beside the stage and the arrows are off. At 900px and under the
   rail lies flat and scrolls sideways, and the wrapper becomes the row:
   arrow, rail, arrow. */
.sp__railNav {
  display: contents;
}

.sp__railArrow {
  display: none;
}

@media (max-width: 900px) {
  .sp__railNav {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .sp__railNav .sp__rail {
    flex: 1 1 auto;
    min-width: 0;
    scrollbar-width: none;
  }

  .sp__railNav .sp__rail::-webkit-scrollbar {
    display: none;
  }

  .sp__railArrow {
    display: grid;
    place-items: center;
    flex: none;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1px solid var(--gold-500);
    border-radius: 50%;
    background: none;
    color: var(--navy-500);
    cursor: pointer;
    transition: opacity 0.25s var(--ease);
  }

  /* Chevron drawn from two borders — no icon file. */
  .sp__railArrow span {
    width: 8px;
    height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
  }

  .sp__railArrow--prev span {
    transform: rotate(135deg);
    margin-left: 2px;
  }

  .sp__railArrow--next span {
    transform: rotate(-45deg);
    margin-right: 2px;
  }

  .sp__railArrow:disabled {
    opacity: 0.3;
    cursor: default;
  }
  .stQuote {
    display: none;
}
.st__track{top:0;}
}


/* =========================================================================
   Pricing table on phones — stacked, never sideways
   ------------------------------------------------------------------------
   Four columns of "1714 Sq.ft. to 1720 Sq.ft." cannot share a 360px line, so
   below 640px each row becomes its own block: the unit type is the row's
   heading and every cell prints its column name from data-label. Last in the
   file so it wins over the earlier per-breakpoint .pr__table tweaks.
   ========================================================================= */

@media (max-width: 640px) {
  .eternityIntro .pi__render img {
        margin: -80px 0 0;
    }
  .pr__card {
    overflow: hidden;
  }

  .pr__scroll {
    overflow: visible;
  }

  /* Unpick the desktop table box and the ≤1000px scroller. */
  .pr__table,
  .pr__table thead,
  .pr__table tbody,
  .pr__table tr,
  .pr__table th,
  .pr__table td {
    display: block;
    width: auto;
    max-width: 100%;
    overflow-x: visible;
    white-space: normal;
    overflow-wrap: anywhere;
  }

  /* --pr-pad also drives the first/last cell inset, so it stays at the card
     gutter rather than 0 — otherwise long prices sit on the border. */
  .pr__table {
    --pr-pad: 16px;
    font-size: 14px;
  }

  /* Column names move into the cells, so the gold header row is redundant. */
  .pr__table thead {
    display: none;
  }

  .pr__table tbody tr,
  .pr__table tbody tr + tr {
    padding-bottom: 12px;
    background-image: none;
    background-color: transparent;
  }

  .pr__table tbody tr + tr {
    border-top: 1px solid rgba(12, 58, 108, 0.12);
  }

  /* The unit type heads its own card. */
  .pr__table tbody th[scope="row"] {
    padding: 14px 16px 10px;
    font-size: 16px;
    font-weight: 700;
    color: #513301;
  background: rgba(248, 166, 25, 0.8);
  }

  .pr__table tbody td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    padding: 7px 16px;
    font-size: 13px;
    font-weight: 600;
    text-align: right;
  }

  .pr__table tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    max-width: 46%;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    line-height: 1.5;
    text-align: left;
    text-transform: uppercase;
    color: var(--ink-500);
  }

  /* No pointer on a phone, and the card's closing band is dead space here. */
  .pr__table tbody tr:hover {
    background-color: transparent;
  }

  .pr__card::after {
    display: none;
  }
    .cn__placeName {
        font-size: 26px;  }
.pi__lede {  font-size: 35px; line-height: 1;  }
.pr__blurb {  text-align: justify; }
.sg__caption {   font-size: 13px;}
.qband__inner h2.display {  margin: 0; }
.zero__track{gap:0;}
}

@media (max-width: 380px) {
.amGroup__title {  font-size: 11px;}
.amGroup__list li {  font-size: 11px;}
}

