/* ═══════════════════════════════════════════════════════════════════
   OMNIWIRE — core
   Tokens · reset · type scale · layout · buttons · nav · hero · footer
   Logical properties throughout, so RTL is a `dir` flip.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* surfaces */
  --paper:#FFFFFF;
  --paper-2:#FBFCFD;
  --wash:#F3F7FA;
  --wash-2:#E9F1F7;
  --line:#E4EDF4;
  --line-2:#D3E1EB;

  /* ink */
  --ink:#0C1720;
  --ink-2:#3B5666;
  --ink-3:#78919F;
  --ink-4:#A9BCC7;

  /* accents */
  --teal:#0E9B8E;
  --teal-d:#0A7A70;
  --cyan:#17A9CC;
  --blue:#2E6FD0;
  --amber:#DE8A2A;
  --accent-soft:rgba(14,155,142,.10);

  /* type */
  --font-display:'Plus Jakarta Sans','Segoe UI',system-ui,-apple-system,sans-serif;
  --font-body:'Inter','Segoe UI',system-ui,-apple-system,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,'Cascadia Mono',Consolas,monospace;

  /* type scale — one ladder, used everywhere */
  /* Re-derived so 1280px is unchanged and only the phone end moves:
     a 40px headline in a 320px column is eight or nine characters a
     line, which reads as shouting rather than as hierarchy. */
  --t-hero:clamp(2.05rem, 2.7vw + 1.43rem, 5.25rem); /* 33 →  84px  */
  --t-h1:clamp(1.7rem, 1.93vw + 1.23rem, 3.5rem);    /* 27 →  56px  */
  --t-h2:clamp(1.45rem, 1.29vw + 1.13rem, 2.6rem);   /* 23 →  42px  */
  --t-h3:clamp(1.05rem, .3vw + .95rem, 1.3rem);      /* 17 →  21px  */
  --t-body:1rem;
  --t-sm:.9rem;
  --t-xs:.8rem;
  --t-label:.75rem;

  /* spacing — 4px base */
  --s1:4px;  --s2:8px;  --s3:12px; --s4:16px; --s5:20px;
  --s6:24px; --s8:32px; --s10:40px; --s12:48px; --s16:64px;
  --s20:80px; --s24:96px;
  --sec-y:clamp(56px,7vw,120px);
  --pad:clamp(22px,4vw,48px);
  --wrap:1240px;

  /* radii + shadow */
  --r-sm:8px; --r:14px; --r-lg:22px; --r-xl:30px;
  --sh-sm:0 1px 2px rgba(12,23,32,.04),0 2px 8px rgba(12,23,32,.03);
  --sh:0 2px 6px rgba(12,23,32,.05),0 12px 32px rgba(12,23,32,.06);
  --sh-lg:0 4px 12px rgba(12,23,32,.06),0 24px 64px rgba(12,23,32,.09);

  --ease:cubic-bezier(.22,.61,.36,1);
  --ease-out:cubic-bezier(.16,1,.3,1);

  /* ── motion system ──────────────────────────────────────────
     Three durations, used everywhere. A control answering the
     pointer, a panel moving, and a section arriving are three
     different kinds of event and must never share a timing —
     that is what makes interface motion read as arbitrary. */
  --m-micro:150ms;   /* press, hover, cursor response  */
  --m-ui:300ms;      /* cards, tooltips, navigation    */
  --m-cine:900ms;    /* section reveals, major visuals */

  /* ── lighting ───────────────────────────────────────────────
     One light, upper-left, shared by every raised object here —
     buttons, cards, the nav rail, the honeycomb, and the hero
     film, which was itself lit from the upper-left. Shadows
     therefore always fall down and to the right. */
  --lit-edge:rgba(255,255,255,.9);
  --lit-cast:rgba(12,23,32,.10);
  --nav-h:64px;
  --nav-top:14px;
  --nav-space:calc(var(--nav-h) + var(--nav-top));
}

[dir="rtl"]{
  --font-display:'IBM Plex Sans Arabic','Plus Jakarta Sans','Segoe UI',system-ui,sans-serif;
  --font-body:'IBM Plex Sans Arabic','Inter','Segoe UI',system-ui,sans-serif;
}

/* ── Arabic typography is not Latin typography ─────────────────────
   Measured at 320px: Arabic headings inherited the Latin line-height
   of 1.14, giving 27px type 31px of leading. Arabic script carries
   ascenders, descenders and diacritics through a taller band than
   Latin, so the same ratio that looks tight-and-deliberate in English
   reads as cramped — and at small sizes the marks on one line begin to
   crowd the line below.

   The negative letter-spacing that tightens the Latin display face is
   also removed: Arabic is a connected script, and tracking it apart
   works against the joins rather than the counters. */
[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3,
[dir="rtl"] h4{
  line-height:1.35;
  letter-spacing:0;
}
[dir="rtl"] .hero__title{line-height:1.3}
[dir="rtl"] body{line-height:1.75}

/* ── reset ───────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{
  -webkit-text-size-adjust:100%;scroll-behavior:smooth;
  scroll-padding-top:calc(var(--nav-space) + var(--s5));
  /* `clip` not `hidden`: hidden makes the viewport a scroll container,
     so an RTL flip can strand the page at a negative scrollLeft. */
  overflow-x:hidden;overflow-x:clip;
}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--font-body);font-size:var(--t-body);line-height:1.65;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;overflow-x:clip;
}
img,svg,canvas{display:block;max-width:100%}
h1,h2,h3,h4{font-family:var(--font-display);font-weight:700;line-height:1.14;letter-spacing:-.022em;margin:0}
p{margin:0}
ul,ol{margin:0;padding:0;list-style:none}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
:focus-visible{outline:2px solid var(--teal);outline-offset:3px;border-radius:4px}
::selection{background:rgba(14,155,142,.16)}

.skip-link{
  position:fixed;inset-block-start:-100px;inset-inline-start:var(--s4);z-index:200;
  background:var(--ink);color:#fff;padding:var(--s3) var(--s5);
  border-radius:0 0 var(--r-sm) var(--r-sm);font-weight:600;
  transition:inset-block-start .2s var(--ease);
}
.skip-link:focus{inset-block-start:0}

/* ── layout ──────────────────────────────────────────────────────── */
.wrap{max-width:var(--wrap);margin-inline:auto;padding-inline:var(--pad);width:100%}
.wrap.narrow{max-width:820px}
.sec{padding-block:var(--sec-y)}
.sec--wash{background:var(--wash)}
.sec__foot{margin-block-start:var(--s12);display:flex;justify-content:center}

/* ── type primitives ─────────────────────────────────────────────── */
.eyebrow{
  font-family:var(--font-mono);font-size:var(--t-label);font-weight:500;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-3);
  margin-block-end:var(--s4);
}
[dir="rtl"] .eyebrow{letter-spacing:0;text-transform:none;font-family:var(--font-body);font-weight:600;font-size:.8rem}

.shead{margin-block-end:clamp(32px,4.5vw,64px);max-width:70ch}
.shead--center{text-align:center;margin-inline:auto}
.shead__title{font-size:var(--t-h2)}
.shead__lede{margin-block-start:var(--s5);color:var(--ink-2);font-size:1.05rem;line-height:1.75;max-width:62ch}
.shead--center .shead__lede{margin-inline:auto}

.note{
  margin-block-start:var(--s8);padding:var(--s5) var(--s6);
  border-inline-start:2px solid var(--line-2);color:var(--ink-3);
  font-size:var(--t-sm);line-height:1.7;background:var(--paper-2);
  border-radius:0 var(--r-sm) var(--r-sm) 0;
}
[dir="rtl"] .note{border-radius:var(--r-sm) 0 0 var(--r-sm)}

/* ── buttons ─────────────────────────────────────────────────────── */
/* ── buttons ─────────────────────────────────────────────────────
   A button here is a small machined component, not a coloured
   rectangle. Three layers, in the order the light reaches them:

     TOP SURFACE  the element's own background, carrying a highlight
                  that tracks the pointer across the face
     EDGE         a hard, unblurred bottom shadow — the material's
                  actual thickness, which is what makes it read as an
                  object rather than a sticker
     CONTACT      a soft cast shadow below and to the right, from the
                  single upper-left light the whole site shares

   Press compresses all three at once: the surface drops, the edge
   shortens, the contact shadow tightens. The simultaneity is the
   trick — moving only the position looks like a slide, and changing
   only the shadow looks like a glow.

   Five custom properties drive it (--px --py --tx --ty --lift), all
   written by tactile.js, all with resting defaults declared here. With
   JavaScript disabled every button keeps its full design and its hover
   state; it simply stops tracking the pointer. */
.btn{
  --lift:0;
  --tilt:2.4deg;
  position:relative;
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s2);
  padding:14px 28px;border-radius:100px;font-family:var(--font-display);
  font-weight:600;font-size:.92rem;letter-spacing:-.005em;white-space:nowrap;
  border:1px solid transparent;
  transform:
    perspective(700px)
    rotateX(calc(var(--ty,0) * var(--tilt) * -1))
    rotateY(calc(var(--tx,0) * var(--tilt)))
    translateY(calc(var(--lift) * -2px));
  transition:transform var(--m-ui) var(--ease-out),box-shadow var(--m-ui) var(--ease-out),
             background-color var(--m-ui) var(--ease),color var(--m-ui) var(--ease),
             border-color var(--m-ui) var(--ease);
}
/* the icon leads by a hair — the object commits to the direction of
   travel fractionally before its surface does */
.btn > svg,.btn .arw{transition:transform var(--m-ui) var(--ease-out)}
.btn.is-lifted > svg,.btn.is-lifted .arw{transform:translateX(2px)}

.btn--solid{
  background-color:var(--ink);color:#fff;
  background-image:radial-gradient(150px 110px at calc(var(--px,.5) * 100%) calc(var(--py,.5) * 100%),
                   rgba(255,255,255,calc(.17 * var(--lift))),transparent 70%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.13),
    0 2px 0 #05101A,
    0 2px 5px rgba(12,23,32,.14);
}
.btn--ghost{
  background-color:transparent;color:var(--ink);border-color:var(--line-2);
  background-image:radial-gradient(150px 110px at calc(var(--px,.5) * 100%) calc(var(--py,.5) * 100%),
                   rgba(14,155,142,calc(.11 * var(--lift))),transparent 70%);
  box-shadow:
    inset 0 1px 0 var(--lit-edge),
    0 2px 0 rgba(196,213,226,.55),
    0 2px 4px rgba(12,23,32,.05);
}
/* Hover lives in a hover-capable query so a touch device can never be
   left stuck in the lifted state after a tap. */
@media (hover:hover) and (pointer:fine){
  .btn:hover{--lift:1}
}
.btn.is-lifted{--lift:1}
.btn--solid.is-lifted,.btn--solid:hover{
  background-color:#14303F;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.18),
    0 4px 0 #05101A,
    0 12px 26px rgba(12,23,32,.19),
    0 2px 6px rgba(12,23,32,.10);
}
.btn--ghost.is-lifted,.btn--ghost:hover{
  border-color:var(--ink-4);background-color:var(--paper);
  box-shadow:
    inset 0 1px 0 var(--lit-edge),
    0 4px 0 rgba(196,213,226,.65),
    0 12px 24px rgba(12,23,32,.09),
    0 2px 5px rgba(12,23,32,.05);
}

/* press — fast, and the only state where the whole object moves down */
.btn.is-pressed,.btn:active{
  transition-duration:var(--m-micro);
  transform:perspective(700px) translateY(1px) scale(.985);
}
.btn--solid.is-pressed,.btn--solid:active{
  box-shadow:
    inset 0 2px 4px rgba(0,0,0,.28),
    0 1px 0 #05101A,
    0 1px 3px rgba(12,23,32,.16);
}
.btn--ghost.is-pressed,.btn--ghost:active{
  box-shadow:
    inset 0 2px 4px rgba(12,23,32,.09),
    0 1px 0 rgba(196,213,226,.6),
    0 1px 3px rgba(12,23,32,.05);
}
.btn--sm{padding:10px 20px;font-size:.85rem}
.btn--lg{padding:17px 36px;font-size:1rem}

/* ── navigation ──────────────────────────────────────────────────
   A floating control surface, not a full-width bar. The rail is the
   physical object: a hairline edge, an inset top highlight for the
   lit bevel, and a two-stage shadow so it reads as suspended above
   the page rather than painted onto it. */
.nav{
  position:fixed;inset-block-start:0;inset-inline:0;z-index:100;
  padding:var(--nav-top) var(--pad) 0;
  pointer-events:none;                     /* page scrolls under the gap */
  perspective:900px;
}
.nav__rail{
  pointer-events:auto;
  max-width:var(--wrap);margin-inline:auto;
  height:var(--nav-h);
  display:flex;align-items:center;gap:var(--s5);
  padding-inline:var(--s5);
  border-radius:100px;
  background:rgba(255,255,255,.72);
  backdrop-filter:blur(20px) saturate(1.8);-webkit-backdrop-filter:blur(20px) saturate(1.8);
  border:1px solid rgba(213,227,238,.85);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    0 1px 2px rgba(12,23,32,.04),
    0 10px 28px rgba(12,23,32,.07);
  /* pointer response — set by nav.js, kept deliberately tiny */
  transform:rotateX(calc(var(--nav-ry, 0) * -.9deg)) rotateY(calc(var(--nav-rx, 0) * 1.1deg));
  transform-style:preserve-3d;
  transition:height .45s var(--ease-out), padding-inline .45s var(--ease-out),
             background .45s var(--ease), box-shadow .45s var(--ease),
             border-color .45s var(--ease), transform .5s var(--ease-out);
}
/* on scroll it compacts and lifts further off the page */
.nav.is-scrolled .nav__rail{
  height:calc(var(--nav-h) - 10px);
  padding-inline:var(--s4);
  background:rgba(255,255,255,.88);
  border-color:rgba(199,217,231,.95);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.95),
    0 2px 4px rgba(12,23,32,.05),
    0 16px 40px rgba(12,23,32,.11);
}
.nav.is-scrolled .brand__ar{opacity:0;max-height:0}

.brand{display:flex;align-items:center;gap:var(--s3);flex-shrink:0;min-width:0}
/* The official logo is only ever scaled — never rotated, recoloured or
   stretched. `object-fit:contain` guarantees the aspect ratio survives
   whatever box it is given. */
.brand__mark{
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
  color:var(--teal);width:30px;height:30px;
  transition:transform .5s var(--ease-out);
}
.brand__img{width:100%;height:100%;object-fit:contain;border-radius:7px;display:block}
.brand__svg{display:none;width:100%;height:100%}
.brand__mark.is-fallback .brand__svg{display:block}
.brand:hover .brand__mark{transform:scale(1.06)}
.nav.is-scrolled .brand__mark{width:26px;height:26px}
.brand__mark--foot{width:40px;height:40px;color:#fff}
.brand__mark--foot .brand__img{border-radius:9px}
.brand__text{display:flex;flex-direction:column;line-height:1.16;min-width:0}
.brand__name{
  font-family:var(--font-display);font-weight:800;font-size:.82rem;
  letter-spacing:.05em;color:var(--ink);white-space:nowrap;
}
.brand__name em{font-style:normal;font-weight:500;color:var(--ink-3)}
.brand__ar{
  font-family:'IBM Plex Sans Arabic',var(--font-body);font-weight:500;
  font-size:.68rem;color:var(--ink-3);white-space:nowrap;
  overflow:hidden;max-height:1.4em;
  transition:opacity .4s var(--ease),max-height .4s var(--ease);
}

/* ── nav links + magnetic highlight ──────────────────────────────
   One shared pill slides between items instead of each item painting
   its own background. That single moving object is what makes the
   surface feel machined rather than merely hovered. */
.nav__links{position:relative;display:flex;align-items:center;gap:2px;margin-inline-start:auto}
/* The pill is a milled slot in the rail's surface, not a coloured
   background: an inner shadow at the top edge where the material was
   removed, and a hairline of returned light at the bottom. The link
   then rises fractionally out of it, so hovering reads as a key being
   pressed on a physical keyboard rather than a colour changing. */
.nav__glow{
  position:absolute;inset-block-start:50%;inset-inline-start:0;
  height:34px;width:0;border-radius:100px;
  background:linear-gradient(180deg,rgba(224,235,243,.95),rgba(240,246,250,.85));
  box-shadow:
    inset 0 1px 2px rgba(12,23,32,.09),
    inset 0 -1px 0 rgba(255,255,255,.9);
  transform:translate(var(--gx,0),-50%) scaleX(var(--gs,1));
  opacity:0;pointer-events:none;
  transition:transform var(--m-ui) var(--ease-out),width var(--m-ui) var(--ease-out),
             opacity var(--m-ui) var(--ease);
}
.nav__links:hover .nav__glow{opacity:1}
.nav__links a{
  position:relative;z-index:1;padding:9px 15px;border-radius:100px;
  font-size:.87rem;font-weight:500;color:var(--ink-2);white-space:nowrap;
  transition:color var(--m-micro) var(--ease),transform var(--m-ui) var(--ease-out),
             text-shadow var(--m-ui) var(--ease);
}
@media (hover:hover) and (pointer:fine){
  .nav__links a:hover{
    color:var(--ink);
    transform:translateY(-1px);
    text-shadow:0 1px 0 rgba(255,255,255,.9);
  }
}
.nav__links a:active{transform:translateY(0);transition-duration:var(--m-micro)}
/* active page — a quiet marker, not a shout */
.nav__links a.is-current{color:var(--ink);font-weight:600}
.nav__links a.is-current::after{
  content:"";position:absolute;inset-block-end:1px;inset-inline-start:50%;
  transform:translateX(-50%);width:5px;height:5px;border-radius:50%;
  background:var(--teal);box-shadow:0 0 0 3px var(--accent-soft);
}
[dir="rtl"] .nav__links a.is-current::after{transform:translateX(50%)}

.nav__actions{display:flex;align-items:center;gap:var(--s3);margin-inline-start:auto}
.nav__links + .nav__actions{margin-inline-start:0}
.lang{display:flex;align-items:center;gap:2px;padding:2px}
.lang__btn{
  font-size:.78rem;font-weight:600;color:var(--ink-4);
  padding:8px;border-radius:8px;transition:color .25s,background .25s;
}
.lang__btn:hover{color:var(--ink-2);background:var(--wash)}
.lang__btn.is-active{color:var(--ink);background:var(--wash)}
.lang__sep{width:1px;height:12px;background:var(--line-2)}

.nav__toggle{
  display:none;width:40px;height:40px;flex-direction:column;
  justify-content:center;align-items:center;gap:5px;border-radius:50%;flex-shrink:0;
  transition:background .3s;
}
.nav__toggle:hover{background:var(--wash)}
.nav__toggle span{display:block;width:17px;height:1.5px;background:var(--ink);border-radius:2px;transition:transform .35s var(--ease),opacity .25s}
.nav__toggle[aria-expanded="true"] span:first-child{transform:translateY(3.25px) rotate(45deg)}
.nav__toggle[aria-expanded="true"] span:last-child{transform:translateY(-3.25px) rotate(-45deg)}

/* Scroll progress. It scales from the leading edge — a bar centred on
   the rail that grows outward in both directions reads as a stray rule
   under the navigation rather than as progress through the page. */
.nav__progress{
  max-width:var(--wrap);margin:6px auto 0;height:2px;border-radius:2px;
  background:linear-gradient(90deg,var(--teal),var(--cyan));
  width:100%;
  transform:scaleX(var(--p,0));transform-origin:left center;
  transition:transform .1s linear,opacity .3s var(--ease);opacity:0;
}
[dir="rtl"] .nav__progress{transform-origin:right center}
.nav.is-scrolled .nav__progress{opacity:1}

/* ── full-screen mobile navigation ───────────────────────────────── */
.sheet{
  position:fixed;inset:0;z-index:120;
  background:linear-gradient(180deg,rgba(255,255,255,.97) 0%,rgba(243,247,250,.98) 100%);
  backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);
  display:flex;align-items:stretch;
  opacity:0;visibility:hidden;
  transition:opacity .34s var(--ease),visibility .34s;
}
.sheet.is-open{opacity:1;visibility:visible}
.sheet[hidden]{display:none}
.sheet__inner{
  width:100%;max-width:var(--wrap);margin-inline:auto;
  padding:calc(var(--nav-h) + var(--nav-top) + var(--s10)) var(--pad) var(--s12);
  display:flex;flex-direction:column;justify-content:space-between;gap:var(--s10);
  overflow-y:auto;
}
.sheet__nav{display:flex;flex-direction:column}
.sheet__nav a{
  display:flex;align-items:baseline;gap:var(--s5);
  padding-block:var(--s5);border-block-end:1px solid var(--line);
  font-family:var(--font-display);font-weight:700;
  font-size:clamp(1.6rem,7vw,2.4rem);letter-spacing:-.03em;color:var(--ink);
  opacity:0;transform:translateY(14px);
  transition:opacity .5s var(--ease-out),transform .5s var(--ease-out),color .25s;
  transition-delay:calc(var(--i) * 45ms + 80ms);
}
.sheet.is-open .sheet__nav a{opacity:1;transform:none}
.sheet__nav a:active{color:var(--teal-d)}
.sheet__nav a.is-current{color:var(--teal-d)}
.sheet__n{
  font-family:var(--font-mono);font-size:.7rem;font-weight:400;
  color:var(--ink-4);letter-spacing:.1em;
}
.sheet__foot{display:flex;flex-direction:column;gap:var(--s5);align-items:flex-start;
  opacity:0;transition:opacity .5s var(--ease-out) .34s}
.sheet.is-open .sheet__foot{opacity:1}
.sheet__foot .btn{width:100%}
.sheet__mail{font-family:var(--font-mono);font-size:var(--t-xs);color:var(--ink-3)}
body.sheet-open{overflow:hidden}

/* ── HERO (home) ─────────────────────────────────────────────────
   Two layers, side by side — never stacked. The text column is plain
   HTML and paints on the first frame; the canvas lives in its own
   column with a reserved aspect-ratio, so it cannot overlap the
   headline and cannot shift the layout when it initialises. */
.hero{
  position:relative;
  overflow:hidden;                        /* the film bleeds past the edges */
  padding-block:calc(var(--nav-space) + clamp(40px,5vw,76px)) clamp(56px,7vw,104px);
  /* The film is lit warm; the site is cool. Without a warm pool
     beneath it the still reads as a photograph pasted onto a cold
     page. This gradient is the join between the two. */
  background:
    radial-gradient(58% 62% at 78% 46%, #F8F5F0 0%, rgba(248,245,240,0) 70%),
    radial-gradient(90% 70% at 80% 38%, #F4FAFC 0%, rgba(244,250,252,0) 62%),
    linear-gradient(180deg,#FFFFFF 0%,#F8FBFD 100%);
  border-block-end:1px solid var(--line);
}
.hero__wrap{
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:clamp(32px,5vw,64px);
  align-items:center;
}
/* A real measure for display type. At 33ch the 64px headline was
   getting five words to a line and orphaning "into the" onto its own —
   the measure, not the size, was what read as amateur.

   Sized as a share of the wrap rather than in ch units, because ch here
   resolves against this element's 16px font and has nothing to do with
   the 57px headline it is supposed to be measuring. The cap also has to
   keep the text clear of the film band, which starts at 52%. */
.hero__text{max-width:min(44%,33rem)}
.hero__lede,.hero__sub{max-width:42ch}
.hero__title{
  font-size:var(--t-hero);
  letter-spacing:-.035em;line-height:1.03;
  text-wrap:balance;
}
.hero__sub{
  margin-block-start:var(--s6);font-family:var(--font-display);font-weight:600;
  font-size:clamp(1.05rem,.23vw + 1rem,1.18rem);color:var(--ink-2);letter-spacing:-.012em;
}
.hero__lede{
  margin-block-start:var(--s4);color:var(--ink-2);
  font-size:clamp(1rem,.04vw + .99rem,1.02rem);line-height:1.75;max-width:46ch;
}
.hero__cta{display:flex;flex-wrap:wrap;gap:var(--s3);margin-block-start:var(--s8)}

/* ── hero brand film ─────────────────────────────────────────────
   Not a media card, and no longer a rectangle sitting in white space.

   The film is a full-height band anchored to the inline end of the
   hero, running off the top, bottom and outer edges. Only ONE edge is
   ever visible — the one facing the text — and that edge is a linear
   fade into the page.

   That single-edge approach is deliberate. The previous attempt used a
   radial vignette sized at 118% of the box, which put its transparent
   stop outside the element entirely: the fade completed off-screen and
   every edge stayed hard. A linear fade across an edge that is actually
   inside the box cannot fail that way, and bleeding the other three
   edges off the section means there is nothing there to soften.

   Being absolutely positioned, it is outside flow entirely, so it
   cannot shift the layout no matter when the image or the film lands. */
.hero__media{
  position:absolute;
  inset-block:0;
  inset-inline-end:0;
  inline-size:clamp(420px,48%,900px);
  margin:0;
  pointer-events:none;                    /* it is scenery, not a control */
  z-index:0;
}
.hero__media-stage{
  position:absolute;inset:0;
  -webkit-mask-image:linear-gradient(to var(--fade-to,right),
    transparent 0%, rgba(0,0,0,.32) 10%, rgba(0,0,0,.86) 22%, #000 34%);
          mask-image:linear-gradient(to var(--fade-to,right),
    transparent 0%, rgba(0,0,0,.32) 10%, rgba(0,0,0,.86) 22%, #000 34%);
}
[dir="rtl"] .hero__media-stage{--fade-to:left}

.hero__media-still,
.hero__media-film{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  /* frames the machined cluster, which sits right-of-centre in the
     source frame, rather than the empty backdrop it floats in */
  object-position:95% 50%;
  display:block;
}
.hero__media-film{
  opacity:0;
  transition:opacity .9s var(--ease);
}
/* A gentle cross-fade, never a reveal — the two images are the same
   composition, so anything more would draw attention to a swap the
   visitor has no reason to notice. */
.hero__media[data-film="playing"] .hero__media-film{opacity:1}

/* Softens where the band meets the top and bottom of the section, so
   it reads as light in the room rather than a cropped photograph.
   Painted rather than masked: the hero's own gradient is the colour
   being blended to, and a mask cannot know that. */
.hero__media::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,
    #FFFFFF 0%, rgba(255,255,255,.55) 9%, rgba(255,255,255,0) 24%,
    rgba(248,251,253,0) 74%, rgba(248,251,253,.72) 93%, #F8FBFD 100%);
}

/* The text wins the stacking contest, but must NOT become the band's
   containing block — the band is positioned against .hero so it can
   bleed past the wrap's max-width to the edge of the section. */
.hero__wrap{z-index:1}
.hero__text{position:relative;z-index:1}

/* ── opening sequence: REGISTRATION ──────────────────────────────
   An overlay above an already-painted hero. It never gates content:
   pointer-events are off, it self-removes on a timer and on the first
   scroll, click or keypress, and it is skipped entirely on repeat
   visits, reduced motion and low-power devices (intro.js decides, CSS
   just plays). If this stylesheet never loads, the page is the page.

   THE ARGUMENT, in six beats:

     0.00  one hairline            something is on
     0.35  it splits into plates   a real system has layers
     1.05  arriving misaligned     the gap between them, made visible
     1.67  snapping into register  what this company actually does
     2.03  converging to one line  one system, not six vendors
     2.10  the logo resolves       the result, earned

   Every plate animates only transform and opacity, on its own layer.
   Six elements, no canvas, no library, nothing fetched.

   The misalignment is SPATIAL, not temporal: every plate shares one
   timing function and one duration, so they reach x=0 on the same
   frame. That simultaneity is the whole point — registration is a
   snap, and staggering it would turn a precision instrument into a
   wave. */
.intro{
  position:fixed;inset:0;z-index:150;pointer-events:none;
  display:grid;place-items:center;
  background:linear-gradient(180deg,#FFFFFF 0%,#FAFCFD 100%);
  animation:introOut .4s var(--ease) 2.72s both;
}
.intro.is-done{display:none}

/* ── the stack ──────────────────────────────────────────────────── */
.intro__stage{
  grid-area:1/1;position:relative;
  width:min(52vmin,320px);height:120px;
  display:grid;place-items:center;
}
.intro__plate{
  grid-area:1/1;
  width:100%;height:2px;border-radius:2px;
  background:var(--c,var(--teal));
  transform-origin:50% 50%;
  will-change:transform,opacity;
  animation:plate 2.05s cubic-bezier(.65,0,.2,1) both;
}

/* Amber at the bottom is the physical layer, teal at the top is
   intelligence — the same two channels the rest of the site uses.
   --y is where the plate settles; --dx is how far out of register it
   arrives before the snap. The dx values alternate sign and vary in
   magnitude so the misalignment reads as real tolerance error rather
   than a pattern. */
.intro__plate:nth-child(1){--y:-42px;--dx: 38px;--c:#17A9CC}
.intro__plate:nth-child(2){--y:-25px;--dx:-26px;--c:#0E9B8E}
.intro__plate:nth-child(3){--y: -8px;--dx: 44px;--c:#0E9B8E}
.intro__plate:nth-child(4){--y:  8px;--dx:-33px;--c:#2E6FD0}
.intro__plate:nth-child(5){--y: 25px;--dx: 21px;--c:#DE8A2A}
.intro__plate:nth-child(6){--y: 42px;--dx:-40px;--c:#DE8A2A}

@keyframes plate{
  /* the signal — a single short rule, held long enough to be noticed */
  0%   {opacity:0;  transform:translate3d(0,0,0) scaleX(.10)}
  8%   {opacity:1;  transform:translate3d(0,0,0) scaleX(.10)}
  16%  {opacity:1;  transform:translate3d(0,0,0) scaleX(.10)}
  /* separation — the stack pulls open, and lands out of register */
  46%  {opacity:1;  transform:translate3d(var(--dx),var(--y),0) scaleX(1)}
  /* registration — every plate reaches x=0 on the same frame */
  74%  {opacity:1;  transform:translate3d(0,var(--y),0) scaleX(1)}
  /* convergence — six become one */
  90%  {opacity:.5; transform:translate3d(0,0,0) scaleX(1)}
  100% {opacity:0;  transform:translate3d(0,0,0) scaleX(.7)}
}

/* ── the brand ──────────────────────────────────────────────────────
   The mark sits dead centre, on the line the plates converge to, so
   the logo resolves out of the convergence rather than arriving over
   it. The wordmark is positioned absolutely below so it cannot shift
   the mark off that point. */
.intro__brand{grid-area:1/1;position:relative;display:grid;place-items:center}
.intro__mark{
  width:72px;height:72px;display:grid;place-items:center;
  opacity:0;animation:markIn .45s var(--ease-out) 1.8s both;
}
.intro__mark.is-fallback{
  width:12px;height:12px;border-radius:50%;
  background:var(--teal);box-shadow:0 0 0 7px var(--accent-soft);
}
/* The logo is never rotated and never distorted. A 6% settle is the
   entire liberty taken with it. */
.intro__logo{width:72px;height:72px;object-fit:contain;border-radius:16px}
.intro__word{
  position:absolute;inset-block-start:calc(50% + 58px);inset-inline-start:50%;
  transform:translateX(-50%);white-space:nowrap;
  font-family:var(--font-display);font-weight:800;
  font-size:clamp(.8rem,2.1vw,1.1rem);letter-spacing:.22em;color:var(--ink);
  /* a mask wipe upward from the baseline, not a letter-by-letter type */
  clip-path:inset(0 0 100% 0);
  animation:wordWipe .48s var(--ease-out) 1.95s both;
}
.intro__word em{font-style:normal;font-weight:400;color:var(--ink-3)}

@keyframes markIn{
  from{opacity:0;transform:scale(.94)}
  to  {opacity:1;transform:scale(1)}
}
@keyframes wordWipe{
  from{clip-path:inset(0 0 100% 0);opacity:0}
  to  {clip-path:inset(0 0 0 0);   opacity:1}
}
@keyframes introOut{to{opacity:0;visibility:hidden}}

/* ── mobile: the same argument, told faster ───────────────────────
   Not a compressed desktop version. Four plates instead of six, a
   tighter spread so the stack stays inside a phone's optical centre,
   and the whole sequence lands in 1.8s because a phone visitor has
   less patience and less GPU. The beats are identical — the story
   does not change, its pacing does. */
@media (max-width:640px){
  .intro__stage{width:min(64vmin,260px);height:86px}
  .intro__plate{animation-duration:1.55s}
  .intro__plate:nth-child(1){--y:-27px;--dx: 26px}
  .intro__plate:nth-child(2){--y: -9px;--dx:-19px}
  .intro__plate:nth-child(5){--y:  9px;--dx: 22px}
  .intro__plate:nth-child(6){--y: 27px;--dx:-28px}
  /* four is enough to read as a stack; six is noise at this size */
  .intro__plate:nth-child(3),
  .intro__plate:nth-child(4){display:none}
  .intro__mark{animation-delay:1.35s;width:60px;height:60px}
  .intro__logo{width:60px;height:60px;border-radius:14px}
  .intro__word{inset-block-start:calc(50% + 48px);animation-delay:1.48s;letter-spacing:.18em}
  .intro{animation-delay:2.22s}
}

/* Nothing here should ever run for someone who asked for less motion.
   intro.js removes the element outright, but if script fails the CSS
   still refuses to animate. */
@media (prefers-reduced-motion:reduce){
  .intro{animation:introOut .01s linear both}
  .intro__plate,.intro__mark,.intro__word{animation:none;opacity:0}
}

/* ── PAGE HERO (inner pages) ─────────────────────────────────────── */
.phero{
  padding-block:calc(var(--nav-space) + clamp(32px,4.5vw,60px)) clamp(40px,5vw,72px);
  background:linear-gradient(180deg,#FFFFFF 0%,var(--wash) 100%);
  border-block-end:1px solid var(--line);
}
.phero__wrap{display:grid;grid-template-columns:minmax(0,1fr);gap:clamp(28px,4vw,56px);align-items:center}
.phero--scene .phero__wrap{grid-template-columns:minmax(0,1.25fr) minmax(0,.75fr)}
.phero__text{max-width:46ch}
.phero__title{font-size:var(--t-h1);letter-spacing:-.03em;text-wrap:balance}
.phero__lede{margin-block-start:var(--s5);color:var(--ink-2);font-size:1.05rem;line-height:1.75;max-width:56ch}
.phero__cta{display:flex;flex-wrap:wrap;gap:var(--s3);margin-block-start:var(--s8)}
.phero__vis{
  position:relative;aspect-ratio:4/3;width:100%;max-width:420px;
  margin-inline:auto;min-height:200px;
}
.phero__vis .scene{position:absolute;inset:0;width:100%;height:100%}

/* ── SERVICES · the brand film ───────────────────────────────────
   Measured, not guessed. The film's plane runs #C0C6CA at its
   lightest to #89959E at its darkest corner; the page runs #FFFFFF
   to #F3F7FA. Dropped in raw, that is a ~50-level step at every edge
   — a grey rectangle on white, which is exactly the "boxed video"
   look this treatment exists to defeat.

   Four moves close that gap, and each one is doing a specific job:

     1. BRIGHTEN  the film 14%, lifting its plane 192 → 219.
     2. POOL      the page toward the film: a cool radial wash painted
                  behind the figure, so the background meets it partway
                  instead of the film having to travel the whole way.
     3. CORNER    the film carries its own vignette toward the lower
                  right; a matching counter-gradient lifts that corner
                  back toward the page tone.
     4. FEATHER   all four edges dissolve inside the box.

   Nothing here touches the middle of the frame, so the structures stay
   at full sharpness — the softening is entirely at the perimeter. */
.phero--media{position:relative;overflow:hidden}
.phero--media .phero__wrap{
  grid-template-columns:minmax(0,1fr) minmax(0,1.12fr);
  gap:clamp(24px,3.2vw,52px);
}

.phero__film{
  position:relative;
  isolation:isolate;
  margin:0;
  aspect-ratio:16/9;
  /* Reaches past the wrap padding toward the outer edge, so it reads as
     part of the page rather than an object sitting inside a column. The
     width has to grow with the negative margin — at a flat 100% the box
     stays pinned to the track and the margin does nothing. */
  width:calc(100% + var(--pad));
  margin-inline-end:calc(-1 * var(--pad));
  pointer-events:none;
}

/* (2) the pool — the page travelling toward the film */
.phero__film::before{
  content:"";position:absolute;z-index:-1;
  inset:-16% -12% -14% -14%;
  background:radial-gradient(58% 60% at 52% 46%,
    #E7EDF0 0%, rgba(231,237,240,.55) 46%, rgba(231,237,240,0) 74%);
}

/* (4) the feather. Two nested single-axis masks — the outer handles the
   inline edges, the inner the block edges, and nesting multiplies them.
   Each gradient completes well inside its own box, which is the part
   that actually matters: a mask whose transparent stop falls outside
   the element fades nothing at all. */
.phero__film-x{
  position:absolute;inset:0;
  -webkit-mask-image:linear-gradient(to right,transparent 0%,#000 14%,#000 86%,transparent 100%);
          mask-image:linear-gradient(to right,transparent 0%,#000 14%,#000 86%,transparent 100%);
}
.phero__film-y{
  position:absolute;inset:0;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0%,#000 13%,#000 85%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0%,#000 13%,#000 85%,transparent 100%);
}

/* (3) the corner counter-gradient. It lives INSIDE the feather so it is
   masked along with the film — painted on the figure it would show as a
   tinted rectangle in the very area the feather just dissolved. */
.phero__film-y::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(315deg,
    rgba(243,247,250,.44) 0%, rgba(243,247,250,.16) 32%, rgba(243,247,250,0) 56%);
}

/* Both layers occupy the same box and crop identically, so the hand-off
   between still and film cannot move a pixel. */
.phero__film-still,
.phero__film-video{
  position:absolute;inset:0;
  width:100%;height:100%;
  object-fit:cover;
  object-position:50% 48%;
  display:block;
  /* (1) — the only colour correction, and it is deliberately small */
  filter:brightness(1.14) saturate(.97);
}
.phero__film-video{
  opacity:0;
  transition:opacity .9s var(--ease);
}
.phero__film[data-film="playing"] .phero__film-video{opacity:1}


/* ── the layers film, in three framings ──────────────────────────
   One clip placed three times. It survives that only because the
   framing changes each time: the two heroes crop 16:9 and show the
   surrounding field wide, the philosophy card crops 1:1 and sits closer
   in. Same material, three compositions.

   Measured: plane luminance 184, saturation 0.098, every edge cool
   (blue > green > red). Close enough to the page that the ordinary
   .phero--media treatment dissolves it — no plate, no field panel,
   none of the machinery the photographic clip needed. */
.phero--media .phero__film-still,
.phero--media .phero__film-video{
  object-position:50% 44%;
}

/* the philosophy card: square, tighter, and sitting on white rather
   than on the page wash */
.layerviz .phero__film--square{
  position:relative;
  aspect-ratio:1/1;
  width:100%;
  max-width:420px;
  margin-inline:auto;
  margin-inline-end:auto;
}
.layerviz .phero__film--square .phero__film-still,
.layerviz .phero__film--square .phero__film-video{
  object-position:50% 50%;
}
/* the card is white, so the film meets a lighter ground than the heroes
   do — the pool is correspondingly lighter and tighter */
.layerviz .phero__film--square::before{
  background:radial-gradient(56% 58% at 50% 48%,
    #EEF3F6 0%, rgba(238,243,246,.5) 48%, rgba(238,243,246,0) 76%);
}

/* ── SYSTEMS · the faint film ────────────────────────────────────
   Every other film on this site had the same problem: too dark for the
   page, close the gap. This one has the opposite problem.

   Measured — field luminance 202, saturation 0.034, and the entire
   frame spans 31 levels (p1 179 → p99 210). Only 0.1% of it is more
   than 35 levels below the field. It is already lighter, flatter and
   more neutral than anything else here, so it blends with no help at
   all. The risk is that outlines this faint simply vanish once they
   are feathered and composited onto a near-white page.

   So the grade RAISES contrast instead of brightness. Both the field
   and the outlines sit well above mid-grey, so pushing contrast lifts
   the field toward the page (better blend) while widening the gap
   between field and outline from 23 levels to 28 (more legible). One
   adjustment, both problems, opposite directions.

   The feather is asymmetric, and the asymmetry is measured rather than
   guessed: column energy runs 0–1 across the left third of the frame
   and 12–18 across the right, so the leading edge can be feathered
   hard through empty field while the trailing edge stays nearly solid
   over the densest content. Block edges are softened but never taken
   fully to zero — row energy peaks top and bottom, and a full fade
   there would erase the outlines that give the frame its depth. */
.phero--faint .phero__film-still,
.phero--faint .phero__film-video{
  object-position:50% 50%;      /* 16:9 in a 16:9 box — nothing is cropped */
  filter:contrast(1.18) saturate(1.05);
}

/* leading edge = the one facing the text, which flips with direction */
.phero--faint .phero__film-x{
  -webkit-mask-image:linear-gradient(to var(--fade-to,right),
    transparent 0%, rgba(0,0,0,.55) 8%, #000 20%, #000 96%, rgba(0,0,0,.88) 100%);
          mask-image:linear-gradient(to var(--fade-to,right),
    transparent 0%, rgba(0,0,0,.55) 8%, #000 20%, #000 96%, rgba(0,0,0,.88) 100%);
}
[dir="rtl"] .phero--faint .phero__film-x{--fade-to:left}

.phero--faint .phero__film-y{
  -webkit-mask-image:linear-gradient(to bottom,
    rgba(0,0,0,.42) 0%, #000 7%, #000 93%, rgba(0,0,0,.42) 100%);
          mask-image:linear-gradient(to bottom,
    rgba(0,0,0,.42) 0%, #000 7%, #000 93%, rgba(0,0,0,.42) 100%);
}

/* the corner counter-gradient is unnecessary here — this film has no
   vignette to fight — so it is switched off rather than left to tint
   an area that needs no correction */
.phero--faint .phero__film-y::after{background:none}

/* a whisper of a pool, only enough to seat it */
.phero--faint .phero__film::before{
  background:radial-gradient(56% 58% at 52% 50%,
    #EFF4F7 0%, rgba(239,244,247,.45) 50%, rgba(239,244,247,0) 78%);
}

/* ── SOLUTIONS · the photographic film, graded into the system ───
   The only photograph on the site, on pages otherwise built from
   light abstract renders. Raw it measures mean luminance 130 and
   saturation 0.109 against a page at 246.

   Two approaches were tried and measured. Arranging the page AROUND
   the photograph — a plate, a tonal field behind it, a heavier scrim —
   closes the gap arithmetically but leaves it looking like a different
   product embedded in the site. The alternative is to change the
   photograph rather than the page.

   Measured across five candidate grades, high-key monochrome lands
   closest to the abstract render used on About and Home:

       raw            mean 130   saturation 0.109   span 193
       this grade     mean 174   saturation 0       span 138
       the render     mean 184   saturation 0.098

   Ten levels apart, and flatter than the render. Once it is neutral and
   high-key it needs none of the special machinery — the ordinary
   .phero--media feather dissolves it like everything else, and the
   geometry stays 16:9 so it is framed identically to the Services,
   About and Systems films rather than getting a bespoke shape.

   Contrast is REDUCED, not raised. Lifting brightness alone would grey
   the whole image toward the page and lose the subject; cutting
   contrast raises the shadows — where the entire tonal gap lives —
   while leaving the highlights near where they already sat. */
.phero--mono .phero__film-still,
.phero--mono .phero__film-video{
  object-position:34% 42%;      /* subject centroid measured at 40%,32% */
  filter:grayscale(1) brightness(1.62) contrast(.68);
}

/* A neutral image on a cool page reads faintly warm by comparison, so
   the scrim that already sits inside the feather carries a light cool
   cast — enough to tie it to the palette, not enough to be a duotone. */
.phero--mono .phero__film-y::after{
  background:
    linear-gradient(315deg,
      rgba(226,234,240,.42) 0%, rgba(226,234,240,.15) 34%, rgba(226,234,240,0) 58%),
    linear-gradient(0deg, rgba(214,226,235,.16), rgba(214,226,235,.16));
}

/* seated in the same cool pool the other films use, a touch stronger
   because this one starts further from the page than they do */
.phero--mono .phero__film::before{
  background:radial-gradient(58% 60% at 52% 48%,
    #E4EBF0 0%, rgba(228,235,240,.55) 46%, rgba(228,235,240,0) 76%);
}




.crumb{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2);
  margin-block-end:var(--s5);font-size:var(--t-xs);color:var(--ink-3);
}
.crumb a{transition:color .25s}
.crumb a:hover{color:var(--teal-d)}
.crumb i{font-style:normal;color:var(--ink-4)}
.crumb span[aria-current]{color:var(--ink-2);font-weight:500}

/* ── CTA band ────────────────────────────────────────────────────── */
/* ── the connection layer ────────────────────────────────────────
   The closing section of every page. A hexagonal engineered surface
   recedes into depth behind the content; the content itself floats
   clearly above it.

   Readability is guaranteed structurally, not by luck: the canvas is
   masked to fade out of the centre of the section, so the area the
   text occupies is always the quietest part of the field regardless of
   what the scene decides to draw there. The text needs no scrim, no
   blur backdrop and no opacity compromise. */
.cta-band{
  position:relative;isolation:isolate;
  padding-block:clamp(72px,9vw,132px);
  background:linear-gradient(180deg,var(--paper) 0%,var(--wash) 100%);
  border-block-start:1px solid var(--line);text-align:center;
  overflow:hidden;
}
.cta-band__env{
  position:absolute;inset:0;z-index:-1;pointer-events:none;
  -webkit-mask-image:radial-gradient(64% 78% at 50% 48%,transparent 0%,rgba(0,0,0,.42) 46%,#000 78%);
          mask-image:radial-gradient(64% 78% at 50% 48%,transparent 0%,rgba(0,0,0,.42) 46%,#000 78%);
}
.cta-band__env .scene{position:absolute;inset:0;width:100%;height:100%}
.cta-band__inner{position:relative;z-index:1}
.cta-band__eyebrow{justify-content:center;display:flex}
.cta-band__title{font-size:var(--t-h2);letter-spacing:-.028em;margin-block-start:var(--s3)}
.cta-band__lede{margin-block-start:var(--s5);color:var(--ink-2);max-width:52ch;margin-inline:auto;line-height:1.75}

/* ── the email, as the primary object ────────────────────────────
   The address is the contact method — there is no form — so it is
   typeset as a thing you act on, not as body copy that happens to be
   a link. The rule beneath it draws in from the leading edge on
   hover, which in RTL means the right. */
.cta-band__mail{
  display:flex;align-items:center;justify-content:center;flex-wrap:wrap;
  gap:var(--s3);margin-block-start:var(--s8);
}
.maillink{
  position:relative;display:inline-block;
  font-family:var(--font-mono);
  font-size:clamp(1rem,.9vw + .8rem,1.32rem);
  letter-spacing:-.01em;color:var(--ink);
  padding-block-end:4px;
  transition:color var(--m-ui) var(--ease),transform var(--m-ui) var(--ease-out);
}
[dir="rtl"] .maillink{direction:ltr}
.maillink__rule{
  position:absolute;inset-block-end:0;inset-inline-start:0;
  height:1.5px;width:100%;background:var(--teal);
  transform:scaleX(0);transform-origin:left center;
  transition:transform var(--m-ui) var(--ease-out);
}
[dir="rtl"] .maillink__rule{transform-origin:right center}
@media (hover:hover) and (pointer:fine){
  .maillink:hover{color:var(--teal-d);transform:translateY(-1px)}
  .maillink:hover .maillink__rule{transform:scaleX(1)}
}
.maillink:focus-visible .maillink__rule{transform:scaleX(1)}

.copybtn{
  --lift:0;
  position:relative;
  padding:9px 16px;border-radius:100px;
  border:1px solid var(--line-2);background-color:var(--paper);
  background-image:radial-gradient(90px 70px at calc(var(--px,.5) * 100%) calc(var(--py,.5) * 100%),
                   rgba(14,155,142,calc(.12 * var(--lift))),transparent 70%);
  font-family:var(--font-display);font-weight:600;font-size:.78rem;color:var(--ink-2);
  box-shadow:
    inset 0 1px 0 var(--lit-edge),
    0 2px 0 rgba(196,213,226,.5),
    0 2px 4px rgba(12,23,32,.05);
  transform:translateY(calc(var(--lift) * -2px));
  transition:transform var(--m-ui) var(--ease-out),box-shadow var(--m-ui) var(--ease-out),
             color var(--m-ui) var(--ease),border-color var(--m-ui) var(--ease);
}
@media (hover:hover) and (pointer:fine){ .copybtn:hover{--lift:1} }
.copybtn.is-lifted,.copybtn:hover{
  color:var(--ink);border-color:var(--ink-4);
  box-shadow:
    inset 0 1px 0 var(--lit-edge),
    0 4px 0 rgba(196,213,226,.6),
    0 10px 20px rgba(12,23,32,.08);
}
.copybtn.is-pressed,.copybtn:active{
  transform:translateY(1px);transition-duration:var(--m-micro);
  box-shadow:inset 0 2px 4px rgba(12,23,32,.09),0 1px 0 rgba(196,213,226,.55);
}
/* Confirmation swaps on the button's own face. Both labels are in the
   DOM and stacked, so the button's width never changes and the row
   cannot reflow at the moment of feedback. */
.copybtn__face{position:relative;display:grid}
.copybtn__label,.copybtn__done{
  grid-area:1/1;transition:opacity var(--m-ui) var(--ease),transform var(--m-ui) var(--ease-out);
}
.copybtn__done{opacity:0;transform:translateY(4px);color:var(--teal-d)}
.copybtn.is-copied{border-color:rgba(14,155,142,.5)}
.copybtn.is-copied .copybtn__label{opacity:0;transform:translateY(-4px)}
.copybtn.is-copied .copybtn__done{opacity:1;transform:none}

.cta-band__actions{display:flex;flex-wrap:wrap;gap:var(--s3);justify-content:center;margin-block-start:var(--s8)}

/* ── footer ──────────────────────────────────────────────────────── */
.foot{background:var(--ink);color:#fff;padding-block:clamp(48px,6vw,80px) var(--s8)}
.foot__grid{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,2fr);gap:clamp(32px,5vw,64px)}
.foot__name{font-family:var(--font-display);font-size:1.1rem;font-weight:800;letter-spacing:.03em}
.foot__name em{font-style:normal;font-weight:400;color:rgba(255,255,255,.55)}
.foot__arname{font-family:'IBM Plex Sans Arabic',var(--font-body);font-size:.92rem;color:rgba(255,255,255,.62);margin-block-start:var(--s2)}
.foot__tag{margin-block-start:var(--s4);max-width:34ch;color:rgba(255,255,255,.55);font-size:var(--t-sm);line-height:1.7}
.foot__mail{
  display:inline-block;margin-block-start:var(--s5);font-family:var(--font-mono);
  font-size:var(--t-xs);color:rgba(255,255,255,.75);
  border-block-end:1px solid rgba(255,255,255,.25);padding-block-end:2px;transition:color .25s,border-color .25s;
}
.foot__mail:hover{color:#fff;border-block-end-color:#fff}
.foot__lockup{display:flex;align-items:center;gap:var(--s4)}
/* A professional connection point, not a social bar */
.foot__li{
  display:inline-flex;align-items:center;gap:var(--s2);
  margin-block-start:var(--s5);padding:8px 14px;border-radius:100px;
  border:1px solid rgba(255,255,255,.18);color:rgba(255,255,255,.75);
  font-size:var(--t-xs);font-weight:500;
  transition:border-color .25s,color .25s,background .25s;
}
.foot__li:hover{border-color:rgba(255,255,255,.4);color:#fff;background:rgba(255,255,255,.06)}
.foot__nav{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--s6)}
.foot__ct{
  font-family:var(--font-mono);font-size:.64rem;font-weight:400;letter-spacing:.16em;
  text-transform:uppercase;color:rgba(255,255,255,.42);margin-block-end:var(--s4);
}
[dir="rtl"] .foot__ct{font-family:var(--font-body);letter-spacing:0;text-transform:none;font-size:.78rem;font-weight:600}
.foot__col a{display:block;padding-block:6px;font-size:.86rem;color:rgba(255,255,255,.72);transition:color .25s}
.foot__col a:hover{color:#fff}
.foot__base{
  margin-block-start:clamp(36px,4.5vw,56px);padding-block-start:var(--s6);
  border-block-start:1px solid rgba(255,255,255,.11);
  display:flex;flex-wrap:wrap;gap:var(--s3) var(--s6);justify-content:space-between;
  font-size:var(--t-xs);color:rgba(255,255,255,.42);
}

/* ── reveal ──────────────────────────────────────────────────────── */
.js .reveal{opacity:0;transform:translateY(20px);transition:opacity .8s var(--ease-out),transform .8s var(--ease-out)}
.reveal.is-in{opacity:1;transform:none}

/* ── page transition ─────────────────────────────────────────────── */
@view-transition{navigation:auto}
.js .page-leave{opacity:.35;transition:opacity .18s ease-out}

/* ── responsive ──────────────────────────────────────────────────── */

@media (max-width:1024px){
  .hero__wrap{grid-template-columns:minmax(0,1fr);gap:var(--s10)}
  .hero__text{max-width:38ch}
  /* Below the desktop breakpoint the band becomes a normal block
     under the message — it is the supporting voice, not the headline.
     Back in flow, so it reserves its own space again. */
  .hero__wrap{grid-template-columns:minmax(0,1fr)}
  .hero__media{
    position:relative;inset:auto;
    inline-size:100%;max-width:620px;margin-inline:auto;
    aspect-ratio:16/10;order:2;
  }
  /* ── the film's edges on mobile ────────────────────────────────
     This was a single radial vignette, and it did not fade anything.
     Measured on a 397x298 box: the gradient's transparent stop sat at
     92% of a radius of .88H, which is 262px, while the top edge is only
     143px from the centre — 55% of the way out, where alpha is still
     ~0.93. Three of the four edges were effectively opaque, so the film
     read as a photograph pasted onto the page. The comment on the page
     hero's feather states the rule this broke: a mask whose transparent
     stop falls outside the element fades nothing at all.

     Replaced with the technique that is already proven on .phero__film:
     two nested SINGLE-AXIS masks, the outer box handling the inline
     edges and the inner the block edges. Nesting multiplies them, so
     all four edges feather, and each gradient completes well inside its
     own box — which is the only thing that actually matters.

     Masking rather than painting, because the hero's background here is
     a radial gradient stack, not a flat colour. A painted blend would
     have to guess one colour and would be visibly wrong wherever the
     gradient is not that colour; a mask dissolves to whatever is
     actually behind it. */
  .hero__media{
    -webkit-mask-image:linear-gradient(to right,transparent 0%,#000 8%,#000 92%,transparent 100%);
            mask-image:linear-gradient(to right,transparent 0%,#000 8%,#000 92%,transparent 100%);
  }
  .hero__media-stage{
    -webkit-mask-image:linear-gradient(to bottom,transparent 0%,#000 16%,#000 82%,transparent 100%);
            mask-image:linear-gradient(to bottom,transparent 0%,#000 16%,#000 82%,transparent 100%);
  }
  .hero__media::after{display:none}
  .hero__text{max-width:min(100%,34rem)}
  .phero--scene .phero__wrap{grid-template-columns:minmax(0,1fr)}
  /* the film returns to normal flow beneath the message */
  .phero--media .phero__wrap{grid-template-columns:minmax(0,1fr)}
  .phero__film{order:2;width:100%;margin-inline-end:0;max-width:640px;margin-inline:auto}
  .layerviz .phero__film--square{max-width:340px}
  .phero__vis{max-width:340px;order:2}
  .foot__nav{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* Between the full desktop rail and the mobile sheet there is a band
   where brand + six links + language + CTA no longer fit inside the
   pill. The CTA yields first — it is repeated in the hero, the closing
   band and the footer, so nothing is lost. */
@media (max-width:1180px){
  .nav__cta{display:none}
  .nav__rail{gap:var(--s4)}
  .nav__links a{padding:8px 11px;font-size:.85rem}
}

@media (max-width:960px){
  :root{--nav-h:58px;--nav-top:10px}
  /* the desktop link row is replaced by the full-screen sheet */
  .nav__links{display:none}
  .nav__toggle{display:flex}
  .nav__cta{display:none}
  /* the brand must yield, or it pushes the menu button off-screen */
  .nav__rail{gap:var(--s3);padding-inline:var(--s3) var(--s2)}
  .brand{flex-shrink:1}
  .brand__name,.brand__ar{overflow:hidden;text-overflow:ellipsis}
  .nav__actions{margin-inline-start:auto;gap:var(--s2);flex-shrink:0}
  .foot__grid{grid-template-columns:minmax(0,1fr)}
}
@media (max-width:620px){
  .hero__text{max-width:none}
  .hero__cta .btn,.cta-band__actions .btn{flex:1 1 100%}
  /* Never shrink it into meaninglessness: it goes full-bleed-ish and
     keeps a generous crop of the subject rather than getting smaller. */
  .hero__media{max-width:100%;aspect-ratio:4/3}
  .hero__media-still,.hero__media-film{object-position:70% 46%}
  .foot__nav{grid-template-columns:minmax(0,1fr)}
  .foot__base{flex-direction:column}
}
/* ── phone refinements ───────────────────────────────────────────
   Display type is drawn for large sizes: tight tracking and a 1.03
   line-height look precise at 84px and cramped at 33px, where the
   descenders of one line nearly meet the caps of the next. Both are
   relaxed here — the same typeface, set for the size it is actually
   being read at.

   Touch targets are the other half of this. The audit found 28 controls
   under the 44px minimum on the homepage; the ones below are the real
   ones a thumb goes for. Their hit area grows without their visual
   weight changing, so the design is untouched and the target is not. */
@media (max-width:620px){
  .hero__title{line-height:1.1;letter-spacing:-.02em}
  .phero__title,.shead__title,.cta-band__title{line-height:1.15;letter-spacing:-.018em}
  .hero__sub{margin-block-start:var(--s5)}

  /* headline measure: let it use the full column on a phone */
  .hero__text{max-width:none}
  .phero__text{max-width:none}
  .shead__lede,.phero__lede{max-width:none}

  /* generous, thumb-sized controls */
  .lang__btn{min-height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:center}
  .nav__toggle{min-height:44px;min-width:44px}
  .crumb a,.crumb span{padding-block:12px}
  .contact__links a{padding-block:11px}
  .foot__col a{padding-block:11px}
  .foot__base a{padding-block:8px;display:inline-block}
  .sheet__nav a{min-height:52px;display:flex;align-items:center}

  /* full-width primary actions read as buttons, not as links */
  .phero__cta .btn{flex:1 1 100%}

  /* the remaining real thumb targets: inline links that carry an action */
  .scard__more{padding-block:12px;display:inline-block}
  .copybtn{min-height:44px}
  .maillink{padding-block:11px}
  .foot__mail,.foot__li{min-height:44px;display:inline-flex;align-items:center}
  .brand{min-height:44px}
}

@media (max-width:400px){
  .brand__name em{display:none}
  .brand__name{font-size:.76rem}
  .brand__ar{font-size:.62rem}
}
@media (min-width:1800px){
  :root{--wrap:1380px}
  body{font-size:1.05rem}
}

/* ── language switch: suppress transitions across the dir flip ───── */
.lang-switching *,.lang-switching *::before,.lang-switching *::after{
  transition:none !important;animation:none !important;
}

/* ── reduced motion ──────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;scroll-behavior:auto !important;
  }
  .js .reveal{opacity:1 !important;transform:none !important}
  .js .page-leave{opacity:1}
  /* No opening sequence, no rail tilt, no button tilt.
     The guides are deliberately NOT hidden: a visitor who prefers
     reduced motion still deserves to be told that the demos are real
     software. They get the words without the choreography — onboard.js
     skips the travel and the mimed click. Only decorative pulses are
     suppressed here. */
  .intro{display:none !important}
  .nav__rail{transform:none !important}
  .btn{transform:none !important}
  .hint__dot{animation:none !important}
  .dguide__ripple{display:none !important}
  .is-guided,.is-hinted{animation:none !important}
}
