/* ==========================================================================
   RUNOVA MARKETING SITE — one design system for every public page.

   This file is the single source of truth for the marketing site's look.
   It deliberately mirrors the product's own tokens (app/src/styles.css) so the
   website and the app read as one thing.

   RULES
   - After changing this file (or site.js / i18n.js), bump the ?v= number on
     the asset links in ALL seven pages, or browsers keep the old file for up
     to an hour and the deploy looks broken. A test enforces they match.
   - Never hardcode a colour, size, radius or spacing below. Use the tokens.
   - Headings and body are both Plus Jakarta Sans (the "Ember Dawn" theme,
     adopted 2026-08-17). Never go above weight 700 — heavier weights are not
     loaded and render as ugly fake bold.
   - A page title is the same size on every page. A section title is the same
     size on every page. Do not introduce a per-page scale.
   ========================================================================== */

:root {
  /* ---- Type ---- */
  --font-display: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-body: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-arabic: "Cairo", sans-serif;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  /* The 2026-08-18 scale, from docs/redesign-2026-08/DESIGN-SYSTEM.md. Bigger
     and tighter than what was here: the new page's headings are large and
     break where a <br> says, so the type has to carry the page rather than
     sit politely inside it. Every page inherits this, which is the point —
     it is what stops Privacy looking like a different website. */
  --fs-display: clamp(2.25rem, 1.4rem + 2.8vw, 3.75rem);  /* page titles: 36 → 60 */
  --fs-h2: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);          /* section titles: 32 → 52 */
  --fs-h3: clamp(1.3rem, 1.1rem + 0.9vw, 1.85rem);        /* card titles: 21 → 30 */
  --fs-h4: 1.0625rem;                                      /* 17 */
  --fs-lead: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);      /* 17 → 20 hero body */
  --fs-body: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);      /* 16 → 18 */
  --fs-sm: 0.9375rem;                                      /* 15 */
  --fs-meta: 0.875rem;                                     /* 14 */
  --fs-eyebrow: 0.8125rem;                                 /* 13 */

  /* Headline tracking. Negative, and tighter the larger the type gets —
     Plus Jakarta Sans opens up at display sizes and reads loose without it. */
  --tr-display: -0.03em;
  --tr-heading: -0.022em;

  --lh-tight: 1.08;
  --lh-heading: 1.2;
  --lh-body: 1.6;

  /* Two aliases the 2026-08-18 page was written against. Kept rather than
     rewritten across 1,200 lines of its stylesheet: --font is the body face,
     --grey is the body-copy grey.

     (--h1-size and --sub-size used to live here. They existed because the
     hero copy was measured against a photograph in container-query units.
     The photo is gone and the hero is ordinary responsive type now.) */
  --font: var(--font-body);
  --grey: var(--muted);

  /* ---- Surfaces & ink ----
     The 2026-08-18 system. The ink is no longer pure black: it is a near-black
     GREEN, #0e2220, which is what makes the whole page read warm next to the
     orange instead of clinical. The greys lost their blue for the same reason.
     Nothing here is pure white or pure black on purpose.

     --btn is the button fill. It is a shade lighter than the ink so a solid
     pill on a white page has an edge you can see without a border. */
  --bg: #fefefe;
  --paper: #f7f8f7;
  --soft: #f6f7f7;
  --cream: #fffaf5;
  --card: #ffffff;
  --ink: #0e2220;
  --btn: #122825;
  --muted: #565b62;
  --line: #e6e9e8;
  --line-soft: #f0f2f1;
  /* The two dark bands, alternating, from the "why Runova" cards. */
  --deep: #13322a;
  --deep-alt: #0f2a23;

  /* ---- Brand: Ember Dawn orange ----

     THREE oranges, and the difference matters. Same brand colour, three jobs:

       --orange       #fe5c24  the theme's primary. Icons, ticks, glows, tinted
                               panels, borders, big display headings. This is
                               the colour of the product.
       --orange-ink   #cd4a1d  the SAME orange darkened until small text on a
                               white or tinted background is legible. The bright
                               orange only reaches 3.1:1 against the page and
                               3.3:1 inside a tinted pill; readable body text
                               needs 4.5:1. Use this for any orange WORD.
                               (This is Ember Dawn's own accent-foreground.)
       --orange-solid #ce3b06  the same orange darkened until WHITE text sitting
                               on top of it is legible — 4.9:1. Used for the
                               primary button fill. Ember Dawn ships white on
                               #fe5c24, which measures 3.7:1 and fails; this is
                               the same hue, two steps down, so it passes.

     Rule of thumb: an orange ICON or shape can stay --orange (graphics only
     need 3:1, which it clears). An orange WORD cannot. */
  --orange: #fe5c24;
  --orange-ink: #cd4a1d;
  --orange-solid: #ce3b06;
  --orange-solid-hover: #b53005;
  --orange-hover: #ef4f18;
  --orange-tint: #fff1ec;
  --orange-paper: #fff8f5;
  --orange-ring: rgba(254, 92, 36, .16);
  /* Success only (form sent, "good" side of a comparison). Ember Dawn has no
     green, so this is a desaturated one that sits quietly next to the greys —
     it is never a second brand colour. Ticks and checks are ORANGE now. */
  --green: #2f7d63;
  --green-deep: #1f5a47;
  --green-tint: #eaf5f0;
  /* Ember Dawn's chart 4 and chart 5, used only as small icon accents. */
  --gold: #8a5410;
  --gold-tint: #fff4d9;
  --blue: #2b63c4;
  --blue-tint: #eef3fc;
  /* Text on the dark green bands. Warmed to match --deep rather than the flat
     greys that were here when the dark bands were a neutral charcoal. */
  --on-dark: #f2f6f4;
  --on-dark-muted: #a8b8b2;
  --on-dark-line: rgba(242, 246, 244, .18);

  /* ---- Shape ----
     Ember Dawn sets one radius, 1.4rem (22px), and everything else steps off
     it. Noticeably rounder than before: inputs and small chips are soft, cards
     are very soft, buttons stay full pills. */
  --r-xs: 10px;
  --r-sm: 14px;
  --r-md: 18px;
  --r-card: 22px;
  --r-lg: 28px;
  --r-pill: 999px;

  /* ---- Rhythm ---- */
  --container: 1120px;
  --gutter: clamp(1.25rem, 4vw, 2rem);
  --section-y: clamp(5.5rem, 9vw, 10.5rem);
  --nav-h: 72px;

  /* ---- Depth ----
     Ember Dawn is nearly flat: one hairline shadow (1px down, 3px blur, 10%).
     Cards are separated by their border, not by a glow. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);
  --shadow-card: 0 1px 3px rgba(0, 0, 0, .06), 0 10px 28px -22px rgba(0, 0, 0, .14);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .04), 0 14px 28px -14px rgba(0, 0, 0, .1),
                 0 36px 72px -28px rgba(0, 0, 0, .2);
  --shadow-orange: 0 10px 26px -12px rgba(254, 92, 36, .55);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ==========================================================================
   BASE
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

/* scroll-padding-top matters more than it looks. Since the site became one
   page on 2026-08-17 the navigation is anchors, and the header is sticky and
   73px tall — without this, every jump to #pricing or #contact parks that
   section's heading underneath the header, so the visitor lands looking at the
   middle of a section with no idea where they are. It is set from the same
   token the header's height comes from, plus a little air. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1.25rem);
  /* Moved here from <body> on 2026-08-17, as a precaution rather than a fix
     for anything observed. It is only here to stop the hero's soft glows
     widening the page. On <body> the shorthand resolves to "hidden auto",
     which makes body a scroll container of its own, and scroll-padding-top
     above is then set on an element that is no longer the scroller — which in
     some browsers means anchors land underneath the sticky header. On <html>,
     already the scrolling element, it clips the same overflow with no such
     question. Anchors are the whole navigation now, so keep it here. */
  overflow-x: hidden;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: var(--fw-regular);
  -webkit-font-smoothing: antialiased;
}

/* Headings sit at 700. Fredoka read bold at 600; Plus Jakarta Sans does not,
   and the Ember Dawn reference has headings clearly heavier than the body.
   700 is the ceiling — nothing above it is loaded, and the browser would fake
   it. Small labels (eyebrows, tags, chips) stay at 600 on purpose. */
h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-heading);
  letter-spacing: var(--tr-heading);
  margin: 0;
  color: var(--ink);
}

/* The two biggest sizes get the tighter tracking and the tighter leading.
   At 52px the heading-level values read loose and the two lines drift apart. */
h1, h2 { line-height: var(--lh-tight); letter-spacing: var(--tr-display); }

p { margin: 0; }
img, svg { max-width: 100%; display: block; }

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

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

::selection { background: var(--orange-tint); color: var(--ink); }

.skip-link {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translate(-50%, -120%);
  z-index: 200;
  background: var(--ink);
  color: #fff;
  padding: 10px 18px;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  font-size: var(--fs-sm);
  transition: transform .2s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* ==========================================================================
   LAYOUT PRIMITIVES
   ========================================================================== */

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

.container--narrow { max-width: 780px; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(2.5rem, 4vw, 4rem); }

/* Section heading block. Same on every page. */
.section-head {
  max-width: 660px;
  margin-inline: auto;
  text-align: center;
  margin-bottom: clamp(2rem, 3.5vw, 3.25rem);
}
.section-head h2 { font-size: var(--fs-h2); }
.section-head p {
  margin-top: 0.75rem;
  color: var(--muted);
  font-size: var(--fs-body);
}

/* Plain lettered eyebrow. No pill behind it: typography, not another box. */
.eyebrow {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--orange-ink);
  margin-bottom: 1.1rem;
}

.lead {
  font-size: var(--fs-lead);
  color: var(--muted);
  line-height: var(--lh-body);
  max-width: 56ch;
}

.grid { display: grid; gap: clamp(1rem, 2vw, 1.5rem); }

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

.split {
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: center;
}

/* ==========================================================================
   BUTTONS
   ========================================================================== */

/* ONE button, and it is a full pill — 2026-08-18 design system, section 4.
   Dark near-black-green fill, white label, ORANGE arrow that steps forward on
   hover. The inset top highlight is what stops a flat dark pill reading as a
   rectangle with rounded ends; the shadow is soft and deepens on hover with a
   1px lift.

   It used to be an orange fill with white text, which measured 3.7:1 and was
   the reason --orange-solid exists. The dark pill is 15:1 and needs no such
   workaround, so the ONLY orange left on a button is the arrow — a graphic,
   which is allowed at 3:1.

   Sized in rem, not in the hero's cqw. The redesign page defined .btn in cqw
   because the first one sat over the photo, then overrode it back to rem in
   five separate places (the top bar, pricing, the contact panel, the form,
   and the whole phone layout). It is the hero that is the exception, so the
   hero scopes its own sizing under .hero-join and everything else inherits
   a button that works on any page. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  padding: .95rem 1.8rem;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--btn);
  color: #fff;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: var(--fw-semibold);
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .14),
    0 10px 22px -12px rgba(15, 42, 35, .55);
  transition: transform .18s var(--ease), box-shadow .25s var(--ease),
              background-color .2s var(--ease), border-color .18s var(--ease);
}
/* No button label may ever wrap. A pill that has broken onto two lines is the
   single ugliest thing that can happen to this design. */
.btn, .btn > span { white-space: nowrap; }
.btn:hover {
  background: #1b3a2b;
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .18),
    0 16px 30px -14px rgba(15, 42, 35, .7);
}
.btn:active { transform: translateY(0); }

/* .btn-primary is what the header, the mobile menu and 404.html ask for by
   name. It IS the button now, so it adds nothing — kept as a name rather than
   renamed across every page and both languages for no gain. */
.btn-primary { background: var(--btn); color: #fff; }
.btn-primary:hover { background: #1b3a2b; }

.btn-ghost {
  background: var(--card);
  color: var(--ink);
  border-color: var(--line);
  box-shadow: var(--shadow-sm);
}
.btn-ghost:hover { border-color: #cfd6d3; box-shadow: var(--shadow-card); background: var(--card); }

.btn-sm { padding: .7rem 1.15rem; font-size: .9375rem; gap: .5rem; }

/* The arrow is orange on the dark pill and steps forward 3px on hover. On the
   white ghost button there is no dark to sit on, so it takes the ink. */
.btn .ico, .btn svg { width: 17px; height: 17px; flex: none; stroke: var(--orange); }
.btn-sm .ico, .btn-sm svg { width: 15px; height: 15px; }
.btn-ghost .ico, .btn-ghost svg, .btn-quiet .ico, .btn-quiet svg { stroke: var(--ink); }

.btn .ico, .btn svg,
.card-link .ico--arrow-right {
  transition: transform .25s cubic-bezier(.4, 0, .2, 1);
}
.btn:hover .ico, .btn:hover svg,
.card-link:hover .ico--arrow-right { transform: translateX(3px); }
[dir="rtl"] .btn:hover .ico, [dir="rtl"] .btn:hover svg,
[dir="rtl"] .card-link:hover .ico--arrow-right { transform: translateX(-3px); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

@property --x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 120%;
}
.btn-shiny { position: relative; overflow: hidden; isolation: isolate; }
.btn-shiny > * { position: relative; z-index: 2; }
.btn-shiny::before,
.btn-shiny::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  animation: btn-sweep 4.2s cubic-bezier(.42, 0, .35, 1) infinite;
}
.btn-shiny::before {
  z-index: 1;
  background: linear-gradient(100deg,
    transparent calc(var(--x) - 11%),
    rgba(255, 255, 255, .17) calc(var(--x) - 1%),
    rgba(255, 255, 255, .05) calc(var(--x) + 4%),
    transparent calc(var(--x) + 11%));
}
.btn-shiny::after {
  z-index: 3;
  padding: 1px;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, .06) calc(var(--x) - 24%),
    rgba(255, 255, 255, .70) calc(var(--x)),
    rgba(255, 255, 255, .06) calc(var(--x) + 24%));
  -webkit-mask: linear-gradient(#000, #000) content-box, linear-gradient(#000, #000);
          mask: linear-gradient(#000, #000) content-box, linear-gradient(#000, #000);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
}
@keyframes btn-sweep { 0% { --x: 120%; } 55%, 100% { --x: -30%; } }
.btn-shiny:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18),
              0 16px 34px -12px rgba(18, 40, 37, .62);
}
@media (prefers-reduced-motion: reduce) {
  .btn-shiny::before, .btn-shiny::after { animation: none; --x: 50%; }
}

/* ==========================================================================
   HEADER
   ========================================================================== */

/* The bar, from the 2026-08-18 design. Momtaz asked for the navigation
   separately from the hero, so it sits ABOVE the copied section rather than
   inside it. Every page gets this one — that is the whole point of the
   conversion: clicking Privacy used to land on something that looked like a
   different website. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(254, 254, 254, .82);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--line-soft);
  box-shadow: 0 1px 20px -12px rgba(14, 34, 32, .18);
}

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  max-width: 1440px;
  margin: 0 auto;
  padding: 1.4rem clamp(1.25rem, 4vw, 2.5rem);
}

.nav-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: none;
}
/* The logo PNG already contains the wordmark. Never redraw it in markup. */
.nav-logo img { display: block; height: 30px; width: auto; }

.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.4vw, 2.2rem);
}
/* No underline, no sliding bar: the link's LETTERS swap. The stacking is set
   up in site.js and the motion is below. */
.nav-link {
  font-size: .9375rem;
  font-weight: var(--fw-medium);
  color: var(--ink);
  opacity: .78;
  padding-block: 10px;              /* tap target, 44px total */
  transition: opacity .2s var(--ease);
}
.nav-link:hover { opacity: 1; }
.nav-link.is-active { opacity: 1; font-weight: var(--fw-semibold); }

/* ---- The letter swap ----------------------------------------------------
   Each character is a two-high stack of itself; on hover both copies slide up
   by exactly one letter's height, each with its own shuffled delay.

   The second copy is drawn HERE, by CSS, from the data-c attribute. Two real
   copies in the markup made the link read "HHoowwiitt wwoorrkkss" to anything
   that reads text rather than pixels. Do not duplicate the letters. */
.nav-links a .rl,
.footer-col a .rl {
  display: inline-block;
  overflow: hidden;
  height: 1.15em;
  line-height: 1.15;
  vertical-align: bottom;
}
.nav-links a .rl::after,
.footer-col a .rl::after { content: attr(data-c); display: block; }
.nav-links a .rl i, .nav-links a .rl::after,
.footer-col a .rl i, .footer-col a .rl::after {
  display: block;
  font-style: normal;
  transition: transform .6s cubic-bezier(.2, .9, .2, 1);
  transition-delay: var(--d, 0s);
}
.nav-links a:hover .rl i, .nav-links a:hover .rl::after,
.footer-col a:hover .rl i, .footer-col a:hover .rl::after { transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) {
  .nav-links a:hover .rl i, .nav-links a:hover .rl::after,
  .footer-col a:hover .rl i, .footer-col a:hover .rl::after { transform: none; }
}

.bar-right {
  position: relative;                /* the status line hangs off this */
  display: flex;
  align-items: center;
  gap: clamp(.6rem, 1.4vw, 1.1rem);
  flex: none;
}
.bar-login {
  color: var(--ink);
  font-size: .9375rem;
  font-weight: var(--fw-semibold);
}

/* ---- The email capture in the bar --------------------------------------
   Ask for the address at the TOP of the page, not only at the bottom. One
   field and one button sharing a single rounded shell, so it reads as one
   control rather than two.

   Below 1180px the shell goes and the button alone remains: a menu, a
   language switch, a log-in and a two-part control will not fit, and a
   squeezed input is worse than none. */
.join {
  display: flex;
  align-items: center;
  gap: .4rem;
  padding: .25rem .25rem .25rem 1rem;
  background: var(--card);
  border: 1px solid #dfe5e2;
  border-radius: var(--r-pill);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.join:focus-within { border-color: var(--orange); box-shadow: 0 0 0 3px var(--orange-ring); }
.join input {
  width: 17rem;
  padding: .45rem 0;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .9375rem;
  background: none;
  border: 0;
  outline: 0;
}
.join input::placeholder { color: #a7b0ab; }
.join .btn { padding: .5rem .95rem; font-size: .8125rem; gap: .35rem; }
.join .btn svg { width: 14px; height: 14px; }

/* The reply sits UNDER the bar, out of the flow. Inline it widened the row
   and shoved the menu sideways the moment it said anything. */
.join-said {
  position: absolute;
  inset-block-start: calc(100% + .4rem);
  inset-inline-end: 0;
  margin: 0;
  font-size: .8125rem;
  font-weight: var(--fw-semibold);
  white-space: nowrap;
}
.join-said.is-ok { color: var(--green); }
.join-said.is-error { color: #b3261e; }

.join-fallback { display: none; }
@media (max-width: 1180px) {
  .join { display: none; }
  .join-fallback { display: inline-flex; }
}

/* Nothing in the bar may wrap. "How it works", "Log in" and the button label
   were all breaking over two lines and shoving the row out of shape. */
.nav-link, .bar-login, .bar .btn, .join input { white-space: nowrap; }

/* ---- The language coin -------------------------------------------------
   One control with two faces, not two buttons: the face you can see is the
   language you are reading, and pressing it turns the coin over. The text
   swaps at the halfway point, while the card is edge on — site.js handles
   that timing, because swapping on click makes the OLD language visibly
   rotate away, which reads as a glitch rather than a flip. */
.lang-flip {
  --coin: 42px;
  position: relative;
  width: 62px;
  height: var(--coin);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  perspective: 520px;          /* without this the turn is a flat squash */
  flex: none;
}
/* 44px of tap area without a 44px pill in the middle of the bar. */
.lang-flip::after {
  content: "";
  position: absolute;
  inset-inline: -2px;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}

.lang-coin {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform .42s cubic-bezier(.5, 0, .2, 1);
}
.lang-flip.is-turning .lang-coin,
.lang-flip.is-ar .lang-coin { transform: rotateY(180deg); }
/* Turning INTO Arabic and turning back both go the same way round, so the
   coin never appears to unwind the way it came. */
.lang-flip.is-ar.is-turning .lang-coin { transform: rotateY(360deg); }

.lang-face {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border-radius: var(--r-pill);
  background: var(--soft);
  border: 1px solid var(--line);
  color: var(--ink);
  font-size: var(--fs-meta);
  font-weight: var(--fw-semibold);
  -webkit-backface-visibility: hidden;
          backface-visibility: hidden;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.lang-face--ar { transform: rotateY(180deg); }
.lang-face b { font-weight: var(--fw-bold); line-height: 1; }
.lang-flip:hover .lang-face {
  background: var(--card);
  border-color: var(--orange);
}

/* The glyph: a folded card, one panel per script. The panels carry the brand
   — dark on the left, orange on the right — so it reads as Runova's rather
   than a borrowed system icon. */
.lang-ico { width: 17px; height: 17px; flex: none; overflow: visible; }
.lang-panel-l { fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round; }
.lang-panel-r { fill: var(--orange); stroke: var(--orange); stroke-width: 1.6; stroke-linejoin: round; }
.lang-glyph-l { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.lang-glyph-r { fill: none; stroke: #fff; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.lang-flip:hover .lang-panel-r { fill: var(--orange-hover); stroke: var(--orange-hover); }

/* Reduced motion: the coin still turns over, it just does not spin. */
@media (prefers-reduced-motion: reduce) {
  .lang-coin { transition: none; }
}

.nav-burger {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  cursor: pointer;
}
.nav-burger .ico { width: 20px; height: 20px; }

.mobile-menu {
  display: none;
  border-top: 1px solid var(--line-soft);
  background: var(--bg);
  padding: 1rem var(--gutter) 1.5rem;
}
.mobile-menu.is-open { display: block; }
/* :not(.btn) matters — a bare `.mobile-menu a` beats `.btn` on specificity
   and would turn the two buttons into left-aligned blocks. */
.mobile-menu a:not(.btn) {
  display: block;
  padding: 13px 0;
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  border-bottom: 1px solid var(--line-soft);
}
.mobile-menu a.is-active { color: var(--orange-ink); }
.mobile-menu .btn-row { margin-top: 1.25rem; }
.mobile-menu .btn { flex: 1; }

/* ==========================================================================
   HERO
   ========================================================================== */

/* The hero sits on the page background. The whole page is one colour;
   structure comes from type and space, not from banded backgrounds. */
.hero {
  padding-block: clamp(4rem, 8vw, 6.5rem) clamp(4rem, 7vw, 6rem);
  position: relative;
  overflow: hidden;
}
.hero h1 {
  font-size: clamp(2.3rem, 1.35rem + 2.9vw, 3.7rem);
  line-height: 1.08;
  max-width: 16ch;
  text-wrap: balance;
}
.hero .lead { margin-top: 1.3rem; }
.hero .btn-row { margin-top: 2rem; }

@keyframes rise-in {
  from { opacity: 0; transform: translateY(30px); filter: blur(6px); }
  to { opacity: 1; transform: none; filter: blur(0); }
}
[data-rise] {
  animation: rise-in .95s cubic-bezier(0.16, 1, 0.3, 1) both;
  will-change: transform, opacity;
}
[data-rise="2"] { animation-delay: .1s; }
[data-rise="3"] { animation-delay: .2s; }
[data-rise="4"] { animation-delay: .3s; }
[data-rise="5"] { animation-delay: .42s; }

.hero > .container { position: relative; z-index: 1; }

/* ==========================================================================
   CARDS
   ========================================================================== */

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  padding: clamp(1.5rem, 2.5vw, 2rem);
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s var(--ease);
}
.card--hover:hover {
  transform: translateY(-3px);
  border-color: #dcdce4;
  box-shadow: var(--shadow-lift);
}
.card h3 { font-size: var(--fs-h3); }
.card p {
  margin-top: 0.6rem;
  color: var(--muted);
  font-size: var(--fs-sm);
}

/* Bare icons. No tinted tile behind them anywhere on the site. */
.card-icon {
  display: block;
  color: var(--orange);
  margin-bottom: 1rem;
}
.card-icon .ico { width: 26px; height: 26px; stroke-width: 1.75; }

/* Bulleted benefit list inside a card. */
.tick-list {
  list-style: none;
  margin: 1.1rem 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.tick-list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.tick-list .ico {
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 3px;
  color: var(--orange);
}
.tick-list--cross .ico { color: #c9353a; }

/* Two open columns setting one thing against another.

   SHARED, not home-only. It used to live inside the home page's section of
   this file, which meant rebuilding the home page silently stripped the
   styling off the security page's "It does / It does not" block. It lives
   here now. Check web/security.html before touching it. */
.contrast-duo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  margin-top: clamp(2rem, 3.5vw, 3rem);
}

.contrast-col {
  position: relative;
  padding-top: 1.6rem;
}
.contrast-col::before {
  content: "";
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  width: 54px;
  height: 3px;
  border-radius: 3px;
  background: #d4d4dc;
}
.contrast-col--good::before { background: var(--green); }

.contrast-tag {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-meta);
  font-weight: var(--fw-semibold);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.contrast-col--good .contrast-tag { color: var(--green-deep); }

.contrast-col p {
  margin-top: .9rem;
  color: var(--muted);
  font-size: clamp(1.02rem, 1rem + .2vw, 1.15rem);
  line-height: 1.7;
  max-width: 46ch;
}
.contrast-col--good p { color: var(--ink); }

@media (max-width: 900px) {
  .contrast-duo { grid-template-columns: minmax(0, 1fr); }
}

.card-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 1.25rem;
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--orange-ink);
}
.card-link .ico { width: 16px; height: 16px; transition: transform .2s var(--ease); }
.card-link:hover .ico { transform: translateX(3px); }
[dir="rtl"] .card-link .ico { transform: scaleX(-1); }
[dir="rtl"] .card-link:hover .ico { transform: scaleX(-1) translateX(3px); }

/* A cursor that clicks, with a ripple. Used to show capture happening. */
.demo-cursor {
  position: absolute;
  width: 20px;
  height: 20px;
  z-index: 3;
  pointer-events: none;
  color: var(--ink);
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .3));
}
.ripple {
  position: absolute;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid var(--orange);
  transform: translate(-50%, -50%) scale(.4);
  opacity: 0;
  pointer-events: none;
  z-index: 2;
}
.ripple.is-firing { animation: ripple-out 1s var(--ease); }
@keyframes ripple-out {
  0% { transform: translate(-50%, -50%) scale(.4); opacity: .9; }
  100% { transform: translate(-50%, -50%) scale(1.7); opacity: 0; }
}

@keyframes rec-blink { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

@keyframes card-drift {
  from { transform: translateY(0); }
  to { transform: translateY(-7px); }
}

@keyframes shot-drift {
  from { transform: translateY(0); }
  to { transform: translateY(-8px); }
}

/* ---- The shared vignette, used here and by the how-it-works pictures ---- */
.vg {
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
}

.vg-pill {
  margin-inline-start: auto;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: var(--fw-medium);
  white-space: nowrap;
  background: var(--soft);
  color: var(--muted);
}

.vg-pill--live { background: var(--orange-tint); color: var(--orange-ink); }

.vg-step {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 13px;
  border: 1px solid var(--line-soft);
  border-radius: var(--r-sm);
  background: var(--bg);
}

.vg-rec {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  background: var(--orange-tint);
  color: var(--orange-ink);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: var(--fw-medium);
}
.vg-rec i { width: 7px; height: 7px; border-radius: 50%; background: var(--orange); }

/* ---- Built for every team: four open blocks, two to a row ---- */

.hp-section--teams { background: var(--paper); }

.team-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3.25rem) clamp(2rem, 5vw, 4.5rem);
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}

@media (max-width: 900px) {
  
  /* Two department blocks side by side get cramped below this. */
  .team-grid { grid-template-columns: minmax(0, 1fr); }
}

.note-line { margin-top: 1.5rem; }

/* ---- Pricing: one flat statement -------------------------------------------

   The pitch on the left, the price and what it includes on the right, from
   the split-panel spec Momtaz sent on 2026-08-17. It replaced three plan
   cards, two of which could only say "pricing announced after the pilot" —
   a section answering a question nobody asked with information we did not
   have. The FAQ below still answers the future-pricing and larger-company
   questions, and the panel links anyone with those questions to the form.
   --------------------------------------------------------------------------- */

.note-line {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-top: 2rem;
  font-size: var(--fs-sm);
  color: var(--muted);
  text-align: center;
}
.note-line .ico { width: 18px; height: 18px; color: var(--orange); flex: none; }

/* ==========================================================================
   ACCORDION (FAQ)
   ========================================================================== */

/* Open rows divided by hairlines, not a stack of boxes. */
.faq { display: grid; gap: 0; border-block: 1px solid var(--line-soft); }

.faq-item {
  border-bottom: 1px solid var(--line-soft);
  overflow: hidden;
}
.faq-item:last-child { border-bottom: 0; }
.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 21px 2px;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: start;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  transition: color .18s var(--ease);
}
.faq-q:hover { color: var(--orange-ink); }
.faq-q span { flex: 1; }
.faq-q .ico {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--muted);
  transition: transform .25s var(--ease), color .25s var(--ease);
}
.faq-item.is-open .faq-q .ico { transform: rotate(180deg); color: var(--orange); }
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s var(--ease);
}
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }
/* Collapsing to 0fr hides the answer visually but leaves it readable by screen
   readers and keeps the link inside it in the tab order — so the button says
   aria-expanded="false" while the answer is still announced, and a keyboard
   user lands on an invisible link. visibility:hidden fixes both and keeps the
   open/close animation, because it is delayed until the transition finishes. */
.faq-a > div { overflow: hidden; visibility: hidden; transition: visibility 0s .3s; }
.faq-item.is-open .faq-a > div { visibility: visible; transition-delay: 0s; }
@media (prefers-reduced-motion: reduce) { .faq-a > div { transition-delay: 0s; } }
.faq-a p {
  padding: 0 2px 21px;
  color: var(--muted);
  font-size: var(--fs-sm);
  max-width: 62ch;
}

/* ==========================================================================
   FOOTER
   ========================================================================== */

/* Four columns beside the brand, on the quiet grey-green. The links carry the
   same letter swap as the top menu — that pairing is what makes the footer
   read as part of the same page rather than as a sitemap bolted on. */
.site-footer {
  background: var(--paper);
  border-top: 1px solid #eef1ef;
  padding: clamp(3rem, 6vw, 4.5rem) 0 clamp(2rem, 4vw, 2.75rem);
}
.site-footer > .container { max-width: 1180px; }
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(4, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3rem);
}
.footer-brand .nav-logo { margin: 0; }
.footer-brand p {
  max-width: 28ch;
  margin-top: 1.1rem;
  color: var(--muted);
  font-size: .9375rem;
  line-height: 1.6;
}
.footer-col h4 {
  margin-bottom: 1.1rem;
  color: var(--ink);
  font-size: .75rem;
  font-weight: var(--fw-bold);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.footer-col a {
  display: block;
  font-size: .9375rem;
  color: var(--muted);
  /* 10px either side of a 15px line puts every footer link over the 44px
     minimum a finger needs. Do not trim this back to tighten the footer. */
  padding-block: 10px;
  transition: color .2s var(--ease);
}
.footer-col a:hover { color: var(--ink); }
.footer-base {
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: clamp(1.4rem, 2.8vw, 1.9rem);
  border-top: 1px solid #e6eae8;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  font-size: .875rem;
  color: #97a29c;
}

/* ==========================================================================
   PROSE — legal and long-form pages
   ========================================================================== */

.prose { max-width: 72ch; }
.prose h2 {
  font-size: var(--fs-h3);
  margin-top: 2.5rem;
  margin-bottom: 0.75rem;
}
.prose h2:first-child { margin-top: 0; }
.prose p, .prose li { color: var(--muted); font-size: var(--fs-sm); }
.prose p + p { margin-top: 0.9rem; }
.prose ul { margin: 0.9rem 0 0; padding-inline-start: 1.25rem; display: grid; gap: 8px; }
.prose a { color: var(--orange-ink); text-decoration: underline; text-underline-offset: 3px; }
.prose strong { font-weight: var(--fw-semibold); color: var(--ink); }
.prose-updated {
  font-size: var(--fs-meta);
  color: var(--muted);
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--line-soft);
  line-height: 1.8;
}

/* A legal page is a title followed immediately by a document — there is no lead
   paragraph or button row to fill the hero. With the standing hero padding
   (96px below the title) plus the section's own 58px above the text, that left
   a ~154px void between "Privacy Policy" and the first line, which read as a
   broken page rather than as breathing room. These two rules close it from both
   sides; the space above the title is untouched. */
.hero--legal { padding-block-end: clamp(1.25rem, 2.5vw, 2rem); }
.hero--legal + .section { padding-block-start: clamp(1.25rem, 2.5vw, 2rem); }

/* Long legal documents: a two-column contents list, and anchor targets that
   land below the sticky header instead of underneath it. */
.legal-toc {
  list-style: none;
  margin: 0.9rem 0 0;
  padding: 0;
  columns: 2;
  column-gap: 2rem;
}
.legal-toc li { break-inside: avoid; }
.legal-toc a {
  display: block;
  padding-block: 5px;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.legal-toc a:hover { color: var(--orange-ink); }
/* Anything an in-page link can land on has to clear the sticky header, or the
   heading it jumped to sits underneath it. The contact form (#send) and the
   department blocks on Solutions are the live cases. */
.prose h2[id],
.ct-panel[id],
.team-block[id] { scroll-margin-top: calc(var(--nav-h) + 16px); }
@media (max-width: 600px) {
  .legal-toc { columns: 1; }
}

.contact-form {
  display: grid;
  gap: 1.15rem;
  margin-top: 1.6rem;
}

.field { display: grid; gap: 8px; }
.field label {
  font-size: var(--fs-meta);
  font-weight: var(--fw-medium);
}

/* Honeypot: parked off-screen, never display:none — bots skip hidden fields. */
.hp { position: absolute; inset-inline-start: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status { font-size: var(--fs-sm); color: var(--muted); margin: 0; }
.form-status.is-ok { color: var(--green-deep); }
.form-status.is-error { color: #c9353a; }
.form-status a { color: var(--orange-ink); font-weight: var(--fw-medium); }

.field-error {
  display: block;
  min-height: 0;
  margin-top: 6px;
  font-size: var(--fs-meta);
  line-height: 1.4;
  color: #c9353a;
}
.field-error:empty { display: none; }


@media (max-width: 600px) {
  
  .contact-form .btn-row { flex-direction: column; align-items: stretch; }
}
/* ==========================================================================
   SCROLL REVEAL — subtle, and switched off for reduced motion.
   ========================================================================== */

/* Content is visible before and after the enhancement runs. The animation is
   applied only when a section is revealed, so a missed observer callback or
   a background browser tab can never leave real content blank. */
.js-anim .reveal {
  opacity: 1;
  transform: none;
}
.js-anim .reveal.is-revealed {
  animation: reveal-in .6s var(--ease) both;
}
@keyframes reveal-in {
  from { opacity: 0; transform: translateY(26px); filter: blur(5px); }
  to { opacity: 1; transform: none; filter: blur(0); }
}
.reveal[data-delay="1"] { animation-delay: .08s; }
.reveal[data-delay="2"] { animation-delay: .16s; }
.reveal[data-delay="3"] { animation-delay: .24s; }
.reveal[data-delay="4"] { animation-delay: .32s; }

/* ==========================================================================
   ARABIC / RTL
   ========================================================================== */

body.is-arabic {
  font-family: var(--font-arabic);
  --fs-body: 1.0625rem;
}
body.is-arabic h1,
body.is-arabic h2,
body.is-arabic h3,
body.is-arabic h4,
body.is-arabic .btn,
body.is-arabic .eyebrow,
body.is-arabic .faq-q,
body.is-arabic .nav-logo span {
  font-family: var(--font-arabic);
  font-weight: var(--fw-bold);
  letter-spacing: 0;
}
body.is-arabic .lead,
body.is-arabic p { line-height: 1.85; }

@media (max-width: 1000px) {
  .footer-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .footer-brand { grid-column: 1 / -1; }
  
}

@media (max-width: 900px) {
  .nav-links, .bar-login { display: none; }
  /* The call to action moves into the burger menu. Keeping it here overflows
     the bar on a phone and pushes the menu button off screen. */
  .bar-right > .btn { display: none; }
  .nav-burger { display: flex; }
  .bar { padding: 1rem 1.1rem; }
  .nav-logo img { height: 25px; }
  .split { grid-template-columns: minmax(0, 1fr); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  
}

@media (max-width: 700px) {
  :root { --nav-h: 64px; }
  .grid-3, .grid-4, .grid-2 { grid-template-columns: minmax(0, 1fr); }
  
  
  
  
  
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .btn-row .btn { flex: 1 1 100%; }
  .hero .btn-row .btn { flex: 1 1 auto; }
}

@media (max-width: 460px) {
  
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .reveal { opacity: 1; transform: none; }
  
}

@media print {
  .site-header, .site-footer, .cta-linear { display: none; }
}

/* ==========================================================================
   HOME PAGE

   Built to a design Momtaz supplied as an image. Section order is fixed:
   hero, why join the pilot, how it works, documentation comparison, teams,
   what the pilot includes, closing panel.

   Everything here is prefixed `hp-` so it cannot collide with the shared
   patterns above. The page uses the same tokens as every other page; no new
   colours, radii or type sizes are invented below.
   ========================================================================== */

.hp-hero {
  position: relative;
  overflow: hidden;
  padding-block: clamp(4.5rem, 8vw, 8rem) clamp(3.5rem, 6vw, 6rem);
}

.hp-hero-copy {
  text-align: center;
  max-width: 50rem;
  margin-inline: auto;
}

@media (min-width: 901px) {
  
  .hp-hero-copy { text-align: start; max-width: none; margin-inline: 0; }
  
  .hp-hero-copy h1 { max-width: 15ch; margin-inline: 0; }
  .hp-hero-copy .lead { margin-inline: 0; max-width: 46ch; }
  .hp-hero-copy .btn-row { justify-content: flex-start; }
  
}

.hp-hero-copy h1 {
  /* Bigger than it was, because centring freed the width. max-width is now
     what governs the wrap (the copy is no longer inside a narrow column), so
     these two values together decide the line count: ~18ch holds it to two
     lines on a laptop and three on a phone. */
  font-size: clamp(2.5rem, 1.15rem + 4.6vw, 4.6rem);
  line-height: 1.03;
  letter-spacing: -0.035em;
  max-width: 20ch;
  margin-inline: auto;
  text-wrap: balance;
}
.hp-hero-copy .lead {
  margin: 1.5rem auto 0;
  max-width: 52ch;
  text-wrap: balance;
}
/* The typed line: the sentence is real text (the span carries it), and
   motion.js retypes it letter by letter with the caret. */
.hp-typed {
  margin-top: 1.4rem;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  color: var(--orange-ink);
  min-height: 1.5em;
}

.hp-hero-copy .btn-row { margin-top: 2.4rem; justify-content: center; }
.hp-hero-copy .btn .ico { width: 17px; height: 17px; }

/* ---- Hero stage ------------------------------------------------------------

   The product sits BESIDE the sentence now, not under it, and it is three
   overlapping pieces rather than one flat card: the process, the recorder
   that made it, and a small result. Momtaz did not like the old placement or
   the scroll animation that opened it, and a hero should be finished the
   moment it arrives.
   ---------------------------------------------------------------------------- */

.hp-stage {
  position: relative;
  /* Room for the two pieces that hang off the main card. */
  padding: 1.75rem 1.5rem 2.25rem;
}
.hp-stage-main {
  position: relative;
  z-index: 1;
  transform: perspective(1400px) rotateY(var(--mo-ry, -4deg)) rotateX(var(--mo-rx, 2deg));
  transition: transform .5s var(--ease);
  will-change: transform;
}
.hp-stage-main .vg { box-shadow: var(--shadow-lift); }
.hp-stage-main.is-tracking { transition: none; }

/* The recorder that made it, tucked over the top corner. */
.hp-stage-chip {
  position: absolute;
  z-index: 2;
  inset-block-start: 0;
  inset-inline-end: .25rem;
  padding: 7px 9px;
  border-radius: var(--r-pill);
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-card);
}
.hp-stage-chip .vg-rec { background: transparent; padding: 0; }
.hp-stage-chip b { font-weight: var(--fw-semibold); font-variant-numeric: tabular-nums; }

.sec-more { margin-top: clamp(1.5rem, 3vw, 2rem); }
.sec-more a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  font-size: var(--fs-sm);
  color: var(--orange-ink);
  transition: gap .2s var(--ease);
}
.sec-more a:hover { gap: 12px; }
.sec-more .ico { width: 16px; height: 16px; }

/* Each home section has its own visual rhythm. The extra space is deliberate:
   these are separate ideas, not one continuous grid of cards. */
.hp-section.section--tight {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(6.5rem, 10vw, 10rem);
}
.hp-section > .container { position: relative; z-index: 1; }

/* The numbered rail above the cards, on the reference Momtaz sent
   (2026-08-17). The step number used to sit inside each card beside its
   icon; pulling it out into a rail says "three steps, in this order" before
   the eye reaches any of the text. */
.hp-rail {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 44rem;
  margin: clamp(2rem, 4vw, 3rem) auto 0;
}

.hp-flow {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
  margin: clamp(1.5rem, 2.5vw, 2rem) 0 0;
  padding: 0;
  list-style: none;
  align-items: stretch;
}
.hp-flow-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-sm);
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}
/* Momtaz asked for the cards to expand a little on hover. Scale rather than
   size, so the three keep their grid and nothing below them shifts. */
.hp-flow-card:hover,
.hp-flow-card:focus-within {
  transform: translateY(-5px) scale(1.02);
  box-shadow: var(--shadow-lift);
  z-index: 2;
}

.hp-flow-card h3 { font-size: var(--fs-h4); }

/* Teams sit on a quiet paper band so the open columns read as one group. */
.hp-section--teams { background: var(--paper); }

@media (prefers-reduced-motion: no-preference) {
  
  
  
  @keyframes hp-icon-float { to { transform: translateY(-5px) rotate(2deg); } }
}

.hp-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: clamp(1.1rem, 2vw, 1.4rem) 0 0;
  transition: transform .22s var(--ease);
}
.hp-card:hover {
  transform: translateY(-2px);
}

.hp-card h3 { font-size: var(--fs-h4); }
.hp-card p {
  margin-top: .45rem;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.65;
}

/* Tinted tile behind an icon. Orange and green alternate so neither floods
   the page; the brief keeps green to a supporting role. */
.hp-tile {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  transition: transform .22s var(--ease);
}
.hp-tile .ico { width: 23px; height: 23px; stroke-width: 1.75; }

.hp-tile--green { background: var(--green-tint); color: var(--green-deep); }
.hp-tile--gold { background: var(--gold-tint); color: var(--gold); }
.hp-tile--blue { background: var(--blue-tint); color: var(--blue); }
.hp-card:hover .hp-tile { transform: translateY(-2px); }

/* ---- Documentation vs Runova ---- */

.hp-vs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 5vw, 4rem);
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  align-items: stretch;
}
.hp-vs-card {
  /* Boxed, on Momtaz's own reference (2026-08-17). This is the ONE place on
     the page allowed a box: the section is a side-by-side comparison, and a
     comparison needs an edge round each side or the two columns read as one
     list. Every other section stays open. */
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  overflow: hidden;
}

/* ---- Teams: heading on the left, four cards on the right ---- */

/* The heading column needs a REAL minimum, not just a fraction: at .52fr of a
   1120px container it resolved to ~277px, which is narrower than the heading's
   own two nowrap lines — so the words ran straight over the first card. The
   min below is sized to the largest the type can get; the breakpoint that
   stacks this band is set to match it. */
/* Heading above the four teams, not beside them.

   It used to take a 400px minimum column of its own, leaving the four cards
   about half the row between them. At that width the card titles broke —
   "Human Resources" and "Customer Support" each went to two lines — and the
   body text ran at four words a line. Stacking gives every card the same
   room the rest of the page's cards get, and matches how every other section
   on this page is laid out. */
.hp-teams-head {
  text-align: center;
  font-size: clamp(1.55rem, 1rem + 1.7vw, 2.15rem);
  line-height: 1.18;
  max-width: none;
  text-wrap: balance;
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
/* Two lines by design. They only refuse to wrap once there is room for the
   longer of the two; below that the phone rules let them break normally. */
.hp-teams-head span { display: block; white-space: nowrap; }

.hp-sec-more {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  font-size: var(--fs-sm);
}
.hp-sec-more a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--orange-ink);
  font-weight: var(--fw-medium);
}
.hp-sec-more a:hover { color: var(--orange-solid); }
.hp-sec-more .ico { width: 17px; height: 17px; }
[dir="rtl"] .hp-sec-more .ico { transform: scaleX(-1); }

@media (max-width: 900px) {
  /* The hero is centred at every width, so nothing has to unstack. The
     headline just gives up its 18ch cap and takes the column. */
  .hp-hero-copy h1 { max-width: 100%; }
  
  .hp-vs { grid-template-columns: minmax(0, 1fr); }

  /* Stacked, the order of the cards says what the rail said. */
  .hp-flow { grid-template-columns: minmax(0, 1fr); }
  .hp-rail { display: none; }

  
}

@media (max-width: 700px) {
  
  
  
  
  .hp-hero-copy .btn-row .btn { flex: 1 1 100%; }
  
  .hp-teams-head span { white-space: normal; }
}

/* ==========================================================================
   MOTION LAYER — the polish pass.

   Everything here is decoration on top of a page that already works. Three
   rules keep it from becoming noise:

   1. Nothing moves more than a few pixels, and nothing moves for longer than
      about half a second. Motion points at what changed; it is not the point.
   2. Nothing here may hide content. Entrances animate a class the reveal
      script adds; if that script never runs, the content is simply there.
   3. The reduced-motion block earlier in this file flattens every animation
      and transition with !important, so all of this switches off for anyone
      who has asked their system for less movement.
   ========================================================================== */

/* ---- Entrances -----------------------------------------------------------
   A softer curve than a plain ease: it overshoots very slightly and settles,
   which reads as "placed" rather than "slid in". */
.js-anim .reveal.is-revealed {
  animation: reveal-in .9s cubic-bezier(0.22, 1, 0.28, 1) both;
}

/* Cards and list items in a row cascade instead of arriving as a block. This
   is done by position rather than by hand-written data-delay attributes, so
   every grid on every page gets it and none can be forgotten. An explicit
   data-delay still wins — the rules above are more specific. */
.js-anim .hp-cards > .reveal:nth-child(2),
.js-anim .grid-3 > .reveal:nth-child(2),
.js-anim .grid-4 > .reveal:nth-child(2),
.js-anim .hp-flow > .reveal:nth-child(2) { animation-delay: .07s; }
.js-anim .hp-cards > .reveal:nth-child(3),
.js-anim .grid-3 > .reveal:nth-child(3),
.js-anim .grid-4 > .reveal:nth-child(3),
.js-anim .hp-flow > .reveal:nth-child(3) { animation-delay: .14s; }

/* ---- Icon tiles ----------------------------------------------------------
   The tile is the one element in a card that can afford personality, so it
   picks up a little scale when the card is hovered. The card's own lift is
   defined with the card; this only adds the tile's part. */
.card .card-icon,
.hp-card .hp-tile,
.solution-item .card-icon {
  transition: transform .28s cubic-bezier(0.22, 1, 0.28, 1);
}
.card:hover .card-icon,
.hp-card:hover .hp-tile,
.solution-item:hover .card-icon { transform: translateY(-2px) scale(1.05); }

/* ---- Links ---------------------------------------------------------------
   Body links draw their underline rather than simply having one. Uses a
   background image so the text itself never shifts. */
.prose a,
.footer-col a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size .28s cubic-bezier(0.22, 1, 0.28, 1), color .18s var(--ease);
}
.prose a { background-size: 100% 1px; }
.prose a:hover { color: var(--orange); }
.footer-col a:hover,
.footer-col a:focus-visible { background-size: 100% 1px; }

/* ---- The process timeline ------------------------------------------------
   Each tile settles as its card is revealed, so the row reads left to right
   the way the process does. (The old per-step connector-draw animation went
   with the per-step connectors; the flow cards share one line behind them.) */
.js-anim .hp-flow > .reveal.is-revealed .hp-tile {
  animation: tile-settle .5s .12s cubic-bezier(0.22, 1, 0.28, 1) both;
}
@keyframes tile-settle {
  from { opacity: 0; transform: scale(.82) rotate(-6deg); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: no-preference) {
  
  @keyframes glow-drift {
    from { transform: translate3d(0, 0, 0) scale(1); opacity: .9; }
    to { transform: translate3d(2%, -1.5%, 0) scale(1.06); opacity: 1; }
  }
  
  @keyframes glow-drift-rtl {
    from { transform: scaleX(-1) translate3d(0, 0, 0) scale(1); opacity: .9; }
    to { transform: scaleX(-1) translate3d(2%, -1.5%, 0) scale(1.06); opacity: 1; }
  }
}

/* ---- Pressed states -------------------------------------------------------
   A control that can be pressed should feel pressed. */
.card-link:active .ico--arrow-right { transform: translateX(2px) scale(.94); }
.faq-q:active { transform: scale(.995); }

/* ==========================================================================
   THE HOME PAGE — the 2026-08-18 design.

   Everything from here down was the <style> block inside new.html, the page
   Momtaz approved section by section on the night of 2026-08-17/18. It moved
   here so the home page stops being a standalone file with its own copy of
   everything and becomes an ordinary page of the site: shared header, shared
   footer, shared tokens, one versioned stylesheet.

   FOUR THINGS CHANGED ON THE WAY IN, and only these four:

   1. .hero became .home-hero. The legal pages' first section is already
      called .hero, and the two are completely different shapes — the photo
      layout would have flattened Privacy, Terms and Security.
   2. The bare h1 rules are scoped to .home-hero. One of them lived inside an
      @supports block and set background-clip: text with a transparent fill:
      unscoped, it would have made the heading on every page invisible.
   3. The button, its shine and the top bar came out — site.css owns those
      now, so every page has them, and the hero keeps only the container-query
      sizing that ties its button to the photo.
   4. Rules nothing on the page used were dropped (an older contact layout, a
      decorative paper plane and dashed routes, a help strip).

   The source of truth for WHY any of it looks the way it does stays
   docs/redesign-2026-08/DESIGN-SYSTEM.md. Read that before changing anything
   below.
   ========================================================================== */
/* ---- THE HERO -----------------------------------------------------------
   Two columns: the words, and the product running beside them.

   It used to be a 900KB photograph of a laptop, with the copy positioned over
   it in cqw — one percent of the photo's width — so the words held their
   place against the picture. All of that went with the picture, and good
   riddance: the photo had the OLD product name printed on the screen inside
   it and could not be edited out, it could not move, and it was by a wide
   margin the heaviest thing on the site.

   Ordinary responsive units now. Nothing here is pinned to an image, so
   nothing here needs the Arabic exception the photo did either. */
.home-hero {
  position: relative;
  padding: clamp(2.5rem, 6vw, 5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(3rem, 7vw, 5.5rem);
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  align-items: center;
  gap: clamp(2.5rem, 6vw, 5rem);
  max-width: 1180px;
  margin: 0 auto;
}
.copy { display: flex; flex-direction: column; align-items: flex-start; }

.home-hero h1 {
  margin: 0;
  font-size: clamp(2.4rem, 1.4rem + 3.4vw, 4.25rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.035em;
}
.home-hero h1 span { color: var(--orange); }

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .home-hero h1 {
    background-color: var(--ink);
    background-image: linear-gradient(102deg,
      transparent 36%,
      rgba(249, 129, 25, .60) 45%,
      rgba(255, 255, 255, .95) 50%,
      rgba(249, 129, 25, .60) 55%,
      transparent 64%);
    background-repeat: no-repeat;
    background-size: 240% 100%;
    background-position-x: 240%;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: h1-shimmer 4.2s linear infinite;
    animation-delay: .9s;
  }
  .home-hero h1 span { -webkit-text-fill-color: var(--orange); }
}
@keyframes h1-shimmer {
  0%   { background-position-x: 240%; }
  62%  { background-position-x: -140%; }
  100% { background-position-x: -140%; }
}

/* ---- The typed line -----------------------------------------------------
   The effect "Join the pilot now." has on the live site. The real sentence
   stays in the page and is only hidden from SIGHT once the script is running,
   so with no JavaScript the visitor reads the plain line — never an empty gap.
   A screen reader gets the whole sentence, never one letter at a time. */
/* Hold both lines' worth of height from the start. Without this the block is
   one line tall until the line break is typed, and the button below jumps down
   mid-animation. */
.sub.is-typing { min-height: 3.2em; }
.sub.is-typing .sub-src {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.typed-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-inline-start: 3px;
  vertical-align: -.15em;
  border-radius: 2px;
  background: var(--orange);
  animation: caret-blink 1.1s steps(1) infinite;
}
@keyframes caret-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }

.sub {
  margin: clamp(1.1rem, 2vw, 1.6rem) 0 clamp(1.75rem, 3vw, 2.4rem);
  max-width: 46ch;
  color: var(--grey);
  font-size: clamp(1.0625rem, 1rem + .3vw, 1.25rem);
  font-weight: 400;
  letter-spacing: .006em;
  line-height: 1.6;
  white-space: pre-line;   /* keeps the break while the line is being typed */
}

/* The hero stacks on a phone: words first, then the product. */
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: clamp(2rem, 6vw, 3rem); }
  .home-hero h1 { font-size: clamp(2.1rem, 7.6vw, 3rem); letter-spacing: -.025em; }
}

/* ==========================================================================
   THE TICK STRIP — six promises, on a wave.

   Every one is something the product actually does today: no invented
   numbers, no "trusted by", which a test forbids outright.

   It used to be three across and two down. It is a single column now
   because the wave needs one — each row is shifted sideways by a sine set
   35 degrees further round than the row above it, so as you scroll the six
   of them read as one travelling wave rather than six things twitching.
   home.js drives it; the CSS just leaves room for the swing.
   ========================================================================== */
.ticks {
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(2.5rem, 5vw, 4.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(3rem, 6vw, 5rem);
  /* The rows travel about 64px either way. Without this the leftmost swing
     puts a tick under the edge of the window and adds a scrollbar. */
  overflow-x: clip;
}
.ticks ul {
  display: grid;
  gap: clamp(.85rem, 1.8vw, 1.35rem);
  margin: 0;
  /* Half the swing, so the row at its furthest left still starts inside the
     column rather than against the window edge. */
  padding: 0 0 0 clamp(1rem, 5vw, 4.5rem);
  list-style: none;
}
.ticks li {
  display: flex;
  align-items: center;
  gap: .8rem;
  min-width: 0;
  color: var(--ink);
  /* A bit smaller than it was — Momtaz's call once they went into one
     column, where six full-size rows read as a menu rather than a list. */
  font-size: clamp(.9375rem, .88rem + .26vw, 1.0625rem);
  font-weight: 600;
  line-height: 1.35;
  white-space: nowrap;
  /* Set from JS. Declared here so the row has somewhere to start and so a
     blocked script leaves a plain, straight list. */
  transform: translate3d(var(--wave, 0px), 0, 0);
  will-change: transform;
}
/* Straight and still: the wave is decoration, the six promises are not. */
@media (prefers-reduced-motion: reduce) {
  .ticks li { transform: none; will-change: auto; }
}
@media (max-width: 700px) {
  .ticks li { white-space: normal; }
  .ticks ul { padding-left: 0; }
}
.ticks svg {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
  stroke: var(--orange);
  stroke-width: 2.6;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
@media (max-width: 860px) {
  /* Two across on a phone, not one: these are short lines and a single column
     turns six of them into a long thin list nobody reads to the end of. */
  .ticks ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem 1rem; }
  .ticks li { align-items: flex-start; gap: .6rem; font-size: .9375rem; }
  .ticks svg { width: 1.1rem; height: 1.1rem; margin-top: .1rem; }
}
@media (max-width: 460px) {
  .ticks ul { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   HOW IT WORKS — four cards that stack as you scroll.

   From a 21st.dev React component Momtaz sent (cards-stack, motion/react +
   Tailwind + shadcn). None of that can be installed here — this site is plain
   HTML — but the stacking itself needs no library at all: it is position:
   sticky with each card's offset a little lower than the one before, so they
   pile up instead of scrolling away.

   THE RULE THIS SECTION OBEYS. A sticky stack was built on 2026-08-17 and
   thrown out: it held three of four cards at 35% opacity with big gaps, and
   Momtaz's verdict was "so so bad" — dimmed or displaced content reads to him
   as a page that failed to load. So every card here is SOLID and fully
   readable the whole time it is on screen. Nothing fades, nothing shrinks,
   nothing slides away. Do not add opacity or scale to these cards.
   ========================================================================== */
.how {
  background: var(--paper);
  padding: clamp(3rem, 6vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 8vw, 7rem);
}
.how-inner {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  max-width: 1440px;
  margin: 0 auto;
}
/* The heading holds still while the cards move past it. */
.how-intro { position: sticky; top: clamp(2rem, 8vh, 5rem); align-self: start; }
.how-eyebrow {
  margin: 0 0 1rem;
  color: var(--orange-ink);
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
.how-intro h2 {
  margin: 0;
  font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
}
.how-intro h2 span { color: var(--orange); }
.how-intro p {
  max-width: 34ch;
  margin: 1.25rem 0 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
}

.stack { margin: 0; padding: 0 0 12vh; list-style: none; }
.stack-card {
  position: sticky;
  /* Each card parks 18px lower than the one before, so the finished ones stay
     visible as a stack of edges rather than disappearing under the next. */
  top: calc(clamp(2rem, 8vh, 5rem) + var(--i) * 18px);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
  padding: clamp(1.6rem, 3vw, 2.5rem);
  background: #fff;                 /* solid. never transparent. */
  border: 1px solid #e4e8e6;
  border-radius: 22px;
  box-shadow: 0 18px 40px -28px rgba(19, 50, 42, .45);
}
.stack-head {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: .9rem;
}
.stack-num {
  display: grid;
  place-items: center;
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: .9375rem;
  font-weight: 700;
}
.stack-card:nth-child(4) .stack-num { background: var(--orange); }
.stack-head h3 {
  margin: 0;
  font-size: clamp(1.25rem, 1.1rem + .55vw, 1.6rem);
  font-weight: 700;
  letter-spacing: -.02em;
}

.stack-card p {
  margin: 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .2vw, 1.0625rem);
  line-height: 1.6;
}

@media (max-width: 860px) {
  /* No stacking on a phone: the viewport is too short for a pile of cards to
     read as anything but a mess. They become a plain list, which says the
     same thing. */
  .how-inner { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .how-intro { position: static; }
  .stack { padding-bottom: 0; }
  .stack-card { position: static; }
}

/* ==========================================================================
   WHY RUNOVA — cards that stack on the same spot as you scroll.

   From a second 21st.dev React component (sticky-scroll-cards-section). Same
   story as the last one: React, Tailwind, an IntersectionObserver hook — none
   of it installable here, and none of it needed. Every card sticks at the SAME
   top offset, so each one covers the one before. That is one CSS line.

   THE ONE THING I CHANGED ON PURPOSE. The original fills the right half of
   each card with an Unsplash photo. This site's policy is img-src 'self',
   which blocks every outside image outright — the cards would have shipped
   with four broken pictures. So the right half is a small live panel of the
   real interface instead: no outside assets, and it shows the product rather
   than a stock photo of a desk.

   Every card is SOLID and fully readable while it is the one on top. Nothing
   is dimmed — see the note on the how-it-works stack above.
   ========================================================================== */
.why {
  background: linear-gradient(180deg, #f7f8f7, var(--paper));
  padding: clamp(3rem, 6vw, 5.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(3rem, 6vw, 6rem);
}
.why-inner { max-width: 1180px; margin: 0 auto; }
.why-head { max-width: 40ch; margin: 0 auto clamp(2.5rem, 5vw, 4rem); text-align: center; }
.why-head p.how-eyebrow { margin-bottom: .9rem; }
.why-head h2 {
  margin: 0;
  font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
}
.why-head h2 span { color: var(--orange); }
.why-head > p:last-child {
  margin: 1.1rem 0 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
}

.why-card {
  position: sticky;
  top: clamp(4.5rem, 12vh, 8.5rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-bottom: clamp(2.5rem, 6vw, 5rem);
  padding: clamp(1.75rem, 4vw, 3rem);
  border-radius: 26px;
  border: 1px solid rgba(255, 255, 255, .10);
  box-shadow: 0 30px 60px -34px rgba(15, 42, 35, .75);
}
/* A warm progression rather than four unrelated colours — they read as one
   family as they pile up. */
.why-card:nth-of-type(odd)  { background: #13322a; }
.why-card:nth-of-type(even) { background: #0f2a23; }

.why-card h3 {
  margin: 0 0 .9rem;
  color: #fff;
  font-size: clamp(1.4rem, 1.1rem + 1.1vw, 2.1rem);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.025em;
}
.why-card > div > p {
  margin: 0;
  max-width: 34ch;
  /* 10.4:1 on the card. Light enough to sit under the white heading, far from
     the washed-out grey that made the old tints look flat. */
  color: #cfdbd5;
  font-size: clamp(1rem, .95rem + .2vw, 1.0625rem);
  line-height: 1.6;
}

/* The small live panel that replaces the stock photo. */
.panel {
  padding: 1rem;
  background: #fff;
  border: 1px solid rgba(19, 50, 42, .08);
  border-radius: 16px;
  box-shadow: 0 18px 34px -22px rgba(0, 0, 0, .55);
}
.panel-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: .8rem;
  font-size: .8125rem;
  font-weight: 700;
}
.pill {
  padding: .2rem .6rem;
  border-radius: 999px;
  background: #fff1e9;
  color: #c3390a;
  font-size: .6875rem;
  font-weight: 700;
}
.pill--ok { background: #e8f3ee; color: #2f7d63; }
.pill--late { background: #fdecec; color: #b3261e; }
.row {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .55rem .65rem;
  border: 1px solid #eef0ef;
  border-radius: 10px;
  font-size: .8125rem;
  font-weight: 500;
}
.row + .row { margin-top: .4rem; }
.row .who {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.4rem;
  height: 1.4rem;
  border-radius: 999px;
  background: #fff1e9;
  color: #c3390a;
  font-size: .625rem;
  font-weight: 700;
}
.row .who--b { background: #e8f3ee; color: #2f7d63; }
.row .who--c { background: #eef1f7; color: #4c5c80; }
.row span:not(.who):not(.pill) { flex: 1; min-width: 0; }
.row--now { border-color: #ffd3c2; background: #fffaf8; }
.row .tick { color: #2f7d63; font-weight: 700; }
.row small { color: #97a29c; font-size: .6875rem; font-weight: 600; }

@media (max-width: 860px) {
  .why-card { position: static; grid-template-columns: minmax(0, 1fr); }
  .why-card h3 br { display: none; }
}

/* ==========================================================================
   RECORD ON ANY PLATFORM — lifted verbatim from the live site.

   Momtaz asked for this section kept exactly as it is, so the markup, the
   layout rules and the drift are copied out of index.html, site.css and
   motion.css rather than rewritten. The three design tokens it leans on are
   redeclared just below, because this preview page does not load site.css.

   The logo files are the site's own, in brand/platforms/ — they ship with
   every deploy of this folder, so nothing new had to be added.
   ========================================================================== */
.mq-scope { --card: #ffffff; --line-soft: #f0f0f3; --shadow-sm: 0 1px 2px rgba(0, 0, 0, .05); }

.plat {
  padding: clamp(3rem, 6vw, 5.5rem) 0 clamp(3.5rem, 7vw, 6.5rem);
  background: var(--paper);
}
.plat-head { max-width: 44ch; margin: 0 auto; padding: 0 clamp(1.25rem, 4vw, 2.5rem); text-align: center; }
.plat-head h2 {
  margin: 0;
  font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
}
.plat-head > p:last-child {
  margin: 1.1rem 0 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
}

/* ==========================================================================
   RECORD ON ANY PLATFORM — the two drifting logo rows (2026-08-17).

   Layout only; the drift itself is in motion.css so reduced motion keeps two
   still, readable rows. The loop trick: each row's track holds the SAME
   group twice, each group carrying its own inter-item gap as padding, so
   sliding the track by exactly half its width lands on an identical frame.
   A flex gap on the track would break that arithmetic — the seam between
   the two groups would differ from the gaps inside them by half a gap and
   the loop would visibly jump.
   ========================================================================== */

.mq {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}
.mq-row {
  overflow: hidden;
  /* The rows fade out at both edges instead of being cut. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.mq-track { display: flex; width: max-content; }
.mq-group {
  display: flex;
  gap: clamp(1.5rem, 3vw, 2.75rem);
  padding-inline-end: clamp(1.5rem, 3vw, 2.75rem);
}
.mq-tile {
  flex: none;
  width: 64px;
  height: 64px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--card);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-sm);
}
.mq-tile img { width: 30px; height: 30px; }
/* ==========================================================================
   3b. THE LOGO ROWS DRIFT (Record on any platform, 2026-08-17)

   Top row drifts start-ward, bottom row drifts the other way, at two
   different unhurried speeds. Sliding by exactly half the track lands on
   the duplicate group, so the loop has no visible seam (the arithmetic is
   explained where the layout lives, in site.css). Hovering a row pauses it
   so a logo can actually be looked at.
   ========================================================================== */

.mq-track--left  { animation: mq-drift-left 48s linear infinite; }
.mq-track--right { animation: mq-drift-right 34s linear infinite; }
.mq-row:hover .mq-track { animation-play-state: paused; }
@keyframes mq-drift-left {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes mq-drift-right {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .mq-track { animation: none !important; }
}

/* ==========================================================================
   PRICING — one card, split, from a reference Momtaz sent.

   Two deliberate departures from that reference:

   1. No price. It is free while the pilot runs, so the big number is the word
      Free. Inventing a figure for a product that does not charge would be the
      one thing on this page that is not true.
   2. NO CUSTOMER LOGOS. The reference fills the bottom right with Nvidia,
      GitHub and Nike. Runova has one pilot company and it has not replied
      yet — the live site has a test that fails the build on "trusted by",
      invented percentages and fake social proof, and this would be exactly
      that. The space carries the leaving-is-free promise instead, which is
      real and is what a buyer actually worries about.
   ========================================================================== */
.price { background: linear-gradient(180deg, #f5f6f5, var(--paper) 55%); padding: clamp(3rem, 6vw, 5.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 8vw, 7rem); }
.price-head { max-width: 50ch; margin: 0 auto clamp(2.5rem, 5vw, 3.5rem); text-align: center; }
.price-head h2 {
  margin: 0;
  font-size: clamp(2.1rem, 1.3rem + 2.6vw, 3.6rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.033em;
}
.price-head h2 span { color: var(--orange); }
.price-head p {
  max-width: 54ch;
  margin: 1.15rem auto 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
}

.price-card {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  max-width: 1120px;
  margin: 0 auto;
  background: #fff;
  border: 1px solid #e6eae8;
  border-radius: 26px;
  box-shadow: 0 30px 60px -42px rgba(19, 50, 42, .5);
  overflow: hidden;
}
.price-left {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .35rem;
  padding: clamp(2rem, 4vw, 3.25rem);
  text-align: center;
  border-inline-end: 1px solid #eef1ef;
}
.price-left h3 { margin: 0; font-size: clamp(1.35rem, 1.1rem + .9vw, 1.85rem); font-weight: 700; letter-spacing: -.02em; }
.price-left .who-for { margin: 0 0 clamp(1.75rem, 3.5vw, 2.5rem); color: var(--grey); font-size: 1rem; }
.price-left .btn { position: static; width: auto; height: auto; padding: .95rem 1.9rem; font-size: 1rem; border-radius: 999px; gap: .55rem; }
.price-left .btn svg { width: 17px; height: 17px; }

.price-includes { margin: clamp(1.5rem, 3vw, 2.25rem) 0 0; max-width: 30ch; color: #8b968f; font-size: .875rem; line-height: 1.55; }

.price-right { padding: clamp(2rem, 4vw, 3.25rem); }
.price-sub { margin: 0 0 clamp(1.1rem, 2.2vw, 1.5rem); font-size: 1rem; font-weight: 700; letter-spacing: -.01em; }
.price-right ul { display: grid; gap: clamp(.7rem, 1.5vw, .95rem); margin: 0 0 clamp(1.75rem, 3.5vw, 2.5rem); padding: 0; list-style: none; }
.price-right li { display: flex; align-items: center; gap: .8rem; font-size: clamp(1rem, .95rem + .2vw, 1.0625rem); font-weight: 600; }
.price-right li svg { flex: none; width: 1.2rem; height: 1.2rem; stroke: var(--orange); stroke-width: 2.6; fill: none; stroke-linecap: round; stroke-linejoin: round; }
/* The closing promise. It was a cream box with a white circle behind the icon
   — Momtaz's word for both was ugly. A hairline, a plain orange mark and one
   sentence instead; the section already has a tinted panel in the contact
   block below, and two of them fought. */
.price-promise {
  display: flex;
  align-items: flex-start;
  gap: .8rem;
  margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
  padding-top: clamp(1.4rem, 2.8vw, 1.9rem);
  border-top: 1px solid #eef1ef;
}
.price-promise svg { flex: none; width: 1.15rem; height: 1.15rem; margin-top: .15rem; stroke: var(--orange); stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.price-promise p { margin: 0; max-width: 46ch; color: var(--grey); font-size: .9375rem; line-height: 1.55; }
.price-promise b { color: var(--ink); font-weight: 700; }

@media (max-width: 860px) {
  .price-card { grid-template-columns: minmax(0, 1fr); }
  .price-left { border-inline-end: 0; border-block-end: 1px solid #eef1ef; }
}

/* ==========================================================================
   FREQUENTLY ASKED QUESTIONS — lifted from the live site, kept the same.

   The markup, the two-column layout and the open/close behaviour are copied
   out of index.html, site.css and site.js rather than rebuilt, because Momtaz
   asked for it unchanged. Two small edits only: the chevron is an inline SVG
   (this page has no icon sprite), and the translation attributes are dropped
   (no language switch on a preview page).

   The .faq-h reset has to stand on its own — each question is an h3 wrapping a
   button, and on the live site that reset once sat under a boxed selector, so
   unboxing the FAQ gave every question full heading typography.
   ========================================================================== */
.faq-section { background: var(--paper); padding: clamp(3rem, 6vw, 5.5rem) 0 clamp(4rem, 8vw, 7rem); }
.faq-layout { max-width: 1180px; margin: 0 auto; padding: 0 clamp(1.25rem, 4vw, 2.5rem); }
.faq-intro .how-eyebrow { margin-bottom: 1rem; }
.faq-intro h2 {
  margin: 0;
  font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
}
.faq-intro .hp-sub {
  max-width: 30ch;
  margin: 1.15rem 0 0;
  color: var(--grey);
  font-size: clamp(1rem, .95rem + .25vw, 1.125rem);
  line-height: 1.6;
}

/* Heading beside the questions, on the two-column split Momtaz sent
   (2026-08-17). The questions get the wider half because they are what the
   visitor came to read; the heading column carries the way out to the form
   for anything the list does not answer. */
.faq-layout {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.faq-layout .faq-intro { text-align: start; }
.faq-layout .eyebrow--sec,
.faq-layout .hp-h2,
.faq-layout .hp-sub { text-align: start; margin-inline: 0; }
.faq-layout .hp-sub { max-width: 34ch; }
/* The list starts level with the heading, not its eyebrow. */
.faq-list { margin-top: .35rem; }
/* Open rows divided by hairlines, not a stack of boxes. */
.faq { display: grid; gap: 0; border-block: 1px solid var(--line-soft); }
/* The question is a heading wrapping a button; the h3 must not add its own
   type scale or spacing.

   This reset used to sit directly under the boxed-variant selector with the
   comment BETWEEN the two, which CSS reads as a descendant combinator, so it
   only ever applied inside a boxed FAQ. Invisible while the only FAQ on the
   site was boxed; it would have handed every question full h3 typography the
   moment one was not, which is exactly what unboxing does. */
.faq-h { margin: 0; font: inherit; }
.faq-item {
  border-bottom: 1px solid var(--line-soft);
  overflow: hidden;
}
.faq-item:last-child { border-bottom: 0; }
.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 21px 2px;
  background: none;
  border: 0;
  cursor: pointer;
  text-align: start;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: var(--fw-semibold);
  transition: color .18s var(--ease);
}
.faq-q:hover { color: var(--orange-ink); }
.faq-q span { flex: 1; }
.faq-q .ico {
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--muted);
  transition: transform .25s var(--ease), color .25s var(--ease);
}
.faq-item.is-open .faq-q .ico { transform: rotate(180deg); color: var(--orange); }
.faq-a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s var(--ease);
}
.faq-item.is-open .faq-a { grid-template-rows: 1fr; }
/* Collapsing to 0fr hides the answer visually but leaves it readable by screen
   readers and keeps the link inside it in the tab order — so the button says
   aria-expanded="false" while the answer is still announced, and a keyboard
   user lands on an invisible link. visibility:hidden fixes both and keeps the
   open/close animation, because it is delayed until the transition finishes. */
.faq-a > div { overflow: hidden; visibility: hidden; transition: visibility 0s .3s; }
.faq-item.is-open .faq-a > div { visibility: visible; transition-delay: 0s; }
.faq-a p {
  padding: 0 2px 21px;
  color: var(--muted);
  font-size: var(--fs-sm);
  max-width: 62ch;
}
.faq-q:active { transform: scale(.995); }
@media (max-width: 900px) {
  .faq-layout { grid-template-columns: minmax(0, 1fr); }
  .faq-layout .faq-intro { text-align: center; }
  .faq-layout .eyebrow--sec,
  .faq-layout .hp-h2,
  .faq-layout .hp-sub { text-align: center; margin-inline: auto; }
}
@media (prefers-reduced-motion: reduce) { .faq-a > div { transition-delay: 0s; } }

/* Tokens the copied rules expect, redeclared: this page does not load site.css. */
.faq-section {
  --line: #e7eae8; --line-soft: #f0f0f3; --ink: #0e2220; --muted: #565b62; --orange: #fe5c24; --orange-ink: #cd4a1d;
  --ease: cubic-bezier(.22, .61, .36, 1);        /* without this the expand is dead */
  --mo-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* The answer blurs in word by word, from motion.css. Splitting happens on the
   first open, never on load. fill-mode `both` holds each word invisible until
   its delay elapses, which is why the script takes the class back off once the
   last word has landed — so the worst case is an answer with no flourish,
   never an answer that stays blank. */
.faq-word {
  display: inline-block;
  /* The spaces are real text nodes BETWEEN the spans; without this an
     inline-block lets the browser drop the one at a line break. */
  white-space: pre-wrap;
}
.faq-a.is-revealing .faq-word {
  animation: faq-word-in .5s var(--mo-ease-out) both;
  animation-delay: calc(var(--i, 0) * 16ms);
}
@keyframes faq-word-in {
  from { opacity: 0; filter: blur(7px); transform: translateY(5px); }
  to   { opacity: 1; filter: blur(0); transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .faq-a .faq-word { animation: none !important; opacity: 1 !important; filter: none !important; transform: none !important; }
}

/* ==========================================================================
   CONTACT — the live site's design, with the new wording.

   Momtaz's note was that the card-and-grey-inputs version was horrible and the
   old one was right. So these rules are lifted from site.css: the form is
   UNBOXED (his instruction on the live site was "white, in theme with the
   rest, no boxes"), and every field carries its icon inside it, tinted orange
   or green in turn. Only the labels and fields changed.
   ========================================================================== */
.ct-panel[id],
.team-block[id] { scroll-margin-top: calc(var(--nav-h) + 16px); }
/* ---- The ending: the form beside a panel of moving light ----

   Momtaz removed the "Join the Runova pilot" heading and the two
   Book-a-demo / Email-us cards on 2026-08-17, from a reference whose page
   ends on the form itself. The styles for .ct-wrap, .ct-cards, .ct-card,
   .ct-tile, .ct-link and .ct-mail went with the markup rather than being
   left behind as dead weight. */
.ct-inner {
  max-width: var(--container);
  padding-bottom: clamp(3rem, 6vw, 5rem);
}
.ct-split {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
/* ---- The form panel ---- */

.ct-panel {
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
}
.ct-sub {
  margin-top: 1.1rem;
  color: var(--muted);
  font-size: var(--fs-lead);
  max-width: 40ch;
}
.form-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.15rem;
}
.field { display: grid; gap: 8px; }
.field label {
  font-size: var(--fs-meta);
  font-weight: var(--fw-medium);
}
.form-status { font-size: var(--fs-sm); color: var(--muted); margin: 0; }
.form-status.is-ok { color: var(--green-deep); }
.form-status.is-error { color: #c9353a; }
.form-status a { color: var(--orange-ink); font-weight: var(--fw-medium); }
.field-error {
  display: block;
  min-height: 0;
  margin-top: 6px;
  font-size: var(--fs-meta);
  line-height: 1.4;
  color: #c9353a;
}
.field-error:empty { display: none; }
/* Required marker sits beside the label, in the brand accent. */
.ct-panel .field label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-sm);
  color: var(--ink);
}
.ct-panel .field label b {
  color: var(--orange-ink);
  font-weight: var(--fw-medium);
  line-height: 1;
}
/* Input with an icon parked inside its leading edge. */
.ct-input {
  position: relative;
  display: block;
}
.ct-input .ico {
  position: absolute;
  inset-inline-start: 17px;
  top: 50%;
  width: 21px;
  height: 21px;
  color: var(--green-deep);
  transform: translateY(-50%);
  pointer-events: none;
  transition: color .18s var(--ease);
}
.ct-input--area .ico {
  top: 18px;
  transform: none;
}
.ct-input--orange .ico { color: var(--orange); }
.ct-input--green .ico { color: var(--green-deep); }
.ct-input input,
.ct-input textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--card);
  padding: 15px 16px;
  padding-inline-start: 46px;
  font-size: var(--fs-sm);
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.ct-input textarea { resize: vertical; min-height: 132px; display: block; }
.ct-input input:focus,
.ct-input textarea:focus {
  outline: none;
  border-color: var(--orange);
  box-shadow: 0 0 0 3px var(--orange-ring);
}
.ct-input--orange:focus-within .ico { color: var(--orange-hover); }
.ct-input--green:focus-within .ico { color: var(--green); }
.ct-input input.is-invalid,
.ct-input textarea.is-invalid { border-color: #c9353a; }
.ct-panel .btn-row { margin-top: .35rem; }
.ct-panel .btn .ico { width: 17px; height: 17px; }
/* Reassurance strip closing the panel. */
.ct-safe {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 2rem;
  padding: 1rem 0;
  background: transparent;
  border: none;
}
.ct-safe-icon {
  flex: none;
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--green-deep);
}
.ct-safe-icon .ico { width: 26px; height: 26px; margin: auto; }
.ct-safe b {
  display: block;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  color: var(--green-deep);
}
.ct-safe > div > span {
  display: block;
  margin-top: 2px;
  color: var(--muted);
  font-size: var(--fs-sm);
}
/* ---- The contact intro column ----

   A dark panel with a drifting orange shape stood beside the form here and
   was rejected on sight, like the dark form before it: four fifths of it was
   empty and it was the only black thing on a white site. Real content
   balances the form instead. Do not rebuild the panel. */
.ct-intro h2 {
  font-size: clamp(2.1rem, 1.3rem + 2.8vw, 3.4rem);
  letter-spacing: -0.03em;
  color: var(--ink);
}
.ct-prefer {
  margin-top: 1.6rem;
  font-size: var(--fs-sm);
  color: var(--muted);
}
.ct-prefer a {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  color: var(--orange-ink);
}
.ct-prefer a:hover { color: var(--orange-solid-hover); }
.ct-intro .ct-safe { margin-top: 1.6rem; }
/* No panel. Momtaz's note was that the tinted pill looked bad, and he is right
   that the page already carries two cream panels — a third made it a pattern
   rather than an accent. A line and a link. */
.faq-ask { margin: 1.9rem 0 0; }
.faq-ask b { display: block; margin-bottom: .3rem; font-size: 1.0625rem; font-weight: 700; color: var(--ink); }
.faq-ask a {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  color: var(--orange-ink);
  font-size: 1rem;
  font-weight: 700;
  text-decoration: none;
  border-bottom: 1px solid rgba(254, 92, 36, .35);
  padding-bottom: 1px;
  transition: border-color .2s ease;
}
.faq-ask a:hover { border-color: var(--orange); }
.faq-ask svg { width: 15px; height: 15px; stroke: currentColor; stroke-width: 2.4; fill: none; stroke-linecap: round; stroke-linejoin: round; transition: transform .25s cubic-bezier(.4,0,.2,1); }
.faq-ask a:hover svg { transform: translateX(3px); }

/* Orange on the answers' links, and on the open question, so the section is
   not entirely black and grey. */
.faq-item.is-open .faq-q { color: var(--orange-ink); }
.faq-item.is-open .faq-q .ico--chevron-down { color: var(--orange); }
.faq-a a { color: var(--orange-ink); }

/* The old design's frame. .ct-inner/.ct-split come from site.css above; these
   are the few bits this standalone page has to supply itself. */
.contact {
  --green-deep: #1f5a47;
  --green: #2f7d63;
  --orange-hover: #ef4f18;
  --card: #ffffff;
  --line: #e7eae8;
  --line-soft: #f0f0f3;
  --muted: #565b62;
  --fs-body: 1.0625rem;
  --fs-sm: .9375rem;
  --fs-meta: .8125rem;
  --r-sm: 14px;
  --r-md: 18px;
  --r-card: 22px;
  background: var(--paper); padding: clamp(3rem, 6vw, 5.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 8vw, 7rem); }
.ct-inner { max-width: 1180px; margin: 0 auto; }
.ct-intro h2 { margin: 0; font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem); font-weight: 700; line-height: 1.08; letter-spacing: -.03em; }
.ct-intro h2 span { color: var(--orange); }
.ct-sub { max-width: 34ch; margin: 1.15rem 0 1.75rem; color: var(--grey); font-size: clamp(1rem, .95rem + .25vw, 1.125rem); line-height: 1.6; }
/* Air between the fields. The old rules were written for a shorter form and
   left each label sitting directly under the box above it. */
.contact-form .field { margin-bottom: clamp(1.4rem, 2.6vw, 1.9rem); }
.contact-form .form-row { gap: clamp(1.1rem, 2.2vw, 1.6rem); margin-bottom: 0; }
.contact-form label { display: block; margin-bottom: .55rem; }
.ct-intro .ct-prefer { margin: 0 0 1rem; }
.ct-intro .ct-safe { margin-top: 1.9rem; }

.ct-panel .btn-row { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: clamp(1.6rem, 3vw, 2.2rem); }
.ct-panel .btn { position: static; width: auto; height: auto; padding: .95rem 1.8rem; font-size: 1rem; gap: .55rem; }
.ct-panel .btn svg { width: 17px; height: 17px; }
.ct-input select {
  width: 100%;
  padding: 15px 46px 15px 46px;
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-sm);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  appearance: none;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.ct-input select:focus { outline: none; border-color: var(--orange); box-shadow: 0 0 0 3px rgba(254,92,36,.13); }
/* appearance:none takes the native arrow away, so one is drawn back on. */
.ct-input--select::after {
  content: "";
  position: absolute;
  inset-inline-end: 18px;
  top: 50%;
  width: 9px;
  height: 9px;
  border-right: 2px solid #9aa5a0;
  border-bottom: 2px solid #9aa5a0;
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

/* ==========================================================================
   CONTACT — superseded, kept only for the pilot note below, with the parts that would have
   broken it fixed.

   THREE CORRECTIONS TO THE REFERENCE, all of them load-bearing:

   1. The address in the reference does not exist as a mailbox — the
      only public address is pilot@runova.ae, and the live site has a test
      that fails the build on any other. A branded address that bounces loses
      enquiries silently, which is worse than no address at all.

   2. It promises a reply "within 24 hours". The live site says one business
      day, which is the promise actually being kept. Do not raise it here.

   3. It has a visible "Company name" field. The backend's spam trap is a
      hidden field NAMED company — anything in it means bot, and the message
      is dropped while the sender is told it worked. Naming the real field
      `company` would have silently binned every genuine enquiry. The visible
      one is `org`; the trap keeps the name it needs.

   The form posts to the same backend as the live site, which stores every
   message BEFORE it tries to email it, so a mail failure cannot lose one.
   ========================================================================== */
.contact {
  --green-deep: #1f5a47;
  --green: #2f7d63;
  --orange-hover: #ef4f18;
  --card: #ffffff;
  --line: #e7eae8;
  --line-soft: #f0f0f3;
  --muted: #565b62;
  --fs-body: 1.0625rem;
  --fs-sm: .9375rem;
  --fs-meta: .8125rem;
  --r-sm: 14px;
  --r-md: 18px;
  --r-card: 22px;
  background: var(--paper); padding: clamp(3rem, 6vw, 5.5rem) clamp(1.25rem, 4vw, 2.5rem) clamp(4rem, 8vw, 7rem); }
.contact h2 {
  margin: 0;
  font-size: clamp(2rem, 1.3rem + 2.2vw, 3.25rem);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -.03em;
}
.contact h2 span { color: var(--orange); }

.form-status { margin: .9rem 0 0; font-size: .9375rem; font-weight: 600; }
.form-status.ok { color: #2f7d63; }
.form-status.bad { color: #b3261e; }
/* The spam trap. Invisible to people, irresistible to bots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ==========================================================================
   THE SIGN IN PAGE (/signup)

   Runova signs people in with Google and nothing else, so there is no form
   here — one button. Momtaz's call on 2026-08-18: white, not the dark green
   the first version had, with the brand's two colours in the dots behind it.

   No shared header or footer. A page whose whole job is one button does not
   want a menu inviting people back out of it; there is a logo at the top and
   one quiet way back at the bottom.
   ========================================================================== */
.signin {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(2rem, 6vw, 4rem) clamp(1.25rem, 5vw, 2.5rem);
  background: var(--bg);
  overflow: hidden;
}
.join-dots { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* Clears the paper behind the card so the dots never sit under the words,
   and fades them out at the very top and bottom. */
.signin-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 27% 34% at 50% 48%, var(--bg) 0%, rgba(254, 254, 254, .86) 38%, rgba(254, 254, 254, .18) 70%, transparent 100%),
    linear-gradient(180deg, var(--bg) 0%, transparent 14%, transparent 84%, var(--bg) 100%);
}

.signin-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 26rem;
  text-align: center;
}
.signin-logo { display: inline-block; margin-bottom: clamp(2rem, 5vw, 3rem); }
.signin-logo img { height: 32px; width: auto; }

.signin h1 {
  margin: 0;
  font-size: clamp(1.75rem, 1.3rem + 1.6vw, 2.35rem);
  line-height: 1.1;
  letter-spacing: var(--tr-display);
}
.signin-sub {
  margin: .9rem auto 0;
  max-width: 32ch;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.6;
}

/* ---- The Google button --------------------------------------------------
   Google's own guidance for "Continue with Google": their mark at full
   colour on a plain white face with a hairline border. It is the one control
   on this site that does NOT take the brand — a recoloured Google button
   reads as a phishing page, which is the opposite of reassuring on a sign in
   screen. Do not tint it orange. */
.gbtn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
  padding: 14px 20px;
  border: 1px solid #dadce0;
  border-radius: var(--r-pill);
  background: #fff;
  color: #1f1f1f;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: var(--fw-semibold);
  box-shadow: 0 1px 2px rgba(60, 64, 67, .12), 0 1px 3px 1px rgba(60, 64, 67, .06);
  transition: box-shadow .18s var(--ease), border-color .18s var(--ease),
              background-color .18s var(--ease), transform .18s var(--ease);
}
.gbtn:hover {
  background: #f8faff;
  border-color: #c9cdd2;
  box-shadow: 0 1px 3px rgba(60, 64, 67, .2), 0 4px 10px 2px rgba(60, 64, 67, .1);
  transform: translateY(-1px);
}
.gbtn:active { transform: translateY(0); }
.gbtn-mark { display: flex; flex: none; }
.gbtn-mark svg { width: 19px; height: 19px; }

.signin-note {
  margin: 1rem 0 0;
  padding: 12px 14px;
  border: 1px solid var(--orange-ring);
  border-radius: var(--r-sm);
  background: var(--orange-paper);
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.6;
  text-align: start;
}
.signin-note a { color: var(--orange-ink); font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 3px; }

.signin-invite {
  margin-top: 1.6rem;
  color: var(--muted);
  font-size: var(--fs-sm);
  line-height: 1.7;
}
.signin-invite a { color: var(--orange-ink); font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 3px; }
.signin-legal {
  margin-top: 1.4rem;
  color: #8b938f;
  font-size: var(--fs-meta);
  line-height: 1.6;
}
.signin-legal a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.signin-legal a:hover { color: var(--ink); }
.signin-back { margin-top: 2.25rem; font-size: var(--fs-sm); }
.signin-back a { color: var(--muted); }
.signin-back a:hover { color: var(--ink); }

/* ---- The request access page (/join) -----------------------------------
   The twin of /signup: same paper, same drifting dots, same card. One has a
   Google button for people who already have access, this one has the form
   for people asking for it. Only the width and the form differ. */
.signin--wide { align-items: flex-start; padding-block: clamp(3rem, 8vw, 6rem); }
.signin-veil--wide {
  background:
    radial-gradient(ellipse 38% 46% at 50% 42%, var(--bg) 0%, rgba(254, 254, 254, .88) 44%, rgba(254, 254, 254, .22) 72%, transparent 100%),
    linear-gradient(180deg, var(--bg) 0%, transparent 12%, transparent 86%, var(--bg) 100%);
}
.signin-card--form { max-width: 30rem; }
.signin-sub--wide { max-width: 40ch; }

.join-form { margin-top: clamp(2rem, 4vw, 2.75rem); text-align: start; }
.join-form .field { margin-bottom: 1.15rem; }
/* Full width and a little clear of the last field: this is the one action on
   the page, so it does not sit tight against the form like a Send. */
.join-go { width: 100%; margin-top: .6rem; }
.join-form .form-status { margin-top: .9rem; text-align: center; }

/* ==========================================================================
   THE PRODUCT, RUNNING (the hero's right-hand column)

   A real panel rather than a picture of one: it moves, it weighs nothing next
   to the 900KB photograph it replaced, and it cannot end up showing the wrong
   product name the way a baked-in screenshot did.

   home.js drives it. With no script it is a still, correct panel — every step
   already has its resting state in the markup.
   ========================================================================== */
.hero-app {
  position: relative;
  border-radius: 20px;
  background: var(--card);
  border: 1px solid var(--line);
  box-shadow:
    0 2px 4px rgba(19, 50, 42, .04),
    0 18px 40px -18px rgba(19, 50, 42, .22),
    0 48px 90px -50px rgba(19, 50, 42, .45);
  overflow: hidden;
}
/* The window chrome. Three dots and nothing else: enough to read as an
   application, not so much that it pretends to be a specific browser. */
.app-bar {
  display: flex;
  gap: 7px;
  padding: 13px 16px;
  background: var(--paper);
  border-bottom: 1px solid var(--line-soft);
}
.app-dot { width: 9px; height: 9px; border-radius: 999px; background: #d8dedb; }
.app-dot:nth-child(1) { background: #fe5c24; opacity: .5; }

.app-body { padding: clamp(1.1rem, 2.2vw, 1.6rem); }
.app-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.app-title { display: block; font-size: clamp(1rem, .95rem + .3vw, 1.1875rem); font-weight: var(--fw-bold); letter-spacing: -.015em; }
.app-meta { display: block; margin-top: .3rem; color: var(--muted); font-size: var(--fs-meta); }
.app-meta i { font-style: normal; font-weight: var(--fw-bold); color: var(--ink); font-variant-numeric: tabular-nums; }

/* The recording chip. The dot pulses; the clock counts. */
.app-rec {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--orange-tint);
  color: var(--orange-ink);
  font-size: .6875rem;
  font-weight: var(--fw-bold);
  letter-spacing: .06em;
}
.app-rec i { width: 7px; height: 7px; border-radius: 999px; background: var(--orange); animation: app-blink 1.4s ease-in-out infinite; }
.app-rec b { font-variant-numeric: tabular-nums; font-weight: var(--fw-bold); }
@keyframes app-blink { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

.app-bar-track {
  height: 5px;
  margin: clamp(.9rem, 2vw, 1.25rem) 0 clamp(1rem, 2vw, 1.4rem);
  border-radius: 999px;
  background: var(--line-soft);
  overflow: hidden;
}
.app-bar-fill {
  display: block;
  height: 100%;
  width: 60%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--orange), #ff7a45);
  transition: width .7s var(--ease);
}

.app-steps { display: grid; gap: 7px; margin: 0; padding: 0; list-style: none; }
.app-step {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .6rem .7rem;
  border-radius: 12px;
  border: 1px solid transparent;
  transition: background-color .45s var(--ease), border-color .45s var(--ease);
}
.app-who {
  display: grid;
  place-items: center;
  flex: none;
  width: 26px; height: 26px;
  border-radius: 999px;
  background: var(--orange-tint);
  color: var(--orange-ink);
  font-size: .625rem;
  font-weight: var(--fw-bold);
}
.app-who--b { background: var(--green-tint); color: var(--green-deep); }
.app-who--c { background: #eef3fc; color: #2b63c4; }
.app-text { flex: 1; min-width: 0; font-size: var(--fs-sm); }
.app-state { flex: none; width: 1.15rem; height: 1.15rem; }

/* Three states, and the whole animation is moving rows between them.
   DONE: a green tick. NOW: warm row, orange ring, the one being worked on.
   WAITING: nothing at all — an empty slot reads as "not yet" without needing
   a label, and a row of grey pills would compete with the tick. */
.app-step.is-done .app-state {
  background: no-repeat center/1.15rem
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232f7d63' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}
.app-step.is-done .app-text { color: var(--muted); }
.app-step.is-now {
  background: var(--orange-paper);
  border-color: #ffe0cd;
}
.app-step.is-now .app-text { font-weight: var(--fw-semibold); }
.app-step.is-now .app-state {
  border: 2px solid var(--orange);
  border-radius: 999px;
  animation: app-pulse 1.6s ease-in-out infinite;
}
@keyframes app-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(254, 92, 36, .35); }
  50%      { box-shadow: 0 0 0 5px rgba(254, 92, 36, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .app-rec i, .app-step.is-now .app-state { animation: none; }
  .app-bar-fill { transition: none; }
}

/* ---- The consent tick on the sign in page ------------------------------
   Consent is given BEFORE the button, and the button does nothing without
   it. A line of small print under a button somebody has already pressed is
   a notice, not consent. */
.agree {
  display: flex;
  align-items: flex-start;
  gap: .7rem;
  margin-top: clamp(1.5rem, 3vw, 2rem);
  text-align: start;
  cursor: pointer;
}
/* The real checkbox stays in the page — focusable, announced, and the thing
   the label is actually tied to — it is just not the thing you see. */
.agree input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  margin: 0;
}
.agree-box {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px; height: 20px;
  margin-top: 1px;
  border: 1.5px solid var(--line);
  border-radius: 6px;
  background: var(--card);
  transition: background-color .16s var(--ease), border-color .16s var(--ease);
}
.agree-box svg {
  width: 13px; height: 13px;
  stroke: #fff;
  stroke-width: 3.2;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  transform: scale(.6);
  transition: opacity .16s var(--ease), transform .16s var(--ease);
}
.agree input:checked + .agree-box { background: var(--orange); border-color: var(--orange); }
.agree input:checked + .agree-box svg { opacity: 1; transform: scale(1); }
.agree input:focus-visible + .agree-box { outline: 2px solid var(--orange); outline-offset: 3px; }
.agree-text { color: var(--muted); font-size: var(--fs-sm); line-height: 1.55; }
.agree-text a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* Until it is ticked the button looks like what it is: not ready yet. It
   stays clickable so pressing it can SAY so, rather than being a dead
   control that ignores you. */
.gbtn[aria-disabled="true"] { opacity: .55; }
.gbtn[aria-disabled="true"]:hover { transform: none; box-shadow: 0 1px 2px rgba(60, 64, 67, .12); }
.agree.is-missing .agree-box { border-color: #c9353a; }

/* ---- The dark half: /join ----------------------------------------------
   Momtaz's call, 2026-08-18. The two pages are twins in shape and opposites
   in weight: sign in is paper, requesting access is ink. */
body.page-dark { background: var(--ink); }
.signin--dark { background: var(--ink); }
.signin--dark .signin-veil {
  background:
    radial-gradient(ellipse 38% 46% at 50% 42%, var(--ink) 0%, rgba(14, 34, 32, .88) 44%, rgba(14, 34, 32, .25) 72%, transparent 100%),
    linear-gradient(180deg, var(--ink) 0%, transparent 12%, transparent 86%, var(--ink) 100%);
}
/* The wordmark is dark green on transparent, which is invisible on ink.
   Brightened rather than kept as a second file: one logo asset, and the rule
   is that it is always the supplied image. */
.signin--dark .signin-logo img { filter: brightness(0) invert(1); }
.signin--dark h1 { color: #fff; }
.signin--dark .signin-sub { color: #a8b8b2; }
.signin--dark .join-form .field label { color: #d6e2dc; }
.signin--dark .ct-input input,
.signin--dark .ct-input select {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .14);
  color: #fff;
}
.signin--dark .ct-input select option { color: var(--ink); }
.signin--dark .ct-input input:focus,
.signin--dark .ct-input select:focus {
  background: rgba(255, 255, 255, .08);
  border-color: var(--orange);
  box-shadow: 0 0 0 3px rgba(254, 92, 36, .24);
}
.signin--dark .ct-input--green .ico { color: #6fbfa0; }
.signin--dark .ct-input--select::after { border-color: #a8b8b2; }
.signin--dark .field-error { color: #ff9a8a; }
/* On ink the dark pill would vanish, so the button inverts: white face, ink
   label, and the arrow keeps the brand orange. */
.signin--dark .join-go { background: #fff; color: var(--ink); }
.signin--dark .join-go:hover { background: #f1f5f3; }
.signin--dark .join-go svg { stroke: var(--orange); }
.signin--dark .form-status { color: #a8b8b2; }
.signin--dark .form-status.is-ok { color: #7fd6b4; }
.signin--dark .form-status.is-error { color: #ff9a8a; }
.signin--dark .form-status a { color: #fff; }
.signin--dark .signin-invite { color: #a8b8b2; }
.signin--dark .signin-back a { color: #a8b8b2; }
.signin--dark .signin-back a:hover { color: #fff; }

/* The legal line now sits ABOVE the button, inside the form, where it is
   read before the action rather than after it. */
.join-terms {
  margin: 1.4rem 0 .2rem;
  color: #8fa39c;
  font-size: var(--fs-meta);
  line-height: 1.6;
  text-align: center;
}
.join-terms a { color: #d6e2dc; text-decoration: underline; text-underline-offset: 3px; }
.join-terms a:hover { color: #fff; }
