/* ===========================================================================
   EMAAR DESIGN SYSTEM · 04 — LAYOUT
   The page shell: container, grid, section rhythm, full-bleed, masthead.

   ---------------------------------------------------------------------------
   THE GRID
   ---------------------------------------------------------------------------
                 gutter              container        columns   gap
     ≥1440       72px (capped)       1320 / 1500      12        28px
     1024–1439   5vw                 fluid            12        2vw
     600–1023    4vw                 fluid             6        2vw
     ≤599        20px                fluid             1        16px

   Two container widths and no third:

     --em-container       1320px   words, cards, forms, every reading page
     --em-container-wide  1500px   a picture-led page that needs the extra air

   A page does not invent a container. If a section needs to be wider than
   1500 it is FULL BLEED (.em-bleed) and paints its own ground; if it needs to
   be narrower it is a MEASURE (--em-container-text, --em-container-form)
   inside the standard one.

   ---------------------------------------------------------------------------
   SECTION RHYTHM
   ---------------------------------------------------------------------------
     --space-band         between two bands of content   48 → 86
     --space-band-tight   between two closely-related    30 → 48
     --space-band-tail    under the last wrapped column  70 → 120
     --space-section      inside a full-bleed band       56 → 110

   A page descends ONCE: ground → sand → night. See DESIGN-STANDARDS.md §6.

   Figma mapping: Foundation Library → Layout grids
   (`Grid / Desktop 12`, `Grid / Tablet 6`, `Grid / Mobile 1`).
   =========================================================================== */


/* ———————————————————————— 1 · Container ———————————————————————— */

.em-main { display: block; }

.em-wrap {
  max-width: var(--em-container);
  margin: 0 auto;
  padding: 0 var(--em-gutter);
}
.em-wrap--wide {
  max-width: var(--em-container-wide);
  padding: 0 var(--em-gutter-wide);
}
/* A reading column inside the container. Both are `max-width` on the element,
   not a narrower container, so the element still sits on the page's own
   gutters and lines up with everything above it. */
.em-wrap--text { max-width: var(--em-container-text); }
.em-wrap--form { max-width: var(--em-container-form); }


/* ———————————————————————— 2 · The 12-column grid ————————————————————————

   Used where content is genuinely columnar. Most of this site is not: a card
   row is `repeat(auto-fill, minmax())` because the number of cards is data,
   not design. Reach for the 12 only when a composition is DESIGNED against
   it — an editorial split, a spine and a rail, a form's two-up fields.

   Named `.em-columns`, NOT `.em-grid`: `.em-grid` is already the site's card
   row (an auto-fill track set, in places.css §14) and the two are different
   ideas. A designed composition takes columns; a list of cards takes a row
   that reflows on its own.

   `minmax(0, 1fr)` and not `1fr`: a 1fr track floors at max-content, so one
   unbreakable string — a long URL, a 44-character heading — widens the track,
   the grid and the page with it. */

.em-columns {
  display: grid;
  grid-template-columns: repeat(var(--em-grid-columns), minmax(0, 1fr));
  gap: var(--em-grid-gap);
}
.em-columns > * { min-width: 0; }

@media (max-width: 1023px) { .em-columns { --em-grid-columns: 6; } }
@media (max-width: 599px)  { .em-columns { --em-grid-columns: 1; } }

/* Spans. Only the ones a composition actually uses. */
.em-span-3  { grid-column: span 3; }
.em-span-4  { grid-column: span 4; }
.em-span-5  { grid-column: span 5; }
.em-span-6  { grid-column: span 6; }
.em-span-7  { grid-column: span 7; }
.em-span-8  { grid-column: span 8; }
.em-span-12 { grid-column: 1 / -1; }

@media (max-width: 1023px) {
  .em-span-3, .em-span-4, .em-span-5  { grid-column: span 3; }
  .em-span-6, .em-span-7, .em-span-8  { grid-column: span 6; }
}
@media (max-width: 599px) {
  .em-span-3, .em-span-4, .em-span-5,
  .em-span-6, .em-span-7, .em-span-8  { grid-column: 1 / -1; }
}

/* A vertical rhythm primitive. One gap, set once, instead of a margin on
   every child and a `:last-child` to take it off again. */
.em-stack      { display: flex; flex-direction: column; gap: var(--space-16); }
.em-stack--sm  { gap: var(--space-8); }
.em-stack--lg  { gap: var(--space-28); }


/* ———————————————————————— 3 · Section rhythm ———————————————————————— */

.em-band        { margin-top: var(--space-band); }
.em-band--tight { margin-top: var(--space-band-tight); }
.em-band--tail  { padding-bottom: var(--space-band-tail); }

/* The tail is the air under a WRAPPED COLUMN — the page ground showing below
   the last line of a measure. A full-bleed closing band is not that: it paints
   its own ground from edge to edge and carries its own padding, so a tail
   below one renders as a strip of page ground trapped between the band and the
   footer. That strip is what put a 92px cream sliver between the launches
   register band and the black footer, and it read as a mistake because it is
   one. :has() is the whole rule; where it is unsupported the declaration is
   dropped and the old spacing comes back, which is loose, not broken. */
.em-band--tail:has(> .em-bleed:last-child) { padding-bottom: 0; }

/* Full-bleed.
   NOT 100vw. `100vw` is the viewport INCLUDING the classic scrollbar, so on any
   page tall enough to scroll it is wider than the scrollport — the element
   overflows by the scrollbar's width, the page grows, and because a page that
   overflows widens the layout viewport, the next 100vw is wider still. Every
   bleed element in these templates is already a direct child of a full-width
   block (#em-main, or a section that carries no max-width), so plain 100% is
   both correct and immune. Never nest a .em-bleed inside .em-wrap:
   assertLayout() reports it if you do. */
.em-bleed { width: 100%; margin-left: 0; }


/* ———————————————————————— 4 · The text masthead ————————————————————————

   Measured across all 43 internal pages, a page title landed at y=240 on the
   27 that use .ab-mast and at 148, 211 or 225 on the three built from
   .em-top — two masthead implementations of one idea, drifting apart. The
   total height of a text masthead is properly copy-dependent, but where the
   TITLE lands is the cue a reader learns, and it has to be the same door
   every time. See DESIGN-STANDARDS.md §9.

   Scoped with :has() to the .em-top blocks that actually open a page with a
   title — .em-top is also the tail band mid-page on several templates, and
   that use must keep its own spacing.

   The arithmetic, matching .ab-mast exactly:
     header clearance 112 + crumb 44 + crumb gap 44 = 200, then 40 to the
     title — spent either on an eyebrow and its gap, or on the title's own
     top margin when there is no eyebrow.

   CLEARANCE IS ADDED TO, NEVER SPENT. A component may push its opening
   further down the page; it may never replace --em-header-clearance with a
   smaller number, because the header is FIXED and whatever is under it is
   not merely hidden, it is unclickable. */

.em-top { padding-top: var(--em-header-clearance); }

.em-top:has(> .em-h1) { padding-top: calc(var(--em-header-height) + clamp(22px, 3.4vw, 40px)); }
.em-top:has(> .em-h1) > .em-crumb { margin-bottom: clamp(26px, 3.4vw, 44px); }
.em-top:has(> .em-h1) > .em-crumb + .em-eyebrow { margin-top: 0; margin-bottom: 23px; }
.em-top:has(> .em-h1) > .em-eyebrow + .em-h1 { margin-top: 0; }
/* Adjacent siblings COLLAPSE: with the crumb's 44px gap below it, a 40px
   margin here would have resolved to max(44, 40) = 44 and landed the title
   at 200, not 240 — which is exactly what it did on first measurement. The
   gap has to be carried whole by the larger of the two. */
.em-top:has(> .em-h1) > .em-crumb + .em-h1 {
  margin-top: calc(clamp(26px, 3.4vw, 44px) + 40px);
}


/* ———————————————————————— 5 · The photograph ————————————————————————

   ONE media frame for the whole site: `.em-shot`. It clips, it carries the
   ground colour behind the picture while the picture loads, and its <img>
   covers. A ratio modifier is the only thing a caller chooses.

   Six ratios and no seventh. A ratio is a CONTENT decision — what the
   photograph is OF — so the set is named for the subject:

     .em-shot--banner     1.949/1   the wide editorial / hero band
     .em-shot--16x9      16/9       a landscape hero or film frame
     .em-shot--16x10     16/10      THE default photograph on this site
     .em-shot--3x2        3/2       a property / project / news card
     .em-shot--4x5        4/5       the phone hero, a person, a tower
     .em-shot--1x1        1/1       a thumbnail, a logo plate

   `--2x1` is kept as an alias of `--banner` because twelve pieces of markup
   already carry it; it is the same 1.949/1 it always was.

   object-position is `center` by default and that is usually WRONG for
   architecture — a tower cropped from the centre loses its crown. Set it per
   image where it matters. That is a content decision, not a token.

   THE FOCAL POINT IS HOW ONE FILE SERVES EVERY BREAKPOINT.

   This site ships ONE asset per placement — no <picture>, no media-switched
   <source>, one file that every viewport crops differently. That only works
   if the crop can be aimed, and until now it could not: `center` was hard
   -wired, so a record whose subject sits left of centre lost its subject on
   the phone and there was nothing a content editor could do about it except
   ask for a second file.

   Two custom properties, set on the FRAME, aim it:

     --em-focal      where the crop is anchored from 1024 up, and the
                     fallback everywhere else.        default 50% 50%
     --em-focal-sm   an override below 1024, where the containers on this
                     site turn portrait or square and the crop bites
                     hardest.                         defaults to --em-focal

   Measured: a 1.949:1 master in the 4:5 phone hero keeps 45% of its width; a
   2.7:1 businesses band keeps 32%. Which 32% is the whole argument, and it is
   one declaration, not one more upload.

     <div class="em-shot em-shot--16x10" style="--em-focal:38% 30%">

   A SECOND FILE IS THE LAST RESORT, NOT THE FIRST. Reach for the focal point,
   then for the container's ratio; ask for a mobile crop only when the subject
   genuinely cannot survive the frame — see docs/design-system/12-assets.md. */

.em-shot {
  position: relative; overflow: hidden;
  background: var(--em-surface-media);
  border-radius: var(--em-radius);
}
.em-shot--banner,
.em-shot--2x1   { aspect-ratio: var(--em-ratio-banner); }
.em-shot--16x9  { aspect-ratio: var(--em-ratio-hero); }
.em-shot--16x10 { aspect-ratio: var(--em-ratio-landscape); }
.em-shot--3x2   { aspect-ratio: var(--em-ratio-card); }
.em-shot--4x5   { aspect-ratio: var(--em-ratio-portrait); }
.em-shot--1x1   { aspect-ratio: var(--em-ratio-square); }
.em-shot > img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
  object-position: var(--em-focal, 50% 50%);
}
/* Below 1024 every art-directed container on this site has already changed
   shape — the hero drops its band for 4:5, the communities lead goes portrait
   — so this is where a separate anchor earns its keep. Inherits --em-focal
   when no phone-specific one is given, which is the common case. */
@media (max-width: 1023px) {
  .em-shot > img { object-position: var(--em-focal-sm, var(--em-focal, 50% 50%)); }
}
.em-shot__cap {
  font-size: var(--em-text-caption);
  line-height: var(--p-lh-snug);
  color: var(--em-text-muted);
  margin-top: var(--space-10);
}

/* The curtain frame must CLIP. Its picture is posed at scale(1.06) before the
   reveal, and a transform creates scrollable overflow: an un-clipped 1440px
   image at 1.06 is 1526px and hangs 43px off each edge, which widens the
   layout viewport, which widens every vw unit on the page. Declared outside
   the motion query so the clip exists whether or not the motion does. */
[data-em-reveal="media"] { overflow: hidden; border-radius: var(--em-radius); }
[data-em-reveal="media"] > img { display: block; width: 100%; }

/* Standard scrims. A page does not write its own gradient over a photograph:
   the scrim is what makes type legible on an image, and a page-specific one
   is a page-specific contrast ratio nobody measured. */
.em-scrim-bottom::after,
.em-scrim-top::after,
.em-scrim-flat::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  z-index: var(--z-raised);
}
.em-scrim-bottom::after { background: var(--em-veil-bottom); }
.em-scrim-top::after    { background: var(--em-veil-top); }
.em-scrim-flat::after   { background: var(--em-scrim); }
