/* ==========================================================================
   Harmony Apartments - everything below the hero, and every interior page.

   main.css owns the hero and the bar and is left alone. This file carries the
   page furniture: the header, the sections, the carousel, the calendar, the
   footer. Both are loaded on the front page; interior pages load this one and
   a short head of main.css by way of the shared custom properties.

   Rules:
     - one chevron, used everywhere
     - depth, not outlines. Rounded corners and a navy-tinted shadow carry the
       separation; borders and rules are used sparingly, because a page full
       of hairlines cutting through words reads as a spreadsheet
     - three shadow steps, --lift-1 to --lift-3, and no others
     - orange is the 10. It appears once or twice a screen, never as a field
     - main.css still owns the hero and the bar and is left alone
   ========================================================================== */

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

:root{
  --white:#ffffff;
  --navy:#263377;
  --navy-deep:#1b2559;
  --orange:#ff831d;
  --ink:#070b1c;
  --paper:#fbfaf8;          /* the quiet ground - fractionally off white */
  --cream:#f6f4ef;
  --sand:#e9e3d8;
  /* the grey of the Sanderson Shore Birds paper the apartments are hung in;
     the birds themselves are drawn in .sec--shore, very lightly */
  --shore:#e6e7ea;
  --mist:#dde2f0;

  --f-display:"Gill Sans","Gill Sans MT","Gill Sans Nova","GillSans",
              "Montserrat",Calibri,"Trebuchet MS",sans-serif;
  --f-ui:"Montserrat","Gill Sans","Gill Sans MT",-apple-system,"Segoe UI",sans-serif;

  --bar-h:66px;
  --rule:#ffffff;
  --gut:clamp(22px,6vw,72px);
  --stack:clamp(64px,10vh,132px);

  /* ---------------------------------------------------------------------
     Spacing. Nine steps, and nothing picks a number outside them.

       small element gap     s2-s3
       component gap         s4-s5
       gap inside a section  s6-s7
       one section to next   s8-s9, which is what --stack clamps between

     A page does not get 150px of empty space because a grid did not fill
     its last row. If a section looks empty the composition is wrong, not
     the padding. */
  --s1:8px;   --s2:12px;  --s3:16px;
  --s4:24px;  --s5:32px;  --s6:48px;
  --s7:64px;  --s8:96px;  --s9:128px;

  /* Three widths, and no page invents a fourth.
       page    the standard container, used by every section and the nav
       media   a wide photographic composition
       read    a column of prose */
  /* rem is 16px here: body sets 17px in absolute units so that the page has
     a floor, but every rem in this file still resolves against 16. Body copy
     is therefore 1.06-1.08rem, which lands at 17-17.3px - the middle of the
     range the brief asks for - and not 1rem, which lands at 16. */
  --w-page:1420px;
  --w-media:1680px;
  --w-read:66ch;

  /* Radius by object type, not by taste. A rounded rectangle is not what
     makes something feel expensive; knowing which things are objects and
     which things are environment is.

       env     an environment is not a card. Full bleed, square.
       media   a small photograph inside a composition.
       float   a large photograph that is genuinely floating.
       lens    a control surface over a photograph.
       pill    a control.

     Sections, legal text, article blocks and amenity groups are not
     rounded. They are not objects. */
  --r-env:0;
  --r-media:16px;
  --r-float:26px;
  --r-lens:20px;
  --r-pill:999px;

  /* the older names, kept so nothing has to be renamed twice */
  --r:var(--r-media);
  --r-lg:var(--r-float);

  /* ---------------------------------------------------------------------
     Three elevations, and nothing sits at one of them because a shadow
     looked nice.

       0  environment  full-bleed photography, page grounds. No shadow.
       1  content      an active photograph, an editorial composition.
                       Separated by geometry - size, position, crop - with
                       only enough shadow to sit off the ground.
       2  controls     navigation, carousel arrows, the booking bar, the
                       panel floating over the location photograph. This is
                       the only layer that gets translucent material.

     Depth comes from geometry first. If something needs a heavy shadow to
     read as raised, it is at the wrong layer or the wrong size. */
  --e0:none;
  --e1:0 2px 8px rgba(16,24,64,.05), 0 18px 40px -26px rgba(16,24,64,.22);
  --e2:0 1px 2px rgba(16,24,64,.06), 0 12px 34px -14px rgba(16,24,64,.30);

  /* Layer 2 material - a control surface, never a content surface */
  --mat-light:rgba(255,255,255,.72);
  --mat-dark:rgba(18,28,74,.44);
  --mat-blur:blur(16px) saturate(160%);

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-drop:cubic-bezier(.19,1,.22,1);

  /* ---------------------------------------------------------------------
     Three motion strengths. Every animation on the site is one of them, so
     nobody has to invent a duration and a curve from scratch.

       calm        text arriving, a small fade. 8-15px of travel.
       spatial     a carousel plane, an image scaling, a depth change.
       structural  the hero handing over to the header, a whole section.

     One spring, --e-spring, used by everything that has mass. It
     decelerates hard and comes to rest without bouncing, which is what
     makes a carousel read as weight rather than as an animation preset.
     Nothing on the site has different physics from anything else. */
  --m-calm:340ms;
  --m-calm-move:12px;
  --m-spatial:620ms;
  --m-structural:820ms;

  --e-out:cubic-bezier(.22,.61,.36,1);
  --e-spring:cubic-bezier(.16,.84,.24,1);

  /* the older names, kept so nothing has to be renamed twice */
  --t-fast:200ms;
  --t-base:var(--m-calm);
  --t-settle:var(--m-spatial);
  --t-slow:var(--m-structural);
  --e-settle:var(--e-spring);
}

@media (max-width:760px){ :root{ --bar-h:60px; } }

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

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

body{
  margin:0;
  font-family:var(--f-ui);
  font-size:17px;
  color:var(--navy);
  background:var(--cream);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img{ display:block; max-width:100%; }
.sprite{ position:absolute; width:0; height:0; overflow:hidden; }
::selection{ background:var(--orange); color:#fff; }
:focus-visible{ outline:2px solid var(--orange); outline-offset:4px; }

a{ color:inherit; }

/* On the front page this file loads after main.css, so its body colour wins
   and the hero and the bar lose their white. Give it back to them here rather
   than reorder the two - main.css has to stay last for the hero to work. */
.hero,
.hero .tbtn,
.hero .drop__link,
.hero .tbtn--drop,
.bar,
.bar .tbtn{ color:var(--white); }


/* ==========================================================================
   Text buttons - the hero's, carried through
   ========================================================================== */

.tbtn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:.55em;
  padding:.45em 0;
  font-family:var(--f-ui);
  font-size:.88rem;
  font-weight:500;
  letter-spacing:.19em;
  text-transform:uppercase;
  text-decoration:none;
  color:currentColor;
  white-space:nowrap;
  background:none; border:0; cursor:pointer;
  transition:transform .35s var(--ease);
}
.tbtn:hover,.tbtn:focus-visible{ transform:translateY(-2px); }
.tbtn__chev{ width:.72em; height:.72em; transition:transform .35s var(--ease); }


/* ==========================================================================
   Boxed buttons - square, 2px, filled on hover. Two words, never a sentence.
   ========================================================================== */

.btn{
  display:inline-flex;
  align-items:center;
  gap:.7em;
  padding:1.05em 1.9em;
  border:1px solid currentColor;
  border-radius:var(--r-pill);
  background:none;
  font-family:var(--f-ui);
  font-size:.86rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  text-decoration:none;
  color:var(--navy);
  cursor:pointer;
  transition:background-color .32s var(--ease), color .32s var(--ease),
             transform .32s var(--ease), box-shadow .32s var(--ease);
}
.btn svg{ width:.8em; height:.8em; transition:transform .32s var(--ease); }
.btn:hover{ background:var(--navy); color:var(--white); transform:translateY(-2px); box-shadow:var(--e1); }
.btn:hover svg{ transform:translateX(3px); }

.btn--go{
  padding:1.25em 2.3em;
  font-size:.82rem;
  border-color:transparent;
  background:var(--orange);
  color:var(--white);
  box-shadow:0 6px 20px -8px rgba(255,131,29,.7);
}
.btn--go:hover{ background:#f2760f; color:var(--white); box-shadow:0 12px 28px -10px rgba(255,131,29,.8); }

.btn--light{ color:var(--white); }
.btn--light:hover{ background:var(--white); color:var(--navy); }

.btn[disabled]{ opacity:.34; pointer-events:none; }

/* the chevron points right on a button, down in a menu */
.btn .i-right{ transform:rotate(-90deg); }
.btn:hover .i-right{ transform:rotate(-90deg) translateY(-3px); }


/* ==========================================================================
   GlobalNav

   ONE navigation. There is no second one anywhere on this site.

   Three states, and they are states of the same object - same mark, same six
   items in the same order, same action, same 66px, same type:

     rail     the front page at rest. The same element carries .bar, so
              main.css goes on positioning it against the hero's bottom edge
              and main.js goes on moving it. Only the mark is held back,
              because the hero has the wordmark in the middle of the screen
              at that moment and putting it twice is the duplication this
              whole pass is about.
     overlay  --dock 0 on an interior page. Dark glass over the photograph.
     docked   --dock 1. Navy glass, the 2px rule underneath.

   --dock is a number from 0 to 1 driven by scroll, on the front page by
   main.js and everywhere else by site.js, using the same ramp. That is why
   the front page resolves into exactly the header the rest of the site opens
   with rather than into something that merely resembles it.

   Enquire is the button and only the button. A text link beside it saying
   the same word is not hierarchy.

   The mark is the way home, so there is no Home item.
   ========================================================================== */

.gnav{
  position:fixed;
  top:0; left:0; right:0;
  z-index:70;
  height:var(--bar-h);
  display:flex;
  align-items:center;
  color:var(--white);

  /* the same glass as the front page's bar, from the same formula. It is
     on the bar itself: a child layer with the filter does not sample the
     page - see .gnav__sheet for why, and for where the phone menu lives. */
  --dock:0;
  background:rgba(14,24,78,calc(.10 + .46 * var(--dock)));
  -webkit-backdrop-filter:blur(5px) saturate(102%) brightness(calc(.58 - .28 * var(--dock)));
  backdrop-filter:blur(5px) saturate(102%) brightness(calc(.58 - .28 * var(--dock)));
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .gnav{ background:rgba(14,24,78,calc(.62 + .24 * var(--dock))); }
}

/* A page with no photograph behind the nav is docked from the first paint
   rather than one frame later, and a page with no script is docked full
   stop - there is nothing to fade it in. */
body:has(.mast) .gnav{ --dock:1; }
html:not(.js) .gnav{ --dock:1; }

/* the rule under it belongs to the docked state, so it arrives with it */
.gnav::after{
  content:"";
  position:absolute; left:0; right:0; bottom:0;
  height:2px;
  background:var(--rule);
  opacity:var(--dock);
}

.gnav__inner{
  width:100%;
  max-width:var(--w-page);
  margin:0 auto;
  padding:0 var(--gut);
  display:grid;
  /* Four columns, named explicitly rather than left to auto-placement: below
     1080px the nav panel becomes position:absolute, and an absolutely
     positioned grid item still occupies the cell it was auto-placed into.
     Saying where each one goes means the bar has the same geometry whether
     the menu is a row of links or a panel hanging off the bar. */
  grid-template-columns:auto minmax(0,1fr) auto auto;
  align-items:center;
  gap:clamp(14px,3vw,40px);
}

.gnav__mark{ grid-column:1; display:block; line-height:0; }
.gnav__mark img{ width:clamp(104px,10vw,148px); height:auto; }

/* the front page holds the mark back while the hero is showing its own */
.gnav--home .gnav__mark{ opacity:var(--dock); }

.gnav__nav{
  grid-column:2;
  display:flex;
  justify-content:center;
  gap:clamp(12px,2.2vw,32px);
}
/* The quiet state is alpha on the colour, not opacity on the element. The
   front page's hero animates .bar .tbtn's opacity as part of its entrance,
   and an animation beats a declaration no matter how specific it is - so
   using opacity here would leave the two navigations at different weights
   for no reason anybody could see in the stylesheet. */
.gnav__nav .tbtn{ font-size:.82rem; letter-spacing:.13em; padding:.7em 0; color:rgba(255,255,255,.82); }
.gnav__nav .tbtn:hover,
.gnav__nav .tbtn:focus-visible{ color:var(--white); }

/* One active treatment, everywhere: full strength and one underline. Not
   bold and scaled and coloured as well. */
.gnav__nav .tbtn[aria-current="page"]{ color:var(--white); }
.gnav__nav .tbtn[aria-current="page"]::after{
  content:"";
  position:absolute; left:0; right:0; bottom:.05em;
  height:2px; background:var(--white);
}

.gnav__cta{ grid-column:3; justify-self:end; }

.gnav__burger{
  grid-column:4;
  display:none;
  position:relative;
  z-index:2;
  width:40px; height:40px;
  padding:0; border:0; background:none;
  color:var(--white); cursor:pointer;
}
.gnav__burger span{
  display:block;
  width:22px; height:2px;
  margin:5px auto;
  background:currentColor;
  transition:transform .35s var(--ease), opacity .25s var(--ease);
}
body.menu-open .gnav__burger span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
body.menu-open .gnav__burger span:nth-child(2){ opacity:0; }
body.menu-open .gnav__burger span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }

/* the phone menu is .gnav__sheet, further down - after the bar in the page,
   not inside it */
@media (max-width:1080px){
  .gnav__burger{ display:block; }
  /* the action stays on screen - it is the one thing a phone visitor is
     most likely to want, and it is the reason the site exists */
  .gnav__cta .btn{ padding:.72em 1.15em; font-size:.72rem; letter-spacing:.14em; }
}

@media (max-width:400px){
  .gnav__mark img{ width:92px; }
  .gnav__cta .btn{ padding:.66em .95em; font-size:.66rem; gap:.5em; }
}


/* ==========================================================================
   Page hero - a band of photograph with the title sitting in it
   ========================================================================== */

.phero{
  position:relative;
  min-height:clamp(340px,50vh,560px);
  display:flex;
  align-items:flex-end;
  padding:calc(var(--bar-h) + clamp(40px,7vh,88px)) var(--gut) clamp(30px,5vh,62px);
  overflow:hidden;
  isolation:isolate;
  background:var(--ink);
  color:var(--white);
}
.phero__media{ position:absolute; inset:0; z-index:0; }
.phero__media img{
  width:100%; height:100%;
  object-fit:cover;
  animation:phero-pan 18s linear both;
}
@keyframes phero-pan{
  from{ transform:scale(1.08) translate3d(-1.2%,0,0); }
  to  { transform:scale(1.08) translate3d(1.2%,0,0); }
}
.phero__tint{
  position:absolute; inset:0; z-index:1;
  background:var(--navy); opacity:.16;
}
.phero__scrim{
  position:absolute; inset:0; z-index:1;
  /* The same navy-black family as .env__scrim--foot, and a little heavier at
     the bottom than it was: the title sits at about 55% of the band, which is
     where both halves of the old gradient had already run out. */
  background:
    linear-gradient(to bottom, rgba(7,11,28,.58) 0%, rgba(7,11,28,.12) 26%, rgba(7,11,28,0) 46%),
    linear-gradient(to top,    rgba(7,11,28,.80) 0%, rgba(7,11,28,.34) 34%, rgba(7,11,28,0) 68%);
}
.phero__inner{
  position:relative; z-index:2;
  width:100%;
  max-width:var(--w-page);
  margin:0 auto;
}

.crumb{
  margin:0 0 clamp(16px,2.6vh,26px);
  font-size:.84rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  opacity:.72;
}
.crumb a{ text-decoration:none; }
.crumb a:hover{ opacity:1; text-decoration:underline; text-underline-offset:4px; }
.crumb span{ opacity:.5; padding:0 .5em; }

.phero h1{
  margin:0;
  max-width:18ch;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.3rem,5.6vw,4.6rem);
  line-height:1;
  letter-spacing:-.012em;
  text-wrap:balance;
}
.phero__lede{
  margin:clamp(18px,2.8vh,30px) 0 0;
  max-width:52ch;
  font-family:var(--f-display);
  font-size:clamp(1.02rem,1.9vw,1.34rem);
  line-height:1.6;
  opacity:.92;
}


/* ==========================================================================
   Sections
   ========================================================================== */

.sec{ padding:var(--stack) var(--gut); }
.sec__inner{ max-width:var(--w-page); margin:0 auto; }
.sec--tight{ padding-top:clamp(40px,6vh,72px); }
.sec--navy { background:var(--navy);  color:var(--white); }
.sec--ink  { background:var(--ink);   color:var(--white); }
.sec--cream{ background:var(--cream); }
.sec--white{ background:var(--paper); }
.sec--sand { background:var(--sand);  }
.sec--mist { background:var(--mist);  }
/* The grey of the rooms' shore-bird paper, with the birds on it - drawn,
   not copied; a few percent of navy, so they are found rather than seen.
   A paper card on it is a card on a wall, not white on white. */
.sec--shore{
  background-color:var(--shore);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320' viewBox='0 0 320 320'%3E%3Cg transform='translate(52 44) rotate(-8) scale(1.15)'%3E%3Cpath d='M-10 3 Q-5 -3 0 2 Q5 -3 10 3' fill='none' stroke='%23263377' stroke-width='1' stroke-opacity='.11' stroke-linecap='round'/%3E%3C/g%3E%3Cg transform='translate(214 96) rotate(6) scale(0.85)'%3E%3Cpath d='M-10 3 Q-5 -3 0 2 Q5 -3 10 3' fill='none' stroke='%23263377' stroke-width='1' stroke-opacity='.11' stroke-linecap='round'/%3E%3C/g%3E%3Cg transform='translate(118 196) rotate(-14) scale(1.3)'%3E%3Cpath d='M-10 3 Q-5 -3 0 2 Q5 -3 10 3' fill='none' stroke='%23263377' stroke-width='1' stroke-opacity='.11' stroke-linecap='round'/%3E%3C/g%3E%3Cg transform='translate(272 262) rotate(10) scale(0.7)'%3E%3Cpath d='M-10 3 Q-5 -3 0 2 Q5 -3 10 3' fill='none' stroke='%23263377' stroke-width='1' stroke-opacity='.11' stroke-linecap='round'/%3E%3C/g%3E%3Cg transform='translate(36 290) rotate(4) scale(0.9)'%3E%3Cpath d='M-10 3 Q-5 -3 0 2 Q5 -3 10 3' fill='none' stroke='%23263377' stroke-width='1' stroke-opacity='.11' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
  background-size:320px 320px;
}
.sec--shore .rev2__card,
.sec--shore .lens{ background:var(--paper); }

/* Level C - an editorial section title. Visibly quieter than the statement
   above, or every heading shouts and none of them means anything. */
.h2{
  margin:0 0 clamp(20px,3vh,32px);
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.5rem,2.7vw,2.2rem);
  line-height:1.04;
  letter-spacing:.01em;
  max-width:20ch;
}
.h2--wide{ max-width:26ch; }

.h3{
  margin:0 0 .8em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.3rem,2.4vw,1.85rem);
  line-height:1.16;
}

.lede{
  margin:0 0 clamp(22px,3vh,34px);
  max-width:56ch;
  font-family:var(--f-display);
  font-size:clamp(1.04rem,1.8vw,1.3rem);
  line-height:1.66;
}
.prose{ max-width:var(--w-read); font-size:1.08rem; line-height:1.76; }
.prose p{ margin:0 0 1.15em; }
.prose a{ color:inherit; text-decoration:underline; text-underline-offset:3px; }
.prose a:hover{ opacity:.68; }

.sec--navy .prose a:hover,
.sec--ink .prose a:hover{ opacity:.68; }

/* a two-column band: words on the left, something on the right */
.split{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:clamp(30px,5vw,88px);
  align-items:start;
}
.split--even{ grid-template-columns:1fr 1fr; }
@media (max-width:900px){ .split,.split--even{ grid-template-columns:1fr; } }


/* ==========================================================================
   Reveal - the hero's settle curve, applied down the page
   ========================================================================== */

.rv{
  opacity:0;
  transform:translateY(26px);
  transition:opacity .8s var(--ease-drop), transform .8s var(--ease-drop);
}
.rv.is-in{ opacity:1; transform:none; }
.rv--d1{ transition-delay:.09s; }
.rv--d2{ transition-delay:.18s; }
.rv--d3{ transition-delay:.27s; }
.rv--d4{ transition-delay:.36s; }

html:not(.js) .rv{ opacity:1; transform:none; }

/* ==========================================================================
   THE FIVE MOTIFS

   Harmony is SEASIDE SPATIAL EDITORIAL. Every public page is assembled from
   five things and no others. A page uses two or three of them; no page uses
   all five; and a sixth is not invented because a route felt repetitive.

     A  ENVIRONMENT      .env      full-bleed photograph, words floating in it
     B  DEPTH            .car[data-variant="depth"]
     C  EDITORIAL RAIL   .car[data-variant="editorial"]
     D  FLOATING LENS    .lens     a small control surface over a photograph
     E  EDITORIAL FIELD  .field    paper, type, alignment, no card

   B and C are the carousel engine's two presentation variants and are
   already defined further down this file; they are listed here so the five
   are in one place. Nothing that browses sideways is built any other way.

   Where the site's older component names map onto the motifs:

     .phero .close .place          ->  A environment
     #aptCar  .car--places          ->  B depth
     the building rail, room rails  ->  C editorial rail
     .place__card .cal .glance      ->  D floating lens
     .kitg .cmp .peers .rows        ->  E editorial field

   The rule that keeps this honest: translucent material (--mat-light /
   --mat-dark / --mat-blur) belongs to D and to carousel controls. Nowhere
   else. A paragraph does not need frosted glass behind it.
   ========================================================================== */


/* --- A. ENVIRONMENT ------------------------------------------------------ */

.env{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  border-radius:var(--r-env);
  background:var(--ink);
  color:var(--white);
}
.env__media{ position:absolute; inset:0; z-index:0; }
.env__media img{ width:100%; height:100%; object-fit:cover; }

/* One scrim family, navy-black, never a generic grey. Two directions, and
   they are additive so a section can use either or both. */
.env__scrim{
  position:absolute; inset:0; z-index:1;
  pointer-events:none;
  background:
    linear-gradient(to right, rgba(7,11,28,.80) 0%, rgba(7,11,28,.42) 46%, rgba(7,11,28,.06) 78%),
    linear-gradient(to top,   rgba(7,11,28,.46) 0%, rgba(7,11,28,0) 42%);
}
.env__scrim--foot{
  background:linear-gradient(to top, rgba(7,11,28,.80) 0%, rgba(7,11,28,.26) 34%, rgba(7,11,28,0) 64%);
}
.env__inner{
  position:relative; z-index:2;
  width:100%;
  max-width:var(--w-page);
  margin:0 auto;
}


/* --- D. FLOATING LENS ---------------------------------------------------- */
/* The only place translucent material is allowed. It is a control surface -
   a panel of facts over a photograph, a map legend, a date picker - and it
   is never wrapped around an ordinary paragraph. */

.lens{
  border-radius:var(--r-lens);
  background:var(--mat-light);
  -webkit-backdrop-filter:var(--mat-blur);
  backdrop-filter:var(--mat-blur);
  border:1px solid rgba(255,255,255,.55);
  box-shadow:var(--e2);
  padding:clamp(22px,3vw,38px);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .lens{ background:rgba(255,255,255,.93); }
}
.lens--dark{
  background:var(--mat-dark);
  border-color:rgba(255,255,255,.2);
  color:var(--white);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .lens--dark{ background:rgba(18,28,74,.9); }
}


/* --- E. EDITORIAL FIELD -------------------------------------------------- */
/* Paper, type, alignment and one image intrusion where it earns it. The
   design interest is scale and offset, not a white box with a shadow. */

.field{ padding:var(--stack) var(--gut); background:var(--paper); }
.field--cream{ background:var(--cream); }
.field--navy { background:var(--navy); color:var(--white); }
.field__inner{ max-width:var(--w-page); margin:0 auto; }

/* the asymmetric head every field section opens with */
.field__head{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(20px,4vw,72px);
  align-items:end;
  margin-bottom:clamp(28px,4.6vh,56px);
}
@media (max-width:820px){ .field__head{ grid-template-columns:1fr; align-items:start; } }

.eyebrow{
  margin:0 0 1em;
  font-size:.76rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.7;
}

/* Hairline rows. Offers, the other six apartments, a guide list, a set of
   facts - the same object every time. A rule between two rows is structure;
   a border around every row is a spreadsheet. */
.rows{ margin:0; padding:0; list-style:none; }
.row{
  display:grid;
  grid-template-columns:minmax(0,14ch) minmax(0,1fr) auto;
  gap:clamp(14px,3vw,48px);
  align-items:baseline;
  padding:clamp(22px,3.4vh,38px) 0;
  border-top:1px solid rgba(38,51,119,.14);
  text-decoration:none;
  color:inherit;
}
.rows > :last-child .row,
.row:last-child{ border-bottom:1px solid rgba(38,51,119,.14); }
.field--navy .row,
.field--navy .rows > :last-child .row{ border-color:rgba(255,255,255,.16); }

.row__k{
  font-size:.76rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.7;
}
.row__t{
  margin:0 0 .45em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.32rem,2.3vw,1.9rem);
  line-height:1.1;
}
.row__d{
  margin:0;
  max-width:54ch;
  font-size:1.06rem;
  line-height:1.72;
  opacity:.76;
}
.row__go{
  display:inline-flex; align-items:center; gap:.55em;
  white-space:nowrap;
  font-size:.78rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  transition:gap var(--t-fast) var(--e-out);
}
.row__go svg{ width:.7em; height:.7em; transform:rotate(-90deg); }
a.row:hover .row__go{ gap:1em; }
a.row:hover .row__t{ text-decoration:underline; text-underline-offset:5px; }

@media (max-width:760px){
  .row{ grid-template-columns:1fr; gap:.5em; }
  .row__go{ margin-top:.6em; }
}



/* ==========================================================================
   Lists - amenities, highlights, rules
   ========================================================================== */

.cols{ columns:2; column-gap:clamp(24px,4vw,56px); }
@media (max-width:620px){ .cols{ columns:1; } }

.ticks{ margin:0; padding:0; list-style:none; }
.ticks li{
  position:relative;
  break-inside:avoid;
  padding:.5em 0 .5em 1.5em;
  font-size:.93rem;
  line-height:1.56;
}
.ticks li::before{
  content:"";
  position:absolute; left:0; top:1.02em;
  width:9px; height:2px;
  background:currentColor;
  opacity:.34;
}

.pairs{ margin:0; }
.pairs > div{
  display:grid;
  grid-template-columns:minmax(120px,.32fr) 1fr;
  gap:clamp(14px,2vw,30px);
  padding:1.05em 0;
  border-top:2px solid rgba(38,51,119,.12);
}
.pairs > div:last-child{ border-bottom:2px solid rgba(38,51,119,.12); }
.sec--navy .pairs > div{ border-color:rgba(255,255,255,.2); }
.pairs dt{
  font-size:.84rem;
  font-weight:600;
  letter-spacing:.19em;
  text-transform:uppercase;
  opacity:.78;
  padding-top:.22em;
}
.pairs dd{ margin:0; font-size:.96rem; line-height:1.6; }
@media (max-width:560px){ .pairs > div{ grid-template-columns:1fr; gap:.4em; } }


/* ==========================================================================
   The carousel

   One engine. Three ways of showing it. Nothing on this site browses
   horizontally by any other mechanism.

   THE CONTRACT - true of every variant, everywhere:

     drag          click and pull sideways
     touch         one finger, sideways
     arrows        the same two circular controls, 52px, always visible
     keyboard      Left / Right / Home / End when it has focus
     neighbours    clicking a visible one brings it to the front
     physics       one spring, --e-spring, at --m-spatial. No exceptions.
     snapping      always lands on a whole item, never between two
     pagination    03 / 07, everywhere, never dots or bars
     autoplay      none
     hover         a small answer, never the only way to understand it
     scroll        never takes the page's vertical scroll away
     cursor        grab, then grabbing
     motion        perspective and blur come off when the OS asks

   The variants change what an item looks like and where it sits. They do not
   change how any of the above behaves.

     depth       the apartments. Three planes, real perspective.
     editorial   the building. A wide frame with a tall one entering beside
                 it - a composition that changes rather than a slider.
     strip       reviews. Flat, one and a bit, no perspective at all.
   ========================================================================== */

.car{
  position:relative;
  overflow:hidden;               /* neighbours reach past the section */
}
@supports (overflow:clip){ .car{ overflow:clip; } }

.car__viewport{
  position:relative;
  touch-action:pan-y;            /* the page keeps its vertical scroll */
  cursor:grab;
}
.car__viewport:active{ cursor:grabbing; }

.car.is-dragging .car__track{ transition:none; }

.car__track{
  position:absolute; inset:0;
  will-change:transform;
  transform:translate3d(var(--car-drag,0px),0,0);
  transition:transform var(--m-spatial) var(--e-spring);
}

.car__item{
  position:absolute;
  margin:0; padding:0; border:0;
  background:none;
  text-align:left;
  color:inherit;
  cursor:pointer;
  transform-origin:50% 50%;
  backface-visibility:hidden;
  transition:transform var(--m-spatial) var(--e-spring),
             opacity var(--m-spatial) var(--e-out),
             filter var(--m-spatial) var(--e-out);
}
.car__item img{ width:100%; height:100%; object-fit:cover; pointer-events:none; }
.car__item[data-o="0"]{ z-index:6; opacity:1; }
.car__item[data-o="1"],  .car__item[data-o="-1"]{ z-index:5; }
.car__item[data-o="2"],  .car__item[data-o="-2"]{ z-index:4; }
.car__item[data-o="out"],.car__item[data-o="-out"]{ z-index:1; opacity:0; pointer-events:none; }

/* every name is in the document, so the section reads without the script */
.car__label{
  position:absolute;
  width:1px; height:1px;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
}

/* --- the words, always outside the picture ------------------------------ */

.car__meta{
  margin:clamp(26px,4vh,44px) auto 0;
  transition:opacity var(--t-fast) var(--e-out);
}
.car.is-turning .car__meta{ opacity:0; }

.car__facts{
  margin:0 0 1.5em;
  font-size:clamp(1.06rem,1.7vw,1.28rem);
  letter-spacing:.03em;
  opacity:.72;
}
.car__facts i{ font-style:normal; padding:0 .6em; opacity:.45; }

.car__go{
  display:inline-flex; align-items:center; gap:.6em;
  padding:.7em 0;
  font-size:.88rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  border-bottom:1px solid currentColor;
  transition:gap var(--t-fast) var(--e-out), opacity var(--t-fast) var(--e-out);
}
.car__go svg{ width:.72em; height:.72em; transform:rotate(-90deg); }
.car__go:hover{ gap:1em; opacity:.7; }

/* ==========================================================================
   Variant: depth - the apartments
   ========================================================================== */

.car[data-variant="depth"]{
  --dc-w:clamp(280px,62vw,980px);
  --dc-ratio:16/10;
  --dc-r:24px;
  --dc-x1:94%;    --dc-z1:-230px;  --dc-rot1:9deg;   --dc-s1:.92;  --dc-o1:.8;   --dc-b1:1.5px;
  --dc-x2:158%;   --dc-z2:-520px;  --dc-rot2:14deg;  --dc-s2:.86;  --dc-o2:.34;  --dc-b2:4px;
}
[data-variant="depth"] .car__viewport{
  height:calc(var(--dc-w) / (var(--dc-ratio)));
  perspective:1500px;
  perspective-origin:50% 50%;
}
[data-variant="depth"] .car__track{ transform-style:preserve-3d; }

[data-variant="depth"] .car__item{
  top:50%; left:50%;
  width:var(--dc-w);
  aspect-ratio:var(--dc-ratio);
  border-radius:var(--dc-r);
  overflow:hidden;
  background:var(--navy-deep);
}
/* Layer 1. The separation is the geometry - closest plane, full size,
   sharp - so the shadow only has to lift it off the ground. */
[data-variant="depth"] .car__item[data-o="0"]{
  transform:translate3d(-50%,-50%,0) scale(1) rotateY(0);
  filter:none;
  box-shadow:var(--e1);
}
[data-variant="depth"] .car__item[data-o="1"]{
  transform:translate3d(calc(-50% + var(--dc-x1)),-50%,var(--dc-z1)) scale(var(--dc-s1)) rotateY(calc(var(--dc-rot1) * -1));
  opacity:var(--dc-o1); filter:blur(var(--dc-b1)); box-shadow:none;
}
[data-variant="depth"] .car__item[data-o="-1"]{
  transform:translate3d(calc(-50% - var(--dc-x1)),-50%,var(--dc-z1)) scale(var(--dc-s1)) rotateY(var(--dc-rot1));
  opacity:var(--dc-o1); filter:blur(var(--dc-b1)); box-shadow:none;
}
[data-variant="depth"] .car__item[data-o="2"]{
  transform:translate3d(calc(-50% + var(--dc-x2)),-50%,var(--dc-z2)) scale(var(--dc-s2)) rotateY(calc(var(--dc-rot2) * -1));
  opacity:var(--dc-o2); filter:blur(var(--dc-b2));
}
[data-variant="depth"] .car__item[data-o="-2"]{
  transform:translate3d(calc(-50% - var(--dc-x2)),-50%,var(--dc-z2)) scale(var(--dc-s2)) rotateY(var(--dc-rot2));
  opacity:var(--dc-o2); filter:blur(var(--dc-b2));
}
[data-variant="depth"] .car__item[data-o="out"]{
  transform:translate3d(calc(-50% + var(--dc-x2)),-50%,var(--dc-z2)) scale(var(--dc-s2)) rotateY(calc(var(--dc-rot2) * -1));
  filter:blur(var(--dc-b2));
}
[data-variant="depth"] .car__item[data-o="-out"]{
  transform:translate3d(calc(-50% - var(--dc-x2)),-50%,var(--dc-z2)) scale(var(--dc-s2)) rotateY(var(--dc-rot2));
  filter:blur(var(--dc-b2));
}
[data-variant="depth"] .car__meta{ max-width:52ch; text-align:center; }


/* ==========================================================================
   Variants: editorial and strip

   These two move the track rather than each item. The depth variant cannot -
   its items live on separate Z planes - but everything the hand can feel is
   still identical, because the transition on the track uses the same spring
   at the same duration as the transition on a depth plane, and the drag
   feeds the same custom property in both cases.

   The step is one item plus one gap, in container units, so the arithmetic
   holds at any width without measuring anything in JavaScript.
   ========================================================================== */

[data-variant="editorial"] .car__viewport,
[data-variant="strip"] .car__viewport{
  container-type:inline-size;
  overflow:visible;
}

[data-variant="editorial"] .car__track,
[data-variant="strip"] .car__track{
  display:flex;
  align-items:stretch;
  gap:var(--car-gap);
  transform:translate3d(calc(var(--car-at,0) * -1 * var(--car-step) + var(--car-drag,0px)),0,0);
  transition:transform var(--m-spatial) var(--e-spring);
}

[data-variant="editorial"] .car__item,
[data-variant="strip"] .car__item{
  position:relative;
  flex:0 0 var(--car-item);
  width:var(--car-item);
  opacity:1;
  transform:none;
  transition:opacity var(--m-spatial) var(--e-out),
             transform var(--m-spatial) var(--e-spring),
             filter var(--m-spatial) var(--e-out);
}
/* everything but the live one steps back a little, so the front of the strip
   is unmistakable without anything being hidden */
/* Further away, not unavailable. Scale and a touch of blur do the receding;
   whitening a photograph until it looks disabled does not. */
[data-variant="editorial"] .car__item:not([data-o="0"]){
  opacity:.92;
  transform:scale(.955);
  filter:none;
}
[data-variant="strip"] .car__item:not([data-o="0"]){ opacity:.62; }
[data-variant="editorial"] .car__item:not([data-o="0"]):hover{ opacity:.92; filter:blur(0); }
[data-variant="strip"] .car__item:not([data-o="0"]):hover{ opacity:.78; }


/* --- editorial: the building -------------------------------------------- */
/* Large frames running past both edges of the section. The one in front is
   whole, the next is already coming in. */

.car[data-variant="editorial"]{
  --car-item:70cqw;
  --car-gap:1.5cqw;
  --car-step:71.5cqw;
  --ed-h:clamp(320px,58vh,620px);
}
[data-variant="editorial"] .car__viewport{ height:var(--ed-h); }
[data-variant="editorial"] .car__item{
  border-radius:var(--r-lg);
  overflow:hidden;
  background:var(--navy-deep);
  box-shadow:var(--e1);
}
[data-variant="editorial"] .car__meta{ max-width:46ch; margin-left:0; }

@media (max-width:760px){
  .car[data-variant="editorial"]{
    --car-item:84cqw; --car-gap:3cqw; --car-step:87cqw;
    --ed-h:clamp(240px,40vh,340px);      /* nearer the shape the photographs are */
  }
}


/* --- strip: reviews ------------------------------------------------------ */
/* Flat, and no perspective at all - the words are the point and turning them
   away from the reader would be silly. */

.car[data-variant="strip"]{
  --car-item:56cqw;
  --car-gap:5cqw;
  --car-step:61cqw;
}
[data-variant="strip"] .car__viewport{ height:clamp(200px,25vh,270px); }
[data-variant="strip"] .car__item{
  text-align:left;
  white-space:normal;
  align-self:start;
}
[data-variant="strip"] .car__q{
  margin:0 0 1.2em;
  font-family:var(--f-display);
  font-size:clamp(1.14rem,2vw,1.5rem);
  line-height:1.6;
}
[data-variant="strip"] .car__who{
  margin:0;
  font-size:.88rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  opacity:.7;
}

@media (max-width:760px){
  .car[data-variant="strip"]{ --car-item:86cqw; --car-gap:4cqw; --car-step:90cqw; }
}


/* ==========================================================================
   Smaller: the interaction gets simpler, not smaller
   ========================================================================== */

@media (max-width:900px){
  .car[data-variant="depth"]{
    --dc-w:min(86vw,520px);
    --dc-ratio:4/3;
    --dc-r:20px;
    --dc-x1:80%;  --dc-z1:-120px;  --dc-rot1:5deg;  --dc-s1:.92;  --dc-o1:.55;  --dc-b1:0px;
    --dc-x2:130%; --dc-z2:-260px;  --dc-rot2:7deg;  --dc-s2:.86;  --dc-o2:0;    --dc-b2:0px;
  }
  [data-variant="depth"] .car__item[data-o="0"]{ box-shadow:var(--e1); }
}

/* --- no script: it unstacks, and everything is still there -------------- */

html:not(.js) .car__viewport{ height:auto; perspective:none; cursor:auto; }
html:not(.js) .car__track{ position:static; display:grid; gap:clamp(14px,2vw,24px); }
html:not(.js) .car__item{
  position:static;
  width:100%;
  opacity:1;
  filter:none;
  transform:none;
  box-shadow:var(--e1);
}
html:not(.js) .car__label{ position:static; width:auto; height:auto; clip-path:none; padding:.9em 0 0; }


/* ==========================================================================
   The quiet section

   Negative space is the technique. No card, no photograph, no movement other
   than the words arriving. It exists to let the page breathe between two
   loud things, and it only works if it is genuinely empty.
   ========================================================================== */

.quiet{
  background:var(--paper);
  padding:clamp(88px,15vh,180px) var(--gut) clamp(52px,8vh,104px);
  text-align:center;
}
.quiet__inner{ max-width:44ch; margin:0 auto; }

/* Level B - the major experience title. One of these on the page. */
.quiet h2{
  margin:0 0 clamp(22px,3.2vh,34px);
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.9rem,4vw,3.1rem);
  line-height:1.02;
  letter-spacing:.005em;
  text-transform:uppercase;
}
.quiet p{
  margin:0 auto;
  max-width:26ch;                       /* breaks to two lines, not three */
  font-family:var(--f-display);
  font-size:clamp(1.14rem,2vw,1.5rem);
  line-height:1.6;
  opacity:.78;
}


/* ==========================================================================
   Footer

   The last calm state of the page, not the place where everything left over
   gets compressed. Bigger type, more air, and touch targets that do not
   need aiming at.
   ========================================================================== */

.foot{
  background:var(--ink);
  color:var(--white);
  padding:clamp(64px,11vh,132px) var(--gut) clamp(32px,5vh,56px);
}
.foot__inner{ max-width:var(--w-page); margin:0 auto; }
.foot__top{
  display:grid;
  grid-template-columns:minmax(0,1.3fr) repeat(3,minmax(0,1fr));
  gap:clamp(34px,5vw,80px);
  padding-bottom:clamp(42px,6vh,72px);
}
@media (max-width:900px){ .foot__top{ grid-template-columns:1fr 1fr; } }
@media (max-width:560px){ .foot__top{ grid-template-columns:1fr; } }

.foot__mark img{ width:clamp(170px,18vw,240px); height:auto; margin-bottom:1.8em; }
.foot__addr{
  margin:0;
  font-style:normal;
  font-size:1.02rem;
  line-height:2.1;
  opacity:.8;
}
.foot__addr a{ text-decoration:none; }
.foot__addr a:hover{ opacity:1; text-decoration:underline; text-underline-offset:4px; }

.foot__h{
  margin:0 0 1.3em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:1.06rem;
  letter-spacing:.02em;
  opacity:.7;
}
.foot__list{ margin:0; padding:0; list-style:none; }
.foot__list li{ margin-bottom:.2em; }
.foot__list a{
  display:inline-block;
  padding:.44em 0;                       /* a comfortable target, not a hairline */
  font-size:1rem;
  text-decoration:none;
  opacity:.84;
  transition:opacity var(--t-fast) var(--e-out);
}
.foot__list a:hover{ opacity:1; text-decoration:underline; text-underline-offset:4px; }

.foot__bot{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:1.2em;
  padding-top:clamp(24px,3.4vh,36px);
  border-top:1px solid rgba(255,255,255,.16);
  font-size:.86rem;
  opacity:.7;
}
.foot__bot p{ margin:0; }
.foot__bot a{ text-decoration:none; }
.foot__bot a:hover{ opacity:1; }


/* ==========================================================================
   Location

   Media background, with one card crossing the bottom edge of it into the
   section underneath. That crossing is the only overlap on the page besides
   the type on the full-bleed photograph, which is what keeps it meaning
   something.
   ========================================================================== */

.place{
  position:relative;
  margin-bottom:clamp(60px,9vh,120px);
}
.place__media{
  position:relative;
  height:clamp(380px,66vh,720px);
  overflow:hidden;
  background:var(--ink);
}
.place__media img{ width:100%; height:100%; object-fit:cover; }
.place__scrim{
  position:absolute; inset:0;
  background:linear-gradient(to top, rgba(7,11,28,.42) 0%, rgba(7,11,28,0) 46%);
}

/* Layer 2. This one earns its container - it is an interface floating over a
   location - so it gets the control material rather than a white website
   card: translucent, softly blurred, barely lifted, and no rules cutting
   between the three figures. */
.place__card{
  position:absolute;
  left:var(--gut);
  bottom:clamp(-56px,-6vh,-40px);
  z-index:2;
  width:min(calc(100% - var(--gut) * 2), 480px);
  padding:clamp(28px,3.2vw,44px);
  border-radius:var(--r-lg);
  background:var(--mat-light);
  -webkit-backdrop-filter:var(--mat-blur);
  backdrop-filter:var(--mat-blur);
  border:1px solid rgba(255,255,255,.5);
  box-shadow:var(--e2);
  color:var(--navy);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .place__card{ background:rgba(255,255,255,.94); }
}
.place__card h2{
  margin:0 0 .9em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.7rem,3.4vw,2.5rem);
  line-height:1.04;
}
.place__facts{
  display:flex;
  flex-wrap:wrap;
  gap:clamp(18px,3vw,40px);
  margin:0 0 1.8em;
}
.place__facts > div{ }
.place__facts dt{
  font-size:.9rem;
  opacity:.7;
  margin-bottom:.25em;
}
.place__facts dd{
  margin:0;
  font-family:var(--f-display);
  font-size:clamp(1.4rem,2.4vw,1.8rem);
  line-height:1;
}

@media (max-width:700px){
  .place{ margin-bottom:0; }
  .place__media{ height:clamp(300px,44vh,420px); }
  .place__card{
    position:static;
    width:auto;
    margin:calc(clamp(26px,3vw,40px) * -1 - 20px) var(--gut) 0;
    box-shadow:var(--e2);
  }
}


/* ==========================================================================
   Reviews

   Plain and readable. This is the one place on the page that is deliberately
   not doing anything clever - it competes with nothing, and the words are
   the whole point.
   ========================================================================== */

/* The score anchors the left and the words sit beside it, so the number is
   an interruption in a composition rather than a figure alone in a field.
   It is navy, not orange: orange is the booking action and nothing else. */

.rev{
  display:grid;
  grid-template-columns:minmax(0,.42fr) minmax(0,1fr);
  gap:clamp(30px,6vw,96px);
  align-items:start;
}
@media (max-width:860px){ .rev{ grid-template-columns:1fr; gap:clamp(26px,4vh,40px); } }

.score{ margin:0; }
/* Level F - the metric. Oversized on purpose: the number is the object. */
.score b{
  display:block;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(3.4rem,7.6vw,5.6rem);
  line-height:.9;
  letter-spacing:-.02em;
}
.score span{
  display:block;
  margin-top:.9em;
  max-width:18ch;
  font-size:1rem;
  line-height:1.6;
  opacity:.78;
}

/* when there are no reviews in yet, the right-hand column carries one
   honest line rather than an empty carousel */
.rev__none{
  margin:0;
  max-width:38ch;
  font-family:var(--f-display);
  font-size:clamp(1.14rem,2vw,1.44rem);
  line-height:1.66;
}
.rev__none a{ text-underline-offset:4px; }


/* ==========================================================================
   The close
   ========================================================================== */

/* the closing band: PASS 9, at the foot of this file */

/* ==========================================================================
   The enquiry - calendar and form

   Two nights minimum, seven maximum, and the calendar refuses to let you
   pick anything else rather than telling you off after the fact.
   ========================================================================== */

.enq{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  max-width:760px; margin-inline:auto;
  gap:clamp(28px,4vw,64px);
  align-items:start;
}
@media (max-width:980px){ .enq{ grid-template-columns:1fr; } }

/* --- the form ----------------------------------------------------------- */

.form{ display:grid; gap:clamp(14px,1.8vw,20px); }
.form__row{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(12px,1.6vw,18px); }
@media (max-width:560px){ .form__row{ grid-template-columns:1fr; } }

.f{ display:block; }
.f > span{
  display:block;
  margin-bottom:.6em;
  font-size:.82rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  opacity:.82;
}
.f > span em{ font-style:normal; font-weight:500; letter-spacing:.06em; text-transform:none; opacity:.7; margin-left:.5em; }
.f input[type="date"]{ min-width:0; color-scheme:light; cursor:pointer; }
.f input[type="date"]::-webkit-calendar-picker-indicator{ opacity:.55; cursor:pointer; }
.form__nights{ margin:-.2em 0 0; min-height:1.4em; font-size:.88rem; font-weight:500; }
.form__send{ margin:.4em 0 0; }
.f input,
.f select,
.f textarea{
  width:100%;
  padding:.95em 1em;
  border:1px solid rgba(38,51,119,.2);
  border-radius:14px;
  background:var(--white);
  font-family:var(--f-ui);
  font-size:.94rem;
  color:var(--navy);
  transition:border-color .28s var(--ease);
}
.f textarea{ min-height:8em; resize:vertical; line-height:1.6; }
.f input:focus,.f select:focus,.f textarea:focus{ border-color:var(--navy); outline:none; }
.f input::placeholder,.f textarea::placeholder{ color:rgba(38,51,119,.38); }

.sec--navy .f > span,.sec--ink .f > span{ color:var(--white); }

.f select{
  appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3.5 8 L12 16.5 L20.5 8' fill='none' stroke='%23263377' stroke-width='2.6'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 1em center;
  background-size:.72em;
  padding-right:2.6em;
}

.form__note{
  margin:0;
  font-size:.82rem;
  line-height:1.6;
  opacity:.8;
}
.form__note a{ color:inherit; }

.form__say{
  margin:0;
  padding:1em 1.15em;
  border-left:2px solid var(--orange);
  background:rgba(255,131,29,.08);
  font-size:.86rem;
  line-height:1.6;
}
.form__say[hidden]{ display:none; }
[hidden]{ display:none !important; }
.form__say.is-bad{ border-left-color:#c8442c; background:rgba(200,68,44,.08); }

/* honeypot */
.hp{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }


/* ==========================================================================
   FAQs - the fold, further down; nothing of its own here
   ========================================================================== */

/* ==========================================================================
   Articles
   ========================================================================== */

/* 74ch at 17px is about 740px, which is the middle of the 680-760 the brief
   asks for. Figures are allowed out of it - see below. */
.art{ max-width:var(--w-read); margin:0 auto; }
.art h2{
  margin:2.2em 0 .7em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.4rem,2.6vw,2rem);
  line-height:1.16;
}
.art h2:first-child{ margin-top:0; }
.art p{ margin:0 0 1.2em; font-size:1.08rem; line-height:1.8; }
.art ul{ margin:0 0 1.6em; padding:0; list-style:none; }
.art ul li{
  position:relative;
  padding:.44em 0 .44em 1.5em;
  font-size:1rem;
  line-height:1.7;
}
.art ul li::before{
  content:""; position:absolute; left:0; top:1.06em;
  width:9px; height:2px; background:currentColor; opacity:.34;
}
.art blockquote{
  margin:2em 0;
  padding:0 0 0 1.4em;
  border-left:2px solid currentColor;
  font-family:var(--f-display);
  font-size:1.24rem;
  line-height:1.56;
}
.art .aside{
  margin:2em 0;
  padding:1.3em 1.5em;
  background:var(--sand);
  border-left:2px solid var(--navy);
  font-size:.95rem;
  line-height:1.72;
}
/* a photograph is allowed to break the reading width */
.art figure{
  margin:clamp(30px,4.4vh,56px) 0;
  width:min(100vw - var(--gut) * 2, 1080px);
  margin-left:50%;
  transform:translateX(-50%);
}
.art figure img{ width:100%; border-radius:var(--r-media); }
.art figcaption{
  margin-top:.9em;
  font-size:.88rem;
  line-height:1.6;
  opacity:.7;
}
.art figure img{ width:100%; }
.art figcaption{
  margin-top:.8em;
  font-size:.86rem; letter-spacing:.13em; text-transform:uppercase; opacity:.7;
}
.art a{ color:inherit; text-decoration:underline; text-underline-offset:3px; }
.art a:hover{ opacity:.68; }


.draftflag{
  display:inline-flex; align-items:center; gap:.6em;
  padding:.6em 1em;
  margin:0 0 clamp(22px,3vh,32px);
  background:var(--orange);
  color:var(--white);
  font-size:.82rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
}

/* The filter row, on things to do and the guides. Not a row of boxes: the
   same quiet uppercase labels the carousel's foot and the cards use, in a
   line, the live one underlined. On a phone it is one line that scrolls
   sideways rather than a stack of buttons. */
.filt{
  display:flex; flex-wrap:nowrap; gap:clamp(18px,2.4vw,34px);
  margin:0 0 clamp(26px,4vh,44px);
  padding-bottom:2px;
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
  border-bottom:1px solid rgba(38,51,119,.1);
}
.filt::-webkit-scrollbar{ display:none; }
.filt button{
  flex:none;
  padding:.55em 0 .8em;
  border:0;
  border-bottom:2px solid transparent;
  margin-bottom:-1px;
  background:none;
  font-family:var(--f-ui);
  font-size:.78rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  color:var(--navy);
  opacity:.7;
  cursor:pointer;
  white-space:nowrap;
  transition:opacity var(--t-fast) var(--e-out), border-color var(--t-fast) var(--e-out);
}
.filt button:hover{ opacity:.85; }
.filt button.is-on{ opacity:1; border-bottom-color:var(--orange); }

/* A page with nothing on it yet is still a page a guest can land on. The
   dashed box this used to draw looked like a developer's drop zone; this is
   a quiet editorial statement with somewhere to go next. */
.empty{
  max-width:52ch;
  padding:clamp(20px,4vh,44px) 0;
  text-align:left;
}
.empty p{ margin:0 0 .7em; }
.empty p:last-child{
  margin:0;
  font-size:1.06rem;
  line-height:1.7;
  opacity:.72;
}
.empty a{ text-underline-offset:4px; }


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

@media (prefers-reduced-motion:reduce){
  .rv{ opacity:1; transform:none; transition:none; }
  .phero__media img{ animation:none; transform:scale(1.02); }
  /* The carousel keeps working; it stops moving. Perspective and blur come
     off and the planes swap instantly, so the hierarchy is carried by size
     and opacity - both of which are still there in a still frame. */
  .car__item{ transition:opacity .18s linear; }
  .car__item[data-o="1"],.car__item[data-o="-1"],
  .car__item[data-o="2"],.car__item[data-o="-2"]{ filter:none; }
  .car[data-variant="depth"]{ --dc-rot1:0deg; --dc-rot2:0deg; --dc-z1:0px; --dc-z2:0px; }
  [data-variant="depth"] .car__viewport{ perspective:none; }
  .car__meta{ transition:none; }
  .btn:hover,.unit:hover .unit__media img,.mag__i:hover .mag__media img{ transform:none; }
  .gnav::after{ transition:none; }

  /* the phase 3 components: every one of them still works, none of them
     moves. The contextual photograph on the amenities page swaps instead of
     crossfading; the indexes still mark where you are. */
  .kitx__frame{ transition:none; }
  .kitx__index a,.kitx__index a::before,
  .floorx a,.floorx a::before,
  .doc__toc a{ transition:none; }
  .pcard,.mag__i,.row,.step{ transition:none; }

  *{ scroll-behavior:auto !important; }
}


/* ==========================================================================
   The bar, given some presence

   main.css builds it and owns how it moves. What it did not have was size:
   at 68px with .7rem lettering it read as a browser toolbar bolted under a
   cinematic hero, and it asked anyone over about fifty to squint. Height,
   type and touch target are raised here rather than in main.css, so the
   mechanism it carries is left alone.
   ========================================================================== */

/* main.css still carries .bar's own lettering from when the front page and
   the interior pages had two different navigations. The GlobalNav's sizes
   win because this file loads second - these two lines set them to exactly
   the same numbers so that is a decision rather than an accident. */
.bar .tbtn{ font-size:.82rem; letter-spacing:.13em; padding:.7em 0; }



/* The hero's own lettering, brought up to the same floor. main.css sets these
   at .72-.745rem, which lands around 11px and is the one place left on the
   site that asks to be squinted at. Raised here rather than there, so the
   file that owns the hero's mechanism is left alone. */
.hero__top .tbtn,
.hero__top .tbtn--drop{ font-size:.88rem; letter-spacing:.15em; }
.drop__link{ font-size:.86rem; letter-spacing:.13em; padding:.72em 0; }

@media (max-width:620px){
  .hero__top .tbtn,
  .hero__top .tbtn--drop{ font-size:.76rem; letter-spacing:.1em; }
  .drop__link{ font-size:.78rem; }
}

/* On a phone main.css takes the hero's controls down to around 10-12px. The
   two that are controls come back up; the eyebrow and the place line are
   display typography at wide letterspacing rather than anything anyone has
   to read to use the site, so those keep the hero's composition. */
@media (max-width:620px){
  .hero__top .tbtn,
  .hero__top .tbtn--drop{ font-size:.82rem; letter-spacing:.1em; }
  .drop .drop__link{ font-size:.84rem; letter-spacing:.11em; padding:.8em 0; }
}

/* A phrase is not a metric. "Rated Superb" at 5.6rem looks like shouting;
   a number that size looks like a fact, which is the whole reason the metric
   is allowed to be oversized in the first place. */
.score--phrase b{ font-size:clamp(1.9rem,3.6vw,2.9rem); line-height:1.06; }
.score b em{ font-style:normal; font-size:.44em; opacity:.7; letter-spacing:.01em; }
.score span a{ text-underline-offset:4px; }


/* ==========================================================================
   Shell B - the entrance

   The photograph is already there when the page opens. The words arrive
   over about 600ms and then it is finished. The front page is the only
   ceremony on this site; an interior page that performs is an interior page
   that keeps you waiting.
   ========================================================================== */

/* Every page arrives the way the front page does, in a fraction of the
   time: the frame settles, then the words, one at a time, on the same
   curve. Under a second and a half, and never in the way - the page is
   whole underneath it from the first frame.

     0.00  the photograph, from 1.06 and (on a cold load) from dark
     0.34  the breadcrumb
     0.46  the title rises
     0.66  the fact line
     0.74  the proposition
     0.86  the actions, and a credit last

   The nav has its own entrance on a cold load - see "Every page arrives"
   below. Reached through a view transition, the frame is moved by the
   transition itself and does not animate twice. */
.js .phero .crumb      { animation:pin      .6s var(--e-out)    .34s backwards; }
.js .phero h1          { animation:pin-up   .8s var(--e-spring) .46s backwards; }
.js .phero__meta       { animation:pin      .6s var(--e-out)    .66s backwards; }
.js .phero__lede       { animation:pin-up   .7s var(--e-spring) .74s backwards; }
.js .phero__line,
.js .phero__acts       { animation:pin      .6s var(--e-out)    .86s backwards; }
.js .phero .credit     { animation:pin      .6s var(--e-out)   1.0s  backwards; }
html.arrive .phero__media{ animation:frame-in 1.4s var(--e-out) backwards; }
@keyframes frame-in{ from{ opacity:0; transform:scale(1.06); } to{ opacity:1; transform:none; } }

@keyframes pin   { from{ opacity:0; }                          to{ opacity:1; } }
@keyframes pin-up{ from{ opacity:0; transform:translateY(16px);} to{ opacity:1; transform:none; } }

.phero__meta{
  margin:clamp(14px,2vh,22px) 0 0;
  font-size:.84rem;
  font-weight:500;
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.78;
}
.phero__meta + .phero__lede{ margin-top:clamp(12px,1.8vh,20px); }

/* On a phone the trail and the fact line are the two pieces of letterspaced
   uppercase that run out of room first, and both break mid-phrase when they
   do. Tightened rather than truncated - a breadcrumb with an ellipsis in it
   is worse than a small one. */
@media (max-width:560px){
  .crumb{ font-size:.72rem; letter-spacing:.14em; }
  .phero__meta{ font-size:.74rem; letter-spacing:.14em; }
}


/* CC BY-SA is a condition, not a courtesy. Two of the guides open on a
   Wikimedia Commons photograph, so the photographer is named on those pages
   and the licence is named and linked. Quiet, in the corner of the picture,
   but never absent - if this stops rendering the photographs come down. */
.phero .credit{
  position:absolute;
  z-index:3;
  right:var(--gut);
  bottom:.9em;
  margin:0;
  max-width:min(60ch,72vw);
  text-align:right;
  font-size:.74rem;
  line-height:1.5;
  color:var(--white);
  opacity:.7;
}
.phero .credit a{ color:inherit; text-underline-offset:3px; }
.phero .credit:hover{ opacity:.9; }
@media (max-width:700px){
  /* in the flow on a phone - and on its own row, or as a flex item it sits
     beside the title and squeezes it into half the width */
  .phero{ flex-wrap:wrap; }
  .phero .credit{ position:static; flex-basis:100%; padding:.8em 0 0; text-align:left; }
}


/* ==========================================================================
   Shell C - the utility masthead

   A form, a list of answers or a document does not need half a screen of
   photograph in front of it. Same nav, same type, same navy, a quarter of
   the height, and the page starts.
   ========================================================================== */

.mast{
  position:relative;
  min-height:clamp(170px,26vh,290px);
  display:flex;
  align-items:flex-end;
  padding:calc(var(--bar-h) + clamp(26px,4.4vh,50px)) var(--gut) clamp(22px,3.4vh,38px);
  background:var(--navy);
  color:var(--white);
}
/* the same graded foot as a photographic hero, so the two belong together */
.mast::after{
  content:"";
  position:absolute; left:0; right:0; bottom:0;
  height:52%;
  background:linear-gradient(to top, rgba(7,11,28,.34), rgba(7,11,28,0));
  pointer-events:none;
}
.mast__inner{
  position:relative; z-index:1;
  width:100%; max-width:var(--w-page); margin:0 auto;
}
.mast h1{
  margin:0;
  max-width:22ch;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.1rem,4.2vw,3.3rem);
  line-height:1.02;
  letter-spacing:-.012em;
}
.mast__lede{
  margin:clamp(14px,2.2vh,24px) 0 0;
  max-width:56ch;
  font-family:var(--f-display);
  font-size:clamp(1rem,1.7vw,1.24rem);
  line-height:1.62;
  opacity:.86;
}
/* the same sequence, a beat sooner: there is no photograph to wait for */
.js .mast .crumb   { animation:pin    .6s var(--e-out)    .2s  backwards; }
.js .mast h1       { animation:pin-up .8s var(--e-spring) .3s  backwards; }
.js .mast__lede    { animation:pin-up .7s var(--e-spring) .5s  backwards; }
.js .mast__note    { animation:pin    .6s var(--e-out)    .62s backwards; }


/* ==========================================================================
   The floor explorer - /apartments/

   Seven apartments in one Victorian house over four levels. The floor is the
   organising fact, so the floor is the layout. Nothing is in a white card:
   the separation is the floor band, the photograph, the alignment and the
   space between them.
   ========================================================================== */

.floors{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:clamp(28px,4vw,76px);
}
@media (max-width:1000px){ .floors{ grid-template-columns:1fr; } }

/* the index. It represents the building, which is why it is here and why it
   is not on a phone - a sticky rail on a 390px screen is furniture. */
.floorx{
  position:sticky;
  top:calc(var(--bar-h) + clamp(24px,5vh,56px));
  align-self:start;
}
.floorx ol{ margin:0; padding:0; list-style:none; }
.floorx a{
  display:flex;
  align-items:center;
  gap:.85em;
  padding:.7em 0;
  font-size:.76rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  opacity:.7;
  transition:opacity var(--m-calm) var(--e-out);
}
.floorx a::before{
  content:"";
  width:12px; height:2px;
  flex:none;
  background:currentColor;
  transition:width var(--m-calm) var(--e-spring);
}
.floorx a:hover{ opacity:.68; }
.floorx a.is-on{ opacity:1; }
.floorx a.is-on::before{ width:28px; }

@media (max-width:1000px){ .floorx{ display:none; } }

/* both of these are grid children holding wide content - a photograph, a
   table, a paragraph. Without min-width:0 a grid track refuses to shrink
   below its content and the page grows a horizontal scrollbar. */
.floors__body,
.moment__body{ min-width:0; }

.floor{
  padding-bottom:clamp(52px,9vh,120px);
  scroll-margin-top:calc(var(--bar-h) + clamp(20px,4vh,48px));
}
.floor:last-child{ padding-bottom:0; }

.floor__units{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(24px,3.2vw,48px);
}
.floor__units--one{ grid-template-columns:1fr; }
@media (max-width:760px){ .floor__units{ grid-template-columns:1fr; gap:clamp(34px,5vh,52px); } }

/* --- one apartment ------------------------------------------------------ */

.unit{
  display:block;
  text-decoration:none;
  color:inherit;
}
.unit__media{
  display:block;
  overflow:hidden;
  border-radius:var(--r-lg);
  background:var(--navy-deep);
  aspect-ratio:16/11;
  box-shadow:var(--e1);
}
.unit__media img{
  width:100%; height:100%;
  object-fit:cover;
  transition:transform var(--m-spatial) var(--e-spring);
}
.unit:hover .unit__media img,
.unit:focus-visible .unit__media img{ transform:scale(1.03); }

.unit__body{ display:block; padding-top:clamp(16px,2.4vh,26px); }
.unit__t{
  display:block;
  font-family:var(--f-display);
  font-size:clamp(1.32rem,2.2vw,1.8rem);
  line-height:1.08;
}
.unit__facts{
  display:flex;
  flex-wrap:wrap;
  gap:.4em 1.5em;
  margin-top:1em;
  font-size:.88rem;
  letter-spacing:.05em;
  opacity:.7;
}
.unit__facts b{ font-weight:500; display:inline-flex; align-items:center; gap:.4em; }
.unit__facts svg{ width:1.15em; height:1.15em; flex:none; }
/* The way in is the hero's own chevron, sitting in the corner of the
   photograph and pointing on, with the hero's pool of shade behind it. It
   comes up as you reach for the card. The whole card is the link. */
.unit__arrow{
  position:absolute; right:clamp(12px,1.6vw,20px); bottom:clamp(12px,1.6vw,20px);
  z-index:2;
  width:44px; height:44px;
  display:grid; place-items:center;
  color:var(--white);
  opacity:.55;
  transition:opacity .45s var(--ease), transform .5s var(--e-spring);
  pointer-events:none;
}
.unit__arrow::before{
  content:"";
  position:absolute; inset:-70%;
  border-radius:50%;
  background:radial-gradient(closest-side, rgba(7,11,28,.36), rgba(7,11,28,0));
  z-index:-1;
}
.unit__arrow svg{ width:22px; height:22px; transform:rotate(-90deg); filter:drop-shadow(0 1px 8px rgba(7,11,28,.5)); }
.unit:hover .unit__arrow,
.unit:focus-visible .unit__arrow{ opacity:1; transform:translateX(4px); }

/* the ground floor has one apartment, so it gets the wide composition */
.unit--wide{
  display:grid;
  grid-template-columns:minmax(0,1.2fr) minmax(0,.8fr);
  gap:clamp(24px,4vw,68px);
  align-items:center;
}
.unit--wide .unit__media{ aspect-ratio:16/10; }
.unit--wide .unit__body{ padding-top:0; }
@media (max-width:760px){
  .unit--wide{ grid-template-columns:1fr; }
  .unit--wide .unit__body{ padding-top:clamp(16px,2.4vh,26px); }
}


/* ==========================================================================
   The comparison strip

   Seven things being compared on the same five axes is the one shape a table
   is genuinely better at than anything else on this site.
   ========================================================================== */

.cmp{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
.cmp table{
  width:100%;
  min-width:660px;
  border-collapse:collapse;
  font-size:1.06rem;
}
.cmp th,.cmp td{ text-align:left; padding:1.05em 1.6em 1.05em 0; }
.cmp thead th{
  padding-bottom:.9em;
  font-size:.72rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.7;
}
.cmp tbody tr{ border-top:1px solid rgba(38,51,119,.13); }
.cmp tbody th{
  font-family:var(--f-display);
  font-weight:400;
  font-size:1.1rem;
}
.cmp a{ text-decoration:none; }
.cmp a:hover{ text-decoration:underline; text-underline-offset:4px; }

.cmp__note{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(18px,3vw,52px);
  margin-top:clamp(24px,3.6vh,40px);
  max-width:96ch;
  font-size:1.06rem;
  line-height:1.72;
  opacity:.74;
}
.cmp__note p{ margin:0; }
.cmp__note b{ font-weight:600; }
@media (max-width:760px){ .cmp__note{ grid-template-columns:1fr; } }


/* ==========================================================================
   One apartment - the page
   ========================================================================== */

/* B: at a glance. A band of facts, not a row of cards. */
.glance{
  padding:clamp(24px,3.6vh,40px) var(--gut);
  background:var(--paper);
  border-bottom:1px solid rgba(38,51,119,.09);
}
.glance__inner{ max-width:var(--w-page); margin:0 auto; }
.glance dl{
  margin:0;
  display:flex;
  flex-wrap:wrap;
  gap:clamp(18px,3.6vw,62px);
}
.glance dt{
  margin-bottom:.5em;
  font-size:.74rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.7;
}
.glance dd{
  margin:0;
  font-family:var(--f-display);
  font-size:clamp(1.02rem,1.5vw,1.2rem);
  line-height:1.2;
}

/* D: one image and text moment, and only one */
/* the apartment's own moment on the left - the photograph, the reason, the
   action - and what is included on the right, from 900px up */
.aptx{
  display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  gap:clamp(28px,5vw,88px);
  align-items:start;
}
.aptx__why .moment__media{ margin-bottom:clamp(24px,3.6vh,40px); }
.aptx__has .ticks{ margin:0 0 clamp(20px,3vh,30px); }
@media (max-width:900px){ .aptx{ grid-template-columns:1fr; } }
/* Every photograph in the set is 16:10 - prep.py crops them that way. A
   portrait frame here would throw two thirds of the room away, so the
   composition uses the shape the photographs actually are. */
.moment__media{
  border-radius:var(--r-lg);
  overflow:hidden;
  aspect-ratio:16/10;
  background:var(--navy-deep);
  box-shadow:var(--e1);
}
.moment__media img{ width:100%; height:100%; object-fit:cover; }
@media (max-width:900px){ .moment{ grid-template-columns:1fr; } }

/* H: the other six */
.peers{
  margin:0; padding:0; list-style:none;
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:0 clamp(24px,4vw,64px);
}
@media (max-width:900px){ .peers{ grid-template-columns:1fr 1fr; } }
@media (max-width:560px){ .peers{ grid-template-columns:1fr; } }
.peers a{
  display:block;
  padding:1.1em 0;
  text-decoration:none;
  border-top:1px solid rgba(38,51,119,.13);
}
.peers b{
  display:block;
  font-family:var(--f-display);
  font-weight:400;
  font-size:1.18rem;
  line-height:1.14;
}
.peers span{
  display:block;
  margin-top:.42em;
  font-size:.88rem;
  opacity:.7;
}
.peers a:hover b{ text-decoration:underline; text-underline-offset:4px; }


/* ==========================================================================
   The nav's action
   ========================================================================== */

.btn--nav{
  padding:.86em 1.5em;
  font-size:.78rem;
  letter-spacing:.16em;
  border-color:rgba(255,255,255,.5);
  color:var(--white);
}
.btn--nav:hover{ background:var(--white); color:var(--navy); border-color:var(--white); }


/* ==========================================================================
   Reduced motion, for everything above
   ========================================================================== */

@media (prefers-reduced-motion:reduce){
  .js .phero .crumb,.js .phero h1,.js .phero__meta,.js .phero__lede,.js .phero__line,.js .phero__acts,.js .phero .credit,
  .js .mast .crumb,.js .mast h1,.js .mast__lede,.js .mast__note,
  html.arrive .phero__media{ animation:none; }
  .unit:hover .unit__media img{ transform:none; }
  .floorx a::before{ transition:none; }
}


/* ==========================================================================
   Amenities - the sticky category index

   A list of everything the place has, with a photograph beside it that
   changes as you move down. One state change, one crossfade, no carousel.
   Below 980px the index becomes a row of labels along the top and the
   photograph goes: a sticky desktop apparatus on a phone is furniture.
   ========================================================================== */

.kitx{ padding:var(--stack) var(--gut); background:var(--paper); }
.kitx__inner{
  max-width:var(--w-page);
  margin:0 auto;
  display:grid;
  grid-template-columns:minmax(0,36fr) minmax(0,64fr);
  gap:clamp(28px,5vw,88px);
}
.kitx__side{
  position:sticky;
  top:calc(var(--bar-h) + clamp(24px,5vh,56px));
  align-self:start;
}
.kitx__body{ min-width:0; }

.kitx__index ol{
  margin:0 0 clamp(26px,4vh,44px);
  padding:0;
  list-style:none;
}
.kitx__index a{
  display:flex;
  align-items:center;
  gap:.85em;
  padding:.5em 0;
  font-family:var(--f-display);
  font-size:clamp(1.06rem,1.5vw,1.24rem);
  line-height:1.3;
  text-decoration:none;
  color:inherit;
  opacity:.7;
  transition:opacity var(--m-calm) var(--e-out);
}
.kitx__index a::before{
  content:"";
  width:12px; height:2px;
  flex:none;
  background:currentColor;
  transition:width var(--m-calm) var(--e-spring);
}
.kitx__index a:hover{ opacity:.7; }
.kitx__index a.is-on{ opacity:1; }
.kitx__index a.is-on::before{ width:28px; }

.kitx__shot{
  position:relative;
  aspect-ratio:4/3;
  border-radius:var(--r-float);
  overflow:hidden;
  background:var(--navy-deep);
  box-shadow:var(--e1);
}
.kitx__frame{
  position:absolute; inset:0;
  opacity:0;
  transition:opacity var(--m-spatial) var(--e-out);
}
.kitx__frame.is-on{ opacity:1; }
.kitx__frame img{ width:100%; height:100%; object-fit:cover; }
/* there is no photograph of a bathroom in the set - this is what that looks
   like, rather than a bedroom pretending to be one */
.kitx__frame--none{ display:grid; place-items:center; }
.kitx__frame--none img{ width:44%; height:auto; object-fit:contain; opacity:.42; }

.kitg{
  padding-bottom:clamp(42px,7vh,92px);
  scroll-margin-top:calc(var(--bar-h) + clamp(20px,4vh,48px));
}
.kitg:last-child{ padding-bottom:0; }
.kitg__h{
  margin:0 0 clamp(14px,2.2vh,24px);
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.4rem,2.4vw,2rem);
  line-height:1.1;
}
.kitg__l{
  margin:0; padding:0;
  list-style:none;
  columns:2;
  column-gap:clamp(24px,3vw,56px);
}
.kitg__l li{
  break-inside:avoid;
  position:relative;
  padding:.5em 0 .5em 1.5em;
  font-size:1.06rem;
  line-height:1.6;
}
.kitg__l li::before{
  content:"";
  position:absolute; left:.1em; top:1.02em;
  width:6px; height:6px;
  border-radius:50%;
  background:currentColor;
  opacity:.3;
}

@media (max-width:980px){
  /* minmax(0,1fr), not 1fr: a bare 1fr lets the column grow to its content's
     min size, and the photographs behind the folds pushed it past the screen */
  .kitx__inner{ grid-template-columns:minmax(0,1fr); gap:clamp(20px,3.4vh,32px); }
  .kitx__side{ position:static; }
  .kitx__shot{ display:none; }
  .kitx__index ol{
    display:flex;
    gap:0 clamp(18px,4vw,30px);
    margin:0 calc(var(--gut) * -1) clamp(22px,3.4vh,34px);
    padding:0 var(--gut) .5em;
    overflow-x:auto;
    scrollbar-width:none;
  }
  .kitx__index ol::-webkit-scrollbar{ display:none; }
  .kitx__index a{ white-space:nowrap; font-size:1rem; opacity:.7; }
  .kitx__index a::before{ display:none; }
}
@media (max-width:620px){ .kitg__l{ columns:1; } }


/* ==========================================================================
   The map, with the facts floating over its edge

   Motif A under motif D. The one overlap on these pages, and the only place
   on them where translucent material appears.
   ========================================================================== */

.map2{ padding:0 0 var(--stack); background:var(--paper); }
.map2__inner{
  position:relative;
  max-width:var(--w-media);
  margin:0 auto;
}
.map2__frame{
  aspect-ratio:21/9;
  min-height:340px;
  overflow:hidden;
  background:var(--mist);
}
.map2__frame iframe{ width:100%; height:100%; border:0; display:block; filter:saturate(.85); }
/* The map takes the wheel and the finger as soon as they cross it, which
   makes the page hard to scroll past. A clear cover sits over it until it is
   clicked or tapped, then steps aside; it comes back when the pointer
   leaves. Same idea as a map asking for two fingers. */
.map2__frame{ position:relative; }
.map2__cover{
  position:absolute; inset:0; z-index:2;
  display:grid; place-items:end center;
  padding-bottom:clamp(14px,2.4vh,24px);
  border:0; background:transparent;
  color:var(--navy);
  font:600 .72rem/1 var(--f-ui); letter-spacing:.18em; text-transform:uppercase;
  cursor:pointer;
}
.map2__cover::after{ content:attr(data-say); padding:.7em 1.1em; border-radius:var(--r-pill); background:rgba(251,250,248,.86); box-shadow:var(--e1); opacity:0; transition:opacity .3s var(--e-out); }
.map2__frame:hover .map2__cover::after{ opacity:1; }
.map2__frame.is-live .map2__cover{ display:none; }
.map2__cover{ font-size:0; }
@media (hover:none){ .map2__cover::after{ opacity:1; } }

.map2__lens{
  position:absolute;
  left:clamp(18px,5vw,84px);
  bottom:clamp(-28px,-3vh,-18px);
  width:min(380px,72vw);
}
.map2__h{
  margin:0 0 1em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.24rem,2vw,1.55rem);
  line-height:1.2;
}
.map2__go{
  display:flex; align-items:center; gap:.7em;
  margin:1.2em 0 0;
  font-size:.9rem;
}
.map2__go span{ opacity:.35; }
.map2__go a{ text-underline-offset:4px; }

@media (max-width:760px){
  .map2{ padding-bottom:calc(var(--stack) + 40px); }
  /* a stated height, not a ratio: min-height with an aspect ratio widened
     the frame past the screen, and a 4:3 map at phone width was too short
     to read once the lens sat on it */
  .map2__frame{ aspect-ratio:auto; height:clamp(360px,60vh,540px); min-height:0; }
  .map2__lens{
    position:relative;
    left:auto; bottom:auto;
    width:auto;
    margin:calc(var(--r-lens) * -1) var(--gut) 0;
  }
}

.pairs--tight div{ padding:.5em 0; }


/* ==========================================================================
   One large statement on paper

   Monalia's lesson: whitespace without a composition is just empty. This is
   the composition - one sentence at display size with a line of context
   beside it, and nothing else in the section.
   ========================================================================== */

.say{
  margin:0;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.1rem,4.6vw,3.4rem);
  line-height:1.02;
  letter-spacing:.005em;
}

/* a photographic interruption, full bleed, words in the foot */
.place2{
  min-height:clamp(380px,62vh,680px);
  display:flex;
  align-items:flex-end;
  padding:clamp(48px,9vh,110px) var(--gut) clamp(34px,6vh,66px);
}
.place2 h2{
  margin:0 0 .5em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.9rem,4vw,3rem);
  line-height:1.04;
}
.place2 p{
  margin:0;
  max-width:46ch;
  font-size:clamp(1.02rem,1.5vw,1.16rem);
  line-height:1.7;
  opacity:.88;
}


/* ==========================================================================
   Things to do - the place cards are further down, under PASS 7
   ========================================================================== */

/* the filter row is shared with the guides index */
.filt[data-target] button{ cursor:pointer; }

/* CC BY-SA is a condition, not a courtesy. Naming the photographer is not
   optional - it just does not belong between a photograph and its controls,
   which is where it used to be. */
.credits{ padding:0 var(--gut) var(--stack); background:var(--cream); }
.credits__inner{ max-width:var(--w-page); margin:0 auto; }
.credits ul{
  margin:0; padding:0;
  list-style:none;
  columns:2;
  column-gap:clamp(24px,4vw,64px);
  font-size:.86rem;
  line-height:1.7;
  opacity:.7;
}
.credits li{ break-inside:avoid; padding:.2em 0; }
.credits a{ text-underline-offset:3px; }
@media (max-width:700px){ .credits ul{ columns:1; } }


/* ==========================================================================
   The secondary ways to get in touch, under the form
   ========================================================================== */

.note{
  margin:clamp(26px,4vh,42px) 0 0;
  max-width:62ch;
  font-size:.95rem;
  line-height:1.7;
  opacity:.7;
}


/* ==========================================================================
   Documents - policies, privacy

   A contents list, a readable column, and nothing else. Legal text does not
   want a signature interaction.
   ========================================================================== */

.doc{ padding:var(--stack) var(--gut); background:var(--paper); }
.doc__inner{
  max-width:var(--w-page);
  margin:0 auto;
  display:grid;
  grid-template-columns:minmax(0,230px) minmax(0,1fr);
  gap:clamp(28px,5vw,88px);
}
.doc__toc{
  position:sticky;
  top:calc(var(--bar-h) + clamp(24px,5vh,56px));
  align-self:start;
}
.doc__toc ol{ margin:0; padding:0; list-style:none; }
.doc__toc a{
  display:block;
  padding:.48em 0;
  font-size:.98rem;
  text-decoration:none;
  opacity:.7;
  transition:opacity var(--m-calm) var(--e-out);
}
.doc__toc a:hover{ opacity:.72; }
.doc__toc a.is-on{ opacity:1; }

.doc__body{ min-width:0; max-width:var(--w-read); }
.doc__part{
  padding-bottom:clamp(34px,5vh,62px);
  scroll-margin-top:calc(var(--bar-h) + clamp(20px,4vh,48px));
}
.doc__part:last-child{ padding-bottom:0; }
.doc__h{
  margin:0 0 clamp(14px,2vh,22px);
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.32rem,2.2vw,1.8rem);
  line-height:1.14;
}

@media (max-width:900px){
  .doc__inner{ grid-template-columns:1fr; gap:clamp(20px,3vh,30px); }
  .doc__toc{ position:static; }
  .doc__toc ol{
    display:flex;
    flex-wrap:wrap;
    gap:0 1.4em;
    padding-bottom:.6em;
    border-bottom:1px solid rgba(38,51,119,.14);
  }
  .doc__toc a{ opacity:.78; font-size:.92rem; }
}


/* ==========================================================================
   Guides - the magazine index

   One lead at full width, then an asymmetric list. A photograph, a category,
   a headline, a read time and two lines. No shadowed blog cards.
   ========================================================================== */

.mag{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(32px,3.6vw,60px) clamp(24px,3vw,48px);
}
@media (max-width:900px){ .mag{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width:600px){ .mag{ grid-template-columns:1fr; } }

.mag__i{ display:block; text-decoration:none; color:inherit; }
.mag__media{
  display:block;
  overflow:hidden;
  border-radius:var(--r-media);
  aspect-ratio:16/11;
  background:var(--navy-deep);
  margin-bottom:clamp(14px,1.8vh,20px);
}
.mag__media img{
  width:100%; height:100%; object-fit:cover;
  transition:transform var(--m-spatial) var(--e-spring);
}
.mag__i:hover .mag__media img{ transform:scale(1.03); }
.mag__body{ display:block; }
.mag__k{
  display:flex; align-items:center; gap:.5em;
  margin-bottom:.5em;
  font-size:.76rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  opacity:.7;
}
.mag__k i{ font-style:normal; opacity:.6; }
.mag__t{
  display:block;
  margin-bottom:.4em;
  font-family:var(--f-display);
  font-size:clamp(1.24rem,1.9vw,1.5rem);
  line-height:1.12;
}
.mag__i:hover .mag__t{ text-decoration:underline; text-underline-offset:5px; }
.mag__d{
  display:block;
  font-size:1.06rem;
  line-height:1.66;
  opacity:.76;
}

/* the lead takes the full row and gets the bigger type */
.mag__i--lead{
  grid-column:1 / -1;
  display:grid;
  grid-template-columns:minmax(0,1.35fr) minmax(0,1fr);
  gap:clamp(22px,4vw,64px);
  align-items:center;
}
.mag__i--lead .mag__media{ aspect-ratio:16/9; margin-bottom:0; border-radius:var(--r-float); }
.mag__i--lead .mag__t{ font-size:clamp(1.7rem,3.2vw,2.6rem); }
.mag__i--lead .mag__d{ font-size:clamp(1.02rem,1.4vw,1.12rem); max-width:46ch; }
@media (max-width:760px){
  .mag__i--lead{ grid-template-columns:1fr; }
  .mag__i--lead .mag__media{ margin-bottom:clamp(14px,1.8vh,20px); }
}


/* ==========================================================================
   Guides - previous and next
   ========================================================================== */

.steps{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(18px,3vw,44px);
  max-width:var(--w-read);
  margin:clamp(40px,6vh,76px) auto 0;
  padding-top:clamp(24px,3.6vh,38px);
  border-top:1px solid rgba(38,51,119,.14);
}
.step{
  display:block;
  text-decoration:none;
  color:inherit;
}
.step--prev{ text-align:left; }
.step--next{ text-align:right; }
.step__k{
  display:block;
  margin-bottom:.5em;
  font-size:.74rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  opacity:.7;
}
.step__t{
  display:block;
  font-family:var(--f-display);
  font-size:clamp(1.06rem,1.6vw,1.24rem);
  line-height:1.2;
}
.step:hover .step__t{ text-decoration:underline; text-underline-offset:5px; }
@media (max-width:600px){
  .steps{ grid-template-columns:1fr; }
  .step--next{ text-align:left; }
}


/* ==========================================================================
   Moving between pages

   Harmony is a plain multi-page site, which is exactly the case the View
   Transition API was added for. On a browser that supports it, moving from
   one page to the next is one product changing what it is showing; on a
   browser that does not, the link works the way links have always worked,
   and the arriving page still choreographs itself in. Nothing depends on it.

   Three rules:

     1. the page crossfades - out in 240ms, in in 360ms - and the nav and
        the footer hold still, because they are the same object on both pages
     2. the photograph at the top of a page is a frame, and a frame is pushed
        off the way the hero's reel pushes a slide off: the old one leaves to
        the left, the new one arrives from the right
     3. where the photograph you clicked IS the next page's frame - an
        apartment's card on the index, a frame in the carousel, a guide's
        cover, the house on the front page - it travels there. The same
        picture, moving from where it was to where it is going.

   Names are unique on a page: a card and the hero it leads to share one.
   The stylesheet gives every frame a class so the rules below can say
   "any frame" without listing them.

   https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API/Using
   ========================================================================== */

@view-transition{ navigation:auto; }

.gnav{ view-transition-name:harmony-nav; }
.foot{ view-transition-name:harmony-foot; }
/* the front page's bar starts as the hero's footer and arrives with the
   welcome, so it is not the same object as a docked header and does not
   pretend to be: it goes with the page and comes back on the clock */
.gnav--home{ view-transition-name:none; }

/* the frames - the page hero, whole (photograph, scrim and title travel
   as one object, or the photograph would be drawn over its own words for
   the length of the transition), and every picture that can become one */
.phero{ view-transition-name:hero; view-transition-class:frame; }
.unit__media,.mag__media,.prop__media,.place__media,
.car__item{ view-transition-class:pic; }

@media (prefers-reduced-motion:no-preference){
  ::view-transition-old(root){ animation:vt-out 240ms var(--e-out) both; }
  ::view-transition-new(root){ animation:vt-in  360ms var(--e-out) both; }
  @keyframes vt-out{ to{ opacity:0; } }
  @keyframes vt-in{ from{ opacity:0; } }

  /* the nav and the footer hold still */
  ::view-transition-group(harmony-nav),
  ::view-transition-group(harmony-foot){ animation-duration:240ms; }
  ::view-transition-old(harmony-nav),
  ::view-transition-new(harmony-nav),
  ::view-transition-old(harmony-foot),
  ::view-transition-new(harmony-foot){ animation:none; mix-blend-mode:normal; }

  /* a picture travelling to where it is going - one spring, the same one
     everything with mass uses */
  ::view-transition-group(.frame),
  ::view-transition-group(.pic){ animation-duration:var(--m-structural); animation-timing-function:var(--e-spring); }
  ::view-transition-old(.frame),::view-transition-new(.frame),
  ::view-transition-old(.pic),::view-transition-new(.pic){ animation-duration:var(--m-structural); animation-timing-function:var(--e-out); }
  ::view-transition-image-pair(.frame),
  ::view-transition-image-pair(.pic){ overflow:hidden; }

  /* a picture with nowhere to go simply goes with the page */
  ::view-transition-old(.pic):only-child{ animation:vt-out 240ms var(--e-out) both; }
  ::view-transition-new(.pic):only-child{ animation:vt-in  360ms var(--e-out) both; }

  /* a frame with no partner is pushed off, the reel's own movement */
  ::view-transition-old(.frame):only-child,
  ::view-transition-old(hero){ animation:vt-push-out 420ms var(--e-out) both; }
  ::view-transition-new(.frame):only-child,
  ::view-transition-new(hero){ animation:vt-push-in var(--m-structural) var(--e-spring) both; }
  @keyframes vt-push-out{ to{ opacity:0; transform:translateX(-5%); } }
  @keyframes vt-push-in{ from{ opacity:0; transform:translateX(5%) scale(1.03); } }
}

/* Asked for less motion: no transition at all, and the browser navigates the
   way it always did. */
@media (prefers-reduced-motion:reduce){
  ::view-transition-old(root),
  ::view-transition-new(root){ animation:none; }
  .gnav,.foot,.phero,.unit__media,.mag__media,.prop__media,.place__media,.car__item{ view-transition-name:none !important; }
}


/* ==========================================================================
   The page below the hero, changed in place

   On the front page and the seven apartment pages, #page is the part of the
   document that changes when an apartment is chosen from the hero's list:
   it fades, its contents are swapped for the other page's, and it fades back
   with its reveals cascading - Harmony.view() in site.js. The footer and the
   hero stay.
   ========================================================================== */

#page{ transition:opacity .26s var(--e-out); }
#page.is-leaving{ opacity:0; }

/* --- the floor plan ------------------------------------------------------------
   Traced 1:1 from the surveyor's sheet (harmony-plans/trace.py) and inlined,
   so it is drawn in the page's own navy on the page's own cream and set in
   its own type. A sheet of paper on the cream ground: the plan stands in it
   at whatever height the screen allows, the width following from the shape
   of the apartment - a tall plan is tall, and is not squashed to fit. */

.plan{
  margin:0;
  --plan-floor:var(--sand);
  --plan-wall:var(--navy);
  --plan-line:var(--navy);
  --plan-text:var(--navy);
}
.plan__fig{ margin:clamp(28px,4vh,44px) 0 0; }
.plan.is-open .btn svg{ transform:rotate(90deg); }
.plan__sheet{
  width:fit-content; max-width:100%;
  margin:0 auto;
  padding:clamp(28px,4vw,60px) clamp(28px,5vw,88px);
  border-radius:var(--r-lg);
  background:var(--paper);
  box-shadow:var(--lift-2);
}
.plan__sheet svg{
  display:block;
  height:clamp(480px,82vh,960px);
  width:auto; max-width:100%;
}
.plan__note{
  margin:clamp(14px,2vh,20px) 0 0;
  text-align:center;
  font-size:.84rem;
  opacity:.78;
}
.plan__none{ padding:2em; text-align:center; opacity:.78; }
@media (max-width:700px){
  .plan__sheet{ width:auto; padding:18px 14px; border-radius:var(--r); }
  .plan__sheet svg{ height:auto; width:100%; max-height:none; margin:0 auto; }
}


/* ==========================================================================
   Every page arrives

   On a cold load - a visitor landing from a search, a bookmark, a link in a
   message - the nav enters the way it does on the front page: the mark, the
   links from the middle outward, the action last. Reached through a view
   transition it is the same object as on the page before and holds still;
   the head of every page decides which, before the first paint.

   Down the page, whatever is already on screen when the page opens arrives
   in order, after the title, one beat apart - see the reveals in site.js.
   Anything further down waits to be scrolled to, as before.
   ========================================================================== */

@keyframes lift-s{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
@keyframes rule-draw{ from{ transform:scaleX(0); } to{ transform:none; } }

html.arrive .gnav:not(.gnav--home) .gnav__mark{ animation:pin .7s var(--e-out) .08s backwards; }
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn{ animation:lift-s .8s var(--e-spring) backwards; }
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn:nth-child(3){ animation-delay:.22s; }
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn:nth-child(2),
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn:nth-child(4){ animation-delay:.32s; }
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn:nth-child(1),
html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn:nth-child(5){ animation-delay:.42s; }
html.arrive .gnav:not(.gnav--home) .gnav__cta .btn{ animation:lift-s .8s var(--e-spring) .56s backwards; }
html.arrive .gnav:not(.gnav--home) .gnav__burger{ animation:pin .6s var(--e-out) .4s backwards; }
/* the docked rule draws from the centre out, as it does after Coming Home */
html.arrive .gnav:not(.gnav--home)::after{ transform-origin:50% 50%; animation:rule-draw .8s var(--e-out) .7s backwards; }

@media (prefers-reduced-motion:reduce){
  html.arrive .gnav:not(.gnav--home) .gnav__mark,
  html.arrive .gnav:not(.gnav--home) .gnav__nav .tbtn,
  html.arrive .gnav:not(.gnav--home) .gnav__cta .btn,
  html.arrive .gnav:not(.gnav--home) .gnav__burger,
  html.arrive .gnav:not(.gnav--home)::after{ animation:none; }
}


/* ==========================================================================
   HOME, SECOND ITERATION

   One control language for the whole front page, and it is the hero's: the
   controls sit on the photograph, they are white, they are quiet, and they
   show themselves when you reach for them. A guest who has just learned how
   the hero works should not have to learn a second thing two screens later.
   ========================================================================== */


/* --- the navigation arrives the way it did in iteration one ---------------
   The hero's choreography animates .bar .tbtn, but only gave delays to the
   first three - the five links, the mark and the Enquire button were arriving
   as one flat fade with the bar. Each one lifts into place again, from the
   middle outward, and the action lands last. Same curve, same timing family
   as the rest of the welcome. */

.js .bar .gnav__cta .btn{ opacity:0; }

body.is-ready .bar .gnav__nav .tbtn{ animation:lift .85s var(--ease-drop) both; }
body.is-ready .bar .gnav__nav .tbtn:nth-child(3){ animation-delay:var(--t-nav); }
body.is-ready .bar .gnav__nav .tbtn:nth-child(2),
body.is-ready .bar .gnav__nav .tbtn:nth-child(4){ animation-delay:calc(var(--t-nav) + .13s); }
body.is-ready .bar .gnav__nav .tbtn:nth-child(1),
body.is-ready .bar .gnav__nav .tbtn:nth-child(5){ animation-delay:calc(var(--t-nav) + .26s); }
body.is-ready .bar .gnav__cta .btn{ animation:lift .85s var(--ease-drop) calc(var(--t-nav) + .43s) both; }

body.is-live .bar .gnav__nav .tbtn,
body.is-live .bar .gnav__cta .btn{ animation:none; opacity:1; transform:none; }

/* the hero's hover lift, on the nav's links too - but not on the button,
   which has its own */
body.is-live .bar .gnav__nav .tbtn:hover,
body.is-live .bar .gnav__nav .tbtn:focus-visible{ transform:translateY(-2px); }

@media (prefers-reduced-motion:reduce){
  body.is-ready .bar .gnav__nav .tbtn,
  body.is-ready .bar .gnav__cta .btn{ animation:soft .4s ease .2s both; }
}


/* --- the hero on a phone -----------------------------------------------------
   The word Apartments was shoving the mark off centre on a 390px screen. The
   toggle is a chevron: > closed, v open. The mark sits a little higher, the
   toggle a little lower, so the two are not on one crowded line. And the
   photograph dims while the list is open so the list can be read over
   whichever frame is behind it. */

.hero__dim{
  position:absolute; inset:0;
  z-index:7;                              /* over the scrim, under the top row */
  background:rgba(7,11,28,.5);
  opacity:0;
  pointer-events:none;
  transition:opacity .45s var(--ease);
}
.hero:has(.drop.is-open) .hero__dim{ opacity:1; }

@media (max-width:620px){
  .hero__top .tbtn--drop .tbtn__label{ display:none; }
  .hero__top .tbtn--drop{ margin-top:1.1em; padding:.6em .4em; }
  .hero__top .tbtn--drop .tbtn__chev{
    width:1.05em; height:1.05em;
    transform:rotate(-90deg);            /* > */
  }
  .drop.is-open .tbtn--drop .tbtn__chev{ transform:rotate(0deg); }   /* v */
  .hero__mark{ margin-top:-.35em; }
  .drop__list{ top:calc(100% + 14px); }
}


/* --- the carousel controls, on the photograph -------------------------------
   Count at the top of the live frame, centred, white, the display face - the
   same place the mark sits on the hero. Name in the bottom-right corner,
   small and bold. The arrows are out over the neighbours and come up when
   the carousel is hovered or has focus, exactly as the hero's edge arrows
   do. On a phone they are not drawn: it visibly slides. */

.car__count{
  position:absolute;
  z-index:8;
  top:clamp(14px,2vh,22px);
  margin:0;
  pointer-events:none;
  font-family:var(--f-display);
  font-size:clamp(.92rem,1.2vw,1.06rem);
  letter-spacing:.2em;
  font-variant-numeric:tabular-nums;
  color:var(--white);
  text-shadow:0 1px 14px rgba(7,11,28,.45);
  opacity:.9;
  min-width:0;
  text-align:center;
}
.car__count b{ font-weight:400; }

.car__name{
  position:absolute;
  z-index:8;
  bottom:clamp(14px,2.2vh,22px);
  margin:0;
  pointer-events:none;
  text-align:right;
  font-family:var(--f-ui);
  font-size:.76rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--white);
  text-shadow:0 1px 14px rgba(7,11,28,.5);
  transition:opacity var(--t-fast) var(--e-out);
}
.car.is-turning .car__name{ opacity:0; }

/* A breath of the hero's scrim at the top and foot of every photographic
   frame, so the count and the name read on a pale sky or a bright worktop
   as well as they do on a dark room. Light enough that a frame without
   words on it does not look treated. */
[data-variant="depth"] .car__item::after,
[data-variant="editorial"] .car__item::after{
  content:"";
  position:absolute; inset:0;
  pointer-events:none;
  background:
    linear-gradient(to bottom, rgba(7,11,28,.30) 0%, rgba(7,11,28,0) 24%),
    linear-gradient(to top,    rgba(7,11,28,.34) 0%, rgba(7,11,28,0) 28%);
}

/* where the live frame is, per variant - the controller never has to know */
[data-variant="depth"] .car__count{ left:50%; transform:translateX(-50%); }
[data-variant="depth"] .car__name{ right:calc(50% - var(--dc-w) / 2 + clamp(16px,1.6vw,24px)); }
[data-variant="editorial"] .car__count,
[data-variant="strip"] .car__count{ left:calc(var(--car-item) / 2); transform:translateX(-50%); }
[data-variant="editorial"] .car__name,
[data-variant="strip"] .car__name{ right:calc(100% - var(--car-item) + clamp(16px,1.6vw,24px)); }

.car__arrow{
  position:absolute;
  z-index:9;
  top:50%;
  width:clamp(44px,4vw,60px); height:clamp(44px,4vw,60px);
  margin-top:calc(clamp(44px,4vw,60px) / -2);
  display:grid; place-items:center;
  padding:0; border:0;
  background:none;
  box-shadow:none;
  color:var(--white);
  cursor:pointer;
  opacity:0;
  transition:opacity .45s var(--ease), transform .5s var(--ease);
  -webkit-tap-highlight-color:transparent;
}
.car__arrow svg{
  width:clamp(20px,1.7vw,26px); height:clamp(20px,1.7vw,26px);
  filter:drop-shadow(0 1px 10px rgba(7,11,28,.6));
}
.car__arrow--prev svg{ transform:rotate(90deg); }
.car__arrow--next svg{ transform:rotate(-90deg); }
/* a pool of shade around the arrow only, as on the hero */
.car__arrow::before{
  content:"";
  position:absolute; inset:-60%;
  border-radius:50%;
  background:radial-gradient(closest-side, rgba(7,11,28,.34), rgba(7,11,28,0));
  z-index:-1;
}
/* out over the neighbours */
[data-variant="depth"] .car__arrow--prev{ left:calc(50% - var(--dc-w) / 2 - clamp(44px,4vw,60px) - clamp(10px,1.4vw,22px)); }
[data-variant="depth"] .car__arrow--next{ right:calc(50% - var(--dc-w) / 2 - clamp(44px,4vw,60px) - clamp(10px,1.4vw,22px)); }
[data-variant="editorial"] .car__arrow--prev,
[data-variant="strip"] .car__arrow--prev{ left:clamp(10px,1.2vw,18px); }
[data-variant="editorial"] .car__arrow--next,
[data-variant="strip"] .car__arrow--next{ left:calc(var(--car-item) + var(--car-gap) + clamp(10px,1.2vw,18px)); }

/* they come up when you reach for the carousel; keyboard focus counts */
.car:hover .car__arrow,
.car:focus-within .car__arrow{ opacity:.82; transform:translateY(0); }
.car__arrow--prev{ transform:translateY(8px); }
.car__arrow--next{ transform:translateY(8px); }
.car__arrow:hover,
.car__arrow:focus-visible{ opacity:1 !important; }
.car__arrow:active svg{ transform:scale(.9) rotate(var(--r,0deg)); }
.car__arrow--prev{ --r:90deg; }
.car__arrow--next{ --r:-90deg; }

/* the dark grounds no longer need an inverted control - it is already white */
.sec--navy .car__arrow,.sec--ink .car__arrow,.close .car__arrow{ background:none; border:0; box-shadow:none; }

/* --- the words under the picture ------------------------------------------- */

.car__meta{ margin:clamp(22px,3.4vh,36px) auto 0; }
[data-variant="depth"] .car__meta{ max-width:none; text-align:center; }
.car__facts{ margin:0 0 1.1em; }
.car__row{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  align-items:baseline;
  gap:.2em clamp(24px,3.4vw,48px);
  margin:0;
}
.car__more{
  display:inline-flex; align-items:center; gap:.6em;
  padding:.7em 0;
  font-size:.88rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  opacity:.78;
  border-bottom:1px solid transparent;
  transition:opacity var(--t-fast) var(--e-out), gap var(--t-fast) var(--e-out);
}
.car__more svg{ width:.72em; height:.72em; transform:rotate(-90deg); }
.car__more:hover{ opacity:1; gap:1em; }

@media (max-width:900px){
  .car__arrow{ display:none; }
  .car__row{ flex-direction:column; align-items:center; gap:0; }
  .car__name{ font-size:.7rem; letter-spacing:.16em; }
  [data-variant="depth"] .car__name{ right:calc(50% - var(--dc-w) / 2 + 14px); }
}

/* no script: the controls are meaningless and the labels do the naming */
html:not(.js) .car__arrow,
html:not(.js) .car__count,
html:not(.js) .car__name{ display:none; }


/* --- one line, said once ----------------------------------------------------- */

.quiet h2{
  font-family:var(--f-display);
  font-weight:700;
  font-style:italic;
  font-size:clamp(1.7rem,3.4vw,2.9rem);
  line-height:1.06;
  letter-spacing:0;
  text-transform:none;
  max-width:none;
  white-space:nowrap;
}
.quiet__inner{ max-width:none; }
.quiet p{ max-width:40ch; }
/* one line on a phone too: the size follows the width */
/* on a phone the line is allowed to break: kept to one line it ran past the
   edge and the page scrolled sideways */
@media (max-width:760px){ .quiet h2{ white-space:normal; text-wrap:balance; font-size:clamp(1.5rem,7vw,2.2rem); } }


/* --- the house ------------------------------------------------------------------
   Meet the house before the rooms in it. Not a card: the photograph runs
   from edge to edge, the way the hero does, and the introduction sits at
   its foot on the hero's own scrim. It is the one full-bleed frame between
   the hero and Weston, so the two of them are not competing. */

.house{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  min-height:clamp(520px,82vh,860px);
  display:flex;
  align-items:flex-end;
  padding:clamp(56px,8vh,96px) var(--gut) clamp(44px,7vh,80px);
  background:var(--ink);
  color:var(--white);
}
.house__media{ position:absolute; inset:0; z-index:0; }
.house__media img{
  width:100%; height:100%;
  object-fit:cover; object-position:50% 40%;
  transform:scale(1.04);
  transition:transform 1.6s var(--e-out);
}
.house.is-in .house__media img{ transform:none; }
.house__scrim{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(to top,   rgba(7,11,28,.82) 0%, rgba(7,11,28,.34) 38%, rgba(7,11,28,0) 66%),
    linear-gradient(to right, rgba(7,11,28,.28) 0%, rgba(7,11,28,0) 55%);
}
.house__inner{ position:relative; z-index:2; width:100%; max-width:var(--w-page); margin:0 auto; }
.house__say{ max-width:46ch; }
.house__say .eyebrow{ color:var(--white); opacity:.8; margin-bottom:.9em; }
.house__say h2{
  margin:0 0 .5em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.1rem,4.6vw,3.6rem);
  line-height:1.02;
  letter-spacing:-.012em;
}
.house__say p:not(.eyebrow){
  margin:0 0 1.4em;
  font-family:var(--f-display);
  font-size:clamp(1.04rem,1.7vw,1.26rem);
  line-height:1.6;
}
.house__say .car__go{ color:var(--white); }
@media (max-width:760px){ .house{ min-height:72svh; } }


/* --- the amenities, read at a glance ------------------------------------------
   Six groups: the name, and what is in it in one line. Nothing to open. */

.split--amen{ align-items:start; }
.amen{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(22px,3vh,34px) clamp(24px,3vw,44px);
}
.amen__g h3{
  margin:0 0 .45em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.14rem,1.6vw,1.34rem);
  line-height:1.2;
}
.amen__g p{
  margin:0;
  font-size:.96rem;
  line-height:1.7;
}
.amen__g p i{ font-style:normal; opacity:.45; padding:0 .55em; }
.amen__k{
  margin:0;
  font-size:.78rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  opacity:.72;
}
@media (max-width:560px){ .amen{ grid-template-columns:1fr; } }


/* --- the guests, turning ---------------------------------------------------------
   The scores stay put on the left; the cards ride the strip carousel on the
   right, two in view, and it turns on its own - the one carousel on the
   site that does, because Ben asked for it. It stops under a hand. */

.rev2__reel{ min-width:0; }
.rev2__reel .car[data-variant="strip"]{
  --car-item:48.5cqw;              /* two whole cards, never a cut sentence */
  --car-gap:3cqw;
  --car-step:51.5cqw;
}
/* the track is in the flow here, so the viewport is as tall as the cards */
.rev2__reel [data-variant="strip"] .car__viewport{ height:auto; }
.rev2__reel [data-variant="strip"] .car__track{ position:relative; inset:auto; align-items:stretch; }
.rev2__reel .car__item{ display:block; align-self:stretch; padding:0; border:0; background:none; text-align:left; cursor:grab; }
.rev2__reel .car__item .rev2__card{ height:100%; box-sizing:border-box; }
.rev2__reel .car__item:not([data-o="0"]){ opacity:.62; }
.rev2__reel .car__arrow--prev{ display:none; }        /* on it goes, to the right */
.rev2__reel .car__arrow--next{ left:auto; right:clamp(4px,1vw,14px); color:var(--navy); }
.rev2__reel .car__arrow--next svg{ filter:none; }
.rev2__reel .car__arrow::before{ background:radial-gradient(closest-side, rgba(255,255,255,.9), rgba(255,255,255,0)); }
.rev2__reel .car__label{ position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); }
@media (max-width:760px){
  .rev2__reel .car[data-variant="strip"]{ --car-item:100cqw; --car-gap:4cqw; --car-step:104cqw; }
}


/* --- the social panel, by the footer ------------------------------------------
   Navy, rounded like everything else, holding the two live feeds - the
   Instagram profile and the Facebook timeline, as Meta serves them. It sits
   after the close and before the footer, so the social bits are together and
   apart from the selling. */

.social{ padding:0 var(--gut) clamp(40px,6vh,72px); background:var(--paper); }
.social__inner{
  max-width:var(--w-page);
  margin:0 auto;
  padding:clamp(28px,4vw,56px);
  border-radius:var(--r-lg);
  background:var(--navy-deep);
  color:var(--white);
}
.social__head{
  display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between; gap:.6em 2em;
  margin-bottom:clamp(20px,3vh,30px);
}
.social__head .h2{ margin:0; color:var(--white); }
.social__line{ margin:0; font-size:.98rem; opacity:.8; }
.social__feeds{
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:clamp(20px,3vw,40px);
}
.social__feed{ min-width:0; }
.social__who{
  display:flex; align-items:center; gap:.7em;
  padding:.6em 0 .9em;
  color:inherit; text-decoration:none;
  font-size:.86rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
}
.social__who svg{ width:22px; height:22px; flex:none; }
.social__who svg:last-child{ width:.7em; height:.7em; margin-left:auto; transform:rotate(-90deg); transition:transform .3s var(--e-out); }
.social__who:hover svg:last-child{ transform:rotate(-90deg) translateY(4px); }
.social__frame{
  overflow:hidden;
  border-radius:var(--r);
  background:var(--paper);
}
.social__frame iframe{ display:block; width:100%; height:600px; border:0; background:var(--paper); }
/* Facebook's plugin stops at 500px however wide its frame; it sits centred */
.social__feed:nth-child(2) .social__frame{ background:var(--paper); }
.social__feed:nth-child(2) iframe{ max-width:500px; margin:0 auto; }
@media (max-width:760px){
  .social{ padding-inline:12px; }
  .social__inner{ border-radius:var(--r); padding:22px 16px; }
  .social__feeds{ grid-template-columns:1fr; }
  .social__frame iframe{ height:520px; }
}


/* --- the instant way in ----------------------------------------------------------
   WhatsApp in its own green, fixed to the corner of every page; on a phone
   the number beside it. On the front page it sits above the bar while the
   bar is still the hero's footer, and comes down once the bar has docked. */

.quick{
  position:fixed;
  right:clamp(16px,2vw,28px);
  bottom:calc(clamp(16px,2vw,28px) + env(safe-area-inset-bottom));
  z-index:60;
  display:flex; flex-direction:column; gap:12px;
  transition:bottom .6s var(--e-out);
}
.quick a{
  width:54px; height:54px;
  display:grid; place-items:center;
  border-radius:50%;
  color:var(--white);
  box-shadow:0 6px 22px rgba(7,11,28,.24);
  transition:transform .35s var(--e-spring), box-shadow .35s var(--e-out);
}
.quick a:hover,
.quick a:focus-visible{ transform:translateY(-2px); box-shadow:0 10px 26px rgba(7,11,28,.3); }
.quick svg{ width:28px; height:28px; }
.quick__wa{ background:#25d366; }
.quick__tel{ background:var(--navy); }
/* on the front page it waits for the welcome to finish */
body:has(.hero):not(.is-live) .quick{ opacity:0; pointer-events:none; }
.quick{ transition:opacity .6s var(--e-out); }
body.menu-open .quick{ opacity:0; pointer-events:none; }

/* the number is for a phone - nobody dials a landline from a laptop */
@media (min-width:761px){ .only-phone{ display:none !important; } }

/* the closing band's ways, with their marks */
.close__ways a{ display:inline-flex; align-items:center; gap:.5em; }
.close__ways svg{ width:1.25em; height:1.25em; }


/* --- the property (the Harmony page) ---------------------------------------------------------------
   One object. The photograph, and the introduction attached directly to its
   lower edge - the same rounded frame the rest of the page's photography
   sits in, with the words inside it rather than in a second box beneath.
   No statistics: this is "meet the house", not a listing. */

.prop{
  max-width:1100px;
  margin:0 auto;
  background:transparent;
}
/* the frame fills the card, and with more than one photograph the rest sit
   behind it, reachable by the arrows and the drag */
.prop .car[data-variant="editorial"]{
  --car-item:100cqw;
  --car-gap:0cqw;
  --car-step:100cqw;
  --ed-h:clamp(360px,60vh,660px);
}
.prop__media{ position:relative; background:var(--navy-deep); border-radius:var(--r-float); overflow:hidden; }
.prop .car__item{ border-radius:0; box-shadow:none; }
.prop .car__item img{ object-position:50% 38%; }   /* the sign and the balconies, for the portrait frame */
.prop .car__viewport{ overflow:hidden; }
/* one photograph: nothing to count, nowhere to go */
.car[data-n="1"] .car__count,
.car[data-n="1"] .car__arrow{ display:none; }

.prop__body{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(18px,3vw,56px);
  align-items:end;
  padding:clamp(26px,3.6vw,44px) 0;
}
.prop__id,.prop__say{ min-width:0; }
.prop__body .eyebrow{ margin-bottom:.8em; }
.prop__say .car__go{ justify-self:start; }
.prop__body h2{
  margin:0;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.8rem,3.4vw,2.7rem);
  line-height:1.02;
}
.prop__p{
  margin:0 0 1.2em;
  max-width:42ch;
  font-size:clamp(1.02rem,1.5vw,1.14rem);
  line-height:1.66;
  opacity:.78;
}
@media (max-width:760px){
  .prop{ border-radius:var(--r-media); }
  .prop__body .eyebrow{ font-size:.7rem; letter-spacing:.14em; }
  .prop .car[data-variant="editorial"]{ --ed-h:clamp(260px,46vh,400px); }
  .prop__body{ grid-template-columns:1fr; gap:clamp(14px,2.4vh,22px); align-items:start; }
}


/* ==========================================================================
   HOME, FOURTH PASS
   ========================================================================== */


/* --- the sheet -----------------------------------------------------------------
   The phone menu is a fixed sheet after the bar in the page, not inside it.
   A backdrop-filter makes its element the backdrop root for everything
   inside it, so a blurred panel cannot live inside a blurred bar. Out here it
   samples the page exactly as the bar does: same formula, same --dock, the
   same colour at every moment. site.js sets its top or bottom against the
   bar's edge as it opens, and says which way it opens. */

.gnav__sheet{ display:none; }

@media (max-width:1080px){
  .gnav__nav{ display:none; }                    /* the bar's own six, on a phone */

  .gnav__sheet{
    display:block;
    position:fixed;
    left:0; right:0;
    top:var(--bar-h);
    height:min(70svh, 560px);
    z-index:69;
    overflow:hidden;                               /* the frame the door slides out of */
    pointer-events:none;
  }
  .gnav__panel{
    position:absolute;
    left:0; right:0;
    top:0;
    display:flex;
    flex-direction:column;
    padding:clamp(14px,3.4vh,30px) var(--gut) clamp(20px,4.4vh,38px);
    /* the bar's glass, from the bar's formula */
    background:rgba(14,24,78,calc(.10 + .46 * var(--dock, 1)));
    -webkit-backdrop-filter:blur(5px) saturate(102%) brightness(calc(.58 - .28 * var(--dock, 1)));
    backdrop-filter:blur(5px) saturate(102%) brightness(calc(.58 - .28 * var(--dock, 1)));
    border-bottom:2px solid var(--rule);           /* the leading edge, coming down */
    color:var(--white);
    transform:translateY(-100%);                   /* behind the bar */
    pointer-events:none;
    transition:transform .72s var(--e-spring);
  }
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .gnav__panel{ background:rgba(14,24,78,calc(.62 + .24 * var(--dock, 1))); }
  }
  /* the bar is the hero's footer: the sheet stands above it and the door
     rises out of it */
  .gnav__sheet.is-up .gnav__panel{
    top:auto; bottom:0;
    border-bottom:0;
    border-top:2px solid var(--rule);              /* the leading edge, going up */
    transform:translateY(100%);
  }
  /* three classes and an element, so it outranks the is-up rule above,
     which is three classes */
  body.menu-open .gnav__sheet .gnav__panel{ transform:none; pointer-events:auto; }

  /* one line: the bar's own rule steps aside while the door is out, and the
     door's edge is the line - it starts exactly where the bar's was */
  body.menu-open .gnav.bar::before,
  body.menu-open .gnav::after{ opacity:0; transition:opacity .2s var(--ease); }

  .gnav__panel .tbtn{
    padding:.9em 0;
    font-size:.78rem;
    letter-spacing:.2em;
    color:rgba(255,255,255,.88);
    opacity:0;
    transform:translateY(10px);
    transition:opacity .5s var(--ease), transform .5s var(--e-spring);
  }
  .gnav__panel .tbtn[aria-current="page"]{ color:var(--white); }
  .gnav__sheet.is-up .gnav__panel .tbtn{ transform:translateY(-10px); }
  body.menu-open .gnav__sheet .gnav__panel .tbtn{
    opacity:1; transform:none;
    transition-delay:calc(var(--i,0) * 30ms + 240ms);
  }
  .gnav__panel .tbtn:hover{ transform:translateX(10px); }
}


/* --- the carousel: no flicker on the links, no grey on hover -------------- */

.car.is-turning .car__meta{ opacity:1; }               /* the row stays put */
.car.is-turning .car__facts{ opacity:0; }              /* only the facts crossfade */
.car__facts{ transition:opacity var(--t-fast) var(--e-out); }
.car__go:hover{ opacity:1; }                           /* the arrow moves; the words stay navy */
.car__more:hover{ opacity:1; }

/* --- the live frame pans, slowly, like the hero's ------------------------------ */

@keyframes car-pan-l{ from{ transform:scale(1.08) translate3d(-2.4%,0,0); } to{ transform:scale(1.08) translate3d(2.4%,0,0); } }
@keyframes car-pan-r{ from{ transform:scale(1.08) translate3d(2.4%,0,0); }  to{ transform:scale(1.08) translate3d(-2.4%,0,0); } }
[data-variant="depth"] .car__item[data-o="0"] img{
  animation:car-pan-l 14s linear infinite alternate;
}
[data-variant="depth"] .car__item[data-o="0"]:nth-child(even) img{ animation-name:car-pan-r; }
@media (prefers-reduced-motion:reduce){
  [data-variant="depth"] .car__item[data-o="0"] img{ animation:none; }
}

/* --- taller on a phone -------------------------------------------------------- */

@media (max-width:900px){
  .car[data-variant="depth"]{ --dc-w:min(86vw,520px); --dc-ratio:4/5; --dc-r:20px; }
}

/* --- beds and guests, as icons, opposite the name ------------------------------ */

.car__spec{
  position:absolute;
  z-index:8;
  bottom:clamp(14px,2.2vh,22px);
  margin:0;
  display:flex;
  flex-direction:column;
  gap:.45em;
  pointer-events:none;
  color:var(--white);
  text-shadow:0 1px 14px rgba(7,11,28,.5);
  transition:opacity var(--t-fast) var(--e-out);
}
.car.is-turning .car__spec{ opacity:0; }
.car__spec span{ display:inline-flex; align-items:center; gap:.5em; }
.car__spec svg{ width:1.15em; height:1.15em; filter:drop-shadow(0 1px 8px rgba(7,11,28,.6)); }
.car__spec b{
  font-family:var(--f-ui);
  font-size:.8rem;
  font-weight:600;
  letter-spacing:.1em;
  font-variant-numeric:tabular-nums;
}
[data-variant="depth"] .car__spec{ left:calc(50% - var(--dc-w) / 2 + clamp(16px,1.6vw,24px)); }

/* --- the foot, attached to the live frame ------------------------------------- */

.car__foot{
  width:var(--dc-w);
  margin:0 auto;
  padding:clamp(16px,2.2vh,22px) clamp(20px,2.4vw,32px);
  background:var(--cream);
  border-radius:0 0 var(--dc-r) var(--dc-r);
  text-align:center;
}
/* not .car__go: the engine rewrites .car__go to the live item's own link,
   and this one is the way to all seven whichever is showing */
.car__browse{
  display:inline-flex; align-items:center; gap:.6em;
  padding:.7em 0;
  font-size:.88rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  border-bottom:1px solid transparent;
  transition:gap var(--t-fast) var(--e-out), border-color var(--t-fast) var(--e-out);
}
.car__browse svg{ width:.72em; height:.72em; transform:rotate(-90deg); }
.car__browse:hover{ gap:1em; border-bottom-color:currentColor; }
/* the live frame meets the foot with square corners; the neighbours keep theirs */
[data-variant="depth"] .car__item{ transition:transform var(--m-spatial) var(--e-spring), opacity var(--m-spatial) var(--e-out), filter var(--m-spatial) var(--e-out), border-radius var(--m-spatial) var(--e-out); }
.car:has(.car__foot)[data-variant="depth"] .car__item[data-o="0"]{ border-bottom-left-radius:0; border-bottom-right-radius:0; }


/* ==========================================================================
   The guests - Google's widget, in the site's clothes
   ========================================================================== */

.rev2{
  display:grid;
  grid-template-columns:minmax(180px,.65fr) minmax(0,1.35fr);
  gap:clamp(18px,2.4vw,34px);
  align-items:stretch;
}
@media (max-width:1000px){ .rev2{ grid-template-columns:1fr 1fr; } }
@media (max-width:620px){
  .rev2{ grid-template-columns:1fr; }
  /* a phone gets the two scores and three cards, not a screen and a half
     of stacked reviews; the other three are still on the Harmony page */
  
}

.rev2__sum{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  text-align:center;
  gap:.5em;
  padding:clamp(20px,3vw,36px);
}
@media (max-width:1000px){ .rev2__sum{ grid-column:1 / -1; } }
.rev2__word{
  margin:0;
  font-family:var(--f-display);
  font-size:clamp(1.6rem,2.6vw,2.1rem);
  letter-spacing:.01em;
}
.rev2__n{ margin:.2em 0 0; font-size:.98rem; opacity:.72; }
.rev2__n b{ font-weight:600; }
.rev2__src{
  margin-top:.6em;
  font-size:.78rem;
  font-weight:600;
  letter-spacing:.2em;
  text-transform:uppercase;
  text-decoration:none;
  opacity:.7;
}
.rev2__src:hover{ opacity:1; text-decoration:underline; text-underline-offset:4px; }

/* the stars: five, gold, half-stops. Gold is a third party's convention for
   a rating and not one of this site's colours, which is why it appears here
   and nowhere else. */
.stars{ display:inline-flex; gap:.15em; margin:0; }
.stars i{
  width:1.15em; height:1.15em;
  background:#e6b422;
  clip-path:polygon(50% 2%, 61% 36%, 98% 38%, 68% 60%, 79% 96%, 50% 74%, 21% 96%, 32% 60%, 2% 38%, 39% 36%);
}
.stars--half i:last-child{ background:linear-gradient(to right, #e6b422 50%, rgba(38,51,119,.18) 50%); }
.rev2__sum .stars i{ width:1.6em; height:1.6em; }

.rev2__card{
  display:flex;
  flex-direction:column;
  gap:.9em;
  padding:clamp(20px,2.4vw,30px);
  border-radius:var(--r-media);
  background:var(--cream);
  border:1px solid rgba(38,51,119,.07);
}
.rev2__card header{ display:flex; align-items:center; gap:.8em; }
.rev2__av{
  flex:none;
  width:44px; height:44px;
  display:grid; place-items:center;
  border-radius:50%;
  background:var(--navy);
  color:var(--white);
  font-family:var(--f-display);
  font-size:1.2rem;
}
.rev2__who{ display:flex; flex-direction:column; min-width:0; }
.rev2__who b{ font-weight:600; font-size:1rem; }
.rev2__who span{ font-size:.86rem; opacity:.78; }
.rev2__g{
  margin-left:auto;
  font-family:var(--f-ui);
  font-weight:600;
  font-size:1.1rem;
  opacity:.45;
}
.rev2__card p{ margin:0; font-size:1.02rem; line-height:1.66; }


/* ==========================================================================
   Out there - the two accounts, and the posts when there are some
   ========================================================================== */

.soc{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(18px,2.4vw,34px);
}
.soc:has(.soc__post){ grid-template-columns:repeat(3,minmax(0,1fr)); }
@media (max-width:760px){ .soc, .soc:has(.soc__post){ grid-template-columns:1fr; } }

.soc__post{
  display:flex; flex-direction:column;
  border-radius:var(--r-media);
  overflow:hidden;
  background:var(--paper);
  text-decoration:none;
  color:inherit;
}
.soc__post img{ width:100%; aspect-ratio:1/1; object-fit:cover; }
.soc__cap{ display:block; padding:1em 1.2em 1.2em; font-size:.98rem; line-height:1.6; }
.soc__cap b{ display:block; margin-bottom:.4em; font-size:.74rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase; opacity:.7; }


/* ==========================================================================
   HOME, FIFTH PASS
   ========================================================================== */


/* --- the sheet, slimmer, and in steps ------------------------------------------
   Three steps, in order, none of them overlapping:
     1. the bar's rule goes             150ms
     2. the door slides                 560ms, starting as the rule is gone
     3. the items arrive                after the door has landed, 35ms apart
   Closing runs the same three the other way, quickly. */

@media (max-width:1080px){
  .gnav__panel{
    padding:clamp(8px,1.4vh,12px) var(--gut) clamp(10px,1.8vh,14px);
    transition:transform .56s var(--e-spring) .12s;      /* 2, after 1 */
  }
  .gnav__panel .tbtn{
    padding:.52em 0;
    font-size:.78rem;
    letter-spacing:.2em;
    transition:opacity .16s var(--ease), transform .16s var(--ease);   /* out: fast, first */
  }
  /* a direction change is laid out, never animated - see seat() in site.js */
  .gnav__sheet.no-move .gnav__panel,
  .gnav__sheet.no-move .gnav__panel .tbtn{ transition:none !important; }
  body.menu-open .gnav__sheet .gnav__panel .tbtn{
    transition:opacity .42s var(--ease), transform .42s var(--e-spring);
    transition-delay:calc(var(--i,0) * 35ms + .64s);      /* 3, after 2 */
  }
  body.menu-open .gnav.bar::before,
  body.menu-open .gnav::after{ transition:opacity .15s var(--ease); }                 /* 1 */
  .gnav.bar::before,
  .gnav::after{ transition:opacity .25s var(--ease) .45s; }                           /* back, after the door */
}


/* --- the social bars ------------------------------------------------------------
   The carousel foot's style: a slim cream bar with the platform's mark, the
   handle and Follow. Hover or press and a photograph drops down beneath it. */

.soc{ gap:clamp(14px,1.8vw,22px); }
.soc__i{
  border-radius:var(--r-media);
  background:var(--paper);
  border:1px solid rgba(38,51,119,.08);
  overflow:hidden;
  transition:box-shadow var(--m-calm) var(--e-out);
}
.soc__i:hover,
.soc__i.is-open{ box-shadow:var(--e1); }
.soc__row{
  display:flex;
  align-items:center;
  gap:.8em;
  padding:0 clamp(14px,1.6vw,22px) 0 clamp(14px,1.6vw,20px);
}
.soc__btn{
  flex:1;
  display:flex;
  align-items:center;
  gap:.7em;
  min-width:0;
  padding:.95em 0;
  border:0; background:none;
  font:inherit; color:inherit;
  text-align:left;
  cursor:pointer;
}
.soc__btn svg{ width:1.3em; height:1.3em; flex:none; }
.soc__h{
  font-family:var(--f-display);
  font-size:clamp(1.06rem,1.5vw,1.24rem);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.soc__k{
  margin-left:.4em;
  font-size:.7rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  opacity:.7;
}
.soc__follow{
  display:inline-flex; align-items:center; gap:.5em;
  flex:none;
  padding:.5em 0;
  font-size:.78rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  border-bottom:1px solid transparent;
  transition:gap var(--t-fast) var(--e-out), border-color var(--t-fast) var(--e-out);
}
.soc__follow svg{ width:.7em; height:.7em; transform:rotate(-90deg); }
.soc__follow:hover{ gap:1em; border-bottom-color:currentColor; }

/* the drop: a grid track from nothing to its content, which is the one way
   to animate an unknown height without measuring it */
.fold__btn{ -webkit-tap-highlight-color:transparent; }
.soc__more{ background:var(--paper); }
.fold__more{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows var(--m-spatial) var(--e-spring);
}
.fold__more > *{ min-height:0; overflow:hidden; }
.fold.is-open .fold__more{ grid-template-rows:1fr; }
@media (hover:hover){ .soc__i:hover .fold__more{ grid-template-rows:1fr; } }

.soc__pic{ padding:0 clamp(10px,1.2vw,14px) clamp(10px,1.2vw,14px); }
.soc__pic img{
  width:100%;
  aspect-ratio:16/10;
  object-fit:cover;
  border-radius:calc(var(--r-media) - 6px);
  opacity:0;
  transform:scale(1.02);
  transition:opacity var(--m-calm) var(--e-out), transform var(--m-spatial) var(--e-spring);
}
.fold.is-open .soc__pic img,
.soc__i:hover .soc__pic img{ opacity:1; transform:none; transition-delay:.12s; }

.soc__post{ border:1px solid rgba(38,51,119,.08); }
@media (max-width:760px){ .soc__k{ display:none; } }


/* --- Fully equipped -----------------------------------------------------------------
   The statement style from "Your home away from home", used once more. */

.quiet--inline{
  max-width:none;
  margin:0 auto clamp(30px,4.6vh,56px);
  text-align:center;
}
.quiet-h{
  margin:0 0 clamp(14px,2.2vh,22px);
  font-family:var(--f-display);
  font-weight:700;
  font-style:italic;
  font-size:clamp(1.7rem,3.4vw,2.9rem);
  line-height:1.06;
}
.quiet-p{
  margin:0 auto;
  max-width:40ch;
  font-family:var(--f-display);
  font-size:clamp(1.14rem,2vw,1.5rem);
  line-height:1.6;
  opacity:.78;
}


/* --- the amenity drop-downs -----------------------------------------------------
   Each group is a photograph of the area, blurred, with the group's name on
   it. Open it and, in order: the chevron turns, the bar grows to make room,
   the photograph sharpens, and the list arrives a line at a time. Closing
   runs it backwards, faster. */

.amx{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(22px,3vw,44px);
  max-width:1100px;
  margin:0 auto;
}
@media (max-width:820px){ .amx{ grid-template-columns:minmax(0,1fr); } }
.amx__col{ display:flex; flex-direction:column; gap:clamp(10px,1.4vw,14px); min-width:0; }
.amx__k{
  margin:0 0 .3em;
  font-size:.76rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  opacity:.7;
}

.amx__g{
  position:relative;
  isolation:isolate;
  border-radius:var(--r-media);
  overflow:hidden;
  background:var(--navy-deep);
  color:var(--white);
}
.amx__bg{
  position:absolute; inset:0;
  z-index:0;
  display:block;
}
.amx__bg img{
  width:100%; height:100%;
  object-fit:cover;
  filter:blur(7px) saturate(.9);
  transform:scale(1.1);                                  /* hides the blur's soft edge */
  transition:filter .7s var(--e-out) .1s, transform .7s var(--e-out) .1s;
}
.amx__g--none .amx__bg{ display:grid; place-items:center; }
.amx__g--none .amx__bg img{ width:36%; height:auto; object-fit:contain; opacity:.35; filter:none; transform:none; }
.amx__scrim{
  position:absolute; inset:0;
  z-index:1;
  background:rgba(7,11,28,.34);
  transition:background-color .6s var(--e-out);
}
.amx__g.is-open .amx__bg img{ filter:blur(0) saturate(1); transform:scale(1.02); }
.amx__g.is-open .amx__scrim{
  background:linear-gradient(to right, rgba(7,11,28,.74) 0%, rgba(7,11,28,.5) 55%, rgba(7,11,28,.24) 100%);
}

.amx__bar{
  position:relative;
  z-index:2;
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1em;
  padding:clamp(18px,2.2vw,24px) clamp(18px,2vw,24px);
  border:0; background:none;
  color:inherit;
  font:inherit;
  text-align:left;
  cursor:pointer;
}
.amx__t{
  font-family:var(--f-ui);
  font-weight:700;
  font-size:clamp(1rem,1.5vw,1.14rem);
  letter-spacing:.06em;
  text-shadow:0 1px 12px rgba(7,11,28,.5);
}
.amx__bar svg{
  width:.9em; height:.9em; flex:none;
  filter:drop-shadow(0 1px 6px rgba(7,11,28,.5));
  transition:transform .3s var(--e-out);                /* 1: the chevron turns */
}
.amx__g.is-open .amx__bar svg{ transform:rotate(180deg); }

.amx__more{ position:relative; z-index:2; }
.amx__l{
  margin:0;
  padding:0 clamp(18px,2vw,24px) clamp(18px,2.2vw,24px);
  list-style:none;
  columns:2;
  column-gap:clamp(16px,2vw,28px);
}
.amx__l li{
  break-inside:avoid;
  padding:.3em 0;
  font-size:.98rem;
  line-height:1.5;
  text-shadow:0 1px 10px rgba(7,11,28,.6);
  opacity:0;
  transform:translateY(6px);
  transition:opacity .16s var(--ease), transform .16s var(--ease);           /* out: fast */
}
/* 4: the lines arrive after the bar has grown, 40ms apart */
.amx__g.is-open .amx__l li{
  opacity:1; transform:none;
  transition:opacity .4s var(--ease), transform .4s var(--e-spring);
}
.amx__g.is-open .amx__l li:nth-child(1){ transition-delay:.36s; }
.amx__g.is-open .amx__l li:nth-child(2){ transition-delay:.40s; }
.amx__g.is-open .amx__l li:nth-child(3){ transition-delay:.44s; }
.amx__g.is-open .amx__l li:nth-child(4){ transition-delay:.48s; }
.amx__g.is-open .amx__l li:nth-child(5){ transition-delay:.52s; }
.amx__g.is-open .amx__l li:nth-child(6){ transition-delay:.56s; }
.amx__g.is-open .amx__l li:nth-child(7){ transition-delay:.60s; }
.amx__g.is-open .amx__l li:nth-child(n+8){ transition-delay:.64s; }
@media (max-width:560px){ .amx__l{ columns:1; } }

.amx__all{ margin:clamp(30px,4.6vh,52px) 0 0; text-align:center; }

@media (prefers-reduced-motion:reduce){
  .fold__more{ transition:none; }
  .amx__bg img,.amx__scrim,.amx__bar svg,.amx__l li,.soc__pic img{ transition:none; }
  .gnav__panel,.gnav__panel .tbtn{ transition:none; }
}


/* ==========================================================================
   EVERY PAGE, THE FRONT PAGE'S VOCABULARY
   ========================================================================== */


/* --- the guests, from both listings -------------------------------------------- */

.rev2__sum{ gap:clamp(18px,3vh,30px); }
.rev2__one{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:.35em;
  text-decoration:none;
  color:inherit;
}
.rev2__one b{
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.4rem,4vw,3.4rem);
  line-height:1;
}
.rev2__one > span:last-child{ font-size:.88rem; opacity:.78; }
.rev2__one:hover > span:last-child{ opacity:1; text-decoration:underline; text-underline-offset:4px; }
.rev2__one .rev2__word{ font-size:clamp(1.1rem,1.6vw,1.3rem); letter-spacing:.14em; }
.stars--full i{ background:#e6b422; }

/* Booking.com reviews carry the listing's score in place of stars - it does
   not show stars per review, and drawing five would be inventing them */
.rev2__score{
  display:inline-flex; align-items:baseline; gap:.5em;
  font-family:var(--f-display);
  font-size:1.2rem;
}
.rev2__score em{ font-style:normal; font-size:.74rem; letter-spacing:.16em; text-transform:uppercase; opacity:.7; font-family:var(--f-ui); }
.rev2__g--g{ font-family:var(--f-ui); }
.rev2__g--b{ font-family:var(--f-display); }

/* six cards: the summary spans both rows on a desktop */
.rev2{ grid-auto-rows:auto; }
@media (min-width:1001px){ .rev2__sum{ grid-row:span 2; } }


/* --- the bars, flat: a mark, a name, a fact ------------------------------------ */

.soc__i--flat .soc__row{ padding-right:clamp(14px,1.6vw,22px); }
.soc__i--flat .soc__btn{ cursor:default; text-decoration:none; color:inherit; }
a.soc__btn{ cursor:pointer; }
.soc__i--flat .soc__k{ margin-left:auto; opacity:.7; font-size:.8rem; }
.soc__i--flat .soc__btn svg{ opacity:.6; }
@media (max-width:760px){ .soc__i--flat .soc__k{ display:inline; } }


/* --- the photo fold, with prose inside ------------------------------------------ */

.amx--one{ grid-template-columns:1fr; max-width:960px; }
.amx__p{
  padding:0 clamp(18px,2vw,24px) clamp(20px,2.4vw,28px);
  max-width:60ch;
}
.amx__p p{
  margin:0 0 .9em;
  font-size:1.02rem;
  line-height:1.66;
  text-shadow:0 1px 10px rgba(7,11,28,.6);
  opacity:0;
  transform:translateY(6px);
  transition:opacity .16s var(--ease), transform .16s var(--ease);
}
.amx__p .amx__k{ margin-bottom:.6em; opacity:0; color:rgba(255,255,255,.7); }
.amx__g.is-open .amx__p p,
.amx__g.is-open .amx__p .amx__k{
  opacity:1; transform:none;
  transition:opacity .4s var(--ease) .36s, transform .4s var(--e-spring) .36s;
}
.amx__g.is-open .amx__p .amx__k{ opacity:.7; }
.amx__go{
  display:inline-flex; align-items:center; gap:.6em;
  margin-top:.2em;
  padding:.5em 0;
  font-size:.8rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:var(--white);
  border-bottom:1px solid rgba(255,255,255,.6);
  text-shadow:0 1px 10px rgba(7,11,28,.6);
  opacity:0;
  transition:opacity .4s var(--ease) .5s, gap var(--t-fast) var(--e-out);
}
.amx__go svg{ width:.7em; height:.7em; transform:rotate(-90deg); }
.amx__g.is-open .amx__go{ opacity:1; }
.amx__go:hover{ gap:1em; }

/* an open fold on the amenities page is the list itself; it opens taller */
.kitx .amx__g.is-open .amx__bg img{ filter:blur(0) saturate(1); transform:scale(1.02); }
.kitx .amx__col{ gap:clamp(14px,2vh,22px); }
.kitx .amx--one{ max-width:none; }
@media (min-width:981px){ .kitx__inner{ grid-template-columns:minmax(0,26fr) minmax(0,74fr); } }   /* the phone's one column stands */


/* --- the FAQ is the same fold --------------------------------------------------- */

.faq{ border-top:0; }
.faq__i{
  border:1px solid rgba(38,51,119,.08);
  border-radius:var(--r-media);
  background:var(--paper);
  overflow:hidden;
  margin-bottom:clamp(8px,1.2vh,12px);
  transition:box-shadow var(--m-calm) var(--e-out);
}
.sec--cream .faq__i,.field--cream .faq__i{ background:var(--paper); }
.sec--white .faq__i,.field .faq__i{ background:var(--cream); }
.faq__i:hover,.faq__i.is-open{ box-shadow:var(--e1); }
.faq__q{
  width:100%;
  display:flex; align-items:center; justify-content:space-between; gap:1em;
  padding:clamp(16px,2vh,20px) clamp(18px,2vw,24px);
  border:0; background:none;
  font:inherit; color:inherit;
  font-family:var(--f-display);
  font-size:clamp(1.06rem,1.5vw,1.22rem);
  line-height:1.3;
  text-align:left;
  cursor:pointer;
}
.faq__q svg{ width:.9em; height:.9em; flex:none; transition:transform .3s var(--e-out); }
.faq__i.is-open .faq__q svg{ transform:rotate(180deg); }
.faq__a > div{
  padding:0 clamp(18px,2vw,24px) clamp(18px,2.2vh,24px);
  font-size:1.02rem;
  line-height:1.7;
  opacity:0;
  transform:translateY(6px);
  transition:opacity .16s var(--ease), transform .16s var(--ease);
}
.faq__i.is-open .faq__a > div{
  opacity:1; transform:none;
  transition:opacity .4s var(--ease) .3s, transform .4s var(--e-spring) .3s;
}
.faq__a p{ margin:0 0 .8em; }
.faq__a p:last-child{ margin:0; }


/* --- photographs move when reached for, everywhere ------------------------------- */

.unit__media img,
.mag__media img{ transition:transform var(--m-spatial) var(--e-spring); }
.unit:hover .unit__media img{ transform:scale(1.04); }

/* the page hero pans, as the front page's does */
.phero__media img{ animation-duration:22s; }


/* ==========================================================================
   PASS 7 - the direct line, the place cards, the gallery by apartment,
   the photograph notes
   ========================================================================== */


/* --- the direct-booking line ----------------------------------------------------
   One sentence, said in the statement voice the front page uses, under the
   action on the closing band and under the masthead of the pages that lead
   to an enquiry. It is content.js's `direct.line`, and nothing else. */

.close__direct{
  margin:clamp(18px,2.6vh,28px) 0 0;
  max-width:44ch;
  font-family:var(--f-display);
  font-weight:700;
  font-style:italic;
  font-size:clamp(1.06rem,1.9vw,1.36rem);
  line-height:1.4;
  color:var(--orange);
}
.close__direct::before{
  content:"";
  display:block;
  width:34px; height:2px;
  margin:0 0 .7em;
  background:currentColor;
  opacity:.8;
}
.mast__note{
  margin:clamp(12px,1.8vh,18px) 0 0;
  max-width:48ch;
  font-family:var(--f-display);
  font-weight:700;
  font-style:italic;
  font-size:clamp(.98rem,1.6vw,1.16rem);
  line-height:1.4;
  color:var(--orange);
}


/* --- the place cards - things to do --------------------------------------------
   The property card's idea, twelve times: the photograph and the words are
   one object. The kind and the distance sit on the picture where the
   carousel keeps its count and its name; the words are attached beneath.
   A card with a guide is one link from corner to corner. */

.pcards{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(20px,2.4vw,36px);
}
@media (max-width:980px){ .pcards{ grid-template-columns:repeat(2,minmax(0,1fr)); } }
@media (max-width:600px){ .pcards{ grid-template-columns:1fr; } }

.pcard{
  position:relative;
  display:flex;
  flex-direction:column;
  border-radius:var(--r-media);
  overflow:hidden;
  background:var(--paper);
  box-shadow:var(--e1);
  transition:transform var(--m-calm) var(--e-spring), box-shadow var(--m-calm) var(--e-out);
}
.field .pcard{ background:var(--cream); }
.field--cream .pcard{ background:var(--paper); }
.pcard:hover,
.pcard:focus-within{ transform:translateY(-4px); box-shadow:var(--e2); }

.pcard__media{
  position:relative;
  aspect-ratio:4/3;
  overflow:hidden;
  background:var(--navy-deep);
}
.pcard__media img{
  width:100%; height:100%;
  object-fit:cover;
  transition:transform var(--m-spatial) var(--e-spring);
}
.pcard:hover .pcard__media img,
.pcard:focus-within .pcard__media img{ transform:scale(1.05); }
.pcard__blank{ display:grid; place-items:center; height:100%; }
.pcard__blank img{ width:42%; height:auto; object-fit:contain; opacity:.42; }
/* the hero's breath of scrim at the top and the foot, so the two labels
   read on a bright sky or pale sand */
.pcard__media::before,
.pcard__media::after{
  content:"";
  position:absolute; left:0; right:0;
  height:34%;
  pointer-events:none;
  z-index:1;
}
.pcard__media::before{ top:0; background:linear-gradient(to bottom, rgba(7,11,28,.42), rgba(7,11,28,0)); }
.pcard__media::after{ bottom:0; background:linear-gradient(to top, rgba(7,11,28,.46), rgba(7,11,28,0)); }
.pcard__kind,
.pcard__far{
  position:absolute;
  z-index:2;
  color:var(--white);
  text-shadow:0 1px 14px rgba(7,11,28,.5);
  pointer-events:none;
}
.pcard__kind{
  top:clamp(12px,1.6vh,18px); left:clamp(14px,1.6vw,20px);
  font-family:var(--f-ui);
  font-size:.72rem; font-weight:600;
  letter-spacing:.2em; text-transform:uppercase;
}
.pcard__far{
  right:clamp(14px,1.6vw,20px); bottom:clamp(12px,1.6vh,18px);
  font-family:var(--f-display);
  font-size:clamp(.96rem,1.2vw,1.1rem);
  letter-spacing:.06em;
  font-variant-numeric:tabular-nums;
}

.pcard__body{
  display:flex;
  flex-direction:column;
  flex:1 1 auto;
  padding:clamp(18px,2.2vw,26px) clamp(18px,2.2vw,26px) clamp(20px,2.4vw,28px);
}
.pcard__where{
  margin:0 0 .5em;
  font-size:.74rem; font-weight:600;
  letter-spacing:.18em; text-transform:uppercase;
  opacity:.7;
}
.pcard__t{
  margin:0 0 .5em;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(1.3rem,1.9vw,1.6rem);
  line-height:1.1;
}
.pcard__t a{ color:inherit; text-decoration:none; }
/* a card with a guide is one link, corner to corner */
.pcard--go .pcard__t a::after{ content:""; position:absolute; inset:0; z-index:3; }
.pcard__d{
  margin:0;
  font-size:1.02rem;
  line-height:1.64;
  opacity:.76;
}
.pcard__go{
  display:flex; flex-wrap:wrap; gap:1.4em;
  margin:auto 0 0;
  padding-top:clamp(16px,2vh,22px);
}
.pcard__link{
  position:relative; z-index:4;
  display:inline-flex; align-items:center; gap:.6em;
  padding:.4em 0;
  font-size:.78rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:inherit;
  border-bottom:1px solid transparent;
  transition:gap var(--t-fast) var(--e-out), border-color var(--t-fast) var(--e-out);
}
.pcard__link svg{ width:.7em; height:.7em; transform:rotate(-90deg); }
.pcard__link:hover{ gap:1em; border-bottom-color:currentColor; }
.pcard__link--map{ opacity:.78; }
.pcard__link--map:hover{ opacity:1; }

.filt + .pcards{ margin-top:clamp(24px,3.4vh,40px); }


/* ==========================================================================
   PASS 9 - the apartments page works harder; the closing band warms up
   ========================================================================== */


/* --- the hero's utility line and its two quiet actions --------------------------- */

.phero__line{
  margin:clamp(14px,2vh,22px) 0 0;
  font-size:.86rem;
  font-weight:500;
  letter-spacing:.08em;
  opacity:.82;
}
.phero__acts{
  display:flex; flex-wrap:wrap; gap:clamp(18px,2.4vw,36px);
  margin:clamp(18px,2.6vh,28px) 0 0;
}
.phero__act{
  display:inline-flex; align-items:center; gap:.6em;
  padding:.5em 0;
  font-size:.78rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  text-decoration:none;
  color:var(--white);
  border-bottom:1px solid rgba(255,255,255,.55);
  transition:gap var(--t-fast) var(--e-out), border-color var(--t-fast) var(--e-out);
}
.phero__act svg{ width:.7em; height:.7em; transform:rotate(-90deg); }
.phero__act:hover{ gap:1em; border-bottom-color:currentColor; }


/* --- the floor index: a label and four dots ---------------------------------------- */

.floorx__k{
  margin:0 0 .6em;
  font-size:.7rem; font-weight:600; letter-spacing:.22em; text-transform:uppercase;
  opacity:.7;
}
.floorx a{ font-size:.74rem; opacity:.7; padding:.62em 0; }
.floorx a::before{
  width:8px; height:8px;
  border-radius:50%;
  background:none;
  border:1.5px solid currentColor;
  box-sizing:border-box;
  transition:background-color var(--m-calm) var(--e-out), transform var(--m-calm) var(--e-spring);
}
.floorx a.is-on::before{ width:8px; background:currentColor; transform:scale(1.15); }
/* on a phone, a row of jump links above the catalogue rather than nothing */
@media (max-width:1000px){
  .floorx{ display:block; position:static; margin-bottom:clamp(22px,3.4vh,34px); }
  .floorx__k{ display:none; }
  .floorx ol{ display:flex; flex-wrap:wrap; gap:.2em clamp(16px,3vw,28px); }
}


/* --- the floor heading: an eyebrow and a rule ------------------------------------- */

.floor{ padding-bottom:clamp(44px,7.4vh,98px); }
.floor__k{
  display:flex; align-items:center; gap:.9em;
  margin:0 0 clamp(16px,2.4vh,28px);
  font-family:var(--f-ui);
  font-size:.74rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  line-height:1;
  color:var(--navy);
}
.floor__k i{ font-style:normal; font-weight:500; opacity:.5; letter-spacing:.14em; }
.floor__k::after{ content:""; flex:1 1 auto; height:1px; background:rgba(38,51,119,.14); margin-left:.4em; }

.floor__units{ gap:clamp(20px,2.6vw,40px); }


/* --- the card ------------------------------------------------------------------------
   Not a card: the photograph and the words beneath it, with nothing drawn
   around them. Hover raises the whole thing 3px, the photograph by 2.5%,
   and the arrow moves 4px to the right. 300ms. Nothing else. */

.unit{
  transition:transform .3s var(--e-spring);
}
.unit:hover,
.unit:focus-visible{ transform:translateY(-3px); }
/* the tag sits beside the photograph, not inside it, so the photograph
   travels to the apartment's page on its own */
.unit__pic{ position:relative; display:block; }
.unit__media{
  position:relative;
  aspect-ratio:4/3;
}
.unit__media img{ transition:transform .3s var(--e-spring); }
.unit:hover .unit__media img,
.unit:focus-visible .unit__media img{ transform:scale(1.025); }
/* one identifier on the photograph, and only one */
.unit__tag{
  position:absolute;
  top:clamp(12px,1.6vh,18px); left:clamp(14px,1.6vw,20px);
  z-index:2;
  padding:.45em .8em;
  border-radius:var(--r-pill);
  background:rgba(7,11,28,.42);
  backdrop-filter:blur(6px);
  -webkit-backdrop-filter:blur(6px);
  color:var(--white);
  font-family:var(--f-ui);
  font-size:.66rem; font-weight:600; letter-spacing:.18em; text-transform:uppercase;
  pointer-events:none;
}
.unit__body{ padding-top:clamp(14px,2vh,22px); }
.unit__k{
  display:block;
  margin-bottom:.9em;
  font-size:.72rem; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  opacity:.7;
}
.unit__t{
  font-size:clamp(1.25rem,1.6vw,1.4rem);      /* 20-22px */
  line-height:1.1;
}
.unit__why{
  display:block;
  margin-top:.45em;
  max-width:36ch;
  font-size:.98rem;                             /* 15-16px */
  line-height:1.55;
  opacity:.84;
}
.unit__facts{
  gap:.4em .7em;
  margin-top:.9em;
  font-size:.86rem;                             /* 13-14px */
  font-weight:500;
  letter-spacing:.03em;
  opacity:.72;
}
.unit__facts i{ font-style:normal; opacity:.5; }
.unit__go{
  margin-top:1.1em;
  font-size:.78rem;                             /* 12-13px */
  transition:none;
}
.unit__go svg{ transition:transform .3s var(--e-spring); }
.unit:hover .unit__go{ gap:.6em; }
.unit:hover .unit__go svg{ transform:rotate(-90deg) translateY(4px); }

/* the featured composition: the ground floor's one apartment */
.unit--wide{
  grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr);
  gap:clamp(24px,4vw,64px);
  align-items:center;
}
.unit--wide .unit__media{ aspect-ratio:4/3; }
.unit--wide .unit__t{ font-size:clamp(1.4rem,2vw,1.7rem); }
.unit__points{
  display:grid;
  gap:.35em;
  margin-top:1.1em;
  padding-top:1.1em;
  border-top:1px solid rgba(38,51,119,.12);
  font-size:.96rem;
  line-height:1.5;
}
.unit__points span{ display:flex; align-items:baseline; gap:.7em; }
.unit__points span::before{ content:""; width:14px; height:1px; background:var(--orange); flex:none; transform:translateY(-.3em); }
@media (max-width:760px){
  .unit--wide{ grid-template-columns:1fr; }
  .unit--wide .unit__media{ aspect-ratio:4/3; }
  .unit--wide .unit__body{ padding-top:clamp(14px,2vh,22px); }
  .unit--wide .unit__k{ display:none; }     /* the floor rule above it says so */
}


/* --- the comparison, readable ------------------------------------------------------- */

.cmp table{ min-width:620px; font-size:1.08rem; }
.cmp th,.cmp td{ padding:1.1em 1.5em 1.1em 0; vertical-align:top; }
.cmp thead th{ font-size:.72rem; opacity:.7; }
.cmp tbody th{ font-size:1.25rem; line-height:1.15; }
.cmp tbody th small{ display:block; margin-top:.3em; font-family:var(--f-ui); font-size:.72rem; font-weight:500; letter-spacing:.14em; text-transform:uppercase; opacity:.7; }
.cmp tbody td{ font-weight:500; opacity:.85; }
.cmp tbody td:last-child{ font-weight:400; }
.cmp tbody tr{ transition:opacity var(--m-calm) var(--e-out); }

/* on a phone the table is a list: each apartment a block, its four facts
   labelled, nothing scrolling sideways */
@media (max-width:620px){
  .cmp{ overflow:visible; }
  .cmp table{ min-width:0; }
  .cmp thead{ display:none; }
  .cmp tbody tr{ display:grid; grid-template-columns:1fr 1fr; gap:.35em 1em; padding:1.1em 0; }
  .cmp tbody th{ grid-column:1 / -1; padding:0 0 .2em; display:flex; align-items:baseline; gap:.8em; }
  .cmp tbody th small{ margin:0; }
  .cmp tbody td{ padding:0; font-size:.94rem; }
  .cmp tbody td::before{ content:attr(data-k); display:block; font-size:.66rem; font-weight:600; letter-spacing:.16em; text-transform:uppercase; opacity:.7; margin-bottom:.15em; }
}

/* --- the closing band, warm ----------------------------------------------------------
   Light content, a warm close, a dark footer. Cream ground, navy words, the
   orange action, and - with a frame - the photograph beside the words. */

.close{
  min-height:0;
  display:block;
  padding:clamp(64px,10vh,120px) var(--gut);
  background:var(--sand);          /* warmer than the cream and the paper, so it reads as its own band before the footer */
  color:var(--navy);
  overflow:visible;
}
.close--photo{ padding-top:clamp(48px,7vh,90px); padding-bottom:clamp(48px,7vh,90px); }
.close__inner{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:clamp(28px,4vw,64px);
  align-items:center;
}
.close--photo .close__inner{ grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
.close__say{ min-width:0; }
.close__kick{
  margin:0 0 clamp(14px,2vh,22px);
  font-size:.72rem; font-weight:600; letter-spacing:.22em; text-transform:uppercase;
  opacity:.7;
}
.close h2{
  margin:0 0 clamp(16px,2.4vh,26px);
  max-width:16ch;
  font-family:var(--f-display);
  font-weight:400;
  font-size:clamp(2.1rem,4.6vw,3.6rem);
  line-height:1.02;
  letter-spacing:-.012em;
}
.close__lede{
  margin:0 0 clamp(24px,3.4vh,36px);
  max-width:44ch;
  font-family:var(--f-display);
  font-size:clamp(1.02rem,1.8vw,1.26rem);
  line-height:1.62;
  opacity:.82;
}
.close__direct{ color:var(--orange); }
.close__ways{
  display:flex; flex-wrap:wrap; align-items:center; gap:.9em;
  margin:clamp(22px,3.2vh,34px) 0 0;
  font-size:.86rem; font-weight:500; letter-spacing:.06em;
}
.close__ways svg{ width:1.3em; height:1.3em; flex:none; }
.close__ways a{ display:inline-flex; align-items:center; gap:.6em; min-height:44px; color:inherit; text-decoration:none; border-bottom:1px solid rgba(38,51,119,.3); padding-bottom:.15em; transition:border-color var(--t-fast) var(--e-out); }
.close__ways a:hover{ border-bottom-color:currentColor; }
.close__ways span{ opacity:.3; }
.close__media{
  position:relative;
  inset:auto;
  z-index:auto;
  aspect-ratio:4/3;
  border-radius:var(--r-media);
  overflow:hidden;
  background:var(--navy-deep);
  box-shadow:var(--e1);
}
.close__media img{ width:100%; height:100%; object-fit:cover; opacity:1; }
@media (max-width:900px){
  .close--photo .close__inner{ grid-template-columns:1fr; }
  .close__media{ aspect-ratio:16/10; }
}
