﻿/* ==========================================================================
   Sdeira Group homepage (Arabic) - page stylesheet
   ==========================================================================
   Lifted verbatim out of the <style> block that used to sit inline in
   index.html (the Arabic homepage). Source order is preserved exactly, because it has to be: this
   file redefines the same selector many times across many @media blocks and
   the winning declaration is whichever one comes last. Do not regroup it by
   topic, and do not lift a rule out of it to reuse on another page - a
   partial copy carries the markup but not the behaviour. Author fresh from
   the winning computed values instead.

   Every colour, surface, radius, motion duration and font value comes from
   assets/css/sdeira-tokens.css, which must stay linked before this file.
   Nothing here may redeclare one of those custom properties: it would win on
   source order and detach the page from the design system with no visible
   error.

   One class of edit was made during the move. A url() inside a stylesheet
   resolves against the stylesheet's own location, not the document's, so the
   image paths lost their assets/ prefix and now start at ../ instead.
   ========================================================================== */
    /* Every design token lives in assets/css/sdeira-tokens.css. Nothing is
       redeclared here on purpose: an inline :root would beat the linked file on
       source order and this page would quietly stop following the system. */

    /* =========================================================================
       CASCADE STRUCTURE: why everything below sits inside @layer legacy
       -------------------------------------------------------------------------
       This style block grew by append. The same selector is redefined many times
       across roughly 130 @media blocks and 16 distinct max-width values:
       .hero 54 times, .hero-content 23, .sector-grid 23. At equal specificity
       the cascade resolves on source order, so a rule near the bottom silently
       beats a correct rule near the top for any viewport where both match. That
       has already produced real bugs (a .scroll-hint z-index reset that hid the
       element completely, a ::before divider that was not adjusted when a later
       breakpoint changed a 4-column grid to 2).

       Flattening 11,900 lines of that by hand is not verifiable in this project:
       there is no build step, no test suite and no snapshot, so a regression at
       one of 16 breakpoints is invisible until a human opens that width. So the
       root cause is addressed structurally instead of by rewriting.

       Everything historical is wrapped in @layer legacy. The SYSTEM LAYER at the
       very end of this block stays UNLAYERED, and unlayered styles beat layered
       ones in the cascade regardless of specificity or source order. That gives
       the design system one deterministic place to assert a canonical role and
       removes the need for !important, which was the only tool available before.

       VERIFIED, NOT ASSUMED: two stylesheets load before this block and are also
       unlayered (the Phosphor icon CSS and the token file), so wrapping the page
       could in principle have handed them the win. Measured in the browser
       across 922 elements plus their ::before and ::after, 32 properties each
       (2,766 checks) at 1280px and at 390px: zero computed-style differences
       between the layered and unlayered form of this block. Neither file
       contains a rule that outranks a page rule.

       RULE FOR FUTURE EDITS
       - A new canonical role, or a fix that must hold at every width, goes in
         the system layer at the end. No !important needed there.
       - A genuinely breakpoint-specific tweak to existing markup goes in
         @layer legacy where the rest of that component lives.
       - Never open a second layer. Two layers is the whole design: history, and
         the system that governs it.
       ====================================================================== */

    @layer legacy {

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box
    }

    /* Form controls do not inherit the document face by default. Without this,
       every <button> and <input> falls back to the UA default: the project
       filter tabs were rendering in Arial 700 next to Tajawal 700 headings,
       which is the single most visible typographic inconsistency on the page. */
    button,
    input,
    select,
    textarea {
      font-family: inherit;
      font-size: inherit;
      line-height: inherit;
      color: inherit;
    }

    /* Removing an author border from a <button> does not leave it borderless: the
       UA default takes over. Measured after the border purge: 28 border edges
       came back on .project-tab / .hero-arrow / .scroll-top from this alone. */
    button {
      background: none;
      border: 0;
    }

    html {
      scroll-behavior: smooth;
      overflow-x: hidden;
    }

    body {
      font-family: var(--font-brand);
      background: var(--offwhite);
      color: var(--ink);
      line-height: 1.75;
      overflow-x: hidden;
      -webkit-font-smoothing: antialiased;
    }

    h1,
    h2,
    h3,
    .display {
      font-family: var(--font-display);
      font-weight: 600;
      line-height: 1.2;
      letter-spacing: 0
    }

    h1,
    h2 {
      text-wrap: balance;
    }

    h1,
    h2,
    h3,
    p,
    a,
    span {
      overflow-wrap: break-word;
    }

    ::selection {
      background: var(--accent);
      color: #fff
    }

    .wrap {
      max-width: var(--max);
      margin: 0 auto;
      padding: 0 32px
    }

    a {
      color: inherit;
      text-decoration: none
    }

    .skip-link {
      position: fixed;
      top: 14px;
      right: 24px;
      z-index: 2000;
      padding: 10px 16px;
      background: var(--charcoal);
      color: #fff;
      border-radius: var(--r);
      transform: translateY(-140%);
      transition: transform var(--dur-base) var(--ease-out);
    }

    .skip-link:focus {
      transform: translateY(0);
    }


    /* ===== ICON SYSTEM: Phosphor Regular =====
       Phosphor glyphs are filled paths delivered as an icon font, so they are
       sized with font-size and coloured with `color`. stroke-width has no
       effect, which is exactly why the weight had to be chosen once. */
    i.ph {
      display: inline-block;
      line-height: 1;
      color: inherit;
      flex: 0 0 auto;
      /* Absolute, not em-relative. Sizing icons in em is how six different
         icon sizes appeared: each one inherited whatever its parent happened
         to set, so the same glyph was 12.48px in one card and 16px in another. */
      font-size: var(--ic-md);
    }

    /* ===== IMAGE TREATMENT =====
       One normalising pass over every card photograph so the grid reads as a
       single art-directed set rather than a pile of stock from four sources.
       Deliberately mild: enough to pull the exposures together, not enough to
       look filtered. Full opacity throughout: darkening for legibility is a
       separate veil layer on each card, never a fade on the photograph itself,
       because a faded photo blends toward whatever sits behind it and reads as
       a grey wash instead of a photo with a shadow on it. */
    .project-card-img img,
    .why-media img,
    .news-card img,
    .story-image img {
      filter: saturate(.94) contrast(1.04);
    }

    /* ===== SECTOR CARDS =====
       Inside the hero, the way the original site had them, not spun off into
       their own section. Five identical cards: same shape, same behaviour, no
       special case for Investment. Portrait, not landscape: three fit one row
       at the widths this grid is built for, the other two wrap to a second row
       and the hero is sized to show it. On very wide screens all five fit one
       row and the second row never forms.
       The pointer still darkens the card and brings its own link forward, and
       on top of that a panel opens above the card, the way the original site's
       hero-sector-panel did: a larger preview and the same approved copy, nothing
       invented, just given room. */
    .sector-grid {
      display: grid;
      grid-template-columns: repeat(3, clamp(170px, 19vw, 232px));
      justify-content: center;
      gap: 18px;
    }

    @media (min-width: 1600px) {
      .sector-grid {
        grid-template-columns: repeat(5, clamp(170px, 13vw, 210px));
      }
    }

    .sector-card {
      position: relative;
      isolation: isolate;
      aspect-ratio: 1 / 1;
      display: flex;
      align-items: flex-end;
      border-radius: var(--r);
      background: var(--surface-inverse);
    }

    /* The clipping boundary. Split out from .sector-card itself because the
       panel below has to escape this card's box to open above it, and an
       overflow:hidden ancestor would clip an absolutely positioned child
       regardless of its own position, panel included. */
    .sector-card-media {
      position: absolute;
      inset: 0;
      z-index: -2;
      overflow: hidden;
      border-radius: var(--r);
    }

    /* Softened: a texture behind the card, not the subject of it. The card's
       own colour and the text on it carry the weight, closer to how the
       original site's dark, blurred strip read than a showcased photograph. */
    .sector-card-img {
      position: absolute;
      inset: 0;
      inline-size: 100%;
      block-size: 100%;
      object-fit: cover;
      filter: saturate(.85) brightness(.92);
      transition: transform var(--dur-slow) var(--ease-out);
    }


    /* Much stronger than a readability floor: the photo is not the point here,
       the label is, the same balance the original site struck with a near-solid
       rgba(65,64,66,.78) bar. Dark from well above the text now, not just
       behind it, so the card reads as a dark tile with a photo texture behind
       it rather than a photo with text stamped on top. Worst case, a fully
       white photo region: at .55 the composite is #A19FA0 and white measures
       3.1, at .78 it is #767576 and white measures 5.3, at .92 it is
       #5C5B5C and white measures 7.3. */
    .sector-card-veil {
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg,
        rgba(var(--image-overlay-rgb), .40) 0%,
        rgba(var(--image-overlay-rgb), .58) 40%,
        rgba(var(--image-overlay-rgb), .92) 100%);
      transition: opacity var(--dur-base) var(--ease-out);
    }

    .sector-card-media::after {
      content: "";
      position: absolute;
      inset: 0;
      background: rgba(var(--image-overlay-rgb), .82);
      opacity: 0;
      transition: opacity var(--dur-base) var(--ease-out);
    }


    .sector-card-body {
      position: relative;
      inline-size: 100%;
      padding: 22px 20px 20px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 8px;
      color: #fff;
    }

    .sector-card-mark {
      display: grid;
  place-items: center start;
      inline-size: 40px;
      block-size: 40px;
      margin-bottom: 4px;
      border-radius: var(--r);
      background: rgba(255, 255, 255, .14);
      color: #fff;
    }

    .sector-card-mark i.ph {
      font-size: var(--ic-md);
    }

    .sector-card-title {
      font-family: var(--font-display);
      font-size: clamp(1.22rem, 1.5vw, 1.5rem);
      line-height: 1.25;
      margin: 0;
      color: #fff;
    }

    .sector-card-sub {
      color: rgba(255, 255, 255, .88);
      font-size: .92rem;
      line-height: 1.6;
    }

    /* The subsidiaries under this sector. This is the only place on the page
       where Zoad and Your Laundry appear at all. */
    .sector-card-subs {
      color: var(--gold-on-dark);
      font-size: .82rem;
      line-height: 1.5;
    }

    /* Hidden until the pointer arrives, so the resting card stays quiet. It is
       revealed by focus too, so keyboard users are never shown a card whose
       action they cannot see. */
    .sector-card-action {
      display: inline-flex;
      align-items: center;
      gap: 8px;
      margin-top: 8px;
      color: #fff;
      font-size: .88rem;
      font-weight: 800;
      opacity: 0;
      transform: translateY(6px);
      transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }


    .sector-card-action i.ph {
      font-size: var(--ic-sm);
    }

    /* A sector whose page does not exist yet. The dash marker carries the
         status; no sentence is spelled out. */
    .sector-card-action.is-pending {
      color: rgba(255, 255, 255, .82);
      font-weight: 600;
      cursor: default;
    }

    .sector-card-action.is-pending .pending-val {
      color: currentColor;
    }

    /* Touch and keyboard have no hover, so the action is simply always visible
       below the pointer breakpoint. */
    @media (hover: none) {

      .sector-card-action {
        opacity: 1;
        transform: none;
      }
    }

    /* The panel from the original site's hero-sector-panel, opening above the
       card instead of covering the hero. Width is pinned to the page's own
       content column regardless of which card triggers it (mid-row cards need
       this as much as edge cards do), which is why it is positioned off the
       viewport edge rather than off the card's own, much narrower, box. */
    .sector-card-panel {
      position: absolute;
      right: max(20px, calc((100vw - var(--max)) / 2 + 20px));
      left: max(20px, calc((100vw - var(--max)) / 2 + 20px));
      bottom: 100%;
      margin-bottom: 14px;
      z-index: 6;
      display: grid;
      grid-template-columns: minmax(180px, .8fr) minmax(240px, 1.2fr);
      background: rgba(255, 255, 255, .98);
      color: var(--charcoal);
      border-radius: var(--r);
      box-shadow: 0 26px 70px rgba(0, 0, 0, .32);
      opacity: 0;
      visibility: hidden;
      transform: translateY(16px);
      pointer-events: none;
      transition: opacity var(--dur-base) var(--ease-out),
        transform var(--dur-base) var(--ease-out),
        visibility var(--dur-base) var(--ease-out);
    }

    .sector-card:hover .sector-card-panel,
    .sector-card:focus-within .sector-card-panel {
      opacity: 1;
      visibility: visible;
      transform: none;
      pointer-events: auto;
    }

    .sector-card-panel-visual {
      min-height: 220px;
      background-size: cover;
      background-position: center;
      border-radius: var(--r);
    }

    .sector-card-panel-copy {
      padding: 30px 34px;
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 12px;
      text-align: right;
    }

    .sector-card-panel-copy h3 {
      font-family: var(--font-display);
      font-size: clamp(1.3rem, 2vw, 1.7rem);
      color: var(--charcoal);
    }

    .sector-card-panel-copy p {
      color: var(--muted);
      line-height: 1.85;
    }

    .sector-card-panel-subs {
      color: var(--label);
      font-size: .86rem;
    }

    .sector-card-panel-link {
      width: fit-content;
      display: inline-flex;
      align-items: center;
      gap: 10px;
      color: var(--accent);
      font-weight: 700;
      margin-top: 4px;
    }

    .sector-card-panel-link i.ph {
      font-size: var(--ic-sm);
    }

    .sector-card-panel-link.is-pending {
      color: var(--pending);
      font-weight: 600;
      cursor: default;
    }

    /* No hover on touch, so no panel either: the action link on the card
       itself already carries the destination. */
    @media (hover: none) {

      .sector-card-panel {
        display: none;
      }
    }

    @media (max-width: 980px) {

      .sector-card-panel {
        display: none;
      }
    }

    .project-card:hover .project-card-img img,
    .why-card:hover .why-media img,
    .news-card:hover img,
    .story-item:hover .story-image img {
      filter: saturate(1) contrast(1.03) brightness(1);
    }

    /* The supplied composites are branded in the green of the services company.
       Pulled most of the way to neutral so they sit inside the group's warm
       palette instead of introducing a second, competing brand colour. */
    .project-card-img img[src$=".png"],
    .why-media img[src$=".png"],

    .project-card:hover .project-card-img img[src$=".png"],
    .why-card:hover .why-media img[src$=".png"] {
      filter: saturate(.55) contrast(1.06) brightness(.98) sepia(.1);
    }

    /* Directional glyphs mirror in RTL by explicit opt-in only. A blanket rule
       would also flip the clock, the map pin and every brand logo. */
    [dir="rtl"] i.ph.icon--dir {
      transform: scaleX(-1);
    }


    /* A value awaiting delivery from Sdeira.
       It used to spell out "Ù‚ÙŠØ¯ Ø§Ù„ØªØ­Ø¯ÙŠØ«" in every slot, which put the same
       sentence on screen ten times and made the page read as a list of excuses.
       It is a single dash now: a mark, not a message. The dash occupies the slot
       so the layout does not shift when the real figure lands, and the meaning
       lives in aria-label for anyone who cannot see it.
       The tone is deliberately neutral rather than red. A value that has not
       arrived yet is not an error, and colouring it like one told the visitor
       something had gone wrong. */
    /* The element IS the dash. It was an inline-flex box with a ::before rule
       drawing the bar, and the box collapsed to zero height wherever it sat
       inside a block-level <strong>, so the marker rendered as nothing at all in
       the partner stats. One element, explicit size, nothing to collapse. */
    .pending-val {
      display: inline-block;
      inline-size: .62em;
      min-inline-size: 22px;
      block-size: .1em;
      min-block-size: 3px;
      background: currentColor;
      color: var(--pending);
      border-radius: var(--r);
      vertical-align: middle;
    }

    /* On a dark or brand surface the neutral grey disappears, so the marker
       switches to the on-dark tone. */
    .surface-inverse .pending-val,
    .cta .pending-val,
    .about-badge .pending-val,
    footer .pending-val {
      color: var(--pending-on-dark);
    }

    /* ===== NAV =====
       The pill itself (gap, padding, CTA) is ONE size in both states - see the
       comment below for why that part stays fixed. The logo is the one
       deliberate exception, by client request: bigger at rest over the hero,
       shrinking to the compact size the instant .scrolled lands. Restoring a
       two-state logo does not reopen the "morphing" bug the one-size pass
       fixed, because it is the only thing still moving - the gap, the padding
       and the CTA hold their one size throughout, so the bar's own shape never
       shifts, only the mark riding inside it. */
    header {
      position: fixed;
      top: 0;
      right: 0;
      left: 0;
      z-index: 1000;

      /* ONE size, both states, for everything except the logo below. The bar
         used to carry a second, smaller set of these three values under
         .scrolled (plus two more pairs inside media blocks, six declarations
         for three properties), so scrolling resized the logo, the CTA and the
         padding all at once. That is what made the state change read as the
         bar "morphing" instead of simply arriving: every element moved. Gap,
         padding and CTA height are declared once here, at the compact size
         the compressed bar used, and .scrolled changes no geometry on them.

         Two distances, two jobs, deliberately separate:
           --hd-gap  viewport edge -> the pill (the float gap)
           --hd-pad  pill edge -> the nav content (equal on all four sides)
         clamp() carries both across the whole range, which is what let the
         four per-breakpoint override blocks go away entirely. */
       --hd-gap: clamp(6px, .6vw, 8px);
       --hd-pad: clamp(6px, .6vw, 8px);
       --cta-h: clamp(34px, 2.6vw, 40px);

      /* Single shared logo height across rest and scrolled states and widths
         (V3 change request): --header-logo-height lives in the token file. */
      --logo-h: var(--header-logo-height);

      /* All four sides: the inline padding is what holds the pill off the
         screen edge on a phone, where the pill is narrower than --max and
         would otherwise run edge to edge. */
      padding: var(--hd-gap);
    }

    /* The one property this class still changes. Everything else about the
       pill - gap, padding, CTA height, the glass fade below - is unconditional
       on purpose (see header{} above); only the logo shrinks back to the
       compact size it always used to be, and .logo img's own
       transition:height (below) is what makes that shrink read as motion
       instead of a jump cut. */
    header.scrolled {
      --logo-h: var(--header-logo-height);
    }

    /* The bar carries its own readability floor instead of borrowing one from
       the hero. It used to rely on the hero scrim being near-opaque at the top,
       which meant lightening the hero (to cut the page's dark area) silently
       took the nav labels with it: white on the worst-case composite dropped to
       2.7. This gradient is local, fades to nothing within the bar's own height,
       and holds white at 5.4 over a fully white photo region. It disappears the
       moment the bar goes solid on scroll. */
    header::before {
      content: "";
      position: absolute;
      inset: 0 0 auto;
      block-size: 230px;
      z-index: -1;
      pointer-events: none;
      /* Holds its floor across the whole bar before it fades, because the nav
         row sits between 40px and 60px: a gradient that starts fading at the top
         is already down to .60 by the time it reaches the labels, which measures
         3.3 and fails. Flat .82 through 45% gives white 5.71 over a fully white
         photo region. */
      background: linear-gradient(180deg,
        rgba(var(--image-overlay-rgb), .82) 0%,
        rgba(var(--image-overlay-rgb), .78) 45%,
        rgba(var(--image-overlay-rgb), .30) 78%,
        transparent 100%);
      transition: opacity var(--dur-base) var(--ease-out);
    }

    header.scrolled::before {
      opacity: 0;
    }

    /* .nav IS the pill box. .wrap already gives it max-width: var(--max) and
       margin-inline: auto, so it is the page's own content column, centred,
       with no width arithmetic of its own - that is the whole reason the
       glass lands exactly on the content width. The padding shorthand
       overrides .wrap's `0 32px`, so the distance from the pill edge to the
       nav content is --hd-pad on all four sides.

       isolation, not z-index: .nav sits inside header's stacking context
       next to header::before (the scrim, z-index:-1). Making .nav its own
       stacking context is what guarantees .nav::before below lands above
       that scrim and below the logo and links. `isolation` says only that,
       and unlike a z-index it cannot be perturbed by a later redeclaration
       in one of this file's 107 media blocks. It creates a stacking context
       WITHOUT creating a containing block for fixed-position descendants,
       which matters enormously here - see .nav::before. */
    .nav {
      position: relative;
      isolation: isolate;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 18px;
      padding: var(--hd-pad);
    }

    /* The floating glass pill.
       ---------------------------------------------------------------------
       WHY A PSEUDO-ELEMENT AND NOT .nav ITSELF. This looks like an
       indirection and it is not optional. backdrop-filter makes an element a
       containing block for every position:fixed descendant, and the mobile
       drawer (.menu / #mobileNav) is position:fixed AND a child of .nav. Put
       the glass on .nav or on header and the drawer stops being measured
       against the viewport. Measured on a 375x812 phone viewport, drawer
       top/bottom:
         glass on header  ->  8.67 / 820.67   (overflows the screen)
         glass on .nav    -> 16.67 / 828.67   (worse)
         glass on ::before ->    0 / 812      (correct)
       A pseudo-element has no descendants, so its containing block traps
       nothing. This is also a fix, not just a precaution: header.scrolled
       used to carry the backdrop-filter, so the drawer was already being
       trapped by it.

       WHY inset: 0 IS EXACT. .nav's padding box is the pill, because .nav's
       padding is --hd-pad on all four sides. So the pill needs no width, no
       gutter arithmetic and no per-breakpoint correction - it is simply its
       parent's padding box.

       WHY NOTHING GEOMETRIC IS IN THE TRANSITION. The pill is fully shaped
       at rest - same box, same border-radius, same 1px border - and is
       invisible only because its paint is transparent. So the corner never
       animates from square to round, the box never grows, and no nav element
       shifts: on scroll the surface simply arrives, already the right shape.
       An earlier version animated the geometry and read as the bar morphing
       into place. The reference implementation this pattern comes from
       (idarat-aqarat.css:248) has exactly that bug - it lists
       `border-radius .35s` while going 0 -> 18px, so you watch its corners
       round off. Only colour and blur may move here.

       blur(0px), not none: `none` -> `blur(18px)` is a discrete jump that
       pops mid-fade, whereas 0px interpolates with the rest of the paint.

       No box-shadow: elevation on this site is tonal-step only. The hairline
       border in --line is what separates the translucent panel from the page
       behind it. */
    .nav::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      border: 1px solid transparent;
      border-radius: var(--r);
      background: rgba(255, 255, 255, 0);
      backdrop-filter: blur(0px) saturate(100%);
      -webkit-backdrop-filter: blur(0px) saturate(100%);
      transition:
        background-color var(--dur-base) var(--ease-out),
        border-color var(--dur-base) var(--ease-out),
        backdrop-filter var(--dur-base) var(--ease-out);
    }

    header.scrolled .nav::before {
      background: rgba(255, 255, 255, .82);
      border-color: var(--line);
      backdrop-filter: blur(18px) saturate(140%);
      -webkit-backdrop-filter: blur(18px) saturate(140%);
    }

    .logo {
      font-family: var(--font-display);
      font-weight: 700;
      font-size: 1.6rem;
      letter-spacing: 0;
      color: #fff;
      transition: color var(--dur-base);
      /* Never shrinks. The nav absorbs the width instead, so a wide menu can no
         longer squeeze the mark and slide a link underneath it. */
      flex: 0 0 auto;
    }

    .logo img {
      display: block;
      width: auto;
      max-width: 220px;
      height: var(--logo-h);
  object-fit: contain;
      transition: height var(--dur-base) var(--ease-out);
    }

    header.scrolled .logo {
      color: var(--charcoal)
    }

    .menu {
      display: flex;
      /* Fluid gap: at 1280 the fixed 34px gap plus 8 links overflowed the row
         the moment the fallback font measured wider than Tajawal, which is what
         wrapped the menu onto two lines and pushed "Ø§Ù„Ø£Ø«Ø±" under the logo. */
      gap: clamp(12px, 1.55vw, 30px);
      align-items: center;
      flex: 1 1 auto;
      min-width: 0;
      justify-content: center;
    }

    .menu a {
      font-size: clamp(.86rem, .95vw, .95rem);
      font-weight: 500;
      /* Solid, not .9. Over a photograph every tenth of alpha comes straight off
         the contrast ratio, and these are 14px labels. */
      color: #fff;
      position: relative;
      /* A nav label must never wrap: a two-line link changes the bar height and
         reflows every sibling. */
      white-space: nowrap;
      transition: color var(--dur-base)
    }

    .menu a::after {
      content: "";
      position: absolute;
      bottom: -6px;
      right: 0;
      width: 0;
      height: 1.5px;
      background: var(--accent);
      transition: width var(--dur-base)
    }

    .menu a:hover::after,
    .menu a.active::after {
      width: 100%
    }

    .menu-mobile-actions a::after {
      display: none;
    }

    header.scrolled .menu a {
      color: var(--ink)
    }

    .menu a.active {
      color: #fff;
    }

    header.scrolled .menu a.active {
      color: var(--accent-text);
    }

    .menu-mobile-actions {
      display: none;
    }

    .menu-lang,
    .menu-contact {
      display: none;
    }

    .nav-actions {
      display: flex;
      align-items: center;
      gap: 12px;
      flex: 0 0 auto;
    }

    .nav-icon {
      width: 44px;
      height: 44px;
      display: inline-grid;
      place-items: center;
      border-radius: var(--r);
      color: #fff;
      transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .nav-icon i.ph {
      font-size: var(--ic-md);
      line-height: 1;
    }

    .nav-icon:hover {
      background: rgba(255, 255, 255, .14);
    }

    header.scrolled .nav-icon {
      color: var(--charcoal);
    }

    header.scrolled .nav-icon:hover {
      background: rgba(145, 8, 17, .1);
      color: var(--accent-text);
    }

    .nav-cta {
      /* Height is driven by the header state so the CTA compresses with the bar
         instead of pinning it open. */
      min-height: var(--cta-h);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0 clamp(18px, 1.8vw, 28px);
      background: var(--charcoal);
      border-radius: var(--r);
      font-size: .82rem;
      font-weight: 700;
      letter-spacing: 0;
      white-space: nowrap;
      color: #fff;
      transition: min-height var(--dur-base) var(--ease-out),
        padding var(--dur-base) var(--ease-out),
        background var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .nav-cta:hover {
      background: var(--accent);
      color: #fff;
      border-color: var(--accent);
    }

    header.scrolled .nav-cta {
      border-color: var(--charcoal);
      background: var(--charcoal);
      color: #fff
    }

    header.scrolled .nav-cta:hover {
      background: var(--accent);
      border-color: var(--accent);
      color: #fff
    }

    .lang {
      font-size: .85rem;
      font-weight: 500;
      color: rgba(255, 255, 255, .8);
      cursor: pointer
    }

    header.scrolled .lang {
      color: var(--muted)
    }

    .burger {
      display: none;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 5px;
      cursor: pointer;
      /* The bars stay 26px wide, but the hit area is a full 44px square.
         Measured before this: 26x16, which fails WCAG 2.5.8 (24x24 minimum) on
         height and is far under the 44px usability standard, on the one control
         that opens navigation on touch devices. */
      min-inline-size: 44px;
      min-block-size: 44px;
      margin-inline-end: -9px;
    }

    .burger span {
      width: 26px;
      height: 2px;
      background: #fff;
      transition: var(--dur-base)
    }

    header.scrolled .burger span {
      background: var(--charcoal)
    }

    .menu-backdrop {
      position: fixed;
      inset: 0;
      z-index: 999;
      display: none;
      border: 0;
      background: rgba(var(--image-overlay-rgb), .38);
      backdrop-filter: blur(8px);
      cursor: pointer;
    }

    body.menu-open .menu-backdrop {
      display: block;
    }

    /* The drawer is a child of the fixed header, so its z-index cannot escape
       the header's stacking context. Hide the resting chrome while it is open
       so the backdrop covers the page without leaving the light logo or glass
       pill floating above it; the drawer's own `.menu-logo` stays visible. */
    body.menu-open header > .nav > .logo,
    body.menu-open header > .nav > .nav-actions,
    body.menu-open header::before,
    body.menu-open header .nav::before {
      visibility: hidden;
      opacity: 0;
    }

    /* Low-priority utility, not a primary action: smaller footprint, no
       border/blur, and it rests at partial opacity even while "visible" -
       full opacity only kicks in on hover/focus. */
    .scroll-top {
      position: fixed;
      left: 24px;
      bottom: 24px;
      z-index: 999;
      width: 38px;
      height: 38px;
      border-radius: var(--r);
      background: rgba(65, 64, 66, .55);
      border: none;
      color: #fff;
      font-size: .95rem;
      line-height: 1;
      display: grid;
      place-items: center;
      cursor: pointer;
      opacity: 0;
      pointer-events: none;
      transform: translateY(12px);
      transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
    }

    .scroll-top.visible {
      opacity: .55;
      pointer-events: auto;
      transform: none;
    }

    .scroll-top:hover,
    .scroll-top:focus-visible {
      background: var(--accent);
      opacity: 1;
    }

    /* ===== HERO ===== */
    /* No longer a fixed 100dvh box. The sector grid is back inside the hero in
       normal flow after .hero-content, so the hero's real height is 100dvh plus
       whatever that grid needs, and the photo/veil (both inset:0 on .hero
       itself) stretch to cover the whole of it automatically. */
    .hero {
      position: relative;
      min-height: max(680px, 100dvh);
    }

    .hero-bg {
      position: absolute;
      inset: 0;
      z-index: -2
    }

    .hero-slide {
      position: absolute;
      inset: 0;
      opacity: 0;
      transition: opacity var(--dur-slow) var(--ease-out);
    }

    .hero-slide.active {
      opacity: 1;
    }

    .hero-slide img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transform: scale(1.08);
    }

    .hero-slide.active img {
      animation: slowZoom 7s ease-out forwards;
    }

    @keyframes slowZoom {
      to {
        transform: scale(1)
      }
    }

    /* Mobile: each slide scales from its top edge so the headline sits on the
       sky rather than over the buildings (25 Sept change request). Applied to
       the slide itself, not the image; no overlay; desktop unchanged. */
    @media (max-width: 980px) {
      .hero-bg {
        height: 100dvh;
        bottom: auto;
        overflow: hidden;
      }

      .hero-slide {
        transform-origin: 50% 0;
      }

      .hero-slide:nth-child(1) { transform: scale(1.6); }
      .hero-slide:nth-child(2) { transform: scale(2.3); }
      .hero-slide:nth-child(3) { transform: scale(2.2); }
    }

    /* A flat, gentle wash over the whole hero (photo plus the sector grid
       below it), just enough to pull the exposure together. Not the text's
       readability floor: that gradient used to live here, sized against
       .hero's own height, and broke the moment the sector grid started adding
       a variable, viewport-width-dependent amount to that height (the grid's
       columns are vw-based, .hero's own height is not, so "46% of .hero" moved
       every time the window resized even though the text itself had not
       moved). The text's floor now lives on .hero-content, which is reliably
       100dvh regardless of what the grid below it is doing. */
    .hero::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      background: rgba(var(--image-overlay-rgb), .16);
    }

    /* Skewed ribbons, extracted from the Eskan microsite's about-deco
       pattern (idarat-aqarat.css:1120-1155). Spans the hero's full height
       (inset:0 plus each span's own -10%/120% overshoot) so the effect reads
       clearly at any scroll position, not just near one corner. Sat in the
       empty photo space past the centred copy column so it never crosses the
       text. Drawn in Sweihan rather than the source's translucent white: on
       this dark photograph the white reading was too faint to register as a
       deliberate mark, and the brand tone carries at the same hairline
       weight. */
    .hero-glass {
      position: absolute;
      z-index: 1;
      inset: 0;
      overflow: hidden;
      pointer-events: none;
    }

    .hero-glass span {
      position: absolute;
      top: -10%;
      height: 120%;
      width: 60px;
      border: 1px solid var(--brand-sweihan);
      border-radius: var(--r);
      background: color-mix(in srgb, var(--brand-sweihan) 8%, transparent);
      transform: skewX(-24deg);
    }

    .hero-glass .r1 { inset-inline-start: 68%; }
    .hero-glass .r2 { inset-inline-start: 78%; }
    /* Third ribbon steps back so the group reads as depth, not three equals -
       the same relationship the source had between its own three ribbons. */
    .hero-glass .r3 {
      inset-inline-start: 88%;
      border-color: color-mix(in srgb, var(--brand-sweihan) 55%, transparent);
    }

    @media (max-width: 920px) {
      .hero-glass { display: none; }
    }

    /* ===== IMAGE RIBBON =====
       One decoration for photography, from the Eskan microsite. It replaced
       an earlier three-drifting-bars variant: three thin outlines competed
       with the photograph instead of marking it, and at hairline weight they
       read as a rendering artefact rather than as identity.

       Geometry comes from the same identity-band tokens used by the section
       ribbons. Image-specific strength tokens keep the 2px shape legible but
       secondary on photography. The frame clips that overfill at the image
       edges, so the visible mark occupies the full photograph instead of
       floating short inside it.

       The element is still a FRAME with the band as its ::before, because the
       band is SKEWED: a -24deg skew over a 500px band throws its corners about
       122px sideways, well past the photograph, and the frame's overflow is
       what contains that. Two shapes of this rule do not work and should not
       be reinstated:

         - clip-path on the band itself. It is applied BEFORE the transform, so
           it cannot contain the skew at all.
         - overflow: hidden on the host. .about-visual deliberately lets
           another child, the year badge, hang outside its box, so clipping
           the host would cut the badge off.

       Every band uses the system radius, so the image mark reads as a cut
       identity band rather than a second visual language. Needs a positioned
       parent. */
    .ribbon-frame {
      --ribbon-line: color-mix(in srgb, var(--brand-sweihan) var(--image-ribbon-line-strength), transparent);
      --ribbon-fill: color-mix(in srgb, var(--brand-sweihan) var(--image-ribbon-fill-strength), transparent);
      position: absolute;
      inset: 0;
      z-index: 2;
      overflow: hidden;
      border-radius: var(--r);
      pointer-events: none;
    }

    .ribbon-frame::before {
      content: "";
      position: absolute;
      right: 14%;
      top: var(--identity-band-top);
      width: var(--identity-band-width);
      height: var(--identity-band-height);
      border: var(--identity-band-border) solid var(--ribbon-line);
      border-radius: var(--r);
      background: var(--ribbon-fill);
      transform: skewX(-24deg);
    }

    /* A ribbon host MUST be positioned. The frame is inset: 0, so on a static
       host it resolves against whatever ancestor happens to be positioned and
       stretches to that instead - and because the frame is what clips the
       skewed band, the band then runs clean across the card, over the white
       body and out the other side. That is exactly what happened on the two
       secondary project cards: their .project-card-img measured static, the
       frame took the whole 659px article instead of the 370px photo, and the
       diagonal crossed the copy. The feature card was correct only by
       accident - its own .project-card-img is absolutely positioned for
       layout reasons, which made it a containing block for free.

       Written at the base class, not scoped to the secondary cards, so the
       same trap cannot reopen from a different direction: the feature card's
       own absolute (0,2,0, later in the file) still wins where it applies,
       and the filtered view - which deliberately returns the feature card to
       normal flow - asks for relative rather than static for this reason. */
    .project-card-img {
      position: relative;
    }

    /* The About photograph carries the band on its outer (left) edge, away
       from the copy column and the year badge that sits at the image's inner
       bottom corner. Physical left, not inline-start: this is decorative
       geometry, and the RTL/LTR mirror is a per-page decision (see the
       sub-page rules in CLAUDE.md), not something the property should do on
       its own. */
    .about-visual .ribbon-frame::before {
      right: auto;
      left: 14%;
    }

    /* Large images push the shared band past the edge so the frame crops it
       sideways and it reads as passing behind the photograph rather than
       sitting inside it. This variant changes position only; its geometry
       remains on the same system tokens as every other photographic band. */
    .ribbon-frame--tall::before {
      right: auto;
      left: -4%;
    }

    /* The route cards alternate their layout - the odd card puts its
       photograph on the right of the copy panel, the even card mirrors it -
       so a band pinned to one physical side is behind the white panel on half
       of them, which is where it cannot be seen at all. Each card takes the
       edge AWAY from its own panel. Selected by nth-child to match the same
       odd/even mirror the layout itself uses, and written in physical left /
       right for the reason in the base rule above. */
    .needs-route:nth-child(odd) .ribbon-frame--tall::before {
      left: auto;
      right: -4%;
    }

    /* Its own full-viewport box, flexed to the bottom edge, exactly the role
       .hero itself used to play alone. The sector grid is a sibling after this
       one in normal flow, so whatever height it needs extends the hero past
       100dvh without this box's own sizing having to know about it. */
    .hero-content {
      position: relative;
      width: min(100%, 860px);
      min-height: 100dvh;
      display: flex;
      flex-direction: column;
      justify-content: flex-end;
      padding-block: 120px 64px;
      max-width: 860px;
    }

    /* The copy and the slide rail as a row, so the rail can stretch (align-
       items: stretch) to match whatever height the copy needs, and never has
       to be told that height. Copy comes first in markup, rail second, so in
       RTL the copy still sits flush against the reading edge exactly as
       before and the rail is what's new beside it, not the other way round. */
    .hero-content-row {
      display: flex;
      align-items: stretch;
      gap: 22px;
    }

    .hero-content-copy {
      flex: 1 1 auto;
      min-width: 0;
      text-align: right;
      transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    /* The text's actual readability floor, scoped to this box instead of to
       .hero. This box is reliably 100dvh (a height quantity), so a stop
       measured against it stays correct at every window width, unlike a stop
       measured against .hero's total height once the sector grid below made
       that total depend on viewport width too.
       Eyebrow (smallest text, 4.5:1 needed) sits at ~46% of this box, the
       paragraph at ~65%: spread wide, one continuous rise, no flat plateau. */
    .hero-content::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      background: linear-gradient(180deg,
        rgba(var(--image-overlay-rgb), .04) 0%,
        rgba(var(--image-overlay-rgb), .10) 16%,
        rgba(var(--image-overlay-rgb), .68) 46%,
        rgba(var(--image-overlay-rgb), .76) 65%,
        rgba(var(--image-overlay-rgb), .80) 100%);
    }

    /* Scoped to the copy alone, not the whole row: the slide rail keeps
       animating its own fill through a rotation, and the buttons/rail no
       longer flicker out and back in on every change, only the text does. */
    .hero-content-copy.is-changing {
      opacity: 0;
      transform: translateY(14px);
    }

    .eyebrow {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      font-size: .85rem;
      font-weight: 500;
      letter-spacing: 0;
      /* 14px over a photograph, so it takes the 4.5 floor and cannot afford
         alpha. .85 measured 3.83 at this height. */
      color: #fff;
      margin-bottom: 22px
    }

    /* removed decorative rule: eyebrow rule (hero) */
    .__removed-eyebrow-rule-hero { display: none }

    .hero h1 {
      font-size: clamp(2.25rem, min(4.75vw, 8svh), 4.18rem);
      color: #fff;
      font-weight: 700;
      margin-bottom: 22px;
      line-height: 1.16;
      text-wrap: balance;
    }

    .hero h1 .em {
      display: inline-block;
      color: #fff;
      background: var(--accent);
      padding: .02em .11em .09em;
      margin-inline: .075em;
      white-space: nowrap;
      vertical-align: baseline;
      line-height: inherit;
      -webkit-text-stroke: 0;
      box-decoration-break: clone;
      -webkit-box-decoration-break: clone;
    }

    @media (max-width: 360px) {
      .hero h1 .em {
        margin-inline: .06em;
      }
    }

    .hero p {
      font-size: clamp(1.05rem, 2vw, 1.3rem);
      color: rgba(255, 255, 255, .88);
      max-width: 560px;
      font-weight: 400;
      line-height: 1.8;
    }

    .hero-actions {
      display: flex;
      gap: 16px;
      margin-top: 38px;
      flex-wrap: wrap
    }

    .btn {
      display: inline-flex;
      align-items: center;
      gap: 12px;
      padding: 15px 30px;
      font-weight: 500;
      font-size: 1rem;
      border-radius: var(--r);
      transition: background var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out),
        border-color var(--dur-fast) var(--ease-out);
      cursor: pointer;
}

    .btn-primary {
      background: var(--accent);
      color: #fff
    }

    .btn-primary:hover {
      background: var(--accent-deep);
      color: #fff;
      box-shadow: 0 14px 30px rgba(145, 8, 17, .35);
    }

    /* The secondary hero button. This is the sanctioned border exception: it has
       no fill, so the outline is the only thing that makes its hit area visible.
       Border alpha raised to .6 so the outline itself clears 3:1 against the
       hero photo, measured across all three slides. */
    .btn-ghost {
      /* Full shorthand, not just border-color. The base .btn no longer carries
         a transparent border, so a colour-only declaration would resolve to
         border-style:none and draw nothing at all. */
      border: 1px solid rgba(255, 255, 255, .6);
      color: #fff;
    }

    .btn-ghost:hover {
      border-color: #fff
    }

    /* .arr is gone from the markup. Links signal themselves with an underline
       that grows from the reading edge instead of a sliding arrow glyph. */
    .more {
      position: relative;
      display: inline-block;
    }

    .more::after {
      content: "";
      position: absolute;
      inset-block-end: -3px;
      inset-inline-start: 0;
      inline-size: 100%;
      block-size: 1px;
      background: currentColor;
      opacity: .32;
      transform: scaleX(0);
      transform-origin: right;
      transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
    }

    a:hover .more::after,
    .more:hover::after {
      transform: scaleX(1);
      opacity: 1;
    }

    .btn:hover .__arr-removed {
      transform: none
    }

    /* A child of .hero now, not .hero-content, and deliberately so: it sits at
       the viewport's actual left edge regardless of where the content column
       (the 860px reading width, itself inset by the page's own side margin)
       happens to fall, rather than at a fixed offset from that column's own
       left edge the way it did while nested inside it. Vertical position is
       pinned to 100dvh rather than to .hero's own height, since .hero is
       taller than one screen once the sector grid is in normal flow below
       .hero-content, and this hint is only meaningful within the first one. */
    .scroll-hint {
      position: absolute;
      top: calc(100dvh - 76px);
      left: 24px;
      z-index: 2;
      display: flex;
      align-items: center;
      gap: 10px;
      /* .7 measured 3.57 over the worst-case photo composite at this height. */
      color: rgba(255, 255, 255, .95);
      font-size: .8rem;
      letter-spacing: 0
    }

    /* Was a 22x36 bordered rectangle standing in for a mouse. With borders gone
       it rendered as an empty outline box next to the label, so it is rebuilt as
       a filled track with a travelling highlight: readable with no border. */
    .scroll-hint .dot {
      width: 2px;
      height: 34px;
      background: rgba(255, 255, 255, .28);
      position: relative;
      overflow: hidden;
    }

    /* A smoother fall than a linear one: eased in as it leaves the top, held
       at full opacity through the travel, eased out only at the very end
       instead of fading across the whole distance. */
    .scroll-hint .dot::after {
      content: "";
      position: absolute;
      top: 4px;
      left: 50%;
      transform: translateX(-50%);
      width: 3px;
      height: 8px;
      background: #fff;
      border-radius: var(--r);
      animation: scrollDot 2s cubic-bezier(.4, 0, .2, 1) infinite;
    }

    @keyframes scrollDot {
      0% {
        opacity: 0;
        top: 4px
      }

      20% {
        opacity: 1
      }

      72% {
        opacity: 1;
        top: 24px
      }

      100% {
        opacity: 0;
        top: 24px
      }
    }

    /* A vertical rail beside the copy block, stretched to its full height by
       the row's align-items: stretch, replacing both the old arrow-button
       pair and the flat horizontal line row. Each segment fills top-to-bottom
       on its own timer instead of just swapping colour, so the rail reads as
       a countdown to the next slide, not a static position marker. */
    .hero-slides-ind {
      display: flex;
      flex-direction: column;
      gap: 10px;
      width: 3px;
      flex: 0 0 auto;
    }

    .hero-slide-line {
      flex: 1 1 0;
      width: 3px;
      padding: 0;
      border: 0;
      border-radius: var(--r);
      background: rgba(255, 255, 255, .28);
      cursor: pointer;
      position: relative;
      overflow: hidden;
    }

    .hero-slide-line::before {
      content: "";
      position: absolute;
      inset-inline: 0;
      top: 0;
      height: 0;
      background: var(--accent);
    }

    /* A slide already passed keeps a solid fill instead of resetting to
       empty, so the rail also reads as "how far through the set", not just
       "which one is playing now". */


    .hero-slide-line:focus-visible {
      outline: 2px solid #fff;
      outline-offset: 4px;
    }

    @media (prefers-reduced-motion: reduce) {

      .hero-slide-line.active::before {
        transition: none;
      }
    }

    /* Normal flow, not pinned: it sits right after .hero-content, which is its
       own 100dvh box, so this grid is what makes the hero taller than one
       screen. Three cards land in the first row, which is why "a little
       taller than the page" is true rather than "twice as tall": only the
       first row has to fit inside that extra reach, the second row is what a
       small scroll reveals. */


    @media (prefers-reduced-motion: reduce) {

      *,
      *::before,
      *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
        transition-duration: .01ms !important;
      }

      /* Reduced motion must never mean reduced content. */
      .reveal.armed {
        opacity: 1 !important;
        transform: none !important;
      }
    }

    /* ===== GROUP IMPACT ===== */
    /* The section that used to be the page's largest dark plate, 1126px of it.
       Measured against four reference sites, dark neutral surface runs from 0%
       (AD Ports Group, this group's own parent, and Modon) through 2.4% (u.ae,
       the federal government portal) to 6.8% (Aldar). This page was at 38.8%.
       Keeping one dark band this tall would still have left it at roughly 15%,
       so the impact band moved onto the light ladder and the weight it used to
       carry is now carried by Liwa, which is a brand colour rather than an
       absence of one. Dark neutral survives only where it earns its place: the
       footer and the sector strip over the hero photograph. */
    .impact {
      background: var(--surface-sunken-strong);
      padding: var(--sec-pad) 0;
      color: var(--ink);
    }

    /* The middle layer is gone.
       This section was three stacked surfaces: a grey section, a white panel
       inside it, and grey cards inside that. Each layer added its own padding,
       so the content sat inside 48px of panel padding inside 96px of section
       padding, and the reader crossed three tone changes to reach a number. A
       panel that only exists to hold a background is not structure, it is an
       extra box.
       The cards now sit directly on the section surface, which is what the tone
       ladder was for in the first place: the section is the sunken surface and
       the cards step up from it. */
    .impact-panel {
      position: relative;
      isolation: isolate;
    }

    .impact-main {
      display: grid;
      grid-template-columns: minmax(310px, .72fr) minmax(0, 1.18fr);
      gap: clamp(26px, 3.2vw, 46px);
      align-items: stretch;
    }

    .impact-visual {
      min-height: 520px;
      position: relative;
      overflow: hidden;
      border-radius: var(--r);
      background: var(--surface-sunken-strong);
    }

    .impact-visual img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      filter: saturate(.92) contrast(1.04);
      opacity: 1;
    }

    .impact-visual::after {
      content: "";
      position: absolute;
      inset: 0;
      /* Both ends carry white text over a photograph, so both ends need a floor,
         with the middle left for the photo. A single gradient that darkens,
         lightens, then darkens again reverses direction twice and draws a visible
         edge at each reversal. Two independently monotonic layers, one fading
         from the top and one from the bottom, give the same dark-light-dark
         shape without either one ever reversing.
         Worst case is a fully white photo region: at .76 the composite clears
         5.1, at .85 it clears 6.6. */
      background:
        linear-gradient(to bottom, rgba(var(--image-overlay-rgb), .76) 0%, rgba(var(--image-overlay-rgb), .76) 15%, transparent 46%),
        linear-gradient(to top, rgba(var(--image-overlay-rgb), .85) 0%, rgba(var(--image-overlay-rgb), .85) 20%, transparent 50%);
    }

    .impact-identity-strips {
      position: absolute;
      z-index: 1;
      top: 34%;
      left: clamp(24px, 8%, 42px);
      width: 92px;
      height: 32%;
      pointer-events: none;
    }

    .impact-identity-strips span {
      position: absolute;
      bottom: 0;
      width: 9px;
      transform: rotate(18deg);
      transform-origin: center;
    }

    .impact-identity-strips span:nth-child(1) {
      left: 4px;
      height: 72%;
      background: var(--brand-white);
    }

    .impact-identity-strips span:nth-child(2) {
      left: 26px;
      height: 100%;
      background: var(--brand-razeen);
    }

    .impact-identity-strips span:nth-child(3) {
      left: 50px;
      height: 84%;
      background: var(--brand-al-khatim);
    }

    .impact-identity-strips span:nth-child(4) {
      left: 74px;
      height: 58%;
      background: var(--brand-liwa);
    }

    .impact-visual-brand,
    .impact-visual-copy {
      position: absolute;
      z-index: 2;
    }

    .impact-visual-brand {
      top: 34px;
      right: 34px;
      display: flex;
      align-items: center;
      gap: 14px;
      color: #fff;
      font-size: .98rem;
      line-height: 1.7;
    }

    /* Was logo.png, the same improvised gold stripe used in the footer bars.
       A plain icon, on-dark colour, matches every other marker on the page. */
    .impact-visual-brand i.ph {
      color: var(--icon-on-dark);
      font-size: var(--ic-lg);
      line-height: 1;
    }

    .impact-visual-copy {
      right: 34px;
      bottom: 32px;
      left: 34px;
      color: rgba(255, 255, 255, .82);
      font-size: 1rem;
      line-height: 1.85;
    }

    .impact-content {
      min-width: 0;
    }

    .impact-head {
      text-align: right;
      max-width: 780px;
      margin: 0 0 34px;
    }

    .impact-kicker {
      display: inline-flex;
      align-items: center;
      gap: 12px;
      color: var(--label);
      font-size: .84rem;
      font-weight: 800;
      letter-spacing: 0;
      margin-bottom: 18px;
    }

    /* removed decorative rule: impact kicker rules */
    .__removed-impact-kicker-rules { display: none }

    .impact h2 {
      color: var(--ink);
      font-size: clamp(2.25rem, 4.6vw, 4.2rem);
      margin-bottom: 18px;
    }

    .impact-head p {
      color: var(--muted);
      font-size: clamp(1rem, 1.7vw, 1.16rem);
      line-height: 1.9;
    }

    .impact-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
      gap: 14px;
    }

    /* Single column, content stacked from the top. The old grid was `1fr auto`
       with the icon pinned to column 2 spanning three rows, so the icon floated
       beside the label with nothing aligning them, and a 168px min-height left
       roughly half of every card empty. */
    .impact-card {
      padding: 24px 22px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 14px;
      text-align: right;
      border-radius: var(--r);
      /* The section is Silver now that the white panel is gone, so the card
         steps UP to white to read as raised. Before, both card and panel were on
         the light half of the ladder and the card had nothing to step away
         from. */
      background: var(--surface-raised);
      transition: background var(--dur-base) var(--ease-out);
    }

    .impact-card:hover {
      background: var(--surface-sunken);
    }

    .impact-number {
      font-family: var(--font-display);
      font-size: clamp(2.1rem, 3.4vw, 3rem);
      font-weight: 800;
      line-height: 1;
      color: var(--figure);
      letter-spacing: 0;
    }

    .impact-number .accent {
      color: var(--figure);
    }

    /* Removed: a 1px divider that occupied the same grid cell as the icon. */
    .impact-rule {
      display: none;
    }

    /* Leads the card. `order` puts it first visually without reordering the DOM,
       so the label still precedes the decorative icon for a screen reader. */
    .impact-icon {
      order: -1;
      width: 52px;
      height: 52px;
      display: grid;
      place-items: center;
      border-radius: var(--r);
      background: var(--icon-wash);
      color: var(--icon);
      transition: background var(--dur-base) var(--ease-out);
    }

    /* Al Khatim, not Liwa: this tile is a decorative marker, not the action
       itself, so it follows the "icons are not red" rule instead of the
       accent colour. Was a raw rgba(145, 8, 17, .14) literal. */
    .impact-card:hover .impact-icon {
      background: var(--icon-warm-wash);
    }

    .impact-icon i.ph {
      font-size: var(--ic-lg);
      line-height: 1;
    }

    .impact-card-body {
      min-width: 0;
    }

    .impact-label {
      color: var(--ink);
      font-size: clamp(1.05rem, 1.5vw, 1.28rem);
      font-weight: 800;
      line-height: 1.25;
    }

    .impact-note {
      color: var(--muted);
      font-size: .84rem;
      margin-top: 8px;
      line-height: 1.55;
    }

    .impact-dots {
      display: none;
    }

    .impact-dots span {
      width: 4px;
      height: 4px;
      border-radius: var(--r);
      background: var(--gold);
    }

    /* Four separate tonal cards on the section background, not one strip carved
       up by dividers. The dividers were the only thing separating the items, so
       with borders gone the four ran together as a single paragraph block. */
    .impact-footer {
      margin-top: 22px;
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
      gap: 14px;
      padding: 0;
      background: none;
      color: var(--ink);
    }

    .impact-value {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;
      padding: 22px 20px;
      border-radius: var(--r);
      background: var(--surface-raised);
      transition: background var(--dur-base) var(--ease-out);
    }

    .impact-value:hover {
      background: var(--surface-sunken);
    }

    .impact-value-icon {
      width: 44px;
      height: 44px;
      display: grid;
      place-items: center;
      border-radius: var(--r);
      background: var(--icon-wash);
      color: var(--icon);
    }

    .impact-value-icon i.ph {
      font-size: var(--ic-md);
      line-height: 1;
    }

    .impact-value h3 {
      color: var(--ink);
      font-size: 1.05rem;
      margin-bottom: 6px;
    }

    .impact-value p {
      color: var(--muted);
      font-size: .86rem;
      line-height: 1.6;
    }

    /* ===== GROUP PROCESS ===== */
    /* Was a photograph under a 0.86-0.94 dark scrim, which put a third dark
       band between two others and made the page read as mostly dark. It is one
       tone step below the page now: the separation is still there, the weight is
       not. This single change removes 854px of dark surface and one stock photo. */
    .process {
      position: relative;
      overflow: hidden;
      padding: var(--sec-pad) 0;
      background: var(--surface-sunken);
      color: var(--ink);
      isolation: isolate;
    }

    .process-head {
      /*max-width: 820px;*/
      margin-inline-start: auto;
      margin-bottom: 48px;
      text-align: right;
    }

    .process-kicker {
      display: inline-flex;
      align-items: center;
      gap: 12px;
      color: var(--label);
      font-size: .86rem;
      font-weight: 800;
      letter-spacing: 0;
      margin-bottom: 18px;
    }

    /* removed decorative rule: process kicker rules */
    .__removed-process-kicker-rules { display: none }

    .process h2 {
      color: var(--ink);
      font-size: clamp(2.45rem, 5vw, 4.4rem);
      margin-bottom: 18px;
    }

    .process-head p {
      color: var(--muted);
      font-size: clamp(1rem, 1.7vw, 1.16rem);
      line-height: 1.9;
    }

    .process-flow {
      display: grid;
      /* Five steps, so the row must hold five. A flat 210px floor could not:
         5x210 + 4x22 = 1138 against a 1115px container, which dropped step 05
         onto a second row by itself. Flooring each track just above 100%/6
         guarantees a 6th track is impossible while letting the row fit 5, and
         still collapse to 4, 3, 2 and 1 as the viewport narrows. */
      grid-template-columns: repeat(auto-fit, minmax(max(180px, calc(100% / 6 + 1px)), 1fr));
      gap: 22px;
      align-items: stretch;
    }

    .process-step {
      position: relative;
      /* Was 340px. The grid already equalises the row, so a hard floor only
         added empty space under the shortest card. */
      padding: 30px 24px 26px;
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      gap: 14px;
      border-radius: var(--r);
      /* White on Cloud. The card is the raised surface now, which is the same
         elevation-by-tone rule read in the opposite direction. */
      background: var(--surface-raised);
      transition: background var(--dur-base) var(--ease-out);
    }


    /* Removed. This drew a 48px box at left:-34px, straddling the gap between
       two cards and clipping into both. The numbered steps already carry the
       order, so the connector was redundant as well as broken. */

    /* order puts the icon and the step number at the head of the card without
       reordering the DOM: the heading still precedes the decorative icon for
       assistive tech. */
    .process-num {
      order: -1;
      font-family: var(--font-display);
      color: var(--icon);
      font-size: 1.05rem;
      font-weight: 700;
      line-height: 1;
      letter-spacing: 0;
    }

    .process-step h3 {
      color: var(--ink);
      font-size: clamp(1.25rem, 1.7vw, 1.6rem);
      margin: 0;
    }

    .process-line {
      display: none;
    }

    .process-icon {
      order: -2;
      width: 58px;
      height: 58px;
      display: grid;
      place-items: center;
      border-radius: var(--r);
      background: var(--icon-wash);
      color: var(--icon);
      margin: 0;
      transition: background var(--dur-base) var(--ease-out);
    }

    /* Al Khatim, not Liwa: same reasoning as impact-icon above. Was a raw
       rgba(145, 8, 17, .14) literal. */

    .process-icon i.ph {
      font-size: var(--ic-lg);
      line-height: 1;
    }


    .process-summary {
      margin-top: 28px;
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 28px;
      align-items: center;
      padding: 26px 34px;
      border-radius: var(--r);
      background: var(--surface-raised);
    }

    .process-summary strong {
      color: var(--ink);
      font-size: 1.25rem;
      padding-inline-start: 24px;
      white-space: nowrap;
    }


    /* ===== SECTION SHELL ===== */
    section {
      position: relative
    }

    /* Default surface for any section that does not declare its own. White,
       so a new section joins the ladder at the page level instead of inheriting
       a tint that used to blanket six sections at once. */
    .pad {
      padding: var(--sec-pad) 0;
      background: var(--surface-base);
    }

    /* One rule for every raised surface on a light band. This used to rely on
       --card (pure white) alone to separate the surface from the page, which
       works on Cloud or Silver but is invisible where the section itself is
       also white: .why, .featured-projects and .news-section all are, so
       .why-footer, .projects-footer, .news-tabs, .news-subscribe and
       .about-values were white cards on a white page, with nothing marking
       their edge. A hairline border holds the edge regardless of what surface
       the card happens to sit on. */
    .news-card,
    .why-card,
    .partner-card,
    .news-tabs,
    .news-subscribe,
    .about-values,
    .story-footer,
    .why-footer,
    .projects-footer,
    .project-tab {
      background: var(--card);
      border: 1px solid var(--line);
    }

    /* The header is fixed, so an in-page anchor would otherwise land with the
       section heading hidden underneath it. Clears the whole floating bar:
       the gap above the pill, plus the pill (its tallest child, the CTA, and
       --hd-pad above and below it), plus breathing room. Was 72px, tuned to a
       compressed bar that no longer exists. Measured bar bottom at its
       largest is 99.31px (2 x --hd-gap 13.66 + 72px pill), so anything under
       ~100 puts the heading behind the glass. */
    section[id] {
      scroll-margin-top: 112px;
    }

    .sec-head {
      margin-bottom: var(--sec-head-gap);
      max-width: 680px
    }

    .kicker {
      font-size: .82rem;
      font-weight: 700;
      letter-spacing: 0;
      color: var(--label);
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 20px
    }

    /* removed decorative rule: kicker rule (about/projects/why/news/cta) */
    .__removed-kicker-rule-about-projects-why-news-cta { display: none }

    .sec-head h2 {
      font-size: clamp(2rem, 4vw, 3.1rem);
      color: var(--charcoal);
      margin-bottom: 18px
    }

    .sec-head p {
      font-size: 1.12rem;
      color: var(--muted);
      font-weight: 400;
    }

    /* ===== ABOUT ===== */
    .sectors {
      background: var(--surface-sunken);
    }

    /* Grey 70 measures 4.01 on Silver and fails body text there. The token file
       states the limit; these are the three sections that hit it. Rather than
       chase every kicker and caption inside them, each Silver surface declares
       what "label" means within itself. Jais measures 5.51 on Silver. */
    .impact,
    .story,
    .partners {
      --label: var(--brand-jais);
      --pending: var(--brand-jais);
      /* Sweihan is the warm figure tone and it is white-only: 3.35 on White,
         2.99 on Cloud, 2.63 on Silver. It fails even the large-text floor here,
         so these surfaces fall back to Black at 8.11. Figures on Silver are
         distinguished by size, not by hue. */
      --figure: var(--ink);
    }

    .about {
      background: var(--surface-base);
    }

    .about-layout {
      direction: ltr;
      display: grid;
      /* Was .78fr/1.22fr (text-majority), before --media-wide moved to 4:3.
         At that split the photo column measured 435px, and .split-badge's
         width follows it (min(72%, 340px) = 313px) while its own height
         stays fixed - driven by its own vw-based padding and its three lines
         of real copy, not by the photo. Shortening the photo from the old
         ~0.87:1 to 4:3 at the same 435px width shrank its area much faster
         than the badge's, so the badge went from covering ~37% of the photo
         to 57% - site owner flagged the badge reading as if it had eaten the
         picture, 16 Aug 2026. An even split gives the photo column back the
         width it needs to carry that fixed-size badge at the new, shorter
         ratio - measured down to ~45% coverage - without touching the badge
         itself or the crop already approved for this photo. */
      grid-template-columns: minmax(360px, 1fr) minmax(0, 1fr);
      gap: clamp(64px, 7vw, 132px);
      align-items: center;
    }

    /* Height is not set here. The About visual is one number shared by the
       photograph and the diagonal band overlay, so it lives in a single
       component variable in the system layer at the end of this block. */
    .about-visual {
      direction: rtl;
      position: relative;
    }

    .about-visual img {
      width: 100%;
      object-fit: cover;
      border-radius: var(--r);
      filter: saturate(.94) contrast(1.04);
    }

    .about-badge {
      position: absolute;
      right: -36px;
      bottom: -28px;
      width: min(420px, 72%);
      padding: 34px 42px;
      border-radius: var(--r);
      /* Was black at .92 over the photograph. On a white section that is a dark
         tile, so it becomes the brand band instead: white on Liwa is 9.35 and
         the badge now carries brand colour where it used to carry weight. */
      background: var(--surface-brand);
      color: #fff;
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 20px;
      align-items: center;
    }

    .about-badge i.ph {
      font-size: var(--ic-sm);
      line-height: 1;
      color: inherit;
    }

    .about-badge .big {
      font-family: var(--font-display);
      font-size: clamp(2.8rem, 4vw, 4.6rem);
      /* The badge is a Liwa band now, and --gold-text also resolves to Liwa, so
         this was Liwa on Liwa at 1.0. White on Liwa measures 9.35. */
      color: #fff;
      line-height: .9;
      letter-spacing: 0;
    }

    .about-badge .label {
      margin-top: 8px;
      color: #fff;
      font-size: 1.05rem;
      font-weight: 700;
    }

    .about-badge .t {
      grid-column: 2;
      color: rgba(255, 255, 255, .72);
      font-size: .98rem;
      line-height: 1.7;
    }

    .about-content {
      direction: rtl;
      text-align: right;
    }

    .about-content .kicker {
      justify-content: flex-start;
      font-size: 1rem;
      letter-spacing: 0;
      text-transform: none;
      color: var(--charcoal);
      margin-bottom: 30px;
    }

    .about-content h2 {
      max-width: 850px;
      color: var(--charcoal);
      font-size: clamp(3.2rem, 5.5vw, 6.6rem);
      line-height: 1.12;
      margin: 0 0 34px;
      letter-spacing: 0;
    }

    .about-copy {
      max-width: 820px;
      margin-inline-start: auto;
      padding-inline-start: 28px;
    }

    .about-copy p {
      color: var(--ink);
      font-size: clamp(1.08rem, 1.25vw, 1.32rem);
      line-height: 2;
      margin: 0 0 14px;
    }

    .about-copy p:last-child {
      margin-bottom: 0;
    }

    .about-pillars {
      margin-top: 46px;
      display: grid;
      /* Same reason as .cta-actions: indefinite container, so keep a shrinkable
         fixed count. */
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 0;
    }


    .about-icon,
    .about-value-icon {
      display: grid;
      place-items: center;
    }

    .about-icon {
      width: 74px;
      height: 74px;
      margin: 0 auto 20px;
      border-radius: var(--r);
      color: var(--icon);
      background: var(--icon-razeen-wash);
    }

    /* Al Khatim tile, same treatment as why-ic and story-icon. The pillars
       above already carry the Razeen wash, so the two rows in this section
       read as two distinct groups rather than one repeated colour. */
    .about-value-icon {
      color: var(--icon-warm-text);
      background: var(--icon-warm-fill);
      border-radius: var(--r);
    }

    .about-value-icon i.ph {
      font-size: var(--ic-lg);
      line-height: 1;
    }

    .about-pillar h3 {
      margin: 0 0 12px;
      color: var(--charcoal);
      font-size: 1.22rem;
    }

    .about-pillar p {
      margin: 0;
      color: var(--muted);
      font-size: .98rem;
      line-height: 1.8;
    }

    .about-values {
      margin-top: 72px;
      padding: 32px 36px;
      border-radius: var(--r);
      background: var(--card);
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
      gap: 0;
    }

    .about-value {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 20px;
      align-items: start;
      padding: 0 28px;
    }

    .about-value:first-child {
      border-inline-start: 0;
    }


    .about-value h3 {
      margin: 0 0 8px;
      color: var(--charcoal);
      font-size: 1.1rem;
    }

    .about-value p {
      margin: 0;
      color: var(--muted);
      line-height: 1.65;
      font-size: .94rem;
    }

    /* ===== FEATURED PROJECTS ===== */
    .featured-projects {
      background: var(--surface-base);
    }

    .projects-head {
      display: grid;
      /*grid-template-columns: minmax(0, 1fr) minmax(320px, .82fr);*/
      gap: 44px;
      align-items: end;
      margin-bottom: 54px;
      justify-content: space-between;
      align-items: end;
    }

    .projects-copy {
      text-align: right;
      max-width: 620px;
      /* In RTL, an auto start margin is on the right and pushes this block
         toward the centre. Keep the editorial header anchored to the right
         edge; the opposite auto margin absorbs the remaining space. */
      margin-inline-start: 0;
      margin-inline-end: auto;
    }

    .projects-copy h2 {
      color: var(--charcoal);
      font-size: clamp(2.3rem, 4.8vw, 4.2rem);
      margin-bottom: 18px;
    }

    .projects-copy p {
      color: var(--muted);
      font-size: 1.08rem;
      line-height: 1.9;
    }

    .project-tabs {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(max(130px, calc(20% + 1px)), 1fr));
      gap: 18px;
      direction: rtl;
    }

    .project-tab {
      min-height: 62px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 12px;
      border-radius: var(--r);
      background: rgba(242, 242, 242, .72);
      color: var(--muted);
      font-size: .88rem;
      font-weight: 700;
      transition: transform var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
    }

    .project-tab i.ph {
      font-size: var(--ic-sm);
      line-height: 1;
    }

    .project-tab {
      transition: background var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }


    .project-cards {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(max(250px, calc(20% + 1px)), 1fr));
      gap: 22px;
    }

    .project-card {
      overflow: hidden;
      border-radius: var(--r);
      background: var(--charcoal);
      transition: transform var(--dur-base) var(--ease-out);
    }

    .project-card:hover {
      background: var(--surface-sunken);
    }

    .project-card-img {
      height: 310px;
      overflow: hidden;
      background: var(--charcoal-soft);
    }

    /* The client's own composites (assets/images/services/services-operations.webp / call-us.png / eskan-*.png) each
       carry roughly 40% empty canvas on one side, which is why this card rendered
       as a white wedge with the photograph shoved against the frame edge.
       Cropping off-centre fills the frame with the photographed content. */
    .project-card-img img[src$=".png"],
    .why-media img[src$=".png"] {
      object-position: 78% center;
    }

    .project-card-img img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-base) var(--ease-out);
    }

    .project-card:hover .project-card-img img {
      transform: scale(var(--zoom));
    }

    /* Was a dark slab under every photograph. Four of those on a light section
       is a large part of why the page read as dark overall: the sampler found
       dark surface in the card bodies even where the section behind them was
       white. The body is a light card now and the photograph above it is what
       separates the card from the page. */
    .project-card-body {
      padding: 27px 28px 25px;
      color: var(--ink);
      background: var(--surface-raised);
    }

    .project-type {
      display: block;
      color: var(--label);
      font-size: .82rem;
      font-weight: 800;
      margin-bottom: 8px;
    }

    .project-card h3 {
      color: var(--ink);
      font-size: 1.45rem;
      margin-bottom: 12px;
    }

    .project-card p {
      color: var(--muted);
      font-size: .94rem;
      line-height: 1.8;
      min-height: 76px;
    }

    .projects-footer {
      margin-top: 38px;
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 26px;
      align-items: center;
      padding: 26px 30px;
      border-radius: var(--r);
      background: var(--card);
    }

    .projects-footer-cta {
      white-space: nowrap;
      background: var(--accent);
      color: #fff;
      font-weight: 700;
    }

    .projects-footer-cta:hover {
      background: var(--accent-deep);
      color: #fff;
    }

    .projects-footer-mark i.ph,
    .footer-mark i.ph {
      font-size: var(--ic-lg);
      line-height: 1;
    }

    .projects-footer h3 {
      color: var(--charcoal);
      font-size: 1.25rem;
      margin-bottom: 6px;
    }

    .projects-footer p {
      color: var(--muted);
      line-height: 1.7;
    }

    /* Shared with .story-footer and .why-footer: a plain icon mark, not a
       decorative image. Those two used to carry logo.png (a diagonal Razeen
       stripe) at 48x48 as a stand-in brand mark, on a card whose fill and the
       page's own background were the same white, so it read as invisible
       rather than as a logo. */
    .projects-footer-mark,
    .footer-mark {
      color: var(--icon);
      width: 50px;
      height: 50px;
      display: grid;
      place-items: center;
      padding-inline-end: 28px;
    }

    /* ===== SDEIRA STORY ===== */
    .story {
      background: var(--surface-sunken-strong);
      color: var(--ink);
      overflow: hidden;
    }

    .story-head {
      /*max-width: 780px;*/
      margin: 0 auto 58px;
      text-align: right;
    }

    .story-kicker {
      display: inline-flex;
      align-items: center;
      gap: 14px;
      color: var(--label);
      font-size: .86rem;
      font-weight: 800;
      margin-bottom: 18px;
    }

    /* removed decorative rule: story kicker rules */
    .__removed-story-kicker-rules { display: none }

    .story h2 {
      color: var(--charcoal);
      font-size: clamp(2.4rem, 5vw, 4.35rem);
      margin-bottom: 18px;
    }

    .story-head p {
      color: var(--muted);
      font-size: 1.08rem;
      line-height: 1.9;
    }


    .story-item {
      position: relative;
      direction: rtl;
      text-align: center;
      padding: 0 22px;
      /* A column, so the paragraph can absorb the slack and everything below it
         lines up across all five items. Without this, a station whose text runs
         one line shorter lifts its image 9px above the others and the row of
         photographs stops being a row. */
      display: flex;
      flex-direction: column;
    }

    /* The paragraph takes the leftover height; the image and the achievement row
       below it therefore start at the same y in every column. */
    .story-item>p {
      flex: 1 0 auto;
    }


    .story-dot {
      position: absolute;
      top: -43px;
      left: 50%;
      width: 24px;
      height: 24px;
      border-radius: var(--r);
      background: var(--icon);
      transform: translateX(-50%);
    }

    .story-year {
      font-family: var(--font-display);
      color: var(--figure);
      font-size: clamp(1.85rem, 3vw, 2.55rem);
      font-weight: 800;
      line-height: 1;
      margin-bottom: 24px;
    }

    .story-item h3 {
      color: var(--charcoal);
      font-size: 1.2rem;
      margin-bottom: 12px;
    }

    .story-item p {
      color: var(--muted);
      font-size: .94rem;
      line-height: 1.75;
      min-height: 96px;
    }

    .story-image {
      margin-top: 28px;
      border-radius: var(--r);
      overflow: hidden;
      aspect-ratio: 4 / 3;
      background: var(--warm-grey);
    }

    .story-image img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--dur-slow) var(--ease-out);
    }

    .story-item:hover .story-image img {
      transform: scale(var(--zoom));
    }

    .story-achievement {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 14px;
      align-items: center;
      /* Pushed to the bottom of the item so the achievement rows line up across
         columns regardless of how long each paragraph runs. */
      margin-top: auto;
      padding-top: 22px;
      text-align: right;
    }

    .story-icon {
      width: 44px;
      height: 44px;
      display: grid;
      place-items: center;
      border-radius: var(--r);
      color: var(--icon-warm-text);
      background: var(--icon-warm-fill);
    }

    .story-icon i.ph {
      font-size: var(--ic-md);
      line-height: 1;
    }

    .story-achievement strong {
      display: block;
      color: var(--charcoal);
      font-size: .98rem;
      margin-bottom: 4px;
    }

    .story-achievement span {
      color: var(--muted);
      font-size: .86rem;
      line-height: 1.55;
    }

    .story-footer {
      margin-top: 62px;
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 28px;
      align-items: center;
      padding: 26px 30px;
      border-radius: var(--r);
      background: var(--card);
    }

    .story-footer p {
      color: var(--muted);
      line-height: 1.85;
      font-size: 1.02rem;
      padding-inline-start: 24px;
    }

    /* ===== WHY ===== */
    .why {
      background: var(--surface-base);
      color: var(--ink)
    }

    .why .sec-head {
      max-width: 760px;
      /*margin-inline-start: auto;*/
      text-align: right;
    }

    .why .sec-head h2 {
      color: var(--charcoal)
    }

    .why .sec-head p {
      color: var(--muted)
    }

    .why .kicker {
      color: var(--label);
    }

    /* removed decorative rule: why kicker rule recolour */
    .__removed-why-kicker-rule-recolour { display: none }

    /* Two per row, not four: at four across, a one-line difference in copy
       length between cards made every row a different height, because the
       photo sat above the text and could not absorb that difference. Media
       beside text instead of above it removes the problem at the root: within
       a row both cards stretch to whichever is taller, photo included, so the
       row is never lopsided regardless of how long any one card's copy runs. */
    .why-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 22px;
    }

    .why-card {
      display: grid;
      grid-template-columns: minmax(160px, 34%) 1fr;
      overflow: hidden;
      border-radius: var(--r);
      background: var(--card);
      transition: transform var(--dur-base) var(--ease-out);
    }

    .why-card:hover {
      background: var(--surface-sunken);
    }

    .why-media {
      position: relative;
      overflow: hidden;
      /* The well behind the photograph. Black here reads as a dark plate
         wherever the image does not fully cover, on a section that is white. */
      background: var(--surface-sunken-strong);
    }

    /* Full opacity, full colour: the same rule as .sector-card-img. It used to
       carry opacity:.56 plus its own saturate(.85), fading the photo toward the
       sunken well behind it, which is what actually read as "grey" rather than
       "black" underneath the veil below. Darkening is .why-media::after alone. */
    .why-media img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      object-fit: cover;
      display: block;
      transition: transform var(--dur-slow) var(--ease-out);
    }

    .why-card:hover .why-media img {
      transform: scale(var(--zoom));
    }

    .why-media::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, rgba(var(--image-overlay-rgb), .12) 0%, rgba(var(--image-overlay-rgb), .34) 45%, rgba(var(--image-overlay-rgb), .88) 100%);
    }

    /* Was centred in the photo frame with a 2px accent outline, so it read as an
       empty bracket floating on the image and clipped the frame edge. It is now a
       solid tile anchored to the bottom reading corner of the photo. */
    /* Al Khatim, not Liwa. Four identical red tiles on one card grid is the same
       "everything is red" problem as the sector icons; this is the marker role,
       not the action role. */
    .why-ic {
      position: absolute;
      inset-block-end: 0;
      inset-inline-start: 0;
      z-index: 1;
      width: 62px;
      height: 62px;
      display: grid;
      place-items: center;
      color: var(--icon-warm-text);
      background: var(--icon-warm-fill);
    }

    .why-ic i.ph {
      font-size: var(--ic-lg);
      line-height: 1;
    }

    .why-card-body {
      padding: 30px 30px 32px;
      text-align: right;
    }

    .why-card h3 {
      font-size: clamp(1.35rem, 2.3vw, 1.8rem);
      color: var(--charcoal);
      margin-bottom: 12px;
    }


    .why-card h3::after {
      content: none;
      display: block;
      width: 34px;
      height: 2px;
      background: var(--accent);
      margin-top: 12px;
    }

    .why-card p {
      color: var(--muted);
      font-weight: 400;
      font-size: .98rem;
      line-height: 1.85;
      margin-bottom: 22px;
    }

    .why-card ul {
      list-style: none;
      display: grid;
      gap: 10px;
      color: var(--muted);
      font-size: .92rem;
      line-height: 1.65;
    }

    .why-card li {
      position: relative;
      padding-inline-start: 18px;
    }

    .why-card li::before {
      content: "";
      position: absolute;
      top: .75em;
      inset-inline-start: 0;
      width: 6px;
      height: 6px;
      border-radius: var(--r);
      background: var(--accent);
    }

    .why-footer {
      margin-top: 40px;
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 28px;
      align-items: center;
      padding: 26px 30px;
      border-radius: var(--r);
      background: var(--card);
    }

    .why-footer p {
      color: var(--muted);
      line-height: 1.85;
      font-size: 1.04rem;
      text-align: right;
      padding-inline-start: 24px;
    }


    /* ===== PARTNERS ===== */
    .partners {
      background: var(--surface-sunken-strong);
    }

    .partners-head {
      max-width: 820px;
      margin: 0 auto 58px;
      text-align: center;
    }

    .partners-kicker {
      display: inline-flex;
      align-items: center;
      gap: 14px;
      color: var(--label);
      font-size: .86rem;
      font-weight: 800;
      margin-bottom: 18px;
    }

    /* removed decorative rule: partners kicker rules */
    .__removed-partners-kicker-rules { display: none }

    .partners h2 {
      color: var(--charcoal);
      font-size: clamp(2.35rem, 5vw, 4.25rem);
      margin-bottom: 18px;
    }

    .partners-head p {
      color: var(--muted);
      font-size: 1.08rem;
      line-height: 1.9;
    }

    /* There are five partner slots, so the row must hold five and never six.
       A flat 190px floor let auto-fit create a sixth track on a wide container,
       which pushed the row past the container edge and clipped the last card.
       Flooring each track just above 100%/6 makes a sixth track arithmetically
       impossible while still collapsing to 4, 3, 2 and 1 as the viewport
       narrows. */
    .partners-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(max(190px, calc(100% / 6 + 1px)), 1fr));
      gap: 20px;
    }

    .partner-card {
      min-height: 300px;
      padding: 34px 26px 30px;
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
      border-radius: var(--r);
      background: var(--card);
      transition: transform var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
    }

    .partner-card:hover {
      border-color: rgba(221, 177, 118, .32);
      background: var(--surface-sunken-strong);
    }

    .partner-logo i.ph {
      font-size: var(--ic-xl);
      color: var(--muted);
    }

    .partner-logo {
      min-height: 74px;
      display: grid;
      place-items: center;
      margin-bottom: 24px;
      font-family: var(--font-display);
      font-weight: 800;
      line-height: 1;
    }

    .partner-card h3 {
      color: var(--charcoal);
      font-size: 1.18rem;
      margin-bottom: 14px;
    }

    .partner-card h3::after {
      content: none;
      display: block;
      width: 34px;
      height: 2px;
      margin: 14px auto 0;
      background: var(--accent);
    }

    .partner-card p {
      color: var(--muted);
      font-size: .94rem;
      line-height: 1.8;
      flex: 1;
    }

    .partner-domain {
      color: var(--pending);
      font-size: .85rem;
      font-weight: 800;
      margin-top: 22px;
    }

    .partners-trust {
      margin-top: 42px;
      position: relative;
      overflow: hidden;
      display: grid;
      /* Was 1fr + three 130px columns + a 260px column. At 130px an Arabic
         caption like "Ù…Ù† ÙƒØ¨Ø±Ù‰ Ø§Ù„Ø´Ø±ÙƒØ§Øª Ø§Ù„Ø±Ø§Ø¦Ø¯Ø© ÙÙŠ Ù…Ø¬Ø§Ù„Ø§Øª Ù…ØªØ¹Ø¯Ø¯Ø©" broke to one
         word per line, five lines deep. The stats share one auto-fit row with a
         floor wide enough to set a line of text, and the copy keeps its own
         column above them. */
      grid-template-columns: minmax(280px, 1fr) minmax(0, 1.6fr);
      gap: 0;
      align-items: center;
      border-radius: var(--r);
      /* A white card on the Silver band. As a dark slab it was the single
         largest patch of dark surface outside the intended dark sections. */
      background: var(--surface-raised);
      color: var(--ink);
    }

    .partners-trust-copy {
      padding: 34px;
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 22px;
      align-items: center;
    }

    .partners-trust-icon {
      width: 54px;
      height: 54px;
      /* Sits on a white card on the Silver band, not on a dark surface. */
      color: var(--icon);
    }

    .partner-stat i.ph {
      font-size: var(--ic-md);
      line-height: 1;
    }

    .partners-trust h3 {
      color: var(--ink);
      font-size: 1.32rem;
      margin-bottom: 8px;
    }

    .partners-trust p {
      color: var(--muted);
      line-height: 1.75;
      font-size: .95rem;
    }

    .partner-stats {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
      gap: 4px;
      padding: 22px;
    }

    .partner-stat {
      padding: 14px 16px;
      text-align: center;
    }

    .partner-stat strong {
      display: block;
      color: var(--figure);
      font-family: var(--font-display);
      font-size: 2rem;
      line-height: 1;
      margin-bottom: 10px;
    }

    .partner-stat span {
      display: block;
      color: var(--ink);
      font-weight: 800;
      margin-bottom: 6px;
    }

    .partner-stat small {
      color: var(--muted);
      line-height: 1.6;
    }

    /* ===== NEWS ===== */
    .news-section {
      background: var(--surface-base);
    }

    .news-head {
      display: flex;
      justify-content: space-between;
      align-items: flex-end;
      gap: 34px;
      max-width: none;
      margin-bottom: 30px;
    }

    .news-head h2 {
      margin: 0;
    }

    .news-head p {
      max-width: 620px;
      margin: 16px 0 0;
      color: var(--muted);
      font-size: 1.05rem;
      line-height: 1.8;
    }

    .news-all {
      min-height: 44px;
      padding: 0 26px;
      border-radius: var(--r);
      display: inline-flex;
      align-items: center;
      justify-content: center;
      color: var(--accent-text);
      font-weight: 700;
      white-space: nowrap;
      transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .news-all:hover {
      background: var(--accent);
      color: #fff;
    }

    /* Newsroom awaiting content.
       Documented fact (content checklist, section 10): not one item has been
       published under the Sdeira Group name since the November 2024 rebrand.
       The four cards that used to sit here carried invented headlines and
       invented dates, so they are replaced by a state that declares itself.
       The category filter bar was removed with them: it was never wired to any
       handler, so it was a control that could not control anything. Both come
       back together the day real press material is delivered. */
    .news-pending {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: clamp(20px, 2.4vw, 34px);
      align-items: center;
      padding: clamp(34px, 4vw, 56px);
      border-radius: var(--r);
      background: var(--card);
      border: 1px dashed var(--line);
    }

    .news-pending-icon {
      display: grid;
      place-items: center;
      inline-size: 64px;
      block-size: 64px;
      border-radius: var(--r);
      background: var(--surface-sunken);
      color: var(--muted);
    }

    .news-pending-icon i.ph {
      font-size: var(--ic-lg);
    }

    .news-pending h3 {
      margin: 0 0 8px;
      font-size: clamp(1.1rem, 1.6vw, 1.4rem);
      color: var(--ink);
    }

    .news-pending p {
      margin: 0;
      max-width: 62ch;
      color: var(--muted);
      line-height: 1.85;
    }

    .news-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(max(250px, calc(20% + 1px)), 1fr));
      gap: 24px;
      align-items: stretch;
    }

    .news-card {
      display: grid;
      grid-template-rows: auto 1fr;
      overflow: hidden;
      background: var(--card);
      border-radius: var(--r);
      cursor: pointer;
      transition: transform var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
    }

    .news-card .img {
      overflow: hidden;
      aspect-ratio: 16 / 9.7;
      height: auto;
      margin-bottom: 0;
      background: #ddd;
    }

    .news-card img {
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--dur-slow)
    }

    .news-card:hover,
    .news-card:focus-within {
      background: #fff;
      border-color: rgba(145, 8, 17, .34);
    }

    /* .news-card:hover img,
    .news-card:focus-within img {
      transform: scale(var(--zoom))
    } */

    .news-body {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      min-height: 270px;
      padding: 24px 26px;
    }

    .news-card .date {
      margin-top: 14px;
      font-size: .86rem;
      color: var(--muted);
      display: inline-flex;
      align-items: center;
      gap: 8px;
      letter-spacing: 0;
    }

    /* Removed: a purely decorative 14px bordered square sat after every news
       date and rendered as an empty box, reading as a failed icon. */

    .news-category {
      color: var(--label);
      font-size: .84rem;
      font-weight: 800;
    }

    .news-card h3 {
      font-size: clamp(1.05rem, 1.35vw, 1.28rem);
      color: var(--charcoal);
      margin: 18px 0 0;
      line-height: 1.5;
      transition: color var(--dur-base)
    }

    .news-card p {
      margin: 14px 0 0;
      color: var(--muted);
      font-size: .92rem;
      line-height: 1.8;
    }

    .news-card:hover h3 {
      color: var(--accent-text);
    }

    .news-card .more {
      min-height: 44px;
      margin-top: auto;
      font-size: .92rem;
      color: var(--muted);
      display: inline-flex;
      align-items: center;
      gap: 8px
    }

    .news-subscribe {
      margin-top: 48px;
      min-height: 116px;
      padding: 24px 32px;
      border-radius: var(--r);
      background: var(--card);
      display: grid;
      grid-template-columns: 1fr minmax(320px, .8fr) auto;
      gap: 28px;
      align-items: center;
    }

    .news-subscribe-copy {
      display: grid;
      grid-template-columns: auto 1fr;
      gap: 18px;
      align-items: center;
    }

    .news-subscribe-icon {
      width: 52px;
      aspect-ratio: 1;
      border-radius: var(--r);
      color: var(--icon);
      display: grid;
      place-items: center;
    }

    .news-subscribe-icon i.ph,
    .news-social a i.ph {
      font-size: var(--ic-sm);
      line-height: 1;
    }

    .news-subscribe h3 {
      margin: 0;
      color: var(--charcoal);
      font-size: 1.12rem;
    }

    .news-subscribe p {
      margin: 6px 0 0;
      color: var(--muted);
      line-height: 1.7;
    }

    /* One composite control: the field is the container and the submit sits
       inside it, so there is no floating second box beside the input. The only
       moving parts are a focus bar that grows from the reading edge and a fill
       that wipes across the button. No gradient, no lift, no sliding glyph. */
    .news-form {
      position: relative;
      min-width: 0;
      display: flex;
      align-items: stretch;
      gap: 0;
      padding: 5px;
      border-radius: var(--r);
      background: var(--surface-sunken);
      transition: background var(--dur-base) var(--ease-out);
    }


    /* The focus bar. Sits under the whole composite and grows from the reading
       edge, which in RTL is the right. */
    .news-form::after {
      content: "";
      position: absolute;
      inset-block-end: 0;
      inset-inline-start: 0;
      inline-size: 100%;
      block-size: 2px;
      background: var(--accent);
      transform: scaleX(0);
      transform-origin: right;
      transition: transform var(--dur-base) var(--ease-out);
    }

    .news-form:focus-within::after {
      transform: scaleX(1);
    }

    .news-form input {
      flex: 1 1 auto;
      min-width: 0;
      min-height: 46px;
      padding: 0 16px;
      border: 0;
      border-radius: var(--r);
      background: none;
      color: var(--charcoal);
      font: inherit;
      outline: 0;
    }

    .news-form input::placeholder {
      color: var(--muted);
    }

    .news-form button {
      position: relative;
      overflow: hidden;
      flex: 0 0 auto;
      min-height: 46px;
      padding: 0 26px;
      border-radius: var(--r);
      background: var(--accent-deep);
      color: #fff;
      font: inherit;
      font-weight: 700;
      cursor: pointer;
      z-index: 0;
    }

    /* Fill wipe. A solid block sweeps across from the reading edge on hover
       instead of the button changing colour all at once. */
    .news-form button::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      background: var(--charcoal);
      transform: scaleX(0);
      transform-origin: right;
      transition: transform var(--dur-base) var(--ease-out);
    }

    .news-form button:hover::before,
    .news-form button:focus-visible::before {
      transform: scaleX(1);
    }

    .news-social {
      padding-inline-start: 28px;
      display: flex;
      align-items: center;
      gap: 12px;
      color: var(--charcoal);
      font-weight: 800;
      white-space: nowrap;
    }

    .news-social a {
      width: 42px;
      aspect-ratio: 1;
      border-radius: var(--r);
      color: var(--icon);
      display: grid;
      place-items: center;
      transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .news-social a:hover {
      background: var(--accent);
      color: #fff;
    }

    /* ===== CTA ===== */
    /* The one place on the page that is the brand colour. This is the highest
       conversion point, which is what earns the primary colour, and it replaces
       a fourth dark photo band. White on Liwa measures 9.35 and Razeen on Liwa
       measures 4.73, the exact pairing the brand guide uses on pages 30 and 32. */
    /* Jais, not Liwa: a full-band red felt like exactly the kind of surface-
       scale use of the accent colour the brand guide's own 50/25/25
       proportion warns against, and this band sits directly above a black
       footer, so it also can't just become --surface-inverse (identical to
       the footer, an adjacent-duplicate surface). Jais is the system's other
       dark neutral, distinct from both. */
    .cta {
      position: relative;
      color: #fff;
      overflow: hidden;
      margin: 0;
      display: grid;
      align-items: center;
      background: var(--surface-inverse-soft);
    }

    /* The three stacked scrims are gone with the photograph they were covering. */

    .cta-inner {
      width: min(980px, 100%);
      margin: 0 auto;
      padding: calc(var(--sec-pad) * 1.35) 0;
      text-align: center;
    }

    .cta .kicker {
      color: var(--gold-on-dark);
      justify-content: center;
      margin-bottom: 30px;
    }

    .cta h2 {
      font-size: clamp(3rem, 6vw, 5.4rem);
      color: #fff;
      margin: 0 auto 26px;
      line-height: 1.32;
    }

    .cta p {
      max-width: 720px;
      margin: 0 auto 54px;
      font-size: clamp(1.1rem, 1.55vw, 1.42rem);
      color: rgba(255, 255, 255, .8);
      font-weight: 400;
      line-height: 1.9;
    }

    .cta-actions {
      display: grid;
      /* Fixed count on purpose: the container width is indefinite, so an auto-fit
         floor resolves against max-content and overflows. minmax(0,...) can
         always shrink. */
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 18px;
      max-width: 1120px;
      margin: 0 auto;
    }

    /* Cards, not buttons in a row. As buttons their content sat flush to the
       reading edge with the icon detached from the label, and two of the three
       had no visible surface at all on the near-black section. As cards they
       carry a real surface, centre their own content, and equalise. */
    /* Three routes, three identical cards.
       They used to be near-invisible: two were rgba(255,255,255,.12) over Liwa,
       which composites to #9C262E and gives the card edge a 1.2 step against the
       band behind it, and the third was filled with --accent-deep, which
       resolves to Liwa itself, so the "primary" card was the same colour as the
       section it sat on. One of the three could not be seen at all and the other
       two were guesses.
       They are white cards now. Same surface, same weight, same contrast: the
       card against the band measures 9.35, the label on the card 10.31, and the
       note 7.01. Nothing here ranks the three routes against each other, because
       nothing about them is ranked. */
    .cta-action {
      padding: 30px 22px 26px;
      border-radius: var(--r);
      background: var(--surface-raised);
      color: var(--ink);
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;
      gap: 14px;
      font-weight: 700;
      font-size: 1.02rem;
      text-align: center;
      transition: background var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .cta-action i.ph {
      display: grid;
      place-items: center;
      inline-size: 56px;
      block-size: 56px;
      border-radius: var(--r);
      /* Red belongs here: this is the action itself, not decoration. */
      background: var(--accent-wash);
      color: var(--accent-text);
      font-size: var(--ic-md);
      line-height: 1;
      flex: 0 0 auto;
      transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
    }


    .cta-action .cta-action-note {
      font-weight: 400;
      font-size: .92rem;
      line-height: 1.7;
      color: var(--muted);
    }

    .cta-action .arr {
      color: rgba(255, 255, 255, .82);
      font-size: 1.35rem;
    }

    /* ===== FOOTER ===== */
    footer {
      /* Dark glass rather than an opaque band, but the tone is the brand Black
         from the token file, not a near-black of its own. The alpha and the
         composited contrast figures live with the token. */
      background: var(--scrim-footer);
      backdrop-filter: blur(16px) saturate(125%);
      -webkit-backdrop-filter: blur(16px) saturate(125%);
      /* .6 composites to 4.85 on Black, which passes but leaves no headroom for
         anything nested that dims further. The floor lives here so descendants
         can step down without falling through it. */
      color: rgba(255, 255, 255, .96);
      font-weight: 600;
      padding: 80px 0 36px;
      /* Extra bottom clearance keeps the socials row from sitting under the
         fixed .scroll-top button once the page is scrolled all the way down. */
      padding-bottom: max(36px, calc(96px + env(safe-area-inset-bottom)));
    }

    .foot-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
      gap: 40px;
      padding-bottom: 56px;
}

    .foot-brand .logo {
      color: #fff;
      font-size: 1.9rem;
      margin-bottom: 20px;
      display: inline-block
    }

    .foot-brand p {
      font-weight: 400;
      max-width: 300px;
      font-size: .98rem;
    }

    .foot-col h4 {
      font-family: var(--font-display);
      color: #fff;
      font-size: 1.05rem;
      margin-bottom: 22px;
      font-weight: 500
    }

    .foot-col a,
    .foot-col .foot-pending {
      display: block;
      margin-bottom: 13px;
      font-size: .95rem;
      font-weight: 400;
      transition: color var(--dur-base)
    }

    .foot-col a {
      color: #fff;
    }

    /* An entry with no destination yet. It reads as a label, so the footer never
       offers a link that goes nowhere. Distinguished by tone, not by opacity: at
       .62 on top of an already-dimmed inherited colour the effective alpha fell
       to .37 and the text measured 2.88 on Black. A declared colour is 7.02 and
       still sits a clear step below the white links above it. */
    .foot-col .foot-pending {
      color: var(--muted-on-dark);
      cursor: default;
    }

    .foot-bottom {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding-top: 30px;
      flex-wrap: wrap;
      gap: 16px
    }

    .foot-bottom .socials {
      display: flex;
      gap: 14px
    }

    .foot-bottom .socials a {
      width: 40px;
      height: 40px;
      border-radius: var(--r);
      display: grid;
      place-items: center;
      background: rgba(255, 255, 255, .12);
      transition: background var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }


    .foot-bottom .socials a:hover {
      background: var(--accent);
      border-color: var(--accent);
      color: #fff;
    }

    .foot-bottom .socials i.ph {
      font-size: var(--ic-sm);
      line-height: 1;
    }

    .copy {
      font-size: .85rem;
    }

    /* ===== REVEAL ===== */
    /* Content is visible by default. JS adds .armed to opt an element in to
       animating. If the script never runs, nothing is hidden. The original
       started at opacity:0 and depended on JS to reveal it. */


    /* The hero reveal used to be JS-gated: a .armed class set the hidden
       start state, then a class added a frame later (via rAF, with a
       window-load fallback) triggered the transition to visible. That
       needs a real paint of the "armed, not yet revealed" frame to exist
       before the second class lands, or the browser never sees a value
       change and the content just appears with no fade - and whether that
       paint happens in time is not guaranteed: on a warm cache the load
       event can fire fast enough to win the race even past a double
       requestAnimationFrame defer, which is exactly what was happening
       here. A CSS animation does not have this problem: it does not need a
       prior painted frame to animate from, only a starting keyframe, so it
       plays reliably regardless of how fast the page loads. */
    @keyframes hero-reveal {
      from {
        opacity: 0;
        visibility: hidden;
        transform: translateY(30px);
      }
      .1% {
        visibility: visible;
      }
      to {
        opacity: 1;
        visibility: visible;
        transform: none;
      }
    }

    /* Longhand, not the `animation` shorthand: the shorthand also resets
       animation-delay to 0s, and .hero .reveal (2 classes) is more specific
       than the per-element .hero h1 / .hero p stagger rules below (1 class +
       1 type), so the shorthand's implicit 0s would win over their delay
       regardless of source order and the stagger would collapse to nothing. */
    /* --dur-base per element with a --dur-fast stagger step, not --dur-slow
       with a --dur-base step: the first pass read as sluggish because the
       last element (the slide rail) did not finish until 960ms of stagger
       plus its own 480ms, 1.44s before the hero read as fully in. Same two
       system tokens, tightened to the steps meant for on-load motion rather
       than the ones meant for image zoom and full-panel reveals. */
    .hero .reveal {
      animation-name: hero-reveal;
      animation-duration: var(--dur-base);
      animation-timing-function: var(--ease-out);
      animation-fill-mode: both;
    }

    .hero h1 {
      animation-delay: calc(var(--dur-fast) * 1);
    }

    .hero p {
      animation-delay: calc(var(--dur-fast) * 2);
    }

    .hero .hero-actions {
      animation-delay: calc(var(--dur-fast) * 3);
    }

    .hero .hero-slides-ind {
      animation-delay: calc(var(--dur-fast) * 4);
    }

    /* ===== RESPONSIVE ===== */
    @media(max-height:900px) and (min-width:981px) {
      .hero {
        min-height: 760px;
      }

      .hero-content {
        width: min(100%, 780px);
        max-width: 780px;
        padding-block: 96px 48px;
      }

      .hero h1 {
        font-size: clamp(2.25rem, min(4.05vw, 6.9svh), 3.55rem);
        line-height: 1.18;
        margin-bottom: 16px;
      }

      .hero p {
        max-width: 540px;
        font-size: clamp(.98rem, 1.35vw, 1.14rem);
        line-height: 1.72;
      }

      .hero-actions {
        margin-top: 26px;
      }

      .scroll-hint {
        top: calc(100dvh - 68px);
      }

    }

    @media(max-width:1280px) and (min-width:981px) {
      .wrap {
        width: min(calc(100% - 84px), var(--max));
      }

      /* The header's four size variables used to be re-declared here, once
         for the resting bar and once for .scrolled. Both are gone: the
         clamp() values on `header` now cover this band, so there is one bar
         size at every width instead of six competing declarations. */

      .nav-cta {
        letter-spacing: 0;
      }

      .logo img {
        max-width: 180px;
      }

      .hero-content {
        width: min(100%, 800px);
        max-width: 800px;
      }

      .hero h1 {
        font-size: clamp(2.35rem, min(4.25vw, 7.4svh), 3.85rem);
        line-height: 1.17;
      }

      .hero p {
        max-width: 540px;
      }

      .about-content h2 {
        font-size: clamp(3rem, 4.85vw, 5.15rem);
        line-height: 1.14;
      }

      .impact-head h2,
      .process-head h2,
      .projects-copy h2,
      .story-head h2,
      .why .sec-head h2,
      .partners-head h2,
      .news-head h2 {
        font-size: clamp(2.2rem, 4vw, 3.65rem);
        line-height: 1.18;
      }

      .cta h2 {
        font-size: clamp(2.65rem, 5vw, 4.6rem);
      }
    }

    @media(max-width:1180px) {
      .menu {
        gap: 22px;
      }

      .nav-actions {
        gap: 8px;
      }

      .nav-cta {
        padding: 0 20px;
        letter-spacing: 0;
      }

      .impact-main {
        grid-template-columns: minmax(280px, .62fr) minmax(0, 1fr);
      }

    }

    @media(max-width:980px) {

      .cta-actions,
      .about-pillars {
        grid-template-columns: 1fr;
      }

      /* The icon column leaves 182px for the copy at 375px, which is too narrow
         for Arabic body text to set. It stacks instead. */
      .news-pending {
        grid-template-columns: 1fr;
        gap: 20px;
      }

      /* Hover-to-reveal is not a pattern a phone can use. @media (hover: none)
         already covers real touch hardware, but it does not fire under desktop
         viewport emulation and it misses hybrid devices, so the action is simply
         always visible at this width. */
      .sector-card-action {
        opacity: 1;
        transform: none;
      }

      /* The sector strip is absolutely pinned to the bottom of the hero on
         desktop, over the darkest part of the veil. At this width the hero
         itself stops being a fixed viewport-tall box, so an absolute strip
         would land on top of the headline instead of under it. Below this
         breakpoint it leaves the overlay and flows in normal document flow
         underneath the first screen instead. */

      .hero {
        height: auto;
        min-height: 0;
        display: block;
      }

      /* The copy block now carries the viewport height the hero used to hold, so
         the first screen is still a full-height image with the headline on it. */
      .hero-content {
        min-height: 100dvh;
        display: flex;
        flex-direction: column;
        justify-content: flex-end;
      }

      /* Positioned against the hero box, which is no longer viewport-tall, so
         it would land on top of the sector strip once the strip flows below. */
      .scroll-hint {
        display: none;
      }

      .hero-sectors {
        position: static;
        padding-block: 22px clamp(28px, 6vw, 40px);
        background: var(--surface-inverse);
      }

      /* The desktop track floors each column at 170px, which is wider than a
         phone viewport has to give three of. Two columns fit five cards as
         2/2/1 instead of overflowing the page horizontally. */
      .sector-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 14px;
      }

      .hero-sectors-label {
        color: rgba(255, 255, 255, .7);
      }


      .menu,
      .menu.open {
        display: flex;
        position: fixed;
        top: 74px;
        right: 20px;
        left: 20px;
        z-index: 1001;
        flex-direction: column;
        align-items: center;
        background: var(--offwhite);
        padding: 28px 32px;
        gap: 22px;
      }

      .menu.open a {
        min-height: 44px;
        display: flex;
        align-items: center;
        color: var(--ink);
      }

      .nav {
        gap: 18px;
      }

      .logo img {
        max-width: 180px;
        height: 42px;
      }

      .hero {
        min-height: 640px;
      }

      .hero-content {
        padding-block: 90px 40px;
      }

      .hero h1 {
        font-size: clamp(2.05rem, 6.1vw, 3.35rem);
        line-height: 1.2;
        max-width: 760px;
      }

      .hero p {
        max-width: 620px;
      }

      .hero-actions {
        width: min(100%, 620px);
      }

      .hero-actions .btn {
        flex: 1 1 230px;
        justify-content: center;
        min-height: 54px;
      }


      .impact-main {
        grid-template-columns: 1fr;
      }

      .impact-visual {
        min-height: 360px;
      }


      .process-head {
        margin-inline-start: 0;
      }

      .about-layout {
        grid-template-columns: 1fr;
        gap: 56px;
      }

      .about-content h2 {
        font-size: clamp(3rem, 8vw, 5.2rem);
      }


      .about-pillar {
        border-inline-start: 0;
        padding: 28px 18px;
      }

      .about-pillar:first-child {
        border-top: 0;
      }

      .about-values {
        gap: 28px 0;
      }

      .about-badge {
        right: 24px;
        bottom: -22px;
      }

      .projects-head {
        grid-template-columns: 1fr;
        align-items: start;
      }

      .projects-copy {
        margin-inline-start: 0;
      }

      .project-tabs {
        order: 2;
      }


      .project-card-img {
        height: 260px;
      }

      .projects-footer {
        grid-template-columns: auto 1fr;
      }

      .projects-footer-mark {
        display: none;
      }

      .story-timeline {
        gap: 42px 0;
      }

      .story-timeline::before {
        display: none;
      }

      .story-item {
        border-inline-start: 0;
      }

      .story-dot {
        display: none;
      }

      .story-item p {
        min-height: 0;
      }

      .story-footer {
        grid-template-columns: auto 1fr;
      }

      .story-footer .btn {
        grid-column: 1 / -1;
        justify-content: center;
      }


      .why-footer {
        grid-template-columns: auto 1fr;
      }

      .why-footer .footer-mark {
        display: none;
      }


      .partners-trust {
        grid-template-columns: 1fr;
      }

      .partner-stat {
        border-inline-start: 0;
      }

      .news-head {
        flex-direction: column;
        align-items: stretch;
        margin-bottom: 36px;
      }

      .news-head p {
        max-width: none;
      }

      .news-all {
        align-self: flex-start;
      }

      .news-tabs {
        width: 100%;
        margin-bottom: 34px;
      }

      .news-grid {
        gap: 18px;
      }

      .news-card .img {
        aspect-ratio: 16 / 10;
      }

      .news-body {
        padding: 22px;
      }

      .news-subscribe {
        grid-template-columns: 1fr;
        padding: 26px 24px;
      }

      .news-form {
        max-width: 560px;
      }

      .news-social {
        padding-inline-start: 0;
        padding-top: 22px;
        border-inline-start: 0;
      }

      .cta-inner {
        padding: var(--sec-pad) 0;
      }

      .cta-actions {
        max-width: 620px;
      }

      .foot-grid {
        grid-template-columns: 1fr 1fr
      }
    }

    /* Lifted out of the 980 block above when the drawer's trigger moved to
     1280. These are the drawer's own contact button and language switch,
     and the two rules that take their desktop counterparts out of the bar.
     Left behind at 980, the drawer opened between 1000 and 1279 with no way
     to contact anyone and no way to change language, while the desktop CTA
     stayed in a bar that no longer had a menu - measured, not guessed.

     What did NOT come with them, deliberately: .nav's gap, .logo img's
     cap and .menu.open's own panel geometry. Those are phone sizing, not
     drawer switching, and they stay where they were. */
    @media (max-width: 1280px) {
    .nav-cta {
      display: none
    }

    .menu.open .menu-mobile-actions {
      width: 100%;
      display: flex;
      flex-direction: column;
      gap: 22px;
      padding-top: 12px;
    }

    .menu.open .menu-lang {
      display: flex;
      width: 100%;
      min-height: 52px;
      align-items: center;
      justify-content: space-between;
      color: var(--charcoal);
      font-size: 1.05rem;
      font-weight: 700;
      letter-spacing: 0;
    }

    .menu.open .menu-lang::after {
      content: "›";
      color: var(--charcoal);
      font-size: 2.2rem;
      line-height: 1;
    }

    .menu.open .menu-contact {
      width: 100%;
      min-height: 58px;
      display: flex;
      justify-content: center;
      background: var(--charcoal);
      color: #fff;
      border-radius: var(--r);
      font-size: .88rem;
      font-weight: 800;
      letter-spacing: 0;
    }

    .menu.open .menu-contact:hover {
      background: var(--accent);
      border-color: var(--accent);
      color: #fff;
    }

    .nav-actions>.lang {
      display: none;
    }

    /* The control that OPENS the drawer. Left behind at 980 it produced the
       worst state of the three: between 1000 and 1279 the menu was a drawer,
       the desktop links were gone, and there was no button to open it - a
       page with no navigation at all. Visible in a screenshot, invisible to a
       probe that clicks the element programmatically, which is how it got
       past the first check. */
    .burger {
      display: flex;
    }
    }

    @media(max-width:560px) {
      .wrap {
        padding: 0 20px
      }

      .pad {
        padding: var(--sec-pad) 0
      }

      /* Same removal as the 981-1500 band above: the header's size variables
         are declared once, on `header`, and their clamp() lower bounds are
         what hold this width. Nothing here re-declares them. */

      .nav-actions {
        gap: 6px;
      }

      .logo img {
        max-width: min(42vw, 146px);
        height: var(--logo-h);
      }

      .nav-icon {
        width: 40px;
        height: 40px;
      }

      .nav-icon i.ph {
        font-size: var(--ic-sm);
        line-height: 1;
      }

      .burger {
        width: 40px;
        height: 40px;
        align-items: center;
        justify-content: center;
      }

      .burger span {
        width: 24px;
      }

      .hero {
        min-height: 820px;
      }

      .hero-content {
        padding-block: 70px 32px;
      }

      .hero h1 {
        font-size: clamp(1.72rem, 7.6vw, 2.28rem);
        line-height: 1.22;
        margin-bottom: 18px;
      }

      .hero p {
        font-size: .98rem;
        line-height: 1.8;
      }

      .hero-actions {
        gap: 12px;
        margin-top: 28px;
      }

      .hero-actions .btn {
        width: 100%;
        flex-basis: 100%;
        justify-content: center;
        min-height: 52px;
      }

      .scroll-top {
        left: 16px;
        bottom: max(16px, env(safe-area-inset-bottom));
        width: 34px;
        height: 34px;
        font-size: .9rem;
      }

      .impact {
        padding: var(--sec-pad) 0;
      }

      .about {
        padding: var(--sec-pad) 0;
      }

      .about-layout {
        gap: 46px;
      }

      .about-visual img {
        border-radius: var(--r);
      }

      .about-badge {
        width: calc(100% - 28px);
        right: 14px;
        bottom: -26px;
        padding: 24px 24px;
      }

      .about-badge .big {
        font-size: 2.7rem;
      }

      .about-badge .t {
        grid-column: 1 / -1;
      }

      .about-content h2 {
        font-size: clamp(2.35rem, 12vw, 3.6rem);
        margin-bottom: 24px;
      }

      .about-copy {
        padding-inline-start: 18px;
      }

      .about-copy p {
        font-size: 1rem;
      }

      .about-pillars {
        margin-top: 34px;
      }

      .about-values {
        margin-top: 42px;
        padding: 24px 20px;
      }

      .about-value {
        border-inline-start: 0;
        padding: 22px 0 0;
      }

      .about-value:first-child {
        border-top: 0;
        padding-top: 0;
      }

      .impact-panel {
        padding: 34px 18px 28px;
      }

      .impact-grid {
        gap: 10px;
      }

      .impact-card {
        padding: 20px 18px;
        gap: 12px;
      }

      .impact-icon {
        width: 44px;
        height: 44px;
      }

      .impact-note {
        font-size: .74rem;
      }

      .impact-value {
        padding: 18px 16px;
      }

      .impact-value:first-child {
        border-top: 0;
        padding-top: 0;
      }

      .process {
        padding: var(--sec-pad) 0;
      }

      .process-head {
        margin-bottom: 34px;
      }

      .process-flow {
        gap: 38px;
      }

      .process-step {
        min-height: 0;
        padding: 28px 22px 26px;
      }

      .process-step:not(:last-child)::after {
        content: "⌄";
        top: auto;
        right: 50%;
        left: auto;
        bottom: -32px;
        width: 42px;
        height: 42px;
        font-size: 1.55rem;
        transform: translateX(50%);
      }

      .process-summary {
        grid-template-columns: 1fr;
        gap: 14px;
        padding: 24px 20px;
      }

      .process-summary strong {
        width: fit-content;
      }

      .projects-head {
        gap: 26px;
        margin-bottom: 34px;
      }

      .project-tabs {
        gap: 10px;
      }

      .project-tab {
        min-height: 56px;
      }


      .project-card-img {
        height: 245px;
      }

      .project-card-body {
        padding: 24px 22px 22px;
      }

      .projects-footer {
        grid-template-columns: 1fr;
        padding: 24px 22px;
      }

      .projects-footer-cta {
        justify-self: start;
      }

      .story-head {
        margin-bottom: 36px;
      }

      .story-timeline {
        gap: 0;
        padding-top: 0;
        direction: rtl;
      }

      .story-item {
        display: grid;
        grid-template-columns: 84px 1fr;
        gap: 0 20px;
        padding: 0 0 34px;
        text-align: right;
        border-inline-start: 0;
        padding-inline-end: 24px;
      }

      .story-item:last-child {
        padding-bottom: 0;
      }

      .story-year {
        grid-row: 1 / span 4;
        font-size: 1.8rem;
        margin: 0;
      }

      .story-image {
        margin-top: 18px;
      }

      .story-achievement {
        margin-top: 18px;
      }

      .story-footer {
        grid-template-columns: 1fr;
        padding: 24px 22px;
      }

      .story-footer p {
        border-inline-start: 0;
        padding-inline-start: 0;
      }

      .why .sec-head {
        margin-bottom: 34px;
      }


      /* Media-beside-text needs width to spare for the narrower column; below
         this breakpoint the card goes back to stacking media above text. */
      .why-grid {
        grid-template-columns: 1fr;
      }

      .why-card {
        grid-template-columns: 1fr;
      }

      .why-media {
        height: 220px;
      }

      .why-card-body {
        padding: 26px 22px 28px;
      }

      .why-footer {
        grid-template-columns: 1fr;
        padding: 24px 22px;
      }

      .why-footer p {
        text-align: right;
      }

      .partners-head {
        margin-bottom: 34px;
      }


      .partner-card {
        min-height: 0;
        padding: 30px 22px 26px;
      }

      .partners-trust-copy {
        grid-template-columns: 1fr;
        padding: 28px 24px;
      }

      .partner-stat {
        padding: 26px 22px;
      }

      .news-tabs {
        border-radius: var(--r);
        padding: 6px;
      }

      .news-tab {
        min-height: 40px;
        padding: 0 16px;
      }


      .news-body {
        min-height: 0;
      }

      .news-subscribe {
        gap: 22px;
        padding: 24px 20px;
      }

      .news-subscribe-copy {
        grid-template-columns: 1fr;
      }

      .news-form {
        flex-wrap: wrap;
      }

      .news-form input {
        flex-basis: 100%;
      }

      .news-form button {
        flex: 1 1 100%;
      }

      .news-social {
        flex-wrap: wrap;
        white-space: normal;
      }

      .cta-inner {
        padding: 88px 0;
      }

      .cta h2 {
        font-size: clamp(2.35rem, 13vw, 3.6rem);
      }

      .cta h2 br {
        display: none;
      }

      .cta p {
        margin-bottom: 34px;
      }

      .cta-action {
        min-height: 74px;
        padding: 0 20px;
        font-size: .98rem;
      }

      .foot-grid {
        grid-template-columns: 1fr
      }

    }

    @media(max-width:420px) {
      .nav {
        gap: 10px;
      }

      .logo img {
        max-width: min(39vw, 146px);
      }

      .lang {
        display: none;
      }

      .nav-actions {
        gap: 4px;
      }
    }

    .h-\[3rem\] {
      height: 3rem
    }

    /* ===== REVIEW PASS: PROJECTS / STORY / WHY / PARTNERS / NEWS / CONTACT =====
       These rules keep sdeira.html's content structure while replacing the
       compressed card rows with clearer, responsive compositions. */

    /* Projects: one connected portfolio rail. Every card owns the same rows, so
       a longer paragraph cannot expose the old dark backing below its siblings. */
    .project-cards {
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 1px;
      background: var(--line);
      overflow: hidden;
      border-radius: var(--r);
    }

    .project-card {
      min-width: 0;
      height: 100%;
      display: grid;
      grid-template-rows: clamp(220px, 22vw, 310px) 1fr;
      background: var(--surface-sunken);
      border-radius: var(--r);
    }

    .project-card-img {
      height: auto;
    }

    .project-card-body {
      min-height: 100%;
      display: flex;
      flex-direction: column;
      padding: clamp(24px, 2.4vw, 34px);
    }

    .project-card p {
      min-height: 0;
      flex: 1 1 auto;
    }

    .projects-footer {
      margin-top: 1px;
      border: 0;
      background: var(--surface-warm);
      padding: clamp(26px, 3vw, 38px);
    }

    .projects-footer h3,
    .projects-footer p {
      color: var(--ink);
    }

    /* Timeline: a real central rail with alternating editorial panels. Each
       milestone gets its own row, so copy length never compresses its neighbour. */
    .story-timeline {
      display: grid;
      grid-template-columns: minmax(0, 1fr) 80px minmax(0, 1fr);
      grid-template-rows: repeat(5, auto);
      gap: 0;
      padding-top: 0;
      margin-top: clamp(48px, 6vw, 82px);
      direction: rtl;
    }

    .story-timeline::before {
      top: 0;
      bottom: 0;
      right: 50%;
      left: auto;
      width: 2px;
      height: auto;
      transform: translateX(50%);
      background: var(--icon-warm-fill);
    }

    .story-item {
      width: 100%;
      min-width: 0;
      display: grid;
      grid-template-columns: minmax(0, 1.05fr) minmax(180px, .95fr);
      grid-template-rows: auto auto 1fr;
      gap: 0 clamp(24px, 3vw, 42px);
      align-items: start;
      padding: clamp(26px, 3.2vw, 42px);
      margin: 0 0 clamp(30px, 4vw, 54px);
      background: var(--surface-raised);
      text-align: right;
      border-radius: var(--r);
    }

    .story-item:nth-child(odd) {
      grid-column: 1;
      margin-inline-end: 0;
    }

    .story-item:nth-child(even) {
      grid-column: 3;
      margin-inline-start: 0;
    }

    .story-item:nth-child(1) { grid-row: 1; }
    .story-item:nth-child(2) { grid-row: 2; }
    .story-item:nth-child(3) { grid-row: 3; }
    .story-item:nth-child(4) { grid-row: 4; }
    .story-item:nth-child(5) { grid-row: 5; }

    .story-dot {
      top: clamp(30px, 3.2vw, 42px);
      left: auto;
      right: auto;
      width: 18px;
      height: 18px;
      transform: none;
      background: var(--accent);
      outline: 8px solid var(--surface-sunken-strong);
    }

    .story-item:nth-child(odd) .story-dot {
      left: calc(-40px - 9px);
      right: auto;
    }

    .story-item:nth-child(even) .story-dot {
      right: calc(-40px - 9px);
      left: auto;
    }


    .story-item h3 {
      grid-column: 1;
      margin-bottom: 12px;
      font-size: clamp(1.25rem, 1.8vw, 1.65rem);
    }


    .story-image {
      grid-column: 2;
      grid-row: 1 / span 3;
      align-self: stretch;
      min-height: 230px;
      margin: 0;
      aspect-ratio: auto;
    }


    .story-footer .btn {
      min-height: 54px;
      justify-content: center;
      text-align: center;
      line-height: 1.45;
    }

    /* Why: image-led editorial cards. Photos remain large at the review width
       instead of being squeezed into a narrow third of each card. */
    .why-grid {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 1px;
      background: var(--line);
      overflow: hidden;
      border-radius: var(--r);
    }

    .why-card {
      min-width: 0;
      display: grid;
      grid-template-columns: 1fr;
      grid-template-rows: clamp(280px, 30vw, 390px) 1fr;
      border-radius: var(--r);
      background: var(--surface-raised);
    }

    .why-media img {
      position: relative;
    }


    .why-card-body {
      padding: clamp(28px, 3.4vw, 46px);
    }

    .why-card h3 {
      min-height: 0;
    }

    /* Partner names restored from the agreed sdeira.html baseline. */
    .partners-grid {
      grid-template-columns: repeat(5, minmax(0, 1fr));
      gap: 1px;
      background: var(--line);
      overflow: hidden;
      border-radius: var(--r);
    }

    .partner-card {
      min-width: 0;
      min-height: 360px;
      border-radius: var(--r);
      background: var(--surface-raised);
    }

    .partner-logo {
      width: 100%;
      min-height: 88px;
      color: var(--ink);
      font-family: Arial, sans-serif;
      font-size: clamp(1.45rem, 2.2vw, 2rem);
      letter-spacing: 0;
    }

    .partner-logo span {
      font-size: .62em;
      letter-spacing: 0;
    }

    .partner-logo.schneider { color: var(--brand-liwa); }
    .partner-logo.abb { color: var(--brand-liwa); font-weight: 900; }
    .partner-logo.carrier { color: var(--brand-jais); font-weight: 500; }
    .partner-logo.honeywell { color: var(--brand-liwa); font-weight: 700; }
    .partner-logo.johnson { color: var(--brand-jais); }

    .partners-trust {
      grid-template-columns: minmax(300px, .9fr) minmax(0, 1.5fr);
      background: var(--surface-raised);
    }

    .partner-stats {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 1px;
      padding: 0;
      background: var(--line);
    }

    .partner-stat {
      min-width: 0;
      min-height: 180px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 24px 18px;
      background: var(--surface-sunken);
    }

    .partner-stat i.ph {
      margin-bottom: 12px;
      color: var(--icon);
    }

    .partner-stat strong {
      font-size: clamp(1.35rem, 2.2vw, 2rem);
      color: var(--ink);
    }

    .partner-stat span,
    .partner-stat small {
      color: var(--muted);
    }

    /* News: source-backed cards with a locally stored image for stable previews. */
    .news-grid {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 1px;
      background: var(--line);
      overflow: hidden;
      border-radius: var(--r);
    }

    .news-card {
      min-width: 0;
      border-radius: var(--r);
      cursor: default;
    }

    .news-image-link {
      display: block;
      overflow: hidden;
    }

    .news-card h3 a {
      color: inherit;
    }


    .news-subscribe {
      background: var(--surface-warm);
      color: var(--ink);
    }

    .news-subscribe h3,
    .news-subscribe p {
      color: var(--ink);
    }

    .news-form {
      background: var(--surface-raised);
    }

    .news-form:focus-within {
      background: var(--surface-base);
    }

    .news-social {
      border-color: rgba(65, 64, 66, .22);
    }

    .news-social,
    .news-social a {
      color: var(--ink);
    }

    /* Contact routes: dark cards belong to the Liwa field; white slabs did not. */
    .cta-action {
      min-height: 230px;
      justify-content: center;
      background: var(--surface-inverse);
      color: #fff;
    }


    .foot-contact bdi {
      direction: ltr;
      unicode-bidi: isolate;
    }

    @media(max-width:1180px) {
      .project-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }

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

      .partners-trust {
        grid-template-columns: 1fr;
      }
    }

    @media(max-width:900px) {
      .story-timeline {
        grid-template-columns: 30px minmax(0, 1fr);
        grid-template-rows: none;
        direction: ltr;
      }

      .story-timeline::before {
        left: 15px;
        right: auto;
        transform: none;
      }

      .story-item,
      .story-item:nth-child(odd),
      .story-item:nth-child(even) {
        grid-column: 2;
        grid-row: auto;
        margin-inline: 0;
        direction: rtl;
      }

      .story-item .story-dot,
      .story-item:nth-child(odd) .story-dot,
      .story-item:nth-child(even) .story-dot {
        display: block;
        left: -24px;
        right: auto;
      }

      /* .news-grid's own auto-fit already handles column collapse now (see
         the active .news-grid rule further down). The old side-by-side
         .news-card override below this used to fire here too, splitting
         each secondary card into image-right/text-left columns while the
         card's height was driven by the (taller) text column - the image
         column then had nowhere to grow into, leaving a large empty grey
         gap under the photo. Removed: the default vertical .news-card
         layout (image full-width on top, body below, no side-by-side
         split) already matches the feature card's own single-column
         behaviour at this width, so nothing needs overriding here. */
    }

    @media(max-width:720px) {
      .project-cards,
      .why-grid,
      .partners-grid,
      .partner-stats {
        grid-template-columns: 1fr;
      }

      .project-card {
        grid-template-rows: clamp(240px, 72vw, 340px) 1fr;
      }

      .projects-footer {
        grid-template-columns: auto 1fr;
      }

      .projects-footer-cta {
        grid-column: 1 / -1;
        width: 100%;
        justify-content: center;
      }

      .story-item {
        grid-template-columns: 1fr;
      }

      .story-image {
        grid-column: 1;
        grid-row: auto;
        min-height: 260px;
        margin-top: 24px;
      }

      .story-achievement {
        grid-column: 1;
      }

      .why-card {
        grid-template-rows: clamp(240px, 76vw, 360px) 1fr;
      }

      .partner-card {
        min-height: 300px;
      }

      .news-card {
        grid-template-columns: 1fr;
        grid-template-rows: auto 1fr;
      }

      .news-card .img {
        height: auto;
      }

      .news-subscribe {
        background: var(--surface-warm);
      }

      .cta-action {
        min-height: 190px;
        padding: 30px 22px;
      }
    }

    /* ===== REVIEW PASS: NAV / SECTION SIGNATURE / ABOUT / PROCESS ===== */
    .lang,
    .menu-lang {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      gap: 7px;
      min-height: 44px;
      padding-inline: 8px;
      color: rgba(255, 255, 255, .84);
      font-size: .82rem;
      font-weight: 600;
      line-height: 1;
      text-decoration: none;
      white-space: nowrap;
      transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
    }

    .lang i.ph,
    .menu-lang i.ph {
      font-size: var(--ic-sm);
    }

    .lang:hover,
    .lang:focus-visible {
      color: var(--brand-white);
      background: rgba(255, 255, 255, .12);
    }

    header.scrolled .lang:hover,
    header.scrolled .lang:focus-visible {
      color: var(--accent-text);
      background: var(--accent-wash);
    }

    main section:not(.hero) :is(.kicker, .impact-kicker, .process-kicker, .story-kicker, .partners-kicker) {
      display: inline-flex;
      align-items: center;
      gap: 10px;
      width: auto;
    }

    main section:not(.hero) :is(.kicker, .impact-kicker, .process-kicker, .story-kicker, .partners-kicker)::before {
      content: "";
      width: 20px;
      height: 20px;
      flex: 0 0 20px;
      background: url("../images/brand/sdeira-mark.png") center / contain no-repeat;
    }

    .about-badge {
      grid-template-columns: auto 1fr;
      align-items: start;
    }

    .about-badge .big {
      font-size: clamp(4rem, 7vw, 7.4rem);
      line-height: .72;
      font-variant-numeric: tabular-nums;
    }

    .about-badge .label {
      margin-top: 18px;
    }

    .about-values {
      margin-top: clamp(64px, 8vw, 112px);
      padding: 0;
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 1px;
      overflow: hidden;
      background: var(--surface-sunken-strong);
      border: 0;
    }

    .about-values-head {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: minmax(190px, .6fr) minmax(0, 1.4fr);
      align-items: end;
      gap: 32px;
      padding: clamp(28px, 4vw, 48px);
      background: var(--surface-inverse);
      color: var(--brand-white);
    }

    /* The homepage About figures continue the layout above; keep the same
       established values spacing after the figure/badge composition. */
    #about .about-layout + .stat-strip {
      margin-block-start: var(--sec-head-gap);
    }

    .about-values-head .kicker {
      color: var(--accent-on-dark);
      margin: 0;
    }

    .about-values-head h3 {
      margin: 0;
      color: var(--brand-white);
      font-size: clamp(2rem, 4vw, 3.8rem);
      line-height: 1.1;
    }

    .about-value {
      min-height: 220px;
      padding: clamp(26px, 3vw, 38px);
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 24px;
      background: var(--surface-sunken);
    }

    .about-value:nth-child(even) {
      background: var(--surface-base);
    }

    .about-value-icon {
      width: 54px;
      height: 54px;
    }

    .about-value h3 {
      font-size: clamp(1.1rem, 1.55vw, 1.35rem);
      margin-bottom: 10px;
    }

    .about-value p {
      max-width: 26ch;
      font-size: 1rem;
      line-height: 1.8;
    }

    .process-head {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(280px, .54fr);
      gap: clamp(30px, 5vw, 76px);
      align-items: end;
      max-width: none;
      margin: 0 0 clamp(42px, 6vw, 76px);
    }

    .process-head .process-kicker,
    .process-head h2 {
      grid-column: 1;
    }


    .process-head p {
      grid-column: 2;
      grid-row: 1 / span 2;
      max-width: 42ch;
      margin: 0;
      padding-inline-start: clamp(22px, 3vw, 42px);
      border-inline-start: 1px solid var(--brand-grey-70);
    }


    .process-step {
      min-width: 0;
      height: 100%;
      padding: clamp(28px, 3vw, 46px);
      align-items: flex-start;
      justify-content: flex-end;
      text-align: right;
      overflow: hidden;
      isolation: isolate;
      background: var(--surface-raised);
      transition: background var(--dur-base) var(--ease-out);
    }

    .process-step:nth-child(1) { grid-column: span 5; }
    .process-step:nth-child(2) { grid-column: span 4; background: var(--surface-sunken-strong); }
    .process-step:nth-child(3) { grid-column: span 3; }
    .process-step:nth-child(4) {
      grid-column: span 7;
      background: var(--surface-inverse);
      color: var(--brand-white);
    }
    .process-step:nth-child(5) { grid-column: span 5; background: var(--surface-warm); }


    .process-step::after,
    .process-step:not(:last-child)::after {
      content: none;
      display: none;
    }

    .process-step:nth-child(4):hover {
      background: var(--surface-inverse-soft);
    }

    .process-step:nth-child(5):hover {
      background: var(--brand-al-khatim);
    }

    .process-num {
      position: absolute;
      z-index: -1;
      inset-block-start: clamp(10px, 2vw, 24px);
      inset-inline-end: clamp(18px, 3vw, 42px);
      color: var(--surface-sunken-strong);
      font-size: clamp(5.6rem, 10vw, 9.6rem);
      font-weight: 700;
      line-height: .8;
      opacity: .62;
      pointer-events: none;
      transition: transform 480ms var(--ease-out);
    }

    .process-step:nth-child(2) .process-num { color: var(--brand-white); }
    .process-step:nth-child(4) .process-num { color: var(--brand-grey-70); opacity: .48; }
    .process-step:nth-child(5) .process-num { color: var(--brand-white); opacity: .42; }

    .process-step:hover .process-num {
      transform: translate3d(-10px, 0, 0);
    }

    .process-step h3,
    .process-step p,
    .process-icon {
      position: relative;
      z-index: 1;
    }


    .process-step:nth-child(4) h3,
    .process-step:nth-child(4) p {
      color: var(--brand-white);
    }

    .process-step:nth-child(4) p {
      color: var(--muted-on-dark);
    }

    .process-icon {
      order: -2;
      width: 60px;
      height: 60px;
      margin-bottom: auto;
      background: var(--surface-sunken);
      color: var(--brand-jais);
    }

    .process-step:nth-child(2) .process-icon {
      background: var(--brand-razeen);
      color: var(--brand-black);
    }

    .process-step:nth-child(3) .process-icon {
      background: var(--brand-al-khatim);
      color: var(--brand-black);
    }

    .process-step:nth-child(4) .process-icon {
      background: var(--brand-grey-70);
      color: var(--brand-white);
    }

    .process-step:nth-child(5) .process-icon {
      background: var(--brand-black);
      color: var(--brand-white);
    }

    .process-step:hover .process-icon {
      background: inherit;
    }

    .process-summary {
      position: relative;
      margin-top: clamp(28px, 4vw, 48px);
      grid-template-columns: minmax(230px, .6fr) minmax(0, 1.4fr);
      gap: clamp(28px, 6vw, 88px);
      padding: clamp(34px, 5vw, 64px);
      overflow: hidden;
      background: var(--surface-brand);
      color: var(--brand-white);
    }

    .process-summary::before {
      content: "";
      position: absolute;
      inset-block-start: 0;
      inset-inline-start: 0;
      width: 100%;
      height: 5px;
      transform: scaleX(0);
      transform-origin: right center;
      background: var(--brand-razeen);
      transition: transform 800ms var(--ease-out);
    }

    .process-summary.reveal.in::before {
      transform: scaleX(1);
    }

    .process-summary-title {
      display: grid;
      gap: 12px;
      align-self: start;
    }

    .process-summary-title span {
      color: var(--accent-on-dark);
      font-family: var(--font-display);
      font-size: .82rem;
      letter-spacing: .08em;
    }

    .process-summary strong {
      padding: 0;
      color: var(--brand-white);
      font-size: clamp(1.7rem, 3vw, 2.8rem);
      line-height: 1.2;
      white-space: normal;
    }

    .process-summary p {
      max-width: 52ch;
      margin: 0;
      color: var(--brand-white);
      font-size: clamp(1.05rem, 1.4vw, 1.25rem);
      line-height: 2;
    }

    @media(max-width:980px) {
      .process-flow {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-auto-rows: minmax(300px, auto);
      }

      .process-step:nth-child(n) {
        grid-column: span 1;
      }

      .process-step:nth-child(5) {
        grid-column: 1 / -1;
      }

    }

    @media(max-width:720px) {
      .nav-actions > .lang {
        display: none;
      }

      .menu-lang {
        gap: 9px;
      }


      .about-values-head {
        grid-template-columns: 1fr;
        gap: 14px;
      }

      .about-value {
        min-height: 0;
      }

      .process-head {
        grid-template-columns: 1fr;
        gap: 22px;
      }

      .process-head .process-kicker,
      .process-head h2,
      .process-head p {
        grid-column: 1;
        grid-row: auto;
      }

      .process-head p {
        max-width: none;
        padding-inline-start: 0;
        padding-block-start: 20px;
        border-inline-start: 0;
        border-block-start: 1px solid var(--brand-grey-70);
      }

      .process-flow {
        grid-template-columns: 1fr;
        grid-auto-rows: minmax(280px, auto);
      }

      .process-step:nth-child(n) {
        grid-column: 1;
      }

      .process-summary {
        grid-template-columns: 1fr;
        gap: 26px;
      }
    }

    @media(prefers-reduced-motion: reduce) {
      .process-summary::before {
        transform: scaleX(1);
        transition: none;
      }

      .process-step:hover .process-num {
        transform: none;
      }
    }

    /* ===== REVIEW PASS: HERO RECONSTRUCTION / ABOUT RHYTHM ===== */
    .hero {
      min-height: max(700px, 100svh);
      display: flex;
      flex-direction: column;
      isolation: isolate;
      background: var(--image-overlay);
    }


    .hero-content {
      width: min(calc(100% - 40px), var(--max));
      max-width: var(--max);
      min-height: clamp(430px, 55svh, 560px);
      margin-inline: auto;
      padding-block: clamp(112px, 15vh, 180px) 48px;
      justify-content: flex-start;
    }

    .hero-content::after {
      content: none;
      display: none;
    }

    .hero-content-row {
      width: min(100%, 860px);
      gap: clamp(18px, 3vw, 34px);
      align-items: stretch;
    }

    .hero-content-copy {
      max-width: 760px;
    }


    .hero h1 {
      max-width: 15ch;
      font-size: clamp(2.35rem, min(5vw, 7.5svh), 4.4rem);
      margin-bottom: 18px;
    }

    .hero p {
      max-width: 52ch;
      font-size: clamp(1rem, 1.6vw, 1.2rem);
    }

    .hero-actions {
      gap: 10px;
      margin-top: 28px;
      align-items: center;
    }

    .hero-actions .btn {
      width: auto;
      min-width: 0;
      min-height: 48px;
      padding: 0 22px;
      justify-content: center;
      font-size: .95rem;
    }

    .hero-sectors {
      flex: 1 0 auto;
      padding-block: 0 clamp(24px, 4svh, 38px);
    }

    .hero-sectors-label {
      margin-bottom: 10px;
    }

    .sector-grid {
      grid-template-columns: repeat(5, minmax(0, 1fr));
      grid-auto-rows: clamp(210px, 24svh, 260px);
      justify-content: stretch;
      gap: 1px;
      overflow: hidden;
      background: rgba(var(--image-overlay-rgb), .7);
    }

    @media(min-width:1600px) {
      .sector-grid {
        grid-template-columns: repeat(5, minmax(0, 1fr));
      }
    }

    .sector-card {
      min-width: 0;
      block-size: 100%;
      min-height: clamp(210px, 24svh, 260px);
      aspect-ratio: auto;
      border-radius: var(--r);
    }

    /* Hover reveals content but never participates in layout: all sector
       cards retain the exact grid-track height in every interaction state. */
    .sector-card:is(:hover, :focus-within) {
      block-size: 100%;
      min-height: 0;
    }

    .sector-card-media {
      border-radius: var(--r);
    }


    .sector-card-media::after {
      background: rgba(var(--image-overlay-rgb), .82);
    }

    .sector-card-body {
      min-height: 100%;
      padding: clamp(18px, 2.2vw, 26px);
      justify-content: flex-end;
      gap: 7px;
    }

    .sector-card-mark {
      width: 42px;
      height: 42px;
      margin-bottom: auto;
      background: rgba(255, 255, 255, .15);
    }

    .sector-card-title {
      font-size: clamp(1.08rem, 1.45vw, 1.35rem);
    }

    .sector-card-sub {
      font-size: .86rem;
    }

    .sector-card-action {
      min-height: 24px;
      margin-top: 2px;
      opacity: .82;
      transform: none;
      font-size: .8rem;
    }

    .sector-card-panel {
      display: none;
    }

    .about-copy {
      max-width: 820px;
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: 22px clamp(28px, 4vw, 52px);
      padding: 0;
    }

    .about-copy p {
      margin: 0;
      font-size: clamp(1rem, 1.18vw, 1.18rem);
      line-height: 1.95;
    }

    .about-copy p:first-child {
      grid-column: 1 / -1;
      color: var(--accent-text);
      font-family: var(--font-display);
      font-size: clamp(1.35rem, 2vw, 1.8rem);
      line-height: 1.45;
    }

    .about-copy p:nth-child(3) {
      padding-inline-start: clamp(22px, 3vw, 38px);
      border-inline-start: 1px solid var(--surface-sunken-strong);
    }

    .about-pillars {
      margin-top: clamp(42px, 6vw, 68px);
      gap: 0;
      border-block: 1px solid var(--surface-sunken-strong);
    }

    .about-pillar {
      min-width: 0;
      padding: clamp(26px, 3vw, 38px);
      text-align: right;
      border-inline-start: 1px solid var(--surface-sunken-strong);
    }

    .about-pillar:first-child {
      border-inline-start: 0;
    }

    .about-icon {
      width: 50px;
      height: 50px;
      margin: 0 0 20px;
    }

    .about-pillar p {
      max-width: 22ch;
    }

    .impact-visual::after {
      background:
        linear-gradient(to bottom,
          rgba(var(--image-overlay-rgb), .78) 0%,
          rgba(var(--image-overlay-rgb), .78) 15%,
          transparent 48%),
        linear-gradient(to top,
          rgba(var(--image-overlay-rgb), .88) 0%,
          rgba(var(--image-overlay-rgb), .88) 20%,
          transparent 52%);
    }


    @media(max-width:980px) {
      .hero-content {
        min-height: clamp(470px, 64svh, 610px);
      }

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

      .sector-card {
        min-height: 230px;
      }
    }

    @media(max-width:720px) {

      .hero-content {
        width: calc(100% - 36px);
        min-height: clamp(470px, 66svh, 590px);
        padding-block: 94px 30px;
      }

      .hero-content-row {
        width: 100%;
        gap: 16px;
      }

      .hero-slides-ind {
        flex-basis: 14px;
      }

      .hero h1 {
        max-width: none;
        font-size: clamp(2.15rem, 11vw, 3.2rem);
        line-height: 1.14;
      }

      .hero p {
        font-size: 1rem;
        line-height: 1.75;
      }

      .hero-actions {
        flex-wrap: nowrap;
      }

      .hero-actions .btn {
        min-height: 46px;
        padding-inline: 16px;
        font-size: .88rem;
      }


      .hero-sectors {
        padding-block: 4px 26px;
      }

      .hero-sectors .wrap {
        width: 100%;
        max-width: none;
        padding-inline: 18px;
      }

      .sector-grid {
        grid-auto-flow: column;
        grid-template-columns: none;
        grid-auto-columns: calc((100vw - 48px) / 2);
        justify-content: start;
        gap: 1px;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: inline mandatory;
        scrollbar-width: thin;
        overscroll-behavior-inline: contain;
      }

      .sector-grid::-webkit-scrollbar {
        height: 4px;
      }

      .sector-grid::-webkit-scrollbar-track {
        background: rgba(var(--image-overlay-rgb), .65);
      }

      .sector-grid::-webkit-scrollbar-thumb {
        background: var(--brand-razeen);
      }

      .sector-card {
        min-height: 224px;
        scroll-snap-align: start;
      }

      .sector-card-body {
        padding: 16px;
      }

      .sector-card-mark {
        width: 38px;
        height: 38px;
      }

      .sector-card-title {
        font-size: 1rem;
      }

      .sector-card-sub {
        font-size: .78rem;
      }

      .sector-card-subs,
      .sector-card-action {
        font-size: .72rem;
      }

      .about-copy {
        grid-template-columns: 1fr;
        gap: 18px;
      }

      .about-copy p:first-child {
        grid-column: 1;
      }

      .about-copy p:nth-child(3) {
        padding-inline-start: 0;
        padding-block-start: 18px;
        border-inline-start: 0;
        border-block-start: 1px solid var(--surface-sunken-strong);
      }

      .about-pillars {
        grid-template-columns: 1fr;
      }

      .about-pillar {
        display: grid;
        grid-template-columns: auto 1fr;
        gap: 6px 18px;
        align-items: start;
        border-inline-start: 0;
        border-block-start: 1px solid var(--surface-sunken-strong);
      }

      .about-pillar:first-child {
        border-block-start: 0;
      }

      .about-icon {
        grid-row: 1 / span 2;
        margin: 0;
      }

      .about-pillar h3,
      .about-pillar p {
        grid-column: 2;
      }
    }

    /* ===== REVIEW PASS: ABOUT BADGE / INSTITUTIONAL VALUES ===== */
    .about-badge {
      grid-template-columns: 1fr;
      overflow: hidden;
      isolation: isolate;
    }

    .about-badge > i.ph {
      position: absolute;
      z-index: -1;
      inset-block-start: 18px;
      inset-inline-end: 18px;
      font-size: clamp(6.5rem, 10vw, 10rem);
      line-height: 1;
      color: var(--brand-white);
      opacity: .12;
      transform: rotate(-8deg);
      pointer-events: none;
    }

    .about-badge .t {
      grid-column: 1;
      max-width: 25ch;
    }

    .about-values {
      grid-template-columns: repeat(4, minmax(0, 1fr));
      gap: 1px;
      background: var(--surface-base);
      border: 0;
    }

    .about-values-head {
      grid-column: 1 / -1;
      display: block;
      padding: 18px clamp(24px, 3vw, 34px);
      background: var(--surface-base);
      color: var(--ink);
    }

    .about-values-head h3 {
      color: var(--ink);
      font-size: clamp(1.1rem, 1.5vw, 1.3rem);
      font-weight: 600;
      line-height: 1.3;
    }

    .about-value,
    .about-value:nth-child(even) {
      min-height: 210px;
      background: var(--surface-sunken);
    }

    .about-value-icon {
      background: var(--icon-value-fill);
      color: var(--icon-value-text);
    }

    @media(max-width:980px) {
      .about-values {
        grid-template-columns: repeat(2, minmax(0, 1fr));
      }
    }

    @media(max-width:720px) {
      .about-badge > i.ph {
        inset-block-start: 14px;
        inset-inline-end: 14px;
        font-size: 5.25rem;
        opacity: .08;
      }

      .about-values {
        grid-template-columns: 1fr;
      }

      .about-values-head {
        padding: 16px 20px;
      }

      .about-value,
      .about-value:nth-child(even) {
        min-height: 220px;
      }
    }

    /* ===== REVIEW PASS: HERO STAGE / FULL-BLEED SECTOR OVERLAP ===== */
    .hero {
      display: block;
      height: max(700px, 100svh);
      min-height: max(700px, 100svh);
      overflow: hidden;
      background: transparent;
    }


    header:not(.scrolled)::before {
      opacity: 0;
    }

    .hero-content {
      height: 100%;
      min-height: 0;
      padding-block: clamp(104px, 14svh, 140px) clamp(132px, 15.75svh, 160px);
    }

    .scroll-hint {
      top: auto;
      bottom: calc(200px + 32px);
      z-index: 5;
    }

    .hero-sectors {
      position: relative;
      z-index: 4;
      width: 100%;
      margin-top: clamp(-112px, -10svh, -84px);
      padding: 0 0 clamp(28px, 4svh, 40px);
      background: var(--surface-inverse);
    }

    .hero-sectors .wrap {
      width: 100%;
      max-width: none;
      padding-inline: clamp(24px, 6vw, 84px);
    }

    .hero-sectors-label {
      min-height: 38px;
      margin: 0;
      display: flex;
      align-items: center;
      color: var(--muted-on-dark);
    }

    .sector-grid {
      width: 100%;
    }

    @media(max-width:720px) {
      .hero {
        height: 100svh;
        min-height: 680px;
      }

      .hero-content {
        min-height: 0;
        height: 100%;
        padding-block: 94px 128px;
      }

      .scroll-hint {
        display: flex;
        left: 18px;
        bottom: 112px;
        font-size: .74rem;
      }

      .scroll-hint span:last-child {
        display: none;
      }

      .hero::after {
        background:
          radial-gradient(ellipse 112% 62% at 64% 62%,
            rgba(var(--image-overlay-rgb), .44) 0%,
            rgba(var(--image-overlay-rgb), .20) 46%,
            rgba(var(--image-overlay-rgb), .04) 72%,
            transparent 100%),
          linear-gradient(180deg,
            transparent 0%,
            rgba(var(--image-overlay-rgb), .05) 55%,
            transparent 100%);
      }

      .hero-sectors {
        margin-top: -92px;
        padding-bottom: 26px;
      }

      .hero-sectors .wrap {
        padding-inline: 18px;
      }

      .hero-sectors-label {
        min-height: 34px;
      }
    }

    /* Sector cards, photographic depth without the previous heavy black hover. */
    .sector-card-img {
      filter: saturate(.96) contrast(1.02);
      transition: transform 450ms var(--ease-out), filter 300ms ease;
    }

    .sector-card:nth-child(3) .sector-card-img {
      object-position: 65% center;
    }

    .sector-card:nth-child(4) .sector-card-img {
      object-position: 48% center;
    }

    .sector-card-veil {
      background: linear-gradient(180deg,
          rgba(var(--image-overlay-rgb), .08) 0%,
          rgba(var(--image-overlay-rgb), .26) 46%,
          rgba(var(--image-overlay-rgb), .78) 100%);
      transition: background 300ms ease;
    }

    .sector-card-media::after {
      display: none;
    }

    .sector-card:hover .sector-card-img,
    .sector-card:focus-within .sector-card-img {
      transform: scale(1.025);
      filter: saturate(1) contrast(1.03);
    }

    .sector-card:hover .sector-card-veil,
    .sector-card:focus-within .sector-card-veil {
      background: linear-gradient(180deg,
          rgba(var(--image-overlay-rgb), .1) 0%,
          rgba(var(--image-overlay-rgb), .3) 46%,
          rgba(var(--image-overlay-rgb), .84) 100%);
    }

    .sector-card-body {
      position: relative;
      padding-bottom: 52px;
    }

    .sector-card-mark {
      color: var(--color-white);
      background: rgba(var(--image-overlay-rgb), .62);
      transition: background-color 200ms ease, transform 200ms var(--ease-out);
    }


    .sector-card-action {
      position: absolute;
      inset-inline-start: clamp(18px, 2.2vw, 26px);
      bottom: 20px;
      min-height: 24px;
      margin: 0;
      opacity: 0;
      visibility: visible;
      pointer-events: none;
      transform: translateY(6px);
      transition: opacity 200ms ease, transform 200ms var(--ease-out);
    }

    .sector-card:hover .sector-card-action,
    .sector-card:focus-within .sector-card-action {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
      transform: translateY(0);
    }

    .sector-card-action.is-pending {
      display: none;
    }

    .sector-card-action:focus,
    .sector-card-action:focus-visible {
      outline: 2px solid var(--color-white);
      outline-offset: 5px;
    }

    .sector-card:focus-within {
      outline: 2px solid rgba(255, 255, 255, .9);
      outline-offset: -4px;
    }

    @media (hover: none), (pointer: coarse) {
      .sector-card-action:not(.is-pending) {
        display: flex;
        min-height: 44px;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: none;
      }
    }

    @media (max-width: 720px) {
      .sector-card-action:not(.is-pending) {
        display: flex;
        min-height: 44px;
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: none;
      }


      .sector-card-action {
        bottom: 10px;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .sector-card-img,
      .sector-card-action,
      .sector-card-veil,
      .sector-card-mark {
        transition: none;
      }

      .sector-card:hover .sector-card-img,
      .sector-card:focus-within .sector-card-img {
        transform: none;
      }

      .sector-card:hover .sector-card-mark,
      .sector-card:focus-within .sector-card-mark {
        transform: none;
      }
    }

    /* ===== REVIEW PASS: FULL-BLEED SECTORS / BRAND BEAM / STORY RAIL / WHY ===== */

    .hero-sectors-label {
      min-height: 58px;
      padding-inline: max(20px, calc((100vw - var(--max)) / 2 + 20px));
      font-family: var(--font-display);
      font-size: clamp(1rem, 1.35vw, 1.2rem);
      font-weight: 700;
      letter-spacing: 0;
      color: var(--color-white);
    }

    .sector-grid {
      gap: 1px;
    }

    .projects-footer {
      position: relative;
      isolation: isolate;
      overflow: hidden;
      grid-template-columns: 1fr auto;
      min-height: 170px;
      padding: clamp(30px, 4vw, 48px);
      padding-inline-start: clamp(150px, 17vw, 210px);
    }

    .projects-footer-mark {
      display: none;
    }

    .projects-footer::after {
      content: "";
      position: absolute;
      z-index: -1;
      inset-inline-start: clamp(-48px, -3vw, -24px);
      inset-block-end: clamp(-72px, -5vw, -46px);
      width: clamp(170px, 18vw, 230px);
      aspect-ratio: 1;
      background: url("../images/brand/sdeira-mark.png") center / contain no-repeat;
    }

    .projects-footer h3 {
      font-family: var(--font-display);
      font-size: clamp(1.35rem, 2vw, 1.8rem);
      line-height: 1.45;
    }

    /* A contemporary chapter rail: chronological, horizontally explorable,
       and equal-height. It replaces the old alternating central spine. */
    .story-timeline {
      display: grid;
      grid-auto-flow: column;
      grid-auto-columns: minmax(320px, min(38vw, 450px));
      grid-template-columns: none;
      grid-template-rows: 1fr;
      gap: 1px;
      margin-top: clamp(42px, 6vw, 72px);
      padding: 0 0 18px;
      overflow-x: auto;
      overflow-y: hidden;
      overscroll-behavior-inline: contain;
      scroll-snap-type: inline mandatory;
      scrollbar-width: thin;
      scrollbar-color: var(--accent) rgba(var(--image-overlay-rgb), .12);
      background: transparent;
    }


    .story-timeline::-webkit-scrollbar {
      height: 6px;
    }

    .story-timeline::-webkit-scrollbar-track {
      background: rgba(var(--image-overlay-rgb), .1);
    }

    .story-timeline::-webkit-scrollbar-thumb {
      background: var(--accent);
    }

    .story-timeline:focus-visible {
      outline: 3px solid var(--accent);
      outline-offset: 8px;
    }

    .story-item,
    .story-item:nth-child(odd),
    .story-item:nth-child(even) {
      grid-column: auto;
      grid-row: 1;
      width: auto;
      min-width: 0;
      min-height: 620px;
      display: grid;
      grid-template-columns: 1fr;
      grid-template-rows: 250px auto auto 1fr auto;
      gap: 0;
      align-items: start;
      margin: 0;
      padding: 0;
      overflow: hidden;
      scroll-snap-align: start;
      text-align: right;
      background: var(--surface-raised);
      border-radius: var(--r);
    }

    .story-item::before {
      content: "";
      position: absolute;
      inset-block-start: 0;
      inset-inline-start: 0;
      z-index: 3;
      width: 42%;
      height: 5px;
      background: var(--accent);
    }

    .story-dot {
      display: none;
    }

    .story-image {
      grid-column: 1;
      grid-row: 1;
      width: 100%;
      min-height: 0;
      height: 250px;
      margin: 0;
      aspect-ratio: auto;
    }

    .story-year {
      grid-column: 1;
      grid-row: 2;
      margin: 0;
      padding: 26px 28px 4px;
      font-family: var(--font-brand);
      font-size: clamp(2.6rem, 4vw, 4rem);
      line-height: 1;
      color: var(--accent-text);
    }

    .story-item h3 {
      grid-column: 1;
      grid-row: 3;
      margin: 0;
      padding: 8px 28px 10px;
      font-family: var(--font-display);
      font-size: clamp(1.2rem, 1.7vw, 1.5rem);
    }

    .story-item>p {
      grid-column: 1;
      grid-row: 4;
      min-height: 0;
      margin: 0;
      padding: 0 28px 24px;
      font-size: .96rem;
      line-height: 1.85;
    }

    .story-achievement {
      grid-column: 1;
      grid-row: 5;
      min-height: 92px;
      margin: 0;
      padding: 20px 28px;
      border-top: 1px solid var(--line);
      background: var(--surface-sunken);
    }

    .story-icon {
      background: var(--surface-inverse);
      color: var(--color-white);
    }

    .why-card {
      position: relative;
    }

    .why-media::after {
      background: linear-gradient(180deg,
        rgba(var(--image-overlay-rgb), .02) 0%,
        rgba(var(--image-overlay-rgb), .12) 58%,
        rgba(var(--image-overlay-rgb), .46) 100%);
    }

    .why-ic {
      inset-block-end: 20px;
      inset-inline-start: 22px;
      width: 92px;
      height: 92px;
      color: #fff;
      background: transparent;
    }

    .why-card:nth-child(2) .why-media img {
      object-position: 50% 24%;
    }

    .why-ic::before {
      content: "";
      position: absolute;
      inset-inline-start: 0;
      inset-block: 10px;
      width: 3px;
      background: var(--accent);
    }

    .why-ic i.ph {
      font-size: 3.25rem;
      filter: drop-shadow(0 2px 8px rgba(var(--image-overlay-rgb), .34));
    }

    .why-card:hover .why-ic i.ph {
      transform: translateY(-2px);
    }

    @media (max-width: 720px) {
      .hero-sectors-label {
        min-height: 50px;
        padding-inline: 18px;
        font-size: .98rem;
      }

      .projects-footer {
        grid-template-columns: 1fr;
        gap: 22px;
        min-height: 0;
        padding: 30px 28px 118px;
      }

      .projects-footer::after {
        width: 140px;
        inset-inline-start: -24px;
        inset-block-end: -44px;
      }

      .projects-footer-cta {
        width: fit-content;
      }

      .story-timeline {
        grid-auto-columns: min(84vw, 340px);
        margin-inline: -18px;
        padding-inline: 18px;
        scroll-padding-inline: 18px;
      }

      .story-item,
      .story-item:nth-child(odd),
      .story-item:nth-child(even) {
        min-height: 590px;
        grid-template-rows: 220px auto auto 1fr auto;
      }

      .story-image {
        height: 220px;
      }

      .story-year {
        padding: 24px 24px 4px;
      }

      .story-item h3 {
        padding-inline: 24px;
      }

      .story-item>p {
        padding-inline: 24px;
      }

      .story-achievement {
        padding-inline: 24px;
      }

      .why-ic {
        width: 72px;
        height: 72px;
        inset-block-end: 16px;
        inset-inline-start: 16px;
      }

      .why-ic i.ph {
        font-size: 2.6rem;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .why-card:hover .why-ic i.ph {
        transform: none;
      }
    }
    /* ===== Closing sections refinement, 2026-07-26 ===== */

    .news-card {
      grid-template-rows: auto 1fr;
      border: 0;
      border-radius: var(--r);
    }

    .news-card .img {
      block-size: clamp(220px, 22vw, 260px);
      aspect-ratio: auto;
      margin: 0;
    }

    .news-card:nth-child(1) img { object-position: 55% center; }
    .news-card:nth-child(2) img { object-position: center 38%; }
    .news-card:nth-child(3) img { object-position: center 42%; }


    .news-card h3 {
      min-height: 4.5em;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 3;
      overflow: hidden;
    }

    .news-card p {
      min-height: 3.6em;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
    }

    .news-card .more {
      gap: 9px;
      color: var(--accent-text);
      font-weight: 700;
    }

    .news-card .more i.ph {
      font-size: 1.15rem;
      line-height: 1;
      transition: transform var(--dur-base) var(--ease-out);
    }

    .news-card .more:hover i.ph,
    .news-card .more:focus-visible i.ph {
      transform: translate(-2px, -2px);
    }

    .news-category::before {
      content: "◈";
      margin-inline-end: 7px;
      color: var(--accent);
      font-size: .78rem;
    }

    .news-card .date::before {
      content: "◷";
      color: var(--icon);
      font-size: 1rem;
    }

    .news-subscribe {
      min-height: 0;
      padding: 20px 24px;
      grid-template-columns: minmax(240px, .85fr) minmax(340px, 1.15fr) 132px;
      gap: 22px;
    }

    .news-subscribe-copy {
      gap: 12px;
    }

    .news-subscribe-icon {
      inline-size: 40px;
    }

    .news-subscribe p {
      font-size: .9rem;
      line-height: 1.55;
    }

    .news-social {
      padding: 0;
      display: grid;
      grid-template-columns: repeat(3, 44px);
      gap: 6px 8px;
      justify-content: start;
      white-space: normal;
    }

    .news-social > span {
      grid-column: 1 / -1;
      font-size: .8rem;
      line-height: 1.2;
    }

    .news-social a {
      inline-size: 44px;
      min-block-size: 44px;
    }

    .cta {
      position: relative;
      isolation: isolate;
      overflow: hidden;
    }

    /* The old .cta::before here was a small faint logo watermark (opacity
       fading in to .085 on reveal), from before the section carried a real
       photo. ::before is now the full-cover photo layer declared further
       down (background: url(real-estate-v2.webp)) - that rule and this one
       shared the same selector and fought over `opacity`, and because
       ".cta:has(.reveal.in)::before" is more specific than plain
       ".cta::before" it was winning regardless of source order, so the
       photo was rendering at ~8.5% opacity (effectively invisible) no
       matter what opacity was set on the actual photo rule. Removed along
       with its matching @media (max-width:800px) and
       @media (prefers-reduced-motion) fragments below. */

    .cta .wrap,
    .cta-inner {
      position: relative;
      z-index: 1;
    }


    .cta-action {
      min-height: 202px;
      padding: 26px 22px;
      gap: 11px;
      border: 0;
    }

    .cta-action > span:not(.cta-action-note) {
      font-family: var(--font-display);
      font-size: clamp(1.12rem, 1.35vw, 1.28rem);
      line-height: 1.35;
      font-weight: 700;
    }

    .cta-action i.ph {
      inline-size: 64px;
      block-size: 58px;
      font-size: 2.5rem;
    }

    .foot-brand {
      min-width: 0;
    }

    .foot-brand .logo {
      display: block;
      inline-size: min(220px, 100%);
      max-inline-size: 100%;
      aspect-ratio: 360 / 92;
      margin-bottom: 20px;
    }

    .foot-brand .logo img {
      display: block;
      inline-size: 100%;
      block-size: 100%;
      max-inline-size: 100%;
      object-fit: contain;
      object-position: right center;
    }

    @media (max-width: 800px) {
      .news-subscribe {
        grid-template-columns: minmax(0, 1fr) minmax(280px, 1fr);
      }

      .news-social {
        grid-column: 1 / -1;
      }

    }

    @media (max-width: 560px) {

      .news-body {
        padding: 20px;
      }

      .news-card h3 {
        min-height: 4.5em;
      }

      .news-card p {
        min-height: 3.6em;
      }

      .news-subscribe {
        grid-template-columns: minmax(0, 1fr);
        padding: 20px;
        gap: 16px;
      }

      .news-social {
        grid-column: auto;
      }

      .news-subscribe-copy {
        grid-template-columns: 40px minmax(0, 1fr);
      }

      .news-form {
        flex-wrap: nowrap;
      }

      .news-form input {
        flex: 1 1 auto;
        flex-basis: auto;
      }

      .news-form button {
        flex: 0 0 auto;
        padding-inline: 18px;
      }

      .cta-action {
        min-height: 168px;
      }

      .cta-action i.ph {
        inline-size: 56px;
        block-size: 52px;
        font-size: 2.15rem;
      }

      .foot-brand .logo {
        inline-size: min(190px, 100%);
      }
    }

    /* ===== Hero responsive reconstruction, 2026-07-26 ===== */
    /* The progress rail uses the x-axis at every viewport. Its 44px controls
       keep touch and keyboard access while the visible track stays 3px thin. */
    .hero-content-row {
      flex-direction: column;
      gap: clamp(12px, 2vw, 18px);
    }

    .hero-slides-ind {
      order: -1;
      flex: 0 0 44px;
      inline-size: clamp(220px, 28vw, 320px);
      block-size: 44px;
      flex-direction: row;
      align-items: center;
      align-self: flex-start;
      gap: 8px;
    }

    .hero-slide-line {
      flex: 1 1 0;
      inline-size: auto;
      block-size: 44px;
      overflow: visible;
      background:
        linear-gradient(to bottom,
          transparent calc(50% - 1.5px),
          rgba(255, 255, 255, .28) calc(50% - 1.5px),
          rgba(255, 255, 255, .28) calc(50% + 1.5px),
          transparent calc(50% + 1.5px));
    }

    .hero-slide-line::before {
      inset-inline-start: 0;
      inset-inline-end: auto;
      inset-block-start: 50%;
      inline-size: 0;
      block-size: 3px;
      height: 3px;
      transform: translateY(-50%);
    }

    .hero-slide-line.done::before {
      inline-size: 100%;
      height: 3px;
    }

    .hero-slide-line.active::before {
      inline-size: 100%;
      height: 3px;
      transition: inline-size var(--hero-slide-duration, 5.2s) linear;
    }

    @media (max-width: 720px) {
      .hero {
        min-height: 660px;
      }

      .hero-content {
        inline-size: calc(100% - 24px);
        min-height: 100svh;
        padding-block: 88px 86px;
        padding-inline: 4px;
      }

      .hero-content-row {
        gap: 8px;
      }

      .hero-content-copy {
        text-align: right;
      }

      .hero-slides-ind {
        flex-basis: 44px;
        inline-size: 100%;
        gap: 6px;
      }

      .hero .eyebrow {
        margin-bottom: 10px;
        font-size: .78rem;
      }

      .hero h1 {
        max-inline-size: 100%;
        margin: 0 0 16px;
        font-size: clamp(1.9rem, 9.6vw, 2.6rem);
        line-height: 1.17;
      }

      .hero p {
        max-inline-size: 31ch;
        margin: 0;
        font-size: clamp(.92rem, 4.1vw, .98rem);
        line-height: 1.68;
      }

      .hero-actions {
        inline-size: 100%;
        margin-top: 22px;
        gap: 8px;
      }

      .hero-actions .btn {
        flex: 1 1 0;
        min-inline-size: 0;
        padding-inline: 10px;
      }

      .hero-sectors {
        margin-top: -56px;
        padding-block: 0 24px;
      }

      .scroll-hint {
        display: none;
      }

      .hero-sectors .wrap {
        inline-size: 100%;
        max-inline-size: none;
        padding-inline: 0;
      }

      .hero-sectors-label {
        min-height: 48px;
        padding-inline: 12px;
      }

      .sector-grid {
        display: grid;
        grid-auto-flow: row;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        grid-auto-columns: auto;
        gap: 1px;
        overflow: visible;
        scroll-snap-type: none;
        scrollbar-width: none;
      }

      .sector-card {
        min-inline-size: 0;
        min-height: clamp(190px, 58vw, 224px);
        scroll-snap-align: none;
      }

      .sector-card:last-child:nth-child(odd) {
        grid-column: 1 / -1;
        min-height: 168px;
      }

      .sector-card-body {
        padding: 14px;
        padding-bottom: 56px;
      }

      .sector-card-title {
        font-size: clamp(.98rem, 5vw, 1.14rem);
      }

      .sector-card-sub {
        font-size: clamp(.74rem, 3.6vw, .84rem);
        line-height: 1.55;
      }

      .sector-card-mark {
        inline-size: 40px;
        block-size: 40px;
      }
    }

    @media (max-width: 360px) {
      .hero-content {
        inline-size: calc(100% - 20px);
        padding-inline: 4px;
      }

      .hero h1 {
        font-size: 2rem;
      }

      .hero p {
        font-size: .94rem;
      }

      .sector-card {
        min-height: 190px;
      }
    }
    /* ===== Mobile page guide + navigation drawer, 2026-07-26 ===== */
    :root {
      --page-gutter: 32px;
    }

    .menu-head {
      display: none;
    }

    @media (max-width: 720px) {
      :root {
        --page-gutter: clamp(14px, 4.6vw, 18px);
      }

      main > section > .wrap,
      footer > .wrap {
        padding-inline: var(--page-gutter);
      }

      /* Full-bleed media/grid exceptions keep their own internal guide. */
      .hero > .wrap {
        padding-inline: 4px;
      }

      .hero-sectors > .wrap {
        padding-inline: 0;
      }

      .hero-sectors-label {
        padding-inline: var(--page-gutter);
      }

      .impact-panel {
        padding-inline: 0;
      }

      .story-timeline {
        margin-inline: calc(-1 * var(--page-gutter));
        padding-inline: var(--page-gutter);
        scroll-padding-inline: var(--page-gutter);
      }
    }

    /* The sector marquee's own two rules were in the drawer block only because
       980 used to be both answers. Lifted out when the drawer's trigger moved
       to 1280 - hiding the marquee clone and its motion toggle at 1280 was
       never the design, and dragging them along would have been a silent
       change to a section that has nothing to do with the nav. */
    @media (max-width: 980px) {
      .sector-card.is-marquee-clone {
        display: none;
      }

      .sector-motion-toggle {
        display: none;
      }
    }

    /* --- Below 1280: the desktop menu becomes a drawer. ---------------------
       1280, not the 980 this was. The number was never measured against the
       nav it gates. .menu carries overflow: visible, so when the bar stops
       fitting between the logo and the icon controls the links do not clip or
       scroll - they draw straight over their neighbours. Measured on this page
       before the change: 60px of overlap at 1000, 20px at 1100, first clean at
       1180. The sub-page sheet had the same wrong number and was fixed in
       c56f5fe; this is the homepage half of it. */
    @media (max-width: 1280px) {
      body.menu-open {
        overflow: hidden;
        overscroll-behavior: none;
      }

      .menu {
        display: flex;
        position: fixed;
        z-index: 1101;
        top: 0;
        right: 0;
        bottom: 0;
        left: auto;
        inline-size: min(88vw, 380px);
        block-size: 100dvh;
        padding: 16px var(--page-gutter) max(24px, env(safe-area-inset-bottom));
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        background: var(--surface-raised);
        color: var(--ink);
        visibility: hidden;
        pointer-events: none;
        opacity: .98;
        transform: translateX(100%);
        transition:
          transform var(--dur-base) var(--ease-out),
          opacity var(--dur-base) var(--ease-out),
          visibility 0s linear var(--dur-base);
      }

      .menu::after {
        content: "";
        position: absolute;
        z-index: -1;
        inset-inline-start: -34px;
        inset-block-end: 54px;
        inline-size: 160px;
        aspect-ratio: 1;
        /* background: url("../images/brand/sdeira-mark.png") center / contain no-repeat; */
        opacity: .055;
        pointer-events: none;
      }

      .menu.open {
        display: flex;
        top: 0;
        right: 0;
        bottom: 0;
        left: auto;
        padding: 16px var(--page-gutter) max(24px, env(safe-area-inset-bottom));
        align-items: stretch;
        gap: 0;
        visibility: visible;
        pointer-events: auto;
        opacity: 1;
        transform: translateX(0);
        transition-delay: 0s;
      }

      .menu-head {
        min-block-size: 64px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 14px;
        border-block-end: 1px solid var(--line);
      }

      .menu-logo {
        min-block-size: 44px;
        display: flex;
        align-items: center;
      }

      .menu-logo img {
        display: block;
        inline-size: min(152px, 52vw);
        block-size: auto;
      }

      .menu-logo::after,
      .menu > a:not(.menu-logo)::after {
        display: none;
      }

      .menu-close {
        position: relative;
        inline-size: 44px;
        block-size: 44px;
        flex: 0 0 44px;
        border: 1px solid var(--line);
        background: transparent;
        color: var(--ink);
        cursor: pointer;
      }

      .menu-close span {
        position: absolute;
        left: 50%;
        right: auto;
        top: 50%;
        inline-size: 22px;
        block-size: 2px;
        background: currentColor;
        transform-origin: center;
      }

      .menu-close span:first-child {
        transform: translate(-50%, -50%) rotate(45deg);
      }

      .menu-close span:last-child {
        transform: translate(-50%, -50%) rotate(-45deg);
      }

      .menu > a:not(.menu-logo) {
        position: relative;
        min-block-size: 54px;
        padding-inline: 4px 12px;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        border-block-end: 1px solid var(--line);
        color: var(--ink);
        font-family: var(--font-display);
        font-size: 1.05rem;
        font-weight: 600;
        opacity: 0;
        transform: translateX(10px);
        transition:
          color 180ms var(--ease-out),
          background 180ms var(--ease-out),
          opacity 220ms var(--ease-out),
          transform 260ms var(--ease-out);
      }

      .menu.open > a:not(.menu-logo) {
        opacity: 1;
        transform: translateX(0);
      }

      .menu.open > a:nth-of-type(2) { transition-delay: 45ms; }
      .menu.open > a:nth-of-type(3) { transition-delay: 70ms; }
      .menu.open > a:nth-of-type(4) { transition-delay: 95ms; }
      .menu.open > a:nth-of-type(5) { transition-delay: 120ms; }
      .menu.open > a:nth-of-type(6) { transition-delay: 145ms; }
      .menu.open > a:nth-of-type(7) { transition-delay: 170ms; }
      .menu.open > a:nth-of-type(8) { transition-delay: 195ms; }
      .menu.open > a:nth-of-type(9) { transition-delay: 220ms; }

      .menu > a:not(.menu-logo):hover,
      .menu > a:not(.menu-logo):focus-visible,
      .menu > a:not(.menu-logo).active {
        background: var(--surface-sunken);
        color: var(--accent-text);
      }

      .menu > a:not(.menu-logo).active::before {
        content: "";
        position: absolute;
        inset-inline-start: 0;
        inline-size: 3px;
        block-size: 24px;
        background: var(--accent);
      }

      .menu.open .menu-mobile-actions {
        margin-block-start: auto;
        padding-block-start: 14px;
        gap: 10px;
        border-block-start: 1px solid var(--line);
      }

      .menu.open .menu-lang {
        min-height: 48px;
        padding-inline: 4px;
        justify-content: flex-start;
        gap: 10px;
        font-size: .95rem;
      }

      .menu.open .menu-lang::after {
        content: none;
      }

      .menu.open .menu-contact {
        min-height: 52px;
        background: var(--accent-deep);
      }

      .menu-backdrop {
        display: block;
        z-index: 999;
        visibility: hidden;
        pointer-events: none;
        opacity: 0;
        background: rgba(var(--image-overlay-rgb), .44);
        backdrop-filter: blur(4px);
        transition:
          opacity 250ms var(--ease-out),
          visibility 0s linear 250ms;
      }

      body.menu-open .menu-backdrop {
        display: block;
        visibility: visible;
        pointer-events: auto;
        opacity: 1;
        transition-delay: 0s;
      }

      body.menu-open .scroll-top {
        z-index: 997;
      }

      .burger {
        position: relative;
        margin-inline-end: 0;
        border: 0;
        background: transparent;
      }

      .burger span {
        position: absolute;
        left: 50%;
        right: auto;
        inline-size: 24px;
        transition:
          transform var(--dur-base) var(--ease-out),
          opacity var(--dur-fast) var(--ease-out);
      }

      .burger span:nth-child(1) {
        transform: translate(-50%, -7px);
      }

      .burger span:nth-child(2) {
        transform: translate(-50%, 0);
      }

      .burger span:nth-child(3) {
        transform: translate(-50%, 7px);
      }

      .burger[aria-expanded="true"] span:nth-child(1) {
        transform: translate(-50%, 0) rotate(45deg);
      }

      .burger[aria-expanded="true"] span:nth-child(2) {
        opacity: 0;
        transform: translate(-50%, 0) scaleX(.2);
      }

      .burger[aria-expanded="true"] span:nth-child(3) {
        transform: translate(-50%, 0) rotate(-45deg);
      }

      body.menu-open .burger {
        opacity: 0;
        pointer-events: none;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .menu,
      .menu-backdrop,
      .menu > a:not(.menu-logo),
      .burger span {
        transition: none !important;
      }
    }
    /* 2026-07-26 content and identity revision */
    .btn-primary,
    .news-form button {
      background: var(--brand-sweihan);
      color: var(--brand-black);
    }

    .btn-primary:hover,
    .btn-primary:focus-visible,
    .news-form button:hover,
    .news-form button:focus-visible {
      background: var(--brand-al-khatim);
      color: var(--brand-black);
      box-shadow: none;
    }

    .method-en {
      display: block;
      color: var(--brand-jais);
      font-size: .78rem;
      font-weight: 700;
      text-transform: uppercase;
      margin-block: 14px 2px;
    }

    .about-figures .about-values-head p {
      max-width: 34ch;
      margin: 8px 0 0;
      color: var(--muted-on-dark);
      line-height: 1.6;
    }

    .verified-figure {
      display: block;
      direction: ltr;
      font-size: clamp(2rem, 3.8vw, 3.7rem);
      line-height: 1;
      color: var(--brand-black);
      font-weight: 500;
      margin-bottom: 12px;
      border-inline-start: 5px solid var(--brand-sweihan);
      padding-inline-start: 14px;
    }

    .value-sections {
      background: var(--surface-sunken);
      padding-block: var(--sec-pad);
    }

    .value-block + .value-block {
      margin-top: clamp(54px, 7vw, 96px);
    }

    .value-head {
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(280px, .72fr);
      gap: clamp(24px, 5vw, 72px);
      align-items: end;
      margin-bottom: clamp(28px, 4vw, 48px);
    }

    .value-head .kicker {
      color: var(--brand-jais);
    }

    .value-head h2 {
      margin: 8px 0 0;
      font-size: clamp(2rem, 4vw, 4.4rem);
      line-height: 1.08;
    }

    .value-head p {
      margin: 0;
      color: var(--muted);
      font-size: 1.03rem;
      line-height: 1.8;
    }

    .companies-grid,
    .services-grid {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      background: var(--line);
      gap: 1px;
    }

    .company-card,
    .service-card {
      background: var(--surface-base);
      padding: clamp(24px, 3vw, 40px);
      min-height: 250px;
      position: relative;
      overflow: hidden;
    }

    .company-card::before {
      content: "";
      position: absolute;
      inset-inline-start: 0;
      top: 0;
      width: 7px;
      height: 100%;
      background: var(--company-accent, var(--brand-sweihan));
    }

    .company-card .company-num,
    .service-card .service-num {
      color: var(--label);
      font-size: .8rem;
      direction: ltr;
      display: block;
      margin-bottom: 44px;
    }

    .company-card h3,
    .service-card h3 {
      font-size: clamp(1.45rem, 2vw, 2rem);
      margin: 0 0 12px;
    }

    .company-card p,
    .service-card p {
      color: var(--muted);
      margin: 0;
      line-height: 1.7;
    }

    .company-card a,
    .service-card a {
      color: var(--ink);
      display: inline-flex;
      gap: 8px;
      align-items: center;
      margin-top: 24px;
      font-weight: 700;
      min-height: 44px;
      padding-block: 10px;
    }


    .service-card .service-meta {
      color: var(--brand-jais);
      font-size: .8rem;
      font-weight: 700;
      margin-bottom: 10px;
    }

    .service-card a {
      margin-top: auto;
      padding-top: 24px;
    }

    .service-pending {
      margin-top: auto;
      padding-top: 24px;
      min-height: 44px;
      display: inline-flex;
      align-items: center;
      color: var(--label);
      font-size: .88rem;
    }

    .openings-panel {
      display: grid;
      grid-template-columns: minmax(220px, .65fr) minmax(0, 1.35fr);
      background: var(--brand-black);
      color: white;
    }

    .openings-intro {
      padding: clamp(28px, 4vw, 52px);
      background: var(--brand-sweihan);
      color: var(--brand-black);
    }

    .openings-intro i {
      font-size: 2rem;
    }

    .openings-intro h3 {
      font-size: clamp(1.7rem, 3vw, 2.8rem);
      margin: 28px 0 10px;
    }

    .openings-intro p {
      margin: 0;
      line-height: 1.7;
    }

    .opening-row {
      display: grid;
      grid-template-columns: 1.4fr .8fr .8fr;
      gap: 24px;
      align-items: center;
      padding: clamp(24px, 3vw, 36px);
    }

    .opening-row + .opening-row {
      border-top: 1px solid var(--line-on-dark);
    }

    .opening-row strong {
      font-size: 1.25rem;
    }

    .opening-row span,
    .opening-row time {
      color: var(--muted-on-dark);
    }

    .opening-status {
      color: var(--brand-razeen) !important;
      font-weight: 700;
    }

    .opening-announcement {
      display: grid;
      grid-template-columns: auto minmax(220px, 1fr) auto minmax(220px, .8fr);
      align-items: center;
      gap: 22px;
      padding: 22px 26px;
      margin-top: 28px;
      background: var(--brand-black);
      color: white;
    }

    .opening-announcement-icon {
      width: 52px;
      height: 52px;
      display: grid;
      place-items: center;
      background: var(--brand-sweihan);
      color: var(--brand-black);
      font-size: 1.45rem;
    }

    .opening-announcement .kicker,
    .opening-announcement time,
    .opening-announcement > span:last-child {
      color: var(--muted-on-dark);
    }

    .opening-announcement h3 {
      margin: 3px 0 0;
      font-size: 1.25rem;
    }

    @media (min-width: 981px) {
      .hero-sectors {
        overflow: hidden;
      }

      .hero-sectors .wrap {
        max-width: none;
        padding-inline: 0;
      }

      .hero-sectors-head {
        max-width: var(--max);
        margin-inline: auto;
        padding-inline: clamp(28px, 5vw, 72px);
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 18px;
      }

      .sector-motion-toggle {
        min-width: 44px;
        min-height: 44px;
        display: inline-grid;
        place-items: center;
        background: transparent;
        color: var(--muted-on-dark);
        border: 0;
        cursor: pointer;
      }

      .sector-grid {
        display: flex;
        width: max-content;
        grid-template-columns: none;
        animation: sectors-marquee 38s linear infinite;
      }

      .sector-grid:hover,
      .sector-grid:focus-within,
      .sector-grid.is-paused {
        animation-play-state: paused;
      }

      .sector-card {
        flex: 0 0 clamp(240px, 20vw, 340px);
      }

      .sector-card-panel {
        display: grid;
        inset: 0;
        margin: 0;
        grid-template-columns: 1fr;
        background: rgba(var(--image-overlay-rgb), .88);
        color: white;
        transform: translateY(12px);
        z-index: 8;
      }

      .sector-card-panel-visual {
        position: absolute;
        inset: 0;
        min-height: 0;
        opacity: .18;
      }

      .sector-card-panel-copy {
        position: relative;
        z-index: 1;
        text-align: start;
        padding: 28px;
      }

      .sector-card-panel-copy h3,
      .sector-card-panel-copy p {
        color: white;
      }

      .sector-card-panel-link {
        color: var(--brand-razeen);
      }

      @keyframes sectors-marquee {
        from { transform: translateX(0); }
        to { transform: translateX(50%); }
      }

      @media (prefers-reduced-motion: reduce) {
        .sector-grid {
          animation: none;
        }
      }
    }

    @media (max-width: 980px) {
      .value-head {
        grid-template-columns: 1fr;
        align-items: start;
      }

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

      .openings-panel {
        grid-template-columns: 1fr;
      }

      .opening-announcement {
        grid-template-columns: auto 1fr;
      }

      .opening-announcement time,
      .opening-announcement > span:last-child {
        grid-column: 2;
      }
    }

    @media (max-width: 560px) {
      .companies-grid,
      .services-grid {
        grid-template-columns: 1fr;
      }

      .company-card,
      .service-card {
        min-height: 0;
        padding: 24px;
      }

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

      .company-card {
        padding: 18px;
      }

      .company-card p {
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
      }

      .company-card h3 {
        font-size: 1.25rem;
      }

      .service-card {
        display: grid;
        grid-template-columns: 46px minmax(0, 1fr) auto;
        grid-template-areas:
          "num meta action"
          "num title action"
          "num copy action";
        align-items: center;
        gap: 4px 12px;
        min-height: 132px;
      }

      .service-card .service-num {
        grid-area: num;
        margin: 0;
      }

      .service-card .service-meta {
        grid-area: meta;
        margin: 0;
      }

      .service-card h3 {
        grid-area: title;
        font-size: 1.18rem;
        margin: 0;
      }

      .service-card p {
        grid-area: copy;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        font-size: .9rem;
      }

      .service-card a {
        grid-area: action;
        margin: 0;
        padding: 10px;
        font-size: 0;
      }

      .service-card .service-pending {
        grid-area: action;
        margin: 0;
        padding: 8px;
        max-width: 78px;
        font-size: .72rem;
      }

      .service-card a i {
        font-size: 1.25rem;
      }

      .company-card .company-num,
      .service-card .service-num {
        margin-bottom: 24px;
      }

      .opening-row {
        grid-template-columns: 1fr;
        gap: 8px;
      }
    }

    .partner-logo.schneider,
    .partner-logo.abb,
    .partner-logo.honeywell {
      color: var(--brand-black);
    }

    .investment-rail {
      max-width: var(--max);
      margin: 0 auto;
      padding: 0 clamp(28px, 5vw, 72px) 28px;
    }

    .investment-rail .sector-card {
      min-height: 150px;
      display: grid;
      grid-template-columns: auto minmax(0, 1fr) auto;
      align-items: center;
      gap: 24px;
      background: var(--brand-black);
      color: white;
      padding: 28px;
    }

    .investment-rail .sector-card-media,
    .investment-rail .sector-card-panel {
      display: none;
    }

    .investment-rail .sector-card-body {
      display: contents;
    }

    .investment-rail .sector-card-title,
    .investment-rail .sector-card-sub {
      color: white;
    }

    .investment-rail .sector-card-action {
      color: var(--brand-razeen);
    }

    @media (max-width: 980px) {
      .investment-rail {
        padding-inline: var(--page-gutter, 16px);
      }

      .investment-rail .sector-card {
        grid-template-columns: 1fr;
        gap: 8px;
      }
    }
    /* ===== Hero / sector integration, visual QA pass =====
       The sectors are intentionally part of the hero on wide screens. The
       former marquee was visually busy, made the sector order unstable and
       hid the interaction. A fixed high-contrast grid now uses the original
       card-overlay pattern: the detail panel is revealed on hover and focus. */
    .hero {
      isolation: isolate;
      min-height: max(760px, 100svh);
      padding-bottom: clamp(236px, 23vw, 320px);
    }

    .hero::after {
      z-index: 0;
      background: linear-gradient(180deg,
        rgba(0, 0, 0, .48) 0%,
        rgba(0, 0, 0, .17) 24%,
        rgba(0, 0, 0, .30) 55%,
        rgba(0, 0, 0, .80) 100%);
    }

    .hero-content,
    .scroll-hint,
    .hero-sectors { z-index: 2; }

    .hero-content {
      min-height: max(560px, 100svh - clamp(236px, 23vw, 320px));
      padding-block: 120px 38px;
    }

    .hero-content::after { display: none; }

    .hero-content-row { gap: 18px; }


    .hero h1 .em {
      display: inline-flex;
      align-items: center;
      vertical-align: middle;
      line-height: 1;
      padding: .13em .18em .17em;
      margin-inline: .07em;
      transform: translateY(-.015em);
    }

    .hero-slides-ind .hero-slide-line {
      isolation: isolate;
    }

    .hero-slides-ind .hero-slide-line.active::before {
      animation: heroProgress var(--hero-slide-duration, 5.2s) linear both;
      transition: none;
    }

    @keyframes heroProgress {
      from { inline-size: 0; }
      to { inline-size: 100%; }
    }

    .hero-sectors {
      position: absolute;
      inset-inline: 0;
      inset-block-end: 0;
      width: 100%;
      padding: 0;
      background: linear-gradient(180deg, rgba(0,0,0,0), rgba(0,0,0,.78) 30%, rgba(0,0,0,.93));
    }

    .hero-sectors .wrap { max-width: none; padding-inline: 0; }

    .hero-sectors-head {
      width: min(100%, var(--max));
      min-height: 42px;
      margin-inline: auto;
      padding-inline: clamp(24px, 5vw, 80px);
      display: flex;
      align-items: end;
    }

    .hero-sectors-label {
      margin: 0 0 9px;
      color: #fff;
      font-size: .9rem;
      letter-spacing: 0;
    }

    .sector-grid {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      width: 100%;
      gap: 1px;
      overflow: visible;
      background: rgba(255,255,255,.22);
      animation: none !important;
      transform: none !important;
    }

    .sector-card,
    .sector-card.is-marquee-clone {
      display: block;
      min-width: 0;
      min-height: clamp(184px, 17vw, 238px);
      margin: 0;
      outline: none;
    }

    .sector-card.is-marquee-clone { display: none; }

    .sector-card-body {
      z-index: 3;
      padding: clamp(18px, 2.1vw, 30px);
      background: linear-gradient(180deg, rgba(0,0,0,.12), rgba(0,0,0,.78));
    }

    .sector-card-title,
    .sector-card-sub { color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.66); }
    .sector-card-mark { background: rgba(0,0,0,.64); color: #fff; }
    .sector-card-action { min-height: 44px; color: #fff; }

    .sector-card-panel {
      display: grid;
      grid-template-columns: 1fr;
      inset: 0;
      margin: 0;
      z-index: 6;
      opacity: 0;
      pointer-events: none;
      transform: translateY(8px);
      background: rgba(0, 0, 0, .92);
      transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .sector-card:hover .sector-card-panel,
    .sector-card:focus .sector-card-panel,
    .sector-card:focus-within .sector-card-panel {
      opacity: 1;
      transform: none;
      pointer-events: auto;
    }

    .sector-card-panel-visual { opacity: .16; }
    .sector-card-panel-copy { padding: clamp(18px, 2.1vw, 30px); }
    .sector-card-panel-copy h3,
    .sector-card-panel-copy p { color: #fff; }
    .sector-card-panel-link { min-height: 44px; color: var(--brand-razeen); }

    .investment-rail {
      display: none;
    }

    .sector-card:focus-visible { outline: 3px solid var(--brand-razeen); outline-offset: -3px; }

    @media (max-width: 980px) {
      .hero {
        height: auto;
        min-height: auto;
        overflow: visible;
        padding-bottom: 0;
      }
      .hero-content { min-height: 100svh; }
      .hero-sectors { position: relative; background: var(--surface-inverse); }
      .hero-sectors-head { padding-inline: var(--page-gutter); align-items: center; }
      .sector-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .sector-card { min-height: clamp(190px, 46vw, 242px); }
    }

    @media (max-width: 560px) {
      .hero-content { padding-block: 96px 54px; }
      .hero h1 .em { padding: .14em .16em .18em; margin-inline: .04em; }
      .hero-sectors-head { min-height: 44px; }
      .sector-grid { gap: 1px; }
      .sector-card { min-height: 196px; }
      .sector-card-body,
      .sector-card-panel-copy { padding: 15px; }
      .sector-card-title { font-size: 1rem; }
      .sector-card-sub { font-size: .78rem; line-height: 1.45; }
      .sector-card-mark { inline-size: 38px; block-size: 38px; }
      .sector-card:last-child:nth-child(odd) { grid-column: auto; }
    }

    @media (prefers-reduced-motion: reduce) {
      .hero-slides-ind .hero-slide-line.active::before { animation: none; inline-size: 100%; }
    }

    /* ===== About / evidence / methodology refinement ===== */
    .about-copy {
      display: block;
      max-width: 62ch;
      padding: 0;
    }

    .about-copy p,
    .about-copy p:first-child,
    .about-copy p:nth-child(3) {
      display: block;
      margin: 0;
      padding: 0;
      border: 0;
      color: var(--ink);
      font-family: inherit;
      font-size: clamp(1.08rem, 1.3vw, 1.3rem);
      font-weight: 400;
      line-height: 1.9;
    }

    .about-pillars {
      border-block: 0;
    }

    .about-badge > i.ph {
      display: none;
    }

    .about-badge::before {
      content: "";
      position: absolute;
      inset-block-start: 18px;
      inset-inline-end: 18px;
      inline-size: clamp(96px, 10vw, 148px);
      aspect-ratio: 1;
      background: url("../images/brand/sdeira-mark.png") center / contain no-repeat;
      opacity: .16;
      transform: rotate(-10deg);
      pointer-events: none;
    }

    .process-head .process-kicker,
    .process-head h2,
    .process-head p {
      display: block;
      margin-inline: 0;
      padding: 0;
      border: 0;
    }

    .process-head h2 { margin-bottom: 18px; }

    .impact-card-unverified { display: none; }

    .impact-footer { display: none; }

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

    @media (max-width: 640px) {
      .impact-grid { grid-template-columns: 1fr; }
    }

    /* Governmental process register: a single, readable sequence instead of a
       bento composition. Every stage uses the same restrained surface. */
    .process-flow {
      display: flex;
      flex-direction: column;
      gap: 0;
      background: var(--surface-base);
      overflow: visible;
    }

    .process-step {
      display: flex;
      gap: clamp(16px, 3vw, 42px);
      align-items: center;
      min-height: 128px;
      padding: 24px clamp(22px, 4vw, 52px);
      background: var(--surface-raised);
      color: var(--ink);
      text-align: right;
      border: 0;
      border-block-end: 1px solid var(--surface-sunken-strong);
    }

    .process-step:last-child { border-block-end: 0; }
    .process-step:hover { background: var(--surface-raised); }
    .process-step .process-num { flex: 0 0 84px; font-size: clamp(2.1rem, 4vw, 3.5rem); color: var(--brand-razeen); opacity: .78; }
    .process-step .process-icon { flex: 0 0 48px; width: 48px; height: 48px; margin: 0; background: var(--icon-wash); color: var(--brand-black); }
    .process-step h3 { flex: 0 1 240px; margin: 0; font-size: clamp(1.25rem, 1.8vw, 1.55rem); }
    .process-step p { flex: 1 1 360px; max-width: 48ch; margin: 0; color: var(--muted); font-size: 1rem; line-height: 1.75; }

    .projects-footer {
      background: var(--brand-black);
    }

    .projects-footer h3 { color: var(--brand-white); }
    .projects-footer p { color: var(--muted-on-dark); }
    .projects-footer-mark { color: var(--brand-razeen); }

    /* .projects-head's own margin-bottom (54px / 34px on tablet, set where
       .projects-head is defined) was tuned for a plain paragraph ending in
       flowing text. With the filter pills now the last element in that
       head, the same margin plus the pill row's own line-height read as an
       oversized empty band before the cards - a pill row carries far less
       visual weight per pixel than text, so it needs less breathing room
       after it, not the same amount. Tightened only for this section. */
    .projects-head:has(.project-filters) {
      margin-bottom: 28px;
    }

    /* Same pill filter language as .news-filters - accent-coloured active
       state, one border/radius/duration token set, reused rather than
       inventing a second filter style. No margin-top here: .projects-head
       is itself a grid with its own `gap` between .projects-copy and this
       row, so an extra margin-top double-stacked with that gap, reading as
       a too-large empty band above the pills. */
    .project-filters {
      display: inline-flex;
      flex-wrap: wrap;
      gap: 4px;
      width: fit-content;
      padding: 4px;
      border: 0;
      border-radius: var(--r);
      background: var(--surface-raised);
    }

    .project-filter {
      border: 0;
      background: var(--surface-raised);
      color: var(--brand-jais);
      padding: 10px 22px;
      border-radius: var(--r);
      font-size: .92rem;
      font-weight: 700;
      cursor: pointer;
      transition: background-color var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .project-filter:hover {
      background: var(--surface-raised);
      color: var(--brand-black);
    }

    .project-filter.is-active {
      background: var(--accent);
      color: var(--brand-white);
    }

    .project-filter:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

    .project-card.is-filtered-out {
      display: none;
    }

    /* Projects read as an editorial sequence, not a repeated card grid: one
       lead community, a photographic interlude, then two equal records. */
    .featured-projects .project-cards {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: clamp(16px, 2vw, 28px);
      background: transparent;
      overflow: visible;
      border-radius: var(--r);
    }

    /* height:auto overrides the generic .project-card { height: 100% } from
       the "REVIEW PASS" rules earlier in the cascade. That 100% was resolving
       against the outer grid's default row stretch, which fed all the way
       down through this card's own auto body row and into the flex-grow:1
       paragraph -- padding a two-line description out to four line-heights
       of empty space. Auto lets each card size to its own real content. */
    .featured-projects .project-card {
      height: auto;
      min-height: 0;
      grid-template-rows: clamp(230px, 25vw, 350px) auto;
      background: var(--surface-base);
    }

    /* The system already answers "how much space between a card's title,
       description, meta row and action link": .news-item-body in
       sdeira-subpage.css (the same stack, on the canonical .project-card-base
       component) uses flex gap: 10px, not per-child margins. This card never
       picked that up - .project-type/h3 carry their own margin-bottom and
       .project-card-action its own margin-top, and nothing at all sits
       between the description and the meta row, which is why the meta row
       read as glued to the paragraph above it. Adopting the same 10px gap
       here and dropping the now-redundant margins so they cannot compound
       with it. Site owner flagged, 12 Aug 2026. */
    .featured-projects .project-card-body {
      gap: 10px;
    }
    .featured-projects :is(.project-type, .project-card h3) {
      margin-bottom: 0;
    }
    .featured-projects .project-card-action {
      margin-top: 0;
    }

    .project-card--feature {
      grid-column: 1 / -1;
      position: relative;
      min-height: clamp(460px, 52vw, 650px) !important;
      overflow: hidden;
      background: var(--brand-black) !important;
    }

    .project-card--feature .project-card-img {
      position: absolute;
      inset: 0;
      height: auto;
    }

    .project-card--feature .project-card-img::after {
      content: "";
      position: absolute;
      inset: 0;
      /* In RTL the copy sits at the right reading edge, so the strongest
         contrast begins there and releases toward the image on the left. */
      background: linear-gradient(270deg, rgba(var(--image-overlay-rgb), .74), rgba(var(--image-overlay-rgb), .20) 68%, rgba(var(--image-overlay-rgb), .48));
      pointer-events: none;
    }

    .project-card--feature .project-card-img img,
    .project-card--feature:hover .project-card-img img {
      object-position: center 54%;
      transform: none;
    }

    .project-card--feature .project-card-body {
      position: absolute;
      z-index: 2;
      inset: auto clamp(24px, 5vw, 72px) clamp(28px, 5vw, 70px);
      max-width: min(620px, 62%);
      min-height: 0;
      padding: 0;
      background: transparent;
      color: var(--brand-white);
    }

    .project-card--feature :is(.project-type, h3, p, .project-meta) { color: var(--brand-white); }
    .project-card--feature h3 { font-size: clamp(2.1rem, 4.3vw, 4.4rem); line-height: 1.04; }
    .project-card--feature p { max-width: 52ch; }
    .project-card--feature .project-meta { margin-top: 24px; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, .46); }
    /* Per-project action, reusing the .action-link underline-grow motion. The
       destination (map vs. an internal project page) isn't decided yet, so
       this ships as a visible but inert placeholder rather than a link to
       nowhere.
       .project-card-body picks up display:flex/flex-direction:column further
       down the cascade (the "REVIEW PASS" rule), which stretches every direct
       child full width by default -- including this one, which is why the
       underline was running the full card width instead of hugging the text.
       align-self + width:fit-content opt this element back out of the stretch. */
    .project-card-action {
      margin-top: 18px;
      font-size: .88rem;
      align-self: flex-start;
      width: fit-content;
      transition: color var(--dur-fast) var(--ease-out);
    }

    .project-card-action i.ph {
      color: currentColor;
      font-size: .95rem;
    }

    /* A project card has one real action. Hovering anywhere on its surface
       activates that action so the card and its CTA read as one target. */
    .project-card:is(:hover, :focus-within) .project-card-action::after,
    .news-card:is(:hover, :focus-within) .more::after {
      transform: scaleX(1);
    }

    .project-card.is-clickable { cursor: pointer; }

    /* Supporting project cards remain a distinct group below the lead project. */
    .featured-projects .project-card--secondary {
      border: 0;
      margin-top: 0;
      /* This track must equal the media's minimum height below. A 350px track
         with a 370px image let the image overflow 20px into the white body,
         so the correctly clipped ribbon still appeared outside the visible
         photograph. */
      grid-template-rows: clamp(240px, 27vw, 370px) auto;
      /* The whole card is the target, not just the small "ØªÙØ§ØµÙŠÙ„ Ø§Ù„Ù…Ø´Ø±ÙˆØ¹"
         label -- same undecided destination as that link (see .is-pending
         above), so this is affordance only for now, no navigation wired. */
      cursor: pointer;
    }
    .project-card--secondary .project-card-img { min-height: clamp(240px, 27vw, 370px); }
    /* Same family of runaway-height bug the comment above .featured-projects
       .project-card already fixed once, recurring one level deeper. That fix
       only reset the CARD's own height:100%; .project-card-body still
       inherits min-height:100% from the generic rule, and .project-card p
       still inherits flex:1 1 auto from it too. Measured effect: with
       min-height:100% in place the body/paragraph pair renders a two-line
       description at ~450px tall regardless of text-wrap:balance (isolated
       both factors independently - removing balance alone left the height
       unchanged; removing min-height alone fixed it), pushing the
       location/date row and the CTA link far past the visible card, where
       they read as missing. min-height: 0 removes the inherited percentage
       and the inflation stops; verified at 390 / 1600 / 1920. */
    .project-card--secondary .project-card-body {
      min-height: 0;
      background: var(--surface-raised);
      transition: background-color var(--dur-base) var(--ease-out);
    }

    /* Tone-step feedback for the now whole-card-clickable secondary cards,
       same vocabulary as every other hover state in the system: one step
       darker, no new colour. */
    .project-card--secondary:hover .project-card-body {
      background: var(--surface-raised);
    }

    .project-card--secondary .project-card-action {
      color: var(--brand-black);
      font-weight: 700;
    }

    /* Two ragged lines (one long, one short trailing word) read as an
       accident. Balancing keeps every description's line lengths even. */
    .featured-projects .project-card p {
      text-wrap: balance;
    }

    @media (max-width: 760px) {
      .featured-projects .project-cards { grid-template-columns: 1fr; gap: 28px; }
      .project-card--feature { min-height: 560px !important; }
      .project-card--feature .project-card-body { max-width: none; inset-inline: 22px; bottom: 28px; }
      .project-card--feature h3 { font-size: clamp(2rem, 10vw, 3rem); }
      .project-card--secondary { border-inline-start: 0; border-block-start: 1px solid var(--surface-sunken-strong); margin-top: 0; }
    }

    @media (max-width: 720px) {
      .process-step {
        flex-wrap: wrap;
        align-items: start;
        gap: 8px 14px;
        min-height: 0;
        padding: 24px 18px;
      }
      .process-step .process-num { flex-basis: 52px; font-size: 2rem; }
      .process-step h3 { flex-basis: calc(100% - 66px); }
      .process-step p { flex-basis: calc(100% - 66px); margin-inline-start: 66px; }
    }

    /* Story: restore the original concise five-column chronology. */
    .story {
      background: linear-gradient(180deg, var(--surface-sunken) 0%, var(--surface-base) 100%);
    }

    .story-timeline {
      position: relative;
      display: grid;
      grid-template-columns: repeat(5, minmax(0, 1fr));
      grid-template-rows: none;
      grid-auto-flow: row;
      grid-auto-columns: auto;
      gap: 0;
      margin: 0;
      padding: 50px 0 0;
      overflow: visible;
      direction: rtl;
      background: transparent;
      scrollbar-width: auto;
    }

    .story-timeline::before {
      content: "";
      position: absolute;
      inset-block-start: 16px;
      inset-inline: 5%;
      inline-size: auto;
      block-size: 2px;
      transform: none;
      background: linear-gradient(90deg, transparent, var(--brand-razeen), transparent);
    }

    .story-item,
    .story-item:nth-child(odd),
    .story-item:nth-child(even) {
      grid-column: auto;
      grid-row: auto;
      display: flex;
      flex-direction: column;
      align-items: stretch;
      width: auto;
      min-width: 0;
      margin: 0;
      padding: 0 18px;
      text-align: center;
      direction: rtl;
      background: transparent;
      border: 0;
      border-inline-start: 1px solid color-mix(in srgb, var(--brand-black) 12%, transparent);
      box-shadow: none;
      transform: none;
    }

    .story-item:first-child { border-inline-start: 0; }

    .story-dot {
      position: absolute;
      inset-block-start: -43px;
      inset-inline-start: 50%;
      inset-inline-end: auto;
      transform: translateX(-50%);
    }

    .story-year {
      min-height: 3.5em;
      margin: 0 0 24px;
      color: var(--brand-sweihan);
    }

    .story-item > p { min-height: 96px; }

    .story-image {
      margin-top: 28px;
      aspect-ratio: 4 / 3;
    }

    .story-achievement {
      margin-top: 22px;
      padding-top: 18px;
    }


    .why-footer a.btn.btn-primary:hover {
      background: var(--brand-sweihan);
      color: var(--brand-black);
    }

    @media (max-width: 900px) {
      .story-timeline {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 34px 0;
        padding-top: 0;
      }

      .story-timeline::before,
      .story-dot { display: none; }

      .story-item,
      .story-item:nth-child(odd),
      .story-item:nth-child(even) {
        padding: 0 14px;
        border-inline-start: 0;
      }

      .story-item > p { min-height: 0; }
    }

    @media (max-width: 560px) {
      .story-timeline { grid-template-columns: 1fr; gap: 30px; }
      .story-item, .story-item:nth-child(odd), .story-item:nth-child(even) { padding: 0; }
    }

    /* Subsidiaries and services: distinct editorial lists, not joined card grids. */
    .value-head {
      display: block;
      max-width: 760px;
      margin-bottom: clamp(28px, 4vw, 44px);
    }

    .value-head h2 { max-width: 14ch; }
    .value-head p {
      max-width: 58ch;
      margin: 16px 0 0;
      font-size: 1.04rem;
    }

    .companies-grid {
      display: flex;
      flex-wrap: wrap;
      gap: 16px;
      background: transparent;
    }

    .company-card {
      flex: 1 1 230px;
      min-height: 270px;
      padding: clamp(26px, 3vw, 38px);
      background: var(--surface-base);
      border-block: 1px solid var(--surface-sunken-strong);
      border-inline-start: 0;
      box-shadow: none;
    }

    .company-card::before {
      inset-inline-start: auto;
      inset-inline-end: 0;
      width: 4px;
    }

    .company-card .company-num {
      margin-bottom: 34px;
      color: var(--brand-jais);
      font-weight: 700;
    }

    .company-card a {
      color: var(--brand-black);
      margin-top: 18px;
    }

    .services-grid {
      display: flex;
      flex-direction: column;
      gap: 14px;
      background: transparent;
    }

    .service-card {
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: clamp(18px, 3vw, 42px);
      min-height: 0;
      padding: 24px clamp(24px, 4vw, 48px);
      background: var(--surface-base);
      border-inline: 0;
      border-block: 1px solid var(--surface-sunken-strong);
    }

    .service-card .service-num {
      flex: 0 0 42px;
      margin: 0;
      color: var(--brand-jais);
      font-weight: 700;
    }

    .service-card .service-meta {
      flex: 0 1 190px;
      margin: 0;
      color: var(--brand-jais);
    }

    .service-card h3 {
      flex: 0 1 280px;
      margin: 0;
      font-size: clamp(1.2rem, 2vw, 1.55rem);
    }

    .service-card p {
      flex: 1 1 340px;
      margin: 0;
      max-width: 42ch;
    }

    .service-card a,
    .service-pending {
      flex: 0 0 auto;
      margin: 0;
      padding: 0;
      color: var(--brand-black);
      white-space: nowrap;
    }

    .openings-block { margin-top: clamp(54px, 7vw, 96px); }
    .openings-block .value-head h2 { max-width: none; }
    .openings-panel { border-block: 1px solid var(--surface-sunken-strong); }
    .openings-intro { background: var(--surface-raised); }
    .opening-row { grid-template-columns: 1.2fr 1fr auto; }
    .opening-row .opening-status { grid-column: 2 / -1; color: var(--brand-razeen) !important; }

    /* Partner introduction: a restrained reading measure instead of one long line. */
    .partners-head p {
      max-width: 62ch;
      margin: 16px auto 0;
      text-wrap: balance;
    }

    /* News: the latest item runs full-width as a horizontal feature, the two
       older ones share a row underneath - same "one lead, two secondary"
       rhythm as the projects section. auto-fit with a real minimum (not a
       fixed max-width:680px breakpoint) so the two secondary cards drop to
       one per row as soon as a column would get too narrow to hold a title
       without breaking mid-word - that happened at tablet widths the old
       single breakpoint never covered, only phone widths below 680px. */
    .news-grid {
      --news-media-height: clamp(260px, 26vw, 380px);
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr));
      gap: 18px;
      background: transparent;
    }

    /* Pill tab row above the grid, filtering the real cards by the two
       categories that actually exist (see the markup comment above
       .news-filters). Same radius/duration tokens as the rest of the
       site, accent-coloured active state instead of a new colour. */
    .news-filters {
      display: inline-flex;
      flex-wrap: wrap;
      gap: 4px;
      width: fit-content;
      padding: 4px;
      margin: 28px 0 36px;
      border: 0;
      border-radius: var(--r);
      background: var(--surface-raised);
    }

    .news-filter {
      border: 0;
      background: var(--surface-raised);
      color: var(--brand-jais);
      padding: 10px 22px;
      border-radius: var(--r);
      font-size: .92rem;
      font-weight: 700;
      cursor: pointer;
      transition: background-color var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .news-filter:hover {
      background: var(--surface-raised);
      color: var(--brand-black);
    }

    .news-filter.is-active {
      background: var(--accent);
      color: var(--brand-white);
    }

    .news-filter:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 2px;
    }

    /* Same failure as .project-card.is-filtered-out above, different cause:
       .news-grid.is-filtered-view .news-card--feature (10663, three classes)
       sets display: block to strip the feature card's grid layout for a
       narrowed result, and that is MORE specific than this two-class rule, so
       when the lead news card itself is the one filtered out, its own
       demotion-to-block-layout rule outranks its own hidden state and it kept
       rendering. The demotion block already reaches for !important twice for
       the same "this state must win" reason (10692, 10694); matching that
       local convention rather than chasing specificity with more classes. */
    .news-card.is-filtered-out {
      display: none !important;
    }

    /* News copy always sits on a clean white surface, independent of the
       photo above or beside it. */
    .news-card {
      background: var(--surface-raised);
      border: 0;
      border-radius: var(--r);
      cursor: pointer;
      transition: background-color var(--dur-base) var(--ease-out);
    }

    .news-card:hover,
    .news-card:focus-within {
      background: var(--surface-raised);
    }

    .news-card--feature {
      grid-column: 1 / -1;
      display: grid;
      grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
      align-items: stretch;
    }

    .news-card--feature .news-image-link {
      height: 100%;
    }

    .news-card--feature .img {
      block-size: 100%;
      min-height: clamp(260px, 26vw, 380px);
    }

    .news-card--feature .news-body {
      justify-content: center;
    }

    .news-card--feature h3 {
      font-size: clamp(1.35rem, 2vw, 1.85rem);
      -webkit-line-clamp: 3;
    }

    /* Every news image uses the same media height and object-fit:cover,
       regardless of source dimensions or whether it appears in the lead
       card or the two supporting cards. The editorial grid stays unchanged. */
    .news-card .img,
    .news-card--feature .img {
      block-size: var(--news-media-height);
      min-height: 0;
      aspect-ratio: auto;
      background: var(--brand-black);
    }

    .news-card img { object-fit: cover; }
    .news-body { min-height: 0; padding: 22px 24px 20px; }

    /* font-weight above 400 has no visual effect here: only the Regular
       DIN Next LT Arabic file is licensed, and every other weight slot
       (500-800) intentionally points at that same file to block browser-
       synthesized bold, which distorts Arabic letter joins - see the
       @font-face comment in sdeira-tokens.css. The title has to read as a
       title through size and colour instead, not weight, until a licensed
       Bold file exists. */
    /* Reserve the space for the max line count every card is allowed, so a
       one-line title/description doesn't leave the "read more" link
       floating at a different height card to card - that gap was the bug.
       The clamp is also cut down (title 2 lines, description 1) so the
       reserved block stays compact instead of ballooning the card. */
    .news-card h3 {
      min-height: 2.8em;
      margin-top: 14px;
      color: var(--brand-black);
      font-size: clamp(1.2rem, 1.7vw, 1.5rem);
      line-height: 1.4;
      text-wrap: balance;
      -webkit-line-clamp: 2;
    }
    .news-card p {
      min-height: 1.7em;
      margin-top: 10px;
      font-size: .96rem;
      line-height: 1.7;
      -webkit-line-clamp: 1;
    }

    /* Reuse the site's underline-grow action link instead of a plain text
       link, matching the projects and subsidiary-company cards. */
    .news-card .more {
      margin-top: 16px;
      color: var(--brand-black);
      font-weight: 700;
    }

    .news-card .more i.ph {
      color: currentColor;
    }

    @media (max-width: 860px) {
      .news-card--feature {
        grid-template-columns: minmax(0, 1fr);
      }

      .news-card--feature .img {
        min-height: 220px;
      }
    }

    @media (max-width: 680px) {
      /* .news-grid's own auto-fit already collapses to one column here -
         only the feature card's explicit full-span needs resetting since
         there's nothing to span across anymore. */
      .news-card--feature {
        grid-column: auto;
      }
    }

    @media (max-width: 860px) {
      .company-card { flex-basis: calc(50% - 8px); }
      .service-card { flex-wrap: wrap; gap: 10px 18px; }
      .service-card .service-meta { flex-basis: calc(100% - 60px); }
      .service-card h3 { flex-basis: calc(100% - 60px); margin-inline-start: 60px; }
      .service-card p { flex-basis: calc(100% - 60px); margin-inline-start: 60px; }
      .service-card a, .service-pending { margin-inline-start: 60px; }
    }

    @media (max-width: 560px) {
      .company-card { flex-basis: 100%; min-height: 0; }
      .service-card { padding: 22px; }
      .service-card h3, .service-card p, .service-card a, .service-pending { margin-inline-start: 0; flex-basis: 100%; }
      .opening-row { grid-template-columns: 1fr; }
      .opening-row .opening-status { grid-column: auto; }
      .news-grid { --news-media-height: 210px; }
    }

    /* Contact states and newsletter: one clear action in each place. Colour
       stays fixed - the only hover feedback is the diagonal wipe defined
       further down, tinted with the card's own icon colour. */

    .news-subscribe {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: clamp(20px, 5vw, 76px);
      grid-template-columns: none;
      padding: clamp(24px, 3vw, 36px);
    }

    .news-subscribe-copy { display: block; }
    .news-subscribe-copy h3 { margin: 0; }
    .news-subscribe-copy p { max-width: 46ch; margin: 8px 0 0; }
    .news-form { flex: 1 1 380px; max-width: 520px; }
    .news-social { display: none; }

    @media (max-width: 680px) {
      .news-subscribe { align-items: stretch; flex-direction: column; gap: 18px; }
      .news-form { max-width: none; width: 100%; }
    }

    /* The full five-part group model: four operating sectors plus investment. */
    @media (min-width: 981px) {
      .sector-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
    }

    .sector-card,
    .sector-card:hover,
    .sector-card:focus-within {
      transform: none;
      box-shadow: none;
    }

    .sector-card .sector-card-img,
    .sector-card:hover .sector-card-img,
    .sector-card:focus-within .sector-card-img {
      transform: none;
      filter: saturate(.9) brightness(.9);
    }

    .sector-card .sector-card-media::after {
      opacity: 0;
      background: rgba(0, 0, 0, .16);
    }

    .sector-card:hover .sector-card-media::after,
    .sector-card:focus-within .sector-card-media::after { opacity: 1; }

    .sector-card:hover .sector-card-veil,
    .sector-card:focus-within .sector-card-veil { opacity: .86; }

    .sector-card:hover .sector-card-title,
    .sector-card:focus-within .sector-card-title,
    .sector-card:hover .sector-card-sub,
    .sector-card:focus-within .sector-card-sub { color: var(--brand-white); }

    /* ===== GROUP SITE FEATURE =====
       Restores the useful part of the original hero-sector panel: a real
       group-company destination and its website preview. It is now a stable
       feature above the five-sector strip, rather than a transient layer that
       covered a card and disappeared before it could be read. */
    .sector-feature {
      width: min(calc(100% - clamp(32px, 7vw, 112px)), var(--max));
      margin: 0 auto clamp(14px, 2vw, 24px);
      display: grid;
      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
      min-height: clamp(214px, 18vw, 280px);
      background: var(--surface-base);
      color: var(--brand-black);
      overflow: hidden;
    }

    .sector-feature-copy {
      position: relative;
      padding: clamp(28px, 4vw, 54px);
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: center;
      gap: 12px;
    }

    .sector-feature-copy::after {
      content: "";
      position: absolute;
      inset-inline-end: clamp(24px, 4vw, 58px);
      inset-block-end: -34px;
      width: 118px;
      height: 118px;
      background: url("../images/brand/sdeira-mark.png") center / contain no-repeat;
      opacity: .07;
      pointer-events: none;
    }

    .sector-feature-kicker {
      color: var(--brand-liwa);
      font-size: .82rem;
      font-weight: 700;
    }

    .sector-feature h2 {
      margin: 0;
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: clamp(1.65rem, 2.6vw, 2.45rem);
      line-height: 1.15;
    }

    .sector-feature p {
      max-width: 53ch;
      margin: 0;
      color: var(--brand-jais);
      font-size: clamp(.98rem, 1.2vw, 1.1rem);
      line-height: 1.8;
    }

    .sector-feature-link {
      position: relative;
      z-index: 1;
      min-height: 44px;
      margin-top: 5px;
      padding-inline: 17px;
      display: inline-flex;
      align-items: center;
      gap: 9px;
      background: var(--brand-black);
      color: var(--brand-white);
      font-weight: 700;
      transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
    }

    .sector-feature-link:hover,
    .sector-feature-link:focus-visible {
      background: var(--brand-sweihan);
      color: var(--brand-black);
    }

    .sector-feature-link i.ph { font-size: var(--ic-sm); }

    .sector-feature-visual {
      padding: clamp(20px, 3vw, 42px);
      display: grid;
      place-items: center;
      background: var(--surface-sunken);
    }

    .sector-feature-visual img {
      width: min(100%, 520px);
      height: auto;
      display: block;
      object-fit: contain;
    }

    @media (min-width: 981px) {


      /* The feature is the single, readable destination preview. Individual
         card overlays would duplicate it and conflict with the five-card row. */
      .sector-card-panel { display: none; }
    }

    @media (max-width: 980px) {
      .sector-feature {
        width: calc(100% - (var(--page-gutter) * 2));
        grid-template-columns: 1fr;
        margin-block: 14px 18px;
      }

      .sector-feature-copy { order: 2; }
      .sector-feature-visual { order: 1; padding: 18px; }
      .sector-feature-visual img { width: min(100%, 440px); }
    }

    /* Hero copy is a headline, not a narrow poster column. The wider measure
       keeps the message to two composed lines on wide screens. */
    @media (min-width: 981px) {
      .hero-content-row {
        width: min(100%, 1080px);
      }

      .hero-content-copy {
        flex-basis: auto;
        max-width: 960px;
      }

      .hero h1 {
        max-width: 23ch;
        font-size: clamp(2.35rem, min(4.1vw, 6.8svh), 3.95rem);
        line-height: 1.12;
        text-wrap: balance;
      }

      .hero p { max-width: 64ch; }
    }
    /* Final process reset. Earlier exploratory bento rules leave absolute
       numbers and column spans behind; reset every layout property here so the
       five stages always render as one calm institutional sequence. */
    .process-head {
      display: block;
      max-width: 760px;
      margin: 0 0 clamp(30px, 4vw, 46px);
      text-align: right;
    }

    .process-head .process-kicker,
    .process-head h2,
    .process-head p {
      grid-column: auto;
      grid-row: auto;
    }

    .process-head h2 { margin: 0; }
    .process-head p {
      max-width: 58ch;
      margin: 14px 0 0;
      padding: 0;
      border: 0;
    }

    .process-flow {
      display: grid;
      grid-template-columns: 1fr;
      grid-auto-rows: auto;
      gap: 0;
      overflow: visible;
      background: var(--surface-sunken-strong);
    }

    .process-step,
    .process-step:nth-child(n) {
      position: relative;
      display: grid;
      grid-template-columns: 74px 52px minmax(150px, .55fr) minmax(0, 1.45fr);
      grid-column: auto;
      align-items: center;
      min-width: 0;
      min-height: 136px;
      height: auto;
      padding: 24px clamp(22px, 4vw, 52px);
      gap: clamp(14px, 2.5vw, 34px);
      overflow: visible;
      isolation: auto;
      background: var(--surface-raised);
      color: var(--ink);
      text-align: right;
      transition: background var(--dur-base) var(--ease-out);
    }

    .process-step:not(:last-child) { border-block-end: 1px solid var(--surface-sunken-strong); }
    .process-step:hover,
    .process-step:nth-child(n):hover { background: var(--surface-sunken); }

    .process-step .process-num,
    .process-step:nth-child(n) .process-num {
      position: static;
      z-index: auto;
      inset: auto;
      order: initial;
      margin: 0;
      color: var(--brand-sweihan);
      font-size: clamp(1.85rem, 3vw, 2.65rem);
      font-weight: 700;
      line-height: 1;
      opacity: 1;
      transform: none;
    }

    .process-step .process-icon,
    .process-step:nth-child(n) .process-icon {
      position: static;
      z-index: auto;
      order: initial;
      width: 48px;
      height: 48px;
      margin: 0;
      background: var(--icon-wash);
      color: var(--brand-black);
    }

    .process-step h3,
    .process-step p,
    .process-step:nth-child(n) h3,
    .process-step:nth-child(n) p {
      position: static;
      z-index: auto;
      margin: 0;
      color: var(--ink);
    }

    .process-step h3 { font-size: clamp(1.15rem, 1.5vw, 1.4rem); }
    .process-step p { max-width: 54ch; font-size: 1rem; line-height: 1.75; }

    @media (max-width: 720px) {
      .process-step,
      .process-step:nth-child(n) {
        grid-template-columns: 48px 1fr;
        grid-template-areas: "number icon" "number title" "number copy";
        align-items: start;
        min-height: 0;
        padding: 22px 18px;
        gap: 8px 14px;
      }

      .process-step .process-num { grid-area: number; }
      .process-step .process-icon { grid-area: icon; }
      .process-step h3 { grid-area: title; }
      .process-step p { grid-area: copy; }
    }

    /* Keep intentionally retired sections out of the visual and accessibility
       trees even when their component rules declare a display value. */
    [hidden] {
      display: none !important;
    }
    /* ===== Sector interaction repair, 2026-07-26 =====
       The large preview is an overlay above the strip, never another row in
       the document flow. Opening it cannot move the title, cards, or scroll. */
    .sector-feature { display: none !important; }
    .hero-sectors,
    .hero-sectors .wrap { overflow: visible; }
    .hero-sectors-head { position: relative; z-index: 2; background: none; }
    .sector-card-panel { display: none !important; }

    .sector-hover-region {
      position: absolute;
      inset-inline: 0;
      bottom: 100%;
      z-index: 12;
      display: block;
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translateY(12px);
      transition:
        opacity var(--dur-slow) var(--ease-out),
        transform var(--dur-slow) var(--ease-out),
        visibility 0s linear var(--dur-slow);
    }

    .sector-hover-panels {
      width: min(calc(100% - clamp(32px, 7vw, 112px)), var(--max));
      margin-inline: auto;
      display: grid;
      overflow: visible;
    }

    .sector-hover-panel {
      grid-area: 1 / 1;
      display: grid;
      grid-template-columns: minmax(300px, .82fr) minmax(480px, 1.38fr);
      align-items: stretch;
      width: 100%;
      min-height: 0;
      margin-block-end: 18px;
      background: var(--surface-base);
      color: var(--brand-black);
      opacity: 0;
      visibility: hidden;
      pointer-events: none;
      transform: translate3d(0, 18px, 0);
      transition:
        opacity var(--dur-slow) var(--ease-out),
        transform var(--dur-slow) var(--ease-out),
        visibility 0s linear var(--dur-slow);
    }

    .sector-hover-copy {
      padding: clamp(28px, 4vw, 54px);
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: center;
      gap: 12px;
    }

    .sector-hover-copy > span { color: var(--brand-liwa); font-size: .82rem; font-weight: 700; }
    .sector-hover-copy h3 { margin: 0; color: var(--brand-black); font-family: var(--font-display); font-size: clamp(1.7rem, 2.7vw, 2.6rem); line-height: 1.1; }
    .sector-hover-copy p { max-width: 48ch; margin: 0; color: var(--brand-jais); line-height: 1.8; }

    .sector-hover-visual {
      position: relative;
      isolation: isolate;
      aspect-ratio: 16 / 9;
      min-height: 0;
      overflow: hidden;
      background: var(--surface-sunken);
    }

    /* Keyed to data-sector, not :nth-child(): orderSectorElements() reorders
       these panels at runtime, so a position-keyed backdrop can end up on the
       wrong panel. It already had - panels 1 and 2 were serving each other's
       photograph, and the services panel had no entry at all. */
    [data-sector="development"] .sector-hover-visual { --sector-preview-image: url("../images/group-living/development-community.webp"); }
    [data-sector="properties"] .sector-hover-visual { --sector-preview-image: url("../images/group-living/living-community.webp"); }
    [data-sector="management"] .sector-hover-visual { --sector-preview-image: url("../images/group-living/community-operations.webp"); }
    [data-sector="services"] .sector-hover-visual { --sector-preview-image: url("../images/group-living/community-services.webp"); }
    [data-sector="investment"] .sector-hover-visual { --sector-preview-image: url("../images/group-living/community-portfolio.webp"); }

    .sector-hover-visual::before {
      content: "";
      position: absolute;
      z-index: 0;
      inset: -18px;
      background-image: var(--sector-preview-image);
      background-size: cover;
      background-position: center;
      filter: blur(18px) saturate(.78) brightness(.92);
      opacity: .82;
      transform: scale(1.04);
    }

    .sector-hover-visual img {
      position: relative;
      z-index: 1;
      width: 100%;
      height: 100%;
      display: block;
      object-fit: cover;
      object-position: center;
    }

    @media (hover: hover) and (pointer: fine) {
      .hero-sectors:has(.sector-card:nth-child(-n + 5):hover) .sector-hover-region,
      .hero-sectors:has(.sector-card:nth-child(-n + 5):focus-within) .sector-hover-region {
        opacity: 1;
        visibility: visible;
        transform: none;
        transition-delay: 0s;
      }

      .hero-sectors:has(.sector-card:nth-child(1):hover) .sector-hover-panel:nth-child(1),
      .hero-sectors:has(.sector-card:nth-child(1):focus-within) .sector-hover-panel:nth-child(1),
      .hero-sectors:has(.sector-card:nth-child(2):hover) .sector-hover-panel:nth-child(2),
      .hero-sectors:has(.sector-card:nth-child(2):focus-within) .sector-hover-panel:nth-child(2),
      .hero-sectors:has(.sector-card:nth-child(3):hover) .sector-hover-panel:nth-child(3),
      .hero-sectors:has(.sector-card:nth-child(3):focus-within) .sector-hover-panel:nth-child(3),
      .hero-sectors:has(.sector-card:nth-child(4):hover) .sector-hover-panel:nth-child(4),
      .hero-sectors:has(.sector-card:nth-child(4):focus-within) .sector-hover-panel:nth-child(4),
      .hero-sectors:has(.sector-card:nth-child(5):hover) .sector-hover-panel:nth-child(5),
      .hero-sectors:has(.sector-card:nth-child(5):focus-within) .sector-hover-panel:nth-child(5) {
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
        transform: none;
        transition-delay: 90ms, 90ms, 0s;
      }

      .sector-card .sector-card-media::after {
        display: block;
        /* One state for the entire sector family: the photo still reads
           through the warm wash, while the black base keeps white copy clear.

           THE FILL IS THE TOKEN, NOT RAW SWEIHAN. It used to be a literal
           rgba(216, 112, 44) - Sweihan itself - and white copy over the
           finished composite measured 4.04 to 4.44 against the description and
           the action link, under AA for text that size. --surface-brand-deep is
           the value the token file already designates for the diagonal wipe,
           and the same composite measures 6.58 to 7.23 with it. Same one
           sanctioned orange step, no ninth colour. */
        background:
          linear-gradient(180deg,
            color-mix(in srgb, var(--surface-brand-deep) 76%, transparent) 0%,
            color-mix(in srgb, var(--surface-brand-deep) 90%, transparent) 100%),
          linear-gradient(180deg,
            rgba(var(--image-overlay-rgb), .46) 0%,
            rgba(var(--image-overlay-rgb), .62) 100%);
        /* Oversized diagonal layer: its slanted ends sit outside the card, so
           the completed state is a full fill rather than a clipped rectangle. */
        inset: -1px -40%;
        opacity: 1;
        clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
        transform: translate3d(78%, 0, 0);
        transition: transform var(--dur-slow) var(--ease-out);
      }

      .sector-card:hover .sector-card-media::after,
      .sector-card:focus-within .sector-card-media::after {
        transform: none;
      }

      .sector-card:hover .sector-card-veil,
      .sector-card:focus-within .sector-card-veil {
        /* The stable base never drops out; the brand diagonal travels above it. */
        opacity: 1;
      }

      .sector-card:hover .sector-card-img,
      .sector-card:focus-within .sector-card-img {
        transform: none;
        filter: saturate(.9) brightness(.9);
      }

      .sector-card:hover .sector-card-sub,
      .sector-card:focus-within .sector-card-sub {
        opacity: 0;
        visibility: hidden;
      }

      .sector-card:hover .sector-card-title,
      .sector-card:focus-within .sector-card-title,
      .sector-card:hover .sector-card-mark,
      .sector-card:focus-within .sector-card-mark {
        color: var(--brand-white);
      }

      .sector-card:hover .sector-card-body,
      .sector-card:focus-within .sector-card-body {
        background: none;
      }

      .sector-card:hover .sector-card-action,
      .sector-card:focus-within .sector-card-action {
        width: fit-content;
        min-height: 0;
        padding: 0 0 8px;
        background: transparent;
        color: var(--brand-white);
      }
    }

    /* All five sectors now share the same card interaction and the same
       preview-panel choreography; none is treated as a special case. */

    .sector-card-title,
    .sector-card-sub,
    .sector-card-action {
      text-shadow: none !important;
    }

    .sector-card-body {
      height: 100%;
      padding: 20px clamp(16px, 1.7vw, 24px);
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      /* Keep the icon and sector name as one compact heading group. The
         flexible track belongs below the description, so the action remains
         anchored at the card base without creating empty space above the name. */
      grid-template-rows: 42px auto minmax(0, 1fr) auto;
      align-items: end;
      gap: 8px;
    }

    .sector-card-mark {
      grid-row: 1;
      align-self: start;
      margin: 0;
      background: transparent;
      transform: none;
    }

    .sector-card:hover .sector-card-mark,
    .sector-card:focus-within .sector-card-mark {
      background: transparent;
      transform: none;
    }

    .sector-card-title {
      grid-row: 2;
      grid-column: 1;
      align-self: end;
    }

    .sector-card-sub,
    .sector-card-action {
      grid-column: 1;
      align-self: start;
      margin: 0;
      transition:
        opacity var(--dur-base) var(--ease-out),
        visibility var(--dur-base) var(--ease-out);
    }

    .sector-card-sub {
      grid-row: 3;
    }

    .sector-card-action {
      grid-row: 4;
      position: static;
      inset: auto;
      inline-size: fit-content;
      min-height: 0;
      pointer-events: none;
      transform: none;
    }

    .sector-card:hover .sector-card-action,
    .sector-card:focus-within .sector-card-action {
      pointer-events: auto;
      transform: none;
    }

    /* Button hierarchy: .btn is the filled CTA, .btn-ghost is secondary,
       and .action-link is the contextual action placed over imagery. */
    .action-link,
    .sector-card-action,
    .section-view-all {
      position: relative;
      z-index: 0;
      display: inline-flex;
      align-items: center;
      gap: 8px;
      min-height: 0;
      padding: 0 0 8px;
      overflow: visible;
      isolation: auto;
      background: transparent;
      color: var(--brand-white);
      font-weight: 800;
      line-height: 1.3;
      transition:
        opacity var(--dur-base) var(--ease-out),
        visibility var(--dur-base) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .action-link::before,
    .sector-card-action::before {
      content: none;
    }

    .action-link::after,
    .sector-card-action::after,
    .section-view-all::after {
      content: "";
      position: absolute;
      inset-inline-start: 0;
      inset-block-end: 0;
      inline-size: 100%;
      block-size: 3px;
      background: currentColor;
      transform: scaleX(.42);
      transform-origin: right center;
      transition: transform 300ms var(--ease-out);
    }

    .action-link:is(:hover, :focus-visible)::after,
    .sector-card:hover .sector-card-action::after,
    .sector-card:focus-within .sector-card-action::after,
    .needs-route:is(:hover, :focus-visible) .needs-route-action::after,
    .section-view-all:is(:hover, :focus-visible)::after {
      transform: scaleX(1);
    }

    .sector-card-action i.ph { color: currentColor; }

    /* The visible action label explains the destination, while the whole
       coloured sector surface remains the same generous pointer target. */
    .sector-card { cursor: pointer; }

    @media (max-width: 980px) {
      .sector-grid > .sector-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
    }

    @media (max-width: 680px) {
      .sector-hover-region { display: none; }
      .hero-sectors-head { background: none; }
    }

    @media (prefers-reduced-motion: reduce) {
      .sector-card-media::after,
      .sector-card-sub,
      .sector-card-action,
      .sector-hover-region,
      .sector-hover-panel {
        transition: none;
      }
    }

    /* The About photograph stays intact. These parallel surface-colour bands
       sit above it and create the same rising direction as the logomark without
       cropping or editing the source image. */
    .about-visual > img {
      position: relative;
      z-index: 0;
      display: block;
    }

    /* A calendar is a clearer cue for a dated beginning than the previous
       certification seal. The strokes stay tonal so they read as part of the
       badge surface rather than a second multi-colour logo. */
    .about-badge {
      z-index: 2;
    }

    .about-badge::before { content: none; }
    .about-badge > i.ph {
      position: absolute;
      z-index: 1;
      inset-block-start: 24px;
      inset-inline-end: 24px;
      color: var(--brand-white);
      font-size: 1.7rem;
      opacity: .9;
    }

    .about-badge > div { position: relative; z-index: 1; }

    /* Alternate impact composition kept beside the original for comparison.
       It follows the supplied editorial reference: copy on the RTL reading
       edge, an angled multi-image composition, then one continuous metric rail. */
    .impact-alt {
      padding: clamp(72px, 7vw, 108px) 0;
      background: var(--surface-base);
    }

    .impact-alt-intro {
      display: grid;
      grid-template-columns: minmax(300px, .72fr) minmax(520px, 1.28fr);
      gap: clamp(44px, 6vw, 92px);
      align-items: center;
    }

    .impact-alt-copy {
      text-align: right;
    }

    .impact-alt-copy .impact-kicker {
      margin-bottom: 18px;
    }

    .impact-alt-copy h2 {
      max-width: 13ch;
      margin: 0 0 22px;
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: clamp(2.5rem, 4.7vw, 5rem);
      line-height: 1.05;
    }

    .impact-alt-copy p {
      max-width: 52ch;
      margin: 0;
      color: var(--brand-jais);
      font-size: clamp(1rem, 1.2vw, 1.16rem);
      line-height: 1.9;
    }

    /* Same .section-view-all action the projects and news sections use, so the
       three read as one kind of section-level link rather than three buttons.
       Only two things differ here, both because it sits in a text column
       instead of a filter bar: it needs its own space under the paragraph, and
       the 4px of inline padding that keeps it clear of a filter tab has to be
       pulled back so its text starts on the same line as the h2 above it.

       The pull is on the START side. It was written as margin-inline-end at
       first, which in RTL resolves to margin-left and moves the edge the text
       does not start from: measured, the label sat at 1317 against the h2's
       1321 and the element box only looked aligned because a bounding rect
       includes the padding. */
    .impact-alt-action {
      margin-top: 26px;
      margin-inline-start: -4px;
    }

    .impact-alt-collage {
      direction: ltr;
      display: grid;
      grid-template-columns: 1.08fr 1fr;
      grid-template-rows: repeat(3, minmax(128px, 1fr));
      gap: 8px;
      height: clamp(470px, 43vw, 620px);
      /* The top and bottom breathing room holds the deliberate image offsets
         inside the composition, instead of letting the collage spill outside
         the section. */
      padding-block: 22px;
      overflow: hidden;
      background: var(--surface-base);
    }

    .impact-alt-collage figure {
      position: relative;
      margin: 0;
      overflow: hidden;
      background: var(--surface-sunken-strong);
    }

    .impact-alt-collage figure:first-child {
      grid-row: 1 / -1;
      clip-path: polygon(0 0, 100% 0, 86% 100%, 0 100%);
    }

    .impact-alt-collage figure:not(:first-child) {
      margin-left: -12%;
      clip-path: polygon(4.881% 0, 100% 0, 95.119% 100%, 0 100%);
    }

    .impact-alt-collage img {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: cover;
      filter: saturate(.9) contrast(1.03);
    }

    .impact-alt-collage figure:nth-child(2) img { object-position: center 58%; }
    .impact-alt-collage figure:nth-child(3) img { object-position: center 45%; }
    .impact-alt-collage figure:nth-child(4) img { object-position: center 55%; }

    /* Below 981px the grid stays 2 columns x 3 rows (no min-width override
       fires), so the supporting trio is a STACKED column, not a horizontal
       row. The desktop clip-path + margin-left:-12% on those figures exists
       to overlap them into one diagonal-seamed strip when they sit side by
       side - stacked vertically instead, that same offset shoves each one
       sideways with no neighbour to seam against, so the right edge reads as
       a broken staircase instead of one straight line. Cancelling both here
       restores plain rectangles for the stacked case; the lead image's own
       corner taper (figure:first-child) is unaffected and still reads fine
       against a straight-edged column. */
    @media (max-width: 980px) {
      .impact-alt-collage figure:not(:first-child) {
        margin-left: 0;
        clip-path: none;
      }
    }

    /* The photographs keep their original editorial cuts. The supporting trio
       is shifted as whole images, rather than receiving a different angle for
       every row; this makes one calm, stepped image field beside the lead. */
    @media (min-width: 981px) {
      .impact-alt-collage {
        overflow: hidden;
      }

      .impact-alt-collage figure:not(:first-child) {
        margin-left: 0;
        z-index: 1;
      }

      /* Percentages, not fixed px: both columns are fr-based and scale together
         with viewport width, so a percentage offset (relative to the figure's
         own width) keeps the diagonal seam exact at every width. Fixed px
         offsets only matched the one viewport they were measured at. */
      .impact-alt-collage figure:nth-child(2) {
        transform: translate3d(-5.513%, 0, 0);
      }

      .impact-alt-collage figure:nth-child(3) {
        transform: translate3d(-10.632%, 0, 0);
      }

      .impact-alt-collage figure:nth-child(4) {
        transform: translate3d(-15.751%, 0, 0);
      }
    }

    .impact-alt-stats {
      display: grid;
      grid-template-columns: repeat(4, minmax(0, 1fr));
      margin-top: clamp(36px, 4vw, 58px);
      /* Raised (white) rather than sunken, so the stat text sits on the
         highest-contrast surface the system has: black 10.5:1 and Jais 6.9:1
         on white, against 9.0:1 and 5.9:1 on Sunken. One slab for all four
         cards - the diagonal rules, not a gap, separate them. */
      background: var(--surface-raised);
    }

    .impact-alt-stat {
      position: relative;
      min-width: 0;
      min-height: 212px;
      padding: 30px clamp(18px, 1.9vw, 30px);
      display: grid;
      grid-template-columns: 42px minmax(0, 1fr);
      grid-template-rows: 54px 26px minmax(66px, auto);
      align-content: start;
      align-items: start;
      gap: 6px 14px;
    }

    .impact-alt-stat + .impact-alt-stat::before {
      content: "";
      position: absolute;
      top: 24px;
      bottom: 24px;
      right: 0;
      width: 2px;
      background: var(--brand-sweihan);
      transform: rotate(18deg);
    }

    .impact-alt-stat i.ph {
      grid-column: 1;
      grid-row: 1;
      align-self: center;
      color: var(--brand-sweihan);
      font-size: var(--ic-lg);
    }

    .impact-alt-stat strong {
      grid-column: 2;
      grid-row: 1;
      align-self: center;
      max-inline-size: 100%;
      min-width: 0;
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: clamp(1.45rem, 1.8vw, 2.1rem);
      line-height: 1;
      font-weight: 500;
      font-variant-numeric: tabular-nums;
      white-space: normal;
      overflow-wrap: anywhere;
    }

    .impact-alt-stat span {
      grid-column: 2;
      grid-row: 2;
      color: var(--brand-black);
      font-size: .96rem;
      line-height: 1.35;
      white-space: nowrap;
    }

    .impact-alt-stat p {
      grid-row: 3;
      grid-column: 2;
      margin: 0;
      color: var(--brand-jais);
      font-size: .86rem;
      line-height: 1.6;
      /* RESERVE, DO NOT CLAMP. This reserved 4.8em AND clamped at 3 lines, so
         a fourth line was hidden from the visitor - the one thing the token
         file's card rule rules out, and the same defect recorded against
         .news-card. The reservation stays and is expressed in lh, so it
         follows the line-height instead of restating it; all four figures are
         one grid row, so a longer sentence grows the row evenly rather than
         leaving one column short. */
      min-block-size: calc(3 * 1lh);
    }

    @media (max-width: 1180px) {
      .impact-alt-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .impact-alt-stat { min-height: 196px; }
      /* In the two-column layout, only the left card in each RTL row gets
         the diagonal divider. */
      .impact-alt-stat + .impact-alt-stat::before { content: none; }
      .impact-alt-stat:nth-child(even)::before {
        content: "";
        position: absolute;
        top: 24px;
        bottom: 24px;
        right: 0;
        width: 2px;
        background: var(--brand-sweihan);
        transform: rotate(18deg);
      }
    }

    @media (max-width: 980px) {
      .impact-alt-intro { grid-template-columns: 1fr; }
      .impact-alt-collage { grid-row: 2; }
    }

    @media (max-width: 640px) {
      .impact-alt { padding-block: 64px; }
      .impact-alt-intro { gap: 38px; }
      .impact-alt-copy h2 { font-size: clamp(2.25rem, 12vw, 3rem); }
      .impact-alt-collage { height: min(126vw, 490px); }
      .impact-alt-stats {
        grid-template-columns: 1fr;
        margin-top: 28px;
      }
      .impact-alt-stat {
        min-height: 168px;
        padding: 24px 22px;
        grid-template-rows: 46px 24px minmax(52px, auto);
      }
      .impact-alt-stat:nth-child(even)::before { content: none; }
      .impact-alt-stat strong {
        font-size: clamp(1.45rem, 7vw, 1.8rem);
      }
      .impact-alt-stat p { min-block-size: calc(2 * 1lh); }
    }

    /* The slider was initialized in JavaScript but absent from the document.
       inline-size used to be capped at 360px max - fine on narrow phones
       (where 100% is under 360px anyway) and on desktop (where
       .hero-content-row's own max-width keeps the column narrow), but
       .hero-content-row is column-direction at every width (see the
       "Hero responsive reconstruction" rule above), so at tablet widths the
       column itself is much wider than 360px and the rail shrank to a thin
       stub in the corner instead of spanning the row like the buttons above
       it. Full width at every size instead of a fixed cap. */
    .hero-slides-ind { display: flex; visibility: visible; opacity: 1; order: 2; inline-size: 100%; margin-top: 4px; }

    /* The page-wide wash was visually too light on the brightest mobile slide:
       white hero copy became dependent on the photograph behind it. This is a
       measured black scrim, intentionally lighter at the header and then
       stronger through the reading zone; it protects text without flattening
       the entire image. */
    .hero::after {
      background: linear-gradient(180deg,
        rgba(0, 0, 0, .58) 0%,
        rgba(0, 0, 0, .44) 24%,
        rgba(0, 0, 0, .72) 58%,
        rgba(0, 0, 0, .88) 100%);
    }

    header::before {
      background: linear-gradient(180deg,
        rgba(0, 0, 0, .72) 0%,
        rgba(0, 0, 0, .48) 52%,
        transparent 100%);
    }

    /* Restore the hero's reading zone after an older feature-preview rule
       reserved twice the required strip height. The copy now clears the header
       and stays bottom-aligned above the five-sector strip. */
    @media (min-width: 981px) {
      .hero { padding-bottom: clamp(236px, 23vw, 320px); }
      .hero-content {
        min-height: calc(100svh - clamp(236px, 23vw, 320px));
        padding-block: 120px 38px;
      }
    }

    /* ===== Unified action colour =====
       Primary actions use the same Sweihan surface as the active sector card.
       White, heavier labels give the CTA the required visual authority. */
    :is(.btn-primary, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a) {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
      font-weight: 800;
      box-shadow: none;
    }

    :is(.btn-primary, .btn-ghost, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a, .project-tab) {
      position: relative;
      isolation: isolate;
      overflow: hidden;
      transition:
        background-color var(--dur-fast) var(--ease-out),
        border-color var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    :is(.btn-primary, .btn-ghost, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a, .project-tab)::before {
      content: "";
      position: absolute;
      z-index: -1;
      inset: -1px -40%;
      background: rgba(65, 64, 66, .30);
      clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
      transform: translate3d(78%, 0, 0);
      transition: transform var(--dur-slow) var(--ease-out) 55ms;
      pointer-events: none;
    }

    :is(.btn-primary, .btn-ghost, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a, .project-tab):is(:hover, :focus-visible) {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
      box-shadow: none;
    }

    :is(.btn-primary, .btn-ghost, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a, .project-tab):is(:hover, :focus-visible)::before {
      transform: none;
    }

    /* Keep the higher-specificity project footer in the same primary-action
       family instead of allowing it to drift back to a black variant. */
    .projects-footer .projects-footer-cta {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
      font-weight: 800;
    }

    .projects-footer .projects-footer-cta:is(:hover, :focus-visible) {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
    }

    .sector-hover-copy a:is(:hover, :focus-visible),
    .why-footer a.btn.btn-primary:is(:hover, :focus-visible) {
      background: var(--brand-sweihan);
      color: var(--brand-white);
    }

    .why-footer a.btn.btn-primary {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
      font-weight: 800;
    }

    /* Ghost actions share the same diagonal wipe entrance as the primary CTA,
       using the same dark overlay fill (no white). Text stays white in both
       states since the wipe never becomes light enough to need a dark label. */
    .btn-ghost {
      background: transparent;
      color: var(--brand-white);
      border-color: var(--brand-white);
      font-weight: 800;
    }

    .btn.btn-ghost:is(:hover, :focus-visible) {
      color: var(--brand-white);
      border-color: var(--brand-white);
    }

    header.scrolled .nav-cta,
    header.scrolled .nav-cta:is(:hover, :focus-visible) {
      background: var(--brand-sweihan);
      color: var(--brand-white);
      border-color: var(--brand-sweihan);
      font-weight: 800;
    }

    .project-tab.active,
    .project-tab:hover {
      background: var(--brand-black);
      border-color: var(--brand-black);
      color: var(--brand-white);
    }

    .project-tab.active:hover,
    .project-tab:focus-visible {
      background: var(--brand-black);
      border-color: var(--brand-black);
      color: var(--brand-white);
    }

    .scroll-top:hover,
    .foot-bottom .socials a:hover,
    .menu.open .menu-contact:hover {
      background: var(--brand-razeen);
      border-color: var(--brand-razeen);
      color: var(--brand-black);
    }

    /* Subsidiary cards: logo-led surfaces with no framing edges. Four fit on a
       wide desktop; the same cards become two-by-two before they get narrow. */
    /* Company cards are separate surfaces. The responsive gutter follows
       the spacing scale used by the other desktop card grids. */
    .companies-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: clamp(16px, 2vw, 24px);
      background: transparent;
    }

    .company-card {
      position: relative;
      min-width: 0;
      min-height: 310px;
      padding: clamp(24px, 2.5vw, 36px) clamp(32px, 3.4vw, 46px);
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      border: 0;
      background: var(--surface-base);
    }

    /* Cards keep straight rectangular edges - no clip-path on the card
       itself. The diagonal motif lives only in the watermark bars below,
       styled after the Sdeira mark's own parallel bars (see the SVG in the
       "Ø¥Ø³ÙƒØ§Ù†" card icon: three parallel parallelogram bars, same slant,
       stepped widths). A hairline gap (grid gap on a strong-tone
       background) separates the four cards instead of a clip-path seam. */
    @media (max-width: 760px) {
      .companies-grid {
        grid-template-columns: 1fr;
        gap: clamp(14px, 4vw, 24px);
        background: transparent;
      }
    }

    /* Corner mark, sized to spill past the card's own top-left edge instead
       of sitting flush inside it. Same physical corner on every card - the
       side away from the right-aligned RTL copy - so it never drifts toward
       the middle or a different spot card to card. --overflow: visible on
       .company-card below (see the SYSTEM LAYER override) is what lets it
       actually escape the box instead of being clipped, since the legacy
       .company-card, .service-card rule this page inherits sets
       overflow: hidden. */
    .company-card::before {
      inset: auto;
      top: -40px;
      left: -78px;
      width: clamp(230px, 46%, 360px);
      height: clamp(230px, 46%, 360px);
      z-index: -1;
      opacity: .1;
      pointer-events: none;
      transform: translate3d(0, 0, 0);
      transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    /* The mark itself, not a hand-built gradient standing in for it -
       assets/images/brand/sdeira-mark.png is the actual three-bar identity
       cut from the logo. One consistent placement for all four cards; the
       hover rule below still steps its strength and drift the same way. */
    .company-card::before {
      background: url("../images/brand/sdeira-mark.png") center / contain no-repeat;
    }

    /* The card itself never changes colour on hover (see the .action-link
       note below) - the watermark stepping up in strength and drifting a
       couple of pixels is the hover cue instead, on both real and pending
       cards so the whole surface still feels reactive. */
    .company-card:hover::before,
    .company-card:focus-within::before {
      opacity: .16;
      transform: translate3d(-6px, 0, 0);
    }

    /* Kept in the DOM for screen readers, without adding a visual ordering
       system that competes with the company identity. */
    .company-card .company-num {
      position: absolute;
      width: 1px;
      height: 1px;
      overflow: hidden;
      clip: rect(0 0 0 0);
      white-space: nowrap;
    }

    .company-logo {
      position: relative;
      z-index: 1;
      width: 100%;
      min-height: 78px;
      margin-bottom: 24px;
      display: flex;
      align-items: flex-start;
      gap: 14px;
      color: var(--company-accent);
      /* Push the logo to the inline-end (visual left in RTL) and sit it
         flush with the top padding, so the identity mark reads as a corner
         pin rather than a centred plate. Applies to every card in the
         group because the corner-pin treatment is the group pattern. */
      align-self: flex-end;
    }

    .company-logo svg {
      width: 54px;
      height: 48px;
      flex: 0 0 auto;
    }

    .company-logo--eskan {
      align-items: center;
      justify-content: flex-start;
      color: var(--brand-black);
    }

    .company-logo--eskan-wordmark {
      display: grid;
      gap: 0;
      color: var(--brand-black);
      font-family: var(--font-display);
      font-weight: 600;
      line-height: .85;
    }

    .company-logo--eskan-wordmark b {
      font-size: clamp(2rem, 2.8vw, 2.85rem);
      font-weight: 600;
    }

    .company-logo--eskan-wordmark small {
      margin: 0;
      color: var(--brand-black);
      font-size: .78rem;
      font-weight: 600;
      line-height: 1;
    }

    .company-logo strong,
    .company-logo h3 {
      margin: 0;
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: clamp(1.6rem, 2vw, 2.1rem);
      font-weight: 500;
      line-height: 1;
    }

    .company-logo small {
      display: block;
      margin-top: 7px;
      color: var(--brand-jais);
      font-size: .72rem;
    }

    .company-logo--image img {
      width: min(190px, 88%);
      height: 76px;
      object-fit: contain;
      object-position: right center;
    }

    .company-logo--zoad img {
      width: min(154px, 82%);
      height: 82px;
    }

    .company-card-title--sr {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
    }

    .company-card > h3 {
      margin-top: 0;
      min-block-size: calc(2em + 7px);
    }

    .company-card > h3 small {
      display: block;
      margin-top: 7px;
      color: var(--brand-jais);
      font-size: .72rem;
      font-weight: 400;
    }

    .company-card p {
      flex: 1 1 auto;
      min-block-size: 3.4em;
      text-wrap: balance;
    }

    /* The card itself never changes colour on hover/click - only the shared
       action link responds. Pending destinations keep the same visual state
       as published ones; only their navigation remains unavailable. */
    .company-card .action-link {
      margin-top: 18px;
      color: var(--brand-black);
      font-weight: 700;
    }

    .company-card .action-link i.ph {
      color: currentColor;
      font-size: .95rem;
    }

    .company-card .action-link.is-pending {
      color: var(--brand-black);
      cursor: default;
    }

    .company-card.is-clickable {
      cursor: pointer;
    }

    .company-card:hover .action-link::after,
    .company-card:focus-within .action-link::after {
      transform: scaleX(1);
    }

    /* Contact choices remain four distinct routing subjects, but the visible
       box grid and the large background mark are removed. Angled card ends and
       short identity strokes carry the Sdeira geometry instead. */

    /* Real photography, kept genuinely visible - a flat 90%-opacity wash
       made the section read as a solid colour band with the photo barely
       showing through as texture, which defeats the point of having a
       photo at all. A gradient wash was tried next (strong behind the
       text, fading out toward the edges) but that produced a visible
       banding seam partway down the section, which read as a bug rather
       than a deliberate effect - so this is one flat, uniform identity
       tint (white+Razeen, not grey) at a light opacity instead: no seam,
       and the photo shows through evenly across the whole section. The
       three cards use their own solid identity-colour fill regardless, so
       they never depend on this wash for contrast. ::before carries the
       photo, ::after the flat tint, both behind .cta-inner's own z-index:1
       stacking context. */
    .cta::before {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -2;
      background: var(--cta-image, url("../images/group-living/living-community.webp")) center / cover no-repeat;
      opacity: 1;
      transform: none;
      pointer-events: none;
    }

    .cta::after {
      content: "";
      position: absolute;
      inset: 0;
      z-index: -1;
      background: var(--brand-black);
      opacity: .55;
      pointer-events: none;
    }

    /* The black tint over the photo darkens the section again, so heading/
       body copy flips back to white for contrast (AAA on the solid-black
       reading, comfortably clear over the darkened photo). The three
       routing cards keep their own solid Razeen fill with brand-black
       text/icon regardless - measured 5.19:1, clears AA body text same as
       the news-card category badge decision, and reads well against dark
       or light surroundings alike. */
    .cta .kicker,
    .cta h2 {
      color: var(--brand-white);
    }

    .cta p {
      color: rgba(255, 255, 255, .82);
    }

    .cta-action {
      border: 1px solid color-mix(in srgb, var(--brand-black) 14%, transparent);
    }

    .cta-inner {
      width: min(1120px, 100%);
      text-align: right;
    }

    .cta .kicker { justify-content: flex-start; }
    .cta h2,
    .cta p { margin-inline: 0; }

    .cta-actions {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 8px;
      max-width: none;
      background: transparent;
    }

    .cta-action {
      position: relative;
      isolation: isolate;
      overflow: hidden;
      min-height: 190px;
      padding: 30px 28px;
      align-items: flex-start;
      text-align: right;
      background: var(--brand-razeen);
      color: var(--brand-black);
      clip-path: polygon(5% 0, 100% 0, 95% 100%, 0 100%);
    }

    /* Straight outer edges and diagonal seams between cards only. RTL grid
       auto-placement renders the first DOM child rightmost. */
    .cta-action:first-child {
      clip-path: polygon(5% 0, 100% 0, 100% 100%, 0 100%);
    }

    .cta-action:last-child {
      clip-path: polygon(0 0, 100% 0, 95% 100%, 0 100%);
    }

    .cta-action i.ph {
      width: auto;
      height: auto;
      background: transparent;
      color: var(--brand-black);
      position: relative;
      z-index: 1;
    }

    .cta-action > span {
      position: relative;
      z-index: 1;
    }

    .cta-action .cta-action-note {
      color: var(--brand-black);
      text-align: right;
    }

    /* Hover is motion only - the diagonal wipe. The card fill is now Razeen
       itself, so a razeen-tinted wipe would be invisible on it; Sweihan
       gives a visible pop of colour instead. */
    .cta-action::before {
      content: "";
      position: absolute;
      z-index: -1;
      inset: -1px -40%;
      background: color-mix(in srgb, var(--brand-sweihan) 30%, transparent);
      clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
      transform: translate3d(78%, 0, 0);
      transition: transform var(--dur-slow) var(--ease-out) 55ms;
      pointer-events: none;
    }

    .cta-action:is(:hover, :focus-visible)::before {
      transform: none;
    }

    /* Three routing choices read as one deliberate set - breaking them into
       2+1 at ordinary laptop widths (the old max-width:1180px breakpoint
       fired on almost any non-ultra-wide screen) made the third card wrap
       onto its own row with a big empty gap beside it. Cards shrink instead
       of wrapping all the way down to real mobile, where the "no lone
       diagonal card" rule below takes over instead. */
    @media (max-width: 620px) {
      .cta-actions { grid-template-columns: 1fr; }

      /* Same rule as .company-card at mobile: a lone diagonal card with
         nothing to seam against reads as visually broken, so the cut is
         removed entirely rather than kept on an isolated stacked card. */
      .cta-action,
      .cta-action:first-child,
      .cta-action:last-child {
        clip-path: none;
      }
    }

    /* Contact follows the primary CTA composition: centered message, three
       equal routes, and one clearly preferred general-contact action. */
    .cta::before {
      background-image: var(--cta-image, url("../images/group-living/contact-community.webp"));
      background-position: center;
    }

    .cta::after {
      background: rgb(0 0 0);
      opacity: .76;
    }

    .cta-inner {
      width: min(1420px, 100%);
      text-align: center;
    }

    .cta .kicker { justify-content: center; }
    .cta h2,
    .cta p { margin-inline: auto; }

    .cta-actions {
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 26px;
      max-width: none;
    }

    .cta-action,
    .cta-action:first-child,
    .cta-action:last-child {
      display: grid;
      grid-template-columns: auto 1fr auto;
      gap: 18px;
      min-height: 128px;
      padding: 24px 28px;
      align-items: center;
      text-align: right;
      background: rgba(43, 41, 41, .92);
      border: 1px solid rgba(255, 255, 255, .22);
      border-radius: var(--r);
      color: var(--brand-white);
      clip-path: none;
    }

    .cta-action:first-child {
      background: var(--accent);
      border-color: var(--accent);
    }

    .cta-action i.ph {
      width: auto;
      height: auto;
      color: currentColor;
      font-size: 2rem;
    }

    .cta-action > span:not(.cta-action-note) {
      font-size: clamp(1.05rem, 1.4vw, 1.35rem);
      font-weight: 700;
    }

    .cta-action .cta-arrow { font-size: 1.25rem; }
    .cta-action .cta-action-note { display: none; }

    /* Reuse the diagonal button wipe for the three contact routes. It sits
       above the card surface but below its content, so the movement is clear
       without reducing the white label/icon contrast. */
    .cta-action::before {
      display: block;
      z-index: 0;
      inset: -1px -40%;
      background: var(--brand-sweihan);
      opacity: .34;
      clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
      transform: translate3d(78%, 0, 0);
      transition: transform var(--dur-slow) var(--ease-out) 55ms;
    }

    /*.cta-action:first-child::before {
      background: color-mix(in srgb, var(--brand-liwa) 58%, var(--brand-sweihan));
    }*/

    .cta-action:is(:hover, :focus-visible) {
      border-color: var(--accent);
    }

    /* Contact routes read as three large, self-contained actions. Stacking
       the icon and title removes the competing icon-text-icon rhythm while
       keeping the entire surface as the accessible link target. */
    .cta-action,
    .cta-action:first-child,
    .cta-action:last-child {
      display: flex;
      position: relative;
      flex-direction: column;
      align-items: flex-start;
      justify-content: space-between;
      gap: 20px;
      min-height: 168px;
      padding: 26px 30px;
    }

    .cta-action > i.ph:not(.cta-arrow) {
      font-size: 2.15rem;
      line-height: 1;
    }

    .cta-action > span:not(.cta-action-note) {
      max-width: 18ch;
      font-size: clamp(1.1rem, 1.5vw, 1.4rem);
      line-height: 1.35;
    }

    .cta-action .cta-arrow {
      display: none !important;
    }

    @media (max-width: 620px) {
      .cta-actions { grid-template-columns: 1fr; gap: 12px; }
    }

    /* Calm institutional choreography: a short vertical travel and a natural
       deceleration, so a section arrives instead of appearing.

       The duration and the curve come from the token file rather than from
       values invented here. --dur-slow is the step the token file assigns to
       the entrance stagger by name, and --ease-out is the only easing the
       system has. This rule used to run at 620ms on a second, undocumented
       curve: 140ms longer than the system allows on every revealed element on
       the page, which is most of it. */
    .reveal.armed {
      opacity: 0;
      visibility: hidden;
      transform: translate3d(0, 24px, 0);
      transition:
        opacity var(--dur-slow) var(--ease-out),
        transform var(--dur-slow) var(--ease-out),
        visibility 0s linear var(--dur-slow);
      will-change: opacity, transform;
    }

    .reveal.armed.in {
      opacity: 1;
      visibility: visible;
      transform: translate3d(0, 0, 0);
      transition-delay: 0s;
      will-change: auto;
    }

    .reveal.armed[data-d="1"] { transition-delay: 80ms; }
    .reveal.armed[data-d="2"] { transition-delay: 160ms; }
    .reveal.armed[data-d="3"] { transition-delay: 240ms; }

    .reveal.armed.in[data-d="1"] { transition-delay: 80ms; }
    .reveal.armed.in[data-d="2"] { transition-delay: 160ms; }
    .reveal.armed.in[data-d="3"] { transition-delay: 240ms; }

    :is(.btn, .nav-cta, .project-tab, .sector-card-action, .sector-hover-copy a, .cta-action):focus-visible {
      outline: 3px solid var(--brand-razeen);
      outline-offset: 3px;
    }

    /* Sector-section title: centred above the grid, on its own blurred bar
       coloured like the card veils, per brand request. Declared last on
       purpose - .hero-sectors-head/-label already carry close to a dozen
       partial redefinitions across breakpoints above, so overriding each one
       is fragile; being last in source order for an unconditional
       (non-media-gated) rule wins the cascade at every width instead. */
    /* The bar sits on the hero photograph, so section 11 of the token file
       governs it: never drop a dark layer over photography below .86, because
       that alpha is the measured contrast floor for the text on top of it. The
       fill was .82, under the floor, and is corrected here.

       An earlier pass tried to keep some photograph visible through the bar by
       putting brightness(7) in the backdrop filter, so the 10% the fill leaves
       would not be wasted. That was reversed on request: it lifted the backdrop
       to near-white, the white came through the remaining 10%, and a bar
       declared at 90% Black rendered as a mid grey band instead. The bar is now
       the same flat glass as the footer, from the same token, and the declared
       colour is what paints.

       Measured on the rendered page after the change, sampled at three points
       across the bar on each of the three hero slides: rgb(59,58,60) to
       rgb(61,60,61) everywhere, so 11.2 against the white label and no drift
       between slides. */
    .hero-sectors-head {
      position: relative;
      isolation: isolate;
      justify-content: center;
      text-align: center;
      min-height: 42px;
      padding-block: 0;
      /* Brand Black at .90. The brightness(7) that used to sit in the filter
         blew the photograph behind the bar out to near-white, and that white
         came through the remaining 10% - so a bar declared at 90% Black still
         read as a mid grey band. Dropping it lets the declared colour be the
         colour. This deliberately does NOT read --scrim-footer: that token is
         the owner's true-black exception for the footer alone, and pointing
         here at it once already turned this bar black by accident. */
      background: var(--scrim-bar);
      backdrop-filter: blur(18px) saturate(112%);
      -webkit-backdrop-filter: blur(18px) saturate(112%);
    }

    .hero-sectors-head::after {
      content: "";
      position: absolute;
      z-index: 1;
      inset-inline: 0;
      inset-block-end: 0;
      height: 1px;
      background: rgb(255 255 255 / .16);
    }

    .hero-sectors-label {
      width: 100%;
      min-height: 0;
      margin: 0;
      display: grid;
      place-items: center;
      font-family: var(--font-display);
      gap: 10px;
      font-size: .86rem;
      font-weight: 700;
      /* Section 11 again: body-size text on these layers is white only, and
         white at .82 opacity is not white. That single value was costing more
         contrast than the whole fill decision above: 4.70 against 6.80 on the
         worst-case region. At solid white the shadow it was leaning on is no
         longer holding anything up, so it goes. */
      color: var(--brand-white);
    }

    /* Every sector card shares this single preview anchor. Keeping the hover
       region at zero height in normal flow makes each preview finish 6px above
       the card row, rather than leaving a separate empty band below it. */
    @media (min-width: 981px) and (hover: hover) and (pointer: fine) {
      .sector-hover-region {
        position: relative;
        inset: auto;
        bottom: auto;
        height: 0;
      }

      .sector-hover-panels {
        position: absolute;
        inset-inline: 0;
        bottom: 6px;
      }

      .sector-hover-panel {
        margin-block-end: 0;
      }
    }

    /* Sector cards: the 5-column desktop/tablet layout collapses them to a
       1px seam (see the "seamless grid" background fill above), which reads
       as one solid slab instead of 5 distinct cards. A real gap, transparent
       grid background so the hero photo shows through the gap instead of the
       old translucent fill tinting it. */
    @media (min-width: 981px) {
      .hero-sectors .wrap {
        width: 100%;
        max-width: none;
        padding-inline: 0;
      }

      .hero-sectors-head {
        width: 100vw;
        max-width: none;
        margin-inline: calc(50% - 50vw);
        padding-inline: 0;
        display: grid;
        place-items: center;
      }

      .hero-sectors-label {
        position: absolute;
        z-index: 2;
        inset: 0;
        display: grid;
        place-items: center;
        text-align: center;
      }

      /* The gap between the five cards is deliberate and stays. What it is
         filled with is the part that kept going wrong, and there are only
         three candidates:

           opaque --surface-inverse   the original. Reads as five drawn black
                                      divider lines over the photograph.
           transparent                the gap becomes a slot of hero photo
                                      between each pair of cards.
           the bar's own glass        chosen.

         Taking --scrim-bar means the seam is the same material as the
         "Ù‚Ø·Ø§Ø¹Ø§Øª Ø§Ù„Ù…Ø¬Ù…ÙˆØ¹Ø©" bar directly above it, so the bar and the five gaps
         read as one glass frame around the row rather than as lines drawn on
         top of it. Same backdrop-filter as the bar for the same reason: a
         different blur either side of a 10px seam is visible. */
      .sector-grid {
        gap: clamp(6px, .55vw, 12px);
        background: var(--scrim-bar);
        backdrop-filter: blur(18px) saturate(112%);
        -webkit-backdrop-filter: blur(18px) saturate(112%);
        border-top: 0;
      }

      .sector-card {
        border-inline-start: 0;
      }

      .sector-card:first-child {
        border-inline-start: 0;
      }
    }

    /* Slide-progress rail: an earlier fix stretched it to the full width of
       the content column (see the "Full width at every size" comment above)
       to fix a tablet-only bug, but on desktop that means it spans the whole
       hero instead of tracking just the two buttons above it. Capped back
       down and kept end-aligned with the buttons on desktop only; the
       mobile/tablet full-width behaviour that earlier fix targeted is
       untouched below 981px. */
    @media (min-width: 981px) {
      .hero-slides-ind {
        inline-size: clamp(160px, 18vw, 240px);
      }
    }

    /* The cue has a real grid row in the hero instead of an absolute offset.
       It therefore sits below the hero copy and before the sector strip,
       regardless of the cards' responsive height.

       It now holds the slide rail as well. The two used to sit on separate
       lines - the rail as the last item of .hero-content-row, the cue in its
       own row underneath - which spent two nearly empty lines of hero height
       on them. The cue also carries .wrap in the markup, so the rail stays
       aligned with the hero buttons above it rather than with the viewport
       edge.

       The rail is FIRST in the markup and the row is a plain flex row, with no
       direction override. That ordering is what makes the placement correct in
       both reading directions and at every width: the rail takes the main
       start, which is the same side the hero buttons are anchored to (right in
       RTL, left in the English mirror), and the hint takes the far end. It also
       survives the hint being hidden between 721px and 980px - a lone rail
       stays on the buttons' side instead of sliding to the empty corner, which
       is exactly what a row-reverse or a direction flip got wrong here.

       These four rules are deliberately last for this component. .hero-slides-ind
       is declared eleven times above, including unconditionally, so the child
       selector here is what makes the new placement win without !important. */
    .hero-scroll-cue {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 16px;
    }

    /* The rail carried a top margin as the last item of the content column,
       and a `flex: 0 0 44px` basis that was sized for that column: the parent
       was column-direction, so 44px was its HEIGHT. In a row that same basis
       becomes its WIDTH and collapsed the rail to a 44px stub. */
    .hero-scroll-cue > .hero-slides-ind {
      margin-top: 0;
      flex: 0 0 auto;
      inline-size: clamp(160px, 18vw, 240px);
      /* The rail is declared `order: 2` and `order: -1` at two widths further
         up, both written for its old parent. Either one would re-sort this row
         and undo the markup order that puts the rail on the buttons' side. */
      order: 0;
    }

    /* Below 720px the hint is hidden, so the rail is alone on the row and
       keeps the full width it had inside the content column. */
    @media (max-width: 720px) {
      .hero-scroll-cue > .hero-slides-ind {
        inline-size: 100%;
      }
    }

    @media (min-width: 981px) {
      .hero {
        display: grid;
        /* Two rows, not three. The middle 58px row existed only to hold the
           scroll cue; the cue is now the last line of the content column, so
           that row would be empty height. This is the space the change was
           asked for. */
        grid-template-rows: minmax(0, 1fr) auto;
        height: max(760px, 100svh);
        min-height: max(760px, 100svh);
        padding-bottom: 0;
      }

      .hero-content {
        grid-row: 1;
        align-self: stretch;
        min-height: 0;
        height: auto;
      }

      .hero-scroll-cue {
        position: relative;
        z-index: 3;
      }

      .hero-sectors {
        grid-row: 2;
        position: relative;
        inset: auto;
        margin-top: 0;
      }
    }

    /* The scroll cue adds no value on the compact mobile hero. */
    @media (max-width: 720px) {
      .scroll-hint {
        display: none;
      }
    }

    /* Filtering changes the information set, not the editorial hierarchy. The
       curated "all" state keeps its lead-card composition; a narrowed result
       is always a conventional, equal-card grid so one surviving item never
       inherits a full-width feature layout. */
    .news-grid.is-filtered-view,
    .featured-projects .project-cards.is-filtered-view {
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: clamp(16px, 2vw, 28px);
      background: transparent;
      overflow: visible;
      border-radius: var(--r);
    }

    /* A narrowed result stays a 2-up grid at every width, even the very
       widest desktop screens - the wider column this gives each surviving
       card reads as generous rather than sparse. A 3rd column used to cut in
       here at >=1680px; removed rather than kept, since two spacious cards
       is the reading this whole "conventional, equal-card grid" treatment
       was built for. Site owner flagged, 12 Aug 2026. */

    .news-grid.is-filtered-view .news-card--feature {
      grid-column: auto;
      display: block;
    }

    .news-grid.is-filtered-view .news-card--feature .news-image-link {
      height: auto;
    }

    /* This comment used to say the lead card's media height is not restated
       here on purpose, because every card took --news-media-height from the
       shared .news-card .img rule. That stopped being true once
       .news-card:not(.news-card--feature) .img (SYSTEM LAYER) started giving
       every OTHER card a var(--media-wide) (4:3 since 15 Aug 2026, was 16:9),
       card-width-independent crop instead of the fixed clamp - a rule that
       deliberately excludes .news-card--feature because its normal editorial
       state stretches the image to a two-column split, not a fixed ratio.
       Once .is-filtered-view puts this card at the same width as its
       siblings, that exclusion stops being correct: the fixed clamp and the
       sibling crop no longer agree at that width, so the demoted lead card's
       photo was visibly taller than its "equal" sibling's. Site owner
       flagged, 12 Aug 2026 ("Ø§Ù„ÙƒØ±Øª Ø§Ù„Ø£ÙˆÙ„ Ù…Ø®ØªÙ„Ù... Ø§Ù„ØªÙ†Ø³ÙŠÙ‚ Ù…Ø«Ù„ Ø§Ù„ÙƒØ±Øª
       Ø§Ù„Ø«Ø§Ù†ÙŠØ©"). Kept reading var(--media-wide) rather than a literal so the
       two can never drift apart like this again. */
    .news-grid.is-filtered-view .news-card--feature .img {
      min-height: 0;
      aspect-ratio: var(--media-wide);
      block-size: auto;
    }

    .news-grid.is-filtered-view .news-card--feature .news-body {
      justify-content: initial;
    }

    .news-grid.is-filtered-view .news-card--feature h3 {
      font-size: clamp(1.2rem, 1.7vw, 1.5rem);
      -webkit-line-clamp: 2;
    }

    .featured-projects .project-cards.is-filtered-view .project-card--feature {
      grid-column: auto;
      position: static;
      min-height: 0 !important;
      overflow: hidden;
      background: var(--surface-raised) !important;
    }

    .project-cards.is-filtered-view .project-card--feature .project-card-img {
      /* relative, not static: the card returns to normal flow here, but it
         still hosts a .ribbon-frame that is inset: 0 and must resolve against
         the photo box. See the base .project-card-img rule. */
      position: relative;
      inset: auto;
      height: auto;
    }

    /* A filtered portfolio is a comparison view, not the editorial feature
       composition. Give every surviving project the exact same media track
       and body rules so an original lead card cannot crop or stretch unlike
       its peers. */
    .featured-projects .project-cards.is-filtered-view .project-card {
      grid-template-rows: clamp(240px, 25vw, 340px) auto;
      min-height: 0;
      height: auto;
      background: var(--surface-raised);
    }

    .project-cards.is-filtered-view .project-card .project-card-img,
    .project-cards.is-filtered-view .project-card--secondary .project-card-img {
      min-height: 0;
      height: clamp(240px, 25vw, 340px);
    }

    .project-cards.is-filtered-view .project-card .project-card-body {
      min-height: 0;
      padding: clamp(24px, 2.4vw, 34px);
      background: var(--surface-raised);
    }

    .project-cards.is-filtered-view .project-card--feature .project-card-img::after {
      display: none;
    }

    .project-cards.is-filtered-view .project-card--feature .project-card-body {
      position: static;
      inset: auto;
      max-width: none;
      min-height: 100%;
      padding: clamp(24px, 2.4vw, 34px);
      background: var(--surface-raised);
      color: var(--brand-black);
    }

    /* One flat var(--brand-black) here used to cover all four - correct for
       h3, but .project-type/p/.project-meta each have their own on-light-surface
       token already (--badge-text, --muted, --icon/--label), and the
       secondary card right next to this one in the same grid uses exactly
       those, not black. Split so each element matches its sibling's actual
       token instead of one flattened color. Found by diffing every computed
       property against .project-card--secondary, not by another one-off
       screenshot report. Site owner flagged, 12 Aug 2026. */
    .project-cards.is-filtered-view .project-card--feature h3 {
      color: var(--brand-black);
    }

    .project-cards.is-filtered-view .project-card--feature p {
      color: var(--muted);
    }

    .project-cards.is-filtered-view .project-card--feature h3 {
      font-size: clamp(1.35rem, 2vw, 1.85rem);
      line-height: 1.25;
    }

    .project-cards.is-filtered-view .project-card--feature p {
      max-width: none;
    }

    .project-cards.is-filtered-view .project-card--feature .project-meta {
      margin-top: clamp(24px, 3vw, 34px);
      padding-top: 0;
      border-top: 0;
    }

    .project-cards.is-filtered-view .project-card--feature .project-card-action {
      color: var(--brand-black);
    }

    /* The feature card's own corner mark, on loan from the same shared
       .card-chevron secondary/company cards already carry (same tokens, same
       drawing, same white-line-on-white-surface treatment - nothing invented).
       Hidden by default: the editorial "all" state has no chevron on this
       card and no z-index escape hatch for its text, so an always-on chevron
       would paint over the copy there (position:0 stacks above in-flow text).
       Only turned on once .is-filtered-view has already demoted this card to
       the same plain white surface as its siblings. Site owner flagged,
       12 Aug 2026 ("Ø§Ù„ÙƒØ±Øª Ø§Ù„Ø£ÙˆÙ„ Ù…Ø®ØªÙ„Ù Ø¨Ø§Ù„ÙƒØ§Ù…Ù„ Ø¹Ù† Ø§Ù„Ø¨Ø§Ù‚ÙŠ... Ù…Ø§ÙÙŠÙ‡ Ø´ÙƒÙ„ Ø¬Ù…Ø§Ù„ÙŠ"). */
    .project-card--feature .card-chevron {
      display: none;
    }

    .project-cards.is-filtered-view .project-card--feature .card-chevron {
      display: block;
      position: absolute;
      z-index: 0;
      /* `inset: auto` FIRST - same fix as the base `.card-chevron` rule
         above: clears the blanket `.card-chevron.card-chevron { inset: 0 }`
         reset in sdeira-sections.css before left/bottom apply. */
      inset: auto;
      left: -7%;
      bottom: -8%;
      width: min(40%, 180px);
      aspect-ratio: 434 / 281;
      opacity: 1;
      --chev-line: var(--brand-white);
      --chev-tint: rgba(255, 255, 255, .30);
      pointer-events: none;
      transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
    }

    .project-cards.is-filtered-view .project-card--feature .card-chevron svg {
      width: 100%;
      height: 100%;
      overflow: visible;
    }

    .project-cards.is-filtered-view .project-card--feature .project-card-body > :not(.card-chevron) {
      position: relative;
      z-index: 1;
    }

    .project-cards.is-filtered-view .project-card--feature:is(:hover, :focus-within) .card-chevron {
      transform: translate3d(14px, -10px, 0);
    }

    @media (prefers-reduced-motion: reduce) {
      .project-cards.is-filtered-view .project-card--feature .card-chevron { transition: none; }
    }

    @media (max-width: 720px) {
      .news-grid.is-filtered-view,
      .featured-projects .project-cards.is-filtered-view {
        grid-template-columns: 1fr;
      }
    }

    /* Feature projects acknowledge the full-card link on hover without
       disturbing the text layer: the image comes forward on hover, and
       the identity bars stay still on purpose - the previous rotate+drift
       motion made the mark feel like a hoverable element in its own right
       and competed with the project-card-action CTA below. */
    .project-card--feature .project-card-img img {
      transform: scale(1);
      transform-origin: center;
      transition: transform var(--dur-slow) var(--ease-out), filter var(--dur-slow) var(--ease-out);
      will-change: transform;
    }

    /* No transition, no transform, no opacity step on the feature-card
       mark: it is a static identity stroke on the photograph and must not
       read as an interactive element on its own. */

    .project-card--feature:is(:hover, :focus-within) .project-card-img img {
      transform: scale(1.045);
      filter: saturate(1.06);
    }

    @media (prefers-reduced-motion: reduce) {
      .project-card--feature .project-card-img img {
        transition: none;
      }

      .project-card--feature:is(:hover, :focus-within) .project-card-img img {
        transform: none;
      }
    }

    /* The oversized identity strips that used to enter from the quiet side of
       the footer were removed: the footer now carries the flat brand Black
       glass on its own, with nothing drawn over it. The positioning context
       stays because .wrap below still relies on it. */
    footer {
      position: relative;
      isolation: isolate;
      overflow: hidden;
    }

    footer > .wrap {
      position: relative;
      z-index: 1;
    }

    /* Descriptive copy benefits from balanced line endings in Arabic. This
       keeps section summaries deliberate without changing their content. */
    main p,
    footer .foot-brand p {
      text-wrap: balance;
    }

    .cta-inner > p {
      max-inline-size: 53ch;
    }

    /* A section-level action shares the filter row, but stays visually
       secondary to the active tab. The same pattern works as an archive link
       once a dedicated archive page is available. */
    .section-filter-bar {
      display: flex;
      align-items: stretch;
      justify-content: space-between;
      gap: 20px;
      width: 100%;
    }

    .section-filter-bar :is(.project-filters, .news-filters) {
      margin: 0;
    }

    /* .section-view-all is a <button>/<a> pair used for the same "view all"
       action .action-link already covers on cards: the structure, underline
       and icon-rotate motion now come from the shared rules above (see
       .action-link, .sector-card-action, .section-view-all). What's left
       here is only what a light-surface button genuinely needs that an
       on-image <a> doesn't: a border reset, inherited font (buttons don't
       inherit font by default), and the dark-surface text colour. It used
       to carry its own translateX hover slide instead of the shared rotate -
       two separate components pretending to be the same button. */
    .section-view-all {
      border: 0;
      color: var(--brand-black);
      font: inherit;
      cursor: pointer;
    }

    /* The icon's own font-size (1.1rem) is dropped for the same reason the
       icon system header comment warns about: sized in em/rem off whatever
       the parent happens to set, it drifted from every other action-link
       icon on the page. Left alone it would fall through to the base
       `i.ph { font-size: var(--ic-md) }` role (~24px, tuned for standalone
       feature icons), not the size an inline text-link icon actually needs.
       --ic-sm is the same token every other .action-link/.sector-card-action
       icon already resolves to (see .sector-card-action i.ph above), so this
       keeps it the one size those icons are meant to be, not a new one. */
    .section-view-all > i.ph {
      font-size: var(--ic-sm);
    }

    .section-view-all:focus-visible {
      outline: 2px solid var(--accent);
      outline-offset: 4px;
    }

    @media (max-width: 620px) {
      .section-filter-bar {
        align-items: flex-start;
        flex-direction: column;
      }
    }

    /* Contact routes keep every action element on one horizontal line: route
       mark, label, then the Arabic-direction arrow. */
    .cta-action,
    .cta-action:first-child,
    .cta-action:last-child {
      display: flex;
      position: relative;
      flex-direction: row;
      align-items: center;
      justify-content: center;
      gap: 14px;
      min-height: 84px;
      padding: 14px 20px;
      text-align: start;
    }

    .cta-action > i.ph:not(.cta-arrow) {
      display: none !important;
    }

    /* The route mark stays in the normal horizontal flow for every action. */
    .cta-action > i.ph.cta-action-mark:not(.cta-arrow) {
      display: block !important;
      position: relative;
      z-index: 2;
      width: auto;
      height: auto;
      margin: 0;
      background: transparent;
      color: currentColor;
      font-size: 1.7rem;
      line-height: 1;
      opacity: 1;
      pointer-events: none;
      transform: none;
    }

    .cta-action > span:not(.cta-action-note),
    .cta-action .cta-arrow {
      position: relative;
      z-index: 2;
    }

    .cta-action > span:not(.cta-action-note) {
      flex: 0 1 auto;
      max-width: none;
      font-size: clamp(1rem, 1.25vw, 1.18rem);
      line-height: 1.35;
      text-align: start;
    }

    .cta-action .cta-arrow {
      display: grid !important;
      place-items: center;
      position: relative !important;
      inset: auto;
      margin-inline-start: auto;
      font-size: .9rem !important;
      transform: none;
    }

    /* Contact routes use the same concise colour response as the primary
       button: no lift, wipe, or layout movement. */
    .cta-action {
      overflow: hidden;
      transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
    }

    .cta-action::before {
      display: none;
    }

    .cta-action:is(:hover, :focus-visible),
    .cta-action:first-child:is(:hover, :focus-visible) {
      transform: none;
      background-color: var(--accent-deep);
      border-color: var(--accent-deep);
    }

    /* Desktop contact routes remain a single three-action row. Mobile keeps
       its intentional one-column layout below 620px. */
    @media (min-width: 621px) {
      .cta-actions { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
    }

    /* Filter strips get their own breathing room: they are controls between
       the editorial introduction and the card collection, never a divider
       glued to either. */
    .section-filter-bar {
      margin-block: clamp(28px, 3vw, 42px) clamp(24px, 2.5vw, 36px);
    }

    .projects-head:has(.section-filter-bar) {
      gap: clamp(28px, 3vw, 42px);
      margin-bottom: 0;
      grid-template-columns: minmax(0, 1fr);
      justify-content: stretch;
    }

    .projects-head .section-filter-bar {
      margin-block: 0 clamp(24px, 2.5vw, 36px);
    }

    /* Contextual action is the one shared card-link component.  Colours may
       vary for contrast against each card surface, but its spacing, underline
       and directional movement never vary by section. */
    :is(.action-link, .sector-card-action, .section-view-all) {
      gap: .48rem;
      padding-block-end: 4px;
      overflow: visible;
    }

    :is(.action-link, .sector-card-action, .section-view-all) > i.ph {
      flex: 0 0 auto;
      transform: rotate(45deg);
      transition: transform var(--dur-base) var(--ease-out);
    }

    :is(.action-link, .sector-card-action, .section-view-all):is(:hover, :focus-visible) > i.ph,
    :is(.news-card, .project-card, .sector-card, .company-card, .needs-route):is(:hover, :focus-within) :is(.action-link, .sector-card-action) > i.ph {
      transform: rotate(0deg);
    }

    :is(.action-link, .sector-card-action, .section-view-all)::after {
      block-size: 2px;
    }

    /* On touch-size sector cards the Arabic action keeps its literal leftward
       arrow. The desktop turn-on-hover rotation is not useful without hover
       and made the direction visually ambiguous. The 8px gutter separates
       every card without changing the two-column structure. */
    @media (max-width: 720px) {
      .hero-sectors .sector-grid {
        gap: 8px;
      }

      .hero-sectors .sector-card-action > i.ph,
      .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-action > i.ph {
        transform: none;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      :is(.action-link, .sector-card-action) > i.ph {
        transition: none;
      }
    }

    /* Hero sectors stay equal without forcing square cards, and the row height
       never changes during the interaction. */
    .hero-sectors .sector-grid {
      grid-auto-rows: 1fr;
      align-items: stretch;
    }

    /* The height used to be a fixed clamp(176px, 16vw, 208px), which carried
       about 47px of empty space at desktop widths: the resting content needs
       155.8px at 1280 and the card was 205px. It is now content-derived.

       This only became possible once every description reserved the same two
       lines, because that is what makes all five cards identical in height with
       no fixed number involved. Measured card height afterwards, five cards
       always equal: 163px at 1920 and 1600, 161 at 1400, 158 at 1280, 153 at
       1180, 150 at 1024 and 980, 168 at 720 and below.

       The hover state does not constrain this. The action link is absolutely
       positioned and hidden at rest, and the -40px shift that reveals it only
       has to clear a 21px link, so the clearance is independent of card height.
       That is why the card can drop to its resting content height without the
       hover interaction colliding. */
    .hero-sectors .sector-card {
      aspect-ratio: auto;
      block-size: auto;
      min-block-size: 0;
      min-height: 0;
      overflow: hidden;
    }

    /* The ramp climbs gradually across nearly the whole card, not in a short
       jump partway down.

       Two earlier attempts inside this same edit were measured against
       unloaded <img> elements (loading="lazy" images that were never
       force-decoded before sampling): getImageData on an incomplete image
       returns transparent black for every pixel, so those contrast numbers
       were computed against rgba(0,0,0,0), not the photograph. They happened
       to still report AA passes, which is meaningless - they were not
       measuring the real composite at all. This is the first version verified
       against fully decoded images (img.decode() awaited before sampling).

       Against the real, loaded photos, the previous stops (a jump from .42 at
       50% to .82 at 65%, slope .027 per 1%) failed Services at 4.36, below
       the 4.5 AA floor. This curve widens the climb further and lifts the
       55%-70% band specifically, where Services' brightest region sits: peak
       slope is .02 per 1%, 44% gentler than the original .036 jump, and every
       card now clears AA with the real images loaded - worst case 6.42 on
       Services, up to 9.16 on Development. */
    .hero-sectors .sector-card-veil {
      background: linear-gradient(180deg,
        rgba(var(--image-overlay-rgb), .04) 0%,
        rgba(var(--image-overlay-rgb), .06) 10%,
        rgba(var(--image-overlay-rgb), .09) 20%,
        rgba(var(--image-overlay-rgb), .14) 30%,
        rgba(var(--image-overlay-rgb), .22) 40%,
        rgba(var(--image-overlay-rgb), .34) 50%,
        rgba(var(--image-overlay-rgb), .42) 55%,
        rgba(var(--image-overlay-rgb), .52) 60%,
        rgba(var(--image-overlay-rgb), .62) 65%,
        rgba(var(--image-overlay-rgb), .70) 70%,
        rgba(var(--image-overlay-rgb), .80) 80%,
        rgba(var(--image-overlay-rgb), .87) 90%,
        rgba(var(--image-overlay-rgb), .92) 100%);
    }

    .hero-sectors .sector-card-body {
      position: relative;
      min-block-size: 0;
      padding: clamp(14px, 1.35vw, 18px);
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      justify-content: flex-end;
      gap: 6px;
    }

    .hero-sectors .sector-card-mark,
    .hero-sectors .sector-card-title,
    .hero-sectors .sector-card-sub {
      margin: 0;
      transition: transform var(--dur-base) var(--ease-out),
        opacity var(--dur-fast) var(--ease-out);
    }

    /* Keep short Arabic headings on the same logical start edge as the description. */
    .hero-sectors .sector-card-title {
      inline-size: 100%;
      text-align: start;
    }

    .hero-sectors .sector-card-mark {
      flex: 0 0 auto;
      margin-block-end: 2px;
    }

    /* The two-line description reservation is a design-system rule and now
       lives once in the system layer at the end of this block, expressed in lh
       so it follows the line-height instead of restating it as an em value. */

    .hero-sectors .sector-card-action {
      position: absolute;
      inset-inline-start: clamp(14px, 1.35vw, 18px);
      inset-block-end: clamp(14px, 1.35vw, 18px);
      margin: 0;
      padding: 0 0 4px;
      min-height: 0;
      opacity: 0;
      pointer-events: none;
      transform: translateY(6px);
      transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .hero-sectors .sector-card:is(:hover, :focus-within) :is(.sector-card-mark, .sector-card-title, .sector-card-sub) {
      transform: translateY(-40px);
    }

    .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-sub {
      opacity: 1;
      visibility: visible;
    }

    .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-action {
      opacity: 1;
      pointer-events: auto;
      transform: none;
    }

    @media (prefers-reduced-motion: reduce) {
      .hero-sectors .sector-card-mark,
      .hero-sectors .sector-card-title,
      .hero-sectors .sector-card-sub,
      .hero-sectors .sector-card-action {
        transition: none;
      }
    }

    @media (max-width: 980px) {
      .hero-sectors .sector-card {
        block-size: clamp(176px, 48vw, 210px);
      }
    }

    /* Direct routes use the same calm white-card language as the subsidiary
       companies. The audience appears first so visitors can recognise their
       route before having to decode the service name. */
    .needs {
      position: relative;
      overflow: hidden;
      padding-block: clamp(76px, 8vw, 124px);
      background: var(--surface-sunken);
      color: var(--ink);
    }

    .needs-layout {
      display: grid;
      grid-template-columns: minmax(250px, .72fr) minmax(0, 1.28fr);
      gap: clamp(40px, 6vw, 92px);
      align-items: start;
    }

    .needs-intro {
      padding-top: clamp(8px, 1.2vw, 20px);
    }

    .needs-intro .kicker {
      color: var(--label);
    }

    .needs-intro h2 {
      max-width: 10ch;
      margin: 16px 0 24px;
      color: var(--ink);
      font-size: clamp(2.6rem, 5vw, 5rem);
      line-height: 1.03;
    }

    .needs-intro p {
      max-width: 37ch;
      margin: 0;
      color: var(--muted);
      font-size: clamp(1rem, 1.25vw, 1.16rem);
      line-height: 1.85;
    }

    .needs-routes {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      gap: clamp(16px, 2vw, 24px);
    }

    .needs-route {
      position: relative;
      display: grid;
      grid-template-rows: clamp(132px, 12vw, 176px) 1fr;
      overflow: hidden;
      min-width: 0;
      min-height: 360px;
      background: var(--surface-base);
      color: var(--ink);
      text-decoration: none;
    }

    .needs-route-media {
      position: relative;
      display: block;
      overflow: hidden;
      border-radius: var(--r);
    }

    .needs-route-media img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--dur-slow);
    }

    .needs-route:hover .needs-route-media img,
    .needs-route:focus-within .needs-route-media img {
      transform: scale(var(--zoom));
    }

    /* ===== CARD CHEVRON =====
       The Khadamat service-card sticker (khadamat.css:975-1029), carried over
       whole: same paths, same per-path opacities, same corner overhang, same
       hover step. One shared class for both white-card families (direct
       routes and subsidiary companies) so the two cannot drift apart.

       Two adaptations the source did not need, both forced by the surface:
       the source sits on a dark photograph, this sits on a white card. Its
       four hairlines are stroked #fff, which is invisible here, so they take
       Sweihan; and the small highlight wedge is likewise a tint rather than
       near-white. Everything else is untouched.

       Layering is z-index 0 with the copy raised to 1, NOT z-index -1. A
       negative index was tried first and is invisible on both hosts, for two
       different reasons that neither look like a bug: .needs-route paints no
       background of its own (the white belongs to .needs-route-copy, which is
       position: relative + z-index: 3, so it covers anything negative beneath
       it), and .company-card is only a stacking context while its .reveal
       animation still holds opacity: 0 - once revealed it stops being one, and
       a negative child drops behind the card's own white background. Raising
       the content is the layering that survives both. The host card already
       clips (overflow: hidden), which is what crops this to a corner sticker
       rather than a floating triangle. */
    .card-chevron {
      --chev-tint: color-mix(in srgb, var(--brand-razeen) 34%, var(--brand-white));
      --chev-line: var(--brand-sweihan);
      position: absolute;
      z-index: 0;
      /* `inset: auto` FIRST - clears sdeira-sections.css's blanket
         `.card-chevron.card-chevron { inset: 0 }` (higher specificity,
         always wins) before this rule's own left/bottom apply, or top/right
         stay pinned at 0 and the sticker stretches across the card instead
         of anchoring a small corner mark - flagged from a screenshot of the
         homepage's own "Direct routes" cards, 28 Aug 2026. */
      inset: auto;
      left: -7%;
      bottom: -8%;
      width: min(62%, 300px);
      aspect-ratio: 434 / 281;
      opacity: .78;
      pointer-events: none;
      transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
    }

    .card-chevron svg {
      width: 100%;
      height: 100%;
      overflow: visible;
    }

    /* The copy has to out-rank the sticker explicitly: in-flow text paints
       BEFORE positioned z-index: 0 elements, so without this the chevron
       would cover the words rather than sit behind them. .company-num is
       excluded because it is the screen-reader-only number and relies on
       position: absolute for its clip - handing it position: relative would
       drop it back into the visible layout. */
    .needs-route-copy > :not(.card-chevron),
    .company-card > :not(.card-chevron, .company-num) {
      position: relative;
      z-index: 1;
    }

    :is(.needs-route, .company-card, .project-card--secondary):is(:hover, :focus-within) .card-chevron {
      opacity: .94;
      transform: translate3d(14px, -10px, 0);
    }

    /* The card sticker is drawn in flat white line, in BOTH states, and at
       full strength, on every card family that carries it.

       Line first. Sweihan hairlines measure 1.28 on the #cb6c2e hover fill and
       read as dirt rather than as drawing, so the hover state had to change
       anyway; plain white in both states is what keeps the drawing one shape
       that fills in, instead of a shape that also changes colour mid-gesture.
       No alpha on the line itself - the SVG's own per-path stroke-opacity
       (.55-.65) is already the depth in this drawing, and stacking a second
       transparency on top of it was what greyed the whole thing out.

       Then strength. The shared class rests at .78 and lifts to .94; here it
       is 1 throughout. The rest state is the state a visitor actually spends
       time looking at, and fading the identity mark to three-quarters there
       bought nothing - the drawing is already quiet by weight (1px lines) and
       by size. Only the position still moves on hover.

       Consequence, stated rather than discovered later: at rest the panel is
       white, so the white lines read only where they cross the coloured
       wedge. That is the intended reading - a soft mark that resolves fully
       once the panel fills. */
    :is(.needs-route, .project-card--secondary, .company-card) .card-chevron,
    :is(.needs-route, .project-card--secondary, .company-card):is(:hover, :focus-within) .card-chevron {
      --chev-line: var(--brand-white);
      --chev-tint: rgba(255, 255, 255, .30);
      opacity: 1;
    }

    /* Deliberately smaller than the shared default. At min(62%, 300px) the
       sticker reached the middle of the card and left no room for the copy to
       grow: one more line of body text and the words would have run into the
       drawing. Now that all three card families carry it, this is the size -
       kept as a scoped rule rather than folded into .card-chevron only
       because that class is also the one the shared default documents. */
    :is(.needs-route, .project-card--secondary, .company-card) .card-chevron {
      width: min(40%, 180px);
    }

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

    .needs-route:focus-visible {
      outline: 2px solid var(--brand-black);
      outline-offset: 4px;
    }

    .needs-route-copy {
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      min-height: 0;
      padding: clamp(22px, 2.3vw, 30px);
      min-width: 0;
    }

    .needs-route-audience {
      display: block;
      margin-bottom: 12px;
      color: var(--label);
      font-size: .84rem;
      font-weight: 700;
      line-height: 1.45;
    }

    .needs-route h3 {
      margin: 0;
      min-block-size: 2.5em;
      color: var(--ink);
      font-size: clamp(1.25rem, 1.7vw, 1.65rem);
      line-height: 1.25;
      text-wrap: balance;
    }

    .needs-route p {
      flex: 1 1 auto;
      margin: 12px 0 0;
      min-block-size: 3.3em;
      color: var(--muted);
      line-height: 1.65;
      text-wrap: balance;
    }

    .needs-route-action {
      /* This route only controls placement. Appearance and motion come from
         the shared .action-link component used by projects and companies. */
      margin-top: auto;
      padding-top: 20px;
      color: var(--ink);
      align-self: flex-start;
      width: auto;
      max-width: calc(100% - 1.5em);
      white-space: nowrap;
    }

    .needs-route-action i.ph {
      color: currentColor;
    }

    /* An older hover rule lived here too, sliding this pseudo-element
       -10px on hover. It was superseded further down the file for the odd
       (mirrored) routes by nth-child(odd), so it only ever fired live on
       the even routes - an inconsistency nobody asked for, on top of the
       actual mirror-flip bug fixed at the later rule. Removed rather than
       carried forward: the line's direction and position must not move on
       interaction, for any route. */

    @media (max-width: 920px) {
      .needs-layout {
        grid-template-columns: 1fr;
        gap: 42px;
      }

      .needs-intro h2 {
        max-width: none;
      }
    }

    @media (max-width: 620px) {
      .needs {
        padding-block: 68px;
      }

      .needs-routes {
        grid-template-columns: 1fr;
      }

      .needs-route {
        grid-template-rows: 168px 1fr;
        min-height: 0;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .needs-route-media img,
      .needs-route-action i {
        transition: none;
      }
    }

    /* Temporary decision previews for the direct-routes section. Both use the
       same routes and photography; only the hierarchy changes, so the choice
       is about the layout rather than different content. */
    .needs-prototypes {
      padding-block: clamp(84px, 10vw, 148px);
      background: var(--surface-base);
      color: var(--ink);
    }

    .needs-prototypes-intro {
      max-width: 760px;
      margin: 0 auto clamp(48px, 6vw, 76px);
      text-align: center;
    }

    .needs-prototypes-intro .kicker { justify-content: center; }
    .needs-prototypes-intro h2 { margin: 14px 0 12px; font-size: clamp(2rem, 4vw, 3.35rem); line-height: 1.18; }
    .needs-prototypes-intro p { margin: 0; color: var(--muted); text-wrap: balance; }

    .needs-prototype + .needs-prototype {
      margin-top: clamp(76px, 10vw, 148px);
      padding-top: clamp(76px, 10vw, 148px);
      border-top: 1px solid var(--surface-sunken-strong);
    }

    .needs-prototype-head {
      position: static !important;
      inset: auto !important;
      transform: none !important;
      max-width: 760px;
      margin: 0 auto;
      padding: 0;
      text-align: center;
    }

    .needs-prototype-head .kicker { justify-content: center; }
    .needs-prototype-head h3 { margin: 14px 0 12px; font-size: clamp(2rem, 4vw, 3.2rem); line-height: 1.18; }
    .needs-prototype-head p { margin: 0; color: var(--muted); text-wrap: balance; }

    .needs-prototype-grid {
      display: grid;
      grid-template-columns: repeat(2, minmax(0, 1fr));
      align-items: start;
      gap: clamp(16px, 2vw, 24px);
      margin-top: clamp(38px, 5vw, 64px);
    }

    .needs-prototype-tile {
      display: grid;
      grid-template-rows: auto auto;
      min-width: 0;
      min-height: 0;
      align-self: start;
      overflow: hidden;
      background: #fff;
      color: var(--ink);
      text-decoration: none;
    }

    .needs-prototype-media,
    .needs-prototype-tile-media,
    .needs-prototype-row-media {
      position: relative;
      overflow: hidden;
      background: var(--brand-black);
    }

    .needs-prototype-media::after,
    .needs-prototype-tile-media::after,
    .needs-prototype-row-media::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(180deg, transparent 35%, rgba(23, 22, 20, .32));
      pointer-events: none;
    }

    .needs-prototype-media::before,
    .needs-prototype-tile-media::before,
    .needs-prototype-row-media::before {
      content: "";
      position: absolute;
      z-index: 1;
      inset-block: -20%;
      inset-inline-start: -5%;
      width: 62%;
      background: linear-gradient(108deg,
        transparent 0 17%, rgba(255, 255, 255, .72) 17% 21%,
        transparent 21% 40%, rgba(201, 151, 55, .8) 40% 47%,
        transparent 47% 64%, rgba(220, 105, 40, .75) 64% 72%, transparent 72%);
      pointer-events: none;
    }

    .needs-prototype-tile img,
    .needs-prototype-row img {
      display: block;
      width: 100%;
      height: 100%;
      object-fit: cover;
      transition: transform var(--dur-slow) var(--ease-out);
    }

    .needs-prototype-tile .needs-prototype-media {
      aspect-ratio: 16 / 9;
    }

    .needs-prototype-copy,
    .needs-prototype-tile-copy {
      display: flex;
      flex-direction: column;
      min-height: 290px;
      padding: clamp(22px, 2.4vw, 30px);
    }

    .needs-prototype-copy small,
    .needs-prototype-row-copy small { color: var(--label); font-size: .82rem; font-weight: 700; line-height: 1.45; }
    .needs-prototype-copy strong { margin: 12px 0 0; font-size: clamp(1.28rem, 1.7vw, 1.55rem); line-height: 1.3; text-wrap: balance; }
    .needs-prototype-copy em { flex: 1 1 auto; margin: 14px 0 0; color: var(--muted); font-size: .94rem; font-style: normal; line-height: 1.7; text-wrap: balance; }

    .needs-prototype-copy b,
    .needs-prototype-row-copy b,
    .needs-prototype-link {
      position: relative;
      display: inline-flex;
      align-self: flex-start;
      max-width: calc(100% - 1.5em);
      margin-top: 24px;
      color: var(--ink);
      font-size: .92rem;
      font-weight: 700;
      white-space: nowrap;
    }

    .needs-prototype-copy b::after,
    .needs-prototype-row-copy b::after,
    .needs-prototype-link::after { content: ""; position: absolute; inset-inline: 0; bottom: -5px; block-size: 2px; background: currentColor; transform-origin: right; transform: scaleX(.38); transition: transform var(--dur-base) var(--ease-out); }
    .needs-prototype-copy b i,
    .needs-prototype-row-copy b i,
    .needs-prototype-link i { position: absolute; inset-inline-end: -1.45em; opacity: 0; transform: translateX(7px); transition: opacity 180ms var(--ease-out), transform 240ms var(--ease-out); }

    .needs-prototype-tile:is(:hover, :focus-visible) img,
    .needs-prototype-row:is(:hover, :focus-visible) img { transform: scale(var(--zoom)); }
    .needs-prototype-tile:is(:hover, :focus-visible) b::after,
    .needs-prototype-row:is(:hover, :focus-visible) b::after,
    .needs-prototype-tile:is(:hover, :focus-visible) .needs-prototype-link::after,
    .needs-prototype-row:is(:hover, :focus-visible) .needs-prototype-link::after { transform: scaleX(1); }
    .needs-prototype-tile:is(:hover, :focus-visible) b i,
    .needs-prototype-row:is(:hover, :focus-visible) b i,
    .needs-prototype-tile:is(:hover, :focus-visible) .needs-prototype-link i,
    .needs-prototype-row:is(:hover, :focus-visible) .needs-prototype-link i { opacity: 1; transform: none; }

    .needs-prototype-stream { display: grid; gap: clamp(24px, 3vw, 40px); margin-top: clamp(38px, 5vw, 64px); }

    .needs-prototype-row {
      display: grid;
      grid-template-columns: minmax(360px, 1.1fr) minmax(320px, .9fr);
      align-items: stretch;
      min-width: 0;
      color: var(--ink);
      text-decoration: none;
    }

    /* Horizontal alternative: every route uses the same 16:9 image field.
       The identity cuts are deliberately warm-white and translucent, so they
       belong to the page surface rather than competing with the photography. */
    .needs-prototype-row-media {
      min-height: 0;
      aspect-ratio: 16 / 9;
    }

    .needs-prototype-row-media::after {
      background: linear-gradient(180deg, rgba(23, 22, 20, .04), rgba(23, 22, 20, .16));
    }

    .needs-prototype-row-media::before {
      inset-block: -12%;
      inset-inline-start: -7%;
      width: 70%;
      background: linear-gradient(108deg,
        transparent 0 19%, rgba(250, 246, 239, .38) 19% 23%,
        transparent 23% 43%, rgba(201, 151, 55, .16) 43% 49%,
        transparent 49% 69%, rgba(220, 105, 40, .12) 69% 76%, transparent 76%);
    }

    .needs-prototype-row:nth-child(1) .needs-prototype-row-media::before {
      width: 38%;
      background: linear-gradient(108deg, transparent 0 42%, rgba(250, 246, 239, .42) 42% 49%, transparent 49%);
    }

    .needs-prototype-row:nth-child(2) .needs-prototype-row-media::before {
      width: 56%;
      background: linear-gradient(108deg, transparent 0 25%, rgba(250, 246, 239, .38) 25% 32%, transparent 32% 57%, rgba(201, 151, 55, .14) 57% 64%, transparent 64%);
    }

    .needs-prototype-row:nth-child(3) .needs-prototype-row-media::before {
      width: 73%;
    }

    .needs-prototype-row:nth-child(4) .needs-prototype-row-media::before {
      inset-inline-start: 30%;
      width: 46%;
      background: linear-gradient(108deg, transparent 0 25%, rgba(250, 246, 239, .42) 25% 33%, transparent 33% 58%, rgba(220, 105, 40, .12) 58% 65%, transparent 65%);
    }

    .needs-prototype-row-copy {
      position: relative;
      z-index: 2;
      display: flex;
      flex-direction: column;
      align-self: center;
      min-height: min(74%, 300px);
      margin-inline-start: clamp(-96px, -7vw, -44px);
      padding: clamp(30px, 4vw, 58px);
      background: #fff;
      box-shadow: none;
    }

    .needs-prototype-row-copy strong { margin: 12px 0 0; font-size: clamp(1.55rem, 2.4vw, 2.35rem); line-height: 1.2; text-wrap: balance; }
    .needs-prototype-row-copy > small {
      display: inline-flex;
      align-self: flex-start;
      padding: 6px 10px;
      border-radius: var(--r);
      background: var(--surface-sunken);
      color: var(--brand-jais);
      font-size: .78rem;
      font-weight: 800;
      line-height: 1.35;
    }
    .needs-prototype-row-copy em {
      margin: 18px 0 0;
      color: var(--muted);
      font-style: normal;
      line-height: 1.8;
      text-wrap: balance;
    }
    .needs-prototype-row-copy b,
    .needs-prototype-row .needs-prototype-link { margin-top: auto; padding-top: 26px; }

    @media (max-width: 700px) {
      .needs-prototype-grid { grid-template-columns: 1fr; }
      .needs-prototype-row { grid-template-columns: 1fr; }
      .needs-prototype-row-copy { margin: -36px 18px 0; min-height: 0; }
    }

    @media (prefers-reduced-motion: reduce) {
      .needs-prototype-tile img,
      .needs-prototype-row img,
      .needs-prototype-link,
      .needs-prototype-link i { transition: none; }
    }

    /* Direct routes: approved horizontal composition. The former grid and
       review alternatives have been consolidated into this one live pattern:
       a calm warm background, a concise centred introduction and four
       substantial routes. Each route uses a 16:9 photographic field with a
       compact white panel overlapping it for a stronger editorial rhythm. */
    .needs {
      /* This section uses the same vertical cadence as the rest of the site so
         the introductory space never becomes visually heavier than its content. */
      padding-block: var(--sec-pad);
      background: var(--surface-sunken);
      color: var(--ink);
    }

    .needs-layout { display: block; }

    /* The section head starts at the content edge like every other one on the
       page, instead of being centred on its own. All three properties are
       logical, so this is right in Arabic and left in the English mirror
       without a second rule: text-align: start, margin-inline: 0 rather than
       auto, and flex-start on the kicker row. The 760px cap stays - it limits
       the line length, it was never what centred the block. */
    .needs-intro {
      max-width: 760px;
      margin-inline: 0;
      padding: 0;
      text-align: start;
    }

    .needs-intro .kicker { justify-content: flex-start; }
    .needs-intro h2 {
      max-width: none;
      margin: 14px 0 12px;
      font-size: clamp(2.25rem, 4.4vw, 3.55rem);
      line-height: 1.16;
    }
    .needs-intro p { max-width: 55ch; margin-inline: 0; }

    .needs-routes {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--sec-head-gap);
      margin-top: var(--sec-head-gap);
    }

    .needs-route {
      display: grid;
      grid-template-columns: minmax(0, 1fr);
      grid-template-rows: minmax(clamp(330px, 40vw, 470px), auto);
      align-items: center;
      min-height: clamp(330px, 40vw, 470px);
      direction: ltr;
      color: var(--ink);
      background: transparent;
      isolation: isolate;
    }

    .needs-route-media {
      grid-area: 1 / 1;
      justify-self: end;
      align-self: center;
      z-index: 1;
      width: min(72%, 800px);
      min-height: 0;
      aspect-ratio: 16 / 9;
      background: var(--surface-sunken);
    }

    .needs-route:nth-child(even) .needs-route-media { justify-self: start; }

    .needs-route-copy {
      grid-area: 1 / 1;
      justify-self: start;
      direction: rtl;
      position: relative;
      z-index: 3;
      align-self: center;
      width: min(48%, 520px);
      min-height: 0;
      margin: 0;
      padding: clamp(28px, 3.4vw, 46px);
      background: var(--surface-raised);
      box-shadow: none;
      overflow: hidden;
      border-radius: var(--r);
    }

    .needs-route:nth-child(even) .needs-route-copy { justify-self: end; }

    .needs-route-audience {
      display: inline-flex;
      align-self: flex-start;
      width: fit-content;
      margin: 0;
      padding: 6px 10px;
      background: var(--surface-sunken);
      color: var(--brand-jais);
      font-size: .78rem;
      font-weight: 800;
      line-height: 1.35;
    }
    .needs-route-copy > strong {
      min-block-size: 0;
      margin: 14px 0 0;
      color: var(--ink);
      font-size: clamp(1.55rem, 2.4vw, 2.35rem);
      font-weight: 400;
      line-height: 1.2;
      text-wrap: balance;
    }
    .needs-route-copy > em {
      flex: 0 1 auto;
      min-block-size: 0;
      margin: 18px 0 0;
      color: var(--muted);
      font-size: 1rem;
      font-style: normal;
      line-height: 1.8;
      text-wrap: balance;
    }
    /* A fixed content gap keeps every route action visible instead of letting a
       stretched panel push it out of view at taller desktop breakpoints. */
    .needs-route-action { align-self: flex-start; margin-top: clamp(18px, 2vw, 26px); padding-top: 0; }

    @media (max-width: 700px) {
      .needs-route {
        display: flex;
        flex-direction: column;
        min-height: 0;
      }
      .needs-route-media { width: 100%; aspect-ratio: 16 / 9; }
      .needs-route-copy {
        width: calc(100% - 36px);
        margin: -42px auto 0;
        min-height: 0;
      }
    }
    /* Footer markup uses .foot-socials. Keep the social links visibly
       interactive without changing the footer layout or their hit area. */
    .foot-socials {
      display: flex;
      align-items: center;
      gap: 16px;
    }

    .foot-socials a {
      inline-size: 40px;
      block-size: 40px;
      display: grid;
      place-items: center;
      /* No outline on the tile. The system separates surfaces by tone, not by
         a line, and on the footer's true black a .3 white hairline was the
         most visible thing in the row. The .08 fill is the tone step, and it
         is what the hover state grows out of. */
      border: 0;
      border-radius: var(--r);
      color: var(--icon-on-dark);
      background: rgba(255, 255, 255, .08);
      transition: background-color var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out),
        transform var(--dur-fast) var(--ease-out);
    }

    .foot-socials a:is(:hover, :focus-visible) {
      background-color: var(--brand-razeen);
      color: var(--brand-black);
      transform: scale(1.06);
    }

    .foot-socials i.ph {
      font-size: var(--ic-sm);
      line-height: 1;
    }

    /* The homepage navigation exposes its two real content hierarchies without
       sending visitors to placeholder pages. */
    .menu > .nav-disclosure {
      position: relative;
      flex: 0 0 auto;
    }

    /* Chromium's anonymous details-content wrapper has zero block-size when
       its only child is the absolutely positioned desktop panel. Its default
       overflow would otherwise clip the open hierarchy. */
    .nav-disclosure[open]::details-content {
      overflow: visible;
    }

    @supports selector(.nav-disclosure::details-content) {
      @media (min-width: 1281px) {
        .nav-disclosure[open]::details-content {
          position: absolute;
          z-index: 4;
          inset-block-start: 100%;
          inset-inline-start: 0;
        }

        .nav-disclosure[open] > .nav-submenu {
          position: relative;
          z-index: auto;
          inset-block-start: 10px;
          inset-inline-start: auto;
        }
      }
    }

    .nav-disclosure > summary {
      min-block-size: 44px;
      display: flex;
      align-items: center;
      gap: 6px;
      padding-inline: 6px;
      color: #fff;
      font-size: clamp(.86rem, .95vw, .95rem);
      font-weight: 500;
      white-space: nowrap;
      list-style: none;
      cursor: pointer;
      /* The open trigger takes the Sweihan fill. That is a colour change, so it
         runs on --dur-fast, the step the token file reserves for colour. */
      transition:
        background var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .nav-disclosure > summary::-webkit-details-marker {
      display: none;
    }

    /* The label is a direct link inside the summary; keep its generic
       nav-link underline from duplicating the summary state line. */
    .nav-disclosure > summary > a::after {
      display: none;
    }

    .nav-disclosure > summary::after {
      content: "";
      position: absolute;
      inset-inline-start: 0;
      inset-block-end: 2px;
      inline-size: 0;
      block-size: 1.5px;
      background: var(--accent);
      transition: inline-size var(--dur-base) var(--ease-out);
    }

    .nav-disclosure > summary i.ph {
      font-size: var(--ic-xs);
      transition: transform var(--dur-fast) var(--ease-out);
    }

    .nav-disclosure:is([open], :has(.nav-submenu a.active)):not(.is-closing) > summary::after {
      inline-size: 100%;
    }

    .nav-disclosure[open]:not(.is-closing) > summary i.ph {
      transform: rotate(180deg);
    }

    /* No fill on the open trigger. The underline is already the open signal,
       and it is the one every other item in the bar uses, so a filled block
       here gave the dropdown trigger a second, louder vocabulary of its own.
       The chevron rotation is the other half of the signal. en/index.html has
       never carried a fill here; this is the Arabic side coming into line
       with it and with the sub-pages. The drawer below keeps its fill: at
       that width the underline is display:none. */
    .nav-disclosure[open]:not(.is-closing) > summary {
      background: transparent;
    }

    .nav-disclosure > summary:focus-visible {
      outline: 3px solid var(--brand-razeen);
      outline-offset: 3px;
    }

    header.scrolled .nav-disclosure > summary {
      color: var(--ink);
    }

    /* One rule for every dropdown, both hierarchies and both viewports: a white
       panel, rows separated by space, and the fill as the only state signal
       WITHIN the panel. This is the same decision already documented for the
       tab lists, so the navigation stops being the one place that also draws
       divider lines between rows.
       The panel's own edge is a separate question: a pure-white #fff panel
       drawn on a --surface-raised (also #fff) section - a scrolled header
       over a white "pad--raised" block, for one - has no edge at all. No
       box-shadow per the token file; the site's elevation is tonal-step, so
       this is the same 1px --line hairline every raised card and form field
       already uses for the same separation. */
    .nav-submenu {
      position: absolute;
      z-index: 4;
      inset-block-start: calc(100% + 10px);
      inset-inline-start: 0;
      min-inline-size: var(--nav-submenu-min);
      inline-size: max-content;
      display: flex;
      flex-direction: column;
      gap: 2px;
      padding: 8px;
      background: #fff;
      border: 1px solid var(--line);
      border-radius: var(--r);
    }

    .menu .nav-submenu a {
      min-block-size: 42px;
      padding-inline: 12px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      color: var(--ink);
      font-size: .88rem;
      white-space: normal;
      transition:
        background-color var(--dur-fast) var(--ease-out),
        color var(--dur-fast) var(--ease-out);
    }

    .nav-submenu-hover-icon {
      flex: 0 0 1em;
      color: inherit;
      font-size: 1em;
      line-height: 1;
      opacity: 0;
      pointer-events: none;
      transform: translateX(4px);
      transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-base) var(--ease-out);
    }

    .menu .nav-submenu i.nav-submenu-hover-icon { font-size: 1em !important; }

    .menu .nav-submenu a:is(:hover, :focus-visible) .nav-submenu-hover-icon {
      opacity: 1;
      transform: translateX(0);
    }

    .nav-submenu--companies .company-nav-link {
      justify-content: flex-start;
      gap: 12px;
    }

    .company-nav-mark {
      /* V3 geometry: a dedicated 96px logo column, 32px-high container,
         reading-start aligned. */
      inline-size: 96px;
      block-size: 32px;
      display: grid;
      place-items: center start;
      flex: 0 0 96px;
      overflow: hidden;
    }

    .company-nav-mark svg {
      inline-size: 31px;
      block-size: 26px;
    }

    .company-nav-mark--eskan {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      gap: 3px;
    }

    .company-nav-mark--eskan svg {
      inline-size: 20px;
      block-size: 25px;
      flex: 0 0 20px;
    }

    .company-nav-mark--eskan b,
    .company-nav-mark--eskan small {
      display: block;
      color: var(--brand-black);
      font-family: var(--font-display);
      line-height: 1;
    }

    .company-nav-mark--eskan b { font-size: .72rem; }
    .company-nav-mark--eskan small { margin-top: 2px; font-size: .54rem; }

    .company-nav-mark img {
      /* Height-led sizing so every mark keeps its own aspect ratio inside the
         32px container; width follows height and is capped by the 96px column
         (V3 per-brand heights below). */
      inline-size: auto;
      block-size: 30px;
      max-inline-size: 100%;
      object-fit: contain;
      object-position: left center;
    }

    /* V3 per-brand logo heights (Arabic/RTL default). */
    .company-nav-mark--eskan img { block-size: 28px; }
    .company-nav-mark--khadamat img { block-size: 30px; }
    .company-nav-mark--zoad img { block-size: 28px; }
    .company-nav-mark--laundry img { block-size: 17px; }

    .company-nav-mark--khadamat {
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: .72rem;
      font-weight: 600;
      line-height: 1;
      text-align: center;
    }

    .company-nav-mark--khadamat small {
      display: block;
      margin-top: 2px;
      font-size: .58rem;
    }
    .company-nav-mark--laundry {
      color: var(--brand-black);
      font-family: var(--font-display);
      font-size: .7rem;
      font-weight: 600;
      line-height: 1;
      text-align: center;
    }

    .company-nav-link .nav-submenu-hover-icon { margin-inline-start: auto; }

    /* Desktop dropdown. The panel is a floating surface, so it moves through
       opacity and transform only, on --dur-base and the single easing curve.
       The movement itself is driven from the script (see setDisclosure); what
       stays here is the part that is a state, not a frame. */
    @media (min-width: 981px) {
      /* A panel on its way out must not answer the pointer, or a hover that is
         leaving would immediately re-open it. */
      .nav-disclosure.is-closing {
        pointer-events: none;
      }

      .nav-disclosure.is-closing > .nav-submenu {
        pointer-events: none;
      }

      /* Bridges the 10px gap under the trigger, so travelling down into the
         panel is never read as leaving the trigger. Invisible by design: it
         adds reach, not a surface. */
      .nav-submenu::before {
        content: "";
        position: absolute;
        inset-inline: 0;
        inset-block-end: 100%;
        block-size: 10px;
      }
    }

    .menu .nav-submenu a::after {
      display: none;
    }

    .menu .nav-submenu a:is(:hover, :focus-visible, .active) {
      background: var(--accent);
      color: #fff;
    }

    .menu .nav-submenu a:focus-visible {
      outline: 3px solid var(--brand-razeen);
      outline-offset: -3px;
    }

    /* Same reason as section[id] above: 104 was tuned to the old compressed
       bar and is now only 5px clear of the floating pill's 99.31px bottom. */
    .sector-card[id],
    .company-card[id] {
      scroll-margin-top: 124px;
    }

    @media (max-width: 1280px) {
      .menu > .nav-disclosure {
        inline-size: 100%;
        border-block-end: 1px solid var(--line);
        opacity: 0;
        transform: translateX(10px);
        transition:
          opacity var(--dur-base) var(--ease-out),
          transform var(--dur-base) var(--ease-out);
      }

      .menu.open > .nav-disclosure {
        opacity: 1;
        transform: translateX(0);
      }

      .nav-disclosure > summary {
        min-block-size: 54px;
        padding-inline: 4px 12px;
        justify-content: space-between;
        color: var(--ink);
        font-family: var(--font-display);
        font-size: 1.05rem;
        font-weight: 600;
      }

      .nav-disclosure > summary::after {
        display: none;
      }

      .nav-disclosure[open]:not(.is-closing) > summary {
        background: var(--accent);
        color: #fff;
      }

      .nav-submenu {
        position: static;
        inline-size: 100%;
        padding: 4px 14px 12px;
        background: #fff;
        border-block-start: 0;
        border-inline-start: 0;
        border-radius: var(--r);
      }

      .menu .nav-submenu a {
        min-block-size: 44px;
        padding-inline: 10px;
        font-size: .92rem;
      }

      /* The drawer panel is in flow and has to push the rows under it, so it
         animates its measured height where the desktop panel only fades and
         travels. Clipping is what makes that height readable as a reveal; the
         movement itself is driven from the script (see setDisclosure). */
      .menu .nav-submenu {
        overflow: hidden;
      }
    }

    @media (prefers-reduced-motion: reduce) {
      .nav-disclosure,
      .nav-disclosure > summary,
      .nav-submenu-hover-icon,
      .nav-disclosure > summary i.ph {
        transition: none !important;
      }
    }

    } /* end @layer legacy */

    /* =========================================================================
       SYSTEM LAYER
       -------------------------------------------------------------------------
       Unlayered on purpose, so every rule here beats all of @layer legacy above
       without !important and without depending on source order. This is the one
       place a design-system role is asserted for the whole page.

       Add a rule here only if it is a ROLE that should hold at every viewport.
       Anything conditional belongs inside @layer legacy with its component.
       ====================================================================== */

    /* --- Identity line colour: one mark, one tone ----------------------------
       The diagonal "line" motif borrowed from the logo's own slanted bars used
       to draw from several different sources per component (--watermark-1/2/3,
       which is Sweihan-based, plus one-off Liwa/Sweihan/Al Khatim/white mixes on
       the project feature card). Recoloured here to Razeen, the softer honey
       tone in the logo's own cut, so every diagonal line on the page reads as
       one identity mark. Local to this page only: sdeira-tokens.css's shared
       --watermark-* tokens stay Sweihan-based for the pages still using them. */
    :root {
      --line-mark-1: var(--brand-razeen);
      --line-mark-2: color-mix(in srgb, var(--brand-razeen) 68%, transparent);
      --line-mark-3: color-mix(in srgb, var(--brand-razeen) 44%, transparent);
    }

    /* --- Company card: one radius, and the corner mark stays inside ----------
       The mark is sized past the card's own corner on purpose, but the card
       clips it rather than letting it bleed onto its neighbours in the tight
       2-column grid. overflow: hidden is what the legacy
       .company-card, .service-card rule already sets; restated here with the
       radius so both hold regardless of which of .company-card's several
       redeclarations in @layer legacy happens to cascade last. */
    .company-card {
      overflow: hidden;
      border-radius: var(--r);
    }

    /* --- Company card corner mark: bottom-LEFT on the Arabic homepage ---------
       sdeira-sections.css's shared `.company-card .card-chevron.card-chevron
       { inset: auto 0 0 auto }` pins the sticker to the bottom-RIGHT physical
       corner for every company card, but the approved p.43 mark anchors in the
       corner furthest from reading start - bottom-LEFT in RTL. That shared
       rule is unlayered and loads after this file, so only a higher-specificity
       unlayered rule (an id beats its classes) can move it here. The wipe below
       grows from the same bottom-left corner, so sticker and fill stay paired. */
    #companies .companies-grid .company-card .card-chevron {
      inset: auto auto 0 0;
      right: auto;
      left: 0;
    }

    /* --- Project meta follows the surface it sits on --------------------------
       .row-item-meta (sdeira-sections.css) sets colour: var(--label) directly
       on the element the text and the icon both live in, and it is unlayered,
       so it always wins over the @layer legacy rules that turn
       .project-card--feature/.project-card--secondary:hover white regardless
       of specificity. The icon needs its own line too - i.ph sets colour
       directly on itself rather than inheriting - but the label text
       ("Mussafah, Abu Dhabi") was reported still reading Jais-dark on the
       feature card's photo scrim even after the icon was fixed, because the
       icon-only version of this rule never touched the parent. Site owner
       flagged, 12 Aug 2026. */
    .project-card--feature .project-meta,
    .project-card--secondary:is(:hover, :focus-within) .project-meta,
    .project-card--feature .project-meta i.ph,
    .project-card--secondary:is(:hover, :focus-within) .project-meta i.ph {
      color: var(--brand-white);
    }

    /* The rule above is written for the feature card's normal dark-scrim
       state and doesn't know about .is-filtered-view, so once that state
       demotes the card to the same white surface as its siblings, the (also
       unlayered, so equally undefeated by anything in @layer legacy) white
       rule above kept winning by being later/more specific - meta text and
       icon stayed white on white. Same fix shape as the .project-type one
       below: a higher-specificity unlayered override for the filtered state
       specifically, matching the surviving secondary card's own --icon/--label
       tokens instead of the dark-surface white. Found by diffing every
       computed property against .project-card--secondary. Site owner
       flagged, 12 Aug 2026. */
    .project-cards.is-filtered-view .project-card--feature .project-meta,
    .project-cards.is-filtered-view .project-card--feature .project-meta i.ph {
      color: var(--icon);
    }

    .project-cards.is-filtered-view .project-card--feature:is(:hover, :focus-within)
      .project-meta,
    .project-cards.is-filtered-view .project-card--feature:is(:hover, :focus-within)
      .project-meta i.ph {
      color: var(--brand-white);
    }

    /* .project-card--feature .project-type (further down this file) sets
       --badge-text-on-dark unconditionally for the same reason as the meta
       rule above - written for the normal dark-scrim state, unlayered, so it
       keeps winning even once .is-filtered-view puts this card on a white
       surface where the secondary card's kicker actually reads --badge-text
       (the accent-strong orange), not the on-dark gold. Site owner flagged,
       12 Aug 2026. */
    .project-cards.is-filtered-view .project-card--feature .project-type {
      color: var(--badge-text);
    }

    /* --- A filtered-out project card must actually disappear ------------------
       .project-card.is-filtered-out { display: none; } lives in @layer legacy
       (the filter is toggled by JS, .project-cards.is-filtered-view above it).
       sdeira-sections.css's .project-card-base.project-card-base sets
       display: flex at equal specificity and loads after sdeira-v2.css, and it
       carries no @layer - same rule as the icon fix above: unlayered always
       beats layered regardless of specificity or source order. The card never
       collapsed: it kept flex layout and its grid track, so a filter for one
       type still rendered every card, including ones tagged for a different
       type. Doubling the class matches sdeira-sections.css's own specificity
       trick rather than reaching for !important. Site owner flagged, 12 Aug
       2026 (a "Ù…Ø´Ø±ÙˆØ¹ Ù…Ø¹Ù„Ù†" card surviving the "Ø¥Ø¯Ø§Ø±Ø© Ø§Ù„Ø¹Ù‚Ø§Ø±Ø§Øª" filter).
       Verified: filteredOut card now computes display: none and 0 width. */
    .project-card.is-filtered-out.is-filtered-out {
      display: none;
    }

    /* --- Filtered view demotes the feature card to the same white surface as
       its siblings (.project-cards.is-filtered-view .project-card--feature,
       @layer legacy) and turns its text --brand-black to match - but the icon
       rule two blocks up forces the icon white unconditionally, for the
       feature card's normal dark-scrim state. In the filtered view that left
       a white icon on the same white surface the demotion just switched it
       to: invisible, same failure shape as the one just above. The surviving
       secondary card in this same view already renders its icon in --icon
       (Jais) via sdeira-sections.css's default .row-item-meta i.ph, so this
       matches its sibling rather than inventing a new tone. Site owner
       flagged, 12 Aug 2026 ("Ø§Ù„Ø¨Ø±Ø¨Ø±ØªÙŠ Ù…Ù†Ø¬Ù…Ù†Øª Ø§ÙˆÙ„ ÙƒØ±Øª Ù…Ø®ØªÙ„ÙØ© Ø¨Ø´ÙƒÙ„ ÙƒØ§Ù…Ù„"). */
    .project-cards.is-filtered-view .project-card--feature .project-meta i.ph {
      color: var(--icon);
    }

    /* --- Company card: one decoration, not two -------------------------------
       ::before was the sdeira-mark watermark in the top-left corner. The card
       now carries .card-chevron instead, and two brand marks on one card read
       as clutter rather than as identity - the decorative vocabulary allows
       one mark per surface. Retired here rather than at any of its four
       redeclarations in @layer legacy, because unlayered is the only place
       that holds regardless of which of them cascades last. The hover cue it
       used to provide moved with it: .card-chevron carries the same step. */
    .company-card::before {
      display: none;
    }

    /* --- Paused auto-rotation ------------------------------------------------
       The rail fill runs as its own CSS animation, so stopping the JS timer
       alone would leave the bar filling and then sitting full while nothing
       advanced: the pause would read as a fault. Holding the fill where it is
       makes the paused state legible. Unlayered so it holds at every viewport,
       which is where the rail is defined more than once. */
    .hero.is-slider-paused .hero-slide-line.active::before {
      animation-play-state: paused;
    }

    /* --- Type roles: headings ------------------------------------------------
       One semantic heading level, one responsive size across the homepage. This
       retires the earlier section-specific type sizes without changing layout or
       content structure. The !important flags these rules used to carry are gone:
       being unlayered is enough. */
    h1, .type-display { font-size: var(--type-display); line-height: var(--leading-display); }
    h2, .type-section { font-size: var(--type-section); line-height: var(--leading-section); }

    /* --- Type roles: everything that is not a heading ------------------------
       303 local font-size declarations on this page, and only the two heading
       rules above had a role. The rest was written per component, over many
       passes, which is why the same job carried seven different values: body
       copy alone ran .9 / .94 / .95 / .96 / .98 / 1 / 1.04rem.

       Each selector below was attributed in the browser to the exact rule that
       was winning for it, and every one of those rules turned out to be
       unconditional. That matters: a size a narrow viewport genuinely needed
       would sit inside an @media block, so an unconditional spread is drift, and
       snapping it to a role is a correction rather than a redesign. The role
       values are the measured dominant of what each group already rendered, so
       the largest single change here is about 1.6px.

       Specificity does the routing: `p` takes body, and the more specific lead
       selectors below beat it. Both live in this unlayered section, so neither
       needs !important.

       DELIBERATE EXCLUSIONS
       - `small` is not styled as a role. Four of them are parts of a wordmark
         lockup (.company-logo small, .company-nav-mark--* small at .54 to
         .72rem) where the size is the logo's proportion, not a text size.
       - .story-year, .impact-number, .partner-stat strong and the other large
         figures are the --figure role, not text. Untouched.
       - i.ph icons follow the icon scale in the token file. Untouched. */

    /* Lead: the one intro paragraph that follows a section heading. */
    :is(.sec-head, .impact-head, .process-head, .story-head, .partners-head,
        .news-head, .projects-copy, .value-head, .needs-intro, .needs-prototypes-intro,
        .impact-alt-copy, .about-copy, .cta-inner, .hero-content-copy, .sector-hover-copy) p,
    .hero p,
    .cta p,
    .type-lead {
      font-size: var(--type-lead);
      line-height: var(--leading-lead);
    }

    /* Body: running copy anywhere in the page or the footer brand block. */
    main p,
    footer .foot-brand p,
    .type-body {
      font-size: var(--type-body);
      line-height: var(--leading-body);
    }

    /* Action: buttons and inline action links inside page content. */
    :is(.btn, .more, .section-view-all, .news-all, .news-form button,
        .projects-footer-cta, .sector-feature-link, .needs-route-action,
   .news-card .more, .project-filter, .news-filter,
        .project-tab, .foot-col a, .foot-col .foot-pending, .needs-prototype-link),
    .cta-action > span:not(.cta-action-note),
    .type-action {
      font-size: var(--type-action);
      color: white;
    }

    /* Control: compact chrome. Kept as its own tier because folding it into the
       action role would grow the header controls by 16 to 25 percent and put the
       navigation at risk of wrapping at the widths where it is already tight. */
    :is(.menu > a, .nav-cta, .lang, .menu-lang, .menu-contact, .sector-card-action,
        .nav-disclosure > summary, .menu .nav-submenu a),
    .type-control {
      font-size: var(--type-control);
    }

    /* Meta: kickers, eyebrows, category labels and data rows. Same grouping the
       --label colour role uses, so size and colour describe one thing. */
    :is(.kicker, .impact-kicker, .process-kicker, .story-kicker, .partners-kicker,
        .sector-feature-kicker, .eyebrow, .project-type, .news-category,
        .needs-route-audience, .partner-domain, .impact-note, .impact-label,
        .service-card .service-meta, .service-pending, .hero-sectors-label),
    .news-card .date,
    .impact-alt-stat p,
    .type-meta {
      font-size: var(--type-meta);
    }

    /* Caption: fine print. Notes and the copyright line. */
    :is(.copy, .cta-action-note),
    .type-caption {
      font-size: var(--type-caption);
    }

    /* --- Card badges: primary orange, no fill --------------------------------
       The small category label inside a repeated card. Every one of them now
       carries the primary action orange with no background at all: no fill, no
       padding, no border. The colour and the weight are the whole treatment.

       .needs-route-audience was the only one that actually had a chip behind it
       (a Silver fill with 6px/10px padding). That fill is removed here, which is
       what "no background" means for it specifically.

       .impact-label and .needs-prototype-copy small are in the selector but do
       not render today: both live inside sections that are currently hidden from
       the visitor. They are included so those sections match the rest the moment
       they go live, rather than being missed later.

       WHAT IS NOT INCLUDED, and why. Section kickers (.kicker and its family)
       are section headings, not card badges, so they keep the neutral --label
       tone. Putting the brand colour on those as well would roughly double the
       count and is the density problem section 4b of the token file describes.
       Say the word and it is one selector.

       TWO MEASURED FACTS THAT THE REQUEST CANNOT OVERRIDE, both recorded in the
       token file next to --badge-text:

       1. This does not clear AA. Sweihan measures 3.35 on White, 3.06 on Cloud,
          2.80 on Silver and 3.08 on the dark feature card, all at 13.12px. AA
          needs 4.5 for normal text, and the 3.0 allowance is for large text
          only. The one-line switch to --warn-text clears it on all three light
          surfaces and still reads as the same orange.

       2. The bold cannot render. Only the Regular weight of DIN Next LT Arabic
          is licensed, all five @font-face slots point at that one file, and the
          html rule carries font-synthesis: none so the browser cannot fake a
          heavier face, because a synthesised bold distorts the joins in Arabic.
          Measured: the same Arabic string renders 65.96px wide at every weight
          from 300 to 900. Most of these badges already declared 700 or 800 and
          it was doing nothing. --badge-weight is set to the top of the scale so
          they thicken by themselves the day the licensed Bold file arrives. */
    :is(.project-type,
        .news-card .date,
        .needs-route-audience,
        .partner-domain,
        .service-card .service-meta,
        .impact-label,
        .needs-prototype-copy small) {
      color: var(--badge-text);
      background: var(--badge-fill);
      /* The size is part of the role now, and it is asserted here for the same
         reason the colour is: these selectors each carried their own
         font-size, which is how the badge ended up as the smallest text on
         the page while wearing the loudest colour. --badge-size resolves to
         --type-action, one step up the same scale. */
      font-size: var(--badge-size);
      font-weight: var(--badge-weight);
      padding: 0;
      border: 0;
    }

    /* The clock glyph in front of a news date was still on the neutral --icon
       role while the date text itself carries the badge orange, so the pair
       read as two different things. currentColor ties the glyph to whatever
       the date is, here and if the badge role ever changes. */
    .news-card .date::before {
      color: currentColor;
    }

    /* --- Filled dropdown item: the label is white ----------------------------
       An active item in a nav dropdown paints the Sweihan fill and then wrote
       its label in brand Black, which is the one colour that has no business
       sitting on that fill. It was a specificity accident, not a decision:

         .menu .nav-submenu a:is(:hover, :focus-visible, .active)   (0,3,1)
         header.scrolled .menu a.active                             (0,3,2)  wins

       The second rule is for the top-level nav item, where an active label on
       the scrolled white header should indeed be dark. It was never meant to
       reach inside the dropdown, but a submenu link is also `.menu a.active`,
       so it did - and only after the header gained .scrolled, which is why the
       item looked correct on a page still at the top and wrong once scrolled.

       Being unlayered is what fixes it. Out-specifying the header rule would
       mean guessing at a selector that stays ahead of it; the system layer wins
       by position, so the rule can stay the plain statement of the role.

       Contrast, measured, not assumed: White on Sweihan is 3.35, which does not
       clear AA for normal text. Neither did what it replaced - brand Black on
       the same fill is 3.14, worse - so this is not a regression, and White is
       what every other filled Sweihan control on the page already uses
       (.btn-primary, .nav-cta, the open dropdown trigger). Clearing AA here
       means darkening the fill, which is a brand decision. */
    .menu .nav-submenu a:is(:hover, :focus-visible, .active) {
      color: var(--brand-white);
    }

    /* Subsidiary cards sit on pure White instead of the cream --surface-base,
       so the four read as one clean block against the section behind them.
       The tonal step that separates them from the page is the grid gap
       showing the darker surface through, not a shadow. */
    .company-card {
      background: var(--brand-white);
    }

    /* --- Sector card icon: fade out in place on hover ------------------------
       On hover the icon used to slide out through the top edge of the card. It
       was collateral damage from one rule:

         .hero-sectors .sector-card:is(:hover, :focus-within)
           :is(.sector-card-mark, .sector-card-title, .sector-card-sub)
           { transform: translateY(-40px) }

       That -40px exists for a real reason: the action link is absolutely
       positioned at the bottom and hidden at rest, so the copy has to move up to
       clear it. But the icon sits 17px from the top, so -40px puts it 23px past
       the edge, where `overflow: hidden` cuts it off mid-travel. The icon was
       never meant to be the thing that leaves.

       The title and the description keep the -40px, because that shift is what
       makes room for the link. Only the icon is separated out: it fades and
       settles slightly, and it cannot reach an edge because the whole movement
       is 6px against a 17px offset. scale keeps the fade from reading as a flat
       disappearance without adding travel.

       Durations come from the motion scale, not from new numbers: opacity on
       --dur-fast because the token file assigns that step to colour and opacity,
       transform on --dur-base because that step is for size and position. The
       icon is therefore fully invisible at 120ms, well before the 240ms drift
       ends, so the eye never sees it near the edge. */
    .hero-sectors .sector-card .sector-card-mark {
      transition:
        opacity var(--dur-fast) var(--ease-out),
        transform var(--dur-base) var(--ease-out),
        background var(--dur-fast) var(--ease-out);
    }

    .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-mark {
      opacity: 0;
      transform: translateY(-6px) scale(.94);
    }

    @media (prefers-reduced-motion: reduce) {
      .hero-sectors .sector-card .sector-card-mark {
        transition: none;
      }

      .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-mark {
        transform: none;
      }
    }

    /* Direction changes the action glyph, not the physical identity slant.
       These explicit endpoints keep a later component transform from reversing
       an Arabic arrow a second time. */
    [dir="rtl"] .hero-sectors .sector-card-action i.ph.icon--dir { transform: scaleX(-1); }
    [dir="ltr"] .hero-sectors .sector-card-action i.ph.icon--dir { transform: none; }

    /* --- Sector card description: reserve two lines --------------------------
       All five sector descriptions now occupy the same height, so their titles,
       icons and action links share one baseline across the strip.

       WHAT WAS WRONG
       The number of lines each description wrapped to changed per card AND per
       width, so the strip lost its alignment at most viewports. Measured line
       counts for the five cards, with the reservation neutralised:

         1920 / 1600   1 1 1 1 1
         1400          1 2 1 1 1
         1280          2 2 1 1 1
         1180 / 1024   2 2 2 1 2
         980 to 640    1 1 1 1 1
         480           2 2 1 1 1
         400           2 2 2 1 1
         360           2 2 2 2 1

       The reservation existed but was written five separate times, as
       min-height 3.1em (>=1600), 3.2em (<=720), 3em (<=720), 0 (<=980) and
       min-block-size 3.2em on .hero-sectors. The <=980 rule set it to 0, which
       cancelled it outright for every viewport below that. The em values
       disagreed because the line-height differs per breakpoint (1.6 / 1.55 /
       1.45) and each pass hand-converted "two lines" and landed on a different
       number.

       THE FIX
       One rule, expressed in lh so it is literally "two lines of whatever
       line-height this element has" and cannot fall out of step with the type
       role. The count itself is --card-sub-lines in the token file, where the
       reasoning lives.

       NO TRUNCATION. There is no line-clamp and no ellipsis. Across the fifteen
       widths above, no description wraps past two lines, so reserving is enough
       on its own and no copy is ever hidden from a visitor. The hard <br> that
       one card carried to force a second line is gone too: it broke the copy at
       a fixed point even at the widths where it fitted on one line. No wording
       changed, only that markup break.

       TWO PROPERTIES, TWO DIFFERENT JOBS
       max-inline-size is what MAKES the text wrap to two lines. Reserving the
       height alone left the short descriptions rendering on one line inside a
       two-line box, so the card kept a visible gap where the second line should
       be and the strip still read as uneven. Narrowing the measure is what
       actually produces the second line, and it is why the description block is
       now narrower than the card rather than filling it.

       min-block-size keeps the reservation as a floor, so a future copy edit
       that shortens a description back to one line cannot break the alignment
       again. Both values live in the token file with the measurements behind
       them. */
    .sector-card-sub {
      max-inline-size: var(--card-sub-measure);
      /*min-block-size: calc(var(--card-sub-lines) * 1lh);*/
      /* A tone step below the title, so the two read as heading and support
         rather than as one block of white. This is the system's secondary
         tone on dark, not a new value, and it is DECLARED rather than an
         opacity: the .94 it replaces was the stacked-transparency pattern the
         token file rules out, and at .94 it was not a visible step anyway.

         Legible because the veil was fixed in the same change: against the
         brightest region behind any description this measures 10.84, where
         the white it replaces measured 2.56 before that fix. */
      color: var(--muted-on-dark);
    }

    /* Hover still lifts it to full white, so the tone step reads as a resting
       state rather than as a permanently dimmer paragraph. */
    .sector-card:is(:hover, :focus-within) .sector-card-sub {
      color: var(--brand-white);
    }

    /* --- About visual: the shared master ratio, not a bespoke fixed height ---
       Site owner instruction, 15 Aug 2026: this panel moves onto
       var(--media-wide) (4:3), the same slot every token-driven page's
       .split-media already uses, instead of the fixed-px height mechanic this
       block used to carry (500px desktop, 430px <=560px, kept in one variable
       rather than five disagreeing declarations - see docs/ar-to-en-port-log.md
       history if that variable resurfaces). A proportional box replaces a
       fixed one: the image no longer clips to a constant height regardless of
       how wide its grid column gets, and this is no longer the one photo panel
       on the site with its own shape. */
    .about-visual {
      aspect-ratio: var(--media-wide);
    }

    .about-visual > img {
      height: 100%;
    }

/* --- Sector-hover media: the portfolio preview ratio ---------------------
   V3 change request: the preview panel is 16:9 again (measured 803x602 at
   1440px as 4:3, becomes 803x452 at 16:9). The base rule already says
   16/9; this unlayered override used to pin it to the shared --media-wide
   4:3 master, so it now matches the base instead of drifting. */
.sector-hover-visual {
  aspect-ratio: 16 / 9;
}

    /* needs-route-media is deliberately NOT on var(--media-wide): site owner
       reviewed the rendered 4:3 card, 16 Aug 2026, and asked for 16:9 back
       here specifically - at this card's own height (min-block-size clamp,
       up to 470px) the extra vertical room 4:3 adds made the whole card read
       taller than intended, unlike the shorter needs-prototype-media cousin
       these cards were compared against. See the matching business overview
       variant (.business-needs-routes .needs-route-media in
       sdeira-sections.css) and the design-system demo (.ds-route-card-media
       in design-system/ds.css), reverted the same way so the one component
       does not drift into two ratios. */

    /* --- About copy: kill a dormant auto margin -----------------------------
       The About paragraphs started up to 363px inside the column while the H2
       above them started flush at the edge, so the section read as if the copy
       had a large indent that appeared and disappeared with the viewport.

       Cause, and it is the documented cascade trap in this file rather than a
       styling choice. An early rule set

         .about-copy { max-width: 820px; margin-inline-start: auto; }

       and at the time 820px was wider than the column, so the auto margin
       resolved to 0 and did nothing. A later refinement pass narrowed the block
       to `max-width: 62ch` for a proper reading measure but never reset the
       margin. The auto then had leftover space to absorb, and absorbed all of
       it, pushing the block off the edge its heading sits on. Measured start gap
       before this fix: 32px at 1180, 89px at 1280, 144px at 1400, 136px at 1600,
       124px at 1920, and 363px at 980 where the layout is a single wide column.
       That is why it looked intermittent.

       62ch stays: a paragraph should not run the full 901px of the column. Only
       the margin is wrong, so only the margin is reset, and it is reset here so
       the value cannot be undone by a later breakpoint. Identical fix on the
       English mirror, which carried the same pair of rules. */
    .about-copy {
      margin-inline-start: 0;
    }

    /* NOT ROLES, and the reason each was ruled out after measuring it:
       - .verified-figure is clamp(2rem, 3.8vw, 3.7rem): the years and counts in
         the about block. It is the --figure role, not text. Styling it as a
         caption collapsed it from 48.6px to 12.5px, which is how it was caught.
       - .opening-status and the .opening-row cells carry no local font-size at
         all, so there is no drift to snap. Shrinking one cell of a data row
         while its siblings stay at 16px would make the row less consistent, not
         more. Sizing that row is a component decision, not a type-role fix.
       - .company-logo small, .company-nav-mark--eskan small and
         .company-nav-mark--khadamat small run .54 to .72rem because they are
         proportions inside a wordmark lockup, not text sizes. */

    /* ===== LINK HOVER: ONE COLOUR ROLE FOR THE WHOLE PAGE =====
       A text link and every icon inside it move to the warm accent together on
       hover and on keyboard focus. The icon needs no rule of its own: the two
       link families already inherit it (.sector-card-action i.ph is
       currentColor) and the growing underline is `background: currentColor`, so
       one colour declaration carries the word, the pictogram and the rule.

       Measured before this existed: 55 hover rules declaring a colour or a
       fill, across seven different values, with .btn-primary alone answered
       three separate times. This is the single place that decides it.

       Excluded on purpose, and each for a measured reason rather than a
       preference:
         - the filled buttons (.btn-primary, .nav-cta, .cta-action, the active
           drawer link). They sit ON the Sweihan fill, where the same orange
           measures 1.00 and vanishes. Fill plus tone step stays their state.
         - .logo and .menu-logo. Recolouring a logo on hover is a brand
           violation, not a hover state.
         - .news-image-link, which wraps a photograph and has no text to tint.
         - the icon-tile links (.socials a, .foot-socials a, .scroll-top). Their
           state is a fill on the tile, and they already have one.
         - the drawer and submenu links (.menu > a, .menu .nav-submenu a,
           .company-nav-link). Measured: their hover state is already a FILL,
           and .nav-submenu a fills with Sweihan itself, so orange text landed
           on orange at 1.00 and the label disappeared. Fill is their state.
         - .needs-route, which has its own rule below for the same reason as
           the drawer links: its copy panel fills on hover (#cb6c2e), and
           Sweihan on that fill measures 1.28. It is the card's surface that
           changed, so the role it belongs to changed with it. */
    :is(.action-link,
        .sector-card-action,
        .more,
        .section-view-all,
        .news-all):is(:hover, :focus-visible) {
      color: var(--link-hover);
    }

    /* The same role, resolved for the other surface family. Sweihan measures
       3.08 on Black #414042, so a link there would DIM on hover instead of
       lifting; Razeen measures 5.22 and is already the system's accent for dark
       surfaces. These are the links that sit on the dark cards, the dark scrim
       over photography, and the footer.

       The footer belongs here and it is easy to miss: its background is
       rgba(23, 22, 20, .8), which composites dark but is translucent, so a
       naive check for an opaque ancestor walks straight past it and reports the
       light page body underneath. .foot-contact was measured at Sweihan 3.06
       against that wrong surface before this was caught. */
    :is(.hero-sectors .sector-card-action,
        .project-card .action-link,
        .action-link.project-card-action,
        .foot-col a,
        .foot-contact,
        .skip-link):is(:hover, :focus-visible) {
      color: var(--link-hover-on-dark);
    }

    /* An icon inside a hovered link follows the link. Both families already
       inherit, but the footer contact icon is pinned to Razeen at rest, so it
       needs telling explicitly or the word moves and the pictogram does not. */
    :is(.action-link, .sector-card-action, .more, .needs-route,
        .foot-contact, .foot-col a):is(:hover, :focus-visible) > i.ph,
    :is(.news-card, .project-card, .company-card, .needs-route):is(:hover, :focus-within)
      :is(.action-link, .more, .needs-route-action) > i.ph {
      color: inherit;
    }

    /* --- Card hover: the white panel steps to the dark tone ----------------
       The subsidiary cards and the direct-route cards fill on hover, the way
       a dropdown entry does (.menu .nav-submenu a fills on hover). Only the
       WHITE PANEL fills: on a direct-route card the photograph sits in its
       own .needs-route-media and is deliberately left alone, so the surface
       moves and the image does not.

       WHY BRAND BLACK AND NOT THE SWEIHAN ORANGE THE DROPDOWN USES. Measured
       in the browser, white on Sweihan is 3.35:1. That clears AA for large
       text only, which is why the hero can set a display headline on an
       orange block and be correct - but these cards carry a 13px label and a
       body paragraph, and both would fail AA (4.5) on that fill. White on
       Brand Black measures 10.31:1, so every size on the card passes AA and
       AAA. No shade was invented to get there: darkening Sweihan would be a
       brand-extension decision, and Black is already one of the eight and
       already this page's dark surface (hero sectors, the feature project
       card, the footer).

       Only background-color and colour transition. Nothing here moves,
       resizes or re-lays-out the card, so the pointer never chases content. */
    .company-card,
    .needs-route .needs-route-copy {
      transition: background-color var(--dur-base) var(--ease-out);
    }

    /* --- The fill sweeps in behind one straight diagonal edge ---------------
       One hover fill for every card family: the panel does not cross-fade to
       its new colour, a straight-edged front sweeps across it, the same
       gesture the hero sector strip already uses.

       THE EDGE IS PARALLEL TO .card-chevron, AND THAT WAS THE WHOLE BUG. Four
       earlier versions all clipped the layer to the sector strip's
       parallelogram, polygon(22% 0, 100% 0, 78% 100%, 0 100%), whose leading
       edge falls DOWN-LEFT. The chevron sticker in the card's bottom-left
       corner is drawn the other way: its lines were measured off the live SVG
       with getPointAtLength + getScreenCTM and every one of them slopes
       DOWN-RIGHT at +0.90 to +0.97, about 43 degrees. So the front and the
       sticker it was supposed to be growing out of were crossing each other,
       and no amount of re-parking the layer fixed that - it just moved which
       corner the mismatch showed up in. Slide it horizontally and the panel
       fills from the top; slide it diagonally and a wedge sweeps the middle;
       scale it from the corner and a triangle grows. All four were rejected.

       Built as a hard-stop gradient rather than a clipped, transformed box,
       because a gradient stop IS a straight line perpendicular to the
       gradient axis by construction, at any box size. A transformed polygon
       only reads as one straight front when the translation happens to be
       perpendicular to the leading edge, which depends on each card's aspect
       ratio - three of the four failures above are that geometry going wrong
       in a different place.

       --wipe-angle points the axis up and to the right, so the fill starts at
       the bottom-left corner (the chevron's corner) and its front travels out
       across the panel staying parallel to the sticker. 43deg is the measured
       chevron slope, not a chosen number: keep them equal or the two lines
       diverge visibly.

       --wipe-p is registered with @property, which is what makes a percentage
       inside a gradient stop animatable at all. Without the registration the
       browser treats it as an unanimatable token and the fill snaps in - which
       is the reduced-motion behaviour anyway, so the degradation is the
       correct one rather than a broken state.

       Layering is wipe 0 / chevron 1 / copy 2 (see the two rules below that
       raise the other two). A pseudo-element is the LAST child in paint order
       at an equal z-index, so at 0 the wipe would have covered .card-chevron
       and the sticker would have vanished exactly when the fill arrived.

       Both hosts were measured before relying on inset: 0 - .company-card and
       .needs-route-copy were already position: relative with overflow: hidden;
       .project-card--secondary .project-card-body measured static/visible, so
       the rule further below gives it both. Without them the layer resolves
       against a further ancestor and paints straight across the card, the same
       failure the ribbon frame hit on this very component. */
    @property --wipe-p {
      syntax: "<percentage>";
      inherits: false;
      initial-value: 0%;
    }

    /* The front also DENSIFIES as it travels, from the sticker's own strength
       to solid. The chevron is translucent at rest - its wedges carry .72 and
       .74 in the SVG itself - so a fill that started at full strength read as
       a different material arriving over the sticker rather than as the
       sticker's own colour spreading. Starting at 72% and resolving to 100%
       makes the first frame of the fill exactly the tone already sitting in
       the corner, and the last frame the opaque panel the copy is measured
       against. Registered as a percentage for the same reason --wipe-p is:
       unregistered it cannot animate. */
    @property --wipe-op {
      syntax: "<percentage>";
      inherits: false;
      initial-value: 72%;
    }

    /* THE TRAVELLING PANEL, not a grown gradient - same rewrite as the
       reference homepage: the gradient-stop version (--wipe-p) is a
       discrete-value animation that can freeze a maroon wedge mid-panel on an
       interrupted hover. transform-only animation is compositor-side and
       cannot freeze at a partial fill. Same fill token, same rest/hover
       endpoints, same duration; only the mechanism changes. */
.company-card::after,
.needs-route .needs-route-copy::after,
.project-card--secondary .project-card-body::after {

    content: "";
    position: absolute;
    z-index: 0;
    inset: -1px -40%;
    background: color-mix(in srgb, var(--wipe-fill) var(--wipe-op,72%), transparent);
    clip-path: polygon(22% 0,100% 0,78% 100%,0 100%);
    transform: translate3d(-78%,0,0);
    transition: transform var(--dur-slow) var(--ease-out);
    pointer-events:none;

}


/* LTR */
html[dir="ltr"] .company-card::after,
html[dir="ltr"] .needs-route .needs-route-copy::after,
html[dir="ltr"] .project-card--secondary .project-card-body::after {

    clip-path: polygon(78% 0,0 0,22% 100%,100% 100%);
    transform: translate3d(78%,0,0);

}


/* Hover */
.company-card:is(:hover,:focus-within)::after,
.needs-route:is(:hover,:focus-within) .needs-route-copy::after,
.project-card--secondary:is(:hover,:focus-within) .project-card-body::after {

    --wipe-op:100%;
    transform:translate3d(0,0,0);

}

    /* The filtered feature card body uses the shared project-card gradient
       wipe, same as .project-card-copy::after (sdeira-sections.css): a
       registered --wipe-p percentage driving the --route-card-wipe-angle
       gradient, not the transform-based travelling panel the other three
       families use. Direction mirrors through the token (45deg here / 315deg
       in LTR), so no per-dir block is needed. */
    .project-cards.is-filtered-view .project-card--feature .project-card-body::after {
      content: "";
      position: absolute;
      z-index: 0;
      inset: 0;
      --wipe-fill: var(--accent-deep);
      --wipe-p: 0%;
      background: linear-gradient(var(--route-card-wipe-angle), var(--wipe-fill) 0 var(--wipe-p), transparent var(--wipe-p) 100%);
      clip-path: none;
      transform: none;
      transition: --wipe-p var(--dur-slow) var(--ease-out);
      pointer-events: none;
    }

    .project-cards.is-filtered-view .project-card--feature:is(:hover, :focus-within) .project-card-body::after {
      --wipe-p: 100%;
      --wipe-op: 100%;
      transform: none;
    }

    /* Snap rather than grow. This file already silences the chevron and the
       sector-card marks for the same reason. */
    @media (prefers-reduced-motion: reduce) {
      .company-card::after,
      .needs-route .needs-route-copy::after,
      .project-card--secondary .project-card-body::after {
        transition: none;
      }
      .project-cards.is-filtered-view .project-card--feature .project-card-body::after {
        transition: none;
      }
    }

    /* --- The photograph's band stops at the photograph -------------------
       .ribbon-frame is the identity band drawn ON a photograph, and it is
       correctly built: it is inset: 0 inside .project-card-img, which is
       position: relative with overflow: hidden, and all three boxes measure
       identical (1164.1 -> 1534.1 at 1400). Nothing escapes its clip, so every
       geometric check of the band passes.

       The band still painted outside the photograph, and the reason is paint
       order rather than geometry. .project-card-body is pulled up over the
       bottom edge of the photo, so its opaque surface covers the last ~20px of
       the image - but .ribbon-frame carries z-index: 2 and the body did not
       carry one at all, so the band painted OVER that surface. The result is a
       diagonal hairline that leaves the photo and runs across the white card
       body, which is what the site owner flagged (2026-08-08): the card line
       must never appear outside the image.

       Fixed by stating what was previously left implicit - the card's copy
       surface is content and outranks a decoration on the photograph above it.
       Raising the body is preferred over lowering the band, because the band's
       z-index: 2 is also what keeps it above the photo itself; lowering it
       would fix this overlap by weakening the rule that puts the band on the
       photograph in the first place.

       Scoped to --secondary deliberately. On the feature card the copy sits ON
       the photograph by design and the two layers are meant to share it, so it
       is not the same relationship and is left alone.

       Measured on BOTH pages before and after: this was never English-only.
       The same rule, applied to the Arabic page, changes its render too. */
    .project-card--secondary .project-card-body,
    .project-cards.is-filtered-view .project-card--feature .project-card-body {
      position: relative;
      z-index: 3;
    }

    /* The chevron and the copy both sit above the travelling layer. Raised
       here rather than at .card-chevron's own rule in @layer legacy, so the
       whole three-level stack is stated in one place. */
    .needs-route .card-chevron,
    .company-card .card-chevron,
    .project-card--secondary .card-chevron,
    .project-cards.is-filtered-view .project-card--feature .card-chevron {
      z-index: 1;
    }

    .needs-route-copy > :not(.card-chevron),
    .company-card > :not(.card-chevron, .company-num),
    .project-card--secondary .project-card-body > :not(.card-chevron),
    .project-cards.is-filtered-view .project-card--feature .project-card-body > :not(.card-chevron) {
      position: relative;
      z-index: 2;
    }

    /* The containing block and the clip for everything above. Measured
       static/overflow: visible before this rule; the other two hosts already
       had both. */
    .project-card--secondary .project-card-body,
    .project-cards.is-filtered-view .project-card--feature .project-card-body {
      position: relative;
      overflow: hidden;
    }

    /* Same fill role as the route card, so the copy reverses the same way and
       on the same delay. .project-type is included deliberately: it is the
       orange badge role, and orange-on-#cb6c2e measures 1.28. */
    .project-card--secondary:is(:hover, :focus-within)
      .project-card-body :is(.project-type, h3, p, .project-meta, .project-card-action),
    .project-cards.is-filtered-view .project-card--feature:is(:hover, :focus-within)
      .project-card-body :is(.project-type, h3, p, .project-meta, .project-card-action) {
      color: var(--brand-white);
    }

    .project-card--secondary .project-card-body
      :is(.project-type, h3, p, .project-meta, .project-card-action),
    .project-cards.is-filtered-view .project-card--feature .project-card-body
      :is(.project-type, h3, p, .project-meta, .project-card-action) {
      transition: color var(--dur-slow) var(--ease-out);
    }

    /* The action links are on the same clock too. They inherit a 120ms colour
       step from the shared link role, which is correct for a link on a static
       surface and wrong for one riding a 480ms fill: measured at 0.12s on all
       three families before this rule. transition-property is left alone -
       these links also animate opacity and visibility elsewhere - so only the
       colour leg is retimed, via the longhands. */
    :is(.needs-route, .company-card, .project-card--secondary, .project-cards.is-filtered-view .project-card--feature)
      :is(.action-link, .more, .needs-route-action, .project-card-action) {
      transition-property: opacity, visibility, color;
      transition-duration: var(--dur-base), var(--dur-base), var(--dur-slow);
      transition-timing-function: var(--ease-out);
    }


    /* The cards fill with #cb6c2e, at the client's explicit direction, so the
       panel agrees with the photograph beside it instead of dropping to the
       neutral dark.

       FLAGGED, NOT SILENT: this is a ninth colour. It is a deep Sweihan and
       the token file's rule is that a derived shade is a brand-extension
       decision for the identity owner, so it is written here as a card-local
       value and deliberately NOT added to sdeira-tokens.css - nothing else on
       the site may reach for it until the identity owner rules on it.

       Contrast was measured rather than assumed, and this fill DOES NOT clear
       AA: white on #cb6c2e is 3.67:1, against the 4.5 needed for the 13px
       audience label and the body paragraph. It clears the 3.0 large-text
       threshold, so only the card heading is compliant. The value is the
       client's explicit choice, made after seeing #a86133 (4.75:1, compliant)
       live on the page, so it is recorded here rather than quietly corrected.
       Brand Black, which the subsidiary cards used until they were moved onto
       this fill for consistency, is 10.31:1, and the nearest deeper tone of
       this same hue that would pass is about #a85a24.
       Razeen is 1.86:1 here and cannot be the accent on this fill - see the
       action-link rule further down. */
    /* The fill is the wipe layer's colour, not the card's own background: a
       background-color that changed on hover would land in --dur-base under a
       front still travelling on --dur-slow, and the wipe would have nothing
       left to reveal.

       ONE fill for all three families. The subsidiary cards used Brand Black
       here, which is the higher-contrast choice (white on it is 10.31:1), and
       they were moved onto #cb6c2e at the client's explicit direction so the
       three card families read as one system rather than as two. The AA
       shortfall recorded above therefore now applies to the subsidiary cards
       too: their body copy sits at 3.67:1. Reverting is one value in this
       rule, not a restructure. */
    .company-card::after,
    .needs-route .needs-route-copy::after,
    .project-card--secondary .project-card-body::after,
    .project-cards.is-filtered-view .project-card--feature .project-card-body::after {
      --wipe-fill: var(--surface-brand-deep);
    }

    /* --- Route card: only the panel is the hit area ------------------------
       The card is one <a> wrapping the photograph and the copy panel, and the
       whole rectangle used to be clickable - including the empty column beside
       the panel, where nothing invites a click and the pointer turning into a
       hand reads as a bug.

       Done with pointer-events rather than by re-nesting the markup: the
       anchor has to stay the grid container (it owns the two-track layout and
       the mirrored even/odd placement), so moving it inside the panel would
       mean rebuilding the layout around a new element for a hit-area change.
       Events still bubble from the panel to the anchor, so the link, its hover
       fill and the image zoom all still fire - from the panel only. That is
       the deliberate part: the whole card responds as one, but only from the
       surface that reads as clickable. Keyboard focus is untouched, the anchor
       is still focusable, and :focus-within drives the same state. */
    .needs-route {
      pointer-events: none;
    }

    .needs-route .needs-route-copy {
      pointer-events: auto;
    }

    /* Selected by POSITION, not by tag name. These two cards are written with
       different elements than they used to be (the route card's copy is
       small/strong/em where it was span/h3/p), so a selector listing tags
       silently stops matching the moment the markup is re-authored - which is
       exactly what happened here, and it fails invisibly: the fill still
       lands and the text just stays dark on dark. Every direct child of the
       panel is copy and should reverse, except the two that carry their own
       colour role: the action link (Razeen, below) and the decorative
       chevron. */
    /* Anything that reverses UNDER the wipe runs on the wipe's own clock:
       same duration, same easing, no delay, in both directions. Two earlier
       versions of this are wrong and were both seen on the page. Colour on
       --dur-base with the wipe on --dur-slow finishes at half the distance,
       so the copy goes white over a panel the fill has not reached; adding a
       delay to compensate only moves the mismatch, it stays a step function
       under a sweep. Sharing the clock is what makes the two read as one
       change. */
    .company-card > *:not(.action-link):not(.card-chevron):not(.company-logo),
    .needs-route .needs-route-copy > *:not(.needs-route-action):not(.card-chevron) {
      transition: color var(--dur-slow) var(--ease-out);
    }

    .company-card:is(:hover, :focus-within)
      > *:not(.action-link):not(.card-chevron):not(.company-logo),
    .needs-route:is(:hover, :focus-within)
      .needs-route-copy > *:not(.needs-route-action):not(.card-chevron) {
      color: var(--brand-white);
    }

    /* The subsidiary marks are brand assets in their own colours - Khadamat
       green, Your Laundry blue, Zoad dark - and every one of them clashes on
       the filled panel. brightness(0) invert(1) renders each as a solid white
       silhouette, which is the reversed/mono form a brand system already
       expects on a saturated surface (this repo ships khadamat-logo-white.webp
       for exactly that reason). Done as a filter rather than four more PNGs so
       there is one behaviour to maintain and no second copy of a brand asset
       to keep in sync. Eskan's mark is inline SVG painted from
       --company-accent, so it reverses by swapping the variable instead. */
    /* On the fill's clock, same as the copy. */
    .company-card .company-logo img {
      transition: filter var(--dur-slow) var(--ease-out);
    }

    .company-card:is(:hover, :focus-within) .company-logo img {
      filter: brightness(0) invert(1);
    }

    /* Zoad's opaque source needs separate symbol and wordmark crops. Keeping
       the small bilingual descriptor out of the reversed crop avoids raster
       specks at card size. The logo swap snaps so two opaque sources never
       overlap while the card's own fill continues its standard motion. */
    .company-card .company-logo--zoad img {
      transition: none;
    }

    /* .company-logo--zoad::before,
    .company-logo--zoad::after {
      content: "";
      position: absolute;
      inset-block-start: 0;
      inset-inline-start: 0;
      inline-size: 65px;
      block-size: 82px;
      background: url(../images/companies/zoad-logo-dual-white.svg) left top / auto 100% no-repeat;
      opacity: 0;
      pointer-events: none;
      transition: none;
    }

    .company-logo--zoad::before {
      clip-path: inset(8% 8% 52%);
      background:
        radial-gradient(circle 4px at 78% 16%, var(--brand-white) 95%, transparent 100%),
        url(../images/companies/zoad-logo-dual-white.svg) left top / auto 100% no-repeat;
      filter: grayscale(1) brightness(2.4) contrast(18);
    }

    .company-logo--zoad::after {
      clip-path: inset(47% 0 22%);
      filter: grayscale(1) invert(1) contrast(8);
    } */

    .company-card:is(:hover, :focus-within) .company-logo--zoad img {
      filter: none;
      /* opacity: 0; */
    }

    /* .company-card:is(:hover, :focus-within) .company-logo--zoad {
      mix-blend-mode: screen;
    } */

    .company-card:is(:hover, :focus-within) .company-logo--zoad::before,
    .company-card:is(:hover, :focus-within) .company-logo--zoad::after {
      opacity: 1;
    }

    .company-card:is(:hover, :focus-within) .company-logo svg {
      --company-accent: var(--brand-white);
      --company-accent-2: rgba(255, 255, 255, .72);
    }

    /* Two places the copy rule above cannot reach, both hardcoding a colour
       of their own rather than inheriting:

       1. Eskan has no image mark. Its lockup is live text, so the filter and
          the SVG variable swap both miss it and it stays Brand Black on the
          fill. It is the wordmark's own declared colour that has to move.
       2. .company-card > h3 small is Jais by declaration, so it survives the
          white assignment its own <h3> parent receives and reads as a grey
          line under a white heading.

       Both ride the fill's clock, same as every other colour on these cards. */
    /* Eskan's stripe mark carries its own three teals as literal fills, so
       the --company-accent swap above is a no-op on it. Same treatment the
       image marks get, for the same reason: on the fill it reads as a solid
       white silhouette. A filter rather than three fill overrides so the
       reversal stays one behaviour across every mark on these cards. */
    .company-card .company-logo--eskan svg {
      transition: filter var(--dur-slow) var(--ease-out);
    }

    .company-card:is(:hover, :focus-within) .company-logo--eskan svg {
      filter: brightness(0) invert(1);
    }

    /* --- The same reversal in the nav dropdown -------------------------------
       The four subsidiary marks appear twice on the site: on the company cards
       above, and as 56x32 tiles in the Ø´Ø±ÙƒØ§Øª Ø§Ù„Ù…Ø¬Ù…ÙˆØ¹Ø© dropdown. The cards
       already reverse them to white on their fill; the dropdown row paints the
       identical fill and left every mark in its own brand colours, so the same
       component answered the same state two different ways - Khadamat green
       and Your Laundry blue sitting on Sweihan, which is the clash the card
       treatment exists to avoid. This is that treatment, not a second one.

       Three marks, three mechanisms, because the SOURCES differ, not because
       the rule does. Measured alpha, not assumed:

         khadamat-logo-ar.webp    16% opaque  -> brightness(0) invert(1)
         your-laundry-logo-ar     18% opaque  -> brightness(0) invert(1)
         Eskan                    inline SVG  -> same filter, plus its lockup
                                                 text, which no filter reaches
         zoad-logo-cropped.webp  100% opaque  -> see below

       Zoad's file is a dark mark printed on a solid white ground, so
       brightness(0) invert(1) would paint a white rectangle over the row.
       Inverting first turns the ground black and the mark white, and screen
       then drops black to the layer underneath - the fill - leaving the mark
       white on it. Same conclusion the card reached with its two cropped
       pseudo-elements; a 32px tile does not need the crops, only the reversal.

       Keyed to the row's own state (:hover, :focus-visible, .active) rather
       than to the panel, so a keyboard walk down the list reverses exactly the
       row that is focused - the same rows the fill itself follows. */
    .company-nav-mark :is(img, svg) {
      transition: filter var(--dur-fast) var(--ease-out);
    }

    .company-nav-mark--eskan :is(b, small) {
      transition: color var(--dur-fast) var(--ease-out);
    }

    .company-nav-link:is(:hover, :focus-visible, .active) .company-nav-mark :is(img, svg) {
      filter: brightness(0) invert(1);
    }

    .company-nav-link:is(:hover, :focus-visible, .active) .company-nav-mark--eskan :is(b, small) {
      color: var(--brand-white);
    }

    /* THE ZOAD NAV EXCEPTIONS ARE GONE, matching the reference: the nav now
       carries the WORDMARK (zoad-logo-wordmark.webp), navy ink on transparent,
       so it takes the same brightness(0) invert(1) hover filter every other
       company mark takes. */

    .company-card .company-logo--eskan,
    .company-card .company-logo--eskan-wordmark,
    .company-card .company-logo--eskan-wordmark small,
    .company-card > h3 small {
      transition: color var(--dur-slow) var(--ease-out);
    }

    .company-card:is(:hover, :focus-within) .company-logo--eskan,
    .company-card:is(:hover, :focus-within) .company-logo--eskan-wordmark,
    .company-card:is(:hover, :focus-within) .company-logo--eskan-wordmark small,
    .company-card:is(:hover, :focus-within) > h3 small {
      color: var(--brand-white);
    }

    /* Card-level hover has to agree with link-level hover, or moving the
       pointer from the card body onto the link itself changes the colour
       mid-gesture. These fire when the CARD is hovered, so they must
       resolve to the same two roles. */
    :is(.news-card, .project-card--secondary):is(:hover, :focus-within)
      :is(.action-link, .more) {
      color: var(--link-hover);
    }

    /* The on-dark role, for the surface that is actually dark. Razeen is the
       system's measured on-dark accent at 5.22 on Brand Black, which is why
       the dark feature project card sits here. The subsidiary cards used to
       be in this group and left it when their fill changed - see the white
       rule below. */
    .project-card:not(.project-card--secondary):is(:hover, :focus-within) .action-link {
      color: var(--link-hover-on-dark);
    }

    /* Every card that fills with #cb6c2e takes white for its action link, not
       Razeen: Razeen measures 1.86:1 on that fill and would read as a smudge
       rather than as an accent. White measures 3.67:1 - see the fill rule for
       what that does and does not clear. The subsidiary cards joined this
       group when their fill changed, which is the same reasoning that moved
       them out of the light group in the first place: the surface decides the
       role, not the component. */
    .needs-route:is(:hover, :focus-within),
    .needs-route:is(:hover, :focus-within)
      :is(.action-link, .more, .needs-route-action),
    .company-card:is(:hover, :focus-within)
      :is(.action-link, .more) {
      color: var(--brand-white);
    }

    /* The sector card fills too, and it fills with the same one orange - so it
       answers the same way, for the same measured reason. Razeen measures 3.40 at
       its best on the finished sector wipe and white measures 6.58 at its
       worst. The card-level
       selector is what matters here: the whole card is the target, so the
       pointer lands on the link itself only by accident, and a link that
       changed colour on that accident would be the one part of the card
       answering a different question from the rest of it. */
    .hero-sectors .sector-card:is(:hover, :focus-within) .sector-card-action {
      color: var(--brand-white);
    }

    /* --- About section: one full-height panel, not two stacked sections -----
       The Aryam metric rail used to live in its own section below (.impact-alt),
       duplicating the About copy as a second, separately-scrolled block. Its
       markup now lives inside #about instead, right after .about-values, so
       the whole thing reads as one section: photo, copy, then the metric rail.
       min-block-size holds it at the viewport height shown in the approved
       reference composition; centering keeps the layout balanced on taller
       viewports where the content is shorter than 100vh. Unlayered so it holds
       regardless of which @layer legacy breakpoint rule sets .about's padding. */
    .about {
      min-block-size: 100vh;
      display: flex;
      align-items: center;
    }

    .about > .wrap {
      width: 100%;
    }

    @media (max-width: 640px) {
      .about {
        min-block-size: 0;
      }
    }

    /* ===== CTA SECTION: HERO RIBBONS =====
       Same mark as .hero-glass, same reason: the hero and the closing CTA are
       the two full-bleed photographic surfaces on the page, so they carry the
       same identity treatment rather than one of them being bare.

       Two things differ from the hero deliberately:
         - The band is its own clipping frame (inset: 0 + overflow: hidden)
           instead of relying on .cta's overflow. The section is a stacking
           context with a photo layer and a scrim, and the frame keeps the
           decoration from ever measuring taller than the section it marks.
         - The bands overfill vertically (top: -20%, height: 140%) and
           are clipped back. A skewX band with height: 100% leaves empty
           triangles at the top and bottom corners, so overfilling is what
           makes the visible height exactly the section height.

       Colour, weight, width, skew and the r3 step-back are the hero's values,
       not new ones. */
    /* The bands are quieter here than the raw colour suggests, and the reason
       is worth recording because it is not a taste decision.

       Colour, weight and alpha are the hero's, measured identical. What made
       these read louder is stacking: the hero's scrim is a pseudo-element at
       the same z-index as .hero-glass, so it paints AFTER the bands and mutes
       them; the CTA's scrim sits at z-index -1, so bands at 0 land on top of
       it at full strength.

       Sinking them under the scrim instead was tried and rejected by
       measurement: the hero's scrim is a gradient bottoming out at .44, while
       the CTA's is a flat .76 black, which erased the mark completely rather
       than quieting it. So the residual strength is applied directly. The
       hero's bands survive its scrim at 1 - alpha, i.e. between .28 and .56
       depending on height. The CTA wrapper uses that quietest .28 endpoint so
       the mark reads like the hero at its lightest and stays behind the
       brighter contact content. */
    .cta-glass {
      position: absolute;
      z-index: 0;
      opacity: .28;
      inset: 0;
      overflow: hidden;
      pointer-events: none;
    }

    .cta-glass span {
      position: absolute;
      top: -10%;
      height: 120%;
      width: 60px;
      border: 1px solid var(--brand-sweihan);
      border-radius: var(--r);
      background: color-mix(in srgb, var(--brand-sweihan) 8%, transparent);
      transform: skewX(-24deg);
    }

    .cta-glass .r1 { inset-inline-start: 68%; }
    .cta-glass .r2 { inset-inline-start: 78%; }

    /* Steps back so the group reads as depth, not three equals. */
    .cta-glass .r3 {
      inset-inline-start: 88%;
      border-color: color-mix(in srgb, var(--brand-sweihan) 55%, transparent);
    }

    @media (max-width: 920px) {
      .cta-glass { display: none; }
    }

    /* ===== SECTION IDENTITY BANDS (the ambient case) =====
       .section-glass is the one component for a group of identity bands drawn
       behind a section's own content. .news-glass is the same component under
       its original name - it was the first and for a while the only place this
       treatment existed, and the markup still writes that class - so it is
       carried in every selector here rather than being given a second
       definition. Anything new writes .section-glass.

       The wrapper clips itself (inset: 0 + overflow: hidden) instead of asking
       the host section to clip. A skewed band throws its corners well past its
       own box, so something must clip it, but making that the SECTION's job
       would silently cut off any content a section deliberately lets hang
       outside its padding - .about is exactly that case (see .ribbon-frame's
       note above, same trap one level down). So the host contributes only a
       stacking context; the decoration contains its own overflow. */
    :is(.news-section, .about, .needs, .featured-projects, .value-sections) {
      position: relative;
      isolation: isolate;
    }

    /* The content rides above the bands. Nothing here changes layout: .wrap is
       already a block at its natural place in flow, and the bands are absolute,
       so this is a paint order statement only. */
    :is(.news-section, .about, .needs, .featured-projects, .value-sections) > .wrap {
      position: relative;
      z-index: 1;
    }

    :is(.section-glass, .news-glass) {
      position: absolute;
      z-index: 0;
      inset: 0;
      overflow: hidden;
      pointer-events: none;
    }

    /* One geometry for every section identity band. The vertical overfill
       absorbs the skew so the visible mark reaches both section edges. */
    :is(.hero-glass, .cta-glass, .section-glass, .news-glass) span {
      top: var(--identity-band-top);
      height: var(--identity-band-height);
      width: var(--identity-band-width);
    }

    /* The two photographic surfaces share the identity-band geometry, including
       the system radius; only their photographic surface strength differs. */
    :is(.hero-glass, .cta-glass) span {
      border-width: var(--identity-band-border);
      background: color-mix(in srgb, var(--brand-sweihan) var(--identity-band-fill), transparent);
    }

    /* The ambient tone, from the token file. This is the tone the news section
       has always carried; naming it is what lets the rest of the page reach it
       without re-deciding how quiet "quiet" is per section. The radius is the
       system's one value rather than the hero's pill: on a flat ground the band
       is a cut in the surface, not a bar laid on top of it. */
    :is(.section-glass, .news-glass) span {
      position: absolute;
      border: var(--identity-band-border) solid
        color-mix(in srgb, var(--brand-sweihan) var(--identity-band-line-ambient), transparent);
      border-radius: var(--r);
      background: color-mix(in srgb, var(--brand-sweihan) var(--identity-band-fill-ambient), transparent);
      transform: skewX(-24deg);
    }

    /* PLACEMENT. Three positions along the inline axis, written as one scale so
       a section picks an edge rather than three numbers. The bands are a group
       with a fixed internal step (10% of the section width between neighbours);
       what varies per section is only where the group starts.

       inset-inline-start is logical on purpose here even though decorative
       geometry on this site is normally physical: this is the one decoration
       that has no fixed relationship to the text beside it, so mirroring it in
       the English mirror is correct rather than a hazard. The SKEW stays
       physical - the mark has one slant and the language never flips it. */
    :is(.section-glass, .news-glass) span { inset-inline-start: calc(var(--band-origin, 68%) + var(--band-step, 0) * 10%); }
    :is(.section-glass, .news-glass) :is(.r1, .b1) { --band-step: 0; }
    :is(.section-glass, .news-glass) :is(.r2, .b2) { --band-step: 1; }
    :is(.section-glass, .news-glass) :is(.r3, .b3) { --band-step: 2; }

    /* Two origins, alternated down the page. A section that repeats the same
       corner as the one above it stops reading as texture and starts reading
       as a repeated stamp, which is the specific way this kind of decoration
       goes wrong. --start opens the group just past the leading edge, so its
       first band is half off-screen and the group reads as continuing beyond
       the page rather than as three bars placed in a corner. */
    .section-glass--start { --band-origin: -4%; }
    .section-glass--end { --band-origin: 68%; }

    /* AMBIENT DRIFT. The bands rise and settle, ~14px over --dur-ambient, on
       the site's one easing curve with `alternate` supplying the return - so
       there is no second curve and no keyframe doing the easing by hand.

       The skew is restated inside the keyframes because transform is one
       property: a translate written here would otherwise replace the skew set
       above and the bands would snap upright on the first frame.

       Negative delays are what stagger the group. A positive delay would hold
       all three still at the start position for the first several seconds and
       then start them one by one, which is visible; a negative delay starts
       each band already partway through its own cycle, so the group is never
       in phase and never seen beginning. */
    @keyframes bandDrift {
      from { transform: skewX(-24deg) translate3d(0, 0, 0); }
      to   { transform: skewX(-24deg) translate3d(0, -14px, 0); }
    }

    :is(.section-glass, .news-glass) span {
      animation: bandDrift var(--dur-ambient) var(--ease-out) infinite alternate;
      animation-delay: calc(var(--band-step, 0) * var(--dur-ambient) / -3);
    }

    /* Below this width the section is a single column and the bands would sit
       under the text rather than beside it. */
    @media (max-width: 920px) {
      .section-glass,
      .news-glass { display: none; }
    }

    @media (prefers-reduced-motion: reduce) {
      :is(.section-glass, .news-glass) span {
        animation: none;
      }
    }

    /* ===== CTA ROUTES: THE PLATFORM BUTTON RESPONSE =====
       These three are buttons, so they answer hover the way every other
       button on the site does: the diagonal wipe travels in and the surface
       resolves to Sweihan with a white label. They had drifted to a plain
       background-colour swap to --accent-deep with the wipe switched off
       (display: none), which is the one thing the system explicitly does not
       do - a direct colour swap is a step function where every other action
       is a sweep.

       The wipe carries the colour on its own: these routes rest on a dark
       surface, so the wipe IS Sweihan and nothing swaps underneath it. The
       .btn-primary arrangement does not transfer here - that button is
       already Sweihan at rest, so its dark overlay is the tone-step. A route
       that is dark at rest needs the opposite: reaching the accent by sweep,
       not by a 120ms background jump followed by a second colour arriving
       over 480ms. Two colour events for one gesture is what read as a fault.

       So there is no background-color transition at all here. Only the label
       colour is on a clock, and it is already white in both states. Same
       geometry, same duration, same 55ms lead-in as every other button. */
    .cta-action {
      position: relative;
      isolation: isolate;
      overflow: hidden;
      transition: color var(--dur-fast) var(--ease-out);
    }

    .cta-action::before {
      content: "";
      display: block;
      position: absolute;
      z-index: -1;
      inset: -1px -40%;
      background: var(--brand-sweihan);
      opacity: 1;
      clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
      transform: translate3d(78%, 0, 0);
      transition: transform var(--dur-slow) var(--ease-out) 55ms;
      pointer-events: none;
    }

    /* The first route rests on Sweihan already, so a Sweihan wipe would be
       invisible on it. It takes a tone-step instead: Sweihan carried 30%
       toward Brand Black.

       Not the Liwa mix this section used to carry. Liwa is a red, and mixing
       58% of it into Sweihan lands on a genuinely red surface next to an
       orange one - it read as a second hue arriving, not as the same button
       going deeper. Black is the system's documented tone-step direction and
       it moves lightness without moving hue.

       The 30% is not a taste value: it is the exact strength of the shared
       rgba(65, 64, 66, .30) overlay every other button on the site wipes in,
       written as an opaque colour because this one sits on an opaque surface.
       Measured in the browser, it resolves to #AB6233 and white on it is
       4.66:1 - clearing the 4.5 AA floor, which the Sweihan rest surface
       does not. */
    .cta-action:first-child::before {
      background: color-mix(in srgb, var(--brand-black) 30%, var(--brand-sweihan));
    }

    /* Hover restates the RESTING surface rather than declaring nothing: a
       @layer legacy rule still swaps these to --accent-deep on hover, and the
       only way to hold the surface still is to name the value it already has.
       Restated per route because the two rest surfaces differ. */
    .cta-action:is(:hover, :focus-visible) {
      background-color: rgba(43, 41, 41, .92);
      border-color: rgba(255, 255, 255, .22);
      color: var(--brand-white);
    }

    .cta-action:first-child:is(:hover, :focus-visible) {
      background-color: var(--accent);
      border-color: var(--accent);
    }

    .cta-action:is(:hover, :focus-visible)::before {
      transform: none;
    }

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

    /* ===== .btn-ghost: THE ONE FILLED BUTTON THIS AUDIT MISSED =====
       The shared filled-button hover rule sets background: var(--brand-sweihan)
       for .btn-primary, .nav-cta, .news-form button and .btn-ghost alike. For
       .btn-primary and the others that is a no-op - they already rest on
       Sweihan, so only the dark tone-step wipe is visible, which is correct.

       .btn-ghost rests transparent. For it that same declaration is not a
       no-op: it is the button's own background-color racing to solid Sweihan
       over --dur-fast (120ms), fully opaque, well ahead of the shared 480ms
       diagonal wipe - and painting OVER that wipe, since a box's own
       background paints below its own ::before in the same stacking context.
       The wipe finishes invisibly under a surface that already snapped to
       colour four times faster. Same fault as the one already fixed on
       .cta-action, just unaudited here.

       Fix mirrors that one: the box's own background never changes, and the
       wipe itself is opaque Sweihan instead of the shared dark wash, so the
       sweep is the only way the colour arrives. */
    .btn-ghost::before {
      background: var(--brand-liwa);
      opacity: 1;
    }

    .btn.btn-ghost:is(:hover, :focus-visible) {
      background: transparent;
    }

    /* --- News card: stretched link ------------------------------------------
       A ROLE that holds at every viewport: the whole card is clickable, not
       just its three separate <a> tags (the image, the title, "read more"),
       which all point at the same story anyway. .news-card already computes
       cursor: pointer everywhere on the card (the last @layer legacy pass on
       this selector sets it unconditionally), so the surface was already
       promising full-card clickability without delivering it - this makes
       that promise true instead of removing it.

       Hosted on the title link, .news-image-link is a sibling of .news-body
       and sits in its own overflow: hidden box, so a pseudo aimed at the full
       card would be cut down to the photo if it lived there instead. .news-body
       carries no overflow rule, so the title link's pseudo reaches .news-card
       cleanly. inset: 0 matches .news-card's own box exactly, so its own
       overflow: hidden never clips it either.

       No z-index games needed for the image and "read more" links: the hover
       state (.news-card:hover / :focus-within) is true the moment the pointer
       is anywhere over this pseudo too, since it is still a card descendant.
       Keyboard order and each link's own href are untouched. */
    .news-card {
      position: relative;
    }

    .news-card h3 a {
      position: static;
    }

    .news-card h3 a::after {
      content: "";
      position: absolute;
      inset: 0;
    }

    /* --- News card image: var(--media-wide), fixed, not a height clamp ------
       A ROLE that holds at every viewport, and the ratio matches every other
       media field on the page (.needs-route-media and its siblings). 4:3
       since 15 Aug 2026, was a literal 16:9 - moved onto the token so this
       and .is-filtered-view's demoted feature card (above) cannot drift
       apart again.
       The last @layer legacy pass on this selector (`.news-card .img { ...
       block-size: var(--news-media-height); aspect-ratio: auto; }`) sizes the
       image purely by height, independent of the card's own width. .news-grid
       is auto-fit, so that width changes as the grid gains or drops a column,
       and the crop ratio drifted with it instead of holding one shape. Scoped
       off .news-card--feature: that card's image is stretched to match its
       text column's height (align-items: stretch on a two-column split), a
       genuinely different layout with no comparable "card width changes, so
       the ratio should too" problem to fix. */
    .news-card:not(.news-card--feature) .img {
      aspect-ratio: var(--media-wide);
      block-size: auto;
    }


    .menu-close {
      display: none;
    }

    /* The marker takes the language control's own class rather than a copy of
       its look: same geometry, same 44px target height, same colour in both
       header states, same scrolled treatment. It sits directly beside that
       control in the bar, so anything less than literally the same definition
       would drift the moment either one is retuned.

       It stays a marker, not a control. pointer-events: none is what keeps the
       hover and focus states .lang carries from firing on something that has
       nowhere to go - the site has no accessibility panel and no destination
       for this to open, and a box that answers a pointer and then does nothing
       is worse than one that never invited the pointer. If a real control
       arrives, this line is what comes out.

       .nav-icon--search remains only on the named error-header variant, where
       there is deliberately no search surface behind it. The shared Arabic
       group header now uses the real .nav-search control instead. */
    .nav-icon--accessibility,
    .nav-icon--search {
      pointer-events: none;
    }

    /* .lang disappears at 980 (the drawer carries .menu-lang instead) and again
       at 420. Neither applies to this: it has no text to make room for, no
       counterpart inside the drawer, and it was visible at those widths before
       it adopted the class. Restated rather than left to inherit the hiding. */
    @media (max-width: 1280px) {
      .nav-actions > :is(.nav-icon--accessibility, .nav-icon--search) {
        display: inline-flex;
      }
    }

    @media (max-width: 420px) {
      :is(.nav-icon--accessibility, .nav-icon--search) {
        display: inline-flex;
      }
    }

    /* The drawer owns its header while open. Keeping a static header marker
       visible over the backdrop makes it look detached from both surfaces. */
    @media (max-width: 1280px) {
      body.menu-open :is(.nav-icon--accessibility, .nav-icon--search) {
        visibility: hidden;
      }

      body.menu-open :is(.ai-chat-toggle, .ai-chat-panel) {
        visibility: hidden;
        pointer-events: none;
      }

      .menu-close {
        display: grid;
        place-items: center;
      }
    }

    /* ---- The menu control's colour -----------------------------------------
       The burger's three bars became a single Phosphor glyph (.ph-list) in the
       markup, but every rule that had ever given it a colour was written
       against `.burger span` and set a BACKGROUND, not a colour. Nothing
       errored: the glyph simply fell through to the inherited document ink and
       painted #414042 on the dark bar, beside a language control at
       rgba(255,255,255,.84). Measured at 375: search #414042, accessibility
       marker white, burger #414042.

       It is a header control, so it takes the control colour set - the same
       four states .lang and .nav-search carry, in both header states. Colour
       only: no background on hover, because unlike those two this one is not a
       text-and-icon pill and a wash behind a bare glyph reads as a second
       button appearing. Here rather than in @layer legacy because it has to
       hold at every viewport, and the span rules it replaces are scattered
       across the breakpoint blocks. */
    .burger {
      color: rgba(255, 255, 255, .84);
      transition: color var(--dur-fast) var(--ease-out);
    }

    .burger:is(:hover, :focus-visible) {
      color: var(--brand-white);
    }

    header.scrolled .burger {
      color: var(--muted);
    }

    header.scrolled .burger:is(:hover, :focus-visible) {
      color: var(--accent-text);
    }

    /* ---- The bar's icon controls are one set ---------------------------------
       Three icon-only controls sit at the end of the bar and were three
       different boxes: the two markers 32px wide (16px glyph + 8px padding each
       side) and the burger 44px. With a 4px gap that put 20px of air between one
       pair of glyphs and 26px between the next, which reads as a spacing mistake
       because it is one.

       44px is the number to standardise on, not 32: it is the touch target the
       burger already carries for WCAG 2.5.8, and the one the markers should have
       had. Equal boxes plus one gap makes the ink spacing fall out even -
       14 + 4 + 14 - rather than being tuned per pair. */
    :is(.nav-search, .nav-icon--accessibility, .nav-icon--search, .burger) {
      min-inline-size: 44px;
    }

    /* Optical alignment, which the equal boxes above do NOT give on their own.
       A 44px box around a 16px glyph carries 14px of internal padding, so the
       outermost control's INK sat 14px further in than the logo's, which is an
       image flush to its own box edge. Measured at 375 before this: logo ink
       28px from the page edge, burger ink 42px. The boxes were aligned; the
       marks were not, and the mark is what the eye lines up.

       The 44px target is not given up to fix it - the box keeps its size and is
       pulled outward by exactly its own padding, so the ink lands on the nav's
       content edge and the hit area grows outward rather than shrinking. Logical
       property, so RTL and LTR both get it from this one line: the burger is the
       last child in both, which is the inline-end edge in both.

       Not applied to .nav-cta, which takes over as the last visible child at
       1280 and up: it is a filled button whose box edge IS its ink, so it is
       already flush and pulling it would overhang the bar.

       CLAMPED TO --hd-pad (site owner flagged, 12 Aug 2026). The formula
       above assumed --icon-control sits around 32px, giving a small -6px
       pull that fits inside --hd-pad's 10-14px with room to spare. But
       --icon-control clamps to its 16px floor at every width the burger is
       actually visible (it only shows at 1280px and below, and 1.2vw does
       not clear 16px until well past that), which fixes the pull at a
       constant -14px - bigger than --hd-pad at every one of those widths, so
       the button's own box overhung the pill's rounded edge instead of just
       its ink reaching the content edge. max() keeps whichever pull is
       smaller in magnitude: the intended optical pull where it fits, capped
       at the pill's own padding where it does not, so the box can never
       protrude past the pill regardless of viewport. */
    .burger {
      margin-inline-end: max(calc((var(--icon-control) - 44px) / 2), calc(-1 * var(--hd-pad)));
    }

    /* ---- The about badge's supporting line -------------------------------
       WHITE AT 72% ON THE SWEIHAN FILL MEASURED 2.45. Solid white on that same
       fill is 3.35, which is the brand's own ceiling and a separate, recorded
       question (see --badge-text in the token file) - but the alpha was ours,
       it cost a third of what contrast the fill does allow, and it bought
       nothing: this is the only line of copy inside the badge, so there was no
       hierarchy for it to sit under. The token file's section 11 already
       forbids body-size text below full white on a translucent dark layer;
       this is the same rule on a coloured one. */
    .about-badge .t {
      color: var(--brand-white);
    }

    /* ---- SCALE FLOOR APPLIED TO WHAT PREDATES IT --------------------
       A full-page audit found 40-odd sizes outside the ten roles, which is
       the drift CLAUDE.md describes in this file. Most of those are card
       headings sitting between 16.8 and 30px where the card role is 31.4px -
       real drift, but snapping them moves layout across half the homepage and
       that is a design change, not a cleanup. It is recorded, not done here.

       WHAT IS DONE HERE IS THE FLOOR. Nothing on the site may render below
       --type-caption (.875rem). These six were under it - 10.8px, 12px,
       12.3px, 12.5px and 12.9px - and every one is a label, a counter or a
       supporting line, which is --type-meta's own job. So this assigns the
       ROLE rather than inventing a size, which is why no number appears below.

       In the SYSTEM LAYER because it is a role assertion that must hold at
       every viewport: these selectors are redefined across several @layer
       legacy breakpoints, so a rule placed among them would win at some widths
       and lose at others. */
    :is(.scroll-hint span,
        .story-achievement span,
        .company-card h3 small,
        .company-num,
        .service-num,
        .sector-hover-copy span,
        .partner-stat small,
        .sector-card-sub) {
      font-size: var(--type-meta);
    }

    /* White-label fills use the accessible role; dark badges use Razeen. */
    :is(.btn-primary, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a),
    :is(.btn-primary, .news-form button, .nav-cta,
      .projects-footer .projects-footer-cta, .sector-hover-copy a):is(:hover, :focus-visible),
    .why-footer a.btn.btn-primary,
    .why-footer a.btn.btn-primary:is(:hover, :focus-visible),
    header.scrolled .nav-cta,
    header.scrolled .nav-cta:is(:hover, :focus-visible) {
      background: var(--accent-fill);
      border-color: var(--accent-fill);
    }

    :is(.project-filter, .news-filter).is-active,
    .about-badge,
    .cta-action {
      background: var(--accent-fill);
    }

    .project-card--feature .project-type {
      color: var(--badge-text-on-dark);
    }

    /* ---- EVERY HEADING AND FIGURE ON THIS PAGE, ON THE SCALE ---------------
       __typecheck.js found 29 selectors on this page rendering a size that is
       not one of the roles - 40-odd nodes, from 14.4px to 97.8px. Every one is
       a local font-size that predates the scale, and together they are why the
       homepage and the generated pages can look like two different products
       even when every colour matches.

       ASSIGNED BY WHAT THE ELEMENT IS, NOT BY WHICH ROLE IS NEAREST. A card
       title takes --type-card whether it currently measures 37.7 or 20.3,
       because the point is that all ten card titles are one size afterwards.
       Nearest-fit would have preserved the spread it was written to remove.

       In the SYSTEM LAYER because these selectors are redefined across many
       @layer legacy breakpoints - .sector-card-title alone appears in five -
       so a rule placed among them wins at some widths and loses at others.
       This is the same reasoning the file's own two-layer note gives. */

    /* Card titles. Ten components, one role. */
    :is(.sector-hover-copy h3,
        .openings-intro h3,
        .company-card h3,
        .why-card-body h3,
        .service-card h3,
        .story-item h3,
        .project-card-body h3,
        .process-step h3,
        .sector-card-title,
        .about-values-head h3,
        .needs-route-copy strong,
        .news-card h3 a,
        .news-card h3) {
      font-size: var(--type-card);
      line-height: var(--leading-card);
    }

    .news-card h3 a{
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 2;
      overflow: hidden;
      text-overflow: ellipsis;
      /* word-break: break-word; */
    }

    .news-card .news-body p {
      display: -webkit-box;
      -webkit-box-orient: vertical;
      -webkit-line-clamp: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      word-break: break-word;
    }

    /* News titles are complete headlines, not excerpts. The legacy two-line
       clamp cuts Arabic text mid-title once the shared card role is applied. */
    .news-card h3 {
      min-block-size: 0;
      display: block;
      -webkit-line-clamp: unset;
      overflow: visible;
    }

    /* Supporting headings: a partner name, a footer column, the small headings
       that sat between 15.8 and 19.8px. --type-label is the heading role
       directly below card and the token file calls it exactly this - heading
       metadata. */
    :is(.partner-card h3,
        .foot-col h3,
        .foot-col h4) {
      font-size: var(--type-label);
      line-height: var(--leading-label);
    }

    /* Figures. Not headings - see --figure-size in the token file. */
    :is(.story-year,
        .verified-figure,
        .process-num,
        .partner-stat strong,
        .about-badge .big) {
      font-size: var(--figure-size);
    }

    /* A figure written as a bidi-isolated numeral inherits the figure size from
       its host rather than carrying one of its own. */
    :is(.verified-figure, .partner-stat strong, .about-badge .big) bdi {
      font-size: inherit;
    }

    /* Supporting lines that sat just off body and lead. */
    :is(.about-badge .t, .about-badge .label, .opening-row strong) {
      font-size: var(--type-body);
      line-height: var(--leading-body);
    }

    :is(.partner-logo span, .impact-alt-stat span) {
      font-size: var(--type-action);
    }

    /* The remainder, once the first pass exposed what the class-less parents
       actually were. `div > h3` and `div > strong` in the audit output are
       these; a selector is only as useful as the name above it.

       A RUNG DOWN, NOT A NEW NUMBER. --figure-size (up to 4rem) is sized for
       a figure that stands alone - the about badge, a timeline year. These
       four sit side by side in one strip, each over its own label and its own
       sentence, and at 64px the numeral swamped both. The answer is the rung
       below on the same ladder - --type-card, the h3 rung, spelled by its
       canonical name rather than the --type-h3 alias so the type linter reads
       it as a role. Not a local clamp: this component stays on the scale and
       moves with it. */
    .impact-alt-stat strong,
    .impact-alt-stat strong bdi {
      font-size: var(--type-card);
    }

    :is(.opening-announcement h3,
        .partner-card .partner-logo,
        .news-subscribe-copy h3,
        .partners-trust-copy h3) {
      font-size: var(--type-label);
      line-height: var(--leading-label);
    }

    .story-achievement strong {
      font-size: var(--type-body);
      line-height: var(--leading-body);
    }


/* =============================================================================
   THE SAND GROUND ON THE HOMEPAGE
   -----------------------------------------------------------------------------
   Two sections here sit on --surface-sunken: "Start with Your Need" and the
   companies band. Section 5b of the token file makes that colour a ground
   rather than a fill - it is the lit half of a pair whose other half is
   --ground-sand, and a section takes both or neither. These two took only the
   colour, so they take the pattern now, from the same token every generated
   page draws.

   WHAT THEY GAVE UP FOR IT, on the site owner's instruction: each carried a
   .section-glass--start group, three placed identity bands, and that decoration
   had no job on a sand section. The ground already IS those bands - the same
   two ambient strengths, repeated across the whole panel instead of parked in
   one corner - so the glass was the same idea drawn a second, louder time in
   one place. The markup is removed from both homepages, not just hidden.

   .section-glass itself is untouched and still runs on the two sections that
   sit on --surface-base: that ground stays plain, so a placed group is the only
   identity those sections get.

   Unlayered, like everything in this part of the file, so it lands regardless
   of what @layer legacy says about these two selectors at any width. */
:is(.needs, .value-sections)::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  background: url("../images/patterns/solid-a.svg?v=032800d78a7d41e0") no-repeat center / cover;
  opacity: 0.05;
  pointer-events: none;
}

/* ===== THE CLOSING BAND'S ROUTES ARE BUTTONS, AND EXACTLY ONE IS PRIMARY
   =====================================================================
   These started life as three diagonal CARDS and were rewritten as actions,
   and each stage left its geometry behind in @layer legacy. The rewrite that
   turned them into buttons gave all three the --accent-fill so they would
   respond identically on hover. Responding identically was right; being
   identical was not. The system offers exactly TWO action levels -
   .btn-primary and .btn-ghost - and a page closes on ONE primary. Three
   filled buttons in a row is three answers to "which one do I press".

   So this is the same component the generated pages already draw, at the same
   two levels: see .cta-action / .cta-action--ghost in sdeira-sections.css,
   which carries the identical rule set for every page that loads that sheet.
   The homepages cannot link it (they carry their own cascade), so the values
   are read from it rather than invented here.

   THE GEOMETRY IS THE BUTTON FAMILY'S, TO THE NUMBER: 48px tall, 0 22px of
   padding, --type-action at weight 800, one radius token, --ic-lg for the
   mark and --ic-sm for the arrow. That replaces this component's three
   off-scale values - a 51px height, a 1.02rem label and a 1.15rem icon, all
   three recorded as "outside the scale" in design-system/index.html. The
   button family is 48px and this is a button.

   The row is a centred flex line, each route flex: 0 0 auto, so the three sit
   together as a set of buttons instead of the 1000px+ orange band the legacy
   `repeat(3, minmax(0, 1fr))` grid drew for a ~180px label. The legacy
   `grid-template-columns: ... !important` at 621px still wins that property -
   an important declaration in a layer beats an unlayered normal one - which
   is exactly why this switches the display mode instead of arguing with it.
   Wrapping replaces the 620px one-column rule for free.

   BOTH LEVELS WIPE TO ONE COLOUR, so the hover vocabulary stays one motion
   and one tone step: one step of Brand Black into --accent-fill. #B85D22
   carries white at 4.54 and the wipe resolves to #94542C, which carries it at
   5.89 - both clear AA, so no label dips through the gesture. The ghost
   promotes to that solid on hover, which is why hovering the secondary can
   never make it look like the resting primary. */
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  max-width: none;
}

.cta-action,
.cta-action:first-child,
.cta-action:last-child {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: auto;
  min-height: 48px;
  min-block-size: 48px;
  padding: 0 22px;
  border: 1px solid transparent;
  border-radius: var(--r);
  background: var(--accent-fill);
  color: var(--brand-white);
  font-size: var(--type-action);
  font-weight: 800;
  line-height: var(--leading-label);
  text-align: center;
}

/* THE SECOND AND THIRD ROUTES ARE NOT SECOND PRIMARIES. A transparent control
   with a white outline is the site's one sanctioned border, sanctioned
   precisely because this band sits over photography and an outline is what
   gives a transparent control a hit area there.

   Written at the same three-selector width as the rule above so it beats the
   :first-child / :last-child forms on source order rather than losing to
   their higher specificity. */
.cta-action--ghost,
.cta-action--ghost:first-child,
.cta-action--ghost:last-child {
  border-color: var(--brand-white);
  background: transparent;
}

/* The mark and the arrow are on the icon scale, by token. */
.cta-action > i.ph.cta-action-mark:not(.cta-arrow) {
  font-size: var(--ic-lg);
  color: var(--brand-white);
}

.cta-action .cta-arrow {
  margin-inline-start: 0;
  font-size: var(--ic-sm);
}

.cta-action::before,
.cta-action:first-child::before {
  display: block;
  background: color-mix(in srgb, var(--brand-black) 30%, var(--accent-fill));
  opacity: 1;
}

/* The resting surface does not move on hover - the wipe is the whole state.
   These two rules exist only to defeat the legacy pair that changed the
   border to --accent and dropped routes 2 and 3 back to a dark card surface. */
.cta-action:is(:hover, :focus-visible),
.cta-action:first-child:is(:hover, :focus-visible) {
  border-color: transparent;
  background-color: var(--accent-fill);
  color: var(--brand-white);
}

.cta-action--ghost:is(:hover, :focus-visible),
.cta-action--ghost:first-child:is(:hover, :focus-visible),
.cta-action--ghost:last-child:is(:hover, :focus-visible) {
  border-color: var(--brand-white);
  background-color: transparent;
}

/* Button hover is one animated wipe, not a competing background swap. */
.cta-action { transition: color var(--dur-slow) var(--ease-out); }
.cta-action--ghost { background-color: transparent; }
.cta-action::before,
.cta-action:first-child::before {
  display: block;
  content: "";
  position: absolute;
  z-index: -1;
  inset: -1px -40%;
  background: var(--accent-fill);
  clip-path: polygon(22% 0, 100% 0, 78% 100%, 0 100%);
  transform: translate3d(78%, 0, 0);
  transition: transform var(--dur-slow) var(--ease-out) 55ms;
  pointer-events: none;
}
/*.cta-action:first-child::before { background: color-mix(in srgb, var(--brand-black) 30%, var(--accent-fill)); }*/
.cta-action:is(:hover, :focus-visible)::before,
.cta-action:first-child:is(:hover, :focus-visible)::before { transform: none; }
.cta-action:is(:hover, :focus-visible) { background-color: var(--accent-fill); }
.cta-action--ghost:is(:hover, :focus-visible) { background-color: transparent; }



/* Ghost buttons keep their transparent surface; the wipe supplies the hover fill. */
.btn-ghost { transition: color var(--dur-slow) var(--ease-out), border-color var(--dur-slow) var(--ease-out); }
.btn-ghost:is(:hover, :focus-visible) { background-color: transparent; }

/* HEADER PARITY (Arabic homepage) - the bar is a full-width white strip from
   first paint (Liwa F1) and its ink is held dark at every scroll position
   (F2), matching the English homepage (sdeira-liwa.css), the reference
   Arabic homepage, and every sub-page. The search/burger ink is handled
   sitewide by sdeira-nav-controls.css. Unlayered so it wins over the
   transparent-rather-than-white rest rules in @layer legacy above. */
header:not(.scrolled) .nav::before {
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  top: calc(-1 * var(--hd-gap));
  bottom: calc(-1 * var(--hd-gap));
  border-radius: 0;
  background: var(--brand-white);
  border-color: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.logo { color: var(--charcoal); }
.menu a { color: var(--ink); }
.menu a.active { color: var(--accent-text); }
.nav-disclosure > summary { color: var(--ink); }
.lang { color: var(--muted); }

/* HERO PARITY (Arabic homepage) - the reference homepage has no eyebrow in
   the hero; hide the block's optional one (mirrors the EN hero parity). */
#hero .eyebrow { display: none; }

/* AR homepage parity: the direct-route action link and the projects view-all
   take the reference's light-surface inks (dark ink / brand accent) on the
   Arabic homepage only. Scoped to #needs / #projects so other sections and
   the English homepage (sdeira-v2-en.css) are untouched. */
#needs .needs-route-action { color: var(--ink); }
#projects .section-view-all { color: var(--accent-strong); }

/* AR homepage parity: the inactive project/news filter tabs take the muted
   tone (not white), matching the Arabic reference. Scoped to #projects /
   #news on the Arabic homepage only. */
#projects .project-filter:not(.is-active),
#news .news-filter:not(.is-active) { color: var(--muted); }

/* AR homepage parity: the news and companies action links rest on a light
   surface, so they take the reference's dark ink instead of the shared
   .action-link white (which is for actions placed over imagery). Scoped to
   #news / #companies on the Arabic homepage only. */
#news .action-link,
#companies .action-link { color: var(--ink); }

/* AR homepage parity: the news view-all link takes the accent colour, not
   white, matching the EN homepage. Scoped to #news on the Arabic homepage. */
#news .section-view-all { color: var(--accent-strong); }

/* AR homepage parity: these cards fill with the dark brand wipe on hover, so
   their action links reverse on hover exactly like the reference - the route
   and company links go white, the secondary project link is black at rest
   and white over the wipe, and the news "more" takes the Liwa accent. Each
   rule carries the section id so it outranks the resting-ink rules above and
   the shared .action-link white default; scoped to the Arabic homepage only. */
#needs .needs-route:is(:hover, :focus-within) .needs-route-action,
#companies .company-card:is(:hover, :focus-within) .action-link {
  color: var(--brand-white);
}

#projects .project-card--secondary .project-card-action {
  color: var(--brand-black);
}

#projects .project-card--secondary:is(:hover, :focus-within)
  .project-card-body .project-card-action {
  color: var(--brand-white);
}

#news .news-card:is(:hover, :focus-within) .more {
  color: var(--brand-liwa);
}

/* --- Hero sector cards: black veil -> Jais, site owner 25 Aug 2026 --------
   Ported from docs/prototypes/a-liwa/theme.css (Direction A, approved same
   day for both a-liwa and b-khatim - identical five-card treatment either
   way): the identity owner asked that black not be used on the five hero
   sector cards. The veil moves off a black-based curve onto Jais
   (#59595C, rgb 89 89 92) at roughly two-thirds of the same weights, and the
   label band the veil sits above moves with it. Unlayered so it beats every
   breakpoint's own .hero-sectors/.sector-card-veil declaration in
   @layer legacy without duplicating each one. */
.hero-sectors .sector-card-veil {
  background: linear-gradient(180deg,
    rgba(89, 89, 92, .03) 0%,
    rgba(89, 89, 92, .04) 10%,
    rgba(89, 89, 92, .06) 20%,
    rgba(89, 89, 92, .09) 30%,
    rgba(89, 89, 92, .15) 40%,
    rgba(89, 89, 92, .22) 50%,
    rgba(89, 89, 92, .28) 55%,
    rgba(89, 89, 92, .34) 60%,
    rgba(89, 89, 92, .41) 65%,
    rgba(89, 89, 92, .47) 70%,
    rgba(89, 89, 92, .54) 80%,
    rgba(89, 89, 92, .59) 90%,
    rgba(89, 89, 92, .62) 100%);
}

.hero-sectors {
  background: linear-gradient(180deg,
    rgba(89, 89, 92, 0) 0%,
    rgba(89, 89, 92, .33) 30%,
    rgba(89, 89, 92, .45) 100%);
}

/* Site owner, 26 Aug 2026: the closing Contact band's glass panel (.cta-inner)
   was exactly as tall as .cta itself, so the photograph it sits on never
   showed above or below it - the panel read as a flat fill across the whole
   section, the opposite of "seen through glass". .cta gets real padding-block
   (the shared --sec-pad token, not a new value) so the section is taller than
   its content; .cta already centres .cta-inner with `display: grid;
   align-items: center`, so that surplus height becomes visible photograph
   margin above and below the panel with no other change needed. Unlayered so
   it wins over every @layer legacy breakpoint's own zero padding on .cta. */
.cta {
  padding-block: var(--sec-pad);
}

