/* ============================================================
   SAKKARY MACHINERY — base and chrome · MIXED BANDS
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Opening the request modal locks scrolling; without a reserved
     gutter the scrollbar vanishes and the whole page jumps sideways. */
  scrollbar-gutter: stable;
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, video, svg { display: block; max-width: 100%; }
img, video { height: auto; }
[hidden] { display: none !important; }

h1, h2, h3, h4 { margin: 0; font-weight: 700; line-height: var(--lh-snug); }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; }

:focus-visible { outline: 2px solid var(--accent-bright); outline-offset: 3px; border-radius: var(--r-1); }
::selection { background: var(--accent-fill); color: #fff; }

/* ---------- Primitives ---------- */

.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.section { position: relative; padding-block: var(--section-y); }
.band { background: var(--bg); color: var(--fg); }
/* .band--tint is declared in tokens.css, which loads first — without
   this the generic .band rule below it would win and repaint it white. */
.band.band--tint { background: var(--bg-alt); }

.spec {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-mono);
  text-transform: uppercase;
  color: var(--fg-3);
  font-weight: 500;
}
.spec--hot  { color: var(--accent); }
.spec--cold { color: var(--cool); }

.eyebrow { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-4); }
.eyebrow::before {
  content: "";
  width: 38px; height: 2px; flex: none;
  background: var(--accent-bright);
}
.eyebrow--center { justify-content: center; }
/* The section label carries more weight than a caption — it is the
   first thing read in each band, so it sits a step above the other
   mono labels rather than at the micro size. */
.eyebrow .spec { font-size: var(--fs-xs); font-weight: 600; }

.h-display {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-display);
  text-transform: uppercase;
}
.h-section {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-2xl);
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-display);
  text-transform: uppercase;
}
.lede { color: var(--fg-2); font-size: var(--fs-lg); max-width: var(--maxw-text); }
.h-display + .lede, .h-section + .lede { margin-top: var(--s-4); }

/* ============================================================
   BUTTONS — a wipe fills from the leading edge, the label rides
   above it, and on a fine pointer the button leans toward you.
   ============================================================ */

.btn {
  --btn-fg: var(--fg);
  --btn-bd: var(--line);
  --btn-wipe: var(--accent-fill);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 50px;
  padding: 0 var(--s-6);
  color: var(--btn-fg);
  background: transparent;
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-1);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  overflow: hidden;
  isolation: isolate;
  will-change: transform;
  /* the magnetic offset lives in custom properties so the pressed
     scale composes with it rather than overwriting it */
  transform: translate(var(--mx, 0px), var(--my, 0px));
  transition: color var(--dur-2) var(--ease-cut),
              border-color var(--dur-2) var(--ease-cut),
              transform 320ms var(--ease-cut);
}
.btn > * { position: relative; z-index: 1; }
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  /* -1, not 0. .btn isolates, so a negative layer still paints above
     the button's own background — but below its inline content. At 0
     the wipe painted OVER a bare text label, because a positioned
     z-index:0 descendant comes after inline content in paint order.
     Only labels wrapped in an element were safe, via .btn > *. */
  z-index: -1;
  background: var(--btn-wipe);
  transform: scaleX(0);
  /* transform-origin takes no logical keywords — `inline-start` is
     invalid and the whole declaration gets dropped, leaving the
     default 50% 50%, so the wipe grew out of the middle of the button
     instead of sweeping across it. Physical values, mirrored for RTL. */
  transform-origin: left center;
  transition: transform 420ms var(--ease-cut);
}
:root[dir="rtl"] .btn::before { transform-origin: right center; }
.btn:hover::before, .btn:focus-visible::before { transform: scaleX(1); }
.btn:active { transform: translate(var(--mx, 0px), var(--my, 0px)) scale(.97); }
.btn[disabled] { opacity: .45; pointer-events: none; }

.btn--primary {
  --btn-fg: var(--accent-on);
  --btn-bd: var(--accent-fill);
  --btn-wipe: #B3121F;
  background: var(--accent-fill);
}
.btn--primary:hover { --btn-bd: #B3121F; }

.btn--ghost { --btn-bd: var(--line); }
.btn--ghost:hover, .btn--ghost:focus-visible { --btn-fg: var(--accent-on); --btn-bd: var(--accent-fill); }

.btn__ico { width: 16px; height: 16px; flex: none; transition: transform var(--dur-2) var(--ease-cut); }
.btn:hover .btn__ico--arrow { transform: translateX(4px); }
:root[dir="rtl"] .btn__ico--arrow { transform: scaleX(-1); }
:root[dir="rtl"] .btn:hover .btn__ico--arrow { transform: scaleX(-1) translateX(4px); }

/* ============================================================
   CURSOR — a dot that tracks exactly and a ring that trails it.
   White + difference blending so one cursor reads on the white
   bands, the graphite bands and the photography alike.
   Only ever enabled on a fine pointer, by JS.
   ============================================================ */

.cursor { position: fixed; inset: 0; pointer-events: none; z-index: var(--z-cursor); display: none; }
html.has-cursor .cursor { display: block; }
html.has-cursor,
html.has-cursor a,
html.has-cursor button,
html.has-cursor label,
html.has-cursor input,
html.has-cursor select,
html.has-cursor textarea { cursor: none; }

/* Brand blue, lifted just enough to clear 4:1 against BOTH the white
   bands and the graphite ones — a blended white cursor vanished on
   the white sections. Red takes over when you are over something
   clickable, so the two brand colours carry the two pointer states. */
.cursor__dot, .cursor__ring {
  position: absolute;
  top: 0; left: 0;
  border-radius: 50%;
  will-change: transform;
}
.cursor__dot {
  width: 8px; height: 8px;
  margin: -4px 0 0 -4px;
  background: var(--cursor-c);
  transition: opacity var(--dur-2), transform var(--dur-2) var(--ease-cut), background var(--dur-2);
}
.cursor__ring {
  width: 34px; height: 34px;
  margin: -17px 0 0 -17px;
  border: 1.5px solid var(--cursor-c);
  transition: width var(--dur-3) var(--ease-cut),
              height var(--dur-3) var(--ease-cut),
              margin var(--dur-3) var(--ease-cut),
              opacity var(--dur-2),
              border-color var(--dur-2);
}
.cursor[data-state="link"] .cursor__dot  { background: var(--cursor-hot); }
.cursor[data-state="link"] .cursor__ring { border-color: var(--cursor-hot); }
/* over something clickable the ring opens up and the dot gets out of the way */
.cursor[data-state="link"] .cursor__ring { width: 58px; height: 58px; margin: -29px 0 0 -29px; }
.cursor[data-state="link"] .cursor__dot { opacity: 0; transform: scale(.4); }
.cursor[data-state="text"] .cursor__ring { width: 20px; height: 20px; margin: -10px 0 0 -10px; opacity: .5; }
.cursor[data-state="down"] .cursor__ring { width: 26px; height: 26px; margin: -13px 0 0 -13px; }
.cursor[data-hidden="true"] .cursor__dot,
.cursor[data-hidden="true"] .cursor__ring { opacity: 0; }

/* While a modal is open the pointer goes back to the system one.
   `revert` rather than `auto` so the UA stylesheet still supplies the
   I-beam over inputs and the pointer over links and buttons — a blanket
   `auto` would flatten all of them to a plain arrow. */
html.cursor-off .cursor { display: none; }
html.has-cursor.cursor-off,
html.has-cursor.cursor-off input,
html.has-cursor.cursor-off textarea { cursor: revert; }
/* Buttons get `default` from the UA stylesheet, not `pointer` — inside
   a form that reads as "not clickable", so state it. */
html.has-cursor.cursor-off a,
html.has-cursor.cursor-off button,
html.has-cursor.cursor-off label,
html.has-cursor.cursor-off select,
html.has-cursor.cursor-off summary { cursor: pointer; }

@media (prefers-reduced-motion: reduce) {
  html.has-cursor .cursor { display: none; }
  html.has-cursor, html.has-cursor * { cursor: auto; }
}

/* ---------- Header ----------
   It sits over the dark hero to begin with, so it starts light-on-dark
   and repaints to the page's own palette once it sticks. */

.header {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  color: #F2F4F7;
  border-bottom: 1px solid transparent;
  transition: background var(--dur-3) var(--ease-cut),
              color var(--dur-3) var(--ease-cut),
              border-color var(--dur-3) var(--ease-cut);
}
/* No backdrop-filter here on purpose. The header sticks after 24px of
   scroll, which is exactly while the hero video is still on screen and
   playing — so a blur would re-filter a full-width strip of moving
   video on every frame. At 96% opacity the blur was contributing almost
   nothing visually and costing a great deal. */
.header[data-stuck="true"] {
  background: rgba(255, 255, 255, .96);
  border-bottom-color: var(--line);
  color: #14161A;
}
.header__in {
  width: 100%; max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex; align-items: center; gap: var(--s-5);
}

.brand { display: flex; align-items: center; gap: var(--s-3); flex: none; }
.brand__mark { width: 30px; height: 42px; }
.brand__txt { display: flex; flex-direction: column; line-height: 1; }
.brand__name {
  font-family: var(--font-display);
  font-weight: 700; font-size: 1.0625rem;
  letter-spacing: .04em; text-transform: uppercase;
}
.brand__since {
  font-family: var(--font-mono); font-size: 9px;
  letter-spacing: .22em; opacity: .62; margin-top: 3px;
}

.nav { display: flex; align-items: center; gap: var(--s-1); margin-inline-start: auto; }
.nav__link {
  position: relative;
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  opacity: .78;
  transition: opacity var(--dur-2) var(--ease-cut);
}
.nav__link::after {
  content: "";
  position: absolute;
  inset-inline: var(--s-3);
  bottom: 2px; height: 1px;
  background: var(--accent-bright);
  transform: scaleX(0);
  transform-origin: inline-start;
  transition: transform var(--dur-2) var(--ease-cut);
}
.nav__link:hover { opacity: 1; }
.nav__link:hover::after, .nav__link[aria-current="true"]::after { transform: scaleX(1); }
.nav__link[aria-current="true"] { opacity: 1; }

.header__act { display: flex; align-items: center; gap: var(--s-3); flex: none; }
.header__cta { min-height: 42px; padding-inline: var(--s-5); }

.lang { display: inline-flex; border: 1px solid currentColor; border-radius: var(--r-1); opacity: .55; transition: opacity var(--dur-2); }
.lang:hover { opacity: 1; }
.lang__b {
  /* Explicit box, because this is a <button> on the home page and an
     <a> on the blog (where switching language is a different URL, not
     a CSS toggle). A button centres its label on its own; an inline
     anchor ignores min-width and min-height entirely and sits on the
     baseline. Same rule, same result either way. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px; min-height: 34px;
  padding: 0 var(--s-2);
  background: transparent; border: 0;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em;
  line-height: 1;
  text-decoration: none;
  color: inherit; opacity: .7;
}
.lang__b[aria-pressed="true"],
.lang__b[aria-current="true"] { opacity: 1; background: rgba(128, 128, 128, .22); }

.burger {
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  background: transparent;
  border: 1px solid currentColor;
  border-radius: var(--r-1);
  opacity: .8;
}
.burger__bars { width: 18px; height: 12px; position: relative; }
.burger__bars i {
  position: absolute; inset-inline: 0; height: 1.5px; background: currentColor;
  transition: transform var(--dur-2) var(--ease-cut), opacity var(--dur-1);
}
.burger__bars i:nth-child(1) { top: 0; }
.burger__bars i:nth-child(2) { top: 5px; }
.burger__bars i:nth-child(3) { top: 10px; }
.burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.burger[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] i:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

/* ---------- Drawer ---------- */

.drawer {
  position: fixed; inset: 0;
  z-index: var(--z-drawer);
  background: #0B0C0F;
  color: #F2F4F7;
  padding: calc(var(--header-h) + var(--s-6)) var(--gutter) var(--s-7);
  display: flex; flex-direction: column; gap: var(--s-2);
  opacity: 0; visibility: hidden; transform: translateY(-8px);
  transition: opacity var(--dur-3) var(--ease-cut),
              transform var(--dur-3) var(--ease-cut),
              visibility var(--dur-3);
}
.drawer[data-open="true"] { opacity: 1; visibility: visible; transform: none; }
.drawer__link {
  padding: var(--s-4) 0;
  border-bottom: 1px solid rgba(255,255,255,.1);
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  text-transform: uppercase;
}
.drawer__link:hover { color: #F46B85; }
.drawer .btn { margin-top: var(--s-5); --btn-bd: rgba(255,255,255,.24); }
.drawer__lang { margin-top: var(--s-5); align-self: flex-start; opacity: 1; }
.drawer__lang .lang__b { min-height: 44px; min-width: 56px; }

/* While the drawer is open the header floats over a dark overlay, so
   it drops its light background and goes light-on-dark to match. */
:root.drawer-open .header,
:root.drawer-open .header[data-stuck="true"] {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  color: #F2F4F7;
}

@media (max-width: 1080px) {
  .nav { display: none; }
  .header__act { margin-inline-start: auto; }
  .burger { display: inline-flex; }
  /* The language toggle stays out in the open on phones — switching
     to Arabic should not require opening a menu first. */
}
@media (max-width: 720px) { .header__cta { display: none; } }
@media (max-width: 420px) {
  .header__in { gap: var(--s-3); }
  .lang__b { min-width: 36px; }
  .brand__since { display: none; }
}
@media (min-width: 1081px) { .drawer { display: none; } }

/* ---------- Scroll progress: a hairline across the very top ---------- */
.progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  height: 2px;
  z-index: calc(var(--z-header) + 1);
  background: transparent;
  pointer-events: none;
}
.progress__bar {
  height: 100%;
  width: var(--p, 0%);
  background: linear-gradient(90deg, var(--blue-deep), var(--red));
}
:root[dir="rtl"] .progress__bar { margin-inline-start: auto; }

/* ============================================================
   REVEALS — progressive enhancement, as in the other builds
   ============================================================ */

.cut-in { position: relative; display: inline-block; }
:root.js-anim .cut-in { clip-path: inset(0 100% 0 0); transition: clip-path 600ms var(--ease-cut); }
:root.js-anim[dir="rtl"] .cut-in { clip-path: inset(0 0 0 100%); }
:root.js-anim .cut-in.is-in { clip-path: inset(0 0 0 0); }
:root.js-anim .cut-in.cut-done { clip-path: none; transition: none; }
:root.js-anim .cut-in::after {
  content: "";
  position: absolute;
  inset-block: -5%;
  inset-inline-start: -1px;
  width: 2px;
  background: var(--accent-bright);
  opacity: 0;
}
:root.js-anim .cut-in.is-in::after { animation: edge-run 600ms var(--ease-cut) forwards; }
:root.js-anim .cut-in.cut-done::after { display: none; }
@keyframes edge-run {
  0%   { opacity: 1; inset-inline-start: 0; }
  90%  { opacity: 1; inset-inline-start: 100%; }
  100% { opacity: 0; inset-inline-start: 100%; }
}

:root.js-anim .rise {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 460ms var(--ease-cut), transform 460ms var(--ease-cut);
  transition-delay: var(--d, 0ms);
}
:root.js-anim .rise.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .cut-in { clip-path: none !important; }
  .cut-in::after { display: none !important; }
  .rise { opacity: 1 !important; transform: none !important; transition: none; }
  .btn { transform: none !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ---------- Boot ---------- */

.boot {
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  display: grid; place-items: center;
  background: #0B0C0F;
  transition: opacity 600ms var(--ease-cut), visibility 600ms;
}
/* pointer-events drops the instant the loader is done, without waiting
   on the fade. A transition that never completes — throttled tab,
   backgrounded load, compositor asleep — would otherwise leave a
   full-screen overlay swallowing every tap on the page. */
.boot[data-done="true"] { opacity: 0; visibility: hidden; pointer-events: none; }
.boot__in { display: flex; flex-direction: column; align-items: center; gap: var(--s-5); }
.boot__mark { width: 46px; height: 64px; }
.boot__bar { width: min(220px, 46vw); height: 1px; background: rgba(255,255,255,.16); position: relative; }
.boot__bar::after {
  content: "";
  position: absolute; inset-block: 0; inset-inline-start: 0;
  width: var(--boot, 0%);
  background: var(--red);
  transition: width 220ms var(--ease-cut);
}
.boot__pct {
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tr-mono);
  color: #7E858F;
}

/* ---------- Skip link ---------- */
.skip {
  position: absolute;
  inset-inline-start: var(--s-4);
  top: -80px;
  z-index: var(--z-modal);
  padding: var(--s-3) var(--s-4);
  background: var(--accent-fill);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  border-radius: var(--r-1);
  transition: top var(--dur-2) var(--ease-cut);
}
.skip:focus { top: var(--s-4); }

:root[data-lang="en"] .lang-ar,
:root[data-lang="ar"] .lang-en { display: none !important; }

/* ---------- floating actions + a11y helper ----------
   Moved here from sections.css: these are global chrome, present
   on every server-rendered page through the shared request-form
   partial, but sections.css is only loaded by the home page. With
   no .wa-fab rule the button's <svg viewBox="0 0 20 20"> has no
   size constraint and expands to the full page width. */

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.wa-fab {
  position: fixed;
  inset-block-end: max(18px, env(safe-area-inset-bottom));
  inset-inline-end: 18px;
  z-index: var(--z-header);
  width: 56px; height: 56px;
  display: grid; place-items: center;
  background: #128C7E;
  color: #fff;
  border: 0;
  border-radius: 50%;
  box-shadow: 0 6px 20px -6px rgba(18, 140, 126, .7), var(--shadow-2);
  transition: transform var(--dur-2) var(--ease-cut), background var(--dur-2);
}
.wa-fab:hover, .wa-fab:focus-visible { transform: scale(1.07); background: #0F7A6D; }
.wa-fab:active { transform: scale(.96); }
.wa-fab svg { width: 26px; height: 26px; position: relative; z-index: 1; }

/* A slow expanding ring — enough to draw the eye back every few
   seconds without nagging. */
.wa-fab__pulse {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #25D366;
  opacity: .55;
  animation: wa-pulse 2.8s var(--ease-cut) infinite;
}
@keyframes wa-pulse {
  0%        { transform: scale(1);    opacity: .5; }
  70%, 100% { transform: scale(1.85); opacity: 0; }
}
.wa-fab:hover .wa-fab__pulse { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { .wa-fab__pulse { display: none; } }

/* ---------- Back to top ----------
   Mirrors the WhatsApp bubble on the opposite side. Both use logical
   inset properties, so in Arabic they swap together and stay opposite
   rather than landing on top of each other. */
.top-fab {
  position: fixed;
  inset-block-end: max(18px, env(safe-area-inset-bottom));
  inset-inline-start: 18px;
  z-index: var(--z-header);
  width: 52px; height: 52px;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .94);
  color: #14161A;
  border: 1px solid var(--line);
  border-radius: 50%;
  box-shadow: var(--shadow-2);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur-3) var(--ease-cut),
              transform var(--dur-3) var(--ease-cut),
              background var(--dur-2), color var(--dur-2);
}
.top-fab[data-show="true"] { opacity: 1; transform: none; }
.top-fab:hover, .top-fab:focus-visible { background: var(--accent-fill); color: #fff; border-color: var(--accent-fill); }
.top-fab:active { transform: scale(.95); }
.top-fab svg { width: 22px; height: 22px; }
@media (max-width: 520px) { .top-fab { width: 46px; height: 46px; } .top-fab svg { width: 20px; height: 20px; } }
