/* =========================================================================
   Next Maroc Digital — design system
   Cinematic, editorial, story-driven. Every animation is gated behind the
   html.js class (added by base.html) and prefers-reduced-motion, so the
   site stays fully readable without JavaScript or with motion disabled.
   ========================================================================= */

/* -------------------------------------------------------------------------
   0. Fonts — self-hosted (static/fonts/, see the README there).
   Inter Tight (display, brand) and Inter (text) from the corporate design,
   IBM Plex Sans Arabic (Arabic), JetBrains Mono (code).
   Nothing is requested from Google any more, so no visitor IP reaches Google
   for typography. Files and unicode ranges are the ones Google's CSS API
   served to the former <link> in base.html, limited to the latin, latin-ext
   and arabic subsets the three site languages need. font-display: swap keeps
   text visible while a file loads.
   ------------------------------------------------------------------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-400-700-normal-latin.260c81a4759b.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-400-700-normal-latin-ext.1ad231aac0a8.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../fonts/inter-tight-500-700-normal-latin.f5af7a761c2b.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../fonts/inter-tight-500-700-normal-latin-ext.496654ac82a3.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-normal-latin.b636a65da4f0.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-normal-latin-ext.bd4781a31b42.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-normal-latin.b636a65da4f0.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/jetbrains-mono-400-normal-latin-ext.bd4781a31b42.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-400-normal-arabic.4fa3d81d41ab.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-400-normal-latin.4767e1197706.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-400-normal-latin-ext.8f47bcb71f45.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-500-normal-arabic.106892212ea7.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-500-normal-latin.80ebc672c915.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-500-normal-latin-ext.71f4c6840dd1.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-600-normal-arabic.64891a810259.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-600-normal-latin.f417eeb0d15e.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-600-normal-latin-ext.73f6208660e9.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-700-normal-arabic.a4390abc98c2.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC, U+102E0-102FB, U+10E60-10E7E, U+10EC2-10EC7, U+10EC9-10EEE, U+10EF0-10EFF, U+1EE00-1EE03, U+1EE05-1EE1F, U+1EE21-1EE22, U+1EE24, U+1EE27, U+1EE29-1EE32, U+1EE34-1EE37, U+1EE39, U+1EE3B, U+1EE42, U+1EE47, U+1EE49, U+1EE4B, U+1EE4D-1EE4F, U+1EE51-1EE52, U+1EE54, U+1EE57, U+1EE59, U+1EE5B, U+1EE5D, U+1EE5F, U+1EE61-1EE62, U+1EE64, U+1EE67-1EE6A, U+1EE6C-1EE72, U+1EE74-1EE77, U+1EE79-1EE7C, U+1EE7E, U+1EE80-1EE89, U+1EE8B-1EE9B, U+1EEA1-1EEA3, U+1EEA5-1EEA9, U+1EEAB-1EEBB, U+1EEF0-1EEF1;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-700-normal-latin.8d04403cf599.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans Arabic";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-arabic-700-normal-latin-ext.8f4b1a9530f1.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* -------------------------------------------------------------------------
   1. Tokens
   ------------------------------------------------------------------------- */
:root {
  --bg: #f3f5f8;
  --surface: #ffffff;
  --surface-2: #e8ecf1;
  --ink: #0b1d33;
  --ink-2: #3a4350;
  --muted: #5a6472;
  --line: #e3e7ec;
  --line-2: #c9d0d8;

  --dark: #0b1d33;
  --dark-2: #122640;
  --dark-3: #1b2f4a;
  --on-dark: #ffffff;
  --on-dark-2: #c9d2de;
  --on-dark-muted: #8f9bab;
  --dark-line: rgba(255, 255, 255, 0.09);

  --blue: #0b1d33;
  --blue-2: #0f7a52;
  --blue-glow: #2fb07c;
  --teal: #0f7a52;
  --teal-2: #2fb07c;
  --teal-ink: #0f7a52;
  --teal-soft: #e6f3ed;
  --grad-brand: linear-gradient(135deg, var(--blue) 0%, var(--blue) 100%); /* flat navy: the brand has no gradients */

  /* contextual tokens — redefined inside dark contexts below */
  --heading: var(--ink);
  --text: var(--ink-2);
  --muted-c: var(--muted);
  --line-c: var(--line);
  --accent-text: var(--teal-ink);

  --font-display: "Inter Tight", "Inter Display", "Inter", system-ui, sans-serif;
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
  --font-ar: "IBM Plex Sans Arabic", "Noto Naskh Arabic", "Segoe UI", Tahoma, sans-serif;

  --container-w: 1240px;
  --gutter: clamp(20px, 4vw, 40px);
  --header-h: 76px;

  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-xl: 16px;

  --shadow-sm: 0 2px 12px rgba(11, 29, 51, 0.06);
  --shadow-md: 0 24px 60px -24px rgba(11, 29, 51, 0.28);
  --shadow-glow: 0 18px 50px -16px rgba(47, 176, 124, 0.45);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.45, 0.64, 1);
  --dur: 1s;
}

.cta-card,
.aside-card-accent,
.solution-card-other,
.site-footer {
  --heading: #ffffff;
  --text: var(--on-dark-2);
  --muted-c: var(--on-dark-muted);
  --line-c: var(--dark-line);
  --accent-text: var(--teal-2);
}

/* -------------------------------------------------------------------------
   2. Base
   ------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 16px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
/* the open menu locks the page scroll; the padding stands in for the vanished
   scrollbar (--nav-sbw, measured by main.js) so nothing slides sideways */
body.nav-open { overflow: hidden; padding-inline-end: var(--nav-sbw, 0px); }

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

a { color: inherit; text-decoration: none; }
img, svg, canvas { max-width: 100%; display: block; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; }

h1, h2, h3, h4 {
  margin: 0 0 0.5em;
  line-height: 1.15;
  font-weight: 600;
  color: var(--heading);
  letter-spacing: -0.02em;
  text-wrap: balance;
}
p { margin: 0 0 1em; color: var(--text); }

:focus-visible {
  outline: 2px solid #1e63c7;
  outline-offset: 3px;
  border-radius: 4px;
}

.container {
  width: 100%;
  max-width: var(--container-w);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* -------------------------------------------------------------------------
   3. Typography
   ------------------------------------------------------------------------- */
.display {
  font-size: clamp(2.4rem, 4.8vw, 4.15rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  font-weight: 600;
}
.h-display {
  font-size: clamp(1.9rem, 4vw, 3.2rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 600;
}
.lead {
  font-size: clamp(1.05rem, 1.35vw, 1.22rem);
  line-height: 1.65;
  max-width: 56ch;
  color: var(--text);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 20px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.eyebrow-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 0 4px rgba(47, 176, 124, 0.18);
  animation: pulse 2.4s ease-in-out infinite;
}

.index {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.12em;
  color: var(--muted-c);
}
.index::after {
  content: "";
  width: 40px;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

/* Read highlight: words light up as the reading line passes */
.read .rw { opacity: 0.28; transition: opacity 0.45s ease; }
.read .rw.on { opacity: 1; }

/* -------------------------------------------------------------------------
   4. Buttons (magnetic, shine sweep, ripple)
   ------------------------------------------------------------------------- */
.btn {
  --tx: 0px;
  --ty: 0px;
  --lift: 0px;
  --press: 1;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 24px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.2;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  isolation: isolate;
  transform: translate3d(var(--tx), calc(var(--ty) + var(--lift)), 0) scale(var(--press));
  transition: transform 0.45s var(--ease), box-shadow 0.45s var(--ease), background 0.3s ease, color 0.3s ease, border-color 0.3s ease;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.btn > * { position: relative; z-index: 2; }
.btn:hover { --lift: -2px; }
.btn:active { --press: 0.97; }
.btn-arrow {
  font-size: 1.05em;
  transition: transform 0.4s var(--ease);
}
.btn:hover .btn-arrow { transform: translateX(5px); }

.btn::before {
  content: "";
  position: absolute;
  inset: -1px;
  z-index: 1;
  background: linear-gradient(115deg, transparent 32%, rgba(255, 255, 255, 0.38) 50%, transparent 68%);
  transform: translateX(-130%) skewX(-12deg);
  transition: transform 0.9s var(--ease);
  pointer-events: none;
}
.btn:hover::before { transform: translateX(130%) skewX(-12deg); }
.btn-outline::before { background: linear-gradient(115deg, transparent 32%, rgba(255, 255, 255, 0.18) 50%, transparent 68%); }

.ripple {
  position: absolute;
  z-index: 1;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.25;
  transform: scale(0);
  animation: ripple 0.75s ease-out forwards;
  pointer-events: none;
}

.btn-cta {
  background: var(--grad-brand);
  color: #fff;
  box-shadow: 0 10px 30px -12px rgba(11, 29, 51, 0.6);
}
.btn-cta:hover { box-shadow: var(--shadow-glow), 0 0 0 1px rgba(255, 255, 255, 0.12) inset; }
.btn-light {
  background: #fff;
  color: var(--ink);
}
.btn-light:hover { background: var(--teal-soft); box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.5); }
.btn-ghost {
  background: rgba(255, 255, 255, 0.55);
  border-color: rgba(11, 29, 51, 0.14);
  color: var(--ink);
  backdrop-filter: blur(8px);
}
.btn-ghost:hover {
  background: #fff;
  border-color: var(--teal);
}
.btn-outline {
  background: transparent;
  border-color: var(--line-2);
  color: var(--ink);
}
.btn-outline:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}
.btn-sm { padding: 10px 18px; font-size: 0.88rem; }
.btn-lg { padding: 16px 30px; font-size: 1.02rem; }
.btn-block { width: 100%; }

/* -------------------------------------------------------------------------
   5. Header
   ------------------------------------------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  z-index: 200;
  background: linear-gradient(90deg, var(--teal-2), var(--blue-glow));
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

.site-header {
  position: fixed;
  top: 0;
  inset-inline: 0;
  z-index: 100;
  padding-top: 18px; /* a little air above the capsule, so it sits with the hero rather than on the edge */
  transition: transform 0.7s var(--ease);
}
@media (max-width: 575.98px) { .site-header { padding-top: 12px; } }
.site-header.is-hidden { transform: translateY(-130%); }
body.nav-open .site-header { transform: none; padding-inline-end: var(--nav-sbw, 0px); }
.site-header .container { padding: 0 12px; }

/* The shell, after the "Margin" Framer template: one small white capsule,
   centred, holding only the logo and a "Menu" pill, at every screen size.
   The Menu pill expands the capsule into a card listing the pages, the hub
   sub-pages (chevrons), the language switch and the CTA. Its radius is half
   its closed height, so it reads as a capsule closed and a rounded card open. */
.nav-shell {
  --nav-fg: var(--ink);
  --nav-fg-inv: #fff;
  --nav-muted: var(--muted);
  --nav-line: rgba(11, 29, 51, 0.16);
  --nav-hover: var(--surface-2);
  --nav-radius: 26px;
  --nav-item-h: 36px;
  --dd-line: rgba(11, 29, 51, 0.12);
  --dd-hover: var(--surface-2);
  --dd-icon-bg: var(--teal-soft);
  --dd-icon-fg: var(--teal-ink);
  --dd-accent: var(--teal-ink);
  position: relative;
  isolation: isolate;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px;
  width: 100%;
  max-width: 400px;
  margin-inline: auto;
  padding: 6px;
  border-radius: var(--nav-radius);
  border: 1px solid rgba(11, 29, 51, 0.07); /* a hairline, not an outline: the shadow carries the edge */
  background: #fff;
  color: var(--nav-fg);
  box-shadow: 0 1px 2px rgba(11, 29, 51, 0.06), 0 10px 30px -8px rgba(11, 29, 51, 0.16);
  transition: box-shadow 0.5s var(--ease), transform 0.5s var(--ease);
}
/* while main.js animates the card between its closed and open sizes: the
   animated width may pass the class's max-width, and the list is clipped */
.nav-shell.is-morphing { max-width: none; overflow: hidden; }
.site-header.is-scrolled .nav-shell { box-shadow: 0 1px 2px rgba(11, 29, 51, 0.06), 0 14px 40px -6px rgba(11, 29, 51, 0.22); }
/* hover on the closed capsule: it lifts a touch and its shadow deepens */
@media (hover: hover) {
  body:not(.nav-open) .nav-shell:hover {
    transform: translateY(-2px);
    box-shadow: 0 2px 4px rgba(11, 29, 51, 0.06), 0 18px 44px -10px rgba(11, 29, 51, 0.28);
  }
  .nav-shell .navbar-brand { transition: opacity 0.3s ease; }
  .nav-shell .navbar-brand:hover { opacity: 0.72; }
}

.navbar-brand {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  color: inherit;
}
.nav-shell .navbar-brand { height: var(--nav-item-h); padding: 0 10px; }
/* smaller than the footer logo: the capsule is 52px tall */
.nav-shell .navbar-brand .brand-logo--full { height: 24px; }
.nav-shell .navbar-brand .brand-logo--mark { height: 22px; }

/* the "Menu" pill (label + hamburger); reads "Fermer" + cross while open */
.navbar-toggler {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  height: var(--nav-item-h);
  padding-inline: 14px 12px;
  border-radius: 999px;
  border: 1px solid var(--nav-line);
  background: transparent;
  color: inherit;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.3s ease, background 0.3s ease, color 0.3s ease;
}
/* hover: the pill fills navy and the hamburger bars spread a little */
body:not(.nav-open) .navbar-toggler:hover { background: var(--ink); border-color: var(--ink); color: #fff; }
body:not(.nav-open) .navbar-toggler:hover .navbar-toggler-icon::before { top: -6px; }
body:not(.nav-open) .navbar-toggler:hover .navbar-toggler-icon::after { top: 6px; }
body.nav-open .navbar-toggler:hover { background: var(--surface-2); border-color: var(--nav-line); }
body.nav-open .navbar-toggler { background: var(--nav-hover); border-color: transparent; }
/* both labels share one grid cell, so the pill keeps the width of the longer one */
.navbar-toggler-label { display: grid; justify-items: center; }
.navbar-toggler-label > span { grid-area: 1 / 1; }
.navbar-toggler .is-open,
body.nav-open .navbar-toggler .is-closed { visibility: hidden; }
body.nav-open .navbar-toggler .is-open { visibility: visible; }
body.is-rtl .navbar-toggler { font-family: var(--font-ar); font-size: 0.8rem; letter-spacing: 0; }
.navbar-toggler-icon {
  position: relative;
  display: block;
  width: 16px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: background 0.2s ease;
}
.navbar-toggler-icon::before,
.navbar-toggler-icon::after {
  content: "";
  position: absolute;
  left: 0;
  width: 16px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.45s var(--ease), top 0.45s var(--ease);
}
.navbar-toggler-icon::before { top: -5px; }
.navbar-toggler-icon::after { top: 5px; }
body.nav-open .navbar-toggler-icon { background: transparent; }
body.nav-open .navbar-toggler-icon::before { top: 0; transform: rotate(45deg); }
body.nav-open .navbar-toggler-icon::after { top: 0; transform: rotate(-45deg); }

/* the expanded list, under the logo row; the page behind is dimmed.
   Without JavaScript the list is simply always open. */
.navbar-collapse { display: none; transition: opacity 0.25s ease; }
/* just opened: the card is still growing, so clicks wait until it settles (main.js) */
.navbar-collapse.is-settling { pointer-events: none; }
/* closing: the list fades while the card folds around it, then hides (main.js) */
.navbar-collapse.is-closing { opacity: 0; pointer-events: none; transition-duration: 0.18s; }
.navbar-collapse.show,
html:not(.js) .navbar-collapse {
  flex-basis: 100%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0 2px;
  max-height: calc(100vh - 100px);
  max-height: calc(100dvh - 100px);
  overflow-y: auto;
  overscroll-behavior: contain;
  animation: overlay-in 0.3s var(--ease) both;
}
html:not(.js) .navbar-toggler { display: none; }
body.nav-open::after,
body.nav-closing::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 98; /* above the cookie banner (95), under the header (100) */
  background: rgba(11, 29, 51, 0.24);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  animation: overlay-in 0.4s var(--ease) both;
}
body.nav-closing:not(.nav-open)::after { pointer-events: none; animation: overlay-out 0.36s var(--ease) both; }

.main-nav { display: flex; flex-direction: column; gap: 1px; }
.main-nav .nav-link {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 6px 12px;
  border-radius: 14px;
  font-size: 0.94rem;
  font-weight: 500;
  color: var(--nav-fg);
  transition: background 0.25s ease;
}
.main-nav .nav-link:hover,
.main-nav .nav-link.active { background: var(--nav-hover); }
/* the current page: a green point before its label */
.main-nav .nav-link.active::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--teal);
}
.navbar-collapse.show .main-nav > li { animation: nav-rise 0.45s var(--ease) both; }
.navbar-collapse.show .main-nav > li:nth-child(2) { animation-delay: 0.04s; }
.navbar-collapse.show .main-nav > li:nth-child(3) { animation-delay: 0.08s; }
.navbar-collapse.show .main-nav > li:nth-child(4) { animation-delay: 0.12s; }
.navbar-collapse.show .main-nav > li:nth-child(5) { animation-delay: 0.16s; }
.navbar-collapse.show .main-nav > li:nth-child(6) { animation-delay: 0.2s; }
.navbar-collapse.show .nav-actions { animation: nav-rise 0.45s var(--ease) 0.24s both; }
@keyframes nav-rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@keyframes nav-swap {
  from { opacity: 0; transform: translateX(var(--swap-from, 16px)); }
  to { opacity: 1; transform: none; }
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 2px 2px;
  border-top: 1px solid var(--nav-line);
}
.lang-switch {
  flex: none;
  display: inline-flex;
  height: var(--nav-item-h);
  padding: 3px;
  border-radius: 999px;
  border: 1px solid var(--nav-line);
}
.lang-form { display: flex; }
.lang-btn {
  height: 100%;
  border: 0;
  background: transparent;
  color: var(--nav-muted);
  padding: 0 10px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: background 0.3s var(--ease), color 0.25s ease;
}
.lang-btn:hover { color: var(--nav-fg); background: var(--nav-hover); }
.lang-btn.active { color: var(--nav-fg-inv); background: var(--nav-fg); }
/* the pill shell gets a pill button: the one exception to the radius-sm rule of section 24 */
.nav-shell .nav-cta {
  flex: 1 1 auto;
  height: var(--nav-item-h);
  padding: 0 16px;
  border-radius: 999px;
  font-size: 0.84rem;
  box-shadow: none;
}
.nav-shell .nav-cta:hover { box-shadow: 0 10px 24px -10px rgba(11, 29, 51, 0.45); }

/* -------------------------------------------------------------------------
   5b. Hub sub-lists (nav)
   One <li class="has-dropdown"> holds the hub link, a chevron button and the
   list of its sub-pages, which the chevron expands inline as a plain
   one-column list. The hub link itself goes to the hub page.
   ------------------------------------------------------------------------- */
.has-dropdown {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}
.has-dropdown > .nav-link { flex: 1 1 0; min-width: 0; }
.has-dropdown.is-open > .nav-link { background: var(--nav-hover); }
.nav-sub-toggle {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 14px;
  border: 1px solid var(--nav-line);
  background: transparent;
  color: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  transition: transform 0.45s var(--ease), background 0.3s ease, border-color 0.3s ease;
}
.nav-sub-toggle:hover { background: var(--nav-hover); }
.has-dropdown.is-open .nav-sub-toggle { transform: rotate(180deg); background: var(--nav-hover); border-color: transparent; }
.nav-dropdown { flex-basis: 100%; display: none; }
.has-dropdown.is-open .nav-dropdown {
  display: block;
  margin-inline-start: 17px; /* under the label, after the active dot */
  padding: 2px 0 6px;
  padding-inline-start: 8px;
  border-inline-start: 1px solid var(--nav-line);
  animation: nav-rise 0.35s var(--ease) both;
}
.nav-dropdown-list { display: flex; flex-direction: column; gap: 1px; }
.nav-sub-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 8px;
  border-radius: 12px;
  font-size: 0.88rem;
  font-weight: 500;
  color: inherit;
  transition: background 0.25s ease;
}
.nav-sub-link:hover { background: var(--dd-hover); }
.nav-sub-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--dd-icon-bg);
  color: var(--dd-icon-fg);
  font-size: 0.85rem;
  transition: background 0.3s ease, color 0.3s ease;
}
.nav-sub-link:hover .nav-sub-icon { background: var(--grad-brand); color: #fff; }
/* last row of a panel: the contact page, for a need the list does not name */
.nav-sub-other { margin-top: 4px; color: var(--dd-accent); }
.nav-sub-other .btn-arrow { margin-inline-start: auto; transition: transform 0.35s var(--ease); }
.nav-sub-other:hover .btn-arrow { transform: translateX(5px); }
/* teaser entry ("soon"): blurred, tagged, linked to nothing */
.nav-sub-link.is-soon { cursor: default; opacity: 0.55; }
.nav-sub-link.is-soon:hover { background: transparent; }
.nav-sub-link.is-soon:hover .nav-sub-icon { background: var(--dd-icon-bg); color: var(--dd-icon-fg); }
.nav-sub-link.is-soon .nav-sub-icon,
.nav-sub-link.is-soon .nav-sub-text { filter: blur(1.2px); }
.nav-sub-tag {
  flex: none;
  margin-inline-start: auto;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--dd-line);
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 0.58rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--dd-accent);
}
/* the hub template also prints a short label (IA / AI); the list always has room for the full one */
.nav-label-short { display: none; }

/* -------------------------------------------------------------------------
   5c. Wide screens: the open capsule grows into a wide, low card. The pages
   sit in one row, the language switch and the CTA in a footer row, and an
   open hub drops its sub-pages into a tinted panel under the row, its groups
   side by side as columns of equal width, each listed top to bottom.
   .has-dropdown becomes display: contents so its label joins the row and its
   panel can wrap below it (the ::after spacer forces the break); the chevron
   button is hidden here and drawn inside the label pill instead.
   ------------------------------------------------------------------------- */
@media (min-width: 960px) {
  body.nav-open .nav-shell,
  html:not(.js) .nav-shell { max-width: 880px; }
  .navbar-collapse.show,
  html:not(.js) .navbar-collapse { gap: 10px; padding: 10px 4px 4px; }

  .main-nav { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 0 2px; }
  .main-nav::after { content: ""; order: 1; flex-basis: 100%; }
  .main-nav > li:not(.has-dropdown) { flex: none; }
  .has-dropdown { display: contents; }
  .has-dropdown > .nav-link { flex: none; }
  .main-nav .nav-link {
    min-height: 38px;
    padding: 6px 14px;
    border-radius: 999px;
    white-space: nowrap;
  }
  /* one control, not two: hovering or focusing the label opens the panel and a
     click goes to the hub page (main.js), so the separate chevron button goes
     away and a chevron joins the pill instead */
  .nav-sub-toggle { display: none; }
  .has-dropdown > .nav-link::after {
    content: "";
    flex: none;
    width: 11px;
    height: 11px;
    opacity: 0.5;
    background: currentColor;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 5.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 5.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
    transition: transform 0.35s var(--ease), opacity 0.3s ease;
  }
  .has-dropdown.is-open > .nav-link::after { transform: rotate(180deg); opacity: 1; }

  .has-dropdown.is-open .nav-dropdown {
    order: 2;
    flex-basis: 100%;
    margin: 8px 0 0;
    padding: 10px;
    border: 0;
    border-radius: 18px;
    background: rgba(11, 29, 51, 0.035);
  }
  /* one column per group (Solutions: by sector, by function), sharing the
     width equally; a hub without groups flows its one list into two balanced
     columns instead, so its panel is not left half empty either */
  .nav-sub-groups {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: 0 8px;
  }
  .nav-sub-col:only-child .nav-dropdown-list { display: block; columns: 2; column-gap: 8px; }
  .nav-sub-col:only-child .nav-dropdown-list > li { break-inside: avoid; padding-bottom: 1px; }
  /* the columns are wide: the "soon" tag stays beside its label */
  .nav-dropdown .nav-sub-tag { margin-inline-start: 0; }
  /* switching straight from one hub to the other (main.js): the tinted panel
     stays and eases to its new height, its content slides in from the side
     of the new label instead of the whole panel rising again */
  .has-dropdown.is-swapped-in .nav-dropdown { animation: none; overflow: hidden; }
  .has-dropdown.is-swapped-in .nav-dropdown-inner { animation: nav-swap 0.34s var(--ease) both; }
  .nav-dropdown .nav-sub-link { padding: 6px 10px; }
  .nav-dropdown .nav-sub-link:hover { background: #fff; }
  .nav-sub-other { display: inline-flex; margin-top: 8px; }

  .nav-actions { justify-content: space-between; padding: 10px 4px 2px; border-top-color: rgba(11, 29, 51, 0.08); }
  .nav-shell .nav-cta { flex: none; }
}

/* -------------------------------------------------------------------------
   6. Flash messages (fixed toasts under the header)
   ------------------------------------------------------------------------- */
.flash-stack {
  position: fixed;
  top: calc(var(--header-h) + 12px);
  inset-inline: 0;
  z-index: 90;
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 0 var(--gutter);
  pointer-events: none;
}
.alert {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-radius: 999px;
  font-size: 0.95rem;
  font-weight: 500;
  box-shadow: 0 20px 50px -20px rgba(11, 29, 51, 0.35);
  animation: flash-in 0.6s var(--ease) both;
}
.alert i { font-size: 1.15rem; }
.alert-success { background: #ecfdf5; color: #047857; border: 1px solid #a7f3d0; }
.alert-danger, .alert-error { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
.alert-info, .alert-warning { background: var(--teal-soft); color: #0b5c3e; border: 1px solid #bfe3d2; }
.contact-form .alert { border-radius: 14px; animation: none; box-shadow: none; }

/* -------------------------------------------------------------------------
   7. Atmosphere: living canvas, orbs, grid, grain
   ------------------------------------------------------------------------- */
.hero-bg,
.section-bg,
.cta-bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: clip; /* clip, not hidden: the ribbon's sticky pane (28) must find no scroll container above it */
  pointer-events: none;
}
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 1;
  filter: saturate(0.85) brightness(1.04);
}
.hero-video-shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(243, 245, 248, 0.9), rgba(243, 245, 248, 0.66) 40%, rgba(243, 245, 248, 0.96)),
    radial-gradient(70% 60% at 30% 50%, rgba(243, 245, 248, 0.72), transparent 70%);
}
.ambient-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.22;
  filter: saturate(1.1);
}

/* Stock-footage panels: a clip in a glass frame, lit by its own measured accent */
.clip {
  --clip-accent: var(--teal);
  --clip-base: var(--dark-2);
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: 24px;
  background: var(--clip-base);
  box-shadow:
    0 0 0 1px rgba(11, 29, 51, 0.08),
    0 30px 80px -30px color-mix(in srgb, var(--clip-accent) 60%, transparent),
    0 20px 50px -30px rgba(11, 29, 51, 0.4);
  transition: transform 0.7s var(--ease), box-shadow 0.7s var(--ease);
}
.clip-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.clip-landscape { aspect-ratio: 16 / 10; }
.clip-portrait { aspect-ratio: 9 / 16; }
.clip-glow {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 55%, color-mix(in srgb, var(--clip-base) 70%, #000));
  box-shadow: inset 0 0 90px color-mix(in srgb, var(--clip-accent) 28%, transparent);
  pointer-events: none;
}
.clip-frame {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
  pointer-events: none;
}
.clip:hover { box-shadow: 0 0 0 1px color-mix(in srgb, var(--clip-accent) 60%, transparent), 0 40px 100px -30px color-mix(in srgb, var(--clip-accent) 75%, transparent), 0 20px 50px -30px rgba(11, 29, 51, 0.4); }

/* portrait clip beside inner page headlines */
.page-hero-grid {
  display: grid;
  gap: 40px;
  align-items: center;
}
.page-hero-media { display: none; }
@media (min-width: 992px) {
  .page-hero-grid { grid-template-columns: minmax(0, 1fr) 300px; gap: 64px; }
  .page-hero-media { display: block; }
  .hero-panel {
    width: 100%;
    max-width: 300px;
    transform: rotate(-3deg);
    animation: float 9s ease-in-out infinite;
  }
  .hero-panel:hover { transform: rotate(0deg) scale(1.02); animation-play-state: paused; }
}

.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.75;
  -webkit-mask-image: radial-gradient(ellipse at 58% 45%, #000 35%, transparent 85%);
  mask-image: radial-gradient(ellipse at 58% 45%, #000 35%, transparent 85%);
}
.page-hero .hero-canvas { opacity: 0.5; }
.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.6;
  will-change: transform;
}
.orb-1 {
  width: min(70vw, 820px);
  height: min(70vw, 820px);
  top: -28%;
  inset-inline-start: -14%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.65), transparent 62%);
  animation: drift 22s ease-in-out infinite alternate;
}
.orb-2 {
  width: min(55vw, 640px);
  height: min(55vw, 640px);
  bottom: -30%;
  inset-inline-end: -10%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.55), transparent 62%);
  animation: drift 26s ease-in-out infinite alternate-reverse;
}
.orb-3 {
  width: min(36vw, 420px);
  height: min(36vw, 420px);
  top: 30%;
  inset-inline-end: 22%;
  background: radial-gradient(circle, rgba(47, 176, 124, 0.35), transparent 62%);
  animation: drift 30s ease-in-out infinite alternate;
  opacity: 0.45;
}
.orb-a {
  width: min(60vw, 700px);
  height: min(60vw, 700px);
  top: -20%;
  inset-inline-end: -16%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.4), transparent 62%);
  animation: drift 28s ease-in-out infinite alternate;
}
.orb-c1 {
  width: 60%;
  padding-top: 60%;
  top: -40%;
  inset-inline-start: -15%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.7), transparent 62%);
}
.orb-c2 {
  width: 50%;
  padding-top: 50%;
  bottom: -45%;
  inset-inline-end: -10%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.6), transparent 62%);
}
.grid-lines {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(11, 29, 51, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 29, 51, 0.06) 1px, transparent 1px);
  background-size: 72px 72px;
  -webkit-mask-image: radial-gradient(ellipse at 55% 40%, #000 25%, transparent 72%);
  mask-image: radial-gradient(ellipse at 55% 40%, #000 25%, transparent 72%);
}
.noise {
  position: absolute;
  inset: 0;
  opacity: 0.08;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* -------------------------------------------------------------------------
   8. Hero (home)
   ------------------------------------------------------------------------- */
.hero {
  position: relative;
  isolation: isolate;
  overflow: clip; /* clip, not hidden: the ribbon's sticky pane (28) must find no scroll container above it */
  display: flex;
  align-items: center;
  padding: calc(var(--header-h) + 48px) 0 72px;
  background: var(--bg);
  color: var(--ink);
}
@media (min-width: 768px) {
  .hero { min-height: min(100svh, 960px); padding-top: calc(var(--header-h) + 32px); }
}
.hero-grid {
  position: relative;
  display: grid;
  gap: 56px;
  align-items: center;
}
@media (min-width: 992px) {
  .hero-grid { grid-template-columns: 1.2fr 0.8fr; gap: 40px; }
}
.hero-copy { max-width: 780px; }
.hero-copy .display { margin-bottom: 28px; }
.hero-copy .lead { margin-bottom: 36px; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; }

.hero-visual {
  position: relative;
  width: 100%;
  max-width: 520px;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
}
.hero-halo {
  position: absolute;
  inset: 10%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.35), rgba(15, 122, 82, 0.12) 45%, transparent 70%);
  filter: blur(30px);
}
.hero-layer {
  position: absolute;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
}
.layer-1 { top: 8%; inset-inline-start: 2%; }
.layer-2 { top: 20%; inset-inline-end: 0; }
.layer-3 { bottom: 20%; inset-inline-start: 0; }
.layer-4 { bottom: 6%; inset-inline-end: 4%; }
.layer-core {
  top: 50%;
  inset-inline-start: 50%;
  transform: translate3d(calc(-50% + var(--px, 0px)), calc(-50% + var(--py, 0px)), 0);
}
body.is-rtl .layer-core {
  transform: translate3d(calc(50% + var(--px, 0px)), calc(-50% + var(--py, 0px)), 0);
}

.hero-card {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 14px 20px 14px 14px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 30px 60px -30px rgba(11, 29, 51, 0.28), inset 0 1px 0 #fff;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  color: var(--ink);
  font-weight: 600;
  font-size: 0.98rem;
  white-space: nowrap;
  animation: float 7s ease-in-out infinite;
  transition: border-color 0.4s ease, box-shadow 0.4s ease;
}
.hero-card:hover { border-color: rgba(15, 122, 82, 0.6); box-shadow: 0 30px 60px -30px rgba(11, 29, 51, 0.28), 0 0 40px -10px rgba(15, 122, 82, 0.45); }
.hero-card i {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 1.3rem;
}
.card-2 { animation-delay: -2s; }
.card-3 { animation-delay: -4s; }
.card-4 { animation-delay: -1s; }

.hero-core {
  position: relative;
  display: grid;
  place-items: center;
  width: 190px;
  height: 190px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.18), rgba(255, 255, 255, 0.55) 70%);
  border: 1px solid rgba(11, 29, 51, 0.08);
  box-shadow: inset 0 0 60px rgba(15, 122, 82, 0.18), 0 30px 60px -30px rgba(11, 29, 51, 0.25);
}
.hero-core::before {
  content: "";
  position: absolute;
  inset: -14px;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 68%, rgba(47, 176, 124, 0.9) 86%, transparent 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  animation: spin 9s linear infinite;
}
.hero-core::after {
  content: "";
  position: absolute;
  inset: -46px;
  border-radius: 50%;
  border: 1px dashed rgba(11, 29, 51, 0.14);
  animation: spin 60s linear infinite reverse;
}
.brand-mark-lg {
  font-size: 1.5rem;
  padding: 12px 20px;
  border-radius: 16px;
  box-shadow: 0 0 60px rgba(15, 122, 82, 0.4);
  animation: core-glow 3.2s ease-in-out infinite;
}

.hero-scroll-hint {
  position: absolute;
  bottom: 28px;
  left: 50%;
  width: 1px;
  height: 56px;
  background: rgba(11, 29, 51, 0.14);
  overflow: hidden;
  transform: translateX(-50%);
}
.hero-scroll-hint span {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 40%;
  background: var(--teal);
  animation: hint 2.2s var(--ease) infinite;
}
@media (max-width: 767px) { .hero-scroll-hint { display: none; } }

@media (max-width: 639px) {
  .hero-visual { max-width: 400px; }
  .hero-card { padding: 10px 14px 10px 10px; font-size: 0.86rem; gap: 10px; border-radius: 14px; }
  .hero-card i { width: 36px; height: 36px; font-size: 1.1rem; border-radius: 10px; }
  .hero-core { width: 140px; height: 140px; }
  .hero-core::after { inset: -30px; }
  .brand-mark-lg { font-size: 1.2rem; padding: 10px 16px; }
}

/* scroll-driven fade of the hero as the story starts (desktop, modern browsers) */
@supports (animation-timeline: scroll()) {
  @media (min-width: 992px) and (prefers-reduced-motion: no-preference) {
    .hero-grid {
      animation: hero-exit linear both;
      animation-timeline: scroll(root);
      animation-range: 0 90vh;
    }
  }
}

/* -------------------------------------------------------------------------
   9. Marquee
   ------------------------------------------------------------------------- */
.marquee {
  position: relative;
  padding: 18px 0;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  overflow: hidden;
}
.marquee::before,
.marquee::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: clamp(60px, 10vw, 160px);
  z-index: 2;
  pointer-events: none;
}
.marquee::before {
  inset-inline-start: 0;
  background: linear-gradient(to right, var(--surface), transparent);
}
.marquee::after {
  inset-inline-end: 0;
  background: linear-gradient(to left, var(--surface), transparent);
}
body.is-rtl .marquee::before { background: linear-gradient(to left, var(--surface), transparent); }
body.is-rtl .marquee::after { background: linear-gradient(to right, var(--surface), transparent); }
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 46s linear infinite;
}
.marquee-item {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-inline-end: 56px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color 0.3s ease;
}
.marquee-item:hover { color: var(--ink); }
.marquee-item i { color: var(--teal-ink); font-size: 1rem; }
body.is-rtl .marquee-track { animation-name: marquee-rtl; }

/* -------------------------------------------------------------------------
   10. Stats
   ------------------------------------------------------------------------- */
.stats {
  padding: clamp(48px, 7vw, 80px) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.stats-grid {
  display: grid;
  gap: 28px;
}
@media (min-width: 720px) { .stats-grid { grid-template-columns: repeat(3, 1fr); gap: 40px; } }
.stat {
  position: relative;
  padding: 6px 0 6px 22px;
  padding-inline: 22px 0;
  border-inline-start: 2px solid var(--teal);
  transition: padding 0.5s var(--ease), border-color 0.4s ease;
}
.stat::before {
  content: "";
  position: absolute;
  inset: -12px -16px;
  border-radius: 18px;
  background: radial-gradient(60% 80% at 10% 50%, rgba(15, 122, 82, 0.12), transparent 70%);
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
}
.stat:hover { padding-inline-start: 30px; border-color: var(--blue-2); }
.stat:hover::before { opacity: 1; }
.stat-num {
  display: block;
  font-size: clamp(2.2rem, 4.5vw, 3.6rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  transition: transform 0.5s var(--ease);
}
.stat:hover .stat-num {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  transform: translateX(4px);
}
body.is-rtl .stat:hover .stat-num { transform: translateX(-4px); }
.stat-label {
  display: block;
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}

/* -------------------------------------------------------------------------
   11. Sections
   ------------------------------------------------------------------------- */
.section {
  position: relative;
  padding: clamp(72px, 10vw, 128px) 0;
}
.section-tint {
  position: relative;
  isolation: isolate;
  /* clip (not hidden): hidden would turn the section into the scroll container
     for sticky children and stop them from sticking */
  overflow: clip;
  background: var(--surface-2);
  color: var(--ink);
}
.section-head {
  max-width: 780px;
  margin-bottom: clamp(40px, 6vw, 64px);
}
.section-head .eyebrow { margin-bottom: 18px; }
.section-head h2 { margin-bottom: 0; }
.section-intro {
  margin-top: 18px;
  font-size: 1.05rem;
  max-width: 60ch;
}
.section-cta {
  display: flex;
  justify-content: center;
  margin-top: 44px;
}

/* -------------------------------------------------------------------------
   12. Page hero (inner pages)
   ------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  isolation: isolate;
  overflow: clip; /* clip, not hidden: the ribbon's sticky pane (28) must find no scroll container above it */
  background: var(--bg);
  color: var(--ink);
  padding: calc(var(--header-h) + clamp(56px, 9vw, 112px)) 0 clamp(56px, 8vw, 96px);
}
.page-hero-inner { max-width: 860px; }
.page-hero .display { margin-bottom: 24px; }
.page-hero .lead { margin-bottom: 0; }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.breadcrumb a { color: var(--ink-2); transition: color 0.2s ease; }
.breadcrumb a:hover { color: var(--blue); }
.crumb-sep { opacity: 0.5; }

/* -------------------------------------------------------------------------
   13. Cards: spotlight, 3D tilt, present mode, services bento, values
   ------------------------------------------------------------------------- */
.spot { position: relative; overflow: hidden; }
.spot::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: radial-gradient(460px circle at var(--mx, 50%) var(--my, 50%), rgba(15, 122, 82, 0.18), transparent 45%);
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.spot:hover::before { opacity: 1; }
.spot > * { position: relative; z-index: 1; }

.tilt {
  --rx: 0deg;
  --ry: 0deg;
  --lift: 0px;
  --sc: 1;
  transform: perspective(1100px) rotateX(var(--rx)) rotateY(var(--ry)) translate3d(0, var(--lift), 0) scale(var(--sc));
  transform-style: preserve-3d;
  transition: transform 0.6s var(--ease), box-shadow 0.6s var(--ease), border-color 0.35s ease, opacity 0.5s ease, filter 0.5s ease;
}

.bento {
  display: grid;
  gap: 16px;
  grid-template-columns: 1fr;
  grid-auto-flow: dense;
  perspective: 1400px;
}
@media (min-width: 640px) { .bento { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .bento { grid-template-columns: repeat(4, 1fr); gap: 18px; } }

.service-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 300px;
  padding: 28px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--line);
}
.service-card::after {
  content: "";
  position: absolute;
  inset-inline-end: -30%;
  bottom: -40%;
  width: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.12), transparent 65%);
  opacity: 0;
  transition: opacity 0.5s ease;
  pointer-events: none;
}
@property --angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}
.service-card:hover {
  border-color: transparent;
  background: var(--surface);
  box-shadow:
    0 0 36px -8px color-mix(in srgb, var(--accent, var(--teal)) 55%, transparent),
    0 30px 60px -30px color-mix(in srgb, var(--accent, var(--teal)) 50%, transparent),
    var(--shadow-md);
}
/* the glowing ring is a rotating layer of its own (transform only, no repaint of the card);
   the solution / AI hub cards (section 25) carry the same span */
.service-card > .service-glow,
.solution-card > .service-glow {
  position: absolute;
  inset: -1px;
  z-index: 2;
  border-radius: inherit;
  padding: 2px;
  overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.service-card > .service-glow::before,
.solution-card > .service-glow::before {
  content: "";
  position: absolute;
  inset: -100%;
  background: conic-gradient(from 0deg, var(--accent, var(--teal)), var(--blue-glow) 30%, transparent 55%, var(--accent, var(--teal)) 80%, var(--accent, var(--teal)));
  animation: spin 3.5s linear infinite;
  animation-play-state: paused;
  will-change: transform;
}
.service-card:hover > .service-glow,
.service-card.is-source > .service-glow,
.solution-card:hover > .service-glow { opacity: 1; }
.service-card:hover > .service-glow::before,
.service-card.is-source > .service-glow::before,
.solution-card:hover > .service-glow::before { animation-play-state: running; }
.bento .service-card { will-change: transform; }
.bento .spot::before { will-change: transform; }
.service-card:hover::after { opacity: 1; }
.service-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.service-index {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  color: var(--muted-c);
  transition: color 0.3s ease;
}
.service-card:hover .service-index { color: var(--teal-ink); }
.service-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 14px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 1.35rem;
  transition: transform 0.6s var(--ease), background 0.35s ease, color 0.35s ease, box-shadow 0.5s ease;
}
.service-card:hover .service-icon {
  transform: rotate(-8deg) scale(1.12);
  color: #fff;
  box-shadow: 0 14px 30px -12px color-mix(in srgb, var(--accent, var(--teal)) 80%, transparent);
}
.service-card h3 {
  margin: 6px 0 0;
  font-size: 1.22rem;
  letter-spacing: -0.015em;
}
.service-body { position: relative; flex: 1; min-height: 158px; }
.service-summary,
.service-card p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.6;
}
.service-summary { transition: opacity 0.35s ease, transform 0.5s var(--ease); }
.service-more {
  position: absolute;
  inset: 0 0 auto 0;
  margin: 0;
  font-size: 0.84rem;
  line-height: 1.5;
  color: var(--ink);
  opacity: 0;
  transform: translateY(12px);
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
  pointer-events: none;
  transition: opacity 0.45s ease 0.05s, transform 0.6s var(--ease) 0.05s;
}
.service-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--blue);
  transition: opacity 0.3s ease, transform 0.4s var(--ease);
}
.service-link i { transition: transform 0.35s var(--ease); }
.service-card:hover .service-link i { transform: translateX(4px); }
body.is-rtl .service-card:hover .service-link i { transform: translateX(-4px); }
@media (hover: hover) {
  .service-card:hover .service-summary { opacity: 0; transform: translateY(-10px); }
  .service-card:hover .service-more { opacity: 1; transform: none; }
}
.service-ghost {
  position: absolute;
  inset-inline-end: -8%;
  bottom: -12%;
  font-size: 150px;
  line-height: 1;
  color: var(--accent, var(--teal));
  opacity: 0.05;
  transform: rotate(-12deg) scale(0.85);
  transition: transform 0.8s var(--ease), opacity 0.5s ease;
  pointer-events: none;
}
.spot > .service-ghost { z-index: 0; }
.service-card:hover .service-ghost,
.chapter-card:hover .service-ghost { opacity: 0.11; transform: rotate(-4deg) scale(1); }
.service-icon-lg {
  width: 72px;
  height: 72px;
  font-size: 2rem;
  border-radius: 20px;
}
.page-hero .service-icon-lg {
  margin-bottom: 26px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  border: 1px solid rgba(11, 127, 119, 0.12);
}

/* -------------------------------------------------------------------------
   14. Approach chapter (sticky storytelling)
   ------------------------------------------------------------------------- */
.approach-grid {
  display: grid;
  gap: 48px;
  align-items: start;
}
@media (min-width: 992px) {
  .approach-grid { grid-template-columns: 0.85fr 1.15fr; gap: 96px; }
  .approach-sticky { position: sticky; top: calc(var(--header-h) + 40px); }
}
.approach .section-head { margin-bottom: 36px; }
.approach-progress {
  width: min(100%, 300px);
  height: 2px;
  border-radius: 2px;
  background: var(--line-2);
  overflow: hidden;
}
.approach-progress span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--teal-2), var(--blue-glow));
  transform: scaleX(0.25);
  transform-origin: 0 50%;
  transition: transform 0.7s var(--ease);
}
body.is-rtl .approach-progress span { transform-origin: 100% 50%; }

.process-list {
  display: grid;
  border-top: 1px solid var(--line-2);
}
.process-step {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 20px;
  padding: clamp(28px, 4vw, 44px) 0;
  border-bottom: 1px solid var(--line);
  opacity: 0.38;
  transition: opacity 0.6s ease;
}
.process-step.is-active,
.process-step:hover { opacity: 1; }
.process-num {
  padding-top: 8px;
  font-family: var(--font-mono);
  font-size: 1rem;
  letter-spacing: 0.08em;
  color: var(--muted);
  transition: color 0.4s ease;
}
.process-step.is-active .process-num,
.process-step:hover .process-num { color: var(--teal-ink); }
.process-step h3 {
  margin-bottom: 10px;
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  letter-spacing: -0.025em;
}
.process-step p {
  margin: 0;
  max-width: 52ch;
  font-size: 1.04rem;
  line-height: 1.65;
}
@media (max-width: 639px) {
  .process-step { grid-template-columns: 44px 1fr; gap: 14px; }
}

/* -------------------------------------------------------------------------
   15. CTA card (kept as is)
   ------------------------------------------------------------------------- */
.cta-band { padding: clamp(32px, 5vw, 80px) 0 clamp(72px, 9vw, 128px); }
.cta-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(40px, 6vw, 80px);
  border-radius: var(--radius-xl);
  background: var(--dark);
  color: var(--on-dark);
  box-shadow: 0 40px 100px -40px rgba(11, 29, 51, 0.5);
}
.cta-card-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}
.cta-card h2 { margin-bottom: 12px; max-width: 18ch; }
.cta-card p { margin: 0; font-size: 1.1rem; max-width: 48ch; }

/* -------------------------------------------------------------------------
   16. Services stories: a horizontal story rail. One panel per service: a
   wide navy plate drawing the service's schema (section 33) with a caption
   chip, the summary as a highlighted pull quote and the description beside
   it. On desktop the section pins and scrolling glides the rail sideways
   while the plate's layers drift for depth. Phones get a swipeable deck.
   ------------------------------------------------------------------------- */
.chapters {
  --panel-w: min(78vw, 1080px);
  --panel-gap: 4vw;
  --deck-step: 60vh;
  --plate-ratio: 2.2;
}
.chapters-pin { position: relative; }
.story-head {
  display: flex;
  align-items: center;
  gap: 22px;
  margin-bottom: 26px;
}
.chapter-progress {
  flex: 1;
  height: 2px;
  border-radius: 2px;
  background: var(--line-2);
  overflow: hidden;
}
.chapter-progress span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--teal-2), var(--blue-glow));
  transform: scaleX(0.125);
  transform-origin: 0 50%;
  transition: transform 0.5s var(--ease);
}
body.is-rtl .chapter-progress span { transform-origin: 100% 50%; }
.story-nav { display: flex; align-items: center; gap: 10px; }
.story-counter {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.12em;
  color: var(--muted);
  /* "current / total" reads the same way in Arabic: keep the pair in left-to-right order */
  direction: ltr;
  unicode-bidi: isolate;
}
.story-counter b { font-weight: 500; color: var(--ink); }
.story-arrow {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: #fff;
  color: var(--ink-2);
  font-size: 1rem;
  cursor: pointer;
  transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease, transform 0.5s var(--ease);
}
.story-arrow:hover { background: var(--ink); border-color: var(--ink); color: #fff; transform: translateY(-2px); }
body.is-rtl .story-arrow i { transform: scaleX(-1); }

.story-rail { position: relative; }
.story-track {
  display: grid;
  gap: 48px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.story-panel {
  --hl: 1;
  --drift: 0;
  display: grid;
  gap: 22px;
}
.story-plate {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  border-radius: 22px;
  background: var(--dark);
  box-shadow:
    0 0 0 1px rgba(11, 29, 51, 0.08),
    0 40px 100px -40px color-mix(in srgb, var(--accent, var(--teal)) 70%, transparent);
}
.story-chip {
  position: absolute;
  bottom: -1px;
  inset-inline-start: -1px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: calc(100% - 6rem);
  padding: 12px 20px 12px 14px;
  border-start-end-radius: 16px;
  border-end-start-radius: 22px;
  background: var(--surface);
  border-top: 2px solid var(--accent, var(--teal));
}
.story-chip .service-icon {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  font-size: 1.1rem;
  background: color-mix(in srgb, var(--accent, var(--teal)) 16%, #fff);
  color: color-mix(in srgb, var(--accent, var(--teal)) 72%, #000);
}
.story-chip h3 { margin: 0; font-size: 1rem; line-height: 1.25; color: var(--ink); }
.story-chip-sub {
  margin: 2px 0 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  color: var(--muted);
  /* "02 / 08" like the head counter: left to right in Arabic too (aligned in section 38) */
  direction: ltr;
  unicode-bidi: isolate;
}
.story-lead {
  margin: 0;
  max-width: 34ch;
  font-size: clamp(1.15rem, 1.6vw, 1.5rem);
  line-height: 1.4;
  font-weight: 500;
  color: var(--ink);
}
/* the highlighter sweeps across the pull quote as the panel becomes the active one */
.story-lead mark {
  color: inherit;
  padding: 0.05em 0.15em;
  border-radius: 4px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  background-color: transparent;
  background-image: linear-gradient(color-mix(in srgb, var(--accent, var(--teal)) 36%, transparent), color-mix(in srgb, var(--accent, var(--teal)) 36%, transparent));
  background-repeat: no-repeat;
  background-position: 0 0;
  background-size: calc(var(--hl) * 100%) 100%;
}
body.is-rtl .story-lead mark { background-position: 100% 0; }
.story-body p {
  margin: 0 0 14px;
  max-width: 46ch;
  font-size: 1rem;
  line-height: 1.68;
  color: var(--ink-2);
}
.story-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* a shade deeper than --teal-ink: on the tint band, under its grid and the
     node network, the plain brand green measured 4.4:1 (5.7:1 now) */
  color: color-mix(in srgb, var(--teal-ink) 80%, var(--ink));
  transition: color 0.3s ease;
}
.story-link i { transition: transform 0.35s var(--ease); }
.story-link:hover { color: var(--ink); }
.story-link:hover i { transform: translateX(4px); }
body.is-rtl .story-link i { transform: scaleX(-1); }
body.is-rtl .story-link:hover i { transform: scaleX(-1) translateX(4px); }
body.is-rtl .story-chip h3,
body.is-rtl .story-lead { font-family: var(--font-ar); }
@media (min-width: 992px) {
  .story-panel {
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    column-gap: 56px;
    row-gap: 24px;
    align-items: start;
  }
  .story-plate { grid-column: 1 / -1; aspect-ratio: var(--plate-ratio); max-height: 50vh; }
  .story-lead { grid-column: 2; grid-row: 2; }
  .story-body { grid-column: 1; grid-row: 2; }
}

/* the pinned, scroll-driven rail (desktop, motion allowed, JS on) */
@media (min-width: 992px) and (prefers-reduced-motion: no-preference) {
  .js .chapters-pin { height: calc(100vh + (var(--n, 8) - 1) * var(--deck-step)); }
  .js .chapters-viewport {
    position: sticky;
    top: var(--header-h);
    height: calc(100vh - var(--header-h));
    display: grid;
    align-content: center;
  }
  .js .story-head { margin-bottom: 22px; }
  .js .story-rail { overflow: hidden; padding: 24px 0 40px; }
  .js .story-track {
    display: flex;
    gap: var(--panel-gap);
    padding-inline: var(--rail-pad, 10vw);
    will-change: transform;
  }
  .js .story-panel { flex: 0 0 var(--panel-w); }
  /* depth, kept legible (2026-11-07): the neighbours rest a shade back (plate
     0.88, text 0.9) and the panel at hand is fully opaque from half-way in
     (--hl >= 0.5), so the current panel never reads dimmed at any scroll
     position; the highlighter's sweep still marks which one it is */
  .js .story-plate { opacity: min(1, calc(0.88 + 0.24 * var(--hl))); }
  .js .story-lead,
  .js .story-body { opacity: min(1, calc(0.9 + 0.2 * var(--hl))); }
}

/* phones and tablets: the rail is a deck of cards the reader swipes through,
   one service per card, snapping into place with the next card peeking in.
   The head's progress bar, counter and arrows follow the swipe (main.js)
   and the highlighter sweeps the pull quote of the card that settles. */
@media (max-width: 991.98px) {
  .chapters {
    --panel-w: min(84vw, 560px);
    --panel-gap: 14px;
    padding-top: clamp(28px, 5vw, 48px);
    padding-bottom: clamp(40px, 6vw, 64px);
  }
  .story-head { gap: 16px; margin-bottom: 20px; }
  .story-arrow { width: 40px; height: 40px; font-size: 0.95rem; }
  .story-track {
    display: flex;
    align-items: stretch;
    gap: var(--panel-gap);
    /* room after the last card so it can snap to the same start edge as the others */
    padding: 6px var(--gutter) 36px;
    padding-inline-end: max(var(--gutter), calc(100% - var(--panel-w) - var(--gutter)));
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .story-track::-webkit-scrollbar { display: none; }
  .story-panel {
    flex: 0 0 var(--panel-w);
    scroll-snap-align: start;
    scroll-snap-stop: always;
    gap: 0;
    align-content: start;
    padding: 8px 8px 24px;
    border-radius: 24px;
    background: var(--surface);
    box-shadow: 0 0 0 1px rgba(11, 29, 51, 0.05), var(--shadow-sm);
    transition: box-shadow 0.6s var(--ease);
  }
  .story-panel.is-current {
    box-shadow:
      0 0 0 1px rgba(11, 29, 51, 0.05),
      0 30px 70px -36px color-mix(in srgb, var(--accent, var(--teal)) 60%, transparent),
      var(--shadow-sm);
  }
  .story-plate {
    aspect-ratio: 4 / 3;
    border-radius: 18px;
    box-shadow: 0 0 0 1px rgba(11, 29, 51, 0.06);
  }
  .story-chip {
    gap: 10px;
    max-width: calc(100% - 3rem);
    padding: 10px 16px 8px 10px;
    border-start-end-radius: 14px;
    border-end-start-radius: 18px;
  }
  .story-chip .service-icon { width: 36px; height: 36px; border-radius: 10px; font-size: 1rem; }
  .story-chip h3 { font-size: 0.92rem; }
  .story-chip-sub { display: none; }
  .story-lead {
    margin: 22px 10px 0;
    max-width: none;
    font-size: 1.12rem;
  }
  .story-body { margin: 14px 10px 0; }
  .story-body p { max-width: none; font-size: 0.95rem; line-height: 1.62; }
  .story-link { margin-top: 2px; }
  /* with JavaScript only the settled card carries the highlight, swept in on arrival */
  .js .story-panel { --hl: 0; }
  .js .story-panel.is-current { --hl: 1; }
  .js .story-lead mark { transition: background-size 0.9s var(--ease) 0.2s; }
}

/* -------------------------------------------------------------------------
   17. About
   ------------------------------------------------------------------------- */
.about-grid {
  display: grid;
  gap: 56px;
  align-items: start;
}
@media (min-width: 992px) {
  .about-grid { grid-template-columns: 1.15fr 0.85fr; gap: 96px; }
  .about-values { position: sticky; top: calc(var(--header-h) + 40px); }
}
.about-block + .about-block { margin-top: clamp(40px, 5vw, 64px); }
.about-block { display: grid; gap: 24px; }
.about-media { aspect-ratio: 4 / 3; border-radius: 20px; }
@media (min-width: 768px) {
  .about-block { grid-template-columns: 220px minmax(0, 1fr); gap: 36px; align-items: start; }
  .about-media { margin-top: 6px; }
}
.contact-media { aspect-ratio: 16 / 10; border-radius: 20px; }
.about-block h2 {
  font-size: clamp(1.7rem, 3vw, 2.4rem);
  margin-bottom: 16px;
}
.about-p {
  font-size: 1.12rem;
  line-height: 1.75;
  max-width: 58ch;
  margin: 0;
}
.about-values { display: grid; gap: 16px; perspective: 1200px; }
.value-card {
  padding: 26px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--line);
}
.value-card:hover {
  border-color: rgba(15, 122, 82, 0.6);
  box-shadow: 0 0 0 1px rgba(15, 122, 82, 0.3), 0 30px 70px -30px rgba(15, 122, 82, 0.4), var(--shadow-md);
}
.value-card:hover .service-icon {
  transform: rotate(-8deg) scale(1.12);
  background: var(--grad-brand);
  color: #fff;
}
.value-card h3 { margin: 18px 0 6px; font-size: 1.15rem; }
.value-card p { margin: 0; font-size: 0.95rem; }

.activity-list {
  counter-reset: activity;
  max-width: 920px;
  border-top: 1px solid var(--line-2);
}
.activity-list li {
  counter-increment: activity;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 1.03rem;
  line-height: 1.65;
  transition: color 0.3s ease, padding 0.4s var(--ease);
}
.activity-list li::before {
  content: counter(activity, decimal-leading-zero);
  padding-top: 5px;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  color: var(--teal-ink);
}
.activity-list li:hover { color: var(--ink); }

/* -------------------------------------------------------------------------
   18. Service detail
   ------------------------------------------------------------------------- */
.service-detail-grid {
  display: grid;
  gap: 48px;
  align-items: start;
}
@media (min-width: 992px) {
  .service-detail-grid { grid-template-columns: minmax(0, 1fr) 360px; gap: 80px; }
  .service-detail-aside { position: sticky; top: calc(var(--header-h) + 40px); }
}
.prose p {
  font-size: 1.12rem;
  line-height: 1.75;
  color: var(--ink-2);
  max-width: 66ch;
  margin-bottom: 1.4em;
}
.prose p:first-child {
  font-size: clamp(1.2rem, 1.8vw, 1.42rem);
  line-height: 1.5;
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.service-detail-aside { display: grid; gap: 16px; perspective: 1200px; }
.aside-card {
  padding: 26px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--line);
}
.aside-card:hover { border-color: rgba(15, 122, 82, 0.5); box-shadow: var(--shadow-md); }
.aside-card h3 { font-size: 1.12rem; margin-bottom: 10px; }
.aside-card p { font-size: 0.95rem; }
.aside-card-accent {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--dark);
  border-color: transparent;
  color: var(--on-dark);
}
.aside-card-accent:hover { border-color: rgba(47, 176, 124, 0.4); box-shadow: 0 30px 70px -30px rgba(15, 122, 82, 0.5); }
.aside-card-accent::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset-inline-end: -40%;
  top: -40%;
  width: 90%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.5), transparent 62%);
  filter: blur(30px);
}
.aside-card-accent .btn { margin-top: 8px; }
.aside-links li { border-top: 1px solid var(--line); }
.aside-links li:first-child { border-top: 0; }
.aside-links a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--ink-2);
  transition: color 0.2s ease, padding 0.35s var(--ease);
}
.aside-links a:hover { color: var(--blue); padding-inline-start: 6px; }
.aside-links i { color: var(--teal-ink); font-size: 1.1rem; }

/* -------------------------------------------------------------------------
   19. Contact
   ------------------------------------------------------------------------- */
.contact-grid {
  display: grid;
  gap: 48px;
  align-items: start;
}
@media (min-width: 992px) {
  .contact-grid { grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.65fr); gap: 64px; }
  .contact-info { position: sticky; top: calc(var(--header-h) + 40px); }
}
.contact-form {
  display: grid;
  gap: 20px;
  padding: clamp(24px, 4vw, 44px);
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 30px 80px -40px rgba(11, 29, 51, 0.25);
}
.form-row { display: grid; gap: 20px; }
@media (min-width: 640px) { .form-row { grid-template-columns: 1fr 1fr; } }
.form-group { display: grid; gap: 8px; }
.form-group label {
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--ink);
  transition: color 0.2s ease;
}
.form-group:focus-within label { color: var(--teal-ink); }
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--line-2);
  border-radius: 14px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  transition: border-color 0.25s ease, box-shadow 0.35s var(--ease), background 0.25s ease, transform 0.35s var(--ease);
}
.form-group select {
  appearance: none;
  -webkit-appearance: none;
  padding-inline-end: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%2364748b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 16px;
}
body.is-rtl .form-group select { background-position: left 16px center; }
.form-group textarea { min-height: 160px; resize: vertical; }
.form-group input:hover,
.form-group select:hover,
.form-group textarea:hover { border-color: var(--muted); }
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  background: #fff;
  border-color: var(--teal);
  box-shadow: 0 0 0 4px rgba(15, 122, 82, 0.18), 0 12px 30px -16px rgba(15, 122, 82, 0.5);
  transform: translateY(-1px);
}
.field-error { margin: 0; font-size: 0.85rem; color: #dc2626; }
.contact-form .btn-block { margin-top: 6px; }

.contact-info { display: grid; gap: 16px; perspective: 1200px; }
.contact-details li,
.check-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 0;
  border-top: 1px solid var(--line);
  font-size: 0.95rem;
  color: var(--ink-2);
}
.contact-details li:first-child,
.check-list li:first-child { border-top: 0; }
.contact-details i,
.check-list i { color: var(--teal-ink); font-size: 1.1rem; }
.contact-details a:hover { color: var(--blue); }

/* -------------------------------------------------------------------------
   20. Footer
   ------------------------------------------------------------------------- */
.site-footer {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: clamp(64px, 8vw, 96px) 0 32px;
  background: var(--dark);
  color: var(--on-dark-2);
}
.footer-top {
  display: grid;
  gap: 40px;
  padding-bottom: 48px;
  border-bottom: 1px solid var(--dark-line);
}
@media (min-width: 768px) { .footer-top { grid-template-columns: 1.6fr 1fr 1fr; } }
.footer-brand .navbar-brand { color: #fff; }
.footer-brand p {
  margin: 20px 0 0;
  max-width: 44ch;
  font-size: 0.95rem;
  line-height: 1.65;
}
.footer-col h3 {
  margin-bottom: 18px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-dark-muted);
}
.footer-col li {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
  font-size: 0.95rem;
}
.footer-col a { display: inline-block; transition: color 0.25s ease, transform 0.4s var(--ease); }
.footer-col a:hover { color: #fff; transform: translateX(4px); }
body.is-rtl .footer-col a:hover { transform: translateX(-4px); }
.footer-col i { color: var(--teal-2); }
.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding-top: 24px;
  font-size: 0.85rem;
  color: var(--on-dark-muted);
}
.footer-bottom p { margin: 0; color: inherit; }
.back-to-top {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--dark-line);
  color: var(--on-dark);
  transition: background 0.3s ease, color 0.3s ease, transform 0.45s var(--ease), box-shadow 0.45s ease;
}
.back-to-top:hover { background: #fff; color: var(--ink); transform: translateY(-4px); box-shadow: 0 16px 30px -12px rgba(255, 255, 255, 0.4); }
.footer-wordmark {
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: -0.2em;
  transform: translateX(-50%);
  font-family: var(--font-sans);
  font-size: clamp(9rem, 30vw, 26rem);
  font-weight: 700;
  letter-spacing: -0.06em;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, 0.07);
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
}

/* -------------------------------------------------------------------------
   21. Motion: reveals + keyframes
   Reveals use the individual translate/scale properties so they compose
   with the transform-based tilt instead of overriding it.
   ------------------------------------------------------------------------- */
.js .reveal {
  opacity: 0;
  translate: 0 32px;
  scale: 0.96;
  filter: blur(10px);
  transition: opacity var(--dur) var(--ease), translate var(--dur) var(--ease), scale var(--dur) var(--ease), filter var(--dur) var(--ease);
  transition-delay: var(--d, 0s);
}
.js .reveal.is-in { opacity: 1; translate: 0 0; scale: 1; filter: none; }

.js .reveal-words .w { display: inline-block; }
.js .reveal-words .w span {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.5em);
  filter: blur(6px);
  transition: opacity 0.7s ease, transform 0.9s var(--ease), filter 0.7s ease;
}
.js .reveal-words.is-in .w span {
  opacity: 1;
  transform: none;
  filter: none;
}

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(47, 176, 124, 0.18); }
  50% { box-shadow: 0 0 0 9px rgba(47, 176, 124, 0); }
}
@keyframes drift {
  0% { transform: translate3d(0, 0, 0) scale(1); }
  100% { transform: translate3d(8%, 10%, 0) scale(1.12); }
}
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-12px); }
}
@keyframes spin {
  to { transform: rotate(360deg); }
}
@keyframes core-glow {
  0%, 100% { box-shadow: 0 0 60px rgba(15, 122, 82, 0.4); }
  50% { box-shadow: 0 0 90px rgba(47, 176, 124, 0.75), 0 0 30px rgba(47, 176, 124, 0.5); }
}
@keyframes hint {
  0% { transform: translateY(-110%); }
  60%, 100% { transform: translateY(260%); }
}
@keyframes marquee {
  to { transform: translateX(-50%); }
}
@keyframes marquee-rtl {
  to { transform: translateX(50%); }
}
@keyframes flash-in {
  from { opacity: 0; transform: translateY(-12px) scale(0.96); }
  to { opacity: 1; transform: none; }
}
@keyframes overlay-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes overlay-out {
  from { opacity: 1; }
  to { opacity: 0; }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(24px); }
  to { opacity: 1; transform: none; }
}
@keyframes ripple {
  to { transform: scale(1); opacity: 0; }
}
@keyframes angle-spin {
  to { --angle: 360deg; }
}
@keyframes hero-exit {
  to { transform: translateY(-48px); opacity: 0.15; }
}

/* -------------------------------------------------------------------------
   13b. Service stage
   A bento card expands in place: its rectangle is morphed (animated
   clip-path) into a full-viewport window lit by the service's own clip,
   the rest of the page blurs behind it, and a rail browses the others.
   ------------------------------------------------------------------------- */
/* card touches: an expand hint appears */
.service-meta { display: inline-flex; align-items: center; gap: 10px; }
.service-expand {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  font-size: 0.8rem;
  color: #fff;
  background: var(--accent, var(--teal));
  box-shadow: 0 8px 20px -8px var(--accent, var(--teal));
  opacity: 0;
  scale: 0.6;
  translate: 6px 0;
  transition: opacity 0.4s ease, scale 0.6s var(--ease), translate 0.6s var(--ease);
}
.service-card:hover .service-expand { opacity: 1; scale: 1; translate: 0 0; }

/* the clicked card becomes the morph source; its siblings step far back */
.service-card.is-source {
  --sc: 1.08;
  --lift: -14px;
  border-color: transparent;
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--accent, var(--teal)) 55%, transparent),
    0 0 90px -10px color-mix(in srgb, var(--accent, var(--teal)) 80%, transparent),
    var(--shadow-md);
}
.service-card.is-source > *,
.service-card.is-source > .service-glow { opacity: 0; transition: opacity 0.25s ease; }
.bento.is-open .service-card:not(.is-source) {
  --sc: 0.96;
  opacity: 0.4;
  transition: opacity 0.9s ease, transform 0.9s var(--ease);
}
.bento.is-open .service-card.is-source { opacity: 1; }

/* page scroll lock without layout shift (scrollbar width compensated) */
html.stage-open { overflow: hidden; }
html.stage-open body { padding-inline-end: var(--sbw, 0px); }
html.stage-open .site-header { padding-inline-end: var(--sbw, 0px); }

@property --stage-accent {
  syntax: "<color>";
  inherits: true;
  initial-value: #0f7a52;
}
.service-stage {
  position: fixed;
  inset: 0;
  z-index: 300;
  --stage-inset: 0px;
  --stage-radius: 0px;
  --stage-pad-x: clamp(22px, 5vw, 72px);
  --stage-pad-y: clamp(28px, 6vh, 64px);
}
@media (min-width: 992px) {
  .service-stage { --stage-inset: clamp(12px, 1.8vw, 26px); --stage-radius: 30px; }
}
.service-stage[hidden] { display: none; }
.stage-veil {
  position: absolute;
  inset: 0;
  background: rgba(243, 245, 248, 0.78);
  opacity: 0;
  transition: opacity 0.7s ease;
}
.service-stage.is-open .stage-veil { opacity: 1; }
.service-stage.is-closing .stage-veil { opacity: 0; transition: opacity 0.5s ease 0.15s; }

.stage-window {
  --stage-accent: var(--teal);
  position: absolute;
  inset: var(--stage-inset);
  border-radius: var(--stage-radius);
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
  color: var(--ink);
  box-shadow: 0 60px 140px -40px rgba(11, 29, 51, 0.45), 0 0 0 1px rgba(11, 29, 51, 0.08);
  outline: none;
  transition: --stage-accent 0.9s ease, opacity 0.4s ease;
}
.service-stage:not(.is-open):not(.is-morphing) .stage-window { opacity: 0; }
/* the card's conic glow continues around the stage */
.stage-window::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 6;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(from var(--angle), var(--stage-accent), transparent 28%, rgba(11, 29, 51, 0.1) 50%, transparent 62%, var(--stage-accent) 82%, var(--stage-accent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: angle-spin 7s linear infinite;
  opacity: 0.9;
  pointer-events: none;
}

/* backdrop: the clip's poster, blurred and drifting, tinted by its accent */
.stage-backdrop {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.stage-bg {
  position: absolute;
  inset: -8%;
  background-size: cover;
  background-position: center;
  filter: blur(38px) saturate(1.1) brightness(1.08);
  opacity: 0;
  transition: opacity 1.1s ease;
  animation: stage-drift 30s ease-in-out infinite alternate;
}
.stage-bg:nth-child(2) { animation-delay: -15s; }
.stage-bg.is-on { opacity: 0.6; }
.stage-tint {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(55% 60% at 82% 12%, color-mix(in srgb, var(--stage-accent) 22%, transparent), transparent 70%),
    radial-gradient(45% 50% at 10% 95%, color-mix(in srgb, var(--stage-accent) 12%, transparent), transparent 70%),
    linear-gradient(105deg, color-mix(in srgb, var(--bg) 94%, transparent) 0%, color-mix(in srgb, var(--bg) 78%, transparent) 50%, color-mix(in srgb, var(--bg) 55%, transparent) 100%);
}
.stage-backdrop .grid-lines { opacity: 0.6; }

.stage-close {
  position: absolute;
  top: 18px;
  inset-inline-end: 18px;
  z-index: 8;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid rgba(11, 29, 51, 0.1);
  background: rgba(255, 255, 255, 0.8);
  color: var(--ink);
  font-size: 1.05rem;
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  scale: 0.7;
  transition: opacity 0.5s ease 0.5s, scale 0.7s var(--ease) 0.5s, background 0.25s ease, rotate 0.5s var(--ease);
}
.service-stage.is-open .stage-close { opacity: 1; scale: 1; }
.service-stage.is-closing .stage-close { opacity: 0; transition: opacity 0.2s ease; }
.stage-close:hover { background: #fff; rotate: 90deg; }
/* scrolling inside the stage browses the services: a hint at the edge, a small
   pull before it snaps, and the panels travel in the direction scrolled */
.stage-hint {
  position: absolute;
  top: 50%;
  inset-inline-end: 22px;
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  translate: 0 -50%;
  color: rgba(11, 29, 51, 0.45);
  font-size: 1.05rem;
  opacity: 0;
  transition: opacity 0.6s ease 1.2s;
  pointer-events: none;
}
.service-stage.is-open .stage-hint { opacity: 1; }
.service-stage.has-scrolled .stage-hint,
.service-stage.is-closing .stage-hint { opacity: 0; transition-delay: 0s; }
.stage-hint-chev { font-size: 0.9rem; animation: hint-bob 1.8s ease-in-out infinite; }
@keyframes hint-bob {
  0%, 100% { translate: 0 0; opacity: 0.4; }
  50% { translate: 0 5px; opacity: 1; }
}
.stage-scroll { transition: translate 0.3s var(--ease); }
.service-stage.is-back .stage-panel:not(.is-active) .stage-copy > * { translate: 0 -28px; }
.service-stage.is-back .stage-panel.is-leaving .stage-copy > * { translate: 0 18px; }
@media (max-width: 991px) { .stage-hint { display: none; } }

/* scrolling content: one panel per service, stacked in the same grid cell so two can crossfade */
.stage-scroll {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: rgba(11, 29, 51, 0.25) transparent;
}
.stage-panels { display: grid; min-height: 100%; }
.stage-panel {
  grid-area: 1 / 1;
  display: grid;
  gap: 32px;
  align-content: start;
  padding: calc(var(--stage-pad-y) + 30px) var(--stage-pad-x) 130px;
  min-height: 100%;
}
.stage-panel[hidden] { display: none; }
.stage-panel.is-leaving { pointer-events: none; }
.stage-copy { max-width: 640px; }
.stage-kicker {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 22px;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  color: color-mix(in srgb, var(--stage-accent) 70%, #000);
}
.stage-num { font-size: 1.7rem; font-weight: 500; line-height: 1; letter-spacing: 0; color: var(--ink); }
.stage-of { color: var(--muted); }
.stage-icon {
  margin-bottom: 22px;
  background: color-mix(in srgb, var(--stage-accent) 16%, #fff);
  color: color-mix(in srgb, var(--stage-accent) 72%, #000);
  border: 1px solid color-mix(in srgb, var(--stage-accent) 30%, transparent);
  box-shadow: 0 20px 50px -20px color-mix(in srgb, var(--stage-accent) 90%, transparent);
}
.stage-title {
  margin: 0 0 20px;
  font-size: clamp(1.9rem, 3.6vw, 3.1rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  font-weight: 600;
  color: var(--ink);
}
.stage-lead { margin: 0 0 26px; color: var(--ink-2); }
.stage-body p {
  margin: 0 0 16px;
  max-width: 60ch;
  font-size: 1.02rem;
  line-height: 1.72;
  color: var(--ink-2);
}
.stage-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  margin-top: 30px;
  padding: 22px 24px;
  border-radius: 20px;
  background: linear-gradient(135deg, color-mix(in srgb, var(--stage-accent) 12%, #fff), #fff);
  border: 1px solid color-mix(in srgb, var(--stage-accent) 30%, var(--line));
}
.stage-cta h3 { margin: 0 0 4px; font-size: 1.05rem; color: var(--ink); }
.stage-cta p { margin: 0; max-width: 44ch; font-size: 0.92rem; color: var(--ink-2); }

.stage-media { position: relative; display: grid; gap: 18px; align-content: start; }
.stage-media .clip { width: 100%; max-height: min(48vh, 440px); aspect-ratio: 16 / 10; }
.stage-media .stage-cta { margin-top: 0; flex-direction: column; align-items: flex-start; gap: 14px; }
.stage-media .stage-cta > div { width: 100%; }
.stage-ghost {
  position: absolute;
  z-index: -1;
  inset-inline-end: -10%;
  bottom: -14%;
  font-size: clamp(160px, 22vw, 300px);
  line-height: 1;
  color: var(--stage-accent);
  opacity: 0.12;
  transform: rotate(-8deg);
  filter: blur(1px);
  pointer-events: none;
}
@media (min-width: 992px) {
  .stage-panel {
    grid-template-columns: minmax(0, 1fr) minmax(300px, 40%);
    gap: clamp(36px, 5vw, 88px);
    align-items: start;
    padding-top: var(--stage-pad-y);
  }
  .stage-media { position: sticky; top: var(--stage-pad-y); }
  .stage-media .clip-portrait {
    width: min(100%, 440px);
    max-height: min(50vh, 460px);
    aspect-ratio: 4 / 5;
    margin-inline-start: auto;
  }
}
@media (max-width: 991px) {
  .stage-media { display: contents; }
  .stage-media > .clip { order: -1; }
  .stage-media .stage-cta { order: 3; }
  .stage-ghost { display: none; }
  .stage-panel { padding-bottom: 120px; }
}

/* choreography: copy lines rise in sequence, the media swings in from the side */
.stage-copy > * {
  opacity: 0;
  translate: 0 28px;
  scale: 0.94;
  transform-origin: 0 50%;
  filter: blur(8px);
  transition: opacity 0.7s var(--ease), translate 0.9s var(--ease), scale 0.9s var(--ease-spring), filter 0.7s var(--ease);
  transition-delay: var(--d, 0s);
}
.stage-copy > :nth-child(1) { --d: 0.1s; }
.stage-copy > :nth-child(2) { --d: 0.16s; }
.stage-copy > :nth-child(3) { --d: 0.22s; }
.stage-copy > :nth-child(4) { --d: 0.34s; }
.stage-copy > :nth-child(5) { --d: 0.42s; }
.stage-copy > :nth-child(6) { --d: 0.52s; }
.stage-panel.is-active .stage-copy > * { opacity: 1; translate: 0 0; scale: 1; filter: none; }
.stage-panel.is-leaving .stage-copy > * {
  opacity: 0;
  translate: 0 -16px;
  filter: blur(6px);
  transition-duration: 0.28s;
  transition-delay: 0s;
}
.js .stage-title .w { display: inline-block; }
.js .stage-title .w span {
  display: inline-block;
  opacity: 0;
  transform: translateY(0.6em) rotate(2deg);
  filter: blur(6px);
  transition: opacity 0.6s ease, transform 0.9s var(--ease), filter 0.6s ease;
}
.js .stage-panel.is-active .stage-title .w span { opacity: 1; transform: none; filter: none; }
.stage-media {
  opacity: 0;
  transform: perspective(1200px) rotateY(-12deg) translateX(48px) scale(0.84);
  transition: opacity 0.8s var(--ease) 0.28s, transform 1.1s var(--ease-spring) 0.28s;
}
body.is-rtl .stage-media { transform: perspective(1200px) rotateY(12deg) translateX(-48px) scale(0.84); }
@media (max-width: 991px) {
  .stage-media,
  body.is-rtl .stage-media { transform: translateY(24px) scale(0.96); }
}
.stage-panel.is-active .stage-media { opacity: 1; transform: none; }
.stage-panel.is-leaving .stage-media {
  opacity: 0;
  transform: translateX(-24px) scale(0.97);
  transition-duration: 0.3s;
  transition-delay: 0s;
}
body.is-rtl .stage-panel.is-leaving .stage-media { transform: translateX(24px) scale(0.97); }

/* rail: previous / next, one dot per service, the active title above */
.stage-rail {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 7;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 14px;
  padding: 44px var(--stage-pad-x) 18px;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--bg) 90%, transparent) 34%, color-mix(in srgb, var(--bg) 98%, transparent) 100%);
  pointer-events: none;
  translate: 0 24px;
  opacity: 0;
  transition: translate 0.9s var(--ease) 0.45s, opacity 0.7s ease 0.45s;
}
.stage-rail > * { pointer-events: auto; }
.service-stage.is-open .stage-rail { translate: 0 0; opacity: 1; }
.service-stage.is-closing .stage-rail { opacity: 0; translate: 0 16px; transition: opacity 0.25s ease, translate 0.25s ease; }
.stage-rail-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.stage-rail-label {
  margin: 0;
  max-width: min(72vw, 520px);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  translate: 0 6px;
  transition: opacity 0.5s ease, translate 0.6s var(--ease);
}
.stage-rail-label.is-in { opacity: 1; translate: 0 0; }
.stage-dots {
  display: flex;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.stage-dot,
.stage-arrow {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(11, 29, 51, 0.12);
  background: rgba(255, 255, 255, 0.75);
  color: var(--ink-2);
  font-size: 1rem;
  cursor: pointer;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transition: background 0.3s ease, color 0.3s ease, transform 0.5s var(--ease), box-shadow 0.5s ease, border-color 0.3s ease;
}
.stage-dot:hover,
.stage-arrow:hover { background: #fff; color: var(--ink); transform: translateY(-2px); }
.stage-dot.is-active {
  background: var(--stage-accent);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--stage-accent) 28%, transparent), 0 12px 30px -10px var(--stage-accent);
}
.stage-arrow { flex: none; width: 50px; height: 50px; }
.stage-close:focus-visible,
.stage-dot:focus-visible,
.stage-arrow:focus-visible { outline: 2px solid #1e63c7; outline-offset: 3px; }
body.is-rtl .stage-arrow i { transform: scaleX(-1); }
body.is-rtl .stage-title,
body.is-rtl .stage-cta h3,
body.is-rtl .stage-rail-label,
body.is-rtl .stage-kicker { font-family: var(--font-ar); letter-spacing: 0; }
body.is-rtl .stage-title { line-height: 1.25; }
@media (max-width: 639px) {
  .stage-dots { display: none; }
  .stage-rail { padding-top: 36px; }
}

@keyframes stage-drift {
  from { transform: scale(1) translate(0, 0); }
  to { transform: scale(1.12) translate(-2%, 2%); }
}
@media (prefers-reduced-motion: reduce) {
  .stage-bg,
  .stage-window::after { animation: none; }
  .stage-copy > *,
  .stage-media,
  .stage-rail,
  .stage-close,
  .stage-rail-label { opacity: 1; translate: 0 0; transform: none; filter: none; }
  .bento.is-open .service-card:not(.is-source) { opacity: 1; }
}

/* -------------------------------------------------------------------------
   13c. Round-3 feedback: hero light-up, expertise backdrop, popout cards,
   calmer process steps, activity list
   ------------------------------------------------------------------------- */
/* hero: touching a card lights its connector; touching the core lights everything */
.hero-card,
.hero-core { cursor: default; }
.hero-card { transition: border-color 0.4s ease, box-shadow 0.4s ease, background 0.4s ease, scale 0.6s var(--ease); }
.hero-card i { transition: background 0.4s ease, color 0.4s ease, box-shadow 0.4s ease; }
.hero-card:hover,
.hero-card.is-lit {
  scale: 1.05;
  border-color: rgba(15, 122, 82, 0.7);
  background: rgba(255, 255, 255, 0.96);
  box-shadow: 0 30px 60px -30px rgba(11, 29, 51, 0.3), 0 0 54px -6px rgba(15, 122, 82, 0.45), inset 0 1px 0 #fff;
}
.hero-card:hover i,
.hero-card.is-lit i {
  background: var(--teal);
  color: #fff;
  box-shadow: 0 0 26px rgba(15, 122, 82, 0.6);
}
.hero-halo { transition: scale 1.2s var(--ease), background 0.9s ease; }
.hero-visual.is-lit .hero-halo {
  scale: 1.3;
  background: radial-gradient(circle, rgba(47, 176, 124, 0.5), rgba(15, 122, 82, 0.3) 45%, transparent 70%);
}
.hero-core { transition: background 0.6s ease, border-color 0.6s ease, box-shadow 0.6s ease; }
.hero-core.is-lit {
  border-color: rgba(15, 122, 82, 0.6);
  background: radial-gradient(circle, rgba(47, 176, 124, 0.3), rgba(15, 122, 82, 0.18) 55%, rgba(255, 255, 255, 0.6) 78%);
  box-shadow: inset 0 0 70px rgba(47, 176, 124, 0.35), 0 0 140px -10px rgba(15, 122, 82, 0.55);
}
.hero-core.is-lit::before {
  animation-duration: 2.4s;
  background: conic-gradient(from 0deg, transparent 0 40%, rgba(47, 176, 124, 1) 72%, transparent 100%);
}
.hero-core.is-lit::after { border-color: rgba(47, 176, 124, 0.5); animation-duration: 20s; }
.hero-core.is-lit .brand-mark-lg {
  box-shadow: 0 0 100px rgba(47, 176, 124, 0.95), 0 0 34px rgba(255, 255, 255, 0.55);
  animation-duration: 1.3s;
}

/* expertise section: the hero's backdrop behind a frosted section head (colours in 13e) */
.expertises {
  position: relative;
  isolation: isolate;
  overflow: clip;
}
.section-scrim {
  position: absolute;
  inset: 0;
}
.expertises .section-head {
  display: inline-block;
  padding: 24px 30px 26px;
  border-radius: var(--radius-md);
}
/* hovered card pops out towards the visitor (no sibling fade or blur any more) */
.service-card:hover,
.service-card.is-source { z-index: 4; }
/* while the pointer rests on a card its description lights up word by word (a
   reading sweep, purely visual); the card opens on click only */
.service-expand { position: relative; }

/* process steps: nothing moves the layout any more (a padding shift re-fitted the
   backdrop video); the active step gets an accent bar instead */
.process-step { position: relative; }
.process-step::before {
  content: "";
  position: absolute;
  inset-inline-start: -26px;
  top: 50%;
  width: 3px;
  height: 0;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--teal-2), var(--blue-glow));
  translate: 0 -50%;
  opacity: 0;
  transition: height 0.6s var(--ease), opacity 0.4s ease;
}
.process-step.is-active::before { height: 58%; opacity: 1; }
.process-step h3 { transition: color 0.4s ease; }
.process-step.is-active h3 { color: var(--ink); }
.approach .noise { mix-blend-mode: normal; opacity: 0.05; }

/* about: the activity list is a block list (a grid turned each highlighted word into a cell) */
.activity-list li {
  display: block;
  position: relative;
  padding: 22px 0;
  padding-inline-start: 76px;
}
.activity-list li::before {
  position: absolute;
  inset-inline-start: 0;
  top: 22px;
}
.activity-list li:hover { padding-inline-start: 76px; }
.activity-list li > span { transition: translate 0.4s var(--ease); }
@media (max-width: 639px) {
  .activity-list li { padding-inline-start: 48px; }
  .activity-list li:hover { padding-inline-start: 48px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-card,
  .hero-card.is-lit,
  .hero-visual.is-lit .hero-halo { scale: 1; }
}

/* -------------------------------------------------------------------------
   13d. Subject select, scroll-driven marker highlight, CTA hover hue
   ------------------------------------------------------------------------- */
/* contact subject: the native select stays (keyboard, phones); a tile shows the
   chosen subject's icon, the chevron badge turns, and on desktop a glass list opens */
.select-shell {
  --accent: var(--teal);
  position: relative;
}
.select-shell select {
  padding-inline-start: 60px;
  background-image: none;
}
.select-tile,
.select-chev {
  position: absolute;
  top: 50%;
  display: grid;
  place-items: center;
  translate: 0 -50%;
  pointer-events: none;
}
.select-tile {
  inset-inline-start: 10px;
  width: 38px;
  height: 38px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) 16%, #fff);
  color: color-mix(in srgb, var(--accent) 72%, #000);
  font-size: 1.1rem;
  transition: background 0.4s ease, color 0.4s ease, scale 0.5s var(--ease-spring);
}
.select-shell.is-changed .select-tile { scale: 1.12; }
.select-chev {
  inset-inline-end: 10px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 0.9rem;
  transition: rotate 0.45s var(--ease), background 0.3s ease, color 0.3s ease;
}
.select-shell:focus-within .select-chev { color: var(--teal-ink); }
.select-shell.is-open .select-chev { rotate: 180deg; background: var(--accent); color: #fff; }
.select-shell:focus-within select,
.select-shell.is-open select {
  background: #fff;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 20%, transparent), 0 12px 30px -16px color-mix(in srgb, var(--accent) 60%, transparent);
}
.select-menu {
  position: absolute;
  z-index: 20;
  inset-inline: 0;
  top: calc(100% + 8px);
  max-height: min(60vh, 540px);
  overflow: auto;
  padding: 8px;
  border-radius: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 30px 80px -30px rgba(11, 29, 51, 0.35);
  opacity: 0;
  translate: 0 -8px;
  scale: 0.98;
  transform-origin: 50% 0;
  visibility: hidden;
  transition: opacity 0.25s ease, translate 0.45s var(--ease), scale 0.45s var(--ease), visibility 0s linear 0.3s;
}
.select-shell.is-open .select-menu {
  opacity: 1;
  translate: 0 0;
  scale: 1;
  visibility: visible;
  transition-delay: 0s;
}
.select-option {
  --accent: var(--teal);
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.95rem;
  text-align: start;
  cursor: pointer;
  opacity: 0;
  translate: 0 6px;
  transition: background 0.2s ease, opacity 0.4s ease var(--d, 0s), translate 0.5s var(--ease) var(--d, 0s);
}
.select-shell.is-open .select-option { opacity: 1; translate: 0 0; }
.select-option-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 16%, #fff);
  color: color-mix(in srgb, var(--accent) 72%, #000);
  font-size: 1rem;
}
.select-option-check {
  margin-inline-start: auto;
  color: var(--teal-ink);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.select-option:hover,
.select-option.is-hot { background: var(--surface-2); }
.select-option[aria-selected="true"] { background: color-mix(in srgb, var(--accent) 12%, #fff); }
.select-option[aria-selected="true"] .select-option-check { opacity: 1; }

/* marker highlight: a teal highlighter sweeps each word as it is read. The hero
   headline is driven by scroll progress, the process steps by the reading line. */
.hero .display .w > span,
.process-body h3.read .rw > span {
  background-image: linear-gradient(90deg, var(--blue-glow), var(--teal-2));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 0.11em;
  padding-bottom: 0.06em;
  transition: background-size 0.5s var(--ease);
}
.hero .display .w > span {
  transition: opacity 0.7s ease, transform 0.9s var(--ease), filter 0.7s ease, background-size 0.5s var(--ease);
}
body.is-rtl .hero .display .w > span,
body.is-rtl .process-body h3.read .rw > span { background-position: 100% 100%; }
.hero .display .w.on > span,
.process-body h3.read .rw.on > span { background-size: 100% 0.11em; }
.process-body h3.read .rw { opacity: 0.45; }
.process-body h3.read .rw.on { opacity: 1; }

/* CTA card: a hue shift and the conic glow while hovered (untouched at rest) */
.cta-card { transition: box-shadow 0.8s var(--ease); }
.cta-card .cta-bg { transition: filter 1.4s ease; }
.cta-card .orb { transition: scale 1.6s var(--ease); }
.cta-card::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  padding: 1.5px;
  background: conic-gradient(from var(--angle), var(--teal-2), transparent 30%, var(--blue-glow) 50%, transparent 70%, var(--teal-2));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  transition: opacity 0.6s ease;
  pointer-events: none;
}
.cta-card:hover { box-shadow: 0 0 0 1px rgba(47, 176, 124, 0.35), 0 50px 130px -40px rgba(47, 176, 124, 0.45); }
.cta-card:hover .cta-bg { filter: hue-rotate(-45deg) saturate(1.4) brightness(1.25); }
.cta-card:hover .orb { scale: 1.25; }
.cta-card:hover::after { opacity: 1; animation: angle-spin 5s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .select-option { opacity: 1; translate: 0 0; }
  .cta-card:hover::after { animation: none; }
}

/* -------------------------------------------------------------------------
   13e. Round-10: the node network behind the approach chapter and the story
   rail, and a continuously eased card hover. Round-17 (section 24) made the
   whole site bright, so the dark stats strip and dark CTA band of this round
   are gone again.
   ------------------------------------------------------------------------- */
/* expertises: on the home hero's backdrop (ribbon and node network, ground
   set in hero-home.css); a frosted white panel behind the section head and
   white glass cards with black text. Every card keeps its own service accent
   (ring, icon gradient, ghost icon, shadow) for the hover. */
.expertises {
  background: var(--bg);
  color: var(--ink);
}
/* the washed ambient clips (hub items section) */
.ambient-video-light {
  opacity: 1;
  filter: saturate(0.9) brightness(1.05) contrast(0.95);
  object-position: 50% 50%;
  transform: translateZ(0);
}
.expertises .section-head {
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.9);
  box-shadow: 0 24px 60px -34px rgba(11, 29, 51, 0.35), inset 0 1px 0 #fff;
  -webkit-backdrop-filter: blur(18px) saturate(1.2);
  backdrop-filter: blur(18px) saturate(1.2);
}
.expertises .service-card {
  background-color: rgba(255, 255, 255, 0.86);
  border-color: rgba(255, 255, 255, 0.95);
  /* a small contact shadow under the long soft one, for depth at rest */
  box-shadow:
    0 1px 2px rgba(11, 29, 51, 0.06),
    0 6px 16px -6px rgba(11, 29, 51, 0.25),
    0 24px 60px -34px rgba(11, 29, 51, 0.3),
    inset 0 1px 0 #fff;
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
}
.expertises .service-card:hover,
.expertises .service-card.is-source {
  background-color: rgba(255, 255, 255, 0.97);
  border-color: transparent;
  box-shadow:
    0 0 36px -8px color-mix(in srgb, var(--accent, var(--teal)) 50%, transparent),
    0 30px 60px -30px color-mix(in srgb, var(--accent, var(--teal)) 45%, transparent),
    var(--shadow-md);
}
.expertises .service-card.is-source {
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--accent, var(--teal)) 55%, transparent),
    0 0 90px -10px color-mix(in srgb, var(--accent, var(--teal)) 70%, transparent),
    var(--shadow-md);
}
.expertises .service-summary { color: var(--ink-2); }
.expertises .service-more { color: var(--ink); }
.expertises .service-ghost { opacity: 0.07; }
.expertises .service-card:hover .service-ghost { opacity: 0.14; }
.expertises .service-card::after { background: radial-gradient(circle, color-mix(in srgb, var(--accent, var(--blue-glow)) 14%, transparent), transparent 65%); }

/* the node network (the hero's living background) behind the approach chapter
   and the story rail; the host section catches the pointer, the canvas just draws */
.net-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.85;
  -webkit-mask-image: radial-gradient(ellipse at 50% 50%, #000 45%, transparent 96%);
  mask-image: radial-gradient(ellipse at 50% 50%, #000 45%, transparent 96%);
}
.net-host { position: relative; }
@media (max-width: 991px), (prefers-reduced-motion: reduce) {
  .net-bg { display: none; }
}

/* smooth hover: JS eases a hover amount (--hv, 0..1) and the tilt angles every
   frame, so pop-out, lift, spotlight and tilt move as one continuous motion from
   the first frame to the last. While it runs, the CSS transform transition is
   off (it would restart on every frame and fight the easing). */
.tilt {
  --hover-sc: 1.015;
  --hover-lift: -6px;
  --sc: calc(1 + (var(--hover-sc) - 1) * var(--hv, 0));
  --lift: calc(var(--hover-lift) * var(--hv, 0));
  transition: transform 0.6s var(--ease), box-shadow 0.6s var(--ease), border-color 0.4s ease, background-color 0.5s ease, opacity 0.5s ease, filter 0.5s ease;
}
.service-card { --hover-sc: 1.05; --hover-lift: -10px; }
.tilt.is-tilting { transition-property: box-shadow, border-color, background-color, opacity, filter; }
.tilt.is-source { transition-property: transform, box-shadow, border-color, background-color, opacity, filter; }
.service-card.is-tilting { z-index: 4; } /* stays above its neighbours until it has settled */
html:not(.js) .tilt:hover { --hv: 1; }
@media (hover: none) { .tilt:hover { --hv: 1; } }
/* the icon's gradient fades in on a layer of its own (a solid-to-gradient
   background cannot be interpolated and used to snap) */
.service-icon { position: relative; isolation: isolate; }
.service-icon::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(135deg, var(--blue), var(--accent, var(--teal)));
  opacity: 0;
  transition: opacity 0.45s ease;
}
.service-card:hover .service-icon::before { opacity: 1; }

/* -------------------------------------------------------------------------
   21b. Hub catalogue (/solutions/, /artificial-intelligence/): the hero's
   jump chips, then one ruled chapter per group of pages/hubs.py. From
   1024px a chapter is two columns: its head in a sticky side column (index,
   count, label, lead), its items as compact tiles in an auto-fill grid that
   takes the remaining width and wraps as items are added (2026-11-03:
   replaced the two-column card grid, which left most of each card empty).
   A hub without groups (AI) is one chapter without a head. A tile: icon and
   index, title, lead (the hover copy of section 25 swaps in over it), then
   a foot with the services mobilised as icon chips (the name in a tooltip;
   the stage spells out each one's role) and the open button. The contact
   card closes the catalogue as one slim band.
   ------------------------------------------------------------------------- */
.solution-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 32px;
}
.solution-jump a,
.solution-jump .is-soon {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.6);
  color: var(--ink-2);
  font-size: 0.86rem;
  font-weight: 500;
  transition: color 0.3s ease, border-color 0.3s ease, background 0.3s ease, transform 0.4s var(--ease);
}
.solution-jump i { color: var(--teal-ink); }
.solution-jump a:hover {
  color: var(--teal-ink);
  border-color: rgba(15, 122, 82, 0.5);
  background: var(--teal-soft);
  transform: translateY(-2px);
}
.solution-jump .is-soon { opacity: 0.45; filter: blur(0.8px); cursor: default; }

/* the catalogue: a stack of chapters (the stage script dims this one grid, section 25) */
.solution-grid { display: grid; gap: clamp(36px, 5vw, 60px); perspective: 1200px; }
.solution-group {
  display: grid;
  gap: 20px;
  padding-top: 22px;
  border-top: 1px solid var(--line-2);
}
.solution-group--plain { padding-top: 0; border-top: 0; }
.solution-group-head { display: grid; gap: 10px; align-content: start; }
.solution-group-index {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.solution-group-index .index { color: var(--teal-ink); }
.solution-group-count { padding-inline-start: 12px; border-inline-start: 1px solid var(--line-2); }
.solution-group-head h2 {
  margin: 0;
  font-size: clamp(1.4rem, 1rem + 1.2vw, 1.9rem);
  letter-spacing: -0.02em;
}
.solution-group-lead {
  margin: 0;
  max-width: 32ch;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-2);
}
@media (min-width: 1024px) {
  .solution-group {
    grid-template-columns: minmax(200px, 0.85fr) minmax(0, 3.6fr);
    gap: clamp(28px, 4vw, 56px);
    align-items: start;
  }
  .solution-group--plain { grid-template-columns: minmax(0, 1fr); }
  .solution-group-head { position: sticky; top: calc(var(--header-h) + 28px); }
}

/* the tiles: as many tracks as fit, every row the same height (the foot sticks to the bottom);
   auto-fit stretches a short chapter over its row, so three sectors read 3-up and four
   functions 4-up on the same page with no empty cell */
.solution-tiles {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 208px), 1fr));
}
.solution-card {
  display: flex;
  flex-direction: column;
  padding: 18px 18px 14px;
  border-radius: 20px;
}
.solution-card > * { position: relative; z-index: 1; }
.solution-card-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.solution-card .service-icon {
  width: 42px;
  height: 42px;
  border-radius: 12px;
  font-size: 1.15rem;
}
.solution-card h2 {
  margin: 16px 0 6px;
  font-size: 1.12rem;
  line-height: 1.25;
  letter-spacing: -0.015em;
}
/* .solution-card prefix: .value-card p resets paragraph margins with higher specificity */
.solution-card .solution-lead {
  margin: 0;
  color: var(--ink-2);
  font-size: 0.9rem;
  line-height: 1.5;
}
.solution-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
/* service chips: icon only, the name in a tooltip above the row (anchored to the list,
   not the chip, so a long name never runs past the tile's edge) */
.solution-services {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.solution-chip {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: var(--surface-2);
  border: 1px solid transparent;
  color: var(--teal-ink);
  font-size: 0.92rem;
  transition: background 0.3s ease, border-color 0.3s ease, transform 0.4s var(--ease);
}
.solution-chip:hover,
.solution-chip:focus-visible {
  background: var(--teal-soft);
  border-color: rgba(15, 122, 82, 0.4);
  transform: translateY(-2px);
}
.solution-chip:focus-visible { outline: 2px solid #1e63c7; outline-offset: 2px; }
.solution-chip::after {
  content: attr(data-label);
  position: absolute;
  z-index: 3;
  bottom: calc(100% + 8px);
  inset-inline-start: 0;
  width: max-content;
  max-width: 230px;
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--dark-2);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.35s var(--ease);
}
.solution-chip:hover::after,
.solution-chip:focus-visible::after { opacity: 1; transform: none; }

/* contact band */
.solution-card-other {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  padding: 24px 28px;
  background: var(--dark-2);
  border-color: transparent;
  color: var(--on-dark);
}
.solution-card-other::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(70% 60% at 100% 0%, rgba(15, 122, 82, 0.45), transparent 70%),
    radial-gradient(60% 50% at 0% 100%, rgba(15, 122, 82, 0.35), transparent 70%);
  pointer-events: none;
}
.solution-card-other-text { display: flex; align-items: center; gap: 18px; }
.solution-card-other .service-icon { flex: none; width: 48px; height: 48px; background: rgba(255, 255, 255, 0.1); color: var(--teal-2); }
.solution-card-other h2 { margin: 0 0 4px; color: #fff; font-size: 1.2rem; }
.solution-card-other .solution-lead { color: var(--on-dark-2); }
.solution-card-other .btn { flex: none; }
/* teaser tile ("soon"): dashed, blurred content, crisp tag, no link anywhere */
.solution-card.is-soon { border-style: dashed; }
.solution-card.is-soon:hover { border-color: var(--line-2); box-shadow: none; }
.solution-card.is-soon:hover .service-icon { transform: none; background: var(--teal-soft); color: var(--teal-ink); }
.solution-card.is-soon .service-icon,
.solution-card.is-soon h2,
.solution-card.is-soon .solution-lead { filter: blur(1.5px); opacity: 0.55; }
.solution-tag {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--teal-ink);
}

/* -------------------------------------------------------------------------
   22. RTL / Arabic
   ------------------------------------------------------------------------- */
body.is-rtl { font-family: var(--font-ar); }
body.is-rtl h1,
body.is-rtl h2,
body.is-rtl h3,
body.is-rtl h4,
body.is-rtl .display,
body.is-rtl .h-display,
body.is-rtl .main-nav .nav-link,
body.is-rtl .btn,
body.is-rtl .brand-full,
body.is-rtl .hero-card,
body.is-rtl .stat-num {
  font-family: var(--font-ar);
  letter-spacing: 0;
}
body.is-rtl .display { line-height: 1.22; }
body.is-rtl .h-display { line-height: 1.28; }
body.is-rtl .process-step h3,
body.is-rtl .about-block h2 { line-height: 1.3; }
body.is-rtl .eyebrow,
body.is-rtl .index,
body.is-rtl .stat-label,
body.is-rtl .marquee-item,
body.is-rtl .footer-col h3,
body.is-rtl .breadcrumb,
body.is-rtl .service-index,
body.is-rtl .chapter-index,
body.is-rtl .chapter-num,
body.is-rtl .process-num,
body.is-rtl .lang-btn {
  font-family: var(--font-ar);
  letter-spacing: 0;
}
body.is-rtl .btn-arrow { transform: scaleX(-1); }
body.is-rtl .btn:hover .btn-arrow { transform: scaleX(-1) translateX(5px); }
body.is-rtl .btn::before { transform: translateX(130%) skewX(12deg); }
body.is-rtl .btn:hover::before { transform: translateX(-130%) skewX(12deg); }
body.is-rtl .scroll-progress { transform-origin: 100% 50%; }
body.is-rtl .hero-card { padding: 14px 14px 14px 20px; }
body.is-rtl .nav-sub-link,
body.is-rtl .solution-jump a,
body.is-rtl .solution-group-lead,
body.is-rtl .solution-lead {
  font-family: var(--font-ar);
  letter-spacing: 0;
}
body.is-rtl .nav-sub-other:hover .btn-arrow { transform: scaleX(-1) translateX(5px); }

/* -------------------------------------------------------------------------
   23. Reduced motion
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; translate: 0 0; scale: 1; filter: none; }
  .js .reveal-words .w span { opacity: 1; transform: none; filter: none; }
  .read .rw { opacity: 1; }
  .marquee-track { animation: none; }
  .hero-grid { animation: none; }
  .tilt, .chapter-card { transform: none; }
  .site-header.is-hidden { transform: none; }
}

/* -------------------------------------------------------------------------
   24. Round-17: the bright theme. White and neutral backgrounds on every page
   with dark text; the only dark surfaces left are the CTA card (kept as is),
   its small cousin on the service detail page, the "other" card of the hubs
   and the footer. The contact and service detail heroes carry a stock clip
   washed almost white (hero_bg.html takes clip=); the home, hub, services
   and about heroes sit on the ribbon (section 28). Inner sections alternate
   between the page background and the cool grey tint band (.section-tint).
   ------------------------------------------------------------------------- */
:root {
  /* node network colours (r, g, b triplets) read by initNetwork in main.js */
  --net-link: 15, 122, 82;
  --net-pointer: 15, 122, 82;
  --net-node: 11, 29, 51;
  --net-spark: 11, 29, 51;
}
.hero .orb,
.page-hero .orb { opacity: 0.4; }
.page-hero .hero-canvas { opacity: 0.45; }
/* the home hero clip is a nearly white screen of code: let a little more through */
.hero .hero-video-shade {
  background:
    linear-gradient(180deg, rgba(243, 245, 248, 0.82), rgba(243, 245, 248, 0.5) 40%, rgba(243, 245, 248, 0.96)),
    radial-gradient(70% 60% at 30% 50%, rgba(243, 245, 248, 0.6), transparent 70%);
}
/* the CTA card keeps its white grid on dark */
.cta-card .grid-lines {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
}
/* approach chapter: the solar-field clip under a heavy wash (the steps sit
   straight on it, no cards), the node network drawn over it */
.approach {
  position: relative;
  isolation: isolate;
  overflow: clip;
  background: var(--bg);
}
.approach .section-scrim {
  background: linear-gradient(180deg, rgba(243, 245, 248, 0.95) 0%, rgba(243, 245, 248, 0.76) 22%, rgba(243, 245, 248, 0.74) 78%, rgba(243, 245, 248, 0.96) 100%);
}
.approach .orb-a { opacity: 0.35; }
/* the drone footage is earth-toned: drained of colour it reads as a neutral grey texture */
.approach .ambient-video-light { filter: saturate(0.45) brightness(1.1) contrast(0.9); }
/* tint bands keep their atmosphere layers soft */
.section-tint .orb { opacity: 0.35; }
.section-tint .noise { opacity: 0.05; mix-blend-mode: normal; }
.section-tint .contact-form,
.section-tint .aside-card,
.section-tint .value-card { background: var(--surface); }
/* hub pages: the card grid sits on the ribbon with the node network over it;
   the cards are white glass so the ribbon lives in the gaps, the "other" card stays dark */
.hub-items .value-card {
  background: rgba(255, 255, 255, 0.8);
  border-color: rgba(255, 255, 255, 0.95);
  box-shadow: 0 24px 60px -34px rgba(11, 29, 51, 0.3), inset 0 1px 0 #fff;
  -webkit-backdrop-filter: blur(7px) saturate(1.2);
  backdrop-filter: blur(7px) saturate(1.2);
}
.hub-items .value-card:hover { background: rgba(255, 255, 255, 0.94); }
/* the node network runs unmasked and denser here (data-net-density / data-net-max on the
   section) so the pointer-linked lines also glow through the card glass */
.hub-items .net-canvas {
  opacity: 1;
  -webkit-mask-image: none;
  mask-image: none;
}
.hub-items .solution-card-other,
.hub-items .solution-card-other:hover { background: var(--dark-2); border-color: transparent; }
.hub-items .solution-card.is-soon { border-color: var(--line-2); }

/* -------------------------------------------------------------------------
   25. Hub stage: a sector / capability card of /solutions/ and /artificial-
   intelligence/ opens into the service stage window (partials/hub_stage.html,
   mounted by main.js beside the home page stage)
   ------------------------------------------------------------------------- */
/* the tile: an expand badge beside the index on hover, a round arrow button at the
   foot's end (label for assistive tech); the full text only reads inline without JavaScript */
.js .solution-card[data-stage] { cursor: pointer; }
.solution-card:hover .service-expand { opacity: 1; scale: 1; translate: 0 0; }
.solution-card .solution-body p {
  margin: 0 0 14px;
  max-width: 52ch;
  font-size: 0.95rem;
  line-height: 1.65;
  color: var(--ink-2);
}
.js .solution-body { display: none; }
/* hover copy: like the services bento, the lead gives way to the full text, which
   the reading sweep (main.js) lights up word by word; pointer devices only */
.solution-text { position: relative; margin: 0 0 18px; }
.solution-card .solution-text .solution-lead { margin: 0; transition: opacity 0.35s ease, transform 0.5s var(--ease); }
.solution-card .solution-more {
  position: absolute;
  inset: 0 0 auto 0;
  margin: 0;
  max-width: 56ch;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--ink);
  opacity: 0;
  transform: translateY(12px);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  pointer-events: none;
  transition: opacity 0.45s ease 0.05s, transform 0.6s var(--ease) 0.05s;
}
html:not(.js) .solution-more { display: none; }
@media (hover: hover) and (pointer: fine) {
  .solution-text { min-height: 4.9rem; } /* room for four lines of the hover copy (three of the lead): no height jump */
  .solution-card:hover .solution-text .solution-lead { opacity: 0; transform: translateY(-10px); }
  .solution-card:hover .solution-more { opacity: 1; transform: none; }
}
.solution-open {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  flex: none;
  width: 34px;
  height: 34px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface-2);
  font: inherit;
  font-size: 0.9rem;
  color: var(--ink);
  cursor: pointer;
  transition: background 0.35s ease, color 0.35s ease, transform 0.5s var(--ease);
}
.solution-open i { transition: transform 0.35s var(--ease); }
.solution-card:hover .solution-open { background: var(--teal-ink); color: #fff; }
.solution-card:hover .solution-open i { transform: translateX(2px); }
body.is-rtl .solution-card:hover .solution-open i { transform: translateX(-2px); }
.solution-open:focus-visible { outline: 2px solid #1e63c7; outline-offset: 4px; }
html:not(.js) .solution-open { display: none; }
/* the clicked card is the morph source; its siblings step back while the stage is open */
.solution-card.is-source {
  z-index: 4;
  border-color: transparent;
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--teal) 55%, transparent),
    0 0 90px -10px color-mix(in srgb, var(--teal) 80%, transparent),
    var(--shadow-md);
}
.solution-card.is-source > * { opacity: 0; transition: opacity 0.25s ease; }
.solution-grid.is-open .solution-card:not(.is-source) { opacity: 0.4; transition: opacity 0.9s ease, transform 0.9s var(--ease); }
.solution-grid.is-open .solution-card.is-source { opacity: 1; }

/* the stage's side column: the services mobilised, each with the part it plays
   in the sector, then the contact card */
.stage-services-label {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.stage-services-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.stage-service {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.82);
  border: 1px solid color-mix(in srgb, var(--stage-accent) 18%, var(--line));
  color: var(--ink);
  text-decoration: none;
  transition: background 0.3s ease, border-color 0.3s ease, transform 0.5s var(--ease), box-shadow 0.5s ease;
}
.stage-service .service-icon {
  flex: none;
  width: 44px;
  height: 44px;
  font-size: 1.1rem;
  background: color-mix(in srgb, var(--stage-accent) 14%, #fff);
  color: color-mix(in srgb, var(--stage-accent) 72%, #000);
}
.stage-service-text { display: grid; gap: 3px; min-width: 0; }
.stage-service-text strong { font-size: 0.98rem; font-weight: 600; line-height: 1.25; }
.stage-service-text span { font-size: 0.86rem; line-height: 1.45; color: var(--ink-2); }
.stage-service-arrow {
  flex: none;
  margin-inline-start: auto;
  color: var(--muted);
  transition: transform 0.35s var(--ease), color 0.3s ease;
}
.stage-service:hover {
  background: #fff;
  border-color: color-mix(in srgb, var(--stage-accent) 45%, transparent);
  transform: translateY(-2px);
  box-shadow: 0 20px 40px -24px color-mix(in srgb, var(--stage-accent) 70%, transparent);
}
.stage-service:hover .stage-service-arrow { color: color-mix(in srgb, var(--stage-accent) 72%, #000); transform: translateX(4px); }
body.is-rtl .stage-service:hover .stage-service-arrow { transform: translateX(-4px); }
.stage-service:focus-visible { outline: 2px solid #1e63c7; outline-offset: 3px; }
body.is-rtl .stage-service-text strong,
body.is-rtl .stage-services-label { font-family: var(--font-ar); letter-spacing: 0; }
@media (prefers-reduced-motion: reduce) {
  .solution-grid.is-open .solution-card:not(.is-source) { opacity: 1; }
}

/* -------------------------------------------------------------------------
   26. Cookie consent banner (base.html + static/js/consent.js), footer legal
       links, the contact form notice and the privacy page (/privacy/)
   ------------------------------------------------------------------------- */
.consent {
  position: fixed;
  z-index: 95;
  inset-inline-start: clamp(12px, 2vw, 24px);
  bottom: clamp(12px, 2vw, 24px);
  width: min(420px, calc(100vw - 2 * clamp(12px, 2vw, 24px)));
  opacity: 0;
  translate: 0 24px;
  transition: opacity 0.6s var(--ease), translate 0.7s var(--ease);
}
.consent.is-open { opacity: 1; translate: 0 0; }
.consent-card {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: 26px 26px 22px;
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md), 0 0 0 1px rgba(255, 255, 255, 0.6) inset;
  -webkit-backdrop-filter: blur(18px);
  backdrop-filter: blur(18px);
}
.consent-card::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -90px;
  inset-inline-end: -90px;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(15, 122, 82, 0.22), transparent 65%);
  pointer-events: none;
}
.consent .eyebrow { margin-bottom: 12px; }
.consent-title { font-size: 1.22rem; margin-bottom: 10px; }
.consent-text { font-size: 0.93rem; line-height: 1.6; margin-bottom: 16px; }
.consent-list { display: grid; gap: 8px; margin-bottom: 20px; }
.consent-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--ink);
}
.consent-list i { color: var(--teal-ink); font-size: 1rem; }
.consent-list em {
  margin-inline-start: auto;
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.consent-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.consent-actions .btn { width: 100%; padding-inline: 16px; }
.consent-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 16px;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-2);
  transition: color 0.2s ease;
}
.consent-link:hover { color: var(--blue); }
.consent-link i { transition: transform 0.4s var(--ease); }
.consent-link:hover i { transform: translateX(4px); }
body.is-rtl .consent-link i { transform: scaleX(-1); }
body.is-rtl .consent-link:hover i { transform: scaleX(-1) translateX(4px); }
body.is-rtl .consent-title { line-height: 1.35; }
@media (max-width: 480px) {
  .consent { inset-inline: 10px; bottom: 10px; width: auto; }
  .consent-card { padding: 22px 20px 18px; border-radius: var(--radius-md); }
}
@media (prefers-reduced-motion: reduce) {
  .consent { transition: none; }
}

/* footer: legal links sit between the copyright and the back-to-top button */
.footer-bottom { flex-wrap: wrap; }
.footer-legal { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 20px; }
.footer-legal a,
.footer-legal-btn {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: color 0.25s ease;
}
.footer-legal a:hover,
.footer-legal-btn:hover { color: #fff; }

/* contact form: the one-line privacy notice under the submit button */
.form-privacy {
  margin: 14px 0 0;
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--muted);
}
.form-privacy a {
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: rgba(11, 29, 51, 0.3);
  text-underline-offset: 3px;
  transition: color 0.2s ease;
}
.form-privacy a:hover { color: var(--blue); }

/* privacy page */
.legal-meta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 22px 0 0;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.74rem;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.legal-meta i { color: var(--teal-ink); }
.legal-grid { display: grid; gap: 48px; align-items: start; }
@media (min-width: 992px) {
  .legal-grid { grid-template-columns: 260px minmax(0, 1fr); gap: 80px; }
  .legal-toc { position: sticky; top: calc(var(--header-h) + 32px); }
}
.legal-toc h2 {
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
.legal-toc ol { display: grid; counter-reset: toc; }
.legal-toc a {
  display: flex;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--ink-2);
  transition: color 0.2s ease, padding 0.35s var(--ease);
}
.legal-toc a::before {
  counter-increment: toc;
  content: counter(toc, decimal-leading-zero);
  padding-top: 3px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--teal-ink);
}
.legal-toc a:hover { color: var(--ink); padding-inline-start: 6px; }
.legal-body { max-width: 780px; }
.legal-section {
  padding: clamp(32px, 4vw, 48px) 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: calc(var(--header-h) + 24px);
}
.legal-section:first-child { padding-top: 0; border-top: 0; }
.legal-section h2 { font-size: clamp(1.4rem, 2.4vw, 1.9rem); margin-bottom: 16px; }
.legal-section h3 { font-size: 1.1rem; margin: 24px 0 8px; }
.legal-section p,
.legal-section li {
  font-size: 1.03rem;
  line-height: 1.7;
  color: var(--ink-2);
}
.legal-section p { max-width: 66ch; }
.legal-section ul { display: grid; gap: 10px; margin: 0 0 1.2em; }
.legal-section ul li { position: relative; padding-inline-start: 22px; }
.legal-section ul li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0.72em;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal);
}
.legal-section p a {
  color: var(--blue);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: rgba(11, 29, 51, 0.3);
  text-underline-offset: 3px;
}
.legal-section p a:hover { text-decoration-color: currentColor; }
.legal-section strong { color: var(--ink); font-weight: 600; }
.legal-table-wrap {
  overflow-x: auto;
  margin: 8px 0 1.4em;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
}
.legal-table { width: 100%; min-width: 600px; border-collapse: collapse; font-size: 0.92rem; }
.legal-table th,
.legal-table td {
  padding: 12px 16px;
  text-align: start;
  vertical-align: top;
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
}
.legal-table th {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-2);
}
.legal-table tr:last-child td { border-bottom: 0; }
.legal-table code { font-family: var(--font-mono); font-size: 0.84rem; color: var(--ink); white-space: nowrap; }
.legal-tag {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 0.64rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.legal-tag-essential { background: var(--teal-soft); color: var(--teal-ink); }
.legal-tag-consent { background: #eef2ff; color: #3730a3; }
.legal-contact { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }
body.is-rtl .legal-section h2 { line-height: 1.3; }
body.is-rtl .legal-toc a,
body.is-rtl .legal-section p,
body.is-rtl .legal-section li { line-height: 1.85; }

/* RTL: the mono labels of section 26 fall back to the Arabic face, no tracking
   (JetBrains Mono has no Arabic glyphs and letter-spacing breaks the joined script) */
body.is-rtl .consent-list em,
body.is-rtl .legal-meta,
body.is-rtl .legal-toc h2,
body.is-rtl .legal-table th,
body.is-rtl .legal-tag { font-family: var(--font-ar); letter-spacing: 0; }

/* -------------------------------------------------------------------------
   27. Corporate identity layer (NMD-Corporate-Design v1.0, 2026-10-31).
   The tokens above now carry the brand values (navy #0b1d33 carries, green
   #0f7a52 punctuates, bright green #2fb07c on navy); this section adds the
   typography, the logo files and the green square on top of the existing
   layout, motion and backgrounds.
   ------------------------------------------------------------------------- */
h1, h2, h3, .display, .h-display, .stat-num, .stage-title, .story-chip h3,
.consent-title, .cta-card h2 { font-family: var(--font-display); }
.display { font-weight: 700; letter-spacing: -0.025em; }
.h-display { font-weight: 700; letter-spacing: -0.02em; }
body.is-rtl h1, body.is-rtl h2, body.is-rtl h3, body.is-rtl .display, body.is-rtl .h-display,
body.is-rtl .stat-num, body.is-rtl .stage-title { font-family: var(--font-ar); letter-spacing: 0; }

/* labels in Inter 500, +8 % tracking; the eyebrow dot becomes the green square */
.eyebrow, .footer-col h3, .stage-services-label, .solution-services-label { font-family: var(--font-sans); letter-spacing: 0.08em; }
.eyebrow-dot { border-radius: 0; }

/* focus ring: blue, never the brand colours (02-couleurs.md) */
:focus-visible { outline-color: #1e63c7; }
.form-control:focus, .form-select:focus { border-color: #1e63c7; }

/* buttons: radius-md instead of pills (components/Button) */
.btn { border-radius: var(--radius-sm); }

/* the official logo files; the monogram alone where the full logo was hidden */
.navbar-brand .brand-logo { display: block; height: 28px; width: auto; }
.navbar-brand .brand-logo--mark { display: none; height: 24px; }
@media (max-width: 359.98px) {
  .navbar-brand .brand-logo--full { display: none; }
  .navbar-brand .brand-logo--mark { display: block; }
}
.footer-brand .navbar-brand .brand-logo { height: 32px; }
.footer-watermark {
  position: absolute;
  z-index: -1;
  left: 50%;
  bottom: -2%;
  width: min(58vw, 680px);
  height: auto;
  transform: translateX(-50%);
  opacity: 0.07;
  pointer-events: none;
  user-select: none;
}

/* hero brand card: the business-card verso of the charte (05-applications.md)
   floating at the centre of the hero layers — navy, vertical white logo,
   the claim with « Et vous ? » in bright green, site and city */
.hero-brandcard {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 310px;
  aspect-ratio: 85 / 55;
  padding: 18px 22px 16px;
  border-radius: var(--radius-lg);
  background: var(--dark);
  color: #fff;
  box-shadow: 0 40px 80px -36px rgba(11, 29, 51, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  animation: float 9s ease-in-out infinite;
}
.hero-brandcard::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, 0.1);
  pointer-events: none;
}
.brandcard-logo { height: 64px; width: auto; align-self: center; margin-top: 4px; }
.brandcard-claim {
  margin: 0;
  font-family: var(--font-display);
  font-size: 0.98rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
}
.brandcard-claim em { display: block; font-style: normal; color: var(--teal-2); }
.brandcard-meta {
  margin: 6px 0 0;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--on-dark-2);
}
body.is-rtl .brandcard-claim { font-family: var(--font-ar); letter-spacing: 0; }
@media (max-width: 639px) {
  .hero-brandcard { width: 240px; padding: 14px 16px 12px; }
  .brandcard-logo { height: 48px; }
  .brandcard-claim { font-size: 0.82rem; }
  .brandcard-meta { font-size: 0.6rem; }
}
@media (prefers-reduced-motion: reduce) { .hero-brandcard { animation: none; } }
/* the brand card is wider than the former core: the two middle layers move
   outward so nothing covers the claim (parallax offsets stay within reach) */
.layer-2 { top: 10%; }
.layer-3 { bottom: 10%; }
.hero-brandcard { width: 296px; }

/* -------------------------------------------------------------------------
   28. Ticklist: the self-checking project list beside the services headline
   (partials/ticklist.html, sequenced by main.js). A white card in the hero
   panel slot: the rows tick one after the other, a new task slides in
   half-way and is ticked too, the delivered row appears, then the list
   clears and starts again. The markup is the still frame for no-JS and
   reduced motion.
   ------------------------------------------------------------------------- */
@media (min-width: 992px) {
  .page-hero-grid--ticklist { grid-template-columns: minmax(0, 1fr) 320px; }
  .hero-panel.ticklist { max-width: 320px; }
}
.ticklist {
  position: relative;
  width: 100%;
  overflow: hidden;
  border-radius: 20px;
  border: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.4); /* 40 %, the opacity shared by the three hero panels (sections 28, 29, 31): the hero shows through, the rows read well (was var(--surface)) */
  color: var(--ink);
  font-family: var(--font-sans);
  text-align: start;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 30px 60px -32px rgba(11, 29, 51, 0.38),
    0 12px 30px -18px rgba(11, 29, 51, 0.18);
}
.ticklist-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 18px 14px;
}
.ticklist-kicker {
  margin: 0 0 4px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
.ticklist-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.ticklist-count {
  flex: none;
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  margin-top: 2px;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  direction: ltr; /* « 5/7 » reads the same in Arabic */
  unicode-bidi: isolate;
}
.ticklist-count b { font-weight: 600; color: var(--ink); }
.ticklist-bar { height: 3px; background: var(--surface-2); }
.ticklist-bar span {
  display: block;
  height: 100%;
  background: var(--teal);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.7s var(--ease);
}
.ticklist-items { margin: 0; padding: 0; list-style: none; }

/* every row is a one-track grid so it can fold to nothing (0fr) and back */
.ticklist-item,
.ticklist-foot {
  display: grid;
  grid-template-rows: 1fr;
  border-top: 1px solid var(--line);
  transition: grid-template-rows 0.6s var(--ease), border-color 0.4s var(--ease);
}
.ticklist-item:first-child { border-top: 0; }
.ticklist-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 0;
  overflow: hidden;
  padding: 11px 18px;
  transition: padding 0.6s var(--ease), opacity 0.4s var(--ease), transform 0.6s var(--ease);
}
.is-collapsed { grid-template-rows: 0fr; border-top-color: transparent; }
.is-collapsed > .ticklist-row { padding-top: 0; padding-bottom: 0; opacity: 0; transform: translateY(8px); }

.ticklist-box {
  flex: none;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 6px;
  border: 1.5px solid var(--line-2);
  background: transparent;
  transition: background-color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.ticklist-box svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: #fff;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 22;
  stroke-dashoffset: 22;
}
.ticklist-label {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 0.84rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
  /* the strike-through is a background line that grows from the start edge */
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size: 0% 1.5px;
  background-position: 0 56%;
  transition: color 0.4s var(--ease), background-size 0.5s var(--ease) 0.05s;
}
.ticklist-tag {
  flex: none;
  margin-inline-start: auto;
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color 0.4s var(--ease), color 0.4s var(--ease);
}

/* a ticked row: the box fills green and pops, the check draws, the label
   dims and is struck through, the row flashes once */
.is-done .ticklist-box { background: var(--teal); border-color: var(--teal); animation: tick-pop 0.45s var(--ease-spring); }
.is-done .ticklist-box svg { stroke-dashoffset: 0; transition: stroke-dashoffset 0.35s var(--ease) 0.12s; }
.is-done .ticklist-label { color: var(--muted); background-size: 100% 1.5px; }
.is-done .ticklist-tag { background: var(--surface-2); color: var(--muted); }
.ticklist-item.is-done > .ticklist-row { animation: tick-row 1s var(--ease); }
@keyframes tick-pop {
  0% { transform: scale(0.8); }
  55% { transform: scale(1.18); }
  100% { transform: scale(1); }
}
@keyframes tick-row {
  from { background-color: var(--teal-soft); }
  to { background-color: transparent; }
}

/* delivered: a green closing row with a pulsing dot */
.ticklist-foot > .ticklist-row {
  gap: 8px;
  padding: 12px 18px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 0.8rem;
  font-weight: 600;
}
.ticklist-foot i { font-size: 1rem; line-height: 1; }
.ticklist-foot-dot {
  flex: none;
  margin-inline-start: auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal-2);
  animation: tick-pulse 1.6s ease-out infinite;
}
@keyframes tick-pulse {
  0% { box-shadow: 0 0 0 0 rgba(47, 176, 124, 0.55); }
  100% { box-shadow: 0 0 0 10px rgba(47, 176, 124, 0); }
}

/* the list fades out, is cleared without transitions (.no-anim), fades back in */
.ticklist-items,
.ticklist-foot { transition: opacity 0.35s var(--ease), grid-template-rows 0.6s var(--ease), border-color 0.4s var(--ease); }
.ticklist.is-resetting .ticklist-items,
.ticklist.is-resetting .ticklist-foot { opacity: 0; }
.ticklist.no-anim,
.ticklist.no-anim * { transition: none !important; animation: none !important; }

body.is-rtl .ticklist-bar span { transform-origin: 100% 50%; }
body.is-rtl .ticklist-label { background-position: 100% 56%; }
body.is-rtl .ticklist-title,
body.is-rtl .ticklist-label,
body.is-rtl .ticklist-kicker,
body.is-rtl .ticklist-tag,
body.is-rtl .ticklist-foot { font-family: var(--font-ar); letter-spacing: 0; }
@media (prefers-reduced-motion: reduce) {
  .ticklist-foot-dot, .is-done .ticklist-box, .ticklist-item.is-done > .ticklist-row { animation: none; }
}

/* -------------------------------------------------------------------------
   28. Ribbon backdrop (templates/partials/hero_ribbon.html), shared by the
   home page and the Solutions hub: column guides and a navy-grey ribbon
   with a halftone dot screen and a green dotted crest, the node network of
   main.js drawn over it, the live WebGL version in static/js/hero-ribbon.js.
   Moved here from hero-home.css (2026-10-31) so /solutions/ carries the same
   backdrop; the home-only sizing stays in hero-home.css.
   ------------------------------------------------------------------------- */
.hero-ribbon { z-index: -1; }

/* the pane holds the art and both canvases (hero_ribbon.html): one viewport
   tall, it sticks to the top of the screen while the section scrolls past, so
   the shader and the node network only ever cover what is on screen. Both
   scripts lay their scene out over the whole host and shift the window by the
   pane's offset each frame, so nothing looks different: a phone just no longer
   gets a 585 x 5364 px canvas for the expertises chapter. Sticky needs
   overflow: clip (never hidden) on every ancestor up to the page. */
.ribbon-pane {
  position: sticky;
  top: 0;
  height: 100vh;
  height: min(100svh, 100%);
}

/* four hairlines: the container edges and its two thirds */
.ribbon-guides {
  position: absolute;
  inset: 0;
  left: 50%;
  translate: -50% 0;
  border-inline: 1px solid rgba(11, 29, 51, 0.06);
  -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}
.ribbon-guides span {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: rgba(11, 29, 51, 0.05);
}
.ribbon-guides span:nth-child(1) { inset-inline-start: 33.333%; }
.ribbon-guides span:nth-child(2) { inset-inline-start: 66.666%; }
@media (max-width: 639px) { .ribbon-guides span { display: none; } }

.ribbon-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.ribbon-dots { opacity: 0.22; }
.ribbon-edge {
  fill: none;
  stroke: #0f7a52;
  stroke-width: 3.2;
  stroke-linecap: round;
  stroke-dasharray: 0 2.4;
  opacity: 0.85;
}

/* slow breathing of the ribbon and marching dots along its crest */
@media (prefers-reduced-motion: no-preference) {
  .ribbon-drift {
    transform-box: view-box;
    transform-origin: 100% 0%;
    animation: ribbon-drift 22s ease-in-out infinite alternate;
  }
  .ribbon-edge { animation: ribbon-march 6s linear infinite; }
}
@keyframes ribbon-drift {
  from { transform: translate(0, 0) rotate(0deg) scale(1); }
  to { transform: translate(-36px, 18px) rotate(-2.5deg) scale(1.04); }
}
@keyframes ribbon-march { to { stroke-dashoffset: -24; } }

/* the host melts into what follows */
.ribbon-fade {
  position: absolute;
  inset: auto 0 0;
  height: 140px;
  background: linear-gradient(180deg, rgba(247, 249, 250, 0), #f7f9fa);
}

/* the live shader (static/js/hero-ribbon.js) replaces the SVG once it runs */
.ribbon-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-ribbon.is-live .ribbon-art { display: none; }

/* the node network over the ribbon */
.hero-ribbon .hero-canvas { opacity: 0.6; }

/* RTL: the ribbon comes in from the other corner */
body.is-rtl .ribbon-art,
body.is-rtl .ribbon-canvas { scale: -1 1; }

/* the Solutions hub on the ribbon (pages/hubs.py, backdrop "ribbon"): the hero
   and the card grid share the home ground; the navy stars and links, green
   where the pointer reaches in, as on the home hero (colours read by initNetwork) */
.page-hero--ribbon,
.hub-items--ribbon {
  background: #f7f9fa;
  --net-link: 11, 29, 51;
  --net-pointer: 15, 122, 82;
  --net-node: 11, 29, 51;
  --net-spark: 15, 122, 82;
}
.hub-items--ribbon {
  position: relative;
  isolation: isolate;
  overflow: clip;
  color: var(--ink);
}

/* -------------------------------------------------------------------------
   29. Hub hero visuals: animated panels in place of the framed stock clips
   beside the hub headlines (partials/visual_radial.html on /solutions/,
   partials/visual_aiflow.html on /artificial-intelligence/). A navy card
   with a thin frame, white paper and chips, green only where work is done:
   the beam, the stamps, the checks, the pulses (02-couleurs.md). The AI
   panel turns the card white (see "the AI panel on the light hero" below)
   so it sits in the hero's own palette instead of against it.
   ------------------------------------------------------------------------- */
.visual {
  --sheet-w: 156px;
  --sheet-h: 82px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
  padding: 18px;
  border-radius: var(--radius-lg);
  background: var(--dark);
  color: #fff;
  font-family: var(--font-sans);
  box-shadow:
    0 0 0 1px rgba(11, 29, 51, 0.08),
    0 30px 80px -30px rgba(15, 122, 82, 0.45),
    0 20px 50px -30px rgba(11, 29, 51, 0.5);
  overflow: hidden;
}
/* a faint white grid and the frame, as on the CTA card and the clips */
.visual::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
  background-size: 36px 36px;
  -webkit-mask-image: radial-gradient(ellipse at 50% 30%, #000 30%, transparent 85%);
  mask-image: radial-gradient(ellipse at 50% 30%, #000 30%, transparent 85%);
  pointer-events: none;
}
.visual::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
  pointer-events: none;
}
.visual > * { position: relative; z-index: 1; }
body.is-rtl .visual { font-family: var(--font-ar); letter-spacing: 0; }

.visual-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-dark-2);
}
body.is-rtl .visual-head { letter-spacing: 0; }
.visual-live {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--teal-2);
  animation: visual-pulse 2.2s ease-out infinite;
}
.visual-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.visual-state {
  flex: none;
  margin-inline-start: auto;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.58rem;
  color: #fff;
}
.visual-foot {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: 0.74rem;
  color: var(--on-dark-2);
}
@keyframes visual-pulse {
  0% { box-shadow: 0 0 0 0 rgba(47, 176, 124, 0.55); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(47, 176, 124, 0); }
}

/* the panel beside the headline: floats like the clips did, keeps a slight tilt while it floats */
@media (min-width: 992px) {
  .visual.hero-panel { max-width: 300px; rotate: -2.5deg; transition: rotate 0.7s var(--ease), box-shadow 0.7s var(--ease); }
  .visual.hero-panel:hover { rotate: 0deg; }
  .visual-aiflow.hero-panel, .visual-radial.hero-panel { max-width: 400px; rotate: -2deg; }
  body.is-rtl .visual.hero-panel { rotate: 2.5deg; }
  body.is-rtl .visual-aiflow.hero-panel, body.is-rtl .visual-radial.hero-panel { rotate: 2deg; }
  body.is-rtl .visual.hero-panel:hover { rotate: 0deg; }
  /* a wider media column for the task pipeline and the services dial */
  .page-hero-grid--wide { grid-template-columns: minmax(0, 1fr) 360px; }
}
@media (min-width: 1200px) {
  .page-hero-grid--wide { grid-template-columns: minmax(0, 1fr) 400px; gap: 72px; }
}

/* ---- the dial (Solutions) --------------------------------------------------
   The sectors and functions on a ring (--n nodes, --k the rank of one, the
   track in one arc per group, --split the size of the first). The item at
   hand sits at the top, under the pill: the wheel turns by --pos steps and
   each node turns back by as much, so the icons stay upright. The item
   expands there: its node grows green, the beam lights from the core, the
   services it mobilises spring into the core and the foot. The core's rim
   times the stop (.is-timing, --dwell set by main.js, initRadial). The
   ring can be dragged round (.is-dragging: no easing on the turn); any
   turn by hand pauses the dial (.is-paused): the core flashes the pause
   sign (.is-flash), then the play badge waits for a click on the core,
   the play / pause button (.is-auto: the dial turns by itself at all).
   RTL turns the other way (--dir). Drawn for the light card of the ribbon hero
   (section 31): white nodes, green where the item at hand works. */
.visual-radial {
  --n: 7;
  --split: 3;
  --pos: 0;
  --dir: 1;
  --r: 116px;    /* ring radius */
  --node: 46px;
  --core: 100px; /* core diameter */
  --turn: 1.1s;
  --step: calc(360deg / var(--n));
  --arc-a: rgba(11, 29, 51, 0.34);
  --arc-b: var(--line-2);
}
.visual-radial.is-second { --arc-a: var(--line-2); --arc-b: rgba(11, 29, 51, 0.34); }
body.is-rtl .visual-radial { --dir: -1; }
.rd-scene {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
/* the pill: the name of the item at hand and its card number, a tooltip over the top node */
.rd-tip {
  position: relative;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  max-width: 100%;
  height: 36px;
  padding-inline: 16px 6px;
  border-radius: 999px;
  background: var(--teal);
  color: #fff;
  font-size: 0.84rem;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: 0 12px 28px -10px rgba(15, 122, 82, 0.7), 0 0 0 5px rgba(15, 122, 82, 0.12);
}
.rd-tip::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -5px;
  width: 10px;
  height: 10px;
  translate: -50% 0;
  rotate: 45deg;
  border-radius: 2px;
  background: var(--teal);
}
.rd-tip b { overflow: hidden; text-overflow: ellipsis; font-weight: 600; }
.rd-tip-key {
  flex: none;
  display: grid;
  place-items: center;
  min-width: 26px;
  height: 26px;
  padding-inline: 5px;
  border-radius: 8px;
  background: #fff;
  color: var(--teal-ink);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 500;
}
body.is-rtl .rd-tip-key { font-family: var(--font-ar); }
.rd-tip.is-pop { animation: rd-pop 0.6s var(--ease-spring) 0.2s both; }
/* the ring: a square around the core, sized for the grown top node */
.rd-ring {
  position: relative;
  width: calc(2 * var(--r) + var(--node) * 1.3);
  max-width: 100%;
  aspect-ratio: 1;
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}
.visual-radial.is-dragging .rd-ring { cursor: grabbing; }
.rd-wheel {
  position: absolute;
  inset: 0;
  rotate: calc(var(--pos) * var(--step) * var(--dir) * -1);
  transition: rotate var(--turn) var(--ease);
}
/* the track: one arc per group, the group at hand in navy; mirrored in RTL */
.rd-track {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(2 * var(--r) + 3px);
  aspect-ratio: 1;
  translate: -50% -50%;
  scale: var(--dir) 1;
  border-radius: 50%;
  background: conic-gradient(from calc(var(--step) * -0.5),
    transparent 0 3deg,
    var(--arc-a) 0 calc(var(--split) * var(--step) - 3deg),
    transparent 0 calc(var(--split) * var(--step) + 3deg),
    var(--arc-b) 0 calc(var(--n) * var(--step) - 3deg),
    transparent 0);
  -webkit-mask-image: radial-gradient(closest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
  mask-image: radial-gradient(closest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
}
/* the beam: from the core's edge up to the top node, lit again at every stop */
.rd-beam {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 50%;
  background: conic-gradient(from -21deg, transparent 0deg, rgba(15, 122, 82, 0.42) 6deg 36deg, transparent 42deg);
  -webkit-mask-image: radial-gradient(circle, transparent calc(var(--core) / 2 + 2px), rgba(0, 0, 0, 0.3) calc(var(--core) / 2 + 4px), #000 calc(var(--r) - 8px), transparent calc(var(--r) + 2px));
  mask-image: radial-gradient(circle, transparent calc(var(--core) / 2 + 2px), rgba(0, 0, 0, 0.3) calc(var(--core) / 2 + 4px), #000 calc(var(--r) - 8px), transparent calc(var(--r) + 2px));
}
.rd-beam.is-pop { animation: rd-beam 0.7s var(--ease) 0.3s both; }
/* the nodes, placed with sin/cos; each turns back by the wheel's turn */
.rd-node {
  --a: calc(var(--k) * var(--step) * var(--dir));
  position: absolute;
  left: calc(50% + var(--r) * sin(var(--a)));
  top: calc(50% - var(--r) * cos(var(--a)));
  z-index: 2;
  display: grid;
  place-items: center;
  width: var(--node);
  height: var(--node);
  translate: -50% -50%;
  rotate: calc(var(--pos) * var(--step) * var(--dir));
  border-radius: 13px;
  background: var(--surface);
  border: 1px solid var(--line-2);
  color: var(--ink);
  font-size: 1.15rem;
  cursor: pointer;
  box-shadow: 0 6px 16px -10px rgba(11, 29, 51, 0.35);
  transition: rotate var(--turn) var(--ease), scale 0.5s var(--ease-spring), background-color 0.35s var(--ease), color 0.35s var(--ease), border-color 0.35s var(--ease), box-shadow 0.35s var(--ease);
}
.rd-node:hover { border-color: var(--teal); color: var(--teal-ink); scale: 1.08; }
.rd-node.is-on {
  background: var(--teal);
  border-color: var(--teal);
  color: #fff;
  scale: 1.26;
  box-shadow: 0 14px 28px -10px rgba(15, 122, 82, 0.7), 0 0 0 5px rgba(15, 122, 82, 0.14);
  transition-delay: 0s, 0.35s, 0.35s, 0.35s, 0.35s, 0.35s; /* it grows once it reaches the top */
}
/* while the ring is dragged it follows the pointer: no easing on the turn */
.visual-radial.is-dragging .rd-wheel { transition: none; }
.visual-radial.is-dragging .rd-node,
.visual-radial.is-dragging .rd-node.is-on {
  transition: scale 0.3s var(--ease-spring), background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
/* the core: the services of the item at hand, the rim timing the stop */
.rd-core {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
  gap: 5px;
  width: var(--core);
  height: var(--core);
  padding-inline: 18px;
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 16px 36px -18px rgba(11, 29, 51, 0.45), 0 0 0 8px rgba(15, 122, 82, 0.06);
}
.rd-core::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  border: 2px solid rgba(47, 176, 124, 0.5);
  animation: rd-pulse 2.8s ease-out infinite;
  pointer-events: none;
}
.rd-timer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  rotate: -90deg;
  overflow: visible;
  pointer-events: none;
}
body.is-rtl .rd-timer { scale: 1 -1; }
.rd-timer circle { fill: none; stroke-width: 3.5; }
.rd-timer-track { stroke: var(--line); }
.rd-timer-bar { stroke: var(--teal); stroke-linecap: round; stroke-dasharray: 100; stroke-dashoffset: 0; }
.rd-core.is-timing .rd-timer-bar { animation: rd-timer var(--dwell, 5200ms) linear both; }
.rd-timer-bar { transition: opacity 0.3s var(--ease); }
.visual-radial.is-paused .rd-timer-bar,
.visual-radial.is-paused .rd-core::before { opacity: 0; }
/* the core as the play / pause button: the sign shows on hover, the pause
   sign flashes when the dial stops, the badge says it waits for a click */
.visual-radial.is-auto .rd-core { cursor: pointer; }
.rd-core-glyph {
  position: absolute;
  inset: 10px;
  z-index: 2;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--teal);
  color: #fff;
  font-size: 2.1rem;
  opacity: 0;
  scale: 0.4;
  rotate: -90deg;
  box-shadow: 0 10px 24px -10px rgba(15, 122, 82, 0.7);
  transition: opacity 0.3s var(--ease), scale 0.5s var(--ease-spring), rotate 0.5s var(--ease);
  pointer-events: none;
}
.rd-core-play i { translate: 2px 0; } /* the triangle's optical centre (media signs are not mirrored in RTL) */
.rd-core.is-flash .rd-core-pause,
.visual-radial.is-dragging .rd-core-pause,
.visual-radial.is-auto:not(.is-paused) .rd-core:hover .rd-core-pause,
.visual-radial.is-paused .rd-core:not(.is-flash):hover .rd-core-play { opacity: 1; scale: 1; rotate: 0deg; }
.rd-core-badge {
  position: absolute;
  left: 50%;
  bottom: -12px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  translate: -50% 0;
  border-radius: 50%;
  background: var(--teal);
  border: 2px solid var(--surface);
  color: #fff;
  font-size: 0.8rem;
  opacity: 0;
  scale: 0.4;
  transition: opacity 0.3s var(--ease), scale 0.45s var(--ease-spring);
}
.rd-core-badge i { translate: 1px 0; }
.visual-radial.is-paused:not(.is-dragging) .rd-core:not(.is-flash) .rd-core-badge { opacity: 1; scale: 1; animation: rd-badge 2s ease-out infinite; }
.visual-radial.is-paused .rd-core:hover .rd-core-badge { opacity: 0; scale: 0.4; }
.rd-core-svc {
  position: relative;
  display: none;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 0.86rem;
}
.rd-core-svc.is-on { display: grid; animation: rd-spring 0.55s var(--ease-spring) both; animation-delay: calc(0.45s + var(--j, 0) * 0.12s); }
/* the foot: the item's lead, then the services it mobilises as chips */
.rd-foot { flex-direction: column; align-items: stretch; gap: 8px; }
.rd-lead {
  display: -webkit-box;
  height: 2.9em;
  margin: 0;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-size: 0.76rem;
  line-height: 1.45;
  color: var(--ink-2);
}
.rd-lead.is-pop { animation: rd-rise 0.5s var(--ease) 0.3s both; }
.rd-foot-label {
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}
body.is-rtl .rd-foot-label { letter-spacing: 0; }
.rd-chips { display: flex; flex-wrap: wrap; align-content: flex-start; gap: 6px; height: 86px; overflow: hidden; }
.rd-chip {
  display: none;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  height: 24px;
  padding-inline: 9px;
  border-radius: 999px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 0.68rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rd-chip i { flex: none; font-size: 0.75rem; }
.rd-chip.is-on { display: inline-flex; animation: rd-rise 0.45s var(--ease) both; animation-delay: calc(0.5s + var(--j, 0) * 0.1s); }

@keyframes rd-pop {
  0% { scale: 0.86; }
  60% { scale: 1.06; }
  100% { scale: 1; }
}
@keyframes rd-beam {
  from { opacity: 0; scale: 0.88; }
  to { opacity: 1; scale: 1; }
}
@keyframes rd-spring {
  from { opacity: 0; scale: 0.3; }
  to { opacity: 1; scale: 1; }
}
@keyframes rd-rise {
  from { opacity: 0; translate: 0 6px; }
  to { opacity: 1; translate: 0 0; }
}
@keyframes rd-pulse {
  0% { opacity: 0.9; scale: 1; }
  100% { opacity: 0; scale: 1.45; }
}
@keyframes rd-badge {
  0% { box-shadow: 0 0 0 0 rgba(15, 122, 82, 0.45); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(15, 122, 82, 0); }
}
@keyframes rd-timer {
  from { stroke-dashoffset: 100; }
  to { stroke-dashoffset: 0; }
}

/* ---- AI workflow (Artificial intelligence) ----------------------------------
   Three columns: input chips, the core, output chips, wired through two
   vertical buses. main.js (initAiFlow) toggles the classes: .is-on on a row
   runs the pulse down its wire and lights the chip, .is-on on a bus and
   .is-busy / .is-done on the core light the middle, .is-done on an output
   row gives it the green check. */
.visual-aiflow { min-height: 460px; }
.af-board {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 62px minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  flex: 1;
  min-height: 0;
}
.af-col-label {
  margin: 0 0 10px;
  font-family: var(--font-mono);
  font-size: 0.56rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-dark-muted);
}
.af-col-label-core { text-align: center; }
.af-col-label-out { text-align: end; }
body.is-rtl .af-col-label { font-family: var(--font-ar); letter-spacing: 0; font-size: 0.62rem; }
.af-rows {
  display: grid;
  grid-auto-rows: 1fr;
  gap: 10px;
  min-width: 0;
}
.af-row {
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(14px, 1fr);
  align-items: center;
  min-width: 0;
}
.af-rows-out .af-row { grid-template-columns: minmax(14px, 1fr) minmax(0, auto); }
.af-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  max-width: 100%;
  padding: 6px 9px 6px 6px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.66rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--on-dark-2);
  text-align: start;
  transition: background 0.35s ease, border-color 0.35s ease, color 0.35s ease, box-shadow 0.35s ease, translate 0.5s var(--ease);
}
body.is-rtl .af-chip { padding: 6px 6px 6px 9px; }
/* two lines at most, so the longest labels still read whole */
.af-chip > span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.af-chip i {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 0.78rem;
  transition: background 0.35s ease, border-color 0.35s ease, color 0.35s ease;
}
.af-row.is-on .af-chip {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(47, 176, 124, 0.6);
  color: #fff;
  box-shadow: 0 0 24px -6px rgba(47, 176, 124, 0.6);
  translate: 2px 0;
}
body.is-rtl .af-row.is-on .af-chip { translate: -2px 0; }
.af-rows-out .af-row.is-on .af-chip { translate: -2px 0; }
body.is-rtl .af-rows-out .af-row.is-on .af-chip { translate: 2px 0; }
/* outputs wait with a hollow ring, then take the green check */
.af-chip-out { padding: 6px 6px 6px 9px; opacity: 0.6; }
body.is-rtl .af-chip-out { padding: 6px 9px 6px 6px; }
.af-chip-out i { order: 1; border-radius: 50%; background: transparent; border: 1.5px solid rgba(255, 255, 255, 0.3); color: transparent; }
.af-row.is-done .af-chip-out { opacity: 1; color: #fff; border-color: rgba(47, 176, 124, 0.45); }
.af-row.is-done .af-chip-out i { background: var(--teal-2); border-color: var(--teal-2); color: #fff; animation: af-pop 0.55s var(--ease-spring); }
.af-wire {
  position: relative;
  height: 2px;
  background: rgba(255, 255, 255, 0.12);
  transition: background 0.4s ease;
}
.af-row.is-on .af-wire { background: rgba(47, 176, 124, 0.35); }
.af-dot {
  position: absolute;
  top: 50%;
  left: 0;
  width: 8px;
  height: 8px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--teal-2);
  box-shadow: 0 0 12px 3px rgba(47, 176, 124, 0.55);
  opacity: 0;
}
body.is-rtl .af-dot { left: auto; right: 0; }
.af-row.is-on .af-dot { animation: af-run 0.6s var(--ease-soft) forwards; }
body.is-rtl .af-row.is-on .af-dot { animation-name: af-run-rtl; }
/* the core and its buses */
.af-core-col {
  position: relative;
  display: grid;
  place-items: center;
}
.af-bus {
  position: absolute;
  top: 17px;
  bottom: 17px;
  width: 2px;
  background: rgba(255, 255, 255, 0.12);
  transition: background 0.35s ease, box-shadow 0.35s ease;
}
.af-bus-in { inset-inline-start: 0; }
.af-bus-out { inset-inline-end: 0; }
.af-bus.is-on { background: var(--teal-2); box-shadow: 0 0 12px rgba(47, 176, 124, 0.6); }
.af-core {
  position: relative;
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--dark-2);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 0 0 0 7px rgba(255, 255, 255, 0.04), 0 18px 30px -16px rgba(0, 0, 0, 0.8);
  transition: background 0.4s ease, box-shadow 0.5s ease, border-color 0.4s ease;
}
.af-core-ring {
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 68%, var(--teal-2) 88%, transparent 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  opacity: 0.7;
  animation: spin 7s linear infinite;
  transition: opacity 0.4s ease;
}
.af-core-icon { font-size: 1.25rem; color: #fff; transition: transform 0.4s var(--ease-spring), color 0.3s ease; }
.af-core.is-busy { box-shadow: 0 0 0 7px rgba(47, 176, 124, 0.12), 0 0 40px -6px rgba(47, 176, 124, 0.7); border-color: rgba(47, 176, 124, 0.6); }
.af-core.is-busy .af-core-ring { opacity: 1; animation-duration: 1.1s; }
.af-core.is-busy .af-core-icon { animation: af-think 1.1s ease-in-out infinite; }
.af-core.is-done { background: var(--teal); border-color: var(--teal-2); box-shadow: 0 0 0 7px rgba(47, 176, 124, 0.18), 0 0 50px -4px rgba(47, 176, 124, 0.8); }
.af-core.is-done .af-core-icon { transform: scale(1.15); }
/* the foot: progress bar, the action under way, tasks done */
.af-foot { flex-direction: column; align-items: stretch; gap: 8px; }
.af-bar {
  display: block;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.1);
  overflow: hidden;
}
.af-bar span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--teal-2);
  transition: width 0.6s var(--ease);
}
.af-foot-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 0.72rem; }
.af-action { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--on-dark-2); }
.af-counter { flex: none; font-variant-numeric: tabular-nums; color: var(--on-dark-muted); }
.af-counter b { font-family: var(--font-display); font-size: 0.95rem; font-weight: 700; color: #fff; }
body.is-rtl .af-counter b { font-family: var(--font-ar); }

/* ---- the AI panel on the light hero ---------------------------------------
   /artificial-intelligence/ keeps the hero's own palette (02-couleurs.md):
   a white card on the page background like the services ticklist, navy ink,
   a navy core, and green only for the work done (pulses, checks, the bar).
   Like the Solutions panel (section 31) the card itself is 40 % white so the
   hero's clip and node network show through; chips and core stay solid. */
.visual-aiflow {
  background: rgba(255, 255, 255, 0.4); /* 40 %, as .page-hero--ribbon .visual and the ticklist (was var(--surface)) */
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 30px 60px -32px rgba(11, 29, 51, 0.38),
    0 12px 30px -18px rgba(11, 29, 51, 0.18);
}
.visual-aiflow::before {
  background-image:
    linear-gradient(rgba(11, 29, 51, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 29, 51, 0.05) 1px, transparent 1px);
}
.visual-aiflow::after { border-color: transparent; box-shadow: none; }
.visual-aiflow .visual-head { color: var(--muted); }
.visual-aiflow .visual-live { background: var(--teal); animation-name: visual-pulse-teal; }
.visual-aiflow .visual-state { background: var(--bg); border-color: var(--line); color: var(--ink-2); }
.visual-aiflow .visual-foot { color: var(--muted); }
.visual-aiflow .af-col-label { color: var(--muted); }
.visual-aiflow .af-chip {
  background: var(--bg);
  border-color: var(--line);
  color: var(--ink-2);
}
.visual-aiflow .af-chip i { background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); color: var(--ink); }
/* the input at work: navy tile, a soft green ring, a navy shadow instead of a glow */
.visual-aiflow .af-row.is-on .af-chip {
  background: var(--surface);
  border-color: rgba(15, 122, 82, 0.45);
  color: var(--ink);
  box-shadow: 0 0 0 3px var(--teal-soft), 0 12px 24px -14px rgba(11, 29, 51, 0.35);
}
.visual-aiflow .af-row.is-on .af-chip i { background: var(--ink); box-shadow: none; color: #fff; }
.visual-aiflow .af-chip-out i { background: transparent; box-shadow: none; border-color: var(--line-2); color: transparent; }
.visual-aiflow .af-row.is-done .af-chip-out { background: var(--surface); border-color: rgba(15, 122, 82, 0.35); color: var(--ink); }
.visual-aiflow .af-row.is-done .af-chip-out i { background: var(--teal); border-color: var(--teal); color: #fff; }
.visual-aiflow .af-wire { background: var(--line-2); }
.visual-aiflow .af-row.is-on .af-wire { background: rgba(15, 122, 82, 0.35); }
.visual-aiflow .af-dot { background: var(--teal); box-shadow: 0 0 10px 2px rgba(15, 122, 82, 0.3); }
.visual-aiflow .af-bus { background: var(--line-2); }
.visual-aiflow .af-bus.is-on { background: var(--teal); box-shadow: 0 0 10px rgba(15, 122, 82, 0.3); }
.visual-aiflow .af-core {
  background: var(--ink);
  border-color: var(--ink);
  box-shadow: 0 0 0 6px var(--bg), 0 14px 28px -14px rgba(11, 29, 51, 0.55);
}
.visual-aiflow .af-core-ring { background: conic-gradient(from 0deg, transparent 0 68%, var(--teal) 88%, transparent 100%); }
.visual-aiflow .af-core.is-busy { border-color: var(--teal); box-shadow: 0 0 0 6px var(--teal-soft), 0 14px 28px -14px rgba(11, 29, 51, 0.55); }
.visual-aiflow .af-core.is-done { background: var(--teal); border-color: var(--teal); box-shadow: 0 0 0 6px var(--teal-soft), 0 14px 30px -12px rgba(15, 122, 82, 0.45); }
.visual-aiflow .af-bar { background: var(--surface-2); }
.visual-aiflow .af-bar span { background: var(--teal); }
.visual-aiflow .af-action { color: var(--ink-2); }
.visual-aiflow .af-counter { color: var(--muted); }
.visual-aiflow .af-counter b { color: var(--ink); }
@keyframes visual-pulse-teal {
  0% { box-shadow: 0 0 0 0 rgba(15, 122, 82, 0.4); }
  70%, 100% { box-shadow: 0 0 0 9px rgba(15, 122, 82, 0); }
}

@keyframes af-run {
  0% { opacity: 0; left: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { opacity: 0; left: calc(100% - 8px); }
}
@keyframes af-run-rtl {
  0% { opacity: 0; right: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { opacity: 0; right: calc(100% - 8px); }
}
@keyframes af-pop {
  0% { scale: 0.4; }
  60% { scale: 1.25; }
  100% { scale: 1; }
}
@keyframes af-think {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(0.88); }
}

/* -------------------------------------------------------------------------
   30. Hub groups (pages/hubs.py, `groups`): the Solutions items read in two
   groups, the industries then the business functions, under a small label in
   the dropdown, in the hero's jump links and over each card grid.
   ------------------------------------------------------------------------- */
.nav-sub-group {
  margin: 8px 8px 3px;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--dd-muted, var(--muted));
}
/* stacked groups (narrow screens) keep some air between them; side by side (5c) their labels stay level */
@media (max-width: 959.98px) { .nav-sub-col + .nav-sub-col .nav-sub-group { margin-top: 12px; } }
body.is-rtl .nav-sub-group { font-family: var(--font-ar); letter-spacing: 0; font-size: 0.72rem; }

.solution-jump-label {
  flex-basis: 100%;
  margin: 6px 0 0;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.solution-jump-label:first-child { margin-top: 0; }
body.is-rtl .solution-jump-label { font-family: var(--font-ar); letter-spacing: 0; font-size: 0.78rem; }

/* the group heads of the page are the chapter side columns of section 21b (2026-11-03) */

/* -------------------------------------------------------------------------
   31. Light hub visual: on the ribbon backdrop (/solutions/) the panel beside
   the headline is a white card, like the ticklist of the services hero and
   the AI board (section 29): white surface, hairline border, the
   navy-tinted shadow of the charte's cards, navy ink; the green stays on
   the live dot and on the lit parts of the dial (02-couleurs.md: white
   carries, green marks).
   ------------------------------------------------------------------------- */
.page-hero--ribbon .visual {
  background: rgba(255, 255, 255, 0.4); /* 40 %: the ribbon shows through, as the AI panel and the ticklist (was var(--surface)) */
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 30px 60px -32px rgba(11, 29, 51, 0.38),
    0 12px 30px -18px rgba(11, 29, 51, 0.18);
}
.page-hero--ribbon .visual::before {
  background-image:
    linear-gradient(rgba(11, 29, 51, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 29, 51, 0.05) 1px, transparent 1px);
}
.page-hero--ribbon .visual::after { border-color: transparent; box-shadow: none; }
.page-hero--ribbon .visual-head { color: var(--muted); }
.page-hero--ribbon .visual-state {
  background: var(--surface-2);
  border-color: transparent;
  color: var(--ink-2);
}
.page-hero--ribbon .visual-foot { color: var(--muted); }
/* the services dial (section 29) is drawn for this light card directly */

/* -------------------------------------------------------------------------
   32. No stock footage left on the hub stage, the services hero and the
   about hero (2026-10-31). The hub stage (partials/hub_stage.html) sits on
   the ribbon like the page behind it: the ribbon's own fade melts into the
   window's ground and the accent tint is lighter, so the band shows through
   behind the services column. The about hero reuses the home hero's centre
   piece (hero-home.css, loaded by pages/about.html): the navy brand card
   with the three values as chips around it, wired to the card by the node
   network (main.js, initNetwork); only their places are set here.
   ------------------------------------------------------------------------- */
.hub-stage .stage-backdrop .ribbon-fade { background: linear-gradient(180deg, rgba(243, 245, 248, 0), var(--bg)); }
.hub-stage .stage-tint {
  background:
    radial-gradient(55% 60% at 82% 12%, color-mix(in srgb, var(--stage-accent) 8%, transparent), transparent 70%),
    linear-gradient(105deg, color-mix(in srgb, var(--bg) 72%, transparent) 0%, color-mix(in srgb, var(--bg) 34%, transparent) 55%, transparent 100%);
}
.hub-stage .stage-backdrop .hero-canvas { opacity: 0.45; }

/* the about visual: one chip at the top start, one at the end middle, one at
   the bottom start, clear of the card; floating out of phase like the sector chips */
.hero-visual--about { margin-inline: auto; }
.layer-v1 { top: 6%; inset-inline-start: -6%; }
.layer-v2 { top: 50%; inset-inline-end: -12%; margin-top: -22px; }
.layer-v3 { bottom: 6%; inset-inline-start: 2%; }
.card-v2 { animation-delay: -2.5s; }
.card-v3 { animation-delay: -4s; }

/* -------------------------------------------------------------------------
   33. Story plates: the schema of a service drawn on the navy plate of its
   panel on /services/ (partials/story_schema.html, content in
   services/schemas.py) where the stock clip used to play. Four facets as
   tiles, arranged as a flow (a wire runs under them, a pulse along it), a
   hub (the service icon at the centre, buses and wires out to the corners)
   or a stack (layers, a beam sweeping them beside a monitor). The panel's
   accent lights the facet at work; a faint grid and the ghost of the icon
   drift with --drift (main.js) for the depth the clip gave. The plate of
   the current panel runs (.is-current, main.js), one facet per quarter of
   --T; the others rest. Without JavaScript or under reduced motion every
   facet shows lit: the finished schema.
   ------------------------------------------------------------------------- */
.story-plate {
  --T: 6.4s;
  --lit: var(--accent, var(--teal-2));
  --lit-soft: color-mix(in srgb, var(--lit) 55%, transparent);
  --lit-glow: 0 0 34px -8px color-mix(in srgb, var(--lit) 70%, transparent);
  --lit-fill: color-mix(in srgb, var(--lit) 9%, var(--dark-2));
}
.story-scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 18px 22px 22px;
  color: #fff;
  font-family: var(--font-sans);
}
body.is-rtl .story-scene { font-family: var(--font-ar); }
/* the layers behind the board: the grid and the ghost, drifting against the rail */
.story-scene-grid {
  position: absolute;
  inset: -40px -140px;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 36px 36px;
  -webkit-mask-image: radial-gradient(ellipse at 50% 35%, #000 25%, transparent 80%);
  mask-image: radial-gradient(ellipse at 50% 35%, #000 25%, transparent 80%);
  transform: translate3d(calc(var(--drift) * 1px), 0, 0);
  will-change: transform;
  pointer-events: none;
}
.story-scene-ghost {
  position: absolute;
  inset-inline-end: -2%;
  bottom: -16%;
  font-size: clamp(150px, 26vw, 300px);
  line-height: 1;
  color: #fff;
  opacity: 0.05;
  transform: translate3d(calc(var(--drift) * 0.45px), 0, 0);
  will-change: transform;
  pointer-events: none;
}
.story-scene-head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-dark-2);
}
body.is-rtl .story-scene-head { letter-spacing: 0; }
.story-scene-square { flex: none; width: 8px; height: 8px; background: var(--teal-2); }
.story-scene-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.story-scene-kind {
  flex: none;
  margin-inline-start: auto;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.7rem;
  color: #fff;
}
/* the board keeps clear of the caption chip along the bottom */
.story-scene-board {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: grid;
  align-content: center;
  margin-bottom: 64px;
}
.story-tiles { display: grid; margin: 0; padding: 0; list-style: none; }
.story-item { display: flex; align-items: center; min-width: 0; }
.story-tile {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  min-width: 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: var(--dark-2);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.story-tile-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 1rem;
}
.story-tile-text { display: grid; gap: 2px; min-width: 0; }
.story-tile-text strong { font-size: 0.9rem; font-weight: 600; line-height: 1.25; color: #fff; }
.story-tile-text span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.84rem;
  font-weight: 450; /* light on navy reads thin at 400 */
  line-height: 1.4;
  color: var(--on-dark-2);
}
.story-tile-num {
  position: absolute;
  top: 10px;
  inset-inline-end: 12px;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  color: var(--on-dark-muted);
}
/* wires and the pulse that runs along them */
.story-wire { position: relative; flex: 1; height: 2px; background: rgba(255, 255, 255, 0.12); }
.story-wire-dot {
  position: absolute;
  top: 50%;
  inset-inline-start: 0;
  width: 10px;
  height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--lit);
  box-shadow: 0 0 14px 3px color-mix(in srgb, var(--lit) 55%, transparent);
  opacity: 0;
}

/* flow: four steps in a row, numbered, on one wire */
.story-flow { position: relative; }
.story-flow-wire { position: absolute; top: 50%; inset-inline: 8%; margin-top: -1px; }
.story-flow .story-tiles { position: relative; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; }
.story-flow .story-tile { flex-direction: column; gap: 14px; padding: 18px 16px; }
.story-flow .story-tile-icon { width: 40px; height: 40px; border-radius: 11px; font-size: 1.1rem; }

/* hub: the service icon at the centre, two facets a side wired to the buses
   standing --hub-in inside the middle column (the items reach over by as much) */
.story-hub { position: relative; --hub-mid: 176px; --hub-in: 40px; }
.story-hub .story-tiles {
  grid-template-columns: minmax(0, 1fr) var(--hub-mid) minmax(0, 1fr);
  row-gap: 22px;
  align-items: center;
}
.story-hub .story-tile { max-width: 330px; }
.story-hub .story-item:nth-child(1) { grid-area: 1 / 1; }
.story-hub .story-item:nth-child(2) { grid-area: 2 / 1; }
.story-hub .story-item:nth-child(3) { grid-area: 1 / 3; }
.story-hub .story-item:nth-child(4) { grid-area: 2 / 3; }
.story-hub .story-item:nth-child(-n+2) { margin-inline-end: calc(-1 * var(--hub-in)); }
.story-hub .story-item:nth-child(n+3) { flex-direction: row-reverse; margin-inline-start: calc(-1 * var(--hub-in)); }
.story-hub-bus {
  position: absolute;
  top: 25%;
  bottom: 25%;
  width: 2px;
  background: rgba(255, 255, 255, 0.12);
}
.story-hub-bus-a { inset-inline-start: calc(50% - var(--hub-mid) / 2 + var(--hub-in)); }
.story-hub-bus-b { inset-inline-end: calc(50% - var(--hub-mid) / 2 + var(--hub-in)); }
.story-hub-core {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--dark-2);
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.04), 0 18px 30px -16px rgba(0, 0, 0, 0.8);
  font-size: 1.7rem;
  color: #fff;
}
.story-hub-ring {
  position: absolute;
  inset: -7px;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 68%, var(--lit) 88%, transparent 100%);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 1px));
  opacity: 0.7;
}

/* stack: the layers one above the other, a beam sweeping them beside the monitor */
.story-stack { display: grid; grid-template-columns: minmax(0, 1fr) 120px; column-gap: 24px; align-items: stretch; }
.story-stack .story-tiles { gap: 6px; align-content: center; }
.story-stack .story-tile { align-items: center; padding: 8px 12px; border-radius: 12px; }
.story-stack .story-tile-icon { width: 32px; height: 32px; font-size: 0.95rem; }
.story-stack .story-tile-text { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 10px; }
.story-stack .story-tile-text span { -webkit-line-clamp: 1; }
.story-tile-led {
  flex: none;
  margin-inline-start: auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, 0.3);
}
.story-stack-monitor { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.story-stack-monitor-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--on-dark-muted);
}
body.is-rtl .story-stack-monitor-label { font-family: var(--font-ar); letter-spacing: 0; font-size: 0.76rem; }
.story-stack-rail { position: relative; flex: 1; width: 2px; background: rgba(255, 255, 255, 0.12); }
.story-stack-beam {
  position: absolute;
  top: 0;
  left: 50%;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  border-radius: 50%;
  background: var(--lit);
  box-shadow: 0 0 14px 3px color-mix(in srgb, var(--lit) 55%, transparent);
  opacity: 0;
}

/* every facet lit: the finished schema, the still frame without JavaScript
   or under reduced motion */
html:not(.js) .story-tile { border-color: var(--lit-soft); background: var(--lit-fill); box-shadow: var(--lit-glow); }
html:not(.js) .story-tile-icon { background: var(--lit); }
html:not(.js) .story-tile-led { background: var(--lit); border-color: var(--lit); }
@media (prefers-reduced-motion: reduce) {
  .story-tile { border-color: var(--lit-soft); background: var(--lit-fill); box-shadow: var(--lit-glow); }
  .story-tile-icon { background: var(--lit); }
  .story-tile-led { background: var(--lit); border-color: var(--lit); }
}

/* the current panel runs: one facet per quarter of the period, the pulses,
   the beam and the core keeping time with it */
@media (prefers-reduced-motion: no-preference) {
  .js .story-panel.is-current .story-tile,
  .js .story-panel.is-current .story-tile-icon,
  .js .story-panel.is-current .story-tile-led {
    animation-duration: var(--T);
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    animation-delay: calc(var(--i) * var(--T) / 4);
  }
  .js .story-panel.is-current .story-tile { animation-name: story-lit; }
  .js .story-panel.is-current .story-tile-icon { animation-name: story-lit-icon; }
  .js .story-panel.is-current .story-tile-led { animation-name: story-lit-led; }
  .js .story-panel.is-current .story-flow .story-wire-dot { animation: story-run var(--T) linear infinite; }
  .js .story-panel.is-current .story-hub .story-wire-dot {
    animation: story-pulse var(--T) linear infinite;
    animation-delay: calc(var(--i) * var(--T) / 4);
  }
  .js .story-panel.is-current .story-hub .story-item:nth-child(n+3) .story-wire-dot { animation-name: story-pulse-back; }
  .js .story-panel.is-current .story-hub-ring { animation: spin 7s linear infinite; }
  .js .story-panel.is-current .story-hub-core { animation: story-core var(--T) linear infinite; }
  .js .story-panel.is-current .story-stack-beam { animation: story-beam var(--T) linear infinite; }
}
@keyframes story-lit {
  0%, 22% { border-color: var(--lit-soft); background-color: var(--lit-fill); box-shadow: var(--lit-glow); }
  27%, 100% { border-color: rgba(255, 255, 255, 0.12); background-color: var(--dark-2); box-shadow: 0 0 34px -8px transparent; }
}
@keyframes story-lit-icon {
  0%, 22% { background-color: var(--lit); }
  27%, 100% { background-color: rgba(255, 255, 255, 0.1); }
}
@keyframes story-lit-led {
  0%, 22% { background-color: var(--lit); border-color: var(--lit); box-shadow: 0 0 10px 2px color-mix(in srgb, var(--lit) 55%, transparent); }
  27%, 100% { background-color: transparent; border-color: rgba(255, 255, 255, 0.3); box-shadow: 0 0 10px 2px transparent; }
}
@keyframes story-run {
  0% { inset-inline-start: 0; opacity: 0; }
  2%, 97% { opacity: 1; }
  100% { inset-inline-start: calc(100% - 10px); opacity: 0; }
}
@keyframes story-pulse {
  0% { inset-inline-start: 0; opacity: 0; }
  1%, 9% { opacity: 1; }
  10%, 100% { inset-inline-start: calc(100% - 10px); opacity: 0; }
}
@keyframes story-pulse-back {
  0% { inset-inline-start: calc(100% - 10px); opacity: 0; }
  1%, 9% { opacity: 1; }
  10%, 100% { inset-inline-start: 0; opacity: 0; }
}
@keyframes story-core {
  0%, 20%, 25%, 45%, 50%, 70%, 75%, 95%, 100% { border-color: rgba(255, 255, 255, 0.16); box-shadow: 0 0 0 8px rgba(255, 255, 255, 0.04), 0 18px 30px -16px rgba(0, 0, 0, 0.8); }
  10%, 35%, 60%, 85% { border-color: var(--lit-soft); box-shadow: 0 0 0 8px color-mix(in srgb, var(--lit) 14%, transparent), 0 0 44px -6px color-mix(in srgb, var(--lit) 75%, transparent); }
}
@keyframes story-beam {
  0% { top: 0; opacity: 0; }
  2%, 97% { opacity: 1; }
  100% { top: calc(100% - 10px); opacity: 0; }
}

/* narrower desktops: the rail panels are 78vw, the plates 770-940px wide */
@media (min-width: 992px) and (max-width: 1199.98px) {
  .story-scene { padding: 16px 18px 18px; gap: 12px; }
  .story-tile-text strong { font-size: 0.88rem; }
  .story-tile-text span { font-size: 0.8rem; }
  .story-flow .story-tiles { gap: 16px; }
  .story-hub { --hub-mid: 140px; --hub-in: 32px; }
  .story-hub-core { width: 68px; height: 68px; font-size: 1.4rem; }
  .story-stack { grid-template-columns: minmax(0, 1fr) 90px; column-gap: 16px; }
}
/* the deck cards of phones and tablets: smaller plates, tighter tiles */
@media (max-width: 991.98px) {
  .story-scene { padding: 14px 16px 16px; gap: 10px; }
  .story-scene-board { margin-bottom: 56px; }
  .story-tile { gap: 10px; padding: 10px 12px; border-radius: 12px; }
  .story-tile-icon { width: 30px; height: 30px; border-radius: 8px; font-size: 0.9rem; }
  .story-tile-text strong { font-size: 0.86rem; }
  .story-tile-text span { font-size: 0.78rem; }
  .story-flow-wire { display: none; }
  .story-flow .story-tiles { grid-template-columns: 1fr 1fr; gap: 10px; }
  .story-flow .story-tile { flex-direction: row; align-items: center; gap: 10px; padding: 10px 12px; }
  .story-flow .story-tile-icon { width: 30px; height: 30px; border-radius: 8px; font-size: 0.9rem; }
  .story-tile-num { display: none; }
  .story-hub { --hub-mid: 96px; --hub-in: 24px; }
  .story-hub .story-tiles { row-gap: 12px; }
  .story-hub-core { width: 56px; height: 56px; font-size: 1.2rem; box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.04); }
  .story-hub-ring { inset: -5px; }
  .story-stack { grid-template-columns: minmax(0, 1fr) 64px; column-gap: 12px; }
  .story-stack .story-tile { padding: 7px 10px; }
  .story-stack .story-tile-icon { width: 28px; height: 28px; }
}
/* phones: a square plate, the facets as a plain two-by-two or four rows,
   titles only; the hub loses its core, the stack its monitor */
@media (max-width: 639.98px) {
  .story-plate { aspect-ratio: 1 / 1; }
  .story-scene { padding: 12px; }
  .story-scene-head { font-size: 0.7rem; }
  /* the two-by-two tiles are as wide as their longest word allows (section 38) */
  .story-tile-text strong { font-size: 0.8rem; }
  .story-scene-kind { display: none; }
  .story-scene-ghost { font-size: 160px; }
  .story-tile-text span { display: none; }
  .story-hub .story-tiles { grid-template-columns: 1fr 1fr; gap: 8px; }
  .story-hub .story-item:nth-child(3) { grid-area: 1 / 2; }
  .story-hub .story-item:nth-child(4) { grid-area: 2 / 2; }
  .story-hub .story-item:nth-child(-n+2) { margin-inline-end: 0; }
  .story-hub .story-item:nth-child(n+3) { flex-direction: row; margin-inline-start: 0; }
  .story-hub .story-wire,
  .story-hub-bus,
  .story-hub-core { display: none; }
  .story-stack { grid-template-columns: minmax(0, 1fr); }
  .story-stack .story-tile-icon { width: 26px; height: 26px; }
  .story-stack-monitor { display: none; }
}

/* -------------------------------------------------------------------------
   34. Phones (no hover): the backdrop budget. Measured 2026-11-07 on a 390px
   viewport (design-preview/android-perf-backup-2026-11-07 holds the files
   from before): a backdrop-filter re-blurs what lies behind it on every frame
   that changes, and behind these panes the ribbon shader and the node network
   change every frame. The glass becomes a plain, slightly more opaque
   surface; the reveals keep their slide and fade but drop the blur (a filter
   transition is rasterised every frame); the SVG ribbon fallback (no WebGL)
   stands still, as its two Gaussian blurs would be re-run every frame of the
   drift. The home-only panes are handled in hero-home.css.
   ------------------------------------------------------------------------- */
@media (hover: none) {
  .btn-ghost,
  .hero-card,
  .expertises .section-head,
  .expertises .service-card,
  .hub-items .value-card,
  .stage-close,
  .stage-dot,
  .stage-arrow,
  .consent-card,
  body.nav-open::after,
  body.nav-closing::after {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .btn-ghost { background: rgba(255, 255, 255, 0.82); }
  .expertises .section-head { background: rgba(255, 255, 255, 0.9); }
  .expertises .service-card { background-color: rgba(255, 255, 255, 0.95); }
  .hub-items .value-card { background: rgba(255, 255, 255, 0.92); }
  .consent-card { background: rgba(255, 255, 255, 0.97); }
  .js .reveal { filter: none; }
  .js .reveal-words .w span { filter: none; }
  .ribbon-drift,
  .ribbon-edge { animation: none; }
}

/* -------------------------------------------------------------------------
   35. Language switch (header island)
   The FR / EN / AR switch left the menu card (visitors did not find it). One
   component, .lang-pop: a toggle showing the current language and a small
   card listing the three languages by their own names (base.html header).
   PREVIEW 2026-11-07: three placements, ?langv=a|b|c, one to be kept:
   A  its own pill beside the island;
   B  a button inside the closed island, beside the Menu pill;
   C  like A on phones; from 768px the three options shown at once.
   Without JavaScript the list is simply shown, each option a form POST.
   ------------------------------------------------------------------------- */
.header-row {
  --lang-pill-w: 66px;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 6px;
}
.header-row > .nav-shell { flex: 0 1 auto; min-width: 0; margin-inline: 0; }
/* an empty twin of the pill on the other side keeps the island centred, so it
   neither sits off-centre nor drifts when its card opens */
@media (min-width: 768px) {
  .header-row--a::before,
  .header-row--c::before { content: ""; flex: 0 0 var(--lang-pill-w); }
}
html:not(.js) .header-row { flex-wrap: wrap; }

.lang-pop { position: relative; z-index: 3; flex: none; }
.lang-pop--a,
.lang-pop--c {
  display: flex;
  min-width: var(--lang-pill-w);
  padding: 2px;
  border-radius: 999px;
  border: 1px solid rgba(11, 29, 51, 0.07);
  background: #fff;
  box-shadow: 0 1px 2px rgba(11, 29, 51, 0.06), 0 10px 30px -8px rgba(11, 29, 51, 0.16);
  transition: box-shadow 0.5s var(--ease);
}
.site-header.is-scrolled .lang-pop--a,
.site-header.is-scrolled .lang-pop--c { box-shadow: 0 1px 2px rgba(11, 29, 51, 0.06), 0 14px 40px -6px rgba(11, 29, 51, 0.22); }

.lang-pop-toggle {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 44px;
  height: 44px;
  padding-inline: 10px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1;
  cursor: pointer;
  transition: background 0.25s ease, color 0.25s ease;
}
.lang-pop-toggle .bi { font-size: 1rem; line-height: 1; }
.lang-pop-toggle:hover,
.lang-pop.is-open .lang-pop-toggle { background: var(--surface-2); }
html:not(.js) .lang-pop-toggle { display: none; }
.lang-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* the card of languages, under the toggle */
.lang-pop-menu { display: flex; gap: 2px; }
.js .lang-pop-menu {
  position: absolute;
  top: calc(100% + 8px);
  inset-inline-end: -1px;
  flex-direction: column;
  min-width: 200px;
  padding: 6px;
  border-radius: 20px;
  border: 1px solid rgba(11, 29, 51, 0.07);
  background: #fff;
  box-shadow: 0 2px 4px rgba(11, 29, 51, 0.06), 0 18px 44px -10px rgba(11, 29, 51, 0.28);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.98);
  transform-origin: 100% 0;
  transition: opacity 0.2s ease, transform 0.35s var(--ease), visibility 0s linear 0.35s;
}
body.is-rtl .lang-pop-menu { transform-origin: 0 0; }
.js .lang-pop.is-open .lang-pop-menu { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.lang-form { display: flex; }
.lang-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  border: 0;
  border-radius: 14px;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 0.94rem;
  font-weight: 500;
  text-align: start;
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease;
}
.lang-opt:hover,
.lang-opt[aria-current] { background: var(--surface-2); }
.lang-opt-code {
  flex: none;
  min-width: 24px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--muted); /* #5a6472: 5.9:1 on white, 5.1:1 on the current row */
}
.lang-opt[lang="ar"] .lang-opt-name { font-family: var(--font-ar); }
/* the current language: the green point of the current page in the menu */
.lang-opt[aria-current]::after {
  content: "";
  flex: none;
  width: 7px;
  height: 7px;
  margin-inline-start: auto;
  border-radius: 50%;
  background: var(--teal);
}
html:not(.js) .lang-opt { width: auto; padding-inline: 10px; gap: 6px; }
.lang-pop-toggle:focus-visible,
.lang-opt:focus-visible { outline: 2px solid #1e63c7; outline-offset: 2px; }

/* B: inside the island, before the Menu pill; the same height as the pill,
   its tap area grown to 44px over the island's padding */
.lang-pop--b { margin-inline-start: auto; }
.lang-pop--b .lang-pop-toggle {
  position: relative;
  height: var(--nav-item-h);
  min-width: 0;
  padding-inline: 10px 9px;
  gap: 5px;
  border: 1px solid var(--nav-line);
}
.lang-pop--b .lang-pop-toggle::before { content: ""; position: absolute; inset: -5px -1px; }
.lang-pop--b .lang-pop-chev { font-size: 0.62rem; transition: transform 0.35s var(--ease); }
.lang-pop--b.is-open .lang-pop-chev { transform: rotate(180deg); }
.js .lang-pop--b .lang-pop-menu { top: calc(100% + 14px); }
@media (max-width: 419.98px) {
  .lang-pop--b .lang-pop-toggle .bi-globe2 { display: none; }
}

/* narrow phones (< 390px): logo, Menu pill and switch share 336px, so the
   paddings tighten a little and the pill beside the island keeps only the
   globe (the current code is still read out); the logo keeps its size */
@media (max-width: 389.98px) {
  .header-row .nav-shell .navbar-brand { padding-inline: 6px; }
  .header-row .navbar-toggler { padding-inline: 12px 10px; gap: 8px; }
  .header-row--a,
  .header-row--c { --lang-pill-w: 50px; }
  .lang-pop--a .lang-pop-code,
  .lang-pop--c .lang-pop-code { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

/* C: from 768px the three languages sit in the pill, one tap each; the codes
   stand for the names (read out in full), the names themselves from 1280px */
@media (min-width: 768px) {
  .header-row--c { --lang-pill-w: 142px; }
  .lang-pop--c .lang-pop-toggle { display: none; }
  .js .lang-pop--c .lang-pop-menu,
  .lang-pop--c .lang-pop-menu {
    position: static;
    flex-direction: row;
    min-width: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
  }
  .lang-pop--c .lang-opt { width: 44px; justify-content: center; padding: 0; gap: 0; border-radius: 999px; }
  .lang-pop--c .lang-opt[aria-current] { background: var(--ink); }
  .lang-pop--c .lang-opt[aria-current] .lang-opt-code { color: #fff; }
  .lang-pop--c .lang-opt[aria-current]::after { display: none; }
  .lang-pop--c .lang-opt-code { min-width: 0; color: var(--ink); font-size: 0.7rem; }
  .lang-pop--c .lang-opt-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}
@media (min-width: 1280px) {
  .header-row--c { --lang-pill-w: 262px; }
  .lang-pop--c .lang-opt { width: 84px; font-size: 0.84rem; }
  .lang-pop--c .lang-opt-code { display: none; }
  .lang-pop--c .lang-opt-name { position: static; width: auto; height: auto; overflow: visible; clip-path: none; }
  .lang-pop--c .lang-opt[aria-current] { color: #fff; }
}

@media (prefers-reduced-motion: reduce) {
  .js .lang-pop-menu { transform: none; transition: opacity 0.01ms, visibility 0s; }
  .lang-pop--b .lang-pop-chev { transition: none; }
}


/* -------------------------------------------------------------------------
   36. Solutions: Management family and subcategories, new sector
   (2026-11-07). An item of pages/hubs.py may declare `children`; the
   Management family holds ERP, steering, projects and CRM. Here: the family
   tile of the catalogue (two tracks wide, the subcategories as chips with
   their anchors), the tree under its row in the nav dropdown, the tabs of
   its stage panel and the subcategory chips of the dial. What overrides
   5b, 21b, 25 or 29 lives here rather than in those sections.
   ------------------------------------------------------------------------- */
/* ---- the family tile ----------------------------------------------------
   Two tracks wide from 640px (one track on phones, where the chapter is a
   single column anyway). The lead stays put (a family has no hover copy to
   swap in); the chips row sits between the lead and the foot. */
@media (min-width: 640px) {
  .solution-card--family { grid-column: span 2; }
}
.solution-card--family .solution-text { min-height: 0; margin-bottom: 14px; }
.solution-card--family .solution-text .solution-lead { max-width: 60ch; }
@media (hover: hover) and (pointer: fine) {
  .solution-card--family:hover .solution-text .solution-lead { opacity: 1; transform: none; }
}
.solution-subs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 18px;
}
.solution-sub {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 4px 12px 4px 4px;
  border-radius: 12px;
  border: 1px solid var(--line-2);
  background: rgba(255, 255, 255, 0.72);
  color: var(--ink);
  font-size: 0.84rem;
  font-weight: 500;
  line-height: 1.2;
  transition: color 0.3s ease, border-color 0.3s ease, background 0.3s ease, transform 0.4s var(--ease), box-shadow 0.4s ease;
}
body.is-rtl .solution-sub { padding: 4px 4px 4px 12px; font-family: var(--font-ar); }
.solution-sub-icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: var(--teal-soft);
  color: var(--teal-ink);
  font-size: 0.86rem;
  transition: background 0.3s ease, color 0.3s ease;
}
.solution-sub:hover,
.solution-sub:focus-visible {
  color: var(--teal-ink);
  border-color: rgba(15, 122, 82, 0.5);
  background: #fff;
  transform: translateY(-2px);
  box-shadow: 0 12px 24px -16px rgba(11, 29, 51, 0.45);
}
.solution-sub:hover .solution-sub-icon,
.solution-sub:focus-visible .solution-sub-icon { background: var(--teal); color: #fff; }
.solution-sub:focus-visible { outline: 2px solid #1e63c7; outline-offset: 2px; }
/* without JavaScript the children read one after the other in the tile */
.solution-card .solution-body h3 { margin: 18px 0 4px; font-size: 1rem; }
.solution-card .solution-body .solution-lead { margin-bottom: 10px; font-weight: 500; }

/* ---- the nav tree ---------------------------------------------------------
   The family's row reads like the others; its children hang beneath it on a
   thin rule aligned with the centre of the icon column, each a smaller row
   (20px icon, 0.8rem text) with a short tick to the rule. */
.nav-sub-tree {
  --tree-x: 21px; /* the row's 8px padding + half the 26px icon */
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 0 4px;
  margin-inline-start: var(--tree-x);
  padding: 2px 0 0;
  padding-inline-start: 12px;
  list-style: none;
}
.nav-sub-tree::before {
  content: "";
  position: absolute;
  top: -2px;
  bottom: 13px; /* down to the middle of the last row */
  inset-inline-start: 0;
  width: 1px;
  background: var(--dd-line);
}
.nav-sub-tree > li { position: relative; }
.nav-sub-tree > li::before {
  content: "";
  position: absolute;
  top: 50%;
  inset-inline-start: -12px;
  width: 9px;
  height: 1px;
  background: var(--dd-line);
}
.nav-sub-link--child { gap: 8px; padding: 3px 8px; font-size: 0.8rem; }
.nav-sub-link--child .nav-sub-icon {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  border: 1px solid var(--dd-line);
  background: transparent;
  color: var(--dd-icon-fg);
  font-size: 0.7rem;
}
.nav-sub-link--child:hover .nav-sub-icon { border-color: transparent; }
@media (min-width: 960px) {
  .nav-dropdown .nav-sub-tree { --tree-x: 23px; } /* the wide panel's rows pad 10px */
  .nav-dropdown .nav-sub-link--child { padding: 4px 10px; }
}

/* ---- the stage tabs ---------------------------------------------------------
   A family's panel keeps one title and one lead; under them a segmented
   control, one tab per subcategory, swaps the pane (the subcategory's lead
   and body) and the services list of the side column without closing the
   stage (main.js mountStage). The pane rises in again at every switch; the
   ghost icon in the corner takes the subcategory's. */
.stage-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0 0 24px;
  padding: 4px;
  border-radius: 16px;
  background: color-mix(in srgb, var(--stage-accent) 7%, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--stage-accent) 16%, var(--line));
}
.stage-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 6px 14px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--ink-2);
  font: inherit;
  font-size: 0.88rem;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
}
.stage-tab i { font-size: 0.95rem; color: color-mix(in srgb, var(--stage-accent) 72%, #000); }
.stage-tab:hover { background: rgba(255, 255, 255, 0.7); color: var(--ink); }
.stage-tab[aria-selected="true"] {
  background: #fff;
  color: var(--ink);
  box-shadow: 0 6px 18px -10px rgba(11, 29, 51, 0.4), 0 0 0 1px color-mix(in srgb, var(--stage-accent) 30%, transparent);
}
.stage-tab[aria-selected="true"] i { color: var(--stage-accent); }
.stage-tab:focus-visible { outline: 2px solid #1e63c7; outline-offset: 2px; }
.stage-panes { display: grid; }
.stage-pane { grid-area: 1 / 1; }
.stage-pane[hidden],
.stage-services[hidden] { display: none; }
.stage-pane-lead {
  margin: 0 0 16px;
  max-width: 60ch;
  font-size: 1.08rem;
  font-weight: 500;
  line-height: 1.55;
  color: var(--ink);
}
.stage-pane.is-in,
.stage-services.is-in { animation: stage-pane-in 0.55s var(--ease) both; }
@keyframes stage-pane-in {
  from { opacity: 0; translate: 0 14px; }
  to { opacity: 1; translate: 0 0; }
}
body.is-rtl .stage-tab,
body.is-rtl .stage-pane-lead { font-family: var(--font-ar); letter-spacing: 0; }
@media (max-width: 639px) {
  .stage-tab { flex: 1 1 auto; justify-content: center; padding-inline: 10px; font-size: 0.82rem; }
}
@media (prefers-reduced-motion: reduce) {
  .stage-pane.is-in,
  .stage-services.is-in { animation: none; }
}

/* ---- the dial: a family's children ----------------------------------------
   Management stays one node; at the top its subcategories spring into the
   core and the foot in place of services, outlined in navy rather than
   filled green (a subcategory is not a service), under the label the
   row carries in data-foot (main.js initRadial swaps it). */
.rd-core-svc--sub { background: var(--surface-2); color: var(--ink); border: 1px solid var(--line-2); }
.rd-chip--sub { background: #fff; color: var(--ink); border: 1px solid var(--line-2); }
.rd-chip--sub i { color: var(--teal-ink); }


/* -------------------------------------------------------------------------
   37. AI hub: four groups
   /artificial-intelligence/ reads in four groups since 2026-11-07 (pages/hubs.py
   "key": "ai": large language models, reinforcement learning, agentic AI,
   computer vision; 11 items in all). The hub templates are shared with
   Solutions and unchanged; what the AI page needs on top sits here, scoped to
   its dropdown (#aiMenu) and to its hero board (.visual-aiflow, section 29).
   Copy sheet: design-preview/ai-hub-2026-11-07/copy-sheet.md.
   ------------------------------------------------------------------------- */
/* the dropdown on wide screens (5c): four groups of one to three rows do not
   fit as four columns of the 880px capsule (a 209px column breaks
   "Apprentissage par renforcement" and most item labels over two lines), so
   they read as a 2 x 2 grid, each cell its label over its rows */
@media (min-width: 960px) {
  #aiMenu .nav-sub-groups {
    grid-auto-flow: row;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px 8px;
  }
  #aiMenu .nav-sub-col:nth-child(n + 3) .nav-sub-group { margin-top: 10px; }
}
/* the board (29): one row per group, a small tag naming the group over each
   input label; the label may wrap under it, so these chips drop the two-line
   clamp of .af-chip > span */
.af-rows-in .af-chip > span { display: block; -webkit-line-clamp: unset; overflow: visible; }
.af-tag {
  display: block;
  margin-bottom: 2px;
  font-family: var(--font-mono);
  font-size: 0.5rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.35s ease;
}
.af-row.is-on .af-tag { color: var(--teal-ink); }
body.is-rtl .af-tag { font-family: var(--font-ar); font-size: 0.6rem; letter-spacing: 0; }


/* -------------------------------------------------------------------------
   38. Services rail legibility
   ------------------------------------------------------------------------- */
/* Measured 2026-11-07 on /services/ (FR + AR, 1440 to 360px): the dimming of
   section 16 left the neighbouring panels at 1.5-1.9:1 and the current panel
   at 3.4:1 half-way between two stops. Sections 16 and 33 now carry the softer
   depth, the larger plate type and the deeper link green; main.js rounds the
   rail's offset to whole device pixels (a fractional translate blurred every
   glyph, at rest too). This section holds the new rules. */

/* Arabic: the chip counter keeps "02 / 08" in left-to-right order (section 16)
   and lines up under the title; the link drops the mono face and its tracking
   (JetBrains Mono has no Arabic glyphs, and letter-spacing pulls the joined
   letters apart); IBM Plex Sans Arabic draws smaller than Inter at the same
   size, so the plate's small text takes a step up */
body.is-rtl .story-chip-sub { text-align: right; }
body.is-rtl .story-link { font-family: var(--font-ar); font-size: 0.9rem; letter-spacing: 0; }
body.is-rtl .story-scene-head { font-size: 0.8rem; }
body.is-rtl .story-tile-text span { font-size: 0.9rem; }
@media (min-width: 992px) and (max-width: 1199.98px) {
  body.is-rtl .story-tile-text span { font-size: 0.86rem; }
}
@media (max-width: 991.98px) {
  body.is-rtl .story-tile-text span { font-size: 0.84rem; }
}
@media (max-width: 639.98px) {
  body.is-rtl .story-scene-head { font-size: 0.76rem; }
}

/* the flow's column tiles have the height for a third line of note: the
   longest notes ("Développement, intégration, mise en service") were cut
   after two from 1024 to 1366px */
.story-flow .story-tile-text span { -webkit-line-clamp: 3; }

/* phones: the longest word of a facet title ("Développement",
   "Externalisation") is wider than the text column of a two-by-two tile and
   ran past the tile's edge; it now hyphenates (<html lang> is set; min-width: 0
   lets the grid track shrink below the word). A browser without a hyphenation
   dictionary keeps the word whole, as before: a break without a hyphen
   ("Nearshori / ng") read worse than the overhang */
@media (max-width: 639.98px) {
  .story-tile-text strong { min-width: 0; -webkit-hyphens: auto; hyphens: auto; }
}

/* -------------------------------------------------------------------------
   39. Responsive audit fixes (2026-11-08)
   From design-preview/responsive-audit-2026-11-07/report.md: F1-F6 are the
   findings, P1-P3 and P9 the polish items. Every block stands on its own and
   can be dropped alone; design-preview/responsive-audit-backup-2026-11-08
   holds this file from before.
   ------------------------------------------------------------------------- */

/* F1: below 992px the legal grid had one implicit auto column, which grew to
   the cookie table's min-width (600px): /privacy/ was 622px wide on every
   phone, and in Arabic the Menu and language buttons sat off-screen. A
   shrinkable column keeps the page at the viewport; the table scrolls inside
   its wrapper, as intended. */
@media (max-width: 991.98px) {
  .legal-grid { grid-template-columns: minmax(0, 1fr); }
}

/* F2: section 34 turns the hub cards into plain white panes on touch screens
   and caught the navy contact band ("Pas ce que vous cherchez ?") as well:
   white heading on white. */
@media (hover: none) {
  .hub-items .solution-card-other { background: var(--dark-2); }
}

/* F3: the beam spans the whole dial above the turning wheel and took every
   click and tap meant for the nodes; it is decoration only */
.rd-beam { pointer-events: none; }

/* F4: the pinned rail is moved by transform (main.js). As a scroll container
   (overflow: hidden) it could still be scrolled by keyboard focus, which threw
   the rail out of step with the page until a reload; a clipping box cannot be
   scrolled. overflow: hidden stays as the fallback (Safari < 16).
   min-width: 0 is required with clip (fixed 2026-11-12): the rail is a grid
   item of .chapters-viewport, and only a scroll container gets 0 as its
   automatic minimum width. Without it the rail took the track's full width,
   main.js centred the track by that width (--rail-pad), the rail grew again,
   and from 992px every panel ended up off-screen while the page scrolled. */
@media (min-width: 992px) and (prefers-reduced-motion: no-preference) {
  .js .story-rail { min-width: 0; overflow: hidden; overflow: clip; }
}

/* F5: wide screens with reduced motion get neither the pinned rail nor the
   deck, just the panels one under the other: they now keep to the page
   container instead of running edge to edge */
@media (min-width: 992px) and (prefers-reduced-motion: reduce) {
  .story-track { max-width: var(--container-w); margin-inline: auto; padding-inline: var(--gutter); }
}

/* F6: below 390px the flow tiles of the first service card are 126-133px
   wide; beside the icon, "Architecture", "Déploiement" or "Deployment" ran up
   to 18px past the tile's edge wherever no hyphenation dictionary is at hand.
   The icon now sits above the label, as on desktop, so the word gets the
   tile's full width; the two-by-two grid and the plate height stay. */
@media (max-width: 389.98px) {
  .story-flow .story-tile { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* P1: a 12px floor for the small mono labels that carry meaning (they were
   9.9-11.8px): eyebrows, footer headings, index numbers, the language codes,
   the group labels of the hubs and the menu, the legal page labels. The Menu
   pill keeps its 10.9px: at 12px the French "Fermer" pushed the pill under
   the logo on 360 and 393px phones, and the hamburger beside it already says
   what it is. */
.eyebrow,
.footer-col h3,
.index,
.service-index,
.lang-pop-toggle,
.lang-opt-code,
.solution-group-index,
.solution-jump-label,
.nav-sub-group,
.legal-toc h2,
.legal-meta,
.legal-table th { font-size: 0.75rem; }
body.is-rtl .nav-sub-group { font-size: 0.75rem; }

/* P2: touch screens, the links that were shorter than 24px (footer 16-24px,
   "Gérer les cookies" 22px, the banner's privacy link 22px, the rail's "En
   savoir plus" 20px) get a 44px tap area. The footer lists take the height in
   the layout; the two inline links take it in padding cancelled by negative
   margins, so nothing around them moves. The 32-40px chips and buttons already
   meet the 24px minimum and stay as they are (growing them would overlap
   their neighbours). */
@media (pointer: coarse) {
  .footer-col li { min-height: 44px; margin-bottom: 0; }
  .footer-col a,
  .footer-legal a,
  .footer-legal-btn { display: inline-flex; align-items: center; min-height: 44px; }
  .footer-legal { row-gap: 0; }
  .consent-link { padding-block: 11px; margin-block: 5px -11px; }
  .story-link { padding-block: 12px; margin-block: -6px -12px; }
}
@media (pointer: coarse) and (max-width: 991.98px) {
  .story-link { margin-block: -10px -12px; }
}

/* P3: the eyebrow green measured 3.9-4.0:1 over the tinted hero clips (404,
   contact, legal, privacy at 768px) and 4.46:1 on the tint band of About; it
   takes the deeper green of the rail links (section 16), 5.0:1 at worst. The
   rail's chip counter (4.49:1 on a resting panel) steps darker as well. Older
   Safari without color-mix() keeps the colours from before. */
.page-hero .eyebrow,
.section-tint .section-head .eyebrow { color: color-mix(in srgb, var(--teal-ink) 80%, var(--ink)); }
.story-chip-sub { color: color-mix(in srgb, var(--muted) 75%, var(--ink)); }

/* P9: Safari before 18 only knows the prefixed backdrop-filter. Hover screens
   only: section 34 keeps the glass off on touch screens. */
@media (hover: hover) {
  .btn-ghost { -webkit-backdrop-filter: blur(8px); }
}


/* -------------------------------------------------------------------------
   40. Approach chapter: the trail (2026-11-12)
   "How we work with you" reads as a path being walked. main.js lays an SVG
   path through the step badges (.process-trail, built from their positions,
   so it follows any layout and mirrors in Arabic): dotted where the visitor
   has not been yet, solid green behind the marker that walks it with the
   scroll. The steps alternate left and right like footsteps, which is what
   makes the path wind. Each badge lights up when the marker reaches it; the
   path ends in a ring that keeps turning once the last step is reached
   (continuous improvement). The old rules (dimmed steps, separators, accent
   bar) are switched off here; files from before:
   design-preview/approach-trail-backup-2026-11-12.
   ------------------------------------------------------------------------- */
.process-list {
  --trail-sway: 64px;
  --trail-badge: 48px;
  position: relative;
  border-top: 0;
  padding-bottom: 24px;
}
/* no dimming any more: every step stays fully legible, the trail and the
   badges carry the progress */
.process-step {
  grid-template-columns: var(--trail-badge) 1fr;
  gap: 24px;
  padding: clamp(26px, 3.6vw, 40px) 0;
  border-bottom: 0;
  opacity: 1;
}
.process-step::before { display: none; }
.process-step:nth-child(even) { padding-inline-start: var(--trail-sway); }

/* the milestone badge: dashed while ahead, tinted once passed, solid green
   where the visitor stands. It sits above the trail, so the marker slips
   under it like a train into a station. */
.process-num {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: var(--trail-badge);
  height: var(--trail-badge);
  margin-top: -6px;
  padding: 0;
  border-radius: 14px;
  border: 1.5px dashed var(--line-2);
  background: #fff;
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--muted);
  box-shadow: 0 10px 24px -14px rgba(11, 29, 51, 0.4);
  transition: background 0.5s ease, color 0.4s ease, border-color 0.4s ease, box-shadow 0.6s ease, scale 0.6s var(--ease-spring, var(--ease));
}
.process-step.is-done .process-num,
.process-step:hover .process-num {
  border-style: solid;
  border-color: rgba(15, 122, 82, 0.4);
  background: var(--teal-soft);
  color: var(--teal-ink);
}
.process-step.is-active .process-num {
  border-style: solid;
  border-color: var(--teal);
  background: var(--teal);
  color: #fff;
  scale: 1.06;
  box-shadow: 0 0 0 5px rgba(47, 176, 124, 0.2), 0 14px 28px -12px rgba(15, 122, 82, 0.6);
}
.process-step h3 { color: var(--ink); }

/* the trail itself */
.process-trail {
  position: absolute;
  inset: 0;
  z-index: 0;
  max-width: none;
  overflow: visible;
  pointer-events: none;
}
.process-trail path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.trail-base { stroke: rgba(11, 29, 51, 0.3); stroke-width: 3; stroke-dasharray: 0 10; }
.trail-glow { stroke: rgba(47, 176, 124, 0.22); stroke-width: 11; }
.trail-walked { stroke: var(--teal); stroke-width: 3; }
.trail-walker { opacity: 0; transition: opacity 0.4s ease; }
.is-walking .trail-walker { opacity: 1; }
.trail-walker-halo { fill: rgba(47, 176, 124, 0.26); }
.trail-walker-dot { fill: var(--ink); stroke: #fff; stroke-width: 3; }
.trail-loop {
  fill: none;
  stroke: rgba(11, 29, 51, 0.3);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 0 8.64;
  transition: stroke 0.5s ease;
}
.is-complete .trail-loop { stroke: var(--teal); stroke-dasharray: 9 8.28; }
@media (prefers-reduced-motion: no-preference) {
  .is-walking .trail-walker-halo { animation: trail-halo 2.2s ease-in-out infinite; }
  .is-complete .trail-loop { animation: trail-loop 9s linear infinite; }
}
@keyframes trail-halo {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
@keyframes trail-loop { to { transform: rotate(360deg); } }
body.is-rtl .is-complete .trail-loop { animation-direction: reverse; }

@media (max-width: 639px) {
  .process-list { --trail-sway: 26px; --trail-badge: 42px; }
  .process-step { grid-template-columns: var(--trail-badge) 1fr; gap: 14px; }
  .process-num { border-radius: 12px; font-size: 0.8rem; }
}

/* -------------------------------------------------------------------------
   41. Stage reel: the sector clips inside the stage (2026-11-13)
   The stock clips that played behind the home hero moved here: each sector's
   clip is the backdrop of the end side of its stage on /solutions/, behind
   the "services mobilised" column (partials/hub_stage.html, .stage-reel;
   main.js mountStage picks, loads and plays the open item's clip and flags
   the window .has-reel). The clip melts into the window's ground towards the
   copy (a mask, so the ribbon shows through the fade) and is washed a little
   so the cards on top keep their contrast. An item without a clip (reel:
   False in pages/hubs.py) keeps the plain ribbon. Phones: the poster alone,
   faded across the top of the window, no video.
   The service stage of the home page carries the same reel since 2026-11-13
   (partials/service_stage.html: one clip per service, static/video/services/,
   placed above the stage's own tint so the footage is not washed twice).
   ------------------------------------------------------------------------- */
.stage-reel {
  --reel-in: to right; /* fades in from the copy's side */
  position: absolute;
  top: 0;
  bottom: 0;
  inset-inline-end: 0;
  width: 60%;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(var(--reel-in), transparent 0, rgba(0, 0, 0, 0.5) 24%, #000 46%);
  mask-image: linear-gradient(var(--reel-in), transparent 0, rgba(0, 0, 0, 0.5) 24%, #000 46%);
}
body.is-rtl .stage-reel { --reel-in: to left; }
.stage-reel-clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transform: scale(1.05);
  filter: saturate(0.82) contrast(0.96);
  transition: opacity 0.9s ease, transform 1.8s var(--ease);
}
.stage-reel-clip.is-on { opacity: 1; transform: none; }
/* framing: the subject of this clip stands at the end of the frame */
.stage-reel-clip[data-reel="conseil-ingenierie-it"] { object-position: 92% center; }
/* service stage: its side column holds the contact card alone, which drops to
   the foot of the window so the footage (and the faces in it) stays open */
@media (min-width: 992px) {
  .service-stage:not(.hub-stage) .has-reel .stage-panel { align-content: stretch; }
  .service-stage:not(.hub-stage) .has-reel .stage-media { align-self: end; top: auto; bottom: 130px; }
}
.stage-reel-shade {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--bg) 50%, transparent), transparent 24%, transparent 62%, color-mix(in srgb, var(--bg) 80%, transparent)),
    linear-gradient(0deg, rgba(11, 29, 51, 0.1), rgba(11, 29, 51, 0.1));
}
/* over footage: the ribbon steps back, the column's label gets a ground of its
   own, the cards turn a touch more opaque and the ghost icon leaves */
.hub-stage .stage-backdrop .ribbon-art,
.hub-stage .stage-backdrop .ribbon-canvas { transition: opacity 0.9s ease; }
.hub-stage .has-reel .stage-backdrop .ribbon-art,
.hub-stage .has-reel .stage-backdrop .ribbon-canvas { opacity: 0.35; }
.has-reel .stage-services-label {
  width: fit-content;
  padding: 6px 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink-2);
}
.has-reel .stage-service { background: rgba(255, 255, 255, 0.92); }
.has-reel .stage-media .stage-cta { background: linear-gradient(135deg, color-mix(in srgb, var(--stage-accent) 12%, #fff), #fff); }
.has-reel .stage-ghost { display: none; }
.has-reel .stage-hint { color: #fff; text-shadow: 0 1px 8px rgba(11, 29, 51, 0.6); }

@media (max-width: 991px) {
  .stage-reel {
    inset-inline: 0;
    bottom: auto;
    width: auto;
    height: min(46%, 380px);
    opacity: 0.5;
    -webkit-mask-image: linear-gradient(180deg, #000 20%, transparent);
    mask-image: linear-gradient(180deg, #000 20%, transparent);
  }
  .stage-reel-shade { background: color-mix(in srgb, var(--bg) 30%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .stage-reel-clip { transform: none; transition: opacity 0.4s ease; }
}

/* -------------------------------------------------------------------------
   42. Approach chapter: the floor plan (2026-11-13)
   The four steps drawn as four rooms of one floor
   (partials/approach_plan.html): a meeting room, the workshop, the server
   room and the control room. The plan stays in view beside the steps and
   shows the same walk as the trail (section 40): main.js moves the dot along
   the route, draws the walked part solid, tints the rooms already crossed
   and washes the one the visitor stands in. Once the last step is reached
   the dot keeps circling the table (continuous improvement). A room is a
   shortcut to its step. The chapter head now runs full width above; the
   progress bar is gone, the plan is the progress. Tablets and phones: the
   plan follows as a mini-map under the header. Files from before:
   design-preview/approach-plan-backup-2026-11-13.
   ------------------------------------------------------------------------- */
.approach-grid > .section-head { grid-column: 1 / -1; margin-bottom: clamp(0px, 1.6vw, 20px); }
.approach-grid { gap: 32px; }

.approach-plan {
  container-type: inline-size;
  padding: clamp(8px, 2.2%, 16px);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-lg);
  background-color: #fff;
  background-image:
    linear-gradient(rgba(11, 29, 51, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(11, 29, 51, 0.04) 1px, transparent 1px);
  background-size: 22px 22px;
  background-position: center;
  box-shadow: var(--shadow-md);
}
.plan-sheet {
  position: relative;
  aspect-ratio: 760 / 480;
}
.plan-draw {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  overflow: visible;
  pointer-events: none;
}
body.is-rtl .plan-draw { transform: scaleX(-1); }
.plan-draw path,
.plan-draw rect,
.plan-draw circle { fill: none; }

/* the rooms: boxes in percentages of the 760 x 480 sheet, under the drawing */
.plan-room {
  position: absolute;
  z-index: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5cqw;
  padding: 2cqw 2.2cqw;
  cursor: pointer;
  background: rgba(47, 176, 124, 0);
  transition: background-color 0.6s ease;
}
.plan-room::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(75% 85% at 50% 45%, rgba(47, 176, 124, 0.3), rgba(47, 176, 124, 0.08));
  opacity: 0;
  transition: opacity 0.8s ease;
}
.plan-room > * { position: relative; }
.plan-room-1 { inset-inline-start: 5.79%; top: 4.17%; width: 29.74%; height: 52.08%; }
.plan-room-2 { inset-inline-start: 35.53%; top: 4.17%; width: 61.32%; height: 52.08%; }
.plan-room-3 { inset-inline-start: 63.16%; top: 56.25%; width: 33.68%; height: 39.58%; }
.plan-room-4 { inset-inline-start: 5.79%; top: 56.25%; width: 57.37%; height: 39.58%; }
.plan-room b {
  font-family: var(--font-mono);
  font-size: clamp(14px, 3.7cqw, 23px);
  font-weight: 500;
  line-height: 1;
  color: var(--muted);
  transition: color 0.5s ease;
}
.plan-room span {
  max-width: 22cqw;
  font-family: var(--font-mono);
  font-size: clamp(8px, 1.72cqw, 10.5px);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.5s ease;
}
.plan-room-2 span { max-width: 40cqw; }
body.is-rtl .plan-room span {
  font-family: inherit;
  font-size: clamp(9.5px, 2cqw, 12.5px);
  letter-spacing: 0;
}
.plan-room.is-past { background-color: rgba(47, 176, 124, 0.09); }
.plan-room.is-cur::before { opacity: 1; }
.plan-room.is-past b,
.plan-room.is-past span,
.plan-room.is-cur span { color: var(--ink); }
.plan-room.is-cur b { color: var(--teal-ink); }
@media (hover: hover) {
  .plan-room:hover { background-color: rgba(11, 29, 51, 0.05); }
  .plan-room.is-past:hover { background-color: rgba(47, 176, 124, 0.16); }
  .plan-room:hover b,
  .plan-room:hover span { color: var(--ink); }
}

/* the drawing */
.plan-draw .plan-wall { stroke: var(--ink); stroke-width: 6; stroke-linecap: square; stroke-linejoin: miter; }
.plan-draw .plan-window { stroke: #fff; stroke-width: 2.4; }
.plan-draw .plan-door { stroke: var(--ink); stroke-width: 1.1; }
.plan-draw .plan-furn > * { stroke: rgba(11, 29, 51, 0.34); stroke-width: 1.1; }
.plan-draw .plan-furn .plan-board { stroke: var(--ink); stroke-width: 3.5; }
.plan-draw .plan-entry { stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.plan-draw .plan-route { stroke: rgba(11, 29, 51, 0.42); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 0 7; }
.plan-draw .plan-walked { stroke: var(--teal); stroke-width: 3.2; stroke-linecap: round; stroke-linejoin: round; }
.plan-draw .plan-dot-halo { fill: rgba(47, 176, 124, 0.3); transform-box: fill-box; transform-origin: center; }
.plan-draw .plan-dot-core { fill: var(--ink); stroke: #fff; stroke-width: 3; }
.plan-orbit { transform-origin: 300px 372px; }

/* "you are here": rides below the dot (the room labels sit above the route),
   flips to its other side near the far edge */
.plan-tag {
  position: absolute;
  z-index: 2;
  left: 0;
  top: 0;
  padding: 5px 9px;
  border-radius: 6px;
  background: var(--ink);
  color: #fff;
  font-family: var(--font-mono);
  font-size: clamp(8.5px, 1.75cqw, 10.5px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate(12px, 12px);
  transition: opacity 0.4s ease;
  box-shadow: 0 10px 22px -12px rgba(11, 29, 51, 0.7);
}
.plan-tag.is-flip { transform: translate(calc(-100% - 12px), 12px); }
body.is-rtl .plan-tag { font-family: inherit; font-size: clamp(10px, 2cqw, 12px); letter-spacing: 0; }
.approach-plan.is-located .plan-tag { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  .approach-plan.is-located .plan-dot-halo { animation: plan-halo 2s ease-out infinite; }
  .approach-plan.is-complete .plan-orbit { animation: plan-orbit 9s linear infinite; }
}
@keyframes plan-halo {
  0% { transform: scale(0.5); opacity: 1; }
  100% { transform: scale(1.5); opacity: 0; }
}
@keyframes plan-orbit { to { transform: rotate(-360deg); } }

/* desktop: the plan holds mid-screen while the steps, set wider apart, scroll past */
@media (min-width: 992px) {
  .approach-grid { grid-template-columns: 1.2fr 1fr; gap: clamp(48px, 5vw, 76px); }
  .approach-sticky { top: max(calc(var(--header-h) + 24px), calc(50vh - 200px)); }
  .process-step { padding-block: clamp(40px, 6.5vh, 68px); }
}
/* tablets and phones: a mini-map under the header (not on very short screens) */
@media (max-width: 991px) and (min-height: 600px) {
  .approach-sticky {
    position: sticky;
    top: calc(var(--header-h) + 8px);
    z-index: 3;
    width: min(100%, 520px);
    margin-inline: auto;
  }
  .approach-plan { box-shadow: 0 18px 40px -22px rgba(11, 29, 51, 0.45); }
}
@media (max-width: 479px) {
  .plan-room { padding: 2.4cqw 2.6cqw; }
  .plan-room span { max-width: 24cqw; letter-spacing: 0.04em; }
  .plan-room-2 span { max-width: 44cqw; }
}

/* -------------------------------------------------------------------------
   43. Approach chapter: the sideways view (2026-11-13)
   Desktop screens (992px wide, 660px tall and up): the four steps stand in a
   row under the chapter head and the floor plan, and the trail runs sideways
   through their badges, which alternate a little up and down so the path
   still winds. The whole chapter fits one screen, so it pins (.approach-pin)
   and the scroll walks the marker instead of moving the page: main.js reads
   the progress from the pinned distance (--approach-run), gives every step
   the same share of it and reads each step's copy word by word meanwhile.
   The plan takes the height the row of steps leaves (--approach-steps-h, set
   by main.js). Without JS or with reduced motion: the same row, not pinned,
   the trail shown walked. Smaller or shorter screens keep the vertical trail
   of sections 40 and 42. Files from before:
   design-preview/approach-sideways-backup-2026-11-13.
   ------------------------------------------------------------------------- */
@media (min-width: 992px) and (min-height: 660px) {
  .approach-grid {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    column-gap: clamp(40px, 5vw, 76px);
    row-gap: clamp(22px, 4.4vh, 48px);
    align-items: center;
  }
  .approach-grid > .section-head { grid-column: 1; margin-bottom: 0; }
  .approach-sticky {
    position: static;
    grid-column: 2;
    justify-self: end;
    width: min(100%, 640px, calc((100vh - var(--header-h) - var(--approach-steps-h, 250px) - 124px) * 1.56));
  }
  .process-list {
    --trail-sway: 26px;
    grid-column: 1 / -1;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: clamp(20px, 2.6vw, 40px);
    align-items: start;
    padding-bottom: 0;
  }
  .process-step {
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding: 0;
  }
  .process-step:nth-child(even) { padding-inline-start: 0; padding-top: var(--trail-sway); }
  .process-num { align-self: flex-start; margin-top: 0; }
  .process-step h3 { margin-bottom: 8px; font-size: clamp(1.12rem, 1.55vw, 1.42rem); }
  .process-step p { font-size: 0.95rem; line-height: 1.6; }
  /* the step the marker stands on steps forward a little */
  .process-body { transition: translate 0.6s var(--ease); }
  .process-step.is-active .process-body { translate: 0 -3px; }
}
@media (min-width: 992px) and (min-height: 660px) and (prefers-reduced-motion: no-preference) {
  .js .approach {
    --approach-run: 190vh;
    height: calc(100vh - var(--header-h) + var(--approach-run));
    padding-block: 0;
  }
  .js .approach-pin {
    position: sticky;
    top: var(--header-h);
    display: grid;
    align-content: center;
    height: calc(100vh - var(--header-h));
    padding-block: 12px 28px;
  }
}
