/* ==========================================================================
   EDLUND ACCESSIBILITY — design system
   Built to §2–§6 of edlund-design-system.md.
   Every colour pair below is annotated with its measured WCAG 2.1 ratio.
   ========================================================================== */

/* ---------- fonts (self-hosted, no external requests) ---------- */
@font-face {
  font-family: "Public Sans";
  src: url("../fonts/public-sans-latin.woff2") format("woff2-variations"),
       url("../fonts/public-sans-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Public Sans";
  src: url("../fonts/public-sans-latin-italic.woff2") format("woff2-variations"),
       url("../fonts/public-sans-latin-italic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Montserrat SemiBold";
  src: url("../fonts/MontserratSemiBold.woff2") format("woff2"),
       url("../fonts/MontserratSemiBold.woff") format("woff");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   §2 COLOR SYSTEM
   SWAP THIS BLOCK when Jens's brand sheet arrives. Nothing else hardcodes colour.
   Brand green sampled from the existing site: #108F46.
   MEASURED: #108F46 on white = 4.17:1 -> passes 3:1 (large text / UI boundary)
             but FAILS 4.5:1 body text. So brand green is used for UI, rules,
             icons and large display type ONLY. --accent-text is the darkened
             sibling used wherever accent colour meets body-size text.
   ========================================================================== */
:root {
  --ink:          #1a1c1a;   /* on --paper 17.14:1 | on --paper-2 15.44:1 */
  --ink-muted:    #41474a;   /* on --paper  9.44:1 | on --paper-2  8.50:1 */
  --paper:        #ffffff;
  --paper-2:      #f4f3ef;   /* warm off-white secondary surface           */
  --paper-3:      #12261a;   /* deep green-black inverted surface          */

  --accent:       #108F46;   /* UI / rules / icons / large type only (3:1) */
  --accent-text:  #0b6e35;   /* accent at body size — 6.37:1 on white      */
  --accent-deep:  #0d5c2c;   /* 8.13:1 on white — pressed / hover states   */
  --accent-ink:   #ffffff;   /* on --accent 4.17:1 (large/UI) — buttons use
                                --accent-deep bg = 8.13:1, so button text
                                is AA at any size                          */
  --on-dark:      #ffffff;   /* on --paper-3 15.93:1                       */
  --on-dark-mute: #c9d6cd;   /* on --paper-3 10.61:1                       */
  --accent-dark:  #7fd4a0;   /* accent legible on --paper-3 — 8.97:1       */

  --focus:        #ffd200;   /* §6 focus token — always paired with an ink
                                inner ring so it is visible on ANY surface  */
  --line:         #d8d6ce;
  --line-strong:  #9aa09b;

  /* type scale — rem based so 200% zoom reflows (§3) */
  --step--1: clamp(1rem, 0.98rem + 0.10vw, 1.0625rem);      /* floor = 16px */
  --step-0:  clamp(1.0625rem, 1.03rem + 0.18vw, 1.1875rem); /* floor = 17px */
  --step-1:  clamp(1.125rem, 1.06rem + 0.32vw, 1.3125rem);
  --step-2:  clamp(1.375rem, 1.24rem + 0.65vw, 1.75rem);
  --step-3:  clamp(1.75rem, 1.5rem + 1.2vw, 2.5rem);
  --step-4:  clamp(2.25rem, 1.75rem + 2.4vw, 3.75rem);

  --measure: 68ch;           /* §3 line length under ~75 characters */
  --gutter: clamp(1.25rem, 4vw, 3rem);
  --bay: clamp(3.5rem, 8vw, 7rem);   /* vertical section rhythm */
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd, ul, ol { margin: 0; }
ul[class], ol[class] { list-style: none; padding: 0; }
img, svg { max-width: 100%; display: block; }
input, button, textarea, select { font: inherit; color: inherit; }

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  font-family: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-size: var(--step-0);
  line-height: 1.65;                /* §3 generous line-height */
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

/* ---------- §6 focus: visible on EVERY background ----------
   Ink ring hugs the element (visible on light surfaces), yellow ring sits
   outside it (visible on dark surfaces). Works on both without variants. */
:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 0;
  box-shadow: 0 0 0 6px var(--focus);
  border-radius: 1px;
}
.on-dark :focus-visible {
  outline-color: var(--paper);
}
/* never remove focus without a stronger replacement (§6) */

/* ---------- skip link (§6) ---------- */
.skip-link {
  position: absolute;
  left: var(--gutter);
  top: 0;
  transform: translateY(-120%);
  z-index: 200;
  background: var(--ink);
  color: var(--paper);
  padding: 0.85rem 1.25rem;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 4px solid var(--focus);
}
.skip-link:focus { transform: translateY(0); }
@media (prefers-reduced-motion: no-preference) {
  .skip-link { transition: transform 120ms ease-out; }
}

/* ---------- layout primitives ---------- */
.shell {
  width: min(100% - (var(--gutter) * 2), 78rem);
  margin-inline: auto;
}
.bay { padding-block: var(--bay); }
.measure { max-width: var(--measure); }

/* ---------- typography (§3) ---------- */
h1, h2, h3 {
  font-family: "Montserrat SemiBold", "Public Sans", system-ui, sans-serif;
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h1 { font-size: var(--step-4); }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); line-height: 1.25; }
p { text-wrap: pretty; }
p + p { margin-top: 1rem; }

.lede { font-size: var(--step-1); line-height: 1.55; color: var(--ink-muted); }

/* Section headings sit on a short brand rule — replaces the banned
   ALL-CAPS tracked eyebrow label (§3). */
.bay > .shell > h2,
.section-head h2 { position: relative; padding-top: 1.25rem; }
.bay > .shell > h2::before,
.section-head h2::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 3.5rem; height: 5px;
  background: var(--accent);
}
.on-dark .section-head h2::before { background: var(--accent-dark); }

.section-head { max-width: var(--measure); margin-bottom: 2.5rem; }
.section-head p { margin-top: 1rem; color: var(--ink-muted); }
.on-dark .section-head p { color: var(--on-dark-mute); }

/* ---------- links (§2: never colour alone — links carry an underline) ---- */
a { color: var(--accent-text); }
a:hover { color: var(--accent-deep); }
main a:not(.btn):not(.nav-list a) {
  text-underline-offset: 0.18em;
  text-decoration-thickness: 2px;
}

/* ---------- buttons (§6 target size >=44px) ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0.8rem 1.6rem;
  font-weight: 600;
  font-size: var(--step-0);
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: 2px;
  cursor: pointer;
}
.btn-primary {
  background: var(--accent-deep);   /* 8.13:1 with white text — AA at any size */
  color: var(--paper);
  border-color: var(--accent-deep);
}
.btn-primary:hover { background: #0a4a23; border-color: #0a4a23; color: var(--paper); }
.btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}
.btn-secondary:hover { border-color: var(--ink); background: var(--paper-2); color: var(--ink); }
.on-dark .btn-secondary { color: var(--on-dark); border-color: var(--on-dark-mute); }
.on-dark .btn-secondary:hover { background: rgba(255,255,255,0.1); color: var(--on-dark); border-color: var(--paper); }
@media (prefers-reduced-motion: no-preference) {
  .btn { transition: background-color 140ms ease, border-color 140ms ease; }
}

/* ==========================================================================
   HEADER
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 4.5rem;
  padding-block: 0.75rem;
}
.brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  text-decoration: none;
  color: var(--ink);
  min-height: 2.75rem;   /* §6 target size */
  padding-inline-end: 0.5rem;
}
.brand-mark { flex: none; width: 2.75rem; height: auto; }
.brand-name {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: 1.0625rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.brand-name span {
  font-family: "Public Sans", system-ui, sans-serif;
  font-weight: 400;
  color: var(--ink-muted);
}
@media (max-width: 26rem) {
  .brand-name span { display: none; }   /* mark + "Edlund" alone on very small screens */
}

.nav-list { display: flex; align-items: center; gap: 0.35rem; }
.nav-list a {
  display: block;
  padding: 0.65rem 0.85rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 500;
  border-radius: 2px;
}
.nav-list a:hover { background: var(--paper-2); color: var(--accent-deep); text-decoration: underline; text-underline-offset: 0.2em; }
.header-cta { flex: none; }
.site-nav .header-cta { display: none; }   /* mobile duplicate, revealed in the small-screen block */

.nav-toggle { display: none; }

@media (max-width: 60rem) {
  .nav-toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 2.75rem;
    padding: 0.5rem 0.9rem;
    background: var(--paper);
    border: 2px solid var(--line-strong);
    border-radius: 2px;
    font-weight: 600;
    cursor: pointer;
  }
  .nav-toggle-bars { display: block; width: 1.15rem; height: 2px; background: var(--ink); position: relative; }
  .nav-toggle-bars::before, .nav-toggle-bars::after {
    content: ""; position: absolute; left: 0; width: 100%; height: 2px; background: var(--ink);
  }
  .nav-toggle-bars::before { top: -6px; }
  .nav-toggle-bars::after { top: 6px; }
  .site-nav {
    position: absolute;
    inset-inline: 0;
    top: 100%;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
    padding: 0.5rem var(--gutter) 1.25rem;
    box-shadow: 0 12px 24px rgba(0,0,0,0.08);
  }
  .site-nav[hidden] { display: none; }
  .nav-list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav-list a { padding: 0.85rem 0.25rem; border-bottom: 1px solid var(--line); }
  .header-cta { display: none; }
  .site-nav .header-cta { display: block; margin-top: 1rem; }
  .site-nav .btn { width: 100%; }
}

/* ==========================================================================
   HERO — §4.1 / §5 single orchestrated motion moment
   ========================================================================== */
.hero {
  position: relative;
  background: var(--paper-3);
  color: var(--on-dark);
  overflow: hidden;
}
/* decorative roofline watermark — echoes the logo mark (see .hero-watermark) */
.hero-watermark {
  position: absolute;
  right: -6%;
  bottom: -18%;
  width: 52rem;
  max-width: 78%;
  height: auto;
  color: #7fd4a0;
  opacity: 0.13;
  pointer-events: none;
  z-index: 0;
}
@media (max-width: 62rem) { .hero-watermark { opacity: 0.08; bottom: -10%; } }
.hero-grid {
  position: relative;
  z-index: 1;
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  padding-block: clamp(4rem, 10vw, 7.5rem);
}
@media (min-width: 62rem) {
  /* §4 asymmetry — DOM order still matches visual order */
  .hero-grid { grid-template-columns: 1.35fr 1fr; align-items: center; }
}
.hero h1 { color: var(--on-dark); max-width: 20ch; }

/* slogan line above the hero headline */
.hero-kicker {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step--1);
  letter-spacing: 0.01em;
  color: var(--accent-dark);
  margin-bottom: 0.9rem;
}
.hero-lede {
  margin-top: 1.5rem;
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--on-dark-mute);
  max-width: 52ch;
}
.hero-actions {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}
.hero-note {
  margin-top: 1.75rem;
  font-size: var(--step--1);
  color: var(--on-dark-mute);
}

/* segment chips — text + border, never colour alone */
.segments {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.5rem;
}
.segments li {
  border: 1px solid rgba(201,214,205,0.5);
  border-left: 3px solid var(--accent-dark);
  padding: 0.35rem 0.75rem;
  font-size: var(--step--1);
  color: var(--on-dark-mute);
}

/* hero credential panel */
.hero-panel {
  border: 1px solid rgba(201,214,205,0.28);
  border-top: 5px solid var(--accent-dark);
  padding: clamp(1.5rem, 3vw, 2rem);
  background: rgba(255,255,255,0.03);
}
.hero-panel h2 {
  font-size: var(--step-1);
  color: var(--on-dark);
  margin-bottom: 1.25rem;
}
.stat-list > li + li { margin-top: 1.25rem; padding-top: 1.25rem; border-top: 1px solid rgba(201,214,205,0.22); }
.stat-num {
  display: block;
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step-2);
  color: var(--accent-dark);
  line-height: 1.1;
}
.stat-label { display: block; color: var(--on-dark-mute); font-size: var(--step--1); margin-top: 0.2rem; }

/* §5 ONE orchestrated reveal, hero only */
@media (prefers-reduced-motion: no-preference) {
  .reveal { animation: rise 620ms cubic-bezier(0.22, 0.61, 0.36, 1) both; }
  .reveal-2 { animation-delay: 110ms; }
  .reveal-3 { animation-delay: 220ms; }
  /* Uses `translate`, not `transform`. A finished animation with fill-mode
     `both` keeps applying its 100% keyframe, and the animation cascade origin
     outranks inline styles - so a `transform: none` here would silently veto
     the cursor tilt applied from script. Separate properties, no conflict. */
  @keyframes rise {
    from { opacity: 0; translate: 0 14px; }
    to   { opacity: 1; translate: 0 0; }
  }
}

/* ==========================================================================
   SERVICES — §4 cards vary by hierarchy; whole card is one link
   ========================================================================== */
.services { background: var(--paper); }
/* Deliberate asymmetric rhythm rather than a kit of four identical boxes (§4):
   wide  -> [ lead x2 | universal ] / [ advisory | business dev x2 ]
   medium-> two columns, lead full width
   small -> single column */
.service-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
  .service-grid { grid-template-columns: repeat(2, 1fr); }
  .service-grid > .is-lead { grid-column: span 2; }
}
@media (min-width: 62rem) {
  .service-grid { grid-template-columns: repeat(3, 1fr); }
  .service-grid > .is-lead { grid-column: span 2; }
  .service-grid > .card:last-child { grid-column: span 2; }
}
.card {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 1.75rem 1.5rem 1.9rem;
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 4px solid var(--accent);
  color: var(--ink);
  text-decoration: none;
  height: 100%;
}
/* hierarchy, not a kit of identical boxes: the lead card is heavier */
.card.is-lead {
  background: var(--paper-2);
  border-top-width: 8px;
}
@media (min-width: 48rem) {
  .card.is-lead .card-body { max-width: 52ch; }
}
.card-icon { color: var(--accent-text); }
.card h3 { color: var(--ink); }
.card-body { color: var(--ink-muted); font-size: var(--step-0); margin: 0; }
.card-meta {
  margin-top: auto;
  padding-top: 1rem;
  font-size: var(--step--1);
  color: var(--ink-muted);
  border-top: 1px solid var(--line);
}
@media (prefers-reduced-motion: no-preference) {
  .card { transition: background-color 140ms ease; }
}

/* ==========================================================================
   WHY US
   ========================================================================== */
.why { background: var(--paper-2); }
.why-grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 62rem) {
  .why-grid { grid-template-columns: 1fr 20rem; align-items: start; }
}
.proof-list > div {
  padding: 1.25rem 0;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 0.35rem;
}
.proof-list > div:last-child { border-bottom: 1px solid var(--line); }
.proof-list dt, .proof-term {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step-0);
}
.proof-list dd, .proof-desc { margin: 0; color: var(--ink-muted); }

.founder {
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 1.5rem;
}
.founder img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3.4;
  object-fit: cover;
  object-position: center 18%;
  border-bottom: 4px solid var(--accent);
}
.founder-name {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step-1);
  margin-top: 1.1rem;
}
.founder-role { color: var(--ink-muted); font-size: var(--step--1); }
.founder p { margin-top: 0.85rem; color: var(--ink-muted); font-size: var(--step--1); }
.founder .contact-line { margin-top: 1rem; font-size: var(--step--1); }

/* ==========================================================================
   ALLIANCE — §4.4 the differentiator, given real weight
   ========================================================================== */
.alliance { background: var(--paper-3); color: var(--on-dark); }
.alliance h2, .alliance h3 { color: var(--on-dark); }
.alliance-partners {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  align-items: center;
  padding: 1.1rem 0 1.5rem;
  border-top: 1px solid rgba(201,214,205,0.25);
  border-bottom: 1px solid rgba(201,214,205,0.25);
  margin-bottom: 2.5rem;
}
.partner-name {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step-1);
  color: var(--accent-dark);
}
a.partner-name { text-underline-offset: 0.18em; text-decoration-thickness: 2px; }
a.partner-name:hover { color: #a8e6c1; }
.partner-rel { color: var(--on-dark-mute); font-size: var(--step--1); }

/* Changing Places fixtures list on the dark panel */
.cp-fixtures {
  list-style: disc;
  padding-left: 1.35rem;
  margin-top: 1.25rem;
  color: var(--on-dark-mute);
}
.cp-fixtures li + li { margin-top: 0.4rem; }

.sensory-grid { display: grid; gap: clamp(2rem, 4vw, 3rem); }
@media (min-width: 62rem) {
  .sensory-grid { grid-template-columns: 1.1fr 1fr; align-items: start; }
}
.sensory-list > li {
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  gap: 0.35rem 1rem;
  padding: 1.1rem 0;
  border-top: 1px solid rgba(201,214,205,0.22);
}
.sensory-list > li:last-child { border-bottom: 1px solid rgba(201,214,205,0.22); }
.sensory-list .s-icon { grid-row: span 2; color: var(--accent-dark); padding-top: 0.15rem; }
.sensory-list .s-term { font-family: "Montserrat SemiBold", system-ui, sans-serif; }
.sensory-list .s-desc { color: var(--on-dark-mute); font-size: var(--step--1); }

.alliance-figure { border: 1px solid rgba(201,214,205,0.25); padding: 0.75rem; background: rgba(255,255,255,0.03); }
.alliance-figure img { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; filter: saturate(0.75); }
.alliance-figure figcaption { margin-top: 0.75rem; font-size: var(--step--1); color: var(--on-dark-mute); }
.alliance-cta { margin-top: 2rem; }

/* ==========================================================================
   CTA BAND — §4.5
   ========================================================================== */
.cta-band { background: var(--paper); border-block: 1px solid var(--line); }
.cta-inner { display: grid; gap: 1.75rem; align-items: center; }
@media (min-width: 55rem) {
  .cta-inner { grid-template-columns: 1fr auto; gap: 3rem; }
}
.cta-inner h2 { font-size: var(--step-2); padding-top: 0; }
.cta-inner h2::before { display: none; }
.cta-inner p { margin-top: 0.75rem; color: var(--ink-muted); max-width: 54ch; }

/* ==========================================================================
   CONTACT — §4.6 prominent, designed, not tacked on
   ========================================================================== */
.contact { background: var(--paper-2); }
.contact-grid { display: grid; gap: clamp(2rem, 5vw, 3.5rem); }
@media (min-width: 62rem) {
  .contact-grid { grid-template-columns: 1.15fr 0.85fr; align-items: start; }
}
.form-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 6px solid var(--accent);
  padding: clamp(1.5rem, 4vw, 2.25rem);
}
.field { margin-bottom: 1.4rem; }
.field label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.35rem;
}
.hint { display: block; font-weight: 400; color: var(--ink-muted); font-size: var(--step--1); margin-bottom: 0.4rem; }
.field input, .field textarea, .field select {
  width: 100%;
  min-height: 3rem;
  padding: 0.7rem 0.85rem;
  background: var(--paper);
  border: 2px solid var(--line-strong);
  border-radius: 2px;
  color: var(--ink);
}
.field textarea { min-height: 8rem; resize: vertical; }
.field input:hover, .field textarea:hover, .field select:hover { border-color: var(--ink-muted); }

/* error state: colour + icon + text, never colour alone (§2) */
.field.has-error input, .field.has-error textarea, .field.has-error select { border-color: #a4262c; border-width: 3px; }
.field-error {
  display: none;
  margin-top: 0.4rem;
  color: #a4262c;              /* 6.9:1 on white */
  font-weight: 600;
  font-size: var(--step--1);
}
.field.has-error .field-error { display: flex; gap: 0.4rem; align-items: flex-start; }
.error-summary {
  display: none;
  border: 3px solid #a4262c;
  padding: 1rem 1.25rem;
  margin-bottom: 1.5rem;
}
.error-summary:not([hidden]) { display: block; }
.error-summary h3 { color: #a4262c; font-size: var(--step-0); }
.error-summary ul { margin-top: 0.5rem; padding-left: 1.1rem; list-style: disc; }
.error-summary a { color: #a4262c; font-weight: 600; }
.form-status { margin-top: 1rem; font-weight: 600; color: var(--accent-text); }
.form-status:empty { margin-top: 0; }

.contact-aside > * + * { margin-top: 2rem; }
.contact-line { display: grid; gap: 0.2rem; padding: 0.9rem 0; border-top: 1px solid var(--line); }
.contact-line:last-child { border-bottom: 1px solid var(--line); }
.contact-line dt, .contact-term { font-weight: 600; font-size: var(--step--1); color: var(--ink-muted); }
.contact-line dd, .contact-val { margin: 0; font-size: var(--step-0); }
.contact-line a { color: var(--accent-text); text-underline-offset: 0.18em; text-decoration-thickness: 2px; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.site-footer { background: var(--paper-3); color: var(--on-dark); padding-block: 3rem 2rem; }
.footer-top { display: grid; gap: 2rem; padding-bottom: 2rem; border-bottom: 1px solid rgba(201,214,205,0.22); }
@media (min-width: 48rem) { .footer-top { grid-template-columns: 1fr auto; align-items: start; } }
.footer-tag { font-family: "Montserrat SemiBold", system-ui, sans-serif; font-size: var(--step-1); margin-top: 0.85rem; color: var(--accent-dark); }
.site-footer .nav-list { flex-wrap: wrap; gap: 0.25rem 1.25rem; }
.site-footer .nav-list a { color: var(--on-dark); padding: 0.4rem 0; }
.site-footer .nav-list a:hover { background: none; color: var(--accent-dark); text-decoration: underline; }
.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;
  justify-content: space-between;
  padding-top: 1.5rem;
  font-size: var(--step--1);
  color: var(--on-dark-mute);
}
.site-footer a { color: var(--accent-dark); }

/* ---------- utility ---------- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   GLASS LAYER + VIDEO HERO
   Later rules deliberately override the flat surfaces defined above.

   CONTRAST PROOF (worst case = a pure-white video frame, i.e. sunlit
   concrete). Composites measured, not eyeballed:
     scrim 0.78 over white video      -> rgb(63,72,67)    white text  9.49:1
     + dark glass 0.55 on that scrim  -> rgb(33,42,37)    white      14.74:1
                                                          mint        8.30:1
                                                          muted       9.82:1
     light glass 0.62 over paper wash -> rgb(246,245,242) ink        15.74:1
                                                          muted       8.67:1
                                                          accent      5.85:1
   Every pairing clears 4.5:1, so the glass cannot drop the page below AA
   no matter which frame of the video is on screen.
   ========================================================================== */
:root {
  --glass-blur: 14px;
  --glass-dark:        rgba(8, 18, 13, 0.55);
  --glass-dark-edge:   rgba(201, 214, 205, 0.28);
  --glass-light:       rgba(255, 255, 255, 0.62);
  --glass-light-edge:  rgba(255, 255, 255, 0.85);
  --glass-shadow: 0 1px 2px rgba(12, 26, 18, 0.05), 0 12px 32px -12px rgba(12, 26, 18, 0.18);
  --radius: 14px;
}

/* ---------- shared glass recipes ---------- */
.glass-dark,
.hero-panel,
.alliance-figure,
.glass-panel.on-dark-panel {
  background: var(--glass-dark);
  border: 1px solid var(--glass-dark-edge);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.25);
          backdrop-filter: blur(var(--glass-blur)) saturate(1.25);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.glass-light,
.card,
.founder,
.form-card,
.contact-aside-inner,
.cta-inner,
.glass-panel:not(.on-dark-panel) {
  background: var(--glass-light);
  border: 1px solid var(--glass-light-edge);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
          backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.9);
}

/* Browsers without backdrop-filter get opaque surfaces, never washed-out text */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass-dark, .hero-panel, .alliance-figure, .glass-panel.on-dark-panel {
    background: #16241c;
  }
  .glass-light, .card, .founder, .form-card, .contact-aside-inner, .cta-inner,
  .glass-panel:not(.on-dark-panel) {
    background: #fbfaf8;
  }
}
/* Users who ask for less transparency get flat, opaque surfaces */
@media (prefers-reduced-transparency: reduce) {
  .glass-dark, .hero-panel, .alliance-figure, .glass-panel.on-dark-panel {
    background: #16241c;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
  .glass-light, .card, .founder, .form-card, .contact-aside-inner, .cta-inner,
  .glass-panel:not(.on-dark-panel) {
    background: #fbfaf8;
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}

/* ---------- ambient wash: gives the light-section glass something to refract.
   Kept far below any text-contrast threshold; it is texture, not decoration. */
.wash { position: relative; isolation: isolate; }
.wash::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(55rem 34rem at 10% -10%, rgba(16, 143, 70, 0.13), transparent 62%),
    radial-gradient(46rem 30rem at 92% 108%, rgba(16, 143, 70, 0.09), transparent 62%);
  pointer-events: none;
}

/* ==========================================================================
   HERO VIDEO
   ========================================================================== */
.hero { position: relative; isolation: isolate; }
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--paper-3);
}
.hero-media video,
.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* scrim: the contrast guarantee. 0.78 floor, deepened on the text side. */
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(100deg, rgba(6, 15, 10, 0.90) 0%, rgba(8, 18, 13, 0.84) 42%, rgba(8, 18, 13, 0.78) 100%),
    linear-gradient(to bottom, rgba(8, 18, 13, 0.42) 0%, transparent 28%, transparent 72%, rgba(8, 18, 13, 0.42) 100%);
}
.hero-grid { position: relative; z-index: 2; }
.hero-watermark { z-index: 2; }

/* pause control - WCAG 2.2.2 requires this for anything auto-playing over 5s */
.video-toggle {
  position: absolute;
  z-index: 3;
  right: var(--gutter);
  bottom: 1.25rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding: 0.5rem 0.95rem;
  color: var(--on-dark);
  background: rgba(8, 18, 13, 0.62);
  border: 1px solid var(--glass-dark-edge);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  font-size: var(--step--1);
  font-weight: 600;
  cursor: pointer;
}
.video-toggle:hover { background: rgba(8, 18, 13, 0.8); }
.video-toggle svg { flex: none; }
@media (max-width: 40rem) {
  .video-toggle {
    right: auto;
    left: var(--gutter);
    bottom: 0.85rem;
    padding: 0.5rem;
    width: 2.75rem;
    justify-content: center;
  }
  .video-toggle .video-toggle-label {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}

/* ==========================================================================
   SECTION SURFACES adjusted for the glass layer
   ========================================================================== */
.services, .why, .contact, .cta-band { background: var(--paper-2); }
.cta-band { border-block: 0; }

.card { padding: 1.75rem 1.5rem 1.9rem; position: relative; overflow: hidden; }
.card.is-lead { background: var(--glass-light); }
.card, .card.is-lead { border-top: 1px solid var(--glass-light-edge); }
/* hierarchy now comes from an accent spine, not from a heavier top rule */
.card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--accent);
}
.card.is-lead::before { width: 7px; }
.card-meta { border-top: 1px solid rgba(26, 28, 26, 0.12); }

.founder { padding: 1.25rem; }
.founder img { border-radius: 10px; border-bottom: 0; box-shadow: 0 0 0 1px rgba(26, 28, 26, 0.08); }
.founder-name { margin-top: 1rem; }

/* text chunks promoted to cards, as asked */
.glass-panel { padding: clamp(1.5rem, 3.5vw, 2.25rem); }
.glass-panel .proof-list > div:first-child { border-top: 0; padding-top: 0; }
.glass-panel .proof-list > div:last-child { border-bottom: 0; padding-bottom: 0; }

.hero-panel { border-top: 1px solid var(--glass-dark-edge); }
.hero-panel::before {
  content: "";
  display: block;
  width: 3rem; height: 4px;
  background: var(--accent-dark);
  border-radius: 2px;
  margin-bottom: 1.1rem;
}

.alliance-figure { padding: 0.85rem; }
.alliance-figure img { border-radius: 8px; }

.cta-inner { padding: clamp(1.75rem, 4vw, 2.5rem); }

.form-card { border-top: 1px solid var(--glass-light-edge); }
.form-card::before {
  content: "";
  display: block;
  width: 3.5rem; height: 5px;
  background: var(--accent);
  border-radius: 2px;
  margin-bottom: 1.5rem;
}
.contact-aside-inner { padding: clamp(1.5rem, 3.5vw, 2rem); }
.contact-aside > * + * { margin-top: 1.25rem; }

/* inputs read as glass too, but stay high-contrast */
.field input, .field textarea, .field select {
  background: rgba(255, 255, 255, 0.85);
  border-radius: 8px;
}
.btn { border-radius: 999px; }
.segments li { border-radius: 999px; }
.error-summary { border-radius: 10px; background: rgba(255, 255, 255, 0.8); }

/* Fit the hero to the viewport so the pause control is always on screen while
   the video is moving. WCAG 2.2.2 only requires the control to exist, but a
   control you have to scroll to find is not a control. */
.hero-grid {
  min-height: calc(100svh - 4.75rem);
  align-content: center;
  padding-block: clamp(3rem, 7vh, 5.5rem);
}
@supports not (height: 100svh) {
  .hero-grid { min-height: calc(100vh - 4.75rem); }
}

/* ==========================================================================
   AMBIENT BLOB FIELD, CLEAR-TO-SOLID HEADER, REVEAL + COUNT-UP
   All motion here is decorative, so all of it is inside a
   prefers-reduced-motion: no-preference guard. With reduced motion the blobs
   sit still, the header still swaps, and every revealed element is simply
   already in its final state.
   ========================================================================== */

/* ---------- the field sits behind everything; light sections go clear ----- */
body { background: var(--paper-2); }

.blob-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
}
.blob {
  position: absolute;
  display: block;
  width: 46vmax;
  height: 46vmax;
  border-radius: 50%;
  filter: blur(70px);
  will-change: transform;
}
.blob-1 { background: radial-gradient(circle at 50% 50%, rgba(16,143,70,0.24), rgba(16,143,70,0) 68%); top: -12vmax; left: -8vmax; }
.blob-2 { background: radial-gradient(circle at 50% 50%, rgba(127,212,160,0.26), rgba(127,212,160,0) 68%); top: 22vmax;  left: 34vmax; }
.blob-3 { background: radial-gradient(circle at 50% 50%, rgba(11,110,53,0.18),  rgba(11,110,53,0) 68%);  top: -4vmax;  left: 58vmax; }

/* light sections become transparent so the field reads through the glass */
.services, .why, .contact, .cta-band { background: transparent; }
.services::before, .why::before, .contact::before, .cta-band::before { display: none; }

/* stacking: page content above the field */
.site-header, main, .site-footer { position: relative; z-index: 1; }
/* opaque sections must stay opaque or the field bleeds into them */
.hero, .alliance, .site-footer { background-color: var(--paper-3); }

@media (prefers-reduced-motion: no-preference) {
  /* Three drifts on deliberately unequal periods, so the blobs converge into
     one mass and pull apart again without ever repeating the same meeting. */
  .blob-1 { animation: drift-1 37s ease-in-out infinite; }
  .blob-2 { animation: drift-2 43s ease-in-out infinite; }
  .blob-3 { animation: drift-3 53s ease-in-out infinite; }
}

@keyframes drift-1 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  25%  { transform: translate3d(22vmax, 10vmax, 0) scale(1.15); }
  50%  { transform: translate3d(34vmax, 26vmax, 0) scale(0.9); }   /* converge */
  75%  { transform: translate3d(8vmax, 30vmax, 0) scale(1.1); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes drift-2 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  30%  { transform: translate3d(-20vmax, 16vmax, 0) scale(0.85); }
  55%  { transform: translate3d(-4vmax, 2vmax, 0) scale(1.2); }    /* converge */
  80%  { transform: translate3d(16vmax, -12vmax, 0) scale(0.95); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes drift-3 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  35%  { transform: translate3d(-26vmax, 22vmax, 0) scale(1.18); }
  60%  { transform: translate3d(-34vmax, 6vmax, 0) scale(0.88); }
  85%  { transform: translate3d(-12vmax, 26vmax, 0) scale(1.05); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

/* ==========================================================================
   HEADER: clear over the video, solid once you scroll off it
   ========================================================================== */
.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
}
/* anchor targets must clear the fixed header */
main[id], section[id] { scroll-margin-top: 5.25rem; }

.site-header.is-clear {
  background: transparent;
  border-bottom-color: transparent;
  box-shadow: none;
}
.site-header.is-clear .brand-name { color: var(--on-dark); }
.site-header.is-clear .brand-name span { color: var(--on-dark-mute); }
.site-header.is-clear .brand-mark path { stroke: var(--accent-dark); }
.site-header.is-clear .nav-list a { color: var(--on-dark); }
.site-header.is-clear .nav-list a:hover { background: rgba(255,255,255,0.14); color: var(--on-dark); }
.site-header.is-clear .nav-toggle {
  color: var(--on-dark);
  background: rgba(8,18,13,0.45);
  border-color: rgba(255,255,255,0.55);
}
.site-header.is-clear .nav-toggle-bars,
.site-header.is-clear .nav-toggle-bars::before,
.site-header.is-clear .nav-toggle-bars::after { background: var(--on-dark); }
/* keyboard focus inside a clear header needs the light ring */
.site-header.is-clear :focus-visible { outline-color: var(--paper); }
/* the open mobile menu is never transparent - it would sit over the video.
   Scoped to the small-screen breakpoint: at desktop .site-nav is always
   :not([hidden]), so an unscoped rule painted a white box behind the nav. */
@media (max-width: 60rem) {
  .site-header.is-clear .site-nav:not([hidden]) { background: var(--paper); }
  .site-header.is-clear .site-nav:not([hidden]) .nav-list a { color: var(--ink); }
}

@media (prefers-reduced-motion: no-preference) {
  .site-header { transition: background-color 260ms ease, border-color 260ms ease, box-shadow 260ms ease; }
  .site-header .brand-name,
  .site-header .brand-name span,
  .site-header .nav-list a { transition: color 260ms ease; }
  .site-header .brand-mark path { transition: stroke 260ms ease; }
}

/* the hero now runs under the fixed header */
.hero-grid {
  min-height: 100svh;
  padding-top: calc(4.75rem + clamp(2.5rem, 6vh, 4.5rem));
  padding-bottom: clamp(3rem, 7vh, 5.5rem);
}
@supports not (height: 100svh) { .hero-grid { min-height: 100vh; } }

/* ==========================================================================
   REVEAL ON SCROLL + COUNT-UP
   Nothing is hidden by CSS alone. The .anim-ready class is added by script
   only when motion is allowed, so no-JS and reduced-motion visitors always
   get the finished state.
   ========================================================================== */
.anim-ready [data-reveal] {
  opacity: 0;
  /* `translate` is a separate property from `transform`, so the scroll reveal
     and the card hover lift compose cleanly and keep independent timings
     instead of one overriding the other on specificity. */
  translate: 0 14px;
  transition: opacity 620ms cubic-bezier(0.22, 0.61, 0.36, 1),
              translate 620ms cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--reveal-delay, 0ms);
}
.anim-ready [data-reveal].is-in {
  opacity: 1;
  translate: 0 0;
}

/* the counter must not reflow the layout as digits change */
.stat-num [data-count] { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   SERVICE CARD HOVER
   Gated on (hover: hover) and (pointer: fine): touch devices resolve :hover
   on tap and then keep it stuck until you tap elsewhere, so they are excluded
   entirely. Reduced motion still gets the lift in depth, just not in movement.
   ========================================================================== */
.card {
  /* the lift is composited: transform + opacity only, no layout work */
  transform: translate3d(0, 0, 0);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
.card::after {
  /* the raised shadow lives here so it can cross-fade instead of animating
     box-shadow on the card itself, which repaints on every frame */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  box-shadow: 0 18px 44px -14px rgba(12, 26, 18, 0.34),
              0 4px 12px -6px rgba(12, 26, 18, 0.18);
}

@media (hover: hover) and (pointer: fine) {
  /* Asymmetric timing is what makes it feel sprung rather than mechanical:
     the card eases OUT quickly and settles back, but rises with a small
     overshoot. Leaving is faster than arriving, as with a real object. */
  .card {
    transition: transform 300ms cubic-bezier(0.4, 0.0, 0.2, 1),
                background-color 300ms ease;
  }
  .card::after { transition: opacity 300ms cubic-bezier(0.4, 0.0, 0.2, 1); }
  .card::before { transition: width 300ms cubic-bezier(0.4, 0.0, 0.2, 1); }

  .card:hover {
    /* No scale(): scaling resamples the glyphs mid-flight and reads as blur.
       A pure Y translation with a deeper shadow gives the same "pop" and
       keeps the text crisp on every frame. */
    transform: translate3d(0, -10px, 0);
    background: rgba(255, 255, 255, 0.84);
    z-index: 2;                       /* lift above its neighbours while raised */
    transition: transform 460ms cubic-bezier(0.34, 1.56, 0.64, 1),
                background-color 300ms ease;
  }
  .card:hover::after {
    opacity: 1;
    transition: opacity 460ms cubic-bezier(0.34, 1.56, 0.64, 1);
  }
  .card:hover::before {
    width: 7px;
    transition: width 460ms cubic-bezier(0.34, 1.56, 0.64, 1);
  }
  .card.is-lead:hover::before { width: 11px; }

  /* Movement is the decoration; depth is the signal. Keep the signal. */
  @media (prefers-reduced-motion: reduce) {
    .card, .card::after, .card::before,
    .card:hover, .card:hover::after, .card:hover::before { transition: none; }
    .card:hover { transform: none; }
  }
}

/* ==========================================================================
   "digitally" GLITCH-IN
   Two safety constraints shaped this, both non-negotiable for this client:

   1. WCAG 2.3.1 (Three Flashes, Level A). A flash is a paired change in
      relative luminance of 10% or more. So the real word NEVER changes
      opacity and is never clipped - it sits at full luminance the whole time.
      The effect is chromatic split plus sub-pixel displacement, which moves
      colour around without strobing brightness. Nothing flashes at all.

   2. Screen-reader duplication. The usual implementation paints two copies
      with content: attr(data-text) on ::before/::after, and NVDA and
      VoiceOver both announce pseudo-element content - the heading would read
      "...physically and digitally digitally digitally." The ghost copies are
      therefore real spans carrying aria-hidden, which AT ignores reliably.

   It runs once on entry and settles clean. No looping ambient glitch.
   ========================================================================== */
.glitch {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}
.glitch-real {
  position: relative;
  z-index: 2;          /* the legible word always sits on top */
}
.glitch-ghost {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1;
  opacity: 0;          /* invisible unless the animation runs */
  pointer-events: none;
  user-select: none;
  will-change: transform, clip-path;
}
.glitch-ghost-a { color: #5ee8ff; }   /* cyan channel  */
.glitch-ghost-b { color: #ff5ec8; }   /* magenta channel */

@media (prefers-reduced-motion: no-preference) {
  /* starts after the hero headline has finished rising in */
  .glitch-real {
    animation: glitch-settle 900ms steps(1, end) 620ms both;
  }
  .glitch-ghost-a {
    animation: glitch-a 900ms steps(1, end) 620ms both;
  }
  .glitch-ghost-b {
    animation: glitch-b 900ms steps(1, end) 620ms both;
  }

  /* Displacement only - opacity stays at 1 throughout, so there is no flash.
     steps(1) gives the hard digital snap rather than a smooth slide. */
  @keyframes glitch-settle {
    0%   { transform: translate3d(-3px, 0, 0); }
    12%  { transform: translate3d(4px, 0, 0); }
    24%  { transform: translate3d(-2px, 0, 0); }
    36%  { transform: translate3d(3px, 0, 0); }
    48%  { transform: translate3d(-1px, 0, 0); }
    60%  { transform: translate3d(2px, 0, 0); }
    72%  { transform: translate3d(-1px, 0, 0); }
    84%  { transform: translate3d(1px, 0, 0); }
    100% { transform: none; }
  }

  /* The ghosts carry the visual noise: colour offset and horizontal slices.
     They decay to nothing, so the headline ends perfectly clean. */
  @keyframes glitch-a {
    0%   { opacity: 0.85; transform: translate3d(-8px, -2px, 0); clip-path: inset(12% 0 58% 0); }
    15%  { opacity: 0.8;  transform: translate3d(7px, 1px, 0);   clip-path: inset(64% 0 12% 0); }
    30%  { opacity: 0.7;  transform: translate3d(-6px, 2px, 0);  clip-path: inset(30% 0 44% 0); }
    45%  { opacity: 0.6;  transform: translate3d(5px, -1px, 0);  clip-path: inset(76% 0 6% 0); }
    60%  { opacity: 0.45; transform: translate3d(-4px, 0, 0);    clip-path: inset(20% 0 62% 0); }
    75%  { opacity: 0.3;  transform: translate3d(3px, 0, 0);     clip-path: inset(48% 0 34% 0); }
    88%  { opacity: 0.15; transform: translate3d(-2px, 0, 0);    clip-path: inset(8% 0 78% 0); }
    100% { opacity: 0;    transform: none;                       clip-path: inset(0 0 0 0); }
  }
  @keyframes glitch-b {
    0%   { opacity: 0.85; transform: translate3d(8px, 2px, 0);   clip-path: inset(58% 0 14% 0); }
    15%  { opacity: 0.8;  transform: translate3d(-7px, -1px, 0); clip-path: inset(10% 0 66% 0); }
    30%  { opacity: 0.7;  transform: translate3d(6px, -2px, 0);  clip-path: inset(70% 0 8% 0); }
    45%  { opacity: 0.6;  transform: translate3d(-5px, 1px, 0);  clip-path: inset(24% 0 54% 0); }
    60%  { opacity: 0.45; transform: translate3d(4px, 0, 0);     clip-path: inset(52% 0 30% 0); }
    75%  { opacity: 0.3;  transform: translate3d(-3px, 0, 0);    clip-path: inset(16% 0 70% 0); }
    88%  { opacity: 0.15; transform: translate3d(2px, 0, 0);     clip-path: inset(66% 0 18% 0); }
    100% { opacity: 0;    transform: none;                       clip-path: inset(0 0 0 0); }
  }
}

/* ==========================================================================
   FLOATING SHAPE FIELD
   Sits in the same fixed layer as the blobs, BEHIND the page content, so the
   frosted cards blur whatever drifts under them and the shapes stay crisp in
   the open gaps between them.

   The layer and every shape are pointer-events: none, permanently. Grabbing is
   done by hit-testing pointer coordinates in script instead, which means a
   shape can never intercept a click meant for a link, a button or a form
   field - the failure mode that makes decorative overlays a usability bug.
   ========================================================================== */
.shape-field {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: strict;
}
.shape {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
  will-change: transform;
  border: 1px solid rgba(16, 143, 70, 0.34);
  background: rgba(127, 212, 160, 0.18);
}
.shape-circle { border-radius: 50%; }
.shape-square { border-radius: 3px; }
/* clip-path cannot take a border, so the triangle carries its own fill only */
.shape-triangle {
  border: 0;
  background: rgba(16, 143, 70, 0.22);
  clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
/* a few read as outlines rather than fills, so the field is not monotonous */
.shape-hollow { background: transparent; border-width: 2px; }

/* while a shape is held */
.shape-held {
  border-color: rgba(16, 143, 70, 0.65);
  background: rgba(127, 212, 160, 0.30);
}
.shape-triangle.shape-held { background: rgba(16, 143, 70, 0.42); }

@media (prefers-reduced-motion: no-preference) {
  .shape { transition: background-color 180ms ease, border-color 180ms ease; }
}

/* The section subhead is the one piece of body copy with no glass beneath it,
   so it composites straight onto the blob field. Measured: with all three
   blobs converged AND a shape border on top, muted grey lands at ~3.7:1 and
   fails. Full ink holds 6.2:1 in that same worst case, so this paragraph
   carries ink and separates from the heading by size and weight instead. */
.section-head p { color: var(--ink); }
.on-dark .section-head p { color: var(--on-dark-mute); }

/* ==========================================================================
   SENSORY ROOM DEMO SLIDERS (Light / Sound)
   Native range inputs, so they are keyboard-operable, announce their value,
   and carry a real label - a bespoke div slider would have none of that.
   The icon reacts only while the control is actively being moved, and resets
   the instant it is released.
   ========================================================================== */

/* Pin the columns explicitly. `grid-row: 1 / -1` looks right but resolves to
   line 1 when the grid has no EXPLICIT rows, so the icon spanned a single row
   and the description auto-placed into the narrow icon column. */
.sensory-list .s-icon { grid-column: 1; grid-row: 1; align-self: start; }
.sensory-list .s-term,
.sensory-list .s-desc,
.sensory-list .s-demo { grid-column: 2; }
.sensory-list .s-icon svg { transform-origin: center; }

.s-demo {
  display: block;
  margin-top: 0.4rem;
  max-width: 22rem;
}
/* No visible label by design - the bare bar is meant to invite a try. The
   accessible name lives on a visually-hidden <label>, so a screen reader still
   hears "Try the light" rather than an anonymous slider. */

/* ---------- range input ---------- */
.s-slider {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 44px;          /* §6 target size; the visible track is thinner */
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.s-slider:focus { outline: none; }   /* the ring is drawn by :focus-visible */

/* track - 4.9:1 against the section, clears the 3:1 UI boundary rule */
.s-slider::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: rgba(201, 214, 205, 0.34);
  border: 1px solid rgba(201, 214, 205, 0.30);
}
.s-slider::-moz-range-track {
  height: 6px;
  border-radius: 999px;
  background: rgba(201, 214, 205, 0.34);
  border: 1px solid rgba(201, 214, 205, 0.30);
}
.s-slider::-moz-range-progress {
  height: 6px;
  border-radius: 999px;
  background: var(--accent-dark);
}

/* thumb - white on the deep green reads at 15.9:1 */
.s-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 24px;
  height: 24px;
  margin-top: -10px;      /* centre the 24px thumb on the 6px track */
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--accent-dark);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.s-slider::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--accent-dark);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}
.s-slider:active::-webkit-slider-thumb { background: var(--accent-dark); }
.s-slider:active::-moz-range-thumb { background: var(--accent-dark); }

/* ---------- icon reactions ----------
   Driven from script, not from CSS animation, so the effect can be cut dead on
   release rather than finishing its current cycle. */
.s-icon svg { will-change: transform; }
/* the snap back to rest, applied only for the reset */
.s-icon.is-resetting svg { transition: transform 260ms cubic-bezier(0.22, 0.61, 0.36, 1); }
@media (prefers-reduced-motion: reduce) {
  .s-icon.is-resetting svg { transition: none; }
}

/* ==========================================================================
   SEGMENT CHIP SHIMMER  (Hospitality / Public sector / Commercial estates)
   A green highlight travels continuously around each chip's outline.

   Built as a masked conic-gradient ring rather than an animated border:
   border-image cannot follow a rounded corner, and animating box-shadow
   repaints every frame. This composites on the GPU and leaves the chip
   interior fully transparent, so the video still shows through.

   The rotation is an infinite ambient animation, so it is gated on
   prefers-reduced-motion; reduced-motion users get the same ring, held still.
   ========================================================================== */
@property --shimmer-angle {
  syntax: "<angle>";
  initial-value: 0deg;
  inherits: false;
}

.segments li {
  position: relative;
  isolation: isolate;
  /* the shimmer ring replaces the old uneven 3px left edge - a highlight
     travelling around a border of two different weights reads as a glitch */
  border: 1px solid rgba(201, 214, 205, 0.34);
}

@supports ((mask-composite: exclude) or (-webkit-mask-composite: xor)) {
  .segments li::after {
    content: "";
    position: absolute;
    inset: -1px;                     /* sit on the border, not inside it */
    border-radius: inherit;
    padding: 1.5px;                  /* ring thickness */
    pointer-events: none;
    z-index: 1;
    background: conic-gradient(
      from var(--shimmer-angle),
      rgba(127, 212, 160, 0.20)   0deg,
      rgba(127, 212, 160, 0.20) 232deg,
      rgba(127, 212, 160, 0.85) 288deg,
      rgba(224, 255, 238, 1.00) 306deg,
      rgba(127, 212, 160, 0.85) 324deg,
      rgba(127, 212, 160, 0.20) 356deg,
      rgba(127, 212, 160, 0.20) 360deg
    );
    /* punch out the middle so only the ring paints */
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
            mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
            mask-composite: exclude;
  }

  @media (prefers-reduced-motion: no-preference) {
    .segments li::after { animation: shimmer-travel 3.6s linear infinite; }
    /* offset each chip so the three do not pulse in lockstep */
    .segments li:nth-child(2)::after { animation-delay: -1.2s; }
    .segments li:nth-child(3)::after { animation-delay: -2.4s; }
  }

  @keyframes shimmer-travel {
    to { --shimmer-angle: 360deg; }
  }
}

/* ==========================================================================
   CTA ATTENTION NUDGE
   A short shake on the "Get a free audit" buttons every few seconds.

   WCAG 2.2.2 (Pause, Stop, Hide, Level A) covers motion that starts
   automatically and runs for more than five seconds - an endless loop would
   need a visible pause control sitting next to the button. Instead the nudge
   is BOUNDED: a handful of short shakes, then it stops for good. Total motion
   stays well under the threshold, so no pause affordance is required and the
   page never nags.

   Position only - no luminance change - so WCAG 2.3.1 (flashing) is not in
   play either.
   ========================================================================== */
@keyframes cta-nudge {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg); }
  10%  { transform: translate3d(-3px, 0, 0) rotate(-0.7deg); }
  22%  { transform: translate3d(3px, 0, 0) rotate(0.7deg); }
  34%  { transform: translate3d(-2.4px, 0, 0) rotate(-0.5deg); }
  46%  { transform: translate3d(2.4px, 0, 0) rotate(0.5deg); }
  58%  { transform: translate3d(-1.4px, 0, 0) rotate(-0.3deg); }
  70%  { transform: translate3d(1.4px, 0, 0) rotate(0.3deg); }
  82%  { transform: translate3d(-0.6px, 0, 0); }
  100% { transform: translate3d(0, 0, 0) rotate(0deg); }
}

@media (prefers-reduced-motion: no-preference) {
  .cta-nudge.is-nudging { animation: cta-nudge 700ms cubic-bezier(0.36, 0.07, 0.19, 0.97) both; }
}
/* hovering or focusing means the button has already been found - stop moving */
.cta-nudge:hover, .cta-nudge:focus-visible { animation: none !important; }

/* ==========================================================================
   HERO PANEL CURSOR TILT
   The credential panel leans slightly toward the pointer. Perspective lives on
   the parent; the panel itself only carries the rotation, so the tilt composites
   without touching layout.
   ========================================================================== */
.hero-grid { perspective: 1100px; }
.hero-panel {
  transform-style: preserve-3d;
  will-change: transform;
}

/* ==========================================================================
   WHATSAPP CARD
   One focusable link wrapping the mark and the copy. The brand mark is
   aria-hidden because the visible text already names the destination -
   otherwise a screen reader announces the logo and the title twice.
   ========================================================================== */
.wa-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem;
  text-decoration: none;
  color: var(--ink);
  border-radius: var(--radius);
  background: var(--glass-light);
  border: 1px solid var(--glass-light-edge);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
          backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.9);
  position: relative;
  overflow: hidden;
}
/* accent spine, matching the service cards */
.wa-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: #25D366;
}
.wa-mark { flex: none; display: block; line-height: 0; }
.wa-mark svg { display: block; width: 64px; height: 64px; }

.wa-copy { display: grid; gap: 0.15rem; }
.wa-title {
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  font-size: var(--step-0);
  color: var(--ink);
  text-decoration: underline;          /* it is a link - say so */
  text-underline-offset: 0.18em;
  text-decoration-thickness: 2px;
}
.wa-number { font-size: var(--step-0); color: var(--ink); }
.wa-note { font-size: var(--step--1); color: var(--ink-muted); }

.wa-card:hover { background: rgba(255, 255, 255, 0.84); color: var(--ink); }
.wa-card:hover .wa-title { color: var(--accent-deep); }

@media (hover: hover) and (pointer: fine) {
  .wa-card { transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), background-color 300ms ease; }
  .wa-card:hover {
    transform: translate3d(0, -4px, 0);
    transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1), background-color 300ms ease;
  }
  @media (prefers-reduced-motion: reduce) {
    .wa-card, .wa-card:hover { transition: none; transform: none; }
  }
}

/* ==========================================================================
   BLOG
   Reuses the glass surfaces and wash from the home page so the section reads
   as the same site rather than a bolted-on subdomain.
   ========================================================================== */
/* the inner pages have no video hero, so the header is solid from the start */
.page-blog .site-header,
.page-post .site-header { position: sticky; }
.page-blog main,
.page-post main { padding-top: 4.75rem; }

.blog-head { padding-bottom: 0; }
.blog-head h1 { font-size: var(--step-3); position: relative; padding-top: 1.25rem; }
.blog-head h1::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 3.5rem; height: 5px;
  background: var(--accent);
}
.blog-list { padding-top: clamp(2rem, 5vw, 3rem); }

.post-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: 1fr;
}
@media (min-width: 52rem) { .post-grid { grid-template-columns: repeat(2, 1fr); } }

.post-card {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1.6rem 1.5rem 1.75rem;
  background: var(--glass-light);
  border: 1px solid var(--glass-light-edge);
  border-radius: var(--radius);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
          backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  box-shadow: var(--glass-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.9);
}
.post-card::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: var(--accent);
}
/* The anchor IS the card, rather than a stretched pseudo-element over it.
   With the stretched-link trick the hit area covers the card but the focus
   ring only draws around the title, so keyboard users get an indicator that
   does not match the target. */
.post-card { text-decoration: none; color: var(--ink); }
.post-card-title {
  font-size: var(--step-1);
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 2px;
}
.post-card:hover .post-card-title { color: var(--accent-deep); }

/* standalone navigation link, so it gets a real target rather than inline size */
.back-link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.25rem 0.1rem;
}
.post-card-desc { color: var(--ink-muted); margin: 0; }

.post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: var(--step--1);
  color: var(--ink-muted);
}
/* a drawn separator rather than a typed middot */
.post-meta-sep { width: 4px; height: 4px; border-radius: 50%; background: var(--line-strong); }

.post-tags { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-top: auto; padding-top: 0.85rem; }
.post-tags li {
  font-size: var(--step--1);
  color: var(--accent-text);
  border: 1px solid rgba(16, 143, 70, 0.34);
  border-radius: 999px;
  padding: 0.15rem 0.65rem;
}
.post-tags-foot { margin-top: 1.75rem; }
.post-empty { color: var(--ink-muted); }

@media (hover: hover) and (pointer: fine) {
  .post-card { transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1), background-color 300ms ease; }
  .post-card:hover,
  .post-card:focus-visible {
    transform: translate3d(0, -6px, 0);
    background: rgba(255, 255, 255, 0.84);
    transition: transform 420ms cubic-bezier(0.34, 1.56, 0.64, 1), background-color 300ms ease;
  }
  @media (prefers-reduced-motion: reduce) {
    .post-card, .post-card:hover { transition: none; transform: none; }
  }
}

/* ---------- single post ---------- */
.post-header { max-width: 46rem; }
.post-back { font-size: var(--step--1); margin-bottom: 1.25rem; }
.post-header h1 { font-size: var(--step-3); margin-bottom: 0.85rem; }
.post-header .post-meta { margin-bottom: 1.1rem; }
.post-lede { font-size: var(--step-1); line-height: 1.55; color: var(--ink-muted); }

.post-body {
  max-width: 46rem;
  margin-top: 2rem;
  font-size: var(--step-0);
}
.post-body > * + * { margin-top: 1.1rem; }
.post-body h2 { font-size: var(--step-2); margin-top: 2.25rem; }
.post-body h3 { font-size: var(--step-1); margin-top: 1.85rem; }
.post-body h4 { font-size: var(--step-0); margin-top: 1.5rem; }
.post-body p { color: var(--ink); }
.post-body a { text-underline-offset: 0.18em; text-decoration-thickness: 2px; }
.post-body .post-list { list-style: disc; padding-left: 1.35rem; }
.post-body ol.post-list { list-style: decimal; }
.post-body .post-list li + li { margin-top: 0.45rem; }
.post-body blockquote {
  border-left: 4px solid var(--accent);
  padding: 0.35rem 0 0.35rem 1.25rem;
  margin-left: 0;
}
.post-body blockquote p { font-size: var(--step-1); line-height: 1.5; color: var(--ink); }
.post-body hr { border: 0; border-top: 1px solid var(--line); margin-block: 2rem; }
.post-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.94em;
  background: rgba(16, 143, 70, 0.10);
  border: 1px solid rgba(16, 143, 70, 0.20);
  border-radius: 4px;
  padding: 0.1em 0.35em;
}
.post-body pre {
  overflow-x: auto;                 /* wide code scrolls inside its own box */
  background: var(--paper-3);
  color: var(--on-dark);
  border-radius: 10px;
  padding: 1rem 1.1rem;
}
.post-body pre code { background: none; border: 0; padding: 0; color: inherit; }

/* ==========================================================================
   MULTI-PAGE CHROME
   The home page keeps the video hero and its clear-to-solid header. Every
   other page (services, about, contact) has no video, so the header is solid
   from the first paint and the main content clears the fixed bar - the same
   treatment the blog pages already use.
   ========================================================================== */
.page-inner .site-header { position: sticky; }
.page-inner main { padding-top: 4.75rem; }

/* a plain page intro where there is no hero to carry it */
.page-intro { background: transparent; padding-bottom: 0; }
.page-intro .shell { max-width: 52rem; }
.page-intro h1 {
  font-size: var(--step-3);
  position: relative;
  padding-top: 1.25rem;
}
.page-intro h1::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 3.5rem; height: 5px;
  background: var(--accent);
}
.page-intro .lede { margin-top: 1.1rem; }

/* current page marker in the nav */
.nav-list a[aria-current="page"] {
  color: var(--accent-deep);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}
.site-header.is-clear .nav-list a[aria-current="page"] { color: var(--on-dark); }

/* ==========================================================================
   FLOATING WHATSAPP BUTTON
   Present on every page. It is the primary contact route the client asked for,
   so it is always in reach without scrolling. A real <a> to wa.me - no script,
   works with JS disabled. The label is visible from the small "pill" width up;
   below that it collapses to the mark alone with a visually-hidden name.
   ========================================================================== */
.wa-float {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right));
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 90;                 /* under the header (100) and skip-link (200) */
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 3.5rem;
  padding: 0.5rem 1.15rem 0.5rem 0.6rem;
  border-radius: 999px;
  background: #075E54;          /* WhatsApp dark green — white label 7.4:1, AA */
  color: #fff;
  text-decoration: none;
  font-weight: 600;
  font-size: var(--step--1);
  box-shadow: 0 6px 20px -4px rgba(12, 26, 18, 0.45),
              0 2px 6px -2px rgba(12, 26, 18, 0.3);
  border: 2px solid rgba(255, 255, 255, 0.22);
}
.wa-float:hover { background: #054b43; color: #fff; }
.wa-float:focus-visible { outline-color: var(--paper); }
.wa-float .wa-float-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.5rem; height: 2.5rem;
  border-radius: 50%;
  background: #25D366;
}
.wa-float .wa-float-mark svg { width: 1.6rem; height: 1.6rem; display: block; }
@media (max-width: 30rem) {
  .wa-float { padding: 0.5rem; gap: 0; }
  .wa-float .wa-float-label {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}
@media (prefers-reduced-motion: no-preference) {
  .wa-float { transition: background-color 140ms ease, transform 200ms ease; }
  .wa-float:hover { transform: translateY(-2px); }
}
/* keep the last stacked element on a page clear of the button */
.site-footer { padding-bottom: 5rem; }

/* ==========================================================================
   CHANGING PLACES - home page highlight band
   A short, dark band that trails to the full section on the services page.
   Reuses the alliance surface so it reads as the same material.
   ========================================================================== */
.cp-band { background: var(--paper-3); color: var(--on-dark); }
.cp-band h2, .cp-band h3 { color: var(--on-dark); }
.cp-inner { display: grid; gap: 1.5rem; max-width: 60rem; }
.cp-inner .lede { color: var(--on-dark-mute); }
.cp-points {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  margin-top: 0.5rem;
}
.cp-points li {
  border: 1px solid rgba(201, 214, 205, 0.34);
  border-left: 3px solid var(--accent-dark);
  padding: 0.35rem 0.8rem;
  font-size: var(--step--1);
  color: var(--on-dark-mute);
  border-radius: 999px;
}
.cp-actions { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 0.5rem; }

/* ==========================================================================
   CONTACT PAGE
   WhatsApp leads. The email form is still here for anyone who prefers it, but
   it is folded into a <details> so it does not compete with the primary route.
   ========================================================================== */
.contact-lead { background: transparent; }
.contact-lead .shell { max-width: 52rem; }
.wa-card.wa-card-lead { padding: 1.6rem; gap: 1.25rem; margin-top: 1.5rem; }
.wa-card.wa-card-lead .wa-mark svg { width: 72px; height: 72px; }
.wa-card.wa-card-lead .wa-title { font-size: var(--step-1); }

.contact-routes { margin-top: 2rem; }

.form-fallback {
  margin-top: 2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--glass-light);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
          backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  overflow: hidden;
}
.form-fallback > summary {
  cursor: pointer;
  padding: 1.1rem 1.35rem;
  font-weight: 600;
  font-family: "Montserrat SemiBold", system-ui, sans-serif;
  list-style-position: inside;
}
.form-fallback > summary:hover { color: var(--accent-deep); }
.form-fallback[open] > summary { border-bottom: 1px solid var(--line); }
.form-fallback .form-card {
  border: 0;
  border-radius: 0;
  background: transparent;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  box-shadow: none;
}
.form-fallback .form-card::before { display: none; }

/* the shape layer is home-only now, but keep it a touch quieter there too */
.shape { opacity: 0.72; }

/* ==========================================================================
   LANGUAGE SWITCH
   Sits immediately after the brand, so it is the first thing on the leading
   edge of the header after the logo — top-left in English, and top-right in
   Arabic, where the whole header mirrors. It carries the auto margin that
   used to live on .brand, which is what pushes the nav to the far edge.

   It is a real link to the mirrored page, not a script toggle: it works with
   JavaScript off, it is crawlable, and each language keeps its own URL so
   Arabic pages can rank on their own.
   ========================================================================== */
.lang-switch {
  flex: none;
  margin-inline-end: auto;
  display: inline-flex;
  align-items: center;
  min-height: 2.25rem;
  padding: 0.3rem 0.8rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
}
.lang-switch:hover {
  color: var(--accent-deep);
  border-color: var(--ink);
  background: var(--paper-2);
}
.site-header.is-clear .lang-switch {
  color: var(--on-dark);
  border-color: rgba(255, 255, 255, 0.5);
}
.site-header.is-clear .lang-switch:hover {
  color: var(--on-dark);
  background: rgba(255, 255, 255, 0.14);
  border-color: var(--paper);
}
@media (max-width: 26rem) {
  .lang-switch { padding: 0.3rem 0.6rem; }
}

/* ==========================================================================
   ARABIC / RIGHT-TO-LEFT
   The Arabic pages are served from /ar with dir="rtl" on <html>. Flexbox and
   grid mirror on their own; everything below is the set of rules that pin a
   physical side (left/right) and therefore has to be flipped by hand.
   ========================================================================== */
[lang="ar"], [lang="ar"] h1, [lang="ar"] h2, [lang="ar"] h3,
[lang="ar"] .brand-name, [lang="ar"] .stat-num, [lang="ar"] .partner-name,
[lang="ar"] .proof-list dt, [lang="ar"] .footer-tag {
  /* Public Sans and Montserrat carry no Arabic glyphs, so name the system
     Arabic faces explicitly rather than letting the browser pick a fallback
     per-glyph, which mixes weights mid-word. */
  font-family: "SF Arabic", "Geeza Pro", "Noto Naskh Arabic", "Noto Sans Arabic",
               "Segoe UI", Tahoma, system-ui, sans-serif;
  letter-spacing: 0;                 /* negative tracking breaks Arabic joins */
}
[lang="ar"] h1, [lang="ar"] h2, [lang="ar"] h3 { line-height: 1.35; }
[lang="ar"] body, [lang="ar"] p { line-height: 1.85; }   /* Arabic needs more */

[dir="rtl"] .skip-link { left: auto; right: var(--gutter); }

[dir="rtl"] .hero-watermark { right: auto; left: -6%; transform: scaleX(-1); }

[dir="rtl"] .video-toggle { right: auto; left: var(--gutter); }
@media (max-width: 40rem) {
  [dir="rtl"] .video-toggle { left: auto; right: var(--gutter); }
}

/* accent spines and section rules */
[dir="rtl"] .card::before,
[dir="rtl"] .post-card::before,
[dir="rtl"] .wa-card::before { left: auto; right: 0; }
[dir="rtl"] .section-head h2::before,
[dir="rtl"] .bay > .shell > h2::before,
[dir="rtl"] .page-intro h1::before,
[dir="rtl"] .blog-head h1::before { left: auto; right: 0; }

/* lists and quotes */
[dir="rtl"] .cp-fixtures,
[dir="rtl"] .post-body .post-list,
[dir="rtl"] .error-summary ul { padding-left: 0; padding-right: 1.35rem; }
[dir="rtl"] .post-body blockquote {
  border-left: 0;
  border-right: 4px solid var(--accent);
  padding: 0.35rem 1.25rem 0.35rem 0;
  margin-left: 0;
  margin-right: 0;
}
[dir="rtl"] .cp-points li,
[dir="rtl"] .segments li { border-left-width: 1px; border-right-width: 3px; }

/* the floating WhatsApp button moves to the other corner */
[dir="rtl"] .wa-float {
  right: auto;
  left: max(1rem, env(safe-area-inset-left));
  padding: 0.5rem 0.6rem 0.5rem 1.15rem;
}

/* numbers and Latin-script contacts stay LTR inside RTL text */
[dir="rtl"] .wa-number,
[dir="rtl"] .contact-line dd a[href^="tel:"],
[dir="rtl"] .contact-line dd a[href^="mailto:"] {
  direction: ltr;
  unicode-bidi: embed;
  display: inline-block;
}

/* "See how each one works" style links under a section grid */
.section-more { margin-top: 2rem; font-size: var(--step-0); }
.section-more a {
  font-weight: 600;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 2px;
}
.on-dark .section-more a { color: var(--accent-dark); }
