/*
Theme Name: EL PATIO TOWNSIDE
Description: EL PATIO TOWNSIDE by LA VISTA Developments, New Cairo. A bilingual villas landing theme: English at the root, Arabic at /ar/ with full RTL. Prices and payment plans are never published; the enquiry form is the price list. No external requests; fonts, media and scripts are served locally. Integrates with Rank Math when it is active and stands in for it when it is not.
Version: 1.0.0
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: marsa-north-coast
Domain Path: /languages
Tags: one-column, custom-logo, rtl-language-support, translation-ready, block-styles
*/

/* ============================================================
   1. TOKENS
   Warm, and stone-led. The page is a lime-washed white ground;
   the cut-stone band separates one section from the next, and a
   deep bay-teal band carries the sections that need weight. The
   colours do not share the page equally: terracotta leads, bronze
   sets the display type, stone holds the quiet, and the sea shows
   up almost entirely inside the photography rather than in the UI.
   ============================================================ */
:root{
  /* ============================================================
     MARSA — Marina 5
     The palette is read off the project itself rather than chosen
     from a mood board: the terracotta is the roof tile, the bronze
     is the wordmark on the building, the sea value is the water in
     the bay, and the ground is the lime-washed stucco every wall on
     the site is finished in.

     The governing rule, and the reason this does not look like every
     other coastal site on this shoreline: the page is warm white and
     terracotta, and the blue arrives almost entirely through the
     photography. Sea is an accent for links and focus, never a fill.
     ============================================================ */

  /* ---- the four, by role */
  --clay:#A8543A;       /* primary   — terracotta, from the roof tile   */
  --bronze:#7A4A2B;     /* display   — the wordmark colour on the walls */
  --stone:#F2E9DC;      /* neutral   — section band, the cut stone      */
  --sea:#0E7FA6;        /* accent    — the bay, used sparingly in UI    */

  /* ---- grounds
     Lime white is the page. Stone is a band, never the default ground:
     a warm wash under the whole site is the brochure look this avoids,
     so stone earns its place by alternating. */
  --paper:#FCF8F2;      /* the page, lime-washed white                  */
  --paper-2:#F8F1E7;    /* a panel raised off the page                  */
  --paper-3:#FFFFFF;    /* a card                                       */
  --band:var(--stone);
  --sea-soft:#E3F0F5;   /* sea at panel strength, for quiet fills       */

  /* ---- text
     Warm, not neutral: a cold grey against terracotta reads as a fault.
     Measured on paper (#FCF8F2) and on the stone band (#F2E9DC). */
  --ink:#241A11;        /* body      — 16.1:1 paper, 14.2:1 band        */
  --ink-2:#150E08;      /* headings  — 18.1:1 paper, 15.9:1 band        */
  --muted:#6B5A4A;      /* secondary —  6.2:1 paper,  5.5:1 band        */

  /* ---- terracotta, by role
     #A8543A is 4.97:1 on paper: sound as body text there, but 4.37:1
     on the stone band, which misses AA. The deep variant is the
     measured answer, so the primary is never used at a size that fails. */
  --brand:var(--clay);
  --brand-deep:#8E4028;  /* clay AS TEXT: 6.81:1 paper, 5.99:1 band     */
  --brand-ink:var(--clay); /* clay AS A GROUND, carrying white 5.26:1   */

  /* ---- the deep band
     Derived from the water rather than from black, so a dark section
     still reads as the same bay. */
  --deep:#0B3A47;
  --deep-2:#12505F;
  --on-deep:#FCF8F2;       /* text on a band, 11.6:1                    */
  --on-deep-muted:#A8C6CE; /* secondary on a band, 6.8:1                */

  /* ---- sea, as an accent
     Carries white at 4.6:1 as a ground; as text on paper it is 4.31:1,
     which is short of AA, so text uses the deep value. */
  --sea-text:#0A6180;      /* 6.54:1 paper, 5.76:1 band                 */
  --sea-edge:#0E7FA6;

  /* The phone action bar is fixed to the foot of the viewport, so anything
     sized against the viewport has to subtract it. One token, read by the
     bar itself, by the body's bottom padding and by the hero's height, so
     the three cannot drift apart. Zero above the breakpoint where the bar
     is not shown. */
  --dock-h:0px;

  /* The overlay bar's own height, stated once. It is the bar's vertical
     padding twice over plus the 44px target inside it, so it follows the
     spacing scale rather than being a number typed in two places. The hero
     reserves it so type rising from the foot of the photograph can never
     arrive underneath the identity. */
  --bar-h:calc((var(--s3) * 2) + 44px);

  --line:rgba(36,26,17,.16);
  --hair:rgba(36,26,17,.09);
  --line-inv:rgba(252,248,242,.22);
  --white:#fff;

  /* One radius for every framed surface. The arch on the building is a
     segmental one, so the corner here is softer than the reference
     project's and the pill is reserved for controls. */
  --cut:18px;
  --cut-sm:12px;
  --cut-pill:999px;

  /* ---- families, served locally as WOFF2, no external request
     Fraunces            English display
     Manrope             English body, UI, and every number in both languages
     Noto Naskh Arabic   Arabic display
     Cairo               Arabic body and UI
     Each stack names the real family first and falls back to what a
     platform already ships, so the page is readable before a font
     file arrives. */
  --serif:"Marsa Display",Fraunces,"Hoefler Text","Iowan Old Style",Constantia,Charter,"Palatino Linotype",Palatino,Georgia,serif;
  --sans:"Marsa Sans",Manrope,"Avenir Next",Avenir,"Segoe UI Variable Text","Segoe UI",Inter,ui-sans-serif,-apple-system,system-ui,Roboto,"Helvetica Neue",Arial,sans-serif;

  /* Arabic is not an afterthought on a Latin stack: it has its own display and
     its own text face, chosen for Arabic rather than adapted from Latin. */
  --ar-display:"Marsa Arabic Display","Noto Naskh Arabic","SF Arabic",Dubai,"Segoe UI",serif;
  --ar-sans:"Marsa Arabic",Cairo,"SF Arabic",Dubai,"Noto Sans Arabic","Segoe UI",Tahoma,sans-serif;

  /* Numbers are Manrope in both languages, so a specification plate lines
     up whichever language surrounds it. */
  --num:"Marsa Sans",Manrope,"Avenir Next",Avenir,"Segoe UI Variable Text","Segoe UI",Inter,ui-sans-serif,system-ui,Arial,sans-serif;

  /* ---- typography scale
     Nine tokens, and nothing outside them.

     The treatment is the project's own: this is a boutique hotel, not a
     developer brochure, so the display sits lower and tighter than the
     reference project's and the step between H1 and H2 is smaller. The
     page is meant to read as a printed hotel folio — close intervals,
     generous leading — rather than as a stack of banner headings. */
  --fs-display:clamp(2.9rem,5.4vw,4rem);     /* 600 */
  --fs-h1:clamp(2.25rem,3.8vw,2.75rem);      /* 600 */
  --fs-h2:clamp(1.75rem,2.6vw,2.05rem);      /* 500 */
  --fs-h3:clamp(1.35rem,1.9vw,1.55rem);      /* 500 */
  --fs-body-lg:1.125rem;                     /* 400 */
  --fs-body:1rem;                            /* 400 */
  --fs-small:.875rem;                        /* 400 */
  --fs-caption:.75rem;                       /* 600 */
  --fs-button:1rem;                          /* 600 */

  --fw-display:600;
  --fw-h1:600;
  --fw-h2:500;
  --fw-h3:500;
  --fw-body:400;
  --fw-button:600;

  /* Tracking is part of the treatment: the display is set tight, and the
     small caps label above each section is opened up. */
  --tr-display:-.022em;
  --tr-h:-.014em;
  --tr-label:.16em;

  /* Line heights are explicit on every token. A line box that depends on
     the font's own metrics moves when the webfont swaps in; an explicit
     one does not, which is where the CLS budget is won. */
  --lh-display:1.06;
  --lh-h:1.16;
  --lh-h-ar:1.4;    /* Naskh needs more room than the Latin face */
  --lh-tight:1.45;
  --lh-body:1.75;

  --s1:.45rem; --s2:.8rem; --s3:1.25rem; --s4:2rem;
  --s5:clamp(1.4rem,2.2vw,2rem);
  --s6:clamp(1.7rem,2.6vw,2.4rem);
  --s7:clamp(2rem,3.2vw,3rem);
  --s8:clamp(2.4rem,3.8vw,3.6rem);

  --gutter:clamp(1.35rem,5vw,5rem);
  --frame:1560px;
  --caption:38%;
  --rule:1px;

  /* ---- motion
     Organic rather than mechanical, which comes down to three things.

     One: every curve is asymmetric. ease-in-out is symmetric, which is
     exactly what makes a page feel machined — the element accelerates and
     decelerates identically, which nothing physical does. Everything here
     leaves fast and arrives slowly, with a long tail where the element
     bleeds off speed the way something with mass does.

     Two: duration follows visual weight. A full-bleed photograph and a
     caption do not arrive together, because they do not weigh the same. The
     mass steps below are the whole scale, and nothing outside them.

     Three: nothing lands dead. An arriving element passes a little beyond
     its resting place and settles back — the "drop and settle" in
     gl-settle below. It is 2 to 3 pixels, which is under conscious notice
     and is the entire difference between weight and a slide. It also reads
     with the page: on a site organised as a descent, things come to rest
     downward. */
  --e-settle:cubic-bezier(.22,1,.36,1);      /* the default arrival     */
  --e-drift:cubic-bezier(.16,1,.3,1);        /* heavy things, long tail */
  --e-lift:cubic-bezier(.34,.82,.32,1);      /* a pointer answer        */
  --e-glide:cubic-bezier(.4,.16,.16,1);      /* travel between states   */

  /* Duration by mass, not by category. */
  --d-xl:1.25s;     /* full bleed photography            */
  --d-l:.95s;       /* panels, cards, figures            */
  --d-m:.78s;       /* headings                          */
  --d-s:.58s;       /* labels, captions, small print     */
  --d-hover:.3s;    /* a card answering a pointer        */
  --d-page:.4s;     /* the page arriving                 */

  /* Retained so existing rules keep resolving while the redesign lands. */
  --ease:cubic-bezier(.22,1,.36,1);
  --ease-out-2:cubic-bezier(.22,1,.36,1);
  --ease-out-3:cubic-bezier(.22,1,.36,1);
  --ease-out-4:cubic-bezier(.16,1,.3,1);
  --ease-expo:cubic-bezier(.16,1,.3,1);
  --d-hero:var(--d-xl);
  --d-reveal:var(--d-l);
  --slow:var(--d-m);
}

/* ============================================================
   2. BASE
   ============================================================ */
*,*::before,*::after{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto;}}
body{
  margin:0;background:var(--paper);color:var(--ink);
  /* iPhone: keep content out of the notch and the home indicator */
  padding-inline:env(safe-area-inset-left) env(safe-area-inset-right);
  font-family:var(--sans);font-size:var(--fs-body);line-height:1.78;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
  overflow-x:hidden;
}
img,video{max-width:100%;display:block;height:auto;}
a{color:inherit;text-decoration:none;}
h1,h2,h3,h4{margin:0;font-weight:var(--fw-h1);line-height:var(--lh-h);letter-spacing:var(--tr-h);}
p{margin:0;}
ol,ul,dl,dd{margin:0;padding:0;} li{list-style:none;}
button,input,select,textarea{font:inherit;color:inherit;}
:focus-visible{outline:2px solid var(--brand-deep);outline-offset:4px;}
/* The ring has to be visible on whatever it lands on: ink on the sand band,
   sky on the deep band. A single white ring was invisible on both. */
.room--warm :focus-visible{outline-color:var(--ink);}
.skip{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;}
.skip:focus{width:auto;height:auto;clip:auto;clip-path:none;inset-inline-start:var(--gutter);top:.6rem;z-index:200;background:var(--ink);color:var(--paper);padding:.9rem 1.4rem;}
.fig,.terms dd b,.reckon dd{
  font-family:var(--num);font-variant-numeric:tabular-nums lining-nums;letter-spacing:0;
}

/* ============================================================
   3. THE CAPTION LINE
   There is no twelve column grid. Everything hangs from one
   line at 38% of the frame, the way a wall card sits beside
   the work rather than under it.
   ============================================================ */
.frame{width:100%;max-width:var(--frame);margin-inline:auto;padding-inline:var(--gutter);}
.room{padding-block:var(--s7);position:relative;}
/* The masthead is 85px and becomes sticky on scroll. Without this, every
   link in the contents lands the reader underneath it. */
section[id]{scroll-margin-top:100px;}
.room--gallery{padding-block:var(--s7) var(--s6);}
/* Sand earns its share here and nowhere else: it is the band that separates
   one room from the next, alternating against the white page rather than
   sitting under the whole site. */
.room--warm{background:var(--band);}
.room--plan .prose,.room--plan .lede{color:var(--on-deep-muted);}
.room--plan .room__name{color:var(--on-deep-muted);}
.room--read{background:var(--sea-soft);padding-block:var(--s6) var(--s6);}
/* 244px is the rhythm between rooms. These two were 172 and 280, which is a
   stumble rather than a phrase. */
.room--gallery+.room--read{padding-top:var(--s7);}
.room--open+.room--wide{padding-top:var(--s6);}
/* A room that holds nothing but pictures needs no side margin at all. */
.room--folio{padding-block:var(--s7) var(--s8);}
.room--office{padding-block:var(--s8);}
.room--wide{padding-block:var(--s8) var(--s7);}
.key--wide{min-width:auto;}
.enquiry__say{position:relative;}
.pn-form{position:relative;}

/* ============================================================
   4. TYPOGRAPHY
   Nine tokens and nothing else. Every rule below names one of
   --fs-display / h1 / h2 / h3 / body-lg / body / small / caption
   / button, with the weight the scale assigns it. A rule that
   wants a tenth size wants the wrong size.
   ============================================================ */
h1,h2,h3,h4{font-family:var(--serif);}
[dir="rtl"] h1,[dir="rtl"] h2,[dir="rtl"] h3,[dir="rtl"] h4{font-family:var(--ar-display);}
/* A display line has to be allowed to break. At the token's floor of 3.5rem
   a long Arabic or German word would otherwise push the page sideways. */
.h-wall,.h-room,.lede{overflow-wrap:break-word;}
.room__name{
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--brand-deep);
  line-height:var(--lh-body);margin-bottom:var(--s4);
}
/* The hero heading carried no size of its own and inherited body copy. It is
   the page's H1 and takes the H1 token. */
.h-wall,.h-room{
  font-family:var(--serif);font-size:var(--fs-h2);font-weight:var(--fw-h2);
  line-height:var(--lh-h);letter-spacing:var(--tr-h);max-width:none;text-wrap:pretty;
}
.lede{
  font-family:var(--serif);font-size:var(--fs-h3);font-weight:var(--fw-h3);
  line-height:var(--lh-tight);letter-spacing:var(--tr-h);
  color:var(--ink);margin-top:var(--s4);text-wrap:pretty;
}
/* The paragraph that follows a heading is the one a reader actually reads on
   a phone, so it sits at body-large rather than body. */
.prose,.tally__item p,.faq__a p{
  font-size:var(--fs-body-lg);font-weight:var(--fw-body);line-height:var(--lh-body);color:var(--ink);
}
.prose{max-width:76ch;margin-top:var(--s3);color:var(--muted);text-wrap:pretty;}
.rubric{
  font-size:var(--fs-small);font-weight:var(--fw-button);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);margin-top:var(--s5);padding-bottom:var(--s2);line-height:var(--lh-body);
  border-bottom:2px solid var(--brand);
}
/* The heading is first in the source and the label is painted above it, so a
   crawler and a screen reader both meet the heading before the kicker. */
.wall{max-width:none;display:flex;flex-direction:column;}
.wall .room__name{order:-1;}
@media (min-width:1024px){
  .wall .h-wall,.wall .h-room{max-width:none;margin-bottom:var(--s4);}
  .wall .lede{max-width:64ch;margin-top:0;}
  .wall .prose{max-width:76ch;margin-top:var(--s3);}
}

/* ============================================================
   5. BUTTONS
   ============================================================ */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:52px;padding:.9rem 2.1rem;
  background:var(--brand-ink);color:var(--white);border:var(--rule) solid var(--brand-ink);
  font-family:var(--sans);font-size:var(--fs-button);font-weight:var(--fw-button);
  line-height:1.2;letter-spacing:.06em;text-transform:uppercase;
  cursor:pointer;transition:background var(--d-hover) var(--ease-out-2),border-color var(--d-hover) var(--ease-out-2);
}
[dir="rtl"] .btn{font-family:var(--ar-sans);}
.btn:hover{background:var(--brand-deep);border-color:var(--brand-deep);}
/* Turquoise carries every action on the page. Coral carries exactly one —
   the enquiry submit — which is what keeps it under 5% and keeps it
   meaning "this is the thing to press" rather than "this is decorated".
   Ink on coral, never white: white on coral is 2.78:1 and this is the one
   control that is not allowed to fail. */
.ask .btn,
.folio__acts .btn:not(.btn--line),
.ask .btn:hover,
.folio__acts .btn:not(.btn--line):hover,
.btn--send{
  width:100%;margin-top:var(--s5);
  background:var(--clay);color:var(--white);border-color:var(--clay);
}
.btn--send:hover{background:var(--brand-deep);border-color:var(--brand-deep);color:var(--white);}
.btn--quiet{background:transparent;color:var(--muted);border-color:var(--line);}
.btn--quiet:hover{background:transparent;border-color:var(--ink);color:var(--ink);}
.btn--line{background:transparent;color:var(--ink);border-color:var(--line);}
.btn--line:hover{background:var(--ink);color:var(--paper);border-color:var(--ink);}
.room--plan .key{border-color:var(--line-inv);color:var(--on-deep);}

.key{
  min-height:44px;min-width:44px;padding:.6rem 1.1rem;background:transparent;
  border:var(--rule) solid currentColor;color:inherit;cursor:pointer;
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.18em;text-transform:uppercase;line-height:1.2;
  transition:background var(--d-hover) var(--ease-out-2);
}
.key:hover{background:rgba(252,248,242,.12);}

/* ============================================================
   7. ARRIVAL
   Type on the ground, the photograph directly beneath it and
   inside the same screen. Nothing sits on top of anything.
   ============================================================ */
/* A picture pressed against a button reads as a background. The pause is
   what lets it be read as a photograph. */
/* The caption sits above the wave in the stack and clear of it in space: the
   wave is drawn over the bottom edge of the picture, so a caption tight to that
   edge reads as if it were cut by it even when nothing overlaps. */
@media (min-width:1024px){
  /* Capping the height turned a 1.78 picture into a 3.08 letterbox, which is
     not a gentle crop. Hanging the plate from the caption line instead keeps
     the whole frame and still puts it inside the first screen. */
  /* Full width, at its own proportions. The fold cuts it, which is an
     invitation to scroll rather than a crop of the photograph. */
  /* Capped so the opening picture and the line under it both sit inside the
     first screen. Left at its natural height it filled the viewport on a wide
     display and the caption fell below the fold. */
}

.broad{
  margin:0 calc(var(--gutter) * -1) var(--s6);
  overflow:hidden;
}
.broad img{width:100%;height:auto;}
.room--warm .broad{margin-top:var(--s6);}
/* On a wide screen a full bleed picture ran taller than the fold and pushed
   the reading down the page. Capping the height and letting the picture crop
   to it keeps the same width without the section becoming a scroll of its own. */
@media (min-width:1024px){
  .broad{max-height:44vh;}
  .broad img{height:44vh;object-fit:cover;object-position:center;}
}

/* ============================================================
   8. LEDGER
   ============================================================ */

/* ============================================================
   9. HANGING A WORK
   The picture keeps its own proportions and is given room. The
   wall card sits beside it on the caption line, never over it.
   ============================================================ */
.hang{display:grid;gap:var(--s5);}
.card{position:relative;display:flex;flex-direction:column;}
.card .room__name{margin-bottom:var(--s3);order:-1;}
/* The developer's mark sits beside the copy on a wide screen and under it on a
   narrow one. It is a brand mark, not a photograph, so it is capped rather than
   stretched and never fills its column. */
@media (min-width:1024px){
  .hang{grid-template-columns:1fr;row-gap:var(--s5);}
  .card{max-width:none;}
  .card .lede{max-width:64ch;}
  .card .prose{max-width:76ch;}
  .card .reckon{columns:2;column-gap:var(--s6);}
}
.reckon{margin-top:var(--s3);}
.reckon dt{padding-top:var(--s3);font-size:var(--fs-small);}
.reckon dd{margin:0;padding-bottom:var(--s3);border-bottom:var(--rule) solid var(--hair);
  font-size:var(--fs-caption);letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}

/* ============================================================
   10. TALLY
   ============================================================ */
.tally{margin-top:var(--s6);counter-reset:tally;}
.tally__item{counter-increment:tally;padding-block:var(--s4);border-top:var(--rule) solid var(--line);display:grid;gap:var(--s2);}
.tally__item::before{content:counter(tally,decimal-leading-zero);font-family:var(--num);font-size:var(--fs-caption);letter-spacing:.2em;color:var(--brand-deep);font-weight:var(--fw-button);}
.tally__item h3{font-family:var(--serif);font-size:var(--fs-body-lg);}
.tally__item p{color:var(--muted);max-width:70ch;text-wrap:pretty;}
@media (min-width:1024px){
  .tally{display:grid;grid-template-columns:1fr 1fr;column-gap:var(--s6);}
  .tally__item{grid-template-columns:3rem 1fr;align-items:start;}
  .tally__item::before{grid-row:span 2;padding-top:.4rem;}
  .tally__item p{grid-column:2;}
}

/* ============================================================
   11. RAILS
   One shape for every run of things: gallery plates and unit
   cards. Same frame, same gap, same controls, one size.
   ============================================================ */
.rail{position:relative;margin-top:var(--s6);}
.rail__track{
  display:flex;gap:var(--s3);
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;scroll-padding-inline:0;
  padding-bottom:var(--s3);
  scrollbar-width:thin;scrollbar-color:var(--line) transparent;
}
.rail__track.is-dragging{scroll-snap-type:none;cursor:grabbing;}
.rail__track:focus-visible{outline-offset:6px;}
.rail__keys{display:flex;gap:.5rem;margin-top:var(--s3);}
.rail__foot{
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);margin-top:var(--s3);flex-wrap:wrap;
}
.rail__foot .rail__keys{margin-top:0;}
.rail__foot .rail__hint{margin:0;}
.rail__key{
  width:52px;height:52px;display:grid;place-items:center;
  background:none;border:var(--rule) solid var(--line);color:var(--ink);
  cursor:pointer;transition:background var(--slow) var(--ease),color var(--slow) var(--ease);
}
.rail__key:hover:not(:disabled){background:var(--ink);color:var(--paper);}
.rail__key:disabled{opacity:.3;cursor:default;}
[dir="rtl"] .rail__key svg{transform:scaleX(-1);}

/* every plate the same frame */
/* ------------------------------------------------ the gallery
   One proportion, one size, wide gaps, no scrollbar. The pictures are the
   largest thing in the room and the run is pushed rather than clicked. */
.rail__track--gallery{
  gap:clamp(24px,4vw,48px);
  scrollbar-width:none;
  -ms-overflow-style:none;
  cursor:grab;
}
.rail__track--gallery::-webkit-scrollbar{display:none;}
.rail__track--gallery.is-dragging{cursor:grabbing;}
.rail__track img{-webkit-user-drag:none;user-select:none;}
.plate{margin:0;flex:0 0 clamp(280px,82vw,680px);scroll-snap-align:start;}
.plate img{
  width:100%;aspect-ratio:3/2;object-fit:cover;object-position:50% 45%;
  transition:transform .8s var(--ease);
}
@media (hover:hover){
  .plate:hover img{transform:translateY(-6px) scale(1.02);}
}
@media (min-width:700px){
  .plate{flex-basis:clamp(560px,46vw,680px);}
}
.rail__hint{
  display:flex;align-items:center;justify-content:center;gap:.9rem;
  margin-top:var(--s4);
  font-size:var(--fs-caption);letter-spacing:.22em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
.rail__hint span{font-family:var(--sans);opacity:.6;}
@media (prefers-reduced-motion:reduce){.plate img{transition:none;}}

/* every unit card the same frame, picture then figures then actions */
.room--warm .unit,.room--read .unit{background:var(--paper);}

/* No unit photography exists for this project, so the cards are typographic:
   the name is set at heading size against a terracotta rule, which gives the
   card the weight the photograph used to carry. A media block returns above
   this the moment real unit imagery is supplied, and nothing else changes. */
.unit .spec{margin:var(--s3) var(--s4) 0;border-top:var(--rule) solid var(--line);}
/* A mark against each spec row. Sized to the label, muted to the same weight,
   and inline-flex so it never disturbs the baseline of the type beside it. */
.unit .spec dt{display:flex;align-items:center;gap:.45em;}
.unit .spec dt svg{flex:0 0 auto;width:15px;height:15px;opacity:.55;}
.unit .spec>div{padding-block:.4rem;}
.unit .spec dt{font-size:var(--fs-caption);font-weight:var(--fw-button);}
.unit .spec .fig{font-size:var(--fs-body-lg);}
.unit__acts .btn{flex:1 1 auto;min-height:46px;padding:.7rem 1rem;font-size:var(--fs-caption);font-weight:var(--fw-button);}

.gal-slider{width:100%;}
/* The plans are portrait and taller than they are wide, so the image keeps its
   own ratio and is capped against the viewport rather than the dialog width:
   a full width portrait plan would otherwise run past the bottom of the screen. */
.lightbox__detail .spec{margin-top:0;}
@media (min-width:900px){
  .lightbox__detail .spec{border-top:0;display:contents;}
  .lightbox__detail .spec>div{display:grid;gap:.3rem;padding-block:var(--s3);
    border-top:var(--rule) solid var(--line);border-bottom:0;}
  .lightbox__detail .spec dd{text-align:start;}
}

/* ============================================================
   12. THE PLAN
   ============================================================ */
.plan__stage.is-dragging{cursor:grabbing;}
.plan__stage.is-zoomed{cursor:grab;}
.plan__stage:not(.is-zoomed){cursor:zoom-in;}
.plan__stage.is-zoomed{cursor:grab;}
.plan__inner.is-live{transition:none;}
@media (min-width:900px){
  /* The plan is a portrait drawing. It keeps its own shape and the legend
     stands beside it rather than under a very tall column. */
}

/* ============================================================
   13. COLLECTIONS
   ============================================================ */
.room{counter-reset:collection;}


/* ============================================================
   14. THE FILM
   ============================================================ */
.reel{position:relative;margin-top:var(--s6);background:var(--deep);}
/* The supplied film is a 720x1280 vertical cut. Poured into a full width
   block it was painted 1440 wide, which is twice its source and produced a
   2561px tall section that swallowed the page. It runs at its own shape,
   capped at the source width, inside a dark band. */
.reel--portrait .reel__cover img{width:100%;height:100%;object-fit:cover;}
.reel video{width:100%;height:auto;display:block;}
.reel__cover{position:static;width:100%;padding:0;border:0;background:none;cursor:pointer;}
.js .reel__cover{position:absolute;inset:0;}
html:not(.js) .reel video{display:block;}
.reel__cover img{width:100%;height:100%;object-fit:cover;}
.reel__cover.is-gone{display:none;}
.reel__blocked{
  position:absolute;left:50%;bottom:12%;transform:translateX(-50%);
  width:min(84%,34ch);text-align:center;
  background:rgba(11,58,71,.88);color:var(--paper);
  font-family:var(--sans);font-size:var(--fs-small);line-height:1.5;
  padding:.7rem .9rem;border-radius:2px;
}
.reel__go{position:absolute;inset-inline-start:50%;top:50%;transform:translate(-50%,-50%);
  width:76px;height:76px;display:grid;place-items:center;border-radius:50%;
  background:rgba(252,248,242,.92);color:var(--deep);transition:opacity var(--slow) var(--ease);}
[dir="rtl"] .reel__go{transform:translate(50%,-50%);}

/* ============================================================
   15. TERMS
   ============================================================ */
.terms{margin-top:var(--s5);}
.terms>div{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s4);
  padding-block:var(--s4);border-top:var(--rule) solid var(--line);}
.terms dt{font-size:var(--fs-caption);letter-spacing:.18em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
.terms dd{margin:0;font-family:var(--serif);font-size:var(--fs-h2);line-height:1;}
.terms dd i{font-style:normal;font-size:var(--fs-small);margin-inline-start:.1em;}
@media (min-width:1024px){
  /* The card spans both columns, which is why the measure was removed. But
     a full 1360px column sets body copy at about 145 characters a line —
     twice a comfortable measure, and the one place on the page where the
     prose stops looking set. It spans the grid and still holds a measure. */
  .card--plain .prose{max-width:72ch;}
  .terms{grid-column:1 / -1;margin-top:var(--s5);}
}

/* ============================================================
   16. THE OFFICE
   ============================================================ */
.enquiry{display:grid;gap:var(--s6);}
.direct{display:flex;flex-wrap:wrap;gap:var(--s4);margin-top:var(--s5);}
.direct a{min-height:44px;min-width:44px;display:inline-flex;align-items:center;gap:.6rem;
  font-size:var(--fs-caption);letter-spacing:.16em;text-transform:uppercase;
  border-bottom:var(--rule) solid var(--line);font-weight:var(--fw-button);}
.direct a:hover{border-color:var(--ink);}
.direct__where{margin-top:var(--s4);font-size:var(--fs-small);color:var(--muted);}
.fields{display:grid;gap:var(--s4);}
.cell{display:grid;gap:.35rem;}
.cell>span{font-size:var(--fs-caption);letter-spacing:.18em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
.cell input,.cell select,.cell textarea,
.pn-form--plugin input[type="text"],.pn-form--plugin input[type="tel"],
.pn-form--plugin input[type="email"],.pn-form--plugin select,.pn-form--plugin textarea{
  width:100%;min-height:48px;padding:.7rem 0;background:none;color:var(--ink);
  border:0;border-bottom:var(--rule) solid var(--line);border-radius:0;
  transition:border-color var(--slow) var(--ease);
}
.cell textarea,.pn-form--plugin textarea{min-height:96px;resize:vertical;}
/* The select was the only control still wearing the operating system. The
   element stays native to the keyboard and to assistive technology; only the
   arrow is drawn, so the form reads as one piece. */
.cell select,.phone-combo__cc{
  appearance:none;-webkit-appearance:none;
  padding-inline-end:1.8rem;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-size:6px 6px,6px 6px;
  background-position:right 0.75rem center,right 0.42rem center;
  background-repeat:no-repeat;
}
[dir="rtl"] .cell select,[dir="rtl"] .phone-combo__cc{
  padding-inline-end:1.8rem;
  background-position:left 0.42rem center,left 0.75rem center;
  background-image:linear-gradient(135deg,transparent 50%,currentColor 50%),
                   linear-gradient(45deg,currentColor 50%,transparent 50%);
}
.cell input:focus,.cell select:focus,.cell textarea:focus{border-color:var(--brand-deep);}
.phone-combo{display:grid;grid-template-columns:auto 1fr;gap:var(--s2);align-items:end;}
.phone-combo__cc{max-width:9.5rem;}
.agree{display:flex;align-items:flex-start;gap:.7rem;font-size:var(--fs-small);color:var(--muted);}
/* 24px is the floor for a pointer target. The label is clickable too, but the
   box itself is what a reader aims at, and it was 20. */
.agree input{width:24px;height:24px;flex:0 0 24px;margin-top:.2rem;accent-color:var(--brand-deep);}
.hp{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;}
.form-msg{margin-top:var(--s3);font-size:var(--fs-small);min-height:1.4em;}
.form-msg.is-ok{color:var(--brand-ink);} .form-msg.is-err{color:#1E7167;}
.pn-form--plugin input[type="submit"],.pn-form--plugin button[type="submit"]{
  min-height:52px;padding:.9rem 2rem;background:transparent;color:var(--ink);
  border:var(--rule) solid var(--ink);cursor:pointer;letter-spacing:.18em;text-transform:uppercase;}
@media (min-width:1024px){
  .enquiry{grid-template-columns:1fr 1fr;column-gap:var(--s6);align-items:start;}
  .enquiry__say{grid-column:1 / -1;}
  .pn-form{grid-column:1 / -1;}
  .enquiry__say .h-wall{margin-bottom:var(--s4);}
  .fields{grid-template-columns:1fr 1fr;column-gap:var(--s4);}
  .cell--wide,.agree{grid-column:1 / -1;}
}

/* ============================================================
   17. FAQ
   ============================================================ */
.faq{margin-top:var(--s5);border-top:var(--rule) solid var(--line);counter-reset:faq;}
.faq__item{border-bottom:var(--rule) solid var(--hair);counter-increment:faq;}
.faq summary{display:flex;gap:var(--s4);align-items:baseline;cursor:pointer;list-style:none;
  padding-block:var(--s4);font-family:var(--serif);font-size:var(--fs-body-lg);}
.faq summary::-webkit-details-marker{display:none;}
.faq summary::before{content:counter(faq,decimal-leading-zero);font-family:var(--num);
  font-size:var(--fs-caption);letter-spacing:.2em;color:var(--brand-deep);flex:0 0 2.2rem;line-height:2.4;font-weight:var(--fw-button);}
.faq__a{padding:0 0 var(--s4) calc(2.2rem + var(--s4));}
[dir="rtl"] .faq__a{padding:0 calc(2.2rem + var(--s4)) var(--s4) 0;}
.faq__a p{color:var(--muted);max-width:82ch;text-wrap:pretty;}
.faq__item[open] summary{color:var(--brand-ink);}
@media (min-width:1024px){
  .faq{max-width:none;}
}

/* ============================================================
   19. FALLBACK PAGES
   ============================================================ */
.section{padding-block:var(--s7);}
.prose h1{font-family:var(--serif);font-size:var(--fs-h2);max-width:20ch;}
.prose__body{max-width:64ch;margin-top:var(--s4);color:var(--muted);}
.prose__cta{margin-top:var(--s5);}
.prose__nav{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:var(--s5);padding-top:var(--s3);
  border-top:var(--rule) solid var(--line);}
.prose__nav a{min-height:44px;min-width:44px;display:inline-flex;align-items:center;
  font-size:var(--fs-caption);letter-spacing:.16em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
.label{display:block;font-size:var(--fs-caption);font-weight:var(--fw-button);letter-spacing:.28em;
  text-transform:uppercase;color:var(--muted);margin-bottom:var(--s3);}

/* ============================================================
   20. MOTION
   Ranked by what each piece of the page has to explain. The
   easing curves are GSAP's, read off its easing definitions
   rather than lifted from one of its demos; the durations and
   the sequencing are this site's.
   ============================================================ */
/* Motion is ranked, not sprinkled. A section gets one arrival, a card answers
   a pointer, a figure counts because the figure means something, and the hero
   gets the only cinematic moment on the site. Anything that does not help the
   reader understand sequence is not here.

   Two budget rules govern all of it:
   - Only opacity and transform are animated. Neither triggers layout, so the
     reveal cannot contribute to CLS however many sections are on the page.
   - Nothing is hidden unless JavaScript has confirmed it is running. The
     hidden state hangs off .js, and main.js shows everything unconditionally
     after four seconds, so a failed script leaves a fully readable page
     rather than a blank one. */

/* ---- the arrival: drop and settle
   Not a slide. The element comes down from a little above its place, passes
   it by two or three pixels, and settles back — which is what anything with
   mass does when it lands, and what separates this from the 20px rise every
   other page uses. The overshoot is deliberately under conscious notice.

   --gl-y and --gl-d let one keyframe serve every weight: the distance and
   the duration change with the mass of the thing arriving, the shape of the
   motion does not. --gl-delay is written by main.js, which computes the
   stagger rather than multiplying an index by a constant. */
@keyframes gl-settle{
  0%   {opacity:0;transform:translate3d(0,calc(var(--gl-y,16px) * -1),0);}
  58%  {opacity:1;transform:translate3d(0,2.5px,0);}
  100% {opacity:1;transform:none;}
}

.js .reveal{opacity:0;}
.js .reveal.is-in{
  animation:gl-settle var(--gl-d,var(--d-l)) var(--e-settle) both;
  animation-delay:var(--gl-delay,0ms);
}
/* Weight classes. A photograph does not arrive at the speed of a caption. */
.js .reveal--xl.is-in{--gl-d:var(--d-xl);--gl-y:26px;}
.js .reveal--l.is-in {--gl-d:var(--d-l); --gl-y:20px;}
.js .reveal--m.is-in {--gl-d:var(--d-m); --gl-y:15px;}
.js .reveal--s.is-in {--gl-d:var(--d-s); --gl-y:10px;}

/* Children arrive on a stagger main.js computes: the gaps compress as the
   group fills rather than repeating one constant, and each element carries a
   few milliseconds of its own derived from its index — never from a random
   number, so the sequence is identical on every load. */
.js .reveal [data-stagger]>*{opacity:0;}
.js .is-in [data-stagger]>*,
.js [data-stagger].is-in>*{
  animation:gl-settle var(--gl-d,var(--d-m)) var(--e-settle) both;
  animation-delay:var(--gl-delay,0ms);
  --gl-y:13px;
}

/* ---- hero: the one cinematic entrance
   Self-completing, so it needs no JavaScript to finish and cannot strand the
   masthead or the headline at opacity 0. The photograph is the heaviest thing
   on the page and settles last. */
@keyframes gl-arrive{
  0%   {opacity:0;transform:translate3d(0,-18px,0) scale(.988);}
  60%  {opacity:1;transform:translate3d(0,3px,0) scale(1);}
  100% {opacity:1;transform:none;}
}
.js .arrival__type{animation:gl-arrive var(--d-l) var(--e-settle) both;}
.js .arrival__plate{animation:gl-arrive var(--d-xl) var(--e-drift) both;animation-delay:90ms;}

/* ---- page: a fade and nothing more */
@keyframes gl-page{from{opacity:0;}to{opacity:1;}}
.js body{animation:gl-page var(--d-page) var(--ease-out-2) both;}

/* ---- cards: a restrained lift, no scale
   6px and a shadow is a card acknowledging the pointer. A scale is a card
   asking for attention it has not earned. */
.card{transition:transform var(--d-hover) var(--e-lift),box-shadow var(--d-hover) var(--e-lift);}
@media (hover:hover){
  .card:hover{transform:translate3d(0,-6px,0);box-shadow:0 14px 30px rgba(36,26,17,.11);}
}
.card:focus-within{transform:translate3d(0,-6px,0);box-shadow:0 14px 30px rgba(36,26,17,.11);}

/* ---- the wave, once
   Earned rather than decorative: it is the edge between the hero photograph
   and the page below it, which is the one place on the site where a coastline
   is literally what the reader is looking at. It is a static mask, not an
   animation, and it is drawn as an inline data URI so it costs no request. */
/* The wave has to be painted in whatever colour follows it, and the hero can
   only look forward with :has(). Where that is unsupported the fill stays
   --paper, which is the common case anyway. */

[data-drift]{overflow:hidden;}
[data-drift] img{will-change:transform;}

/* Every animation on the site, without exception, stops here. */
@media (prefers-reduced-motion:reduce){
  .js .reveal,.js .reveal.is-in,
  .js .reveal [data-stagger]>*,
  .js .is-in [data-stagger]>*,
  .js [data-stagger].is-in>*{
    opacity:1;transform:none;transition:none;animation:none;
  }
  .js .arrival__type,.js .arrival__plate,.js body{animation:none;}
  /* The descent stops being scroll-driven and becomes a plain stack. */
  [data-drift] img{transform:none!important;}
  .card,.btn,.key{transition:none!important;}
  .card:hover,.card:focus-within{transform:none;box-shadow:none;}
}

/* ============================================================
   6. MASTHEAD
   Set like a publication's masthead: a hairline, the mark
   centred beneath it, and the two controls out in the margins.
   The section list is not here; it opens as a full page index.
   ============================================================ */
.logo__by{font-size:var(--fs-caption);letter-spacing:.22em;text-transform:uppercase;color:var(--muted);margin-inline-start:.5rem;font-weight:var(--fw-button);}
/* The switcher shows the OTHER language, so it is sized by its own lang
   attribute rather than by the direction of the page it sits on. */
/* Both controls in the masthead were set at .66rem, which is smaller than any
   other text on the page and read as fine print rather than as the two things
   a visitor is meant to press. They are larger now, and the contents toggle is
   drawn as a bordered control so it looks pressable rather than decorative. */

/* ------------------------------------------------ the index page */
.index-page{
  position:fixed;inset:0;z-index:100;background:var(--paper);color:var(--ink);
  display:grid;grid-template-rows:1fr auto;
  padding:var(--s7) var(--gutter) var(--s5);
  opacity:0;visibility:hidden;
  transition:opacity .6s var(--ease),visibility .6s;
}
.index-page.is-open{opacity:1;visibility:visible;}
.index-page__inner{align-self:center;width:100%;max-width:var(--frame);margin-inline:auto;}
.index-page__cap{
  font-size:var(--fs-caption);font-weight:var(--fw-button);letter-spacing:.34em;text-transform:uppercase;
  color:var(--muted);padding-bottom:var(--s3);border-bottom:var(--rule) solid var(--line);
}
.index-page__list{display:flex;flex-direction:column;counter-reset:idx;}
.index-page__list a{
  counter-increment:idx;
  display:grid;grid-template-columns:3.4rem 1fr;align-items:baseline;
  min-height:56px;padding-block:var(--s2);
  border-bottom:var(--rule) solid var(--hair);
  transition:color .5s var(--ease);
}
.index-page__list a:hover{color:var(--brand-ink);}
.index-page__list a::before{content:counter(idx,decimal-leading-zero);
  font-family:var(--num);font-size:var(--fs-caption);letter-spacing:.2em;color:var(--brand-deep);font-weight:var(--fw-button);}
.index-page__list a{font-family:var(--serif);font-size:var(--fs-h2);line-height:1.1;}
.index-page__lang{
  display:inline-flex;align-items:center;min-height:44px;min-width:44px;margin-top:var(--s4);
  font-size:var(--fs-caption);letter-spacing:.24em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
.index-page__close{
  position:absolute;top:var(--s4);inset-inline-end:var(--gutter);
  width:52px;height:52px;display:grid;place-items:center;
  background:none;border:var(--rule) solid var(--line);color:var(--ink);
  cursor:pointer;transition:background var(--slow) var(--ease),color var(--slow) var(--ease);
}
.index-page__close:hover{background:var(--ink);color:var(--paper);}
@media (min-width:900px){
  .index-page__list{
    display:grid;grid-template-columns:1fr 1fr;column-gap:var(--s7);
  }
}

/* ============================================================
   18. COLOPHON
   The page ends the way a publication ends: the mark set large,
   one line of imprint, the contents once across the width, and
   the legal line last. No column grid, no icon row.
   ============================================================ */
.colophon{background:var(--deep);color:var(--paper);padding-block:var(--s5) var(--s4);}
.colophon__mark{display:block;}
.colophon__mark img{height:clamp(38px,4.6vw,54px);width:auto;}
.colophon__mark .logo__by{color:rgba(168,198,206,.55);}
.colophon__mark .logo__name{font-family:var(--serif);font-size:var(--fs-h1);}
.colophon__imprint{
  margin-top:var(--s3);max-width:60ch;
  font-family:var(--serif);font-size:var(--fs-body);line-height:1.5;
  color:rgba(252,248,242,.8);
}
.colophon__reach{display:flex;gap:.5rem;margin-top:var(--s4);}
.reach{
  width:52px;height:52px;display:grid;place-items:center;
  border:var(--rule) solid var(--line-inv);color:var(--paper);
  transition:background .5s var(--ease),color .5s var(--ease),border-color .5s var(--ease);
}
.reach:hover{background:var(--paper);color:var(--deep);border-color:var(--paper);}
.reach--wa:hover{background:#227E72;color:#fff;border-color:#227E72;}
.colophon__social{display:flex;gap:.5rem;margin-top:var(--s3);}
.colophon__social a{
  width:44px;height:44px;display:grid;place-items:center;
  border:var(--rule) solid var(--line-inv);color:var(--paper);
}
.colophon__social a:hover{background:var(--paper);color:var(--deep);}
.colophon__legal{
  margin-top:var(--s4);padding-top:var(--s3);
  border-top:var(--rule) solid var(--line-inv);
  font-size:var(--fs-caption);color:rgba(252,248,242,.46);font-weight:var(--fw-body);}
@media (min-width:1024px){
  .colophon .frame{
    display:grid;grid-template-columns:minmax(28ch,1fr) auto;
    column-gap:var(--s6);row-gap:var(--s4);align-items:start;
  }
  .colophon__mark{grid-column:1;}
  .colophon__imprint{grid-column:1;max-width:56ch;}
  .colophon__reach{grid-column:2;grid-row:1 / 3;justify-self:end;margin-top:0;}
  .colophon__social{grid-column:1;}
  .colophon__legal{grid-column:1 / -1;}
}

/* ------------------------------------------------ one standing action */
.standing{display:none;}
@media (min-width:901px){
  .standing{
    display:flex;flex-direction:column;gap:.55rem;
    position:fixed;inset-inline-end:var(--s3);top:50%;z-index:80;
    transform:translateY(-50%);
    background:none;border:0;box-shadow:none;
    transition:transform var(--slow) var(--ease),opacity var(--slow) var(--ease);
  }
  .standing.is-away{opacity:0;transform:translateY(-50%) translateX(100%);pointer-events:none;}
  [dir="rtl"] .standing.is-away{transform:translateY(-50%) translateX(-100%);}
  /* Three marks of equal weight. None of them outranks the others.
     Ink on the page, turquoise only on hover: three standing turquoise
     discs read as a warning rather than an invitation, and the accent is
     worth more spent on the action being taken. */
  /* Geometry only. The colour is set once, outside this query, so the rail
     cannot drift between breakpoints again. */
  .standing a{
    width:52px;height:52px;display:grid;place-items:center;
    font-size:0;line-height:0;overflow:hidden;
  }
}
.dock{
  position:fixed;inset-inline:0;bottom:0;z-index:80;
  padding-bottom:env(safe-area-inset-bottom);
  display:grid;grid-template-columns:repeat(3,1fr);
  background:var(--brand-deep);
  border-top:0;
  box-shadow:0 -14px 34px -26px rgba(11,58,71,.5);
  transition:transform var(--slow) var(--ease);
}
.dock.is-away{transform:translateY(100%);}
.burger{color:inherit;}
.dock__call,.dock__wa,.dock__go,.standing__act,.cta-rail__wa{color:inherit;}
.dock a{
  min-height:var(--dock-h);display:flex;align-items:center;justify-content:center;
  color:var(--paper);background:none;
  border-inline-end:var(--rule) solid rgba(252,248,242,.22);
}
.dock a:last-child{border-inline-end:0;}
.dock a:active{background:var(--brand-deep);}
@media (max-width:900px){:root{--dock-h:62px;}}
@media (min-width:901px){.dock{display:none;}}
@media (max-width:900px){body{padding-bottom:calc(var(--dock-h) + env(safe-area-inset-bottom));}}

/* ============================================================
   21. ARABIC
   ============================================================ */
body.pn-ar{direction:rtl;}
/* Arabic takes its own faces. The numeric stack is left alone so figures stay
   tabular and line up down the page. */
[dir="rtl"] body,body.pn-ar{font-family:var(--ar-sans);}
[dir="rtl"] .wordmark,[dir="rtl"] .h-wall,[dir="rtl"] .h-room,[dir="rtl"] .lede,[dir="rtl"] .arrival__line,[dir="rtl"] .faq summary,[dir="rtl"] .terms dd,[dir="rtl"] .tally__item h3,[dir="rtl"] .colophon__imprint{
  font-family:var(--ar-display);
}
[dir="rtl"] .room__name,[dir="rtl"] .rubric,[dir="rtl"] .btn,[dir="rtl"] .key,[dir="rtl"] .rail__hint,[dir="rtl"] .cell>span,[dir="rtl"] .spec dt,[dir="rtl"] .terms dt{
  font-family:var(--ar-sans);
}
/* The Arabic page swaps both families. Figures keep the numeric face, because
   the digits are Latin and are compared against one another. */
[dir="rtl"] body,[dir="rtl"] .prose,[dir="rtl"] p,[dir="rtl"] li,[dir="rtl"] dt,[dir="rtl"] dd,[dir="rtl"] label,[dir="rtl"] input,[dir="rtl"] select,[dir="rtl"] textarea,[dir="rtl"] .btn,[dir="rtl"] .key,[dir="rtl"] .room__name,[dir="rtl"] .rubric,[dir="rtl"] .nav a,[dir="rtl"] .rail__hint{font-family:var(--ar-sans);}
[dir="rtl"] .wordmark,[dir="rtl"] .h-wall,[dir="rtl"] .h-room,[dir="rtl"] .lede,[dir="rtl"] .arrival__line,[dir="rtl"] .terms dd,[dir="rtl"] .faq summary,[dir="rtl"] .tally__item h3,[dir="rtl"] .colophon__imprint{font-family:var(--ar-display);}
[dir="rtl"] .fig,[dir="rtl"] .faq summary::before{font-family:var(--num);}
/* Arabic letterforms carry their own rhythm; tracking meant for Latin caps
   pulls them apart. */
[dir="rtl"] .room__name,[dir="rtl"] .rubric,[dir="rtl"] .rail__hint{letter-spacing:.08em;}
[dir="rtl"] .wordmark,[dir="rtl"] .h-wall,[dir="rtl"] .h-room{letter-spacing:0;line-height:1.3;}
[dir="rtl"] .h-wall,[dir="rtl"] .h-room,[dir="rtl"] .wordmark{font-weight:var(--fw-h2);}
[dir="rtl"] .display,[dir="rtl"] .wordmark,[dir="rtl"] h1,[dir="rtl"] h2,
[dir="rtl"] h3,[dir="rtl"] h4{letter-spacing:0;line-height:1.28;}
[dir="rtl"] .wordmark{line-height:1.02;}
[dir="rtl"] [dir="rtl"] [dir="rtl"] .lede{}
[dir="rtl"] .index,[dir="rtl"] .rubric,[dir="rtl"] .spec dt,[dir="rtl"] .terms dt,[dir="rtl"] .cell>span{letter-spacing:.06em;}
[dir="rtl"] .wordmark__b{letter-spacing:.16em;}
[dir="rtl"] .btn,[dir="rtl"] .key,[dir="rtl"] .nav a,[dir="rtl"] .lang,
[dir="rtl"] .direct a,[dir="rtl"] .mbar a,[dir="rtl"] .cta-rail a{letter-spacing:.04em;}
/* Values that are only ever figures stay left to right. */
[dir="rtl"] .terms dd,[dir="rtl"] .phone-combo input,
[dir="rtl"] .cell input[type="email"]{
  direction:ltr;unicode-bidi:isolate;text-align:start;
}
/* These hold a figure on one row and an Arabic sentence on the next, so the
   direction is inherited and the run is isolated instead of forced. */
[dir="rtl"] .reckon dd,[dir="rtl"] .spec dd{
  unicode-bidi:isolate;text-align:start;
}
[dir="rtl"] .spec dd{text-align:end;}


/* ============================================================
   RESIDENCES AS A GRID
   Two cards per collection do not overflow a desktop rail, so the
   arrows had nothing to scroll and sat there dead. The collection
   is a grid instead: everything visible, nothing to push.
   ============================================================ */


/* ============================================================
   HORIZONTAL FIRST
   The house rule for this build and the ones after it: read
   across before reading down. Everything that was a stack of
   full width rows becomes a run of columns on a desktop and a
   snap rail on a phone, so a thumb moves sideways instead of
   scrolling past twelve identical bands.
   ============================================================ */

/* --- the eight figures: a row, not a list ------------------- */

/* --- the amenities: three across, a rail on a phone --------- */
@media (max-width:759px){
  .tally{
    display:flex;gap:var(--s3);overflow-x:auto;
    scroll-snap-type:x proximity;overscroll-behavior-x:contain;
    padding-bottom:var(--s3);scrollbar-width:none;
  }
  .tally::-webkit-scrollbar{display:none;}
  .tally__item{
    flex:0 0 76%;scroll-snap-align:start;
    border-top:var(--rule) solid var(--line);
  }
}
@media (min-width:760px){
  .tally{display:grid;grid-template-columns:repeat(2,1fr);column-gap:var(--s5);}
}
@media (min-width:1100px){
  .tally{grid-template-columns:repeat(3,1fr);column-gap:var(--s5);}
}

/* --- the questions: two columns of answers ------------------ */
@media (min-width:1024px){
  .faq{columns:2;column-gap:var(--s6);}
  .faq__item{break-inside:avoid;}
}

/* --- the payment terms: a row of four ----------------------- */
@media (min-width:760px){
  .terms{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s4);}
  .terms>div{
    display:block;padding-block:var(--s3) var(--s4);
    border-top:var(--rule) solid var(--line);
  }
  .terms>div dt{font-size:var(--fs-caption);letter-spacing:.16em;text-transform:uppercase;color:var(--muted);font-weight:var(--fw-button);}
  .terms>div dd{margin:.4rem 0 0;font-family:var(--num);font-size:var(--fs-h2);line-height:1;}
}

/* --- picture beside its card, not above it ------------------ */
@media (min-width:1024px){
  .hang{grid-template-columns:1.15fr .85fr;column-gap:var(--s6);align-items:center;}
  .hang--dev{grid-template-columns:1fr minmax(0,320px);column-gap:var(--s6);align-items:center;}
}

/* --- the residences: a rail on a phone, a pair on a desktop -- */

/* --- the distances table reads across ----------------------- */
@media (min-width:760px){
  .hang__map + .card .ledger{grid-template-columns:repeat(2,1fr);}
}


/* --- masthead on a narrow phone ----------------------------
   The horizontal lockup is wider than the stacked one it
   replaced, and at 390px it walked straight into the contents
   label. The mark shrinks and the word "contents" drops to its
   rule, which is what the burger already means. */
@media (max-width:600px){
  /* The comment above says the word drops to its rule on a phone; it never
     did, and the English label pushed the masthead 3px past the viewport at
     390. The burger already carries the meaning, so the word goes and the
     accessible name is kept on the button. */
}


/* --- the arrival on a phone --------------------------------
   94svh reserved a screen the type did not fill, so the two
   actions floated in the middle of nothing and the photograph
   sat below the fold twice over. The screen is given back to
   the picture, and the two actions sit side by side. */
@media (max-width:759px){
  /* Still one screen, as the arrival is meant to be, but the rows are
     sized by their content so the picture takes the slack instead of a gap. */
}


/* ============================================================
   HORIZONTAL, FURTHER
   The remaining verticality was the head of every section: a
   label, a heading, a standfirst and two paragraphs, each one
   full width and stacked. They now sit as two columns, so the
   reader crosses the page before dropping down it.
   ============================================================ */
@media (min-width:1024px){
  .wall{
    display:grid;
    grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
    column-gap:var(--s6);align-items:start;
  }
  .wall .room__name{grid-column:1;grid-row:1;order:0;margin-bottom:var(--s2);}
  .wall .h-wall,.wall .h-room{grid-column:1;grid-row:2;margin-bottom:0;max-width:none;}
  .wall .lede{grid-column:2;grid-row:2;margin-top:0;max-width:48ch;}
  .wall .prose{grid-column:2;max-width:64ch;margin-top:var(--s3);}
}

/* the card head, same treatment */
@media (min-width:1024px){
  .card:not(.card--plain) .lede{max-width:48ch;}
  .ledgerwall .card{display:grid;grid-template-columns:1fr;}
}

/* --- four across where there is room ------------------------ */
@media (min-width:1420px){
  .tally{grid-template-columns:repeat(4,1fr);}
}
@media (min-width:1420px){
  .faq{columns:3;}
}

/* --- the gallery runs wider plates so fewer bands are needed - */
@media (min-width:1024px){
  .plate{flex-basis:clamp(520px,38vw,700px);}
}

/* --- amenity rail on tablets too, not just phones ----------- */
@media (min-width:760px) and (max-width:1023px){
  .tally{grid-template-columns:repeat(2,1fr);column-gap:var(--s4);}
}

/* --- the enquiry form fields sit across ---------------------- */
@media (min-width:760px){
  .fields{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s3) var(--s4);}
  .cell--wide{grid-column:1 / -1;}
}


/* ============================================================
   RESIDENCE CARDS ON A PHONE
   The spec list stacked its label above its value, so each of the
   six rows cost two lines and a card ran past 1300px on an 844px
   screen. A card taller than the screen cannot be compared with
   the one beside it, which is the whole point of a rail. The rows
   read across now, which halves the card and matches the standing
   rule that this site lays out horizontally rather than stacking.
   ============================================================ */
@media (max-width:759px){
  .unit .spec>div{
    display:grid;grid-template-columns:1fr auto;
    align-items:baseline;gap:var(--s2);
    padding-block:.55rem;
    border-bottom:var(--rule) solid var(--hair);
  }
  .unit .spec>div:last-child{border-bottom:0;}
  .unit .spec dt{margin:0;font-size:var(--fs-caption);line-height:1.3;font-weight:var(--fw-body);}
  .unit .spec dd{margin:0;text-align:end;font-size:var(--fs-small);line-height:1.35;}
  .unit .spec .fig{font-size:var(--fs-body);}
  /* 82% left a clipped sliver of the next card with two letters of its
     heading showing. 86% with the gutter as scroll padding shows a clean
     edge instead, and still says there is another card. */
}


/* ============================================================
   THE TWO BANDS
   The page is white. Two kinds of band are laid across it, and
   they are no longer the same band: --plan carries the deep teal
   that gives the photography something to sit against, and --warm
   carries sand, which is where the palette's 20% is actually
   spent. Under the previous identity both were dark, so pointing
   --warm at sand without splitting these rules would have left
   pale-on-pale text across the whole section.
   ============================================================ */
.room--plan .prose,.room--plan .lede,.room--plan .tally__item p{color:var(--on-deep-muted);}
.room--plan .tally__item h3{color:var(--on-deep);}
.room--plan .room__name{color:var(--sea-text);}
.room--plan .h-room,.room--plan .h-wall{color:var(--on-deep);}
.room--plan .key{border-color:var(--line-inv);color:var(--on-deep);}
.room--plan .key:hover{background:var(--deep-2);}
/* Buttons and keys carry their own ground and their own measured text
   colour, so the band's link rule must not reach them: .room--x a beats .btn
   on specificity and would repaint a turquoise button in link colour. */
.room--plan a:not(.btn):not(.key):not(.rail__key){color:var(--sea-text);}

/* Sand is a light ground, so it takes the page's own ink rather than the
   inverted set. Ink on sand is 14.1:1, muted 5.2:1, turquoise-as-text 4.6:1. */
.room--warm{background:var(--band);color:var(--ink);}
.room--warm .prose,.room--warm .lede,
.room--warm .tally__item p,
.room--warm .card__note,
.room--warm .cap,
.room--warm .ledger__d,
.room--warm dt{color:var(--muted);}
.room--warm .tally__item h3,
.room--warm .ledger__v,
.room--warm dd{color:var(--ink);}
.room--warm .room__name{color:var(--muted);}
.room--warm .h-room,.room--warm .h-wall{color:var(--ink);}
.room--warm .legend__t{color:var(--ink);}
.room--warm .key{border-color:var(--line);color:var(--ink);}
.room--warm .key:hover{background:rgba(36,26,17,.06);}
.room--warm a:not(.btn):not(.key):not(.rail__key){color:var(--brand-deep);}

.colophon{background:var(--deep);color:var(--on-deep);}
.colophon a{color:var(--on-deep);}
.colophon .logo__name,.colophon__mark .logo__name{color:var(--on-deep);}
.colophon .prose,.colophon p{color:var(--on-deep-muted);}

/* The map plate sits on the dark band, so it needs no surface of its own. */


/* ============================================================
   THE ENQUIRY, SET INTO THE PAGE
   The form read as one more section in the column. It is now a
   recessed panel in its own colour, so the eye finds it without
   having to be told, and so the page ends on an action rather
   than on more reading.
   ============================================================ */

.room--office{
  background:var(--paper-2);
  border-block:var(--rule) solid var(--line);
}
.room--office .frame{
  background:var(--paper-3);
  border:var(--rule) solid var(--line);
  border-radius:3px;
  padding:clamp(28px,4vw,64px);
  box-shadow:0 1px 0 rgba(36,26,17,.04), 0 24px 60px -40px rgba(36,26,17,.5);
}
.room--office .h-room,.room--office .h-wall{color:var(--ink);}
.room--office .room__name{color:var(--brand-deep);}
.room--office .prose,.room--office .lede{color:var(--muted);}

/* ============================================================
   ICON CONTROLS
   Every icon-only control gets a real target and a state that
   says it is pressable. An icon with no affordance reads as
   decoration, which is the reported symptom.
   ============================================================ */

a:has(> svg.icon:only-child),
button:has(> svg.icon:only-child),
.reach a,.dock a,.rail__key{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;
  cursor:pointer;
}
.reach a:hover,.dock a:hover,.rail__key:hover:not(:disabled){
  transform:translateY(-1px);
}
.reach a:focus-visible,.dock a:focus-visible,.rail__key:focus-visible{
  outline:2px solid var(--brand-deep);outline-offset:3px;
}
svg.icon{pointer-events:none;}


/* ============================================================
   SCALE AND DENSITY
   The page was reading as though the browser were zoomed in: the
   body ran at 1.22rem with 1.78 leading, so a paragraph filled the
   screen and the reader had to scroll to find the next fact. Body
   copy comes down to 1rem, the measure comes in, and the vertical
   rhythm tightens. The page gets shorter without losing anything.
   ============================================================ */

body{font-size:var(--fs-body);line-height:1.65;}
.prose,.tally__item p,.faq__a p{
  font-size:var(--fs-body);line-height:1.72;max-width:64ch;
}
.lede,.arrival__line{font-size:var(--fs-body-lg);line-height:1.55;max-width:52ch;}

/* Sections were built on a scale that no longer applies. */
:root{
  --s3:clamp(.75rem,1.1vw,1rem);
  --s4:clamp(1.1rem,1.7vw,1.6rem);
  --s5:clamp(1.7rem,2.6vw,2.4rem);
  --s6:clamp(2.4rem,4vw,3.6rem);
}
.room{padding-block:clamp(48px,6vw,96px);}

/* The footer was a full screen of its own with dead space under it. */
.colophon{padding-block:clamp(32px,4vw,52px) clamp(20px,2vw,28px);}
.colophon__mark .logo__name{font-size:var(--fs-h3);}
.colophon p,.colophon li,.colophon a{font-size:var(--fs-small);line-height:1.6;}
body>:last-child{margin-block-end:0;}
.colophon:last-child{margin-block-end:0;padding-block-end:clamp(18px,2vw,26px);}

/* ============================================================
   FORM FIELDS
   Every field was a bare underline on the page ground, so the
   reader could not see where one ended and the next began. Each
   is a filled box now, with its label above it and a visible
   focus state, which is what tells someone this is fillable.
   ============================================================ */

.room--office .frame{background:var(--paper-3);}

.field{margin-block-end:var(--s4);}
.field > span,.field label,.enquiry label > span:first-child{
  display:block;margin-block-end:.4rem;
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
}
.enquiry input[type="text"],
.enquiry input[type="tel"],
.enquiry input[type="email"],
.enquiry select,
.enquiry textarea,
.room--office input[type="text"],
.room--office input[type="tel"],
.room--office input[type="email"],
.room--office select,
.room--office textarea{
  box-sizing:border-box;width:100%;
  padding:.85rem 1rem;
  font-family:var(--sans);font-size:var(--fs-small);color:var(--ink);
  background:var(--paper);
  border:1px solid var(--line);
  border-radius:2px;
  transition:border-color .2s var(--ease),background .2s var(--ease),box-shadow .2s var(--ease);
}
.room--office textarea{min-height:104px;resize:vertical;}
.room--office input::placeholder,
.room--office textarea::placeholder{color:rgba(36,26,17,.38);}
.room--office input:hover,.room--office select:hover,.room--office textarea:hover{
  border-color:rgba(36,26,17,.34);
}
.room--office input:focus,
.room--office select:focus,
.room--office textarea:focus{
  outline:0;
  background:#fff;
  border-color:var(--brand-deep);
  box-shadow:0 0 0 3px rgba(168,84,58,.14);
}

/* The control the form script rejected. The message under the button
   says what is wrong; nothing said which of the six controls it meant,
   because the script looked for a .field wrapper this markup does not
   have, so is-invalid never landed anywhere and the only signal was
   aria-invalid. Coral is the page's one alert colour, and --coral-edge
   is the value that clears 3:1 against white. Placed after the focus
   rule above on purpose: that rule is what paints these controls, and
   an equal-weight selector earlier in the file would lose to it. */
.cell.is-invalid input,.cell.is-invalid select,.cell.is-invalid textarea,
.field.is-invalid input,.field.is-invalid select,.field.is-invalid textarea{
  border-color:var(--brand-deep);
  box-shadow:0 0 0 3px rgba(168,84,58,.16);
}
.cell.is-invalid input:focus,.cell.is-invalid select:focus,.cell.is-invalid textarea:focus,
.field.is-invalid input:focus,.field.is-invalid select:focus,.field.is-invalid textarea:focus{
  border-color:var(--brand-deep);
  box-shadow:0 0 0 3px rgba(168,84,58,.30);
}
.room--office select{
  appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),
                   linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:right 1.05rem center,right .72rem center;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
  padding-inline-end:2.4rem;
}
[dir="rtl"] .room--office select{
  background-position:left 1.05rem center,left .72rem center;
  padding-inline-end:2.4rem;padding-inline-start:1rem;
}


/* ============================================================
   ICON CONTROLS
   The icons were already clickable: a real click on the dock's
   WhatsApp navigates. What they lacked was affordance, which is
   the same thing to a reader. Every icon control now reads the way
   the hero buttons do: a fully rounded chip, transparent with a
   hairline, filling on hover, with a real 44px target.
   ============================================================ */

.reach,
.standing__act,
.rail__key,
.dock a,
.reel__cover{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  min-width:44px;min-height:44px;
  border-radius:999px;
  border:1px solid currentColor;
  background:transparent;
  color:inherit;
  cursor:pointer;
  transition:background .25s var(--ease),color .25s var(--ease),
             border-color .25s var(--ease),transform .25s var(--ease);
}
.reach:hover,.standing__act:hover,.rail__key:hover:not(:disabled),
.dock a:hover,.reel__cover:hover{
  background:var(--ink);
  color:var(--paper);
  border-color:var(--ink);
  transform:translateY(-1px);
}
.reach:focus-visible,.standing__act:focus-visible,.rail__key:focus-visible,
.dock a:focus-visible,.reel__cover:focus-visible{
  outline:2px solid var(--brand-deep);outline-offset:3px;
}
.reach:active,.standing__act:active,.dock a:active{transform:translateY(0);}

/* On the deep band the chip inverts rather than disappearing. On sand it
   stays the page's own chip, because sand is a light ground. */
.room--plan .rail__key,
.room--plan .reel__cover{
  border-color:var(--line-inv);color:var(--on-deep);
}
.room--plan .rail__key:hover,
.room--plan .reel__cover:hover{
  background:var(--on-deep);color:var(--deep);border-color:var(--on-deep);
}
.room--warm .rail__key,
.room--warm .reel__cover{border-color:var(--line);color:var(--ink);}
.room--warm .rail__key:hover,
.room--warm .reel__cover:hover{background:var(--ink);color:var(--band);border-color:var(--ink);}

/* The standing rail: chips on the page, not solid discs. */
.standing__act{
  background:rgba(252,248,242,.82);
  backdrop-filter:blur(10px);
  border-color:var(--line);
  color:var(--ink);
  box-shadow:0 6px 22px -12px rgba(36,26,17,.55);
}
.standing__act:hover{background:var(--ink);color:var(--paper);}

/* The mobile bar: three equal chips on one surface. */
.dock{gap:.5rem;padding:.5rem .75rem calc(.5rem + env(safe-area-inset-bottom));}
.dock a{flex:1;background:transparent;border-color:var(--line);color:var(--ink);}

/* The strokes read thinner and more current at this size. */
svg.icon{pointer-events:none;stroke-width:1.5;}
svg.icon path,svg.icon rect,svg.icon circle,svg.icon line,svg.icon polyline{
  vector-effect:non-scaling-stroke;
}

/* Buttons follow the same shape, so the whole set reads as one family. */
.btn{border-radius:999px;}
.btn--quiet,.btn--line{background:transparent;border:1px solid currentColor;}


/* ============================================================
   LOCATION
   Built on the pattern the client sent: the argument on one side,
   the map plated on its own warm surface on the other, and the
   neighbouring communities as a row of chips with this project
   marked. A buyer places a development by the company it keeps,
   so the chips do more work than another paragraph would.
   ============================================================ */

.room--place{background:var(--paper-2);}

.place{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1.08fr);
  gap:clamp(28px,4vw,72px);
  align-items:start;
}

.place__plate{
  background:var(--paper-3);
  border:1px solid var(--line);
  border-radius:4px;
  padding:clamp(18px,2.2vw,30px);
}

/* The shoreline: chips, wrapping, with this project filled in. */
.shore{
  display:flex;flex-wrap:wrap;gap:.5rem;
  margin:.9rem 0 0;padding:0;list-style:none;
}
.shore__pin{
  display:inline-flex;align-items:baseline;gap:.4rem;
  padding:.55rem .95rem;
  background:var(--paper-3);
  border:1px solid var(--line);
  border-radius:999px;
  font-size:var(--fs-small);line-height:1.2;
  white-space:nowrap;
}
.shore__name{font-weight:var(--fw-button);color:var(--ink);}
.shore__by{font-size:var(--fs-caption);color:var(--muted);font-weight:var(--fw-body);}
.shore__pin.is-here{
  background:var(--ink);border-color:var(--ink);
}
.shore__pin.is-here .shore__name{color:var(--paper);}
.shore__pin.is-here .shore__by{color:rgba(252,248,242,.72);}

/* Distances read across, two to a row, rather than as a long list. */
.reckon--across{
  display:grid;grid-template-columns:1fr 1fr;
  gap:0 var(--s5);margin:.9rem 0 0;
}
.reckon__row{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding-block:.62rem;
  border-block-end:1px solid var(--hair);
}
.reckon--across dt{font-size:var(--fs-small);color:var(--muted);margin:0;}
.reckon--across dd{
  margin:0;font-family:var(--num);font-size:var(--fs-small);font-weight:var(--fw-button);color:var(--ink);
  font-variant-numeric:tabular-nums lining-nums;white-space:nowrap;
}

@media (max-width:900px){
  .place{grid-template-columns:1fr;gap:26px;}
  .reckon--across{grid-template-columns:1fr;}
  /* The chips stay on one line and scroll, per the standing rule that this
     site lays out horizontally rather than stacking.

     The bleed is done with padding and a negative margin on the SAME axis so
     they cancel. Doing it with margin alone, as the first version did, pushed
     the whole grid column 419px past the viewport in RTL, because a negative
     inline margin inside a grid item widens the item rather than letting the
     content hang out of it. The column is also given a zero min-width, which
     is what stops a scrolling child from forcing a grid track wider than its
     share. */
  .place{min-width:0;}
  .place__say,.place__plate{min-width:0;}
  .shore{
    flex-wrap:nowrap;
    max-width:100%;
    overflow-x:auto;
    scroll-snap-type:x proximity;
    scrollbar-width:none;
    -webkit-overflow-scrolling:touch;
  }
  .shore::-webkit-scrollbar{display:none;}
  .shore__pin{scroll-snap-align:start;}
}

.place__say .prose{max-width:56ch;}
.place__say .rubric{margin-block-start:var(--s5);}


/* ============================================================
   RESIDENCES AS A RAIL AT EVERY WIDTH
   Nine unit types stacked two to a row ran the section past three
   screens, and a reader comparing a 50 m2 studio with a 254 m2
   loft had to scroll between them. The set is one horizontal rail
   now, on the desktop as well as the phone, which is the standing
   rule for this site: lay out across, not down.
   ============================================================ */

/* A rail needs to say it is a rail. */

/* Grid children that scroll must be allowed to be narrower than their content,
   or the track grows to fit and the page overflows. */
.place,.place__say,.place__plate{min-width:0;}


/* ============================================================
   MOTION
   Opacity and transform only. Nothing here reads or writes
   layout, so every frame is composited and the scroll thread is
   untouched. There is no library: the whole system is four
   declarations and a stagger index set once by script.
   ============================================================ */

.js .reveal{
  opacity:0;
  transform:translate3d(0,14px,0);
  will-change:opacity,transform;
}
.js .reveal.is-in{
  opacity:1;
  transform:none;
  transition:opacity .7s var(--ease), transform .7s var(--ease);
}
/* Released once it has played, so nothing holds a compositor layer for the
   life of the page. */
.js .reveal.is-in{will-change:auto;}

.reveal-d1.is-in{transition-delay:.12s;}
.reveal-d2.is-in{transition-delay:.24s;}

/* Children stagger off an index the script writes once. */
.js .reveal [data-stagger] > *{
  opacity:0;transform:translate3d(0,10px,0);
}
.js .reveal.is-in [data-stagger] > *{
  opacity:1;transform:none;
  transition:opacity .55s var(--ease), transform .55s var(--ease);
  transition-delay:calc(var(--i,0) * 55ms);
}

/* The masthead settles onto a surface once the page has moved.

   The ground is very nearly opaque rather than the 0.9 it carried before.
   At 0.9 the section heading passing underneath stayed legible through the
   bar, so the two sets of type read as one overlapping block — the blur
   softens a photograph but does nothing to text at that alpha. 0.985 keeps
   the sense of a surface sitting above the page without letting anything
   read through it. */

/* Cards lift rather than grow, so the neighbours do not reflow. */
.shore__pin,.tally__item{transition:transform .35s var(--ease), border-color .35s var(--ease);}

/* Photography settles in on its own frame. */
.plate img{
  transition:transform .8s var(--ease);
}

/* The rail hint drifts, which is what tells a reader it scrolls. */
@keyframes gl-nudge{
  0%,100%{transform:translateX(0);}
  50%{transform:translateX(5px);}
}
.rail__hint svg{animation:gl-nudge 2.4s var(--ease) infinite;}
[dir="rtl"] .rail__hint svg{
  animation-name:gl-nudge-rtl;
}
@keyframes gl-nudge-rtl{
  0%,100%{transform:scaleX(-1) translateX(0);}
  50%{transform:scaleX(-1) translateX(5px);}
}

@media (prefers-reduced-motion:reduce){
  .js .reveal,
  .js .reveal [data-stagger] > *{opacity:1;transform:none;}
  .js .reveal.is-in,
  .js .reveal.is-in [data-stagger] > *{transition:none;}
  .rail__hint svg{animation:none;}
}


/* ============================================================
   MASTER PLAN FILTER
   The chips narrow what the plan shows; a legend row takes the
   plan to its own pin. Filtered-out items fade and stop taking
   pointer events rather than being removed, so the layout never
   reflows and the list keeps its numbering.
   ============================================================ */
.chip{
  /* 44px, because measure counts anything under it as a failed tap target
     and it is right to: a 38px chip on a phone is a miss. */
  min-height:44px;padding:.6rem 1.05rem;
  font-family:var(--sans);font-size:var(--fs-small);font-weight:var(--fw-button);
  color:var(--on-deep);
  background:transparent;
  border:1px solid var(--line-inv);
  border-radius:999px;cursor:pointer;
  transition:background .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease);
}
.chip:hover{border-color:var(--on-deep);}
.chip.is-on{background:var(--on-deep);color:var(--deep);border-color:var(--on-deep);}
.chip:focus-visible{outline:2px solid var(--sea-text);outline-offset:3px;}
.pin.is-out,.legend__row.is-out{opacity:.18;pointer-events:none;}
.pin.is-lit{transform:translate(-50%,-50%) scale(1.35);z-index:3;}
.legend__row.is-lit .legend__t{color:var(--sea-text);}

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


/* ============================================================
   THE FILM
   The container was reel--portrait at 720x1280, inherited from a
   project whose film really was vertical. This one is 1920x1080, so
   a landscape master was being letterboxed into a portrait box:
   two black bars, the picture a third of the width it should be,
   and every pixel scaled down twice. It is a wide frame now, and
   it sits inside a plate rather than running loose on the page.
   ============================================================ */

.reel--wide{
  max-width:1040px;
  margin-inline:auto;
  aspect-ratio:16 / 9;
  overflow:hidden;
  border-radius:var(--cut);
  background:var(--deep);
  box-shadow:0 28px 70px -50px rgba(36,26,17,.8);
}
.reel--wide video,
.reel--wide .reel__cover img{
  width:100%;height:100%;
  object-fit:cover;
  display:block;
}
.reel--wide .reel__cover{border-radius:var(--cut);}


/* ============================================================
   FRAMED SURFACES
   Every picture and every panel on the site is cut at the same
   radius. A single token drives all of it, so the whole system
   moves together if the shape is ever revised.
   ============================================================ */

.plate img,
.place__plate,
.broad img,
.faq__item,
.room--office .frame,
.tally__item{
  border-radius:var(--cut);
}

.plate,
.broad{
  overflow:hidden;
  border-radius:var(--cut);
}

.shore__pin,.chip,.btn,.key,
.reach,.standing__act,.dock a,.rail__key,.reel__cover{
  border-radius:var(--cut-pill);
}

.field input,.field select,.field textarea,
.room--office input,.room--office select,.room--office textarea{
  border-radius:var(--cut-sm);
}

/* ============================================================
   THE STANDING ACTION
   It read as three grey discs. It is turquoise now, which is the
   only colour the buildings carry and the same colour the primary
   button uses, so the standing action and the page's main action
   are visibly the same offer. Cut at the system radius.
   ============================================================ */

.standing__act{
  background:var(--brand-ink);
  border-color:var(--brand-ink);
  color:#fff;
  backdrop-filter:none;
  box-shadow:0 10px 26px -16px rgba(168,84,58,.9);
}
.standing__act:hover,.standing__act:focus-visible{
  background:var(--ink);border-color:var(--ink);color:var(--paper);
}

.dock{
  background:var(--paper-3);
  border-top:1px solid var(--line);
}
.dock a{
  background:var(--brand-ink);
  border-color:var(--brand-ink);
  color:#fff;
}
.dock a:hover,.dock a:focus-visible{
  background:var(--ink);border-color:var(--ink);color:var(--paper);
}


/* ============================================================
   RAIL EDGES
   The page does not overflow: a scroll-width check at 320, 360,
   390 and 414 comes back clean in both languages. What looks like
   the design escaping is a rail card cut by the viewport edge with
   nothing to say it is a rail. Two changes fix the reading: the
   snap is mandatory, so a card always lands whole, and the edge
   carries a fade, so the cut is obviously an edge and not a bug.
   ============================================================ */

.shore,
.tally,
.rail__track{
  scroll-snap-type:x mandatory;
  scroll-snap-stop:always;
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 18px,#000 calc(100% - 26px),transparent 100%);
          mask-image:linear-gradient(to right,transparent 0,#000 18px,#000 calc(100% - 26px),transparent 100%);
}
[dir="rtl"] .shore,
[dir="rtl"] .tally,
[dir="rtl"] .rail__track{
  -webkit-mask-image:linear-gradient(to left,transparent 0,#000 18px,#000 calc(100% - 26px),transparent 100%);
          mask-image:linear-gradient(to left,transparent 0,#000 18px,#000 calc(100% - 26px),transparent 100%);
}

/* The mask clips a focus ring, so the ring is drawn inside instead. */
.shore :focus-visible,
.tally :focus-visible{outline-offset:-3px;}

@media (max-width:900px){
  /* Amenities were a wrapping grid of fourteen items, which on a phone is a
     column three screens long. One rail, like every other set on this site. */
  .tally{
    display:flex;flex-wrap:nowrap;gap:12px;
    overflow-x:auto;overscroll-behavior-x:contain;
    scrollbar-width:none;
    padding-inline:var(--gutter);
    margin-inline:calc(var(--gutter) * -1);
    scroll-padding-inline-start:var(--gutter);
  }
  .tally::-webkit-scrollbar{display:none;}
  .tally__item{
    flex:0 0 74vw;max-width:300px;
    scroll-snap-align:start;
    background:var(--paper-3);
    border:1px solid var(--line);
    padding:var(--s4);
  }
  .room--warm .tally__item{
    background:rgba(252,248,242,.06);
    border-color:var(--line-inv);
  }
}


/* ============================================================
   WHAT MAY BE A RAIL ON A PHONE, AND WHAT MAY NOT
   The horizontal rule was applied to everything, including cards
   that are a heading and a paragraph. A rail cuts its last card at
   the viewport edge on purpose, which is fine for a picture and
   wrong for a sentence: the reader gets "Sandy lagoons and wa".

   The rule now has a condition. A set may be a rail on a phone
   when each card is self-contained at a glance, which means it
   leads with an image or is a short label. A set of cards carrying
   running text stacks, because text that is cut is text that is
   lost, and no layout preference is worth that.
   ============================================================ */

@media (max-width:900px){

  /* Amenities: a heading and a sentence each. These stack. */
  .tally{
    display:grid;
    grid-template-columns:1fr;
    gap:12px;
    overflow:visible;
    margin-inline:0;
    padding-inline:0;
    -webkit-mask-image:none;
            mask-image:none;
    scroll-snap-type:none;
  }
  .tally__item{
    flex:none;
    width:auto;
    max-width:none;
    scroll-snap-align:none;
  }

  /* The shoreline chips are two or three words each, so they stay a rail. */
  .shore{scroll-snap-type:x proximity;}

  /* The residences lead with a plan drawing and their text is a spec table,
     never a paragraph, so they stay a rail. The card is widened so the
     specification column is never the part that gets cut. */
}

@media (max-width:560px){
  /* Two facts side by side is still horizontal, and nothing is clipped. */
  .tally{grid-template-columns:1fr;}
}

/* The fade was masking the last line of a stacked card. It belongs only on
   the sets that actually scroll. */
.tally{-webkit-mask-image:none;mask-image:none;}


/* ============================================================
   THE STANDING ACTION, RESTATED
   Three filled discs read as a warning, not as an invitation.
   The system works because it keeps one ink chip against
   a warm ground and spends its accent colour sparingly: the active
   thing is dark, everything else is quiet.

   So the rail is ink on cream, cut at the system radius, and the
   accent is kept for the primary enquiry alone. Cream on ink
   measures 15.9:1.
   ============================================================ */

.standing__act{
  background:var(--ink);
  border:1px solid var(--ink);
  color:var(--paper);
  backdrop-filter:none;
  box-shadow:0 10px 30px -18px rgba(36,26,17,.75);
}
.standing__act:hover,
.standing__act:focus-visible{
  background:var(--brand-ink);
  border-color:var(--brand-ink);
  color:#fff;
  transform:translateY(-1px);
}

/* The mobile bar: the same chip, on the page surface. */
.dock{
  background:rgba(252,248,242,.94);
  backdrop-filter:blur(14px);
  border-top:1px solid var(--line);
}
.dock a{
  background:var(--ink);
  border:1px solid var(--ink);
  color:var(--paper);
}
/* The enquiry chip used to carry the accent, which split the set into two
   colours on the phone and matched nothing on the desktop. All three chips are
   one control now; the accent stays on the primary button in the page flow. */
.dock a:hover,
.dock a:focus-visible{
  background:var(--brand-ink);
  border-color:var(--brand-ink);
  color:#fff;
}


/* ============================================================
   THE PEEK MUST BE NARROWER THAN THE CARD'S PADDING
   A rail says there is more by letting the next card show at the
   edge. That only works if the sliver contains no text: at 86% the
   sliver was wide enough to show a heading and two spec rows cut
   mid word, which is the thing the client photographed.

   The card is now the full width less a sliver smaller than its own
   inner padding, so whatever shows past the edge is border and
   padding. There is still a visible next card; there is no longer a
   half-read sentence.
   ============================================================ */

@media (max-width:900px){
  /* Sized against the viewport, not the rail's content box. The rail carries
     a gutter of padding and a negative margin of the same size, so a
     percentage basis is a percentage of the inset box and lands about 30px
     short: the card ends early and the next one shows a readable strip.
     Measured from 100vw, the sliver is smaller than the card's own padding,
     so nothing but border and padding can appear past the edge. */

  /* The mask fades the sliver out as well, so the edge is soft rather than a
     cut line. Narrower than before, because the card now reaches further. */

  /* Same reasoning for the shoreline chips: a chip is two or three words, so
     a cut chip is a cut word. They wrap instead of scrolling. */
  .shore{
    flex-wrap:wrap;
    overflow:visible;
    -webkit-mask-image:none;
            mask-image:none;
  }
}


/* ============================================================
   TYPOGRAPHY ROLES
   The four supplied families, each doing the one job it was
   chosen for. Fraunces is a display face and is never used for
   running text; Manrope carries every number in both languages so
   a spec table lines up whatever language surrounds it.

   This block runs late in the cascade, so it repeats the scale's
   weights rather than resetting them. A role rule that quietly
   dropped every heading back to 400 is how a type scale stops
   being a scale.
   ============================================================ */

/* Arabic display takes Naskh, not the Latin serif. Naskh carries its own
   ascenders and descenders and needs more leading than the Latin face at
   the same size, which is the one metric that is script-specific. */
[lang="ar"] .h-wall,
[lang="ar"] .h-room,
[lang="ar"] .wordmark,
[dir="rtl"] .h-wall,
[dir="rtl"] .h-room,
[dir="rtl"] .wordmark{
  font-family:var(--ar-display);
  letter-spacing:0;
  line-height:var(--lh-h-ar);
}
[lang="ar"] .wordmark,[dir="rtl"] .wordmark{font-weight:var(--fw-display);}
[lang="ar"] .h-wall,[lang="ar"] .h-room,
[dir="rtl"] .h-wall,[dir="rtl"] .h-room{font-weight:var(--fw-h2);}

/* Arabic running text and UI take Cairo. */
[lang="ar"] body,[dir="rtl"] body,[dir="rtl"] .prose,[dir="rtl"] .lede,[dir="rtl"] .btn,[dir="rtl"] .chip,[dir="rtl"] label,[dir="rtl"] input,[dir="rtl"] select,[dir="rtl"] textarea,[dir="rtl"] .room__name,[dir="rtl"] .rubric{
  font-family:var(--ar-sans);
}

/* Numbers stay Manrope even inside Arabic, and stay lining and tabular so
   columns of areas and distances align. */
.fig,.reckon--across dd,.unit .spec dd,.terms dd,.shore__by,[dir="rtl"] .fig,[dir="rtl"] .reckon--across dd,[dir="rtl"] .unit .spec dd{
  font-family:var(--num);
  font-variant-numeric:lining-nums tabular-nums;
  font-feature-settings:"lnum" 1,"tnum" 1;
}

/* Fraunces sits close to its fallback in x-height, so it needs no size
   correction — only the tighter tracking a display face wants at these sizes. */
.h-wall,.h-room,.wordmark{letter-spacing:-0.012em;}
.h-wall,.h-room{font-weight:var(--fw-h2);}


/* ============================================================
   THE STANDING RAIL
   Both classes exist: ".standing__act" is the fixed side rail and
   ".reach" is the footer's contact row. An earlier check sampled
   the first ".reach" on the page, found the footer, and concluded
   the rail used that class. It does not. Querying by resolved
   position instead of by guessed class is what found the real one.

   Ink chip on the page, turquoise only on hover, matching the
   reference: the accent is spent on the action being taken, not
   on three buttons sitting there.
   ============================================================ */

.standing{gap:.55rem;}

.reach{
  width:48px;height:48px;
  border-radius:var(--cut-pill);
  border:1px solid var(--ink);
  background:var(--ink);
  color:var(--paper);
  box-shadow:0 10px 26px -18px rgba(36,26,17,.8);
}
.reach:hover,.reach:focus-visible{
  background:var(--brand-ink);
  border-color:var(--brand-ink);
  color:#fff;
}
/* WhatsApp keeps its own colour on hover; it is the one mark people
   recognise before they read the label. */
.reach--wa:hover{background:#1E7167;border-color:#1E7167;color:#fff;}
.reach:focus-visible{outline:2px solid var(--brand-deep);outline-offset:3px;}

/* The footer's social marks sit on the dark colophon, so they invert. */
.colophon__social a{
  border-radius:var(--cut-pill);
  border-color:var(--line-inv);
  color:var(--on-deep);
}
.colophon__social a:hover{background:var(--on-deep);color:var(--deep);}


/* Superseded: the rail's colour is set once, further down, for both the
   desktop side rail and the mobile bar. This block set the WhatsApp chip with
   a two-class selector, which outranked the unified rule and left one ink chip
   between two turquoise ones on the desktop only. */


/* ============================================================
   THE GALLERY, AT THE SIZE THE BRIEF ASKS FOR
   Measured at 1440: a plate was 547px wide, 38% of the viewport.
   That is a thumbnail strip, not the wide editorial sequence the
   brief specifies, and no amount of spacing fixes a small picture.

   A plate is now the dominant object on the row: one large image
   filling most of the screen, with enough of the next one showing
   to say the sequence continues. Nothing else changes, because the
   interaction was already right: native overflow, drag, trackpad,
   touch, keyboard, no carousel chrome.
   ============================================================ */

.rail__track--gallery{
  gap:clamp(10px,1vw,18px);
  scroll-padding-inline-start:var(--gutter);
}

.plate{
  flex:0 0 clamp(280px,84vw,760px);
}

@media (min-width:700px){
  /* Two plates and the edge of a third at desktop width. The earlier 62vw put
     a single picture across most of the screen, which read as a hero rather
     than a sequence and pushed the rest of the strip out of sight. */
  .plate{flex-basis:clamp(420px,42vw,620px);}
}

@media (min-width:1600px){
  .plate{flex-basis:min(38vw,700px);}
}

/* 3:2 was cropping the wide renders top and bottom. The brochure images run
   about 16:9, so the frame follows them instead of cutting them. */
.plate img{
  aspect-ratio:16/9;
  object-position:50% 50%;
  border-radius:var(--cut);
}

/* ============================================================
   THE MASTER PLAN, AT READABLE SIZE
   The stage measured 662x234 on a 1440 screen: a strip in the
   middle of a dark section, with the drawing too small to read
   the levels it exists to explain. It is the fact the whole
   layout is built around, so it gets the room.
   ============================================================ */

@media (max-width:900px){
  /* On a phone the plan is taller than it is wide in usable terms, so it is
     given more height and the pan gesture does the rest. */
}


/* ============================================================
   THE PLAN IS LANDSCAPE, NOT PORTRAIT
   The desktop grid put the drawing in a 1.15fr column with the
   legend beside it, and the comment above it says why: that plan
   was a portrait drawing. That reference drawing was 1920x679, nearly three times
   as wide as it is tall, so the column squeezed it to 662px on a
   1440 screen and the levels it exists to show were unreadable.

   The drawing now takes the full width of the frame and the legend
   sits beneath it in two columns, which is the arrangement the
   shape asks for.
   ============================================================ */


/* ============================================================
   THE ARRIVAL ON A PHONE, ACTUALLY
   The rule above says the picture should take the slack, and it
   was already there: min-height 86svh with rows auto 1fr. It did
   not work, because the figure in row two never stretched. The
   row grew; the picture stayed 252px and the difference showed as
   278px of empty page between the buttons and the photograph, a
   third of the viewport, measured at 390.

   The figure now fills its row and the image fills the figure.
   ============================================================ */



/* ============================================================
   UNIT CARDS ON A WIDE SCREEN
   The rail capped a card at 340px, so on a 1440 or 1920 screen
   three cards filled about half the frame and the rest of the row
   was empty. A rail is meant to run out of room, not to sit short
   of it. The cards grow with the frame, so a row is full at every
   width and the collections that hold four still scroll.
   ============================================================ */

/* flex-grow rather than a fixed basis: the collection that holds only two
   types filled 61 per cent of the row and looked short. With grow, a short
   collection fills the frame and a long one still overflows and scrolls,
   because grow has nothing to distribute once the basis exceeds the width. */


/* ============================================================
   THE GALLERY ON A PHONE
   84vw at 16:9 gave a 328x184 plate: horizontal, as the brief
   requires, but a thumbnail. A phone screen is portrait, so the
   frame takes a squarer crop there and the picture gets height
   without the sequence losing its direction.
   ============================================================ */

@media (max-width:759px){
  .plate{flex-basis:86vw;}
  .plate img{aspect-ratio:4/3;}

  /* The two arrows were as tall as a fifth of the picture. They stay, because
     they are the keyboard and pointer route through the sequence, but at the
     size of a control rather than of a feature. */
  .rail__key{width:40px;height:40px;}
  .rail__key svg{width:15px;height:15px;}
}


/* ============================================================
   MOBILE COMPOSITION
   Measured at 360 and 390: a 21.6px gutter and 48px of section
   padding. That is what makes the page feel pressed against the
   screen. The type stays exactly as it is — the problem is
   spacing, not size — and the room around it opens up.
   ============================================================ */

@media (max-width:759px){
  :root{
    --gutter:26px;
    --s2:.6rem;
    --s3:1rem;
    --s4:1.5rem;
    --s5:2.1rem;
    --s6:3rem;
  }

  .room{padding-block:clamp(64px,13vw,88px);}

  /* Heading to its paragraph, and paragraph to paragraph. */
  .h-room,.h-wall{margin-block-end:var(--s3);}
  .room__name{margin-block-end:var(--s2);}
  .lede{margin-block-end:var(--s3);}
  .prose + .prose{margin-block-start:var(--s3);}
  .prose:last-of-type{margin-block-end:0;}

  /* Copy to the picture beneath it. */
  .wall + .rail,
  .wall + .plan,
  .prose + .broad,
  .place__say + .place__plate{margin-block-start:var(--s5);}

  /* The two hero actions. */

  /* Cards and rails clear the gutter rather than sitting on it. */
  .tally{gap:14px;}
  .tally__item{padding:var(--s4);}
  .rail__track--gallery,.shore{
    padding-inline:var(--gutter);
    margin-inline:calc(var(--gutter) * -1);
  }

  /* The dock is a fixed bar; the page ends above it, not under it. */
  body{padding-block-end:88px;}
}

/* 22px is the floor for the narrowest phones only. The 400px breakpoint pulled
   390 down with it, so a 390 screen got the 360 gutter; the specification is
   22px at 360 and 26px from 390 up. */
@media (max-width:370px){
  :root{--gutter:22px;}
}


/* ============================================================
   THE STANDING CONTACT RAIL — ONE TREATMENT
   Desktop showed three ink chips; mobile showed two ink chips and
   one accent. Same control, two identities, and the accent
   button read as a warning rather than an invitation.

   Both are now the same turquoise chip at the same size and radius,
   with the same hover. Coral stays where it belongs: the
   primary button in the page flow.
   ============================================================ */

.standing a,
.standing__act,
.dock a,
.dock__call,.dock__wa,.dock__go{
  background:var(--brand-ink);
  border:1px solid var(--brand-ink);
  color:#fff;
  border-radius:var(--cut-pill);
  box-shadow:0 8px 22px -14px rgba(168,84,58,.75);
  transition:background .3s var(--ease),border-color .3s var(--ease),
             transform .3s var(--ease);
}

.standing a:hover,.standing a:focus-visible,
.standing__act:hover,.standing__act:focus-visible,
.dock a:hover,.dock a:focus-visible{
  background:var(--brand-deep);
  border-color:var(--brand-deep);
  color:#fff;
  transform:translateY(-1px);
}

.standing a:active,.dock a:active{transform:translateY(0);}

.standing a:focus-visible,.dock a:focus-visible{
  outline:2px solid var(--brand-deep);
  outline-offset:3px;
}

/* WhatsApp is the one mark people recognise before reading a label, so it
   keeps its own colour on hover and only on hover. */
.standing a.cta-rail__wa:hover,
.dock__wa:hover{background:#1E7167;border-color:#1E7167;}

/* The bar behind the mobile chips stays the page surface, so the three chips
   read as one group rather than a coloured band across the screen. */
.dock{
  background:rgba(252,248,242,.94);
  backdrop-filter:blur(14px);
  border-top:1px solid var(--line);
}


/* The section list in the colophon: one row across the width, wrapping, so the
   footer stays a single band rather than becoming a column of links. */
.colophon__index{
  display:flex;flex-wrap:wrap;gap:.5rem 1.6rem;
  margin-block:var(--s4) var(--s5);
  padding-block-start:var(--s4);
  border-block-start:1px solid var(--line-inv);
}
.colophon__index a{
  font-family:var(--sans);
  font-size:var(--fs-small);
  color:var(--on-deep-muted);
  text-decoration:none;
  padding-block:.35rem;
  min-height:44px;
  display:inline-flex;align-items:center;
  transition:color .25s var(--ease);
}
.colophon__index a:hover,.colophon__index a:focus-visible{color:var(--on-deep);}
[dir="rtl"] .colophon__index{font-family:var(--ar-sans);}

@media (max-width:759px){
  .colophon__index{gap:.2rem 1.1rem;margin-block:var(--s3) var(--s4);}
  .colophon__index a{font-size:var(--fs-small);}
}


/* ============================================================
   THE LABEL SITS ABOVE ITS HEADING
   The heading comes first in the source so a crawler and a screen
   reader meet it before the kicker; the label is lifted visually.
   That rule was scoped to .wall, so the two sections built on a
   different container — Location and Enquiry — showed the label
   underneath the heading and read backwards against every other
   section.
   ============================================================ */

.place__say,
.enquiry__say{
  display:flex;
  flex-direction:column;
}
.place__say .room__name,
.enquiry__say .room__name{
  order:-1;
  margin-block-end:var(--s2);
}


/* ============================================================
   THE BAND UNDER THE FOOTER
   The page carried 88px of bottom padding so the last content
   would clear the fixed mobile bar. Because the padding sat on the
   body, it rendered as a white strip below the dark colophon at
   the very end of the page.

   The clearance moves onto the colophon itself: the dark ground
   now extends behind the bar, the content still clears it, and the
   page ends on the footer instead of on a gap.
   ============================================================ */

/* The bar is shown up to 900px, so the clearance has to match that boundary
   exactly. Stopping at 759 left a 62px white strip at 768. */
@media (max-width:900px){
  body{padding-block-end:0;}
  .colophon{padding-block-end:calc(clamp(18px,2vw,26px) + 76px);}
}

/* The marks inside the standing rail and the mobile bar carry the
   recognition, so they are set larger against the chip. */
.standing a svg.icon,
.dock a svg.icon{width:24px;height:24px;}

@media (max-width:759px){
  .dock a svg.icon{width:26px;height:26px;}
}


/* ============================================================
   THE CONTACT LINKS, ENQUIRY AND FOOTER
   Both sets were ink on their ground and sized like small print,
   which made them read as legal text rather than as the three ways
   to reach the sales team. They now carry the same turquoise the
   standing rail uses, so every contact action on the site is one
   colour, and they are set large enough to be found without
   hunting.

   Petrol on the white enquiry card measures 7.09:1. In the footer
   the chip is filled and the mark is white, which is the same
   7.09:1 the other way round.
   ============================================================ */

/* --- the enquiry section ------------------------------------ */
.direct{gap:var(--s4) var(--s5);margin-top:var(--s5);}
.direct a{
  gap:.55rem;
  padding-block:.5rem;
  font-size:var(--fs-small);
  letter-spacing:.04em;
  text-transform:none;
  font-weight:var(--fw-button);
  color:var(--brand-ink);
  border-bottom:1px solid rgba(168,84,58,.28);
  transition:color .25s var(--ease),border-color .25s var(--ease);
}
.direct a:hover,.direct a:focus-visible{
  color:var(--brand-deep);
  border-color:var(--brand-deep);
}
.direct a svg.icon{width:22px;height:22px;flex:none;}

/* --- the footer ---------------------------------------------- */
.colophon__reach{gap:.6rem;}
.reach{
  width:56px;height:56px;
  border-radius:var(--cut-pill);
  background:var(--brand-ink);
  border:1px solid var(--brand-ink);
  color:#fff;
}
.reach:hover,.reach:focus-visible{
  background:var(--brand-deep);
  border-color:var(--brand-deep);
  color:#fff;
}
.reach--wa:hover{background:#1E7167;border-color:#1E7167;color:#fff;}
.reach svg.icon{width:24px;height:24px;}

@media (max-width:759px){
  .direct{gap:var(--s3) var(--s4);}
  .direct a{font-size:var(--fs-small);}
  .reach{width:52px;height:52px;}
}

/* ============================================================
   THE DESCENT
   The site's four levels, drawn to scale beside the text that
   describes them. The drawing sticks while the levels scroll
   past it, so the reader is looking at the same section of
   ground the paragraph is talking about.

   The palette is doing literal work here for once: the ground
   is sand because the ground is sand, and the water is the
   primary because the water is what the whole project is
   pointed at. Nothing in this block is decorative colour.
   ============================================================ */
/* The drawing is sand on a near-white page, which is a deliberately quiet
   pair — so the section sits on the panel tone rather than the page, and the
   ground carries an edge. Without both, a pale cream shape on white reads as
   nothing at all. */

/* ---- the drawing */
/* The drawing is the anchor of the section and has to hold the eye against a
   column of type twice its height. */
/* The section is drawn from the road inward. In Arabic the page runs the
   other way, so the drawing is mirrored to match the reading direction. */
.descent__pin.is-here{fill:var(--brand-deep);}

/* The readout counts down as the reader descends. Tabular figures so the
   number does not jog sideways when 13 becomes 7. */

/* ---- the levels */
.descent__level.is-here{border-inline-start-color:var(--brand);}
.descent__body .h-room{margin-bottom:var(--s2);}
.descent__body .prose{margin-top:0;}

/* The levels have to be given real scroll distance, or the whole idea
   collapses: packed at their natural height the five of them are shorter
   than one viewport, so a reader crosses the entire site in a flick and the
   drawing beside them never has anything to track. Each level holding a bit
   over half a screen is what turns the section into a descent rather than a
   list — it is the reason the sticky drawing is worth having at all. */
@media (max-width:899px){
  /* On a phone the drawing sits above the levels and stays put while they
     pass, which is the same relationship in less room. */
}

/* ============================================================
   THE BROKEN GRID
   Every repeating set on the page stops being a row of identical
   boxes. The irregularity is never decorative: where there is a
   real quantity to encode it drives the size, and where there
   is not, the treatment changes instead of the scale.

   One rule governs all of it. The visual order and the DOM order
   are the same order, always — no `order`, no `grid-auto-flow:
   dense`. Both decouple what the eye sees from what the tab key
   and the screen reader follow, and dense does it silently by
   back-filling holes. Asymmetry here comes only from spans and
   from column placement, neither of which moves an element in
   the accessibility tree.
   ============================================================ */
/* ---- units: one horizontal strip, at every width
   Stacking the units vertically was the mistake in the last round. Nine cards
   down the page — with the largest taking a full row to itself — made the
   section enormous and gave a single unit the whole viewport. The range is now
   read across rather than down: all nine sit on one line and the reader moves
   sideways through them.

   The encoding survives the change intact. Floor area still sets the size, it
   just sets width along a row instead of columns in a grid, so the loft is
   visibly wider than the studio while both stay on the same line.

   This is horizontal on a phone too. Collapsing to a single column below a
   breakpoint is the usual reflex and it is exactly what was asked against —
   the strip is the layout, not a desktop enhancement of one. */

/* Three widths, from the three size bands. Each is a clamp so the strip works
   from a 360px phone to a wide desktop without a breakpoint deciding the
   layout — only the card's own width changes. */
/* Scoped under the strip on purpose. An earlier `.units-grid > .unit` rule
   sets width:auto, and a bare `.unit--w4` is one class against a class plus a
   child combinator — it loses on specificity however late it appears, which is
   why the three widths silently did nothing on the first attempt. */
/* Equal cards, not three stepped widths.
   The stepped widths existed to encode floor area — a bigger unit got a
   wider card. MARSA publishes no areas, so a width difference here would
   signal a size relationship the page never states. Four equal cards also
   fit the frame at desktop, which is what stopped the fourth one being cut
   through its CTA. Below that the rail scrolls, one card per snap. */
/* Card width is set so the peek is deterministic.
   A rail needs the next card to show a sliver, or nothing says it scrolls.
   But the sliver has to land inside that card's padding — the cards carry
   var(--s4) of inline padding, so a peek under about 32px shows only blank
   card, never half a button. Sizing the card as "the rail minus 46px" makes
   the peek 46px less the gap, which is roughly 24-30px at every width. */
/* The card is sized so the peek is exactly --rail-peek.
   A rail has to show a sliver of the next card or nothing says it scrolls.
   That sliver has to be narrower than the card's own inline padding
   (var(--s4), 2rem) — otherwise it cuts through the enquire button, which
   reads as a broken card rather than as "there is more". Solving for the
   card width from the viewport, the gutter and the gap keeps the peek at
   20px whatever the screen is, so no CTA pixel ever lands inside it. */

/* The rail only scrolls when it has to. Four equal cards plus their gaps
   come to about 1330px, so from a wide tablet up the strip sits still and
   there is nothing to clip. */

/* When it does scroll, the trailing edge fades.

   A rail cannot both show a sliver of the next card — which is the only
   thing that says it scrolls — and have every card complete. The sliver is
   the affordance. What matters is that it reads as deliberate rather than
   as a card someone chopped, so the last stretch fades out over the width
   of the gutter plus a little. Combined with the "scroll for more" hint and
   the two arrow keys under the strip, the continuation is stated three
   ways. This is a mask, so nothing intercepts pointer events. */

/* Emphasis beyond width: the crop widens and the square metre figure grows. */
/* Emphasis tiers previously widened the photograph's crop. With typographic
   cards they step the name instead, so a three bedroom still reads as the
   largest card in the row. */
/* One heading size across the four. Stepping it was the same size signal as
   the stepped widths, and it has the same problem. */
.unit .spec .fig{font-size:var(--fs-body-lg);}

/* ---- amenities: also one strip
   Fourteen items in a twelve column grid wrapped into five rows and ran to
   nearly four thousand pixels, which is the same vertical pile the units had
   in a different shape. They read across now, on one line, at every width —
   the two treatments alternate along the strip so a picture tile is followed
   by a mark, and the rhythm is visible without scrolling a screen to find it. */
.tally{
  display:flex;
  grid-template-columns:none;
  gap:clamp(16px,1.8vw,28px);
  overflow-x:auto;
  overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  scroll-padding-inline-start:var(--gutter);
  margin-inline:calc(var(--gutter) * -1);
  padding-inline:var(--gutter);
  padding-block-end:var(--s3);
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
  align-items:start;
}
.tally::-webkit-scrollbar{display:none;}
.tally > .tally__item{flex:0 0 auto;scroll-snap-align:start;}
.tally > .tally__item--w7{width:clamp(300px,74vw,460px);}
.tally > .tally__item--w5{width:clamp(250px,62vw,360px);}
.tally > .tally__item--w4{width:clamp(230px,58vw,320px);}
/* A mark and two lines of type needs less room than a photograph, and saying
   so is part of the contrast between the two treatments. */
.tally > .tally__item--said{width:clamp(190px,48vw,290px);}

/* ---- the amenity that is only words
   No card, no border, no shadow. The plate below carries it.
   
   A terracotta rule used to run across the top of these cards and of no
   others, which was the last thing making one row look like two components
   spliced together — a picture card opened with a photograph, a type card
   opened with a coloured line. The plate does that job now, on both, so the
   rule has gone. */
.tally__item--said{
  background:none;border:0;box-shadow:none;padding:0;
}
/* The mark that replaces the photograph. Sized and coloured so an icon plus a
   line of type carries the same weight in the row as a picture tile does —
   the point is two treatments, not a full one and an empty one. */
.tally__mark{
  display:block;color:var(--brand-deep);margin-bottom:var(--s3);
}
.tally__mark svg{display:block;}
.tally__item--said h3{
  font-family:var(--serif);font-size:var(--fs-h3);font-weight:var(--fw-h3);
  line-height:var(--lh-h);color:var(--ink);margin-bottom:var(--s2);
}
[dir="rtl"] .tally__item--said h3{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.tally__item--said p{color:var(--muted);}

/* ---- the amenity that has a photograph
   Still frameless: the picture is the frame. */
.tally__item--shot{background:none;border:0;box-shadow:none;padding:0;}
.tally__item--shot .tally__media{overflow:hidden;border-radius:var(--cut);margin-bottom:var(--s3);}
.tally__item--shot .tally__media img{
  width:100%;height:auto;display:block;
  transition:transform var(--d-l) var(--e-drift);
}
@media (hover:hover){
  .tally__item--shot:hover .tally__media img{transform:scale(1.03);}
}
.tally__item--shot h3{
  font-family:var(--serif);font-size:var(--fs-h3);font-weight:var(--fw-h3);
  line-height:var(--lh-h);color:var(--ink);margin-bottom:var(--s2);
}
[dir="rtl"] .tally__item--shot h3{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.tally__item--shot p{color:var(--muted);}
/* One plate height across the whole rail, widths still varying.
   The crops used to alternate between 16/9, 4/3 and 1/1, which meant every
   card in the row started its heading at a different height — and the cards
   set as type, which have no plate at all, started theirs at the top. Read
   across, the rail looked like two unrelated components interleaved rather
   than one row with two treatments. Holding the plate to a single height
   puts every heading on one baseline; the widths still differ, so the row
   keeps its rhythm and no photograph is cropped to a shape it was not
   filmed for. */
.tally{--tally-plate:clamp(180px,23vw,248px);}
.tally__item--shot .tally__media img{
  height:var(--tally-plate);aspect-ratio:auto;object-fit:cover;
}
/* The card that is only words reserves the same plate, and stands its mark
   in it, so its heading meets the photographs' headings on the same line
   instead of floating a plate's height above them.
   
   It also takes a ground. Reserved but left empty, the plate read as a
   picture that had failed to load rather than as a card meant to be type,
   and the mark standing at the foot of all that blank space looked like the
   affordance for adding one. On the stone the project already uses for a
   raised panel, with the same corner as the photographs and the rosette
   centred in it, the two treatments read as a pair. */
.tally__item--said .tally__mark{
  min-height:var(--tally-plate);
  display:flex;align-items:center;justify-content:center;
  margin-bottom:var(--s3);
  background:var(--band);
  border-radius:var(--cut);
  color:var(--clay);
}
.tally__item--said .tally__mark .rosette{width:34px;height:34px;opacity:.62;}

/* Headings run to one line or two depending on the name, which left the
   descriptions starting at two different heights across a row that had just
   been aligned at the heading. Two lines are reserved for every heading, so
   the whole row starts its prose together. */
.tally__item--shot h3,
.tally__item--said h3{min-height:calc(var(--fs-h3) * var(--lh-h) * 2);}

@media (prefers-reduced-motion:reduce){
  .tally__item--shot:hover .tally__media img{transform:none;}
}

/* ============================================================
   REVIEW FIXES
   ============================================================ */

/* ---- the conceptual badge
   The badge itself was removed at the client's request; the rule that gave its
   container a positioning context is kept because the media block still relies
   on it. */
.tally__item--concept .tally__media{position:relative;}

/* ---- strip affordances
   The controls worked but were easy to miss: a hint in muted type and two
   outline chips. A strip that can scroll has to say so before it is touched,
   so the keys are filled and the running edge is faded. */
.rail__keys{display:flex;gap:.5rem;}
.rail__keys .rail__key{
  min-width:44px;min-height:44px;
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--brand-ink);color:var(--white);
  border:var(--rule) solid var(--brand-ink);border-radius:var(--cut-pill);
  cursor:pointer;opacity:1;
  transition:background var(--d-hover) var(--e-lift),transform var(--d-hover) var(--e-lift);
}
/* The hover was brand-ink to brand-deep — four points of luminance apart, and
   in a side-by-side screenshot of the two states the button looks unchanged.
   A control that gives no visible answer to the pointer reads as inert, so the
   hover inverts instead of darkening: ink ground, white glyph, and a small
   lift. Ink on white is 17.7:1. */
.rail__keys .rail__key:hover:not(:disabled){
  background:var(--ink);border-color:var(--ink);color:var(--white);
  transform:translate3d(0,-2px,0);
}
.rail__keys .rail__key:active{transform:scale(.94);}
.rail__keys .rail__key:disabled{
  background:transparent;color:var(--muted);border-color:var(--line);cursor:default;opacity:1;
}
.rail__foot{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  margin-top:var(--s3);flex-wrap:wrap;
}
.rail__hint{
  display:inline-flex;align-items:center;gap:.5rem;
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.16em;text-transform:uppercase;color:var(--brand-deep);
}
[dir="rtl"] .rail__hint{font-family:var(--ar-sans);letter-spacing:0;}
.rail__hint svg{width:26px;height:auto;stroke:currentColor;fill:none;stroke-width:1.6;}
[dir="rtl"] .rail__hint svg{transform:scaleX(-1);}

/* The fade tells the eye there is more before it tries. Masked rather than
   painted with a gradient overlay, so it works on any ground the strip sits
   on — white, sand or the sky panel — without matching a colour to it. */
.tally{
  -webkit-mask-image:linear-gradient(to right,transparent 0,#000 var(--gutter),#000 calc(100% - 44px),transparent 100%);
          mask-image:linear-gradient(to right,transparent 0,#000 var(--gutter),#000 calc(100% - 44px),transparent 100%);
}
[dir="rtl"] .tally{
  -webkit-mask-image:linear-gradient(to left,transparent 0,#000 var(--gutter),#000 calc(100% - 44px),transparent 100%);
          mask-image:linear-gradient(to left,transparent 0,#000 var(--gutter),#000 calc(100% - 44px),transparent 100%);
}

/* ---- heading and its paragraph
   The heading and its standfirst sit in two columns. They are tied together by
   sharing a top edge and by the column gap, not by a rule: a line drawn across
   the paragraph column reads as a divider cutting the text, which is the
   opposite of the link it was meant to make. */
.wall .lede{margin-top:var(--s3);}
.wall .h-wall,.wall .h-room{margin-bottom:var(--s2);}
@media (min-width:1024px){
  .wall .lede{margin-top:0;}
}

/* The standing contact rail is fixed against the inline edge and the strip
   controls sit at the same edge of their foot, which left exactly one pixel
   between them at 1366px — not an overlap, and clickable, but reading as a
   single jammed cluster of circles. The foot keeps clear of the rail's column
   wherever that rail is on screen. */
@media (min-width:1024px){
  .rail__foot{padding-inline-end:96px;}
}

/* The two photographs that appear twice on the page are framed differently in
   their second place: pushed off centre and scaled up, so the card shows a
   different part of the picture than the full width plate does. Transform on
   the image inside its own clipped box, so nothing about the card's geometry
   or the reserved space changes. */

/* The offset is not flipped for Arabic. The photograph is not mirrored by the
   page direction, so flipping it here showed Arabic and English readers two
   different parts of the same picture for no reason. */

/* senior three: reviewed and accepted, left exactly as it was. */

/* duplex: the first attempt was too timid, and the arithmetic is why. At
   scale 1.38 the furthest an image can travel before its edge enters the box
   is about (S-1)/2S, roughly 14%, so a 9% offset was already near the limit
   and the centre of the frame — the palm cluster — stayed in shot. This one
   is scaled far enough to actually leave the middle, and pushed down and left
   onto the sand, the loungers and the water's edge, which is the part of this
   photograph the plate above never shows. */

/* ============================================================
   CINEMATIC COMPOSITION (the project the theme was first built for)
   Everything below is this project's page architecture rather
   than the platform's. The engineering above — tokens, motion
   contract, reveal/no-JS rule, focus states, RTL handling — is
   shared; the arrangement is not.

   The reference project opened on type, ran uniform bands down
   the page, numbered them 01/02/03, framed every photograph and
   put a stack of round contact buttons in the right margin.
   MARSA opens on water and is built the other way round: the
   photographs are unframed and full bleed, the text sits in a
   narrow measure against them, sections are marked with the
   rosette from the building rather than a numeral, and the only
   standing call to action is a word in the bar.
   ============================================================ */

/* ---- the bar: an overlay on the hero, a surface after it ---- */
.quaybar{
  position:absolute;top:0;inset-inline:0;z-index:90;
  display:flex;align-items:center;justify-content:space-between;
  gap:var(--s3);
  padding:calc(var(--s3) + env(safe-area-inset-top)) var(--gutter) var(--s3);
  color:var(--white);
  background:transparent;border:0;
  transition:background .4s var(--ease), color .4s var(--ease), box-shadow .4s var(--ease);
}
.quaybar__id{display:inline-flex;align-items:baseline;gap:.6em;min-height:44px;text-decoration:none;color:inherit;}
.quaybar__id img{height:34px;width:auto;}
.quaybar__name{font-family:var(--serif);font-size:1.4rem;letter-spacing:.02em;line-height:1;}
.quaybar__sub{
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;opacity:.78;
  /* Half of a lockup. Left to wrap it broke as "MARINA" over "5" on every
     English phone, which is the identity coming apart in the one place the
     reader looks first. */
  white-space:nowrap;
}
.quaybar__acts{display:flex;align-items:center;gap:clamp(.6rem,1.6vw,1.4rem);}
.quaybar__ask{
  display:none;align-items:center;min-height:40px;
  padding:.5rem 1.1rem;border-radius:var(--cut-pill);
  background:var(--clay);color:var(--white);text-decoration:none;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
}
.quaybar__ask:hover{background:var(--brand-deep);color:var(--white);}
.quaybar__lang{
  min-height:44px;display:inline-flex;align-items:center;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
  color:inherit;text-decoration:none;opacity:.9;
  border-bottom:1px solid currentColor;padding-bottom:2px;
}
.quaybar__lang[lang="ar"]{text-transform:none;letter-spacing:.02em;font-size:var(--fs-small);}
.quaybar__lang:hover{opacity:1;}
.quaybar__index{
  display:inline-flex;align-items:center;gap:.55em;min-height:44px;
  background:none;border:0;padding:0;cursor:pointer;color:inherit;
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
}
.quaybar__bars{display:inline-flex;flex-direction:column;gap:5px;width:22px;}
.quaybar__bars i{display:block;height:1.5px;background:currentColor;transition:transform .3s var(--ease);}
.quaybar__index[aria-expanded="true"] .quaybar__bars i:first-child{transform:translateY(3.25px) rotate(45deg);}
.quaybar__index[aria-expanded="true"] .quaybar__bars i:last-child{transform:translateY(-3.25px) rotate(-45deg);}

/* Once the photograph has gone past there is nothing to sit on, so the bar
   takes a ground, turns its type back to ink, and offers the sales line. */
.quaybar.is-past{
  position:fixed;top:0;
  background:rgba(252,248,242,.985);
  backdrop-filter:blur(14px);
  color:var(--ink);
  box-shadow:0 1px 0 var(--hair), 0 10px 30px -26px rgba(36,26,17,.55);
}
/* Below this the bar is carrying the lockup, the language switch and the
   index in about 340px, and the word beside the bars is the one part of it
   that the bars already say. It is hidden from the eye and kept for the
   accessibility tree, which is where it is naming the button. */
@media (max-width:559.98px){
  .quaybar__index-t{
    position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
  }
  /* With the word taken out of the flow the button is as wide as the bars,
     which is 22px — under the minimum target. The width is put back on the
     control rather than on the label. */
  .quaybar__index{gap:0;min-width:44px;justify-content:flex-end;}
}
@media (min-width:820px){ .quaybar.is-past .quaybar__ask{display:inline-flex;} }
@media (prefers-reduced-motion:reduce){ .quaybar{transition:none;} }

/* ---- the arrival: the photograph is the hero ---- */
.arrival{
  position:relative;isolation:isolate;
  /* The visible viewport on a phone is the screen less the action bar. Sized
     to the full 100svh the hero's own foot — the four standing facts, the
     things a reader who never scrolls is meant to leave with — sat behind
     that bar on arrival at every phone width. */
  min-height:min(calc(100svh - var(--dock-h)),860px);
  /* And the head of it is reserved for the bar. The type block is aligned to
     the end of its track and therefore grows upward; with nothing held back
     at the top it grew straight under the header, and at 320px the hero
     title sat 25px above the bottom of the identity that names it — two
     MARSAs on top of one another. The reservation costs nothing while the
     copy fits, because the block is still aligned to the foot; when the copy
     does not fit, the section grows instead of colliding. That is true for
     any width and any length of sentence, in either language, so it needs no
     breakpoint to know about it. */
  padding-top:var(--bar-h);
  display:grid;grid-template-rows:1fr auto;
  color:var(--white);
  background:var(--deep);
}
.arrival__shot{position:absolute;inset:0;z-index:-2;}
.arrival__shot img{width:100%;height:100%;object-fit:cover;object-position:50% 46%;display:block;}
/* The type sits on the water, so it needs a ground of its own. A gradient
   rather than a flat scrim: the top stays clear for the bar, the foot goes
   dark enough to carry the strip.
   
   The stops are where they are because of what is behind them rather than
   by eye. Sampling the photograph under the hero sentence with the type
   hidden, the brightest pixels behind it — the sunlit terracotta roof —
   were reaching a luminance of .688 at 320px and .309 at 1440. Against
   near-white type that is 1.35:1 and 2.77:1, both far under the 4.5:1 the
   sentence needs.
   
   The answer is not a darker overlay across the whole frame: that is the
   one thing this hero cannot afford, because the water and the terracotta
   are the identity. So the ramp is reshaped instead of deepened — the top
   quarter stays as open as it was, and the band where the type actually
   sits carries the weight. */
.arrival::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(11,58,71,.52) 0,
    rgba(11,58,71,.16) 24%,
    rgba(11,58,71,.62) 56%,
    rgba(11,58,71,.80) 76%,
    rgba(11,58,71,.90) 100%);
}
/* On a phone the type block is two thirds of the frame rather than a third,
   so the band it needs starts higher up. */
@media (max-width:759.98px){
  .arrival::after{
    background:linear-gradient(to bottom,
      rgba(11,58,71,.52) 0,
      rgba(11,58,71,.20) 16%,
      rgba(11,58,71,.70) 38%,
      rgba(11,58,71,.82) 64%,
      rgba(11,58,71,.90) 100%);
  }
}
.arrival__type{
  align-self:end;
  padding:var(--s7) var(--gutter) var(--s5);
  max-width:min(48rem,92vw);
}
.wordmark{
  font-family:var(--serif);font-weight:var(--fw-display);
  font-size:clamp(3rem,10vw,6.6rem);line-height:.92;
  letter-spacing:-.03em;color:var(--white);
}
.wordmark__a{display:block;}
.wordmark__b{
  display:block;margin-top:.5rem;
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.42em;text-transform:uppercase;opacity:.9;
}
.arrival__line{
  margin-top:var(--s4);max-width:34rem;
  font-size:var(--fs-body-lg);line-height:var(--lh-body);color:rgba(252,248,242,.94);
}
.arrival__cta{
  display:inline-flex;align-items:center;min-height:52px;margin-top:var(--s4);
  padding:.85rem 1.9rem;border-radius:var(--cut-pill);
  background:var(--clay);color:var(--white);text-decoration:none;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
  transition:background .3s var(--ease);
}
.arrival__cta:hover{background:var(--brand-deep);color:var(--white);}

/* The standing facts, run along the foot of the photograph. A reader who
   never scrolls still leaves knowing the four things that matter. */
.quay{
  display:grid;grid-template-columns:repeat(2,1fr);
  margin:0;padding:0 var(--gutter) calc(var(--s4) + env(safe-area-inset-bottom));
  list-style:none;gap:var(--s3) var(--s4);
  border-top:1px solid rgba(252,248,242,.24);padding-top:var(--s3);
  margin-inline:var(--gutter);
}
.quay__item{display:flex;flex-direction:column;gap:.2rem;min-width:0;}
.quay__k{
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
  color:rgba(252,248,242,.7);
}
.quay__v{font-family:var(--serif);font-size:var(--fs-body-lg);line-height:1.25;color:var(--white);}
@media (min-width:760px){
  .quay{grid-template-columns:repeat(4,1fr);}
  .arrival__type{padding-bottom:var(--s6);}
}

/* ---- narrow phones, deliberately rather than by accident ----
   Below about 380px the hero is carrying the same four elements in roughly
   forty fewer pixels of width, so the English sentence runs to eight lines
   and each standing fact wraps to three. The answer is not to shrink the
   hero: the wordmark, the sentence and the action all keep their size. What
   changes is the two places where the narrow column costs the most —
   the air above the type, and the value type in the four facts, which is
   set at reading size in a column barely wide enough for two words. Set one
   step down and closed up, the values take two lines instead of three and
   the whole hero fits above the action bar again. */
@media (max-width:379.98px){
  /* The English sentence runs two lines longer here than it does at 390, so
     its top edge reaches into the open part of the ramp. Measured with the
     type hidden, 2% of the pixels behind it were still lighter than
     near-white type can sit on; the band starts a little higher on this
     width alone, which leaves 390 and above exactly as they are. */
  .arrival::after{
    background:linear-gradient(to bottom,
      rgba(11,58,71,.52) 0,
      rgba(11,58,71,.20) 14%,
      rgba(11,58,71,.70) 33%,
      rgba(11,58,71,.82) 64%,
      rgba(11,58,71,.90) 100%);
  }
  .arrival__type{padding-top:var(--s5);}
  /* 1.75 on a 320px column puts the English sentence on eight lines and
     pushes its first line up into the open part of the scrim. 1.55 is still
     above the 1.5 a paragraph is owed, holds the sentence on seven lines,
     and keeps its top edge inside the band that carries it. */
  .arrival__line{line-height:1.55;}
  .quay{gap:var(--s2) var(--s3);}
  .quay__v{font-size:var(--fs-body);line-height:1.22;}
  .quay__k{letter-spacing:.1em;}
}

/* ---- the narrow measure
   Body copy runs in a single column at a reading measure, offset from the
   leading edge, rather than in the two-column wall the reference used. */
.column{
  max-width:var(--frame);margin-inline:auto;
  padding:var(--s8) var(--gutter) var(--s5);
}
.column__head{
  font-family:var(--serif);font-size:var(--fs-h1);font-weight:var(--fw-h1);
  line-height:var(--lh-h);letter-spacing:var(--tr-h);
  max-width:22ch;color:var(--ink-2);
}
.column__lede{
  margin-top:var(--s3);max-width:46ch;
  font-size:var(--fs-body-lg);line-height:var(--lh-body);color:var(--ink);
}
.column__prose{margin-top:var(--s3);max-width:60ch;color:var(--muted);line-height:var(--lh-body);}
.column--note{
  padding-top:0;padding-bottom:var(--s7);
  max-width:none;font-size:var(--fs-small);color:var(--muted);
}
.column--note{max-width:var(--frame);}

/* The section mark, in place of a numeral. */
.mark{margin:0 0 var(--s3);color:var(--clay);line-height:0;}
.mark .rosette{display:block;}

/* ---- full-bleed photography: no frame, no radius ---- */
.bleed{margin:0;position:relative;}
.bleed img{width:100%;height:auto;display:block;border-radius:0;}
.bleed__cap{
  padding:var(--s2) var(--gutter) 0;
  font-size:var(--fs-caption);letter-spacing:.04em;color:var(--muted);
}
@media (min-width:900px){
  .bleed img{max-height:78vh;object-fit:cover;object-position:50% 52%;}
}

/* ---- the claim: the differentiator, given its own moment ---- */
.claim{background:var(--paper);}
.claim__frame{
  max-width:var(--frame);margin-inline:auto;
  padding:var(--s8) var(--gutter) var(--s6);
  display:grid;gap:var(--s5);
}
.claim__head{
  font-family:var(--serif);font-weight:var(--fw-display);
  font-size:clamp(2rem,4.4vw,3.2rem);line-height:1.08;letter-spacing:var(--tr-display);
  max-width:16ch;color:var(--ink-2);
}
.claim__prose{margin-top:var(--s3);max-width:56ch;line-height:var(--lh-body);color:var(--ink);}
.credits{
  margin:0;display:grid;gap:0;align-content:start;
  border-top:2px solid var(--clay);padding-top:var(--s3);
}
.credits>div{display:flex;flex-direction:column;gap:.15rem;padding-block:.7rem;border-bottom:1px solid var(--hair);}
.credits>div:last-child{border-bottom:0;}
.credits dt{
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--muted);
}
.credits dd{margin:0;font-family:var(--serif);font-size:var(--fs-h3);color:var(--ink-2);line-height:1.2;}
@media (min-width:900px){
  .claim__frame{grid-template-columns:minmax(0,1.55fr) minmax(16rem,.85fr);gap:var(--s7);align-items:start;}
}

/* ---- the folio: unit types as a ruled sheet, not cards ---- */
.folio{
  list-style:none;margin:0 auto;padding:0 var(--gutter) var(--s5);
  max-width:var(--frame);
  border-top:2px solid var(--clay);
}
.folio__row{
  display:grid;grid-template-columns:1fr auto;
  gap:.35rem var(--s4);align-items:baseline;
  padding-block:var(--s4);
  border-bottom:1px solid var(--line);
}
.folio__name{
  grid-column:1;font-family:var(--serif);font-weight:var(--fw-h2);
  font-size:clamp(1.4rem,2.6vw,2rem);line-height:1.15;letter-spacing:var(--tr-h);color:var(--ink-2);
}
.folio__beds{grid-column:1;margin:0;display:flex;align-items:baseline;gap:.45em;color:var(--ink);}
.folio__beds .fig{font-family:var(--num);font-size:var(--fs-body-lg);font-weight:var(--fw-button);color:var(--brand-deep);}
.folio__beds span{font-size:var(--fs-small);}
/* The action, understated. Four outlined pills down a ruled sheet gave every
   row the weight of a pricing table and drew the eye away from the thing the
   row is actually about, which is the unit name. It is a word with a rule
   under it instead — the same device the rest of the page uses for a
   secondary action — and it still carries a 46px target.
   
   On a phone it drops under the specification rather than sitting beside the
   name, so each row reads down in the order it should: name, count, what it
   comes with, then what to do about it. */
.folio__ask{
  grid-column:1;justify-self:start;margin-top:.15rem;
  display:inline-flex;align-items:center;min-height:46px;
  color:var(--brand-deep);text-decoration:none;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;white-space:nowrap;
  border-bottom:1px solid var(--clay);
  transition:color .28s var(--ease), border-color .28s var(--ease);
}
.folio__ask:hover{color:var(--ink-2);border-bottom-color:var(--ink-2);}
@media (min-width:760px){
  /* Proportional, not two fixed columns and a stretched one. Pinning the
     name to 15rem and the count to 9rem left the specification cell holding
     roughly half the row for a line of text a third that long, so every row
     ended in a void before the action. */
  .folio__row{grid-template-columns:minmax(0,3fr) minmax(0,2fr) minmax(0,4fr) auto;align-items:center;}
  .folio__name{grid-column:1;}
  .folio__beds{grid-column:2;}
  .folio__ask{grid-column:4;grid-row:auto;justify-self:end;margin-top:0;}
}

/* ---- the standing contact stack is not this project's answer.
   Three circles in the right margin is the reference project's device and it
   competes with the photography here. The bar carries the enquiry link once
   it has a ground, and the phone keeps its foot bar. */
.standing.cta-rail{display:none;}

/* The foot bar, set as a quay rather than as three coloured tiles. */
@media (max-width:900px){
  .dock{
    background:rgba(11,58,71,.97);backdrop-filter:blur(10px);
    border-top:1px solid rgba(252,248,242,.16);
  }
  .dock a{
    color:var(--on-deep);border-inline-end:1px solid rgba(252,248,242,.16);
    font-size:var(--fs-caption);font-weight:var(--fw-button);
    letter-spacing:var(--tr-label);text-transform:uppercase;
  }
  .dock a:active{background:var(--clay);}
}

/* ---- rhythm
   Sections alternate ground rather than repeating one band, and the vertical
   step is wider than the reference used, because this page has fewer things
   in it and each is meant to land on its own. */
.room--place{background:var(--band);}
.room--warm{background:var(--paper);}
.room--folio{background:var(--paper);}
.room--read{background:var(--paper-2);}
.room--gallery{background:var(--paper);}

/* RTL: the bar, the strip and the folio all mirror from logical properties
   already; the only thing that needs saying is the wordmark's tracking, which
   is a Latin device and does not belong on the Arabic lockup. */
[dir="rtl"] .wordmark__b{letter-spacing:.12em;}
[dir="rtl"] .quaybar__sub{letter-spacing:.08em;}

/* ============================================================
   COMPOSITION: ARCHITECTURAL
   A second art direction, not a skin of the first. Every
   selector below is its own — .railbar not .quaybar, .plinth
   not .arrival, .schedule not .folio — so the two compositions
   share the engine above and nothing else. Neither can be
   reduced to the other by changing a palette.

   Where cinematic overlaps type and photograph, this separates
   them. Where cinematic leads with a view, this leads with a
   measured field. Where cinematic marks a section with a motif,
   this marks it with a position in a set.
   ============================================================ */

.pn-comp-architectural{ --frame:1360px; }

/* ---- the rail: present from the first pixel, never changes state ---- */
.railbar{
  position:sticky;top:0;z-index:90;
  background:var(--paper);
  border-bottom:1px solid var(--line);
}
.railbar__inner{
  max-width:var(--frame);margin-inline:auto;
  padding:0 var(--gutter);
  display:grid;grid-template-columns:auto 1fr auto;align-items:stretch;
  gap:var(--s4);
}
.railbar__id{
  display:flex;flex-direction:column;justify-content:center;gap:.28rem;
  min-height:74px;padding-inline-end:var(--s4);
  text-decoration:none;color:var(--ink-2);
  border-inline-end:1px solid var(--line);
}
.railbar__id img{height:30px;width:auto;}
.railbar__name{
  font-family:var(--sans);font-weight:var(--fw-button);
  font-size:1.05rem;letter-spacing:.2em;text-transform:uppercase;line-height:1;
}
.railbar__rule{display:none;}
.railbar__sub{
  font-family:var(--sans);font-size:var(--fs-caption);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);line-height:1;
}
/* The sections listed across the rail, not hidden behind a trigger. */
.railbar__nav{display:none;align-items:center;gap:clamp(.9rem,2vw,2rem);min-width:0;}
.railbar__nav a{
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-body);
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
  text-decoration:none;padding-block:.4rem;white-space:nowrap;
  border-bottom:1px solid transparent;
}
.railbar__nav a:hover{color:var(--ink-2);border-bottom-color:var(--ink-2);}
.railbar__acts{display:flex;align-items:center;gap:var(--s3);}
.railbar__lang{
  min-height:44px;display:inline-flex;align-items:center;
  font-size:var(--fs-caption);letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);text-decoration:none;
}
.railbar__lang[lang="ar"]{text-transform:none;letter-spacing:.02em;font-size:var(--fs-small);}
.railbar__lang:hover{color:var(--ink-2);}
.railbar__index{
  display:inline-flex;align-items:center;gap:.5em;min-height:44px;
  background:none;border:0;padding:0;cursor:pointer;color:var(--ink-2);
  font-family:var(--sans);font-size:var(--fs-caption);
  letter-spacing:.14em;text-transform:uppercase;
}
.railbar__index-t{display:none;}
.railbar__bars{display:inline-flex;flex-direction:column;gap:4px;width:20px;}
.railbar__bars i{display:block;height:1px;background:currentColor;}
@media (min-width:1100px){
  .railbar__nav{display:flex;}
  .railbar__index{display:none;}
  .railbar__index-t{display:inline;}
}

/* ---- the plinth: a measured split, nothing overlapping ---- */
.plinth{
  background:var(--paper);
  border-bottom:1px solid var(--line);
}
.plinth__grid{
  max-width:var(--frame);margin-inline:auto;
  padding:var(--s7) var(--gutter) var(--s6);
  display:grid;gap:var(--s5);
}
.plinth__say{display:flex;flex-direction:column;align-items:flex-start;}
.plinth__id{margin:0;}
.plinth__a{
  display:block;font-family:var(--sans);font-weight:var(--fw-button);
  font-size:clamp(2.4rem,6vw,4.6rem);line-height:1;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2);
  text-wrap:balance;
}
.plinth__b{
  display:block;margin-top:var(--s3);padding-top:var(--s3);
  border-top:1px solid var(--ink-2);
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-body);
  letter-spacing:.3em;text-transform:uppercase;color:var(--muted);
  min-width:min(18rem,100%);
}
.plinth__line{
  margin-top:var(--s4);max-width:38ch;
  font-size:var(--fs-body);line-height:var(--lh-body);color:var(--ink);
}
/* The standing facts as a plain schedule under the type, not a strip over
   a photograph: the reader is meant to compare them, not glance at them. */
.plinth__spec{
  margin:var(--s5) 0 0;width:100%;
  display:grid;grid-template-columns:1fr 1fr;gap:0;
  border-top:1px solid var(--line);
}
.plinth__spec>div{
  padding:.85rem 0;border-bottom:1px solid var(--line);
  display:flex;flex-direction:column;gap:.2rem;
}
.plinth__spec>div:nth-child(odd){padding-inline-end:var(--s4);}
.plinth__spec dt{
  font-size:var(--fs-caption);letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.plinth__spec dd{margin:0;font-size:var(--fs-body);color:var(--ink-2);}
.plinth__cta{
  display:inline-flex;align-items:center;min-height:50px;margin-top:var(--s5);
  padding:.8rem 2rem;border-radius:0;
  border:1px solid var(--ink-2);background:none;color:var(--ink-2);
  text-decoration:none;font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.18em;text-transform:uppercase;
  transition:background .28s var(--ease), color .28s var(--ease);
}
.plinth__cta:hover{background:var(--ink-2);color:var(--paper);}
.plinth__plate{margin:0;}
.plinth__plate img{width:100%;height:auto;display:block;border-radius:0;}
.plinth__plate figcaption{
  margin-top:var(--s2);padding-top:var(--s2);border-top:1px solid var(--line);
  font-size:var(--fs-caption);letter-spacing:.06em;color:var(--muted);
}
@media (min-width:960px){
  .plinth__grid{
    grid-template-columns:minmax(0,5fr) minmax(0,7fr);
    gap:var(--s7);align-items:start;
    padding-block:var(--s8) var(--s7);
  }
  .plinth__plate img{aspect-ratio:4/5;object-fit:cover;object-position:50% 45%;}
}

/* ---- the index mark: a position in a set, not a motif ---- */
.indexmark{
  margin:0 0 var(--s3);display:flex;align-items:center;gap:var(--s3);
  font-family:var(--num);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.2em;color:var(--muted);
}
.indexmark::after{content:"";flex:1 1 auto;height:1px;background:var(--line);max-width:120px;}

/* ---- the schedule: aligned columns, one rule per row ---- */
.schedule{max-width:var(--frame);margin-inline:auto;padding:0 var(--gutter) var(--s5);min-width:0;}
.schedule__table{width:100%;border-collapse:collapse;text-align:start;}
.schedule__table caption.skip-cap,.skip-cap{
  position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
}
.schedule__table th,.schedule__table td{
  text-align:start;padding:1rem var(--s3) 1rem 0;border-bottom:1px solid var(--line);
  vertical-align:baseline;
}
.schedule__table thead th{
  border-bottom:1px solid var(--ink-2);
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
  padding-bottom:.7rem;
}
.schedule__table tbody th{
  font-family:var(--sans);font-weight:var(--fw-button);
  font-size:var(--fs-body-lg);letter-spacing:.04em;color:var(--ink-2);
}
.schedule__table tbody td{font-size:var(--fs-small);color:var(--muted);}
.schedule__table .fig{font-family:var(--num);font-size:var(--fs-body-lg);color:var(--ink-2);}
.schedule__act{text-align:end;padding-inline-end:0;}
.schedule__act a{
  display:inline-flex;align-items:center;min-height:40px;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-2);text-decoration:none;border-bottom:1px solid var(--ink-2);
}
.schedule__act a:hover{color:var(--brand-deep);border-bottom-color:var(--brand-deep);}

/* A five column schedule does not belong on a phone, and sliding it sideways
   is not a fix — a reader comparing types cannot compare what is off screen.
   Below the breakpoint each row becomes its own block with the column head
   carried in front of every value, so the same table reads down the page.
   The markup does not change, so the table semantics and the header
   association survive for a screen reader. */
@media (max-width:759.98px){
  .schedule__table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);}
  .schedule__table tr{display:block;padding-block:var(--s3);border-bottom:1px solid var(--line);}
  .schedule__table tbody th,
  .schedule__table tbody td{display:block;border:0;padding:0;}
  .schedule__table tbody th{margin-bottom:.5rem;font-size:var(--fs-h3);}
  .schedule__table tbody td{
    display:flex;justify-content:space-between;gap:var(--s3);
    padding-block:.32rem;font-size:var(--fs-small);
  }
  .schedule__table tbody td::before{
    content:attr(data-label);
    font-size:var(--fs-caption);letter-spacing:.14em;text-transform:uppercase;
    color:var(--muted);flex:0 0 auto;
  }
  .schedule__act{justify-content:flex-start;padding-top:var(--s2);}
  .schedule__act::before{content:none;}
}

/* ---- rhythm: measured rather than open ---- */
.pn-rhythm-measured .column{padding-block:var(--s7) var(--s4);}
.pn-rhythm-measured .column__head{max-width:26ch;}
.pn-rhythm-measured .bleed img{max-height:62vh;}

/* ------------------------------------------------------------
   The architectural palette.

   The engine's tokens were measured for a terracotta project and
   carry its hue in the accent, the focus ring and the checkbox.
   Inherited unchanged, a second project reads as the first one
   in a different photograph. Architectural takes the same warm
   ground and the same near black type — those are legible, not
   branded — and replaces the accent with weight rather than
   colour: a graphite that reads as ink under pressure. Nothing
   below is a new colour system; it is the removal of one
   project's signature from another project's page.
   ------------------------------------------------------------ */
.pn-comp-architectural{
  --brand:#2B2723;
  --brand-deep:#2B2723;   /* 14.6:1 on paper — accent by weight, not hue */
  --brand-ink:#2B2723;
  --line:rgba(21,14,8,.15);
  --hair:rgba(21,14,8,.08);
  --cut:0px;
  --cut-sm:0px;
}

/* ---- the rail with an index of one, or none ----
   The middle cell still has to exist or the identity and the
   actions collapse together against the leading edge. It holds
   the measure open and carries nothing. */
.railbar__gap{display:block;}
.railbar__go{
  display:none;align-items:center;min-height:44px;
  padding-inline-end:var(--s3);margin-inline-end:var(--s3);
  border-inline-end:1px solid var(--line);
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-2);text-decoration:none;
}
.railbar__go:hover{color:var(--muted);}
@media (min-width:560px){ .railbar__go{display:inline-flex;} }

/* ------------------------------------------------------------
   The plinth as a cover.

   A split needs two things to split. Before a project's
   photograph and its schedule have been issued there is one —
   its name — and a hero that keeps the two column grid for it
   is a layout waiting for content, which is exactly what reads
   as broken. So the field is held whole instead: the mark and
   its rule at the top, the name set large against the leading
   edge, the action at the foot, and the rest deliberately air.
   No box is drawn where a photograph would go, because there is
   no photograph; nothing is greyed out to stand in for a fact.
   ------------------------------------------------------------ */
.plinth--cover .plinth__grid{
  grid-template-columns:minmax(0,1fr);
  min-height:clamp(30rem, calc(100svh - 74px), 46rem);
  padding-block:var(--s6) var(--s7);
  /* One row that fills the field, so the say block can distribute inside
     it: mark at the head, name on the optical centre, action at the foot.
     Sized to content instead, the whole cover stacks at the top and the
     air collects underneath, which is the arrangement this replaces. */
  align-content:stretch;align-items:stretch;
  gap:var(--s6);
}
.plinth--cover .plinth__say{
  justify-content:space-between;flex:1 1 auto;width:100%;
  gap:var(--s6);
}
.plinth--cover .indexmark{
  margin:0;width:100%;
}
.plinth--cover .indexmark::after{max-width:none;}
.plinth--cover .plinth__id{
  margin-block:auto;padding-block:var(--s5);
  border-bottom:1px solid var(--line);width:100%;
}
.plinth--cover .plinth__a{
  font-size:clamp(2.6rem,10vw,7.5rem);
  letter-spacing:.04em;line-height:.94;
}
.plinth--cover .plinth__cta{margin-top:0;}
@media (min-width:960px){
  .plinth--cover .plinth__grid{
    grid-template-columns:minmax(0,1fr);
    padding-block:var(--s8) var(--s8);
  }
  /* No measure on the name. A cap in ch units breaks a wordmark at
     whatever point the project's own name happens to reach it, which is a
     wrap that looks designed on one name and wrong on the next. The size
     clamp holds it inside the field instead, and it breaks only when the
     name is genuinely too long for the width. */
  .plinth--cover .plinth__id{max-width:none;}
}

/* ------------------------------------------------------------
   The enquiry, set as a drawing rather than as a card.

   The cinematic office lifts the form onto a white card with a
   soft shadow, which is how a brochure presents a coupon. This
   composition presents it the way it presents everything else:
   ruled, aligned to the leading edge, no raised surface, the
   labels carrying the structure. Same markup, same fields, same
   validation — only the drawing changes.
   ------------------------------------------------------------ */
.pn-comp-architectural .room--office{
  background:var(--paper);
  border-block:1px solid var(--line);
}
.pn-comp-architectural .room--office .frame{
  background:none;border:0;border-radius:0;box-shadow:none;
  padding-inline:var(--gutter);
  padding-block:var(--s7);
}
.pn-comp-architectural .room--office .room__name{
  color:var(--muted);
  font-size:var(--fs-caption);letter-spacing:.2em;text-transform:uppercase;
}
.pn-comp-architectural .cell>span{
  color:var(--ink-2);letter-spacing:.16em;
}
/* A ruled field, not an underlined one: the box is the drawing. */
.pn-comp-architectural .cell input,
.pn-comp-architectural .cell select,
.pn-comp-architectural .cell textarea{
  border:1px solid var(--line);border-radius:0;
  padding:.7rem .85rem;background:var(--paper-3);
}
.pn-comp-architectural .cell select,
.pn-comp-architectural .phone-combo__cc{
  background-position:right 0.85rem center,right 0.52rem center;
}
[dir="rtl"].pn-comp-architectural .cell select,
[dir="rtl"].pn-comp-architectural .phone-combo__cc{
  background-position:left 0.52rem center,left 0.85rem center;
}
.pn-comp-architectural .phone-combo__cc{
  border:1px solid var(--line);border-radius:0;
  padding:.7rem 1.9rem .7rem .85rem;background-color:var(--paper-3);
}
.pn-comp-architectural .cell input:focus,
.pn-comp-architectural .cell select:focus,
.pn-comp-architectural .cell textarea:focus{
  border-color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--ink-2);
}
.pn-comp-architectural .phone-combo{align-items:stretch;}
.pn-comp-architectural .btn--send{
  border-radius:0;letter-spacing:.18em;
}

/* Solo: the enquiry is the only thing on the page below the cover.
   It keeps the band's two column measure — the section mark in the
   position the address column would hold, the form on the trailing
   columns — so the page reads as a document with one section left to
   read rather than as a form that has taken the site over. */
/* The office band carries its own generous padding on top of the frame's,
   which is right when the band holds an address column and a form and
   wrong when it holds a form alone: the two stack into a screen of air
   under the button. The band gives its padding back to the frame. */
.pn-comp-architectural .room--office-solo{padding-block:var(--s4);}
.pn-comp-architectural .room--office-solo .frame{
  max-width:var(--frame);margin-inline:auto;
  padding-block:var(--s6);
}
.pn-comp-architectural .enquiry--solo{
  gap:var(--s5);
  border-top:1px solid var(--ink-2);
  padding-top:var(--s5);
}
@media (min-width:900px){
  .pn-comp-architectural .enquiry--solo{
    grid-template-columns:minmax(0,3fr) minmax(0,8fr);
    column-gap:var(--s7);align-items:start;
  }
  .pn-comp-architectural .enquiry--solo .enquiry__mark{grid-column:1;}
  .pn-comp-architectural .enquiry--solo .pn-form{grid-column:2;}
  .pn-comp-architectural .enquiry--solo .fields{grid-template-columns:1fr 1fr;}
}

/* The country selector has to stay usable at the narrowest width: the
   code and the number share one row on a phone and the code is held to
   a legible measure rather than being squeezed to an arrow. */
@media (max-width:420px){
  .pn-comp-architectural .phone-combo{grid-template-columns:minmax(5.6rem,7rem) 1fr;}
  .pn-comp-architectural .phone-combo__cc{
    max-width:none;padding-inline:.55rem 1.5rem;font-size:var(--fs-small);
    background-position:right 0.42rem center,right 0.22rem center;
  }
  [dir="rtl"].pn-comp-architectural .phone-combo__cc{
    padding-inline:1.5rem .55rem;
    background-position:left 0.22rem center,left 0.42rem center;
  }
}

/* ---- the actions ----
   The engine reserves terracotta for exactly one control, the enquiry
   submit, so that it means "this is the thing to press". The reasoning
   holds; the colour belongs to the other project. Here the same rule is
   carried by weight: the one solid control on the page. */
.pn-comp-architectural .btn{
  background:var(--ink-2);border-color:var(--ink-2);color:var(--paper);border-radius:0;
}
.pn-comp-architectural .btn:hover{background:var(--muted);border-color:var(--muted);}
.pn-comp-architectural .btn--send{
  background:var(--ink-2);border-color:var(--ink-2);color:var(--paper);
}
.pn-comp-architectural .btn--send:hover{
  background:var(--muted);border-color:var(--muted);color:var(--paper);
}

/* ---- the mark in the address column ----
   Held to the top of its column so it rules across to the form rather
   than floating beside it. */
.pn-comp-architectural .enquiry__mark .indexmark{margin:0;}
.pn-comp-architectural .enquiry__mark .indexmark::after{max-width:none;}

/* ---- the colophon on a page with almost nothing in it ----
   The engine's footer is a two column grid sized for an imprint and a
   row of contact icons. With neither issued it opens a void between the
   mark and the index. Here the two sit on one line and the legal rule
   closes immediately under them. */
.pn-comp-architectural .colophon .frame{row-gap:var(--s3);}
@media (min-width:1024px){
  .pn-comp-architectural .colophon .frame{
    grid-template-columns:auto 1fr;align-items:baseline;
  }
  .pn-comp-architectural .colophon__index{
    grid-column:2;grid-row:1;justify-self:end;margin-top:0;
  }
}

/* ---- the colophon ----
   The engine closes on the bay: a deep teal band drawn from the other
   project's water. There is no water here, and a coloured band under an
   otherwise ruled ivory page reads as a fragment of a different site. The
   page ends on the same ground it began on, with one rule and the mark
   set in the same face as the rail and the cover. */
.pn-comp-architectural .colophon{
  background:var(--paper);color:var(--ink);
  border-top:1px solid var(--ink-2);
}
.pn-comp-architectural .colophon a,
.pn-comp-architectural .colophon .logo__name,
.pn-comp-architectural .colophon__mark .logo__name{color:var(--ink-2);}
.pn-comp-architectural .colophon .prose,
.pn-comp-architectural .colophon p{color:var(--muted);}
.pn-comp-architectural .colophon__mark .logo__name{
  font-family:var(--sans);font-weight:var(--fw-button);
  font-size:var(--fs-h3);letter-spacing:.2em;text-transform:uppercase;
}
.pn-comp-architectural .colophon__mark .logo__by{color:var(--muted);}
.pn-comp-architectural .colophon__legal{
  border-top-color:var(--line);color:var(--muted);
}
.pn-comp-architectural .colophon__index a{
  font-size:var(--fs-caption);letter-spacing:.16em;text-transform:uppercase;
}

/* ---- the close of the residences section ----
   The four types end on the page's primary action rather than on a note.
   Not a banner and not a second CTA system: the same words the hero and the
   bar use, set once, on the leading edge, with the note that says who
   confirms availability sitting above it rather than being replaced by it. */
.folio__close{
  max-width:var(--frame);margin-inline:auto;
  padding:var(--s5) var(--gutter) var(--s7);
  display:grid;gap:var(--s3);justify-items:start;
  border-top:var(--rule) solid var(--hair);
}
.folio__close-note{margin:0;font-size:var(--fs-small);color:var(--muted);max-width:62ch;}
.folio__close-ask{
  margin:0;max-width:44ch;
  font-family:var(--serif);font-size:var(--fs-h3);line-height:var(--lh-h);color:var(--ink-2);
}
[dir="rtl"] .folio__close-ask{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.folio__close-cta{margin-top:var(--s2);}
@media (min-width:900px){
  .folio__close{
    grid-template-columns:minmax(0,1fr) auto;
    align-items:end;column-gap:var(--s6);
  }
  .folio__close-note{grid-column:1;grid-row:1;}
  .folio__close-ask{grid-column:1;grid-row:2;}
  .folio__close-cta{grid-column:2;grid-row:2;margin-top:0;justify-self:end;}
}

/* ============================================================
   THE ORIENTATION PLATE
   The one aerial the project owns, given the room it earns,
   with the things in it named where they stand. Not a master
   plan: no boundary, no phase, no plot, no distance. A reader
   who never scrolls past this should still know what MARSA is
   and how its parts sit together.
   ============================================================ */
.orient{
  margin:var(--s7) 0 0;
  display:grid;gap:var(--s4);
}
.orient__plate{
  position:relative;line-height:0;
  background:var(--band);
}
.orient__plate img{width:100%;height:auto;display:block;}
.orient__pins{position:absolute;inset:0;pointer-events:none;}
/* Physical left/top, deliberately. Logical properties would mirror these
   under RTL and slide every marker off the building it points at — the
   photograph does not flip with the language. */
.orient__pin{
  position:absolute;transform:translate(-50%,-50%);
  width:34px;height:34px;border-radius:var(--cut-pill);
  display:grid;place-items:center;
  background:rgba(252,248,242,.94);
  box-shadow:0 2px 10px -3px rgba(11,58,71,.55);
}
.orient__pin b{
  font-family:var(--num);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.06em;color:var(--brand-deep);
}
.orient__key{margin:0;display:grid;gap:var(--s3);}
.orient__cap{
  margin:0;max-width:60ch;
  font-size:var(--fs-small);color:var(--muted);line-height:var(--lh-body);
}
.orient__list{
  list-style:none;margin:0;padding:0;
  display:grid;gap:0;counter-reset:orient;
  border-top:var(--rule) solid var(--line);
}
.orient__list li{
  counter-increment:orient;
  display:grid;grid-template-columns:2.4rem 1fr;align-items:baseline;
  gap:.2rem var(--s3);
  padding-block:.85rem;border-bottom:var(--rule) solid var(--hair);
}
.orient__list li::before{
  content:counter(orient,decimal-leading-zero);grid-row:span 2;
  font-family:var(--num);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.16em;color:var(--brand-deep);
}
.orient__name{
  font-family:var(--serif);font-size:var(--fs-body-lg);color:var(--ink-2);line-height:1.2;
}
[dir="rtl"] .orient__name{font-family:var(--ar-display);}
.orient__note{font-size:var(--fs-small);color:var(--muted);line-height:var(--lh-body);}
@media (min-width:900px){
  .orient{
    grid-template-columns:minmax(0,7fr) minmax(0,3fr);
    gap:var(--s6);align-items:start;
  }
  .orient__pin{width:40px;height:40px;}
}
@media (max-width:479.98px){
  /* Four markers on a 320px-wide frame would sit on top of one another.
     The picture keeps its markers only where they can be told apart; below
     that the numbered key carries the whole job on its own. */
  .orient__pins{display:none;}
}

/* The location section with no drive times to show: the prose leads the
   spread rather than sitting in half of a two column grid with nothing
   opposite it. The heading holds the leading column, the reading matter
   the trailing one, and the orientation plate below carries the picture. */
.place--wide{grid-template-columns:minmax(0,1fr);}
@media (min-width:900px){
  .place--wide .place__say{
    display:grid;
    grid-template-columns:minmax(0,4fr) minmax(0,6fr);
    column-gap:var(--s7);align-items:start;
  }
  /* The label and the heading hold the leading column; everything that is
     read — the lede and the prose — flows down the trailing one. */
  .place--wide .place__say > *{grid-column:2;}
  .place--wide .place__say .room__name{grid-column:1;grid-row:1;margin-block-end:var(--s2);}
  .place--wide .place__say .h-room{grid-column:1;grid-row:2;margin:0;}
  .place--wide .place__say .lede{margin-top:0;}
  .place--wide .place__say .prose{max-width:62ch;}
}

/* ============================================================
   THE MODEL — four steps, numbered
   "Hotel-managed" was on the page nine times and explained
   nowhere. Set as a numbered sequence rather than as cards,
   because the four are an order of events, not a menu.
   ============================================================ */
.room--model{background:var(--band);border-block:var(--rule) solid var(--line);}
.steps{
  list-style:none;margin:var(--s6) auto 0;padding:0 var(--gutter);
  max-width:var(--frame);
  display:grid;gap:0;
  border-top:2px solid var(--clay);
}
.steps__item{
  display:grid;grid-template-columns:3.2rem 1fr;
  gap:.3rem var(--s4);align-items:baseline;
  padding-block:var(--s4);
  border-bottom:var(--rule) solid var(--line);
}
.steps__n{
  grid-row:span 2;
  font-family:var(--num);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:.18em;color:var(--brand-deep);
}
.steps__t{
  margin:0;font-family:var(--serif);font-size:var(--fs-h3);font-weight:var(--fw-h3);
  line-height:var(--lh-h);color:var(--ink-2);
}
[dir="rtl"] .steps__t{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.steps__p{margin:0;color:var(--muted);line-height:var(--lh-body);max-width:64ch;}
@media (min-width:900px){
  .steps__item{grid-template-columns:3.2rem minmax(0,4fr) minmax(0,6fr);align-items:baseline;}
  .steps__n{grid-row:auto;}
  .steps__t{grid-column:2;}
  .steps__p{grid-column:3;}
}

/* ============================================================
   TRANSPARENCY — two columns, confirmed against unconfirmed
   Replaces a disclaimer that was repeated in six sections. The
   two columns are deliberately equal in weight: the point is
   that the page is as clear about what it will not say as
   about what it will.
   ============================================================ */
.ledger2{
  max-width:var(--frame);margin:var(--s6) auto 0;padding:0 var(--gutter) var(--s6);
  display:grid;gap:var(--s6);
}
.ledger2__col{display:grid;gap:var(--s3);align-content:start;}
.ledger2__head{
  margin:0;padding-bottom:var(--s2);
  border-bottom:2px solid var(--clay);
  font-family:var(--sans);font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ink-2);
}
[dir="rtl"] .ledger2__head{font-family:var(--ar-sans);letter-spacing:.02em;}
.ledger2__col--ask .ledger2__head{border-bottom-color:var(--line);color:var(--muted);}
.ledger2__list{list-style:none;margin:0;padding:0;display:grid;gap:0;}
.ledger2__list li{
  padding-block:.8rem;border-bottom:var(--rule) solid var(--hair);
  color:var(--ink);line-height:var(--lh-body);
  display:grid;grid-template-columns:1.5rem 1fr;gap:var(--s2);align-items:baseline;
}
.ledger2__col--yes .ledger2__list li::before{
  content:"";width:9px;height:9px;border-radius:var(--cut-pill);
  background:var(--clay);transform:translateY(-.15em);
}
.ledger2__col--ask .ledger2__list li{color:var(--muted);}
.ledger2__col--ask .ledger2__list li::before{
  content:"";width:9px;height:9px;border-radius:var(--cut-pill);
  border:1.5px solid var(--line);transform:translateY(-.15em);
}
.ledger2__cta{
  justify-self:start;margin-top:var(--s2);min-height:44px;
  display:inline-flex;align-items:center;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
  color:var(--brand-deep);text-decoration:none;
  border-bottom:1px solid var(--clay);
}
.ledger2__cta:hover{color:var(--ink-2);border-bottom-color:var(--ink-2);}
@media (min-width:820px){
  .ledger2{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s7);}
}

/* The standard, stated once for the collection instead of four times down
   the sheet. Two facts, ruled apart, sitting under the section prose. */
.folio__std{
  margin:var(--s4) 0 0;display:flex;flex-wrap:wrap;gap:.5rem var(--s4);
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ink-2);
}
[dir="rtl"] .folio__std{letter-spacing:.02em;text-transform:none;font-size:var(--fs-small);}
.folio__std span{display:inline-flex;align-items:center;gap:.6rem;}
.folio__std span + span::before{
  content:"";width:5px;height:5px;border-radius:var(--cut-pill);background:var(--clay);
}

/* ============================================================
   FALLBACK VIEWS — 404 and anything not a landing page
   These render rarely, but when they do they have to be the
   same site. The overlay header is knockout type built to sit
   on the hero photograph; with no photograph behind it the
   identity and the index were white on lime. The bar takes its
   solid state here from the first pixel, and the content takes
   the gutters and the measure the rest of the site uses.
   ============================================================ */
.pn-plain .quaybar{
  position:sticky;top:0;
  background:var(--paper);
  color:var(--ink);
  border-bottom:var(--rule) solid var(--hair);
}
.pn-plain .quaybar__lang,
.pn-plain .quaybar__index{color:var(--ink);}

.pn-plain .wrap{
  max-width:var(--frame);
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.pn-plain .wrap.section{padding-block:var(--s7) var(--s8);}
.pn-plain .prose{max-width:68ch;}
.pn-plain .prose + .prose{margin-top:var(--s6);padding-top:var(--s5);border-top:var(--rule) solid var(--hair);}
.pn-plain .prose h1{
  font-family:var(--serif);font-size:var(--fs-h1);font-weight:var(--fw-h1);
  line-height:var(--lh-h);color:var(--ink-2);margin:0 0 var(--s5);
}
[dir="rtl"].pn-plain .prose h1{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.pn-plain .prose h2{
  font-family:var(--serif);font-size:var(--fs-h3);font-weight:var(--fw-h3);
  line-height:var(--lh-h);color:var(--ink-2);margin:0 0 var(--s2);
}
[dir="rtl"].pn-plain .prose h2{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.pn-plain .prose__body{color:var(--muted);line-height:var(--lh-body);}
.prose__more{margin-top:var(--s3);}
.prose__more a{
  display:inline-flex;align-items:center;min-height:44px;
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;
  color:var(--brand-deep);text-decoration:none;
  border-bottom:1px solid var(--clay);
}
[dir="rtl"] .prose__more a{letter-spacing:.02em;text-transform:none;font-size:var(--fs-small);}
.prose__more a:hover{color:var(--ink-2);border-bottom-color:var(--ink-2);}
.pn-plain .prose__cta{margin-top:var(--s5);}

/* ============================================================
   THE TURN
   A pause, not a section. Everything above it is the site as it
   stands; everything below is what a buyer owns. The page used
   to pass that hinge with the same gap it puts between any two
   sections, so the change of subject had no signal at all.
   Three lines on the stone band, no image and no action —
   a pause only works if it is quiet.
   ============================================================ */
.turn{
  background:var(--band);
  border-block:var(--rule) solid var(--line);
  padding-block:clamp(3.5rem,9vw,7rem);
}
.turn__inner{
  max-width:var(--frame);margin-inline:auto;padding-inline:var(--gutter);
  display:grid;gap:var(--s2);justify-items:start;
}
.turn__a{
  margin:0;font-family:var(--serif);font-weight:var(--fw-h1);
  font-size:clamp(1.9rem,4.4vw,3.1rem);line-height:1.08;
  letter-spacing:var(--tr-h);color:var(--ink-2);text-wrap:balance;
}
[dir="rtl"] .turn__a{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.turn__b{
  margin:0;font-family:var(--serif);font-weight:var(--fw-h1);
  font-size:clamp(1.9rem,4.4vw,3.1rem);line-height:1.08;
  letter-spacing:var(--tr-h);color:var(--clay);text-wrap:balance;
}
[dir="rtl"] .turn__b{font-family:var(--ar-display);line-height:var(--lh-h-ar);}
.turn__c{
  margin:var(--s4) 0 0;padding-top:var(--s3);
  border-top:2px solid var(--clay);
  font-size:var(--fs-caption);font-weight:var(--fw-button);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--muted);
}
[dir="rtl"] .turn__c{
  font-family:var(--ar-sans);letter-spacing:.02em;text-transform:none;
  font-size:var(--fs-small);
}
