@charset "UTF-8";
/* RWD — the descent, and the homepage's own blocks
   ==========================================================================
   What is left after the shared chrome moved to site.css: the plate and its
   travel, the keyhole, the key, the preloader, the curtain it opens onto,
   the record band, the chairman portrait, and the ongoing and homepage
   block layouts. Loaded by the homepage alone.
   ========================================================================= */

/* ---- The descent --------------------------------------------------------
   The track is a scroll spacer and nothing else; its height is how far the
   camera travels down the building. 400vh gives the plate room to move at a
   pace where the facade reads rather than streaks.
------------------------------------------------------------------------- */
.track{ height:400vh; position:relative }

/* Fixed, so the plate stays put while the page scrolls past it. hero.js
   translates it down and, once the curtain has fully arrived, moves the whole
   frame up so the two travel together. */
.frame{
  position:fixed; inset:0; z-index:0;
  overflow:hidden;
  background:var(--ink);
  will-change:transform;
}
/* Deliberately wider than the viewport — the overflow is what there is to
   descend through. Width and offset are set by hero.js from the measured
   position of the tower. */
.rig{
  position:absolute; top:0;
  transform:translate3d(0,0,0);
  will-change:transform;
}
.plate{ display:block; width:100%; max-width:none; height:auto }

/* ---- What lives on the plate (alive.js) ---------------------------------
   Both sized to the plate and masked by alive.js with maps keyed off the
   plate itself: the clouds to its sky, the glint to its building. */
.clouds, .glint{
  position:absolute; inset:0; pointer-events:none;
  -webkit-mask-size:100% 100%; mask-size:100% 100%;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
}
/* A band of cloud along the top of the plate, tiled across and drifting.
   Two tiles to the loop, so it comes round seamlessly. */
.clouds{
  opacity:0; transition:opacity 2.4s ease;
  background-repeat:repeat-x; background-size:50% 30%; background-position:0 1%;
  mix-blend-mode:screen;
  animation:kh-drift 180s linear infinite;
}
.clouds.on{ opacity:.55 }
@keyframes kh-drift{ from{ background-position:0% 1% } to{ background-position:200% 1% } }

/* Sun across the facade: a soft band that sweeps once every thirteen
   seconds and is otherwise not there. */
.glint{
  opacity:0; mix-blend-mode:screen;
  background:linear-gradient(105deg, rgba(255,240,214,0) 42%,
             rgba(255,240,214,.42) 50%, rgba(255,240,214,0) 58%) no-repeat;
  background-size:250% 100%; background-position:130% 0;
}
.glint.on{ animation:kh-glint 13s ease-in-out infinite }
@keyframes kh-glint{
  0%   { opacity:0; background-position:130% 0 }
  3%   { opacity:1 }
  24%  { opacity:1; background-position:-30% 0 }
  27%  { opacity:0; background-position:-30% 0 }
  100% { opacity:0; background-position:-30% 0 }
}
@media (prefers-reduced-motion:reduce){ .clouds, .glint{ display:none } }

/* Daylight flooding in as you step through the door. A warm white screened
   over the whole picture — it lifts every channel together, so a bright
   sky stays a sky instead of clipping to cyan. alive.js drives its
   opacity, and it is otherwise not there. */
.veil{
  position:absolute; inset:0; pointer-events:none;
  background:#FFF3E2; mix-blend-mode:screen;
  opacity:0; will-change:opacity;
}

/* The hero's own two faces, not the site's: a Didone at display size
   reads as expensive — the whole effect is the stroke contrast — and a
   geometric sans beside it for the small tracked lines. */
:root{
  --lux:var(--rwd-serif);
  --lux-sans:var(--rwd-sans);
}


/* Scrolling still works — the bar is only hidden, and the plate gets the
   full viewport width instead of losing ~15px to a track nothing needs. */
html{ scrollbar-width:none; -ms-overflow-style:none }
html::-webkit-scrollbar,
body::-webkit-scrollbar{ width:0; height:0; display:none }
/* clip, not hidden: overflow-x:hidden turns the body into a scroll container
   of its own, and position:sticky anywhere on the page then sticks to that
   box — which never scrolls — so nothing sticks at all (the footprint map,
   the project sheet's title rail). clip trims the same overflow without
   making a scroll container. hidden stays as the fallback. */
body{ overflow-x:hidden; overflow-x:clip }

/* ---- The keyhole --------------------------------------------------------
   An ink sheet with the shape cut out of it, sitting above the plate and
   below the header. The cut-out scales; the sheet does not.
------------------------------------------------------------------------- */
.keyhole{
  position:fixed; inset:0; z-index:60;
  pointer-events:none;
  opacity:1;
}
.keyhole[hidden]{ display:none }
.keyhole svg{ width:100%; height:100%; display:block }
#khhole{ fill:#000 }          /* black in the mask = cut away */
/* ---- The key -----------------------------------------------------------
   Above the sheet, below the header. hero.js measures the hole and hands
   its position over as custom properties; everything here hangs off them,
   so the line and the key stay seated on the hole at any viewport.
------------------------------------------------------------------------- */
.kh-intro{
  position:fixed; inset:0; z-index:61;
  pointer-events:none;
  color:#F3F0E9;
  will-change:transform, opacity;
}

/* The line, set round the keyhole, in the hero's own face and in its
   italic — the hand it would be written in. Everything inside is in the
   ring's own units, so the words scale with it. */
.kh-ring{
  position:absolute;
  width:var(--kh-ring); height:var(--kh-ring);
  left:calc(var(--kh-cx) - var(--kh-ring) / 2);
  top:calc(var(--kh-mid) - var(--kh-ring) / 2);
  overflow:visible;
}
.kh-arc{
  fill:currentColor;
  font:italic 400 21px var(--lux);
  letter-spacing:.02em;
  /* A little air between the words: on a curve the gaps close up on the
     inside of the ring, and the italic leans them together further. */
  word-spacing:.2em;
}

/* Written on a letter at a time, left to right along each curve: hero.js
   gives every letter its own tspan and its own delay. The top line first,
   then the bottom, done just before the key turns. */
.kh-ch{ fill-opacity:0; transition:fill-opacity .45s ease }
.kh-intro.on .kh-ch{ fill-opacity:1 }

/* "key", set apart in polished gold — the metal of the key turning above
   it, with a glint travelling across the word (the gradient is in the
   ring's defs) — and a size up. Plain gold where the gradient can't
   resolve. */
.kh-hl{ fill:url(#kh-gold) #CBAE80; font-size:24px }

/* Everything right of the rim is inside the lock. */
.kh-keyway{
  position:absolute; inset:0;
  clip-path:inset(0 calc(100% - var(--kh-rim)) 0 0);
}
/* The key in the round (key3d.js), when WebGL is there. Full screen, so the
   camera can put the key anywhere between the eye and the hole. */
.kh-3d{ position:absolute; inset:0; width:100%; height:100%; display:block }

/* The flat key, which plays when it is not. Cast gold, the one warm object
   on the ink. Seated with the bit and most
   of the shaft past the rim; hero.js starts it back along the shaft line
   and glides it home. The viewBox is 320 x 116 and centred on the shaft,
   so centring the box on the hole's round centres the shaft on it. */
.kh-key{
  position:absolute;
  width:var(--kh-kw); height:calc(var(--kh-kw) * .3625);
  left:calc(var(--kh-rim) - var(--kh-kw) * .65);
  top:calc(var(--kh-cy) - var(--kh-kw) * .18125);
  overflow:visible; opacity:0;
  will-change:transform, opacity;
}

/* ---- Preloader ----------------------------------------------------------
   Above everything, including the header. Nothing behind it is worth seeing
   half-built, and the page must not be scrollable underneath or the viewer
   lands somewhere in the middle when it clears.
------------------------------------------------------------------------- */
html.booting, html.booting body{ overflow:hidden }

.boot{
  position:fixed; inset:0; z-index:9999;
  background:var(--ink); color:var(--white);
  display:grid; place-items:center;
  transition:opacity .95s ease, transform .95s cubic-bezier(.16,.84,.30,1);
}
/* Lifting away rather than simply vanishing, so the cut to the tower reads
   as a dissolve between two shots. */
.boot.done{ opacity:0; transform:scale(1.04); pointer-events:none }
.boot[hidden]{ display:none }

.boot-inner{ display:grid; justify-items:center; padding:0 24px }

/* The webfonts are requested with display:swap, so anything painted before
   they land is drawn in the fallback and then redrawn. Everything here is
   held until document.fonts.ready and then brought up as a title card.

   --in is the one curve: a fast start and a very long tail, so the type
   arrives quickly and then takes its time settling. Each element is offset
   behind the one above it, and nothing moves far — a title sequence reads as
   slow because of duration, not distance. */
.boot-inner{ --in:cubic-bezier(.16,.84,.30,1) }

/* Racking into focus. The blur is what makes it read as film rather than as
   a web page fading an element in. */
.boot-mark{
  opacity:0; transform:translateY(16px) scale(.985); filter:blur(9px);
  transition:opacity 1.5s var(--in), transform 1.5s var(--in), filter 1.5s var(--in);
}
.boot.fonts-in .boot-mark{ opacity:1; transform:none; filter:blur(0) }

/* Letter-spacing settling inward — the oldest title-card trick there is, and
   the only place on the site where type animates. */
.boot-tag{
  opacity:0; letter-spacing:.62em; filter:blur(4px);
  transition:opacity 1.7s var(--in), letter-spacing 2s var(--in), filter 1.7s var(--in);
  transition-delay:.42s;
}
.boot.fonts-in .boot-tag{ opacity:1; letter-spacing:.28em; filter:blur(0) }

/* The bar and the count come last, and quietly — they are instrumentation,
   not the title. */
.boot-bar{
  opacity:0; transform:scaleX(.7); transform-origin:50% 50%;
  transition:opacity 1.1s var(--in), transform 1.4s var(--in);
  transition-delay:.9s;
}
.boot.fonts-in .boot-bar{ opacity:1; transform:none }

.boot-pct{
  opacity:0;
  transition:opacity 1.1s var(--in);
  transition-delay:1.15s;
}
.boot.fonts-in .boot-pct{ opacity:.85 }

.boot-mark{
  display:flex; align-items:center; gap:12px;
  font:400 clamp(38px,7vw,64px)/1 var(--disp);
  letter-spacing:.01em; text-transform:uppercase;
}
.boot-mark .dots i{ width:9px; height:9px }

.boot-tag{
  margin:16px 0 0;
  font:400 clamp(16px,1.4vw,16px)/1 var(--mono);
  letter-spacing:.28em; text-transform:uppercase; color:var(--grey);
}

.boot-bar{
  width:min(280px,54vw); height:2px; margin-top:clamp(34px,6vh,52px);
  background:rgba(118,188,33,.2);
}
.boot-bar u{
  display:block; height:100%; width:0; background:var(--green);
  /* Frames land in bursts, so ease the fill rather than let it twitch. */
  transition:width .3s cubic-bezier(.22,.61,.36,1);
}

.boot-pct{
  margin:14px 0 0;
  font:400 16px/1 var(--mono);
  letter-spacing:.16em; color:var(--grey);
  font-variant-numeric:tabular-nums;
}

/* If the manifest cannot be fetched the preloader is where the reason has to
   be said — there is nothing else on screen. */
.boot-error{
  max-width:46ch; margin:22px 0 0;
  font:400 16px/1.7 var(--body); color:var(--green); text-align:center;
}

/* ---- Fold -------------------------------------------------------------
   After React Bits' FoldText. Each letter is a panel hinged at its top edge,
   swung back past edge-on and folded down into place, with a crease shade
   over it that lifts as it opens. --d is the letter's own delay, set where
   the letters are made (Boot.astro, hero.js); what starts the run is the
   class on the parent — .fonts-in on the preloader, .on on the keyhole line.
   Plain transitions on power3.out's curve, so no animation library. */
.fold-seg{
  display:inline-block; perspective:700px; transform-style:preserve-3d;
  vertical-align:baseline;
}
.fold-pc{
  position:relative; display:inline-block;
  transform-origin:50% 0; transform:rotateX(-92deg);
  opacity:0; backface-visibility:hidden;
  transition:transform .65s cubic-bezier(.215,.61,.355,1) var(--d,0s),
             opacity .65s cubic-bezier(.215,.61,.355,1) var(--d,0s);
}
.fold-pc::after{
  content:''; position:absolute; inset:-.08em -.02em;
  pointer-events:none; border-radius:.08em; mix-blend-mode:multiply;
  background:linear-gradient(180deg, rgba(0,0,0,.58) 0%, rgba(0,0,0,.22) 42%,
                             rgba(255,255,255,.26) 100%);
  opacity:.55;
  transition:opacity .65s ease var(--d,0s);
}

@media (prefers-reduced-motion:reduce){
  .fold-pc{ transform:none !important; transition:opacity .22s ease var(--d,0s) }
  .fold-pc::after{ display:none }
}

@media (prefers-reduced-motion:reduce){
  .boot, .boot-bar, .boot-bar u, .boot-mark, .boot-tag, .boot-pct{
    transition:none !important; filter:none !important; transform:none !important;
  }
  .boot-tag{ letter-spacing:.28em }
}

/* ---- Landscape button --------------------------------------------------
   Offered, never forced. Portrait renders on its own; this only says a
   better view exists. Touch devices held upright only.
------------------------------------------------------------------------- */
.rotate{
  position:fixed; left:50%; bottom:24px; transform:translateX(-50%);
  z-index:90; display:none; align-items:center; gap:10px;
  padding:12px 18px;
  background:rgba(11,11,12,.82); backdrop-filter:blur(8px);
  border:1px solid rgba(118,188,33,.5);
  color:var(--white); font:500 16px/1 var(--body);
  letter-spacing:.04em; white-space:nowrap;
  cursor:pointer; -webkit-tap-highlight-color:transparent;
  opacity:0; transition:opacity .5s ease, transform .15s ease;
}
.rotate.show{ display:flex; opacity:1 }
.rotate:active{ transform:translateX(-50%) scale(.96) }
.rotate:focus-visible{ outline:2px solid var(--green); outline-offset:3px }
.rotate svg{
  width:17px; height:17px; flex:none;
  stroke:var(--green); fill:none; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
  animation:tip 3.4s ease-in-out infinite; transform-origin:50% 50%;
}
@keyframes tip{ 0%,58%{transform:rotate(0)} 72%,92%{transform:rotate(90deg)} 100%{transform:rotate(0)} }
@media (pointer:fine){ .rotate{ display:none!important } }


/* ---- The curtain --------------------------------------------------------
   The hero's own copy, held over the tower for the whole descent rather than
   arriving at the end of it. Fixed, like the frame it sits on: the building
   travels behind the words and the words do not move. hero.js carries both up
   together once the track runs out, which is the only time it leaves.

   No background of its own — the plate is the picture, and the wash below is
   all that stands between it and the type.

   pointer-events are off on the sheet and back on for the column alone, so
   the four fifths of the screen that are only photograph stay inert.
------------------------------------------------------------------------- */
.curtain{
  position:fixed; inset:0; z-index:4;
  display:flex; align-items:center;
  color:var(--white);
  pointer-events:none;
  will-change:transform;
}
.ct-plate{ pointer-events:auto }

/* Directional, not a blanket. The old top-to-bottom wash darkened the render
   evenly and put the type in a grey box; angling it holds the left column
   without touching the right two thirds of the picture, and the low bar
   underneath is only there to keep the buttons off the road markings. */
.curtain::before{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(102deg,
      rgba(11,11,12,.80)  0%,
      rgba(11,11,12,.58) 26%,
      rgba(11,11,12,.20) 52%,
      rgba(11,11,12,0)   74%),
    linear-gradient(180deg,
      rgba(11,11,12,0)   40%,
      rgba(11,11,12,.34) 100%);
}
.curtain-inner{
  position:relative;
  width:100%; max-width:1360px; margin:0 auto;
  padding:clamp(80px,10vh,120px) 32px clamp(56px,8vh,96px);
}

/* ---- The plate ----------------------------------------------------------
   Everything hangs off one left edge, marked by a hairline that runs the
   height of the block. The measure is capped well short of the viewport:
   a headline that runs the full width of a 1360px page is a banner, and a
   banner is the opposite of what this is meant to read as.
------------------------------------------------------------------------- */
.ct-plate{
  position:relative;
  max-width:min(680px, 56%);
  padding-left:clamp(22px,2.4vw,38px);
}
.ct-plate::before{
  content:""; position:absolute; left:0; top:.3em; bottom:.6em;
  width:1px; background:linear-gradient(180deg,
    rgba(255,255,255,.42), rgba(255,255,255,.06));
}

.curtain .ct-eyebrow{
  display:flex; align-items:center; gap:12px;
  margin:0 0 clamp(22px,3vh,34px);
  font:400 clamp(16px,.78vw,16px)/1 var(--lux-sans);
  text-transform:uppercase; letter-spacing:.3em;
  color:rgba(255,255,255,.70);
}
/* The site's default dot is 10px, drawn for a 14px sentence. Against an
   11px line tracked to .3em it reads as two bullets rather than as a mark. */
.ct-eyebrow .dots{ gap:5px }
.ct-eyebrow .dots i{ width:6px; height:6px }

/* Mixed case, and the emphasis carried by an italic rather than by brand
   colour. Green and blue on a 108px cap line read as a logo; the italic of a
   Didone reads as a voice, which is the register the descent above it set. */
.curtain h1{
  margin:0;
  font:400 clamp(38px,5.2vw,88px)/1.06 var(--lux);
  letter-spacing:0; text-transform:none;
  text-shadow:0 2px 40px rgba(11,11,12,.35);
}
.curtain h1 em{ font-style:italic; font-weight:400 }

/* The folded headline (Descent.astro splits it). The h1 sits out of the
   column's rise-and-fade — its letters do the arriving — and each word
   holds together so a line can only break between words. */
.ct-word{ display:inline-block; white-space:nowrap }
.ct-word.is-em{ font-style:italic; font-weight:400 }
.hero-live .curtain .ct-plate > h1.ct-fold{ opacity:1; transform:none }
.curtain.in .ct-fold .fold-pc{ transform:none; opacity:1 }
.curtain.in .ct-fold .fold-pc::after{ opacity:0 }
/* Without the intro (no script, or reduced motion) the words are simply
   there. */
html:not(.hero-live) .ct-fold .fold-pc{ transform:none; opacity:1 }
html:not(.hero-live) .ct-fold .fold-pc::after{ opacity:0 }
.curtain .sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}

.ct-rule{
  width:clamp(54px,6vw,92px); height:1px;
  margin:clamp(26px,3.6vh,42px) 0 clamp(24px,3.2vh,36px);
  background:rgba(255,255,255,.46);
}

.curtain .ct-sub{
  margin:0; max-width:44ch;
  font:400 clamp(16px,1.06vw,16px)/1.72 var(--lux-sans);
  color:rgba(255,255,255,.80);
}

/* ---- Actions ------------------------------------------------------------
   Square, generous, and tracked. The filled green button was the loudest
   element on a page that is otherwise a photograph; paper carries the same
   weight without competing with the render, and the brand greens stay where
   they belong — on the dots above and on the rest of the site.
------------------------------------------------------------------------- */
.ct-act{ display:flex; flex-wrap:wrap; gap:14px; margin-top:clamp(30px,4.4vh,48px) }

.ct-btn{
  display:inline-block;
  padding:clamp(14px,1.9vh,19px) clamp(24px,2.4vw,38px);
  font:400 clamp(16px,.84vw,16px)/1 var(--lux-sans);
  text-transform:uppercase; letter-spacing:.22em; text-decoration:none;
  transition:background .35s ease, color .35s ease,
             border-color .35s ease, transform .35s ease;
}
.ct-solid{
  background:var(--paper); color:var(--ink);
  border:1px solid var(--paper);
}
.ct-solid:hover{ background:transparent; color:var(--paper) }
.ct-line{
  background:transparent; color:#fff;
  border:1px solid rgba(255,255,255,.42);
}
.ct-line:hover{ border-color:#fff; background:rgba(255,255,255,.09) }

/* Below the fold of a phone the column has no room to be a column. */
@media (max-width:820px){
  .ct-plate{ max-width:none }
  .curtain::before{
    background:linear-gradient(180deg,
      rgba(11,11,12,.28) 0%, rgba(11,11,12,.52) 46%, rgba(11,11,12,.78) 100%);
  }
  .ct-act{ gap:11px }
  .ct-btn{ flex:1 1 auto; text-align:center }
}
@media (max-width:700px){ .curtain-inner{ padding-left:22px; padding-right:22px } }


/* ---- Numbers ------------------------------------------------------------
   Its own band on solid ink, below the hero rather than over it. It is also
   what covers the tower: the hero is released at the top of this section, so
   the film slides up as this arrives rather than showing through it.
------------------------------------------------------------------------- */
.stats{
  position:relative; z-index:2;
  background:var(--ink); color:var(--white);
  padding:clamp(54px,8vh,88px) 0;
}
.stats-inner{ width:min(1360px, calc(100% - 44px)); margin:0 auto }

/* The band was drawn for exactly this ground, so only two things change:
   it no longer hangs off the buttons above it, and the figures need fixed
   width because they are counting. */
.stats .stat-band{ margin-top:0 }
.stats .stat .num{
  /* Digits change every frame while counting; without tabular figures the
     whole band jitters sideways as it runs. */
  font-variant-numeric:tabular-nums;
}

@media (max-width:820px){
  /* Two up rather than four squeezed — the labels are long. */
  .stats .stat-band{ grid-template-columns:repeat(2,1fr) }
  .stats .stat{ padding:22px 18px 26px }
  .stats .stat:nth-child(even){ border-right:none }
  .stats .stat:nth-child(-n+2){ border-bottom:1px solid rgba(255,255,255,.18) }
}


/* ---- Reveal -------------------------------------------------------------
   The words fade up as they arrive rather than simply being there, staggered
   so the headline leads and the buttons land last. .no-reveal is the escape
   hatch for a browser where the observer never fires.
------------------------------------------------------------------------- */
[data-reveal]{
  opacity:0; transform:translateY(20px);
  transition:opacity .85s cubic-bezier(.22,.61,.36,1),
             transform .85s cubic-bezier(.22,.61,.36,1);
}
[data-reveal].is-in{ opacity:1; transform:none }

/* The curtain is on screen from first paint, so the page's observer would
   fire the moment it was registered — behind the splash, with nothing to
   see. hero.js adds .in as the keyhole opens instead, and the column plays
   the same stagger onto a building that is already there. */
.hero-live .curtain .ct-plate > *{
  opacity:0; transform:translateY(20px);
  transition:opacity .85s cubic-bezier(.22,.61,.36,1),
             transform .85s cubic-bezier(.22,.61,.36,1);
}
.curtain.in .ct-plate > *{ opacity:1; transform:none }

.ct-plate > *:nth-child(1){ transition-delay:0s }
.ct-plate > *:nth-child(2){ transition-delay:.10s }
.ct-plate > *:nth-child(3){ transition-delay:.22s }
.ct-plate > *:nth-child(4){ transition-delay:.34s }
.ct-plate > *:nth-child(5){ transition-delay:.46s }

.no-reveal [data-reveal]{ opacity:1; transform:none; transition:none }

@media (prefers-reduced-motion:reduce){
  [data-reveal]{ opacity:1; transform:none; transition:none }
  .curtain .ct-plate > *{ opacity:1; transform:none; transition:none }
  .rotate svg{ animation:none }
  *{ transition:none!important }
}

/* ---- Chairman portrait --------------------------------------------------
   No rule needed, and that is the point. The site crops this to a circle with
   object-fit:cover, and the plate supplied was 400x601 — a 1:1 box can only
   ever show a 400x400 slice of that, so no object-position existed that kept
   the whole head. assets/media/habib.jpg is stored pre-squared at 601x601,
   his own backdrop clamped outward to fill the margins, so cover has nothing
   left to crop. Replace it with another square plate and it still works.
------------------------------------------------------------------------- */


/* ==== ONGOING PROJECTS ===================================================
   Not three equal cards. Only one of the three has a render, and forcing the
   other two into the same frame made them look like failed image loads. The
   one with a photograph leads; the two that live on their own microsites sit
   beside it as a stacked pair, on ink, labelled for what they are.
========================================================================= */
.og-grid{
  display:grid; gap:clamp(18px,2.4vw,28px);
  grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  align-items:stretch;
}
@media (max-width:900px){ .og-grid{ grid-template-columns:1fr } }

/* ---- Lead --------------------------------------------------------------- */
.og-lead{
  display:flex; flex-direction:column;
  background:var(--white); border:1px solid var(--line);
  transition:border-color .25s ease, transform .25s ease, box-shadow .25s ease;
}
.og-lead:hover{
  border-color:var(--ink); transform:translateY(-4px);
  box-shadow:0 20px 44px rgba(11,11,12,.13);
}
.og-lead:focus-visible{ outline:2px solid var(--green); outline-offset:3px }

.og-shot{ position:relative; aspect-ratio:16/10; overflow:hidden; background:var(--ink) }
.og-shot img{
  width:100%; height:100%; object-fit:cover;
  transition:transform .7s cubic-bezier(.22,.61,.36,1);
}
.og-lead:hover .og-shot img{ transform:scale(1.045) }

.og-tag{
  position:absolute; top:16px; left:16px;
  display:inline-flex; align-items:center; gap:8px;
  padding:8px 13px; background:var(--ink); color:var(--white);
  font:500 16px/1 var(--mono); letter-spacing:.13em; text-transform:uppercase;
}
.og-tag i{ width:6px; height:6px; border-radius:50%; background:var(--green) }

/* Column, not a grid: the call to action takes margin-top:auto so it sits on
   the bottom edge whatever the card holds. The card is stretched to the height
   of the pair beside it either way, so anything else leaves a gap under the
   content. */
.og-info{
  padding:clamp(24px,2.6vw,34px);
  display:flex; flex-direction:column; flex:1 1 auto;
}
.og-loc{
  margin:0 0 10px;
  font:500 16px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--grey);
}
.og-lead h3{
  margin:0; font:400 clamp(24px,2.8vw,36px)/1.06 var(--disp);
  text-transform:uppercase; letter-spacing:-.015em; color:var(--ink);
}
.og-say{ margin:14px 0 0; max-width:44ch; color:var(--grey); font-size:16px; line-height:1.6 }

/* The numbers the buyer is actually comparing, on the card, so they do not
   have to open three pages to compare three projects. */
.og-about{
  margin:16px 0 0; max-width:52ch;
  font:400 16px/1.65 var(--body); color:#333834;
}
.og-rera{
  margin:20px 0 0;
  font:400 16px/1.6 var(--mono); letter-spacing:.02em; color:var(--grey);
}
.og-facts{
  list-style:none; display:flex; flex-wrap:wrap; gap:0;
  margin:26px 0 0; padding:0;
  border-top:1px solid var(--line);
}
.og-facts li{ flex:1 1 0; min-width:90px; padding:16px 18px 4px 0 }
.og-facts b{
  display:block; font:400 clamp(19px,2vw,24px)/1 var(--disp);
  color:var(--ink); font-variant-numeric:tabular-nums;
}
.og-facts span{
  display:block; margin-top:7px;
  font:500 16px/1.3 var(--mono); letter-spacing:.13em; text-transform:uppercase;
  color:var(--grey);
}

/* ---- The pair ----------------------------------------------------------- */
.og-stack{ display:grid; gap:clamp(18px,2.4vw,28px); grid-template-rows:1fr 1fr }
@media (max-width:900px){ .og-stack{ grid-template-rows:auto } }

.og-side{
  display:flex; flex-direction:column; justify-content:flex-end;
  padding:clamp(24px,2.4vw,32px);
  background:var(--ink); color:var(--white);
  border:1px solid var(--ink); border-top:3px solid var(--green);
  min-height:190px; position:relative; overflow:hidden;
  transition:border-color .25s ease, transform .25s ease;
}
.og-side:nth-child(2){ border-top-color:var(--blue) }
.og-side:hover{ transform:translateY(-4px) }
.og-side:focus-visible{ outline:2px solid var(--green); outline-offset:3px }

/* A wash rather than an initial. The old cards set a 150px outlined letter in
   the corner, which read as a placeholder waiting for a photograph. */
.og-side::after{
  content:""; position:absolute; inset:auto -20% -60% auto;
  width:70%; aspect-ratio:1; border-radius:50%;
  background:radial-gradient(circle, rgba(118,188,33,.18), transparent 68%);
  pointer-events:none;
}
.og-side:nth-child(2)::after{
  background:radial-gradient(circle, rgba(43,169,224,.18), transparent 68%);
}

.og-kind{
  margin:0 0 auto; position:relative;
  font:500 16px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--grey);
}
.og-side h3{
  margin:26px 0 0; position:relative;
  font:400 clamp(20px,2.1vw,27px)/1.08 var(--disp);
  text-transform:uppercase; letter-spacing:-.01em;
}
.og-side .og-loc{ margin:12px 0 0; color:#9AA39C; position:relative }
.og-spec{ margin:8px 0 0; position:relative; color:#C9C9C4; font-size:16px }

/* ---- Shared call to action ---------------------------------------------- */
.og-go{
  display:inline-flex; align-items:center; gap:10px;
  margin-top:auto; padding-top:26px; position:relative; align-self:start;
  font:500 16px/1 var(--mono); letter-spacing:.11em; text-transform:uppercase;
  padding-bottom:8px; border-bottom:2px solid var(--green);
}
.og-lead .og-go{ color:var(--ink) }
.og-side .og-go{ color:var(--white); border-bottom-color:rgba(255,255,255,.35) }
.og-go i{ font-style:normal; transition:transform .25s cubic-bezier(.4,0,.2,1) }
.og-lead:hover .og-go i,
.og-side:hover .og-go i{ transform:translateX(5px) }
.og-side:hover .og-go{ border-bottom-color:var(--green) }

@media (prefers-reduced-motion:reduce){
  .og-lead, .og-side, .og-shot img, .og-go i{ transition:none }
}


/* ---- Section headings ---------------------------------------------------
   The intro line was pushed to the far right by justify-content:space-between
   and left sitting on its own in the corner, tied to nothing — the wider the
   screen, the further it drifted from the heading it belongs to.

   Set under the heading instead, on a measure that keeps it readable. It is a
   subtitle, so it should read as one.
------------------------------------------------------------------------- */
.block-head{
  display:block;
  margin-bottom:clamp(34px,5vh,52px);
}
.block-head .lead{
  margin:18px 0 0; max-width:62ch;
  font-size:16.5px; line-height:1.65; color:var(--grey);
}
/* On the careers page the intro carries a link, which needs to look like one. */
.block-head .lead a{ color:var(--ink); border-bottom:1px solid var(--green) }
.block-head .lead a:hover{ color:var(--green-deep) }


/* ---- A side card that has a photograph ----------------------------------
   Marbella has a real aerial on its own microsite. Behind a scrim rather than
   above the text, so the pair still reads as one shape whether or not the
   other card ever gets an image of its own.
------------------------------------------------------------------------- */
.og-side.has-shot{ border-color:var(--ink) }
.og-side-shot{
  position:absolute; inset:0; z-index:0;
  width:100%; height:100%; object-fit:cover;
  transition:transform .7s cubic-bezier(.22,.61,.36,1);
}
.og-side.has-shot:hover .og-side-shot{ transform:scale(1.05) }
.og-side-scrim{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(180deg,
    rgba(11,11,12,.42) 0%, rgba(11,11,12,.62) 46%, rgba(11,11,12,.92) 100%);
}
/* The wash is there to fill an empty card; a photograph does that already. */
.og-side.has-shot::after{ display:none }
.og-side.has-shot > *{ position:relative; z-index:2 }

@media (prefers-reduced-motion:reduce){ .og-side-shot{ transition:none } }


/* ---- Why RWD ------------------------------------------------------------
   Five pillars, indexed. Replaces a three-item FIRST / THEN / ALWAYS block
   that the brief does not contain.
------------------------------------------------------------------------- */
.why{
  list-style:none; margin:0; padding:0;
  display:grid; gap:0 clamp(24px,4vw,56px);
  grid-template-columns:repeat(auto-fit,minmax(290px,1fr));
}
.why li{ padding:26px 0 24px; border-top:1px solid var(--line) }
.wy-n{
  display:block; margin-bottom:12px;
  font:400 16px/1 var(--mono); letter-spacing:.1em; color:var(--green-deep);
}
.why h3{
  margin:0 0 10px; font:400 20px/1.18 var(--disp);
  text-transform:uppercase; letter-spacing:-.01em; color:var(--ink);
}
.why p{ margin:0; max-width:46ch; font-size:16px; line-height:1.65; color:var(--grey) }

/* ---- Careers: why RWD --------------------------------------------------- */
.cr-why{
  list-style:none; margin:30px 0 0; padding:0;
  display:flex; flex-wrap:wrap; gap:10px;
}
.cr-why li{
  padding:9px 15px; border:1px solid var(--line-dark);
  font:500 16px/1 var(--mono); letter-spacing:.1em; text-transform:uppercase;
  color:#C9C9C4;
}


/* ==== HOMEPAGE BLOCKS ====================================================
   The five sections the brief specifies between the hero and the closing CTA.
========================================================================= */

/* ---- 05.2 Find your RWD address ----------------------------------------- */
.find-row{
  display:grid; gap:16px; align-items:end;
  grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  padding:clamp(22px,2.4vw,30px);
  background:var(--white); border:1px solid var(--line);
  border-top:3px solid var(--green);
}
.find-row label{ display:grid; gap:9px }
.find-row span{
  font:500 16px/1 var(--mono); letter-spacing:.14em; text-transform:uppercase;
  color:var(--grey);
}
.find-row select{
  width:100%; padding:13px 14px; font:400 16px/1.4 var(--body);
  color:var(--ink); background:var(--paper);
  border:1px solid var(--line); border-radius:0;
}
.find-row select:focus-visible{ outline:2px solid var(--green); outline-offset:1px }
.find-row .btn{ justify-content:center; height:47px }

/* ---- 05.5 Legacy -------------------------------------------------------- */
.legacy{ max-width:900px }
.lg-eyebrow{
  margin:0 0 20px; max-width:44ch;
  font:500 16px/1.5 var(--mono); letter-spacing:.12em; text-transform:uppercase;
  color:var(--green);
}
.legacy h2{
  margin:0 0 24px;
  font:400 clamp(28px,4vw,54px)/1.06 var(--disp);
  text-transform:uppercase; letter-spacing:-.02em; color:var(--white);
  text-wrap:balance;
}
.lg-copy{
  margin:0 0 32px; max-width:68ch;
  font:400 clamp(16px,1.7vw,18.5px)/1.68 var(--body); color:#D8D8D2;
}

/* ---- 05.7 Chennai footprint ---------------------------------------------
   Generated from the project data, so a new project puts its own
   neighbourhood on the rail without a second list to maintain.
------------------------------------------------------------------------- */
.loc-rail{ display:flex; flex-wrap:wrap; gap:10px }
.loc-chip{
  display:inline-flex; align-items:baseline; gap:10px;
  padding:13px 18px; cursor:pointer;
  background:var(--white); border:1px solid var(--line);
  transition:border-color .2s ease, background .2s ease;
}
.loc-chip span{ font:500 16px/1 var(--body); color:var(--ink) }
.loc-chip b{
  font:500 16px/1 var(--mono); letter-spacing:.06em; color:var(--green-deep);
}
.loc-chip:hover{ border-color:var(--ink); background:var(--paper) }
.loc-chip:focus-visible{ outline:2px solid var(--green); outline-offset:2px }

/* ---- 05.8 / 05.9 two-column blocks -------------------------------------- */
.land{
  display:grid; gap:clamp(24px,5vw,72px);
  grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  align-items:start;
}
@media (max-width:820px){ .land{ grid-template-columns:1fr; gap:26px } }
.land h2{
  margin:14px 0 0;
  font:400 clamp(25px,3.2vw,42px)/1.08 var(--disp);
  text-transform:uppercase; letter-spacing:-.015em; color:var(--ink);
  text-wrap:balance;
}
.land p{
  margin:0; max-width:56ch;
  font:400 clamp(16px,1.7vw,18px)/1.68 var(--body); color:#333834;
}
.land{ border-top:1px solid var(--line); padding-top:clamp(40px,5vw,64px) }


/* ---- Hidden sections ----------------------------------------------------
   .block sets its own display, so a bare [hidden] loses to it.
------------------------------------------------------------------------- */
[hidden]{ display:none !important }

/* A fixed box so four marks of different proportions sit on one optical
   baseline instead of each finding its own. */
.grp-mark{
  display:grid; place-items:center;
  height:86px; margin-bottom:20px;
}
.grp-mark img{ max-width:100%; max-height:86px; width:auto; object-fit:contain }

.grp-name{
  margin:0; font:600 16px/1.35 var(--body); color:var(--ink);
  padding-top:16px; border-top:1px solid var(--line);
}
.grp-say{
  margin:7px 0 0;
  font:400 16px/1.4 var(--mono); letter-spacing:.08em; color:var(--grey);
}


/* ---- Section headings, matched to the project sheet ---------------------
   The sheet opens a section with a mono label, a hairline out to the column
   edge, then a large display heading. The homepage had a smaller label, no
   rule, and an h2 a step down from the sheet's — so the same site read as two.
   One treatment now, everywhere.
------------------------------------------------------------------------- */
.block-head .eyebrow{
  display:flex; align-items:center; gap:18px;
  font-size:16px; font-weight:500; letter-spacing:.16em;
  color:var(--ink);
}
/* The rule runs from the label to the edge of the measure. */
.block-head .eyebrow::after{
  content:""; flex:1 1 auto; height:1px; background:var(--line);
}
.band-dark .block-head .eyebrow::after,
.beyond .block-head .eyebrow::after{ background:var(--line-dark) }

.block-head h2{
  margin-top:20px;
  font-size:clamp(34px,5vw,68px);
  line-height:.98;
  letter-spacing:-.025em;
  text-wrap:balance;
}


/* ---- Beyond RWD ---------------------------------------------------------
   The group's marks in a row on the page ground, the way the group is shown
   on rwd.in. No cards, no captions: every one of these logos already
   contains its own company name and strapline, so anything set underneath
   repeats it.

   The row is centred on a shared optical baseline because the marks have
   very different proportions — NXG is squarish, Wavoo is tall, the two Ramky
   marks are wide. Columns go down to 150px so six still sit on one row.
------------------------------------------------------------------------- */
.group-strip{
  list-style:none; margin:0; padding:0;
  display:grid; gap:clamp(28px,5vw,72px);
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  align-items:center; justify-items:center;
}
.group-strip li{ display:grid; place-items:center; width:100% }
.group-strip img{
  max-width:min(100%,230px); max-height:120px;
  width:auto; height:auto; object-fit:contain;
  /* They are set on white and the page ground is a warm off-white, so a touch
     of desaturation stops them sitting on a brighter patch than the page. */
  mix-blend-mode:multiply;
}
/* The others carry a wide white margin inside their files; Vistawh's runs
   edge to edge, so at the same box it reads twice their weight. Held down
   to sit level with them. */
.group-strip img[src$="vistawh.png"]{ max-width:min(100%,175px) }
/* A company with no artwork yet, set as a wordmark in the site's face. */
.group-strip .group-word{
  font:600 clamp(22px,2.4vw,30px)/1 var(--rwd-sans);
  letter-spacing:.02em; color:#1A1A1A; white-space:nowrap;
}

@media (max-width:640px){
  .group-strip{ grid-template-columns:repeat(2,1fr); gap:34px }
  .group-strip img{ max-height:92px }
  /* A mark left on its own in the last row is centred under the pair. */
  .group-strip li:last-child:nth-child(odd){ grid-column:1 / -1 }
}
