/*
  aromarytechnologies.com — the whole stylesheet.

  ORGANISATION
    1  tokens            colours, type, space, motion — light and dark
    2  base              reset, type scale, links, buttons
    3  chrome            glass header, footer
    4  heroes            light hero, dark "stage" hero, aurora, pill, gradient text
    5  the scene         code editor, phone, floating chips, wires, grid floor
    6  home sections     bento, timeline, orbit, work card, CTA, the story pages
    7  product           phone stage, pinned scroll story
    8  contact           the enquiry form
    9  shared pieces     cards, glass, panels, devices, legal documents
    10 motion            reveals, keyframes, reduced motion
    11 responsive

  COLOURS are the website's own emerald palette, defined once in section 1.
  Nothing below names a brand colour directly: it uses --brand-* (or the
  -rgb triplets for glows) or a theme token. The dark hero and bands have
  their own small palette ("stage") because they are dark in both themes.
  The Hiyava app keeps its teal; only its screenshots show it here.

  NO STYLE ATTRIBUTES ANYWHERE. The content-security policy is style-src
  'self', which blocks style="" in markup, so every position and delay is a
  class here. site.js may set custom properties through the CSSOM (--mx, --my,
  --progress), which the policy permits.

  MOTION is scoped so the page is complete without it: reveal states only
  apply under .js-reveal, which site.js adds; prefers-reduced-motion switches
  every animation off (section 10). The app itself still has no entrance
  animations — this is the marketing site, where the reader is browsing.
*/

/* =============================================================== 1 tokens */

/*
  THE BRAND: EMERALD

  One green family, defined once. Everything else in this file takes its
  colours from these, either directly or through the theme tokens below —
  including the alpha glows, which use the -rgb triplets:
  rgb(var(--brand-500-rgb) / 0.2).

  WHICH GREEN WHERE
    500 #10b981  fills and light only: glows, chart bars, icon tiles, dots.
                 As text it is 2.3:1 on the page, and white on it is 2.5:1,
                 so it never carries a word.
    700 #047857  anything read: links, labels, buttons (white on it 5.5:1,
                 it on the page 5.0:1, on --surface-alt 4.6:1).
    950→900      the dark sections, in place of black — deep emerald, so the
                 site has no black or dark-blue blocks in the light theme.

  The website's palette is its own. The Hiyava app keeps its teal
  (src/constants/theme.ts); the app's screenshots on the product page show it.
*/
:root {
  --brand-50: #ecfdf5;
  --brand-100: #d1fae5;
  --brand-200: #a7f3d0;
  --brand-300: #6ee7b7;
  --brand-400: #34d399;
  --brand-500: #10b981;
  --brand-600: #059669;
  --brand-700: #047857;
  --brand-800: #065f46;
  --brand-900: #064e3b;
  --brand-950: #022c22;
  --brand-300-rgb: 110 231 183;
  --brand-400-rgb: 52 211 153;
  --brand-500-rgb: 16 185 129;
  --brand-700-rgb: 4 120 87;
  --brand-950-rgb: 2 44 34;

  --text: #1c1917;
  --text-secondary: #57534e;
  --text-muted: #6b6560;
  --bg: #f5f5f4;
  --surface: #ffffff;
  --surface-alt: #ecebe9;
  --border: #e7e5e4;
  --border-strong: #d6d3d1;
  --primary: var(--brand-500);
  --primary-pressed: var(--brand-600);
  --primary-soft: var(--brand-100);
  --on-primary: #ffffff;
  --accent: #c77f2e;
  --accent-soft: #f9ebd6;

  /* Anything that has to be read: see THE BRAND above. Fields get their own
     line, 3:1 against the field, so the box is visible. */
  --primary-ink: var(--brand-700);
  --primary-ink-pressed: var(--brand-800);
  --accent-ink: #8f5714;
  --field-line: #8f8882;
  --focus: var(--brand-700);
  --danger: #b8453e;
  --success: #3e9668;

  --grad-text: linear-gradient(100deg, var(--brand-900) 0%, var(--brand-700) 50%, var(--brand-600) 100%);
  --shadow-card: 0 1px 2px rgba(28, 25, 23, 0.04), 0 8px 24px -12px rgba(87, 83, 78, 0.22);
  --shadow-lift: 0 24px 48px -20px rgba(28, 25, 23, 0.28);
  --shadow-device: 0 50px 90px -30px rgb(var(--brand-950-rgb) / 0.45), 0 10px 30px rgba(28, 25, 23, 0.1);
  --bezel: #101614;

  --glass-bg: rgba(255, 255, 255, 0.66);
  --glass-line: rgba(255, 255, 255, 0.8);
  --glass-shadow: 0 20px 50px -24px rgba(28, 25, 23, 0.3);

  --wash:
    radial-gradient(60rem 40rem at 80% -10%, rgb(var(--brand-500-rgb) / 0.14), transparent 60%),
    radial-gradient(44rem 34rem at 4% 6%, rgba(199, 127, 46, 0.08), transparent 62%);

  /* The stage: the dark hero and the dark bands, identical in both themes. */
  --stage-bg: var(--brand-950);
  --stage-bg-2: var(--brand-900);
  --stage-text: var(--brand-50);
  --stage-secondary: #b4d1c4;
  --stage-line: rgba(255, 255, 255, 0.12);
  --stage-accent: var(--brand-300);
  --grad-stage: linear-gradient(100deg, var(--brand-100) 0%, var(--brand-300) 50%, var(--brand-400) 100%);

  --font: 'Spline Sans', Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif,
    'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji';
  --mono: ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, Consolas, monospace;

  --s2: 8px;
  --s3: 16px;
  --s4: 24px;
  --s5: 32px;
  --s6: 64px;
  --s7: 112px;
  --r-md: 12px;
  --r-lg: 18px;
  --r-xl: 26px;
  --r-2xl: 34px;
  --r-pill: 999px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Dark theme: green-black rather than blue-black, with the lighter emeralds
   doing the reading (#34d399 is 9:1 on --surface). */
@media (prefers-color-scheme: dark) {
  :root {
    --text: #f5f5f4;
    --text-secondary: #b2aca6;
    --text-muted: #9a948e;
    --bg: #0c1310;
    --surface: #131c18;
    --surface-alt: #1a2520;
    --border: #243029;
    --border-strong: #33423a;
    --primary: var(--brand-400);
    --primary-pressed: var(--brand-500);
    --primary-soft: #0b3b2c;
    --on-primary: var(--brand-950);
    --accent: #e0a455;
    --accent-soft: #33280f;

    --primary-ink: var(--brand-400);
    --primary-ink-pressed: var(--brand-300);
    --accent-ink: #e0a455;
    --field-line: #66736c;
    --focus: var(--brand-300);
    --danger: #dd6e66;
    --success: #52b682;

    --grad-text: var(--grad-stage);
    --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 28px -14px rgba(0, 0, 0, 0.7);
    --shadow-lift: 0 24px 48px -20px rgba(0, 0, 0, 0.8);
    --shadow-device: 0 50px 90px -30px rgba(0, 0, 0, 0.85), 0 10px 30px rgba(0, 0, 0, 0.5);
    --bezel: #040806;

    --glass-bg: rgba(22, 34, 29, 0.6);
    --glass-line: rgba(255, 255, 255, 0.09);
    --glass-shadow: 0 20px 50px -24px rgba(0, 0, 0, 0.75);

    --wash:
      radial-gradient(60rem 40rem at 80% -10%, rgb(var(--brand-500-rgb) / 0.13), transparent 60%),
      radial-gradient(44rem 34rem at 4% 6%, rgba(224, 164, 85, 0.06), transparent 62%);
  }
}

/* ================================================================= 2 base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 80px;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img {
  max-width: 100%;
  height: auto;
}

::selection {
  background: rgb(var(--brand-500-rgb) / 0.3);
}

.wrap {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--s4);
}

.prose {
  max-width: 680px;
}

section {
  padding: var(--s7) 0;
  position: relative;
}

section + section {
  padding-top: 0;
}

h1 {
  font-size: clamp(2.6rem, 6.2vw, 5rem);
  line-height: 1.02;
  letter-spacing: -0.04em;
  font-weight: 700;
  margin: 0 0 var(--s4);
  text-wrap: balance;
}

h2 {
  font-size: clamp(1.9rem, 3.8vw, 3rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  font-weight: 700;
  margin: 0 0 var(--s4);
  text-wrap: balance;
}

h3 {
  font-size: 1.2rem;
  font-weight: 650;
  letter-spacing: -0.015em;
  line-height: 1.3;
  margin: 0 0 var(--s2);
}

p {
  margin: 0 0 var(--s3);
  color: var(--text-secondary);
}

.lede {
  font-size: clamp(1.1rem, 1.8vw, 1.35rem);
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 36ch;
}

.lede.wide {
  max-width: 50ch;
}

.eyebrow {
  font-size: 13px;
  font-weight: 650;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--primary-ink);
  margin: 0 0 var(--s3);
}

a {
  color: var(--primary-ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

a:hover {
  color: var(--primary-ink-pressed);
}

/* One focus ring for everything a keyboard can reach: solid, 2px, and at
   least 3:1 against whatever it sits on. The dark hero and bands swap the
   colour, since they are dark in both themes. */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

.hero-dark,
.band {
  --focus: var(--stage-accent);
}

/* Hidden until a keyboard reaches it: the first stop on every page, so
   nobody has to tab through the header to get to what they came for. */
.skip {
  position: absolute;
  left: var(--s3);
  top: 8px;
  z-index: 60;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--bg);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-160%);
}

.skip:focus-visible {
  transform: none;
  color: var(--bg);
}

/*
  THE PAUSE BUTTON

  site.js adds it to any page with an endless animation (the
  drifting light, the travelling grid and wires, the live dots) and nowhere else. Fixed
  to a corner so it is there wherever the reader has scrolled to; on a phone
  it shrinks to the icon, and the words stay as its name.
*/
.motion-toggle {
  position: fixed;
  right: var(--s3);
  bottom: var(--s3);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px 0 14px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-card);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}

.motion-toggle:hover {
  background: var(--surface-alt);
}

.motion-toggle svg {
  width: 16px;
  height: 16px;
  flex: none;
}

.motion-toggle .icon-play,
.motion-paused .motion-toggle .icon-pause {
  display: none;
}

.motion-paused .motion-toggle .icon-play {
  display: block;
}

/* Paused, not removed: everything stays exactly where it was. */
.motion-paused *,
.motion-paused *::before,
.motion-paused *::after {
  animation-play-state: paused !important;
}

@media (max-width: 640px) {
  .motion-toggle {
    width: 44px;
    padding: 0;
    justify-content: center;
  }

  .motion-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* The skip link's target. Focusable only so the next Tab starts inside it;
   it is not a control, so it gets no ring. */
main:focus {
  outline: none;
}

ul {
  margin: 0 0 var(--s3);
  padding-left: 1.15em;
  color: var(--text-secondary);
}

li {
  margin-bottom: var(--s2);
}

li::marker {
  color: var(--text-muted);
}

strong {
  color: var(--text);
  font-weight: 600;
}

.icon {
  width: 20px;
  height: 20px;
  flex: none;
}

/* Gradient headline text. The fallback colour is the text colour, so a browser
   without background-clip:text shows a normal headline, not an invisible one. */
.grad {
  color: var(--text);
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ------------------------------------------------------------- buttons */

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  margin-top: var(--s5);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 26px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--primary-ink);
  color: var(--on-primary);
  font: inherit;
  font-weight: 600;
  font-size: 16px;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition:
    transform 160ms var(--ease),
    background-color 160ms var(--ease),
    box-shadow 200ms var(--ease),
    border-color 160ms var(--ease);
}

.btn:hover {
  background: var(--primary-ink-pressed);
  color: var(--on-primary);
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

/* The primary action: a lit gradient with a soft glow under it. Every stop
   keeps white text above 4.5:1, so the bright teal is the glow, not the fill. */
.btn-glow {
  background: linear-gradient(135deg, var(--brand-700) 0%, var(--brand-800) 55%, var(--brand-900) 100%);
  color: #fff;
  box-shadow:
    0 10px 30px -10px rgb(var(--brand-500-rgb) / 0.7),
    inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.btn-glow:hover {
  background: linear-gradient(135deg, var(--brand-800) 0%, var(--brand-900) 55%, var(--brand-950) 100%);
  color: #fff;
  box-shadow:
    0 16px 40px -12px rgb(var(--brand-500-rgb) / 0.85),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}

.btn.ghost,
.btn.secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--border-strong);
}

.btn.ghost:hover,
.btn.secondary:hover {
  background: var(--surface-alt);
  color: var(--text);
}

.btn[disabled] {
  opacity: 0.65;
  cursor: progress;
  transform: none;
}

.badge {
  display: inline-block;
  padding: 7px 16px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 14px;
  font-weight: 600;
}

/* ============================================================== 3 chrome */

header.site {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid transparent;
  transition:
    border-color 200ms var(--ease),
    background-color 200ms var(--ease);
}

header.site.scrolled {
  border-bottom-color: var(--border);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
}

header.site .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  min-height: 64px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 650;
  font-size: 15.5px;
  letter-spacing: -0.005em;
  color: var(--text);
  text-decoration: none;
}

.wordmark .logo,
.wordmark .mark {
  height: 26px;
  width: auto;
  flex: none;
  color: var(--primary);
}

.wordmark span {
  white-space: nowrap;
}

nav.site {
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 15px;
}

nav.site a {
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
  transition: color 150ms var(--ease);
}

nav.site a:hover,
nav.site a[aria-current='page'] {
  color: var(--text);
}

nav.site .nav-cta {
  padding: 8px 18px;
  border-radius: var(--r-pill);
  background: var(--text);
  color: var(--bg);
  font-weight: 600;
  transition:
    transform 150ms var(--ease),
    opacity 150ms var(--ease);
}

nav.site .nav-cta:hover,
nav.site .nav-cta[aria-current='page'] {
  color: var(--bg);
  opacity: 0.88;
  transform: translateY(-1px);
}

nav.site {
  margin-left: auto;
}

/*
  THE PHONE MENU

  Below 940px the inline links are hidden and this takes their place. It is a
  <details>, so it opens and closes with no JavaScript at all — which keeps
  the rule that a blocked script leaves a working page. site.js only adds the
  conveniences: closing on Escape, on a tap outside, and after following a
  same-page link such as /#services.

  The panel hangs from the header (sticky, so it is the containing block) and
  spans the gutter to gutter width.
*/
.menu {
  display: none;
}

.menu > summary {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
  list-style: none;
}

.menu > summary::-webkit-details-marker {
  display: none;
}

.menu > summary svg {
  width: 18px;
  height: 18px;
}

.menu .icon-close,
.menu[open] .icon-open {
  display: none;
}

.menu[open] .icon-close {
  display: block;
}

.menu-panel {
  position: absolute;
  top: calc(100% + 8px);
  left: var(--s3);
  right: var(--s3);
  display: flex;
  flex-direction: column;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-card);
}

.menu-panel a {
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: 0 16px;
  border-radius: 12px;
  color: var(--text);
  font-size: 16px;
  font-weight: 550;
  text-decoration: none;
}

.menu-panel a:hover,
.menu-panel a[aria-current='page'] {
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}

footer.site {
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: var(--s6) 0 var(--s5);
}

footer.site .cols {
  display: grid;
  grid-template-columns: 1.4fr repeat(4, 1fr);
  gap: var(--s5);
  margin-bottom: var(--s6);
}

footer.site .about-col p {
  font-size: 14px;
  max-width: 32ch;
}

footer.site h2 {
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: 650;
  margin-bottom: var(--s3);
}

footer.site ul {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 15px;
}

footer.site li {
  margin-bottom: 9px;
}

footer.site a {
  color: var(--text-secondary);
  text-decoration: none;
}

footer.site a:hover {
  color: var(--text);
}

.colophon {
  font-size: 13px;
  color: var(--text-muted);
  border-top: 1px solid var(--border);
  padding-top: var(--s4);
  margin: 0;
}

/* ============================================================== 4 heroes */

.hero {
  position: relative;
  padding: 128px 0 var(--s7);
  overflow: hidden;
  isolation: isolate;
}

/* Two blurred brand lights on long, offset loops (28s and 36s — they never
   visibly sync into a pulse). Transform only, so it runs on the compositor. */
.hero::before {
  content: '';
  position: absolute;
  inset: -20% -10% auto -10%;
  height: 150%;
  background: var(--wash);
  pointer-events: none;
  z-index: -1;
  animation: drift-a 28s var(--ease) infinite alternate;
}

.hero::after {
  content: '';
  position: absolute;
  top: -30%;
  right: -12%;
  width: 46rem;
  height: 46rem;
  background: radial-gradient(circle, rgb(var(--brand-500-rgb) / 0.2), transparent 62%);
  filter: blur(30px);
  pointer-events: none;
  z-index: -1;
  animation: drift-b 36s var(--ease) infinite alternate;
}

.hero-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
  align-items: center;
}

/* Half a page wide, a headline at full size breaks after every word. */
.hero-grid h1 {
  font-size: clamp(2.5rem, 4.6vw, 4.1rem);
}

/* ---------------------------------------------------- the dark stage hero */

.hero-dark {
  background:
    radial-gradient(70rem 42rem at 85% 0%, rgb(var(--brand-500-rgb) / 0.28), transparent 60%),
    radial-gradient(50rem 36rem at 0% 100%, rgb(var(--brand-400-rgb) / 0.18), transparent 60%),
    linear-gradient(180deg, var(--stage-bg) 0%, var(--stage-bg-2) 100%);
  color: var(--stage-text);
  margin-top: -64px;
  padding-top: 176px;
}

.hero-dark::before {
  background:
    radial-gradient(40rem 30rem at 70% 20%, rgb(var(--brand-500-rgb) / 0.2), transparent 60%),
    radial-gradient(30rem 24rem at 20% 70%, rgb(var(--brand-300-rgb) / 0.12), transparent 60%);
}

.hero-dark h1,
.hero-dark h2,
.hero-dark strong {
  color: var(--stage-text);
}

.hero-dark p,
.hero-dark .lede {
  color: var(--stage-secondary);
}

.hero-dark .grad {
  background: var(--grad-stage);
  -webkit-background-clip: text;
  background-clip: text;
}

.hero-dark .btn.ghost {
  color: var(--stage-text);
  border-color: rgba(255, 255, 255, 0.22);
}

.hero-dark .btn.ghost:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--stage-text);
}

.hero-dark .eyebrow {
  color: var(--stage-accent);
}

/* A status pill: a live dot and a short line, like a system that is running. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 7px 16px 7px 12px;
  border-radius: var(--r-pill);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--primary-ink);
  background: var(--glass-bg);
  border: 1px solid var(--border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  margin: 0 0 var(--s4);
}

.hero-dark .pill {
  color: var(--brand-200);
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.14);
}

.live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand-500);
  box-shadow: 0 0 0 0 rgb(var(--brand-500-rgb) / 0.6);
  animation: ping 2.4s var(--ease) infinite;
}

/* =========================================================== 5 the scene */

/*
  A code editor, the real app in a phone, three floating facts and the wires
  between them, over a grid floor receding to a horizon. Everything is
  positioned against the .scene box, whose aspect ratio is fixed, so the
  composition holds its shape at any width.
*/
.scene {
  position: relative;
  width: 100%;
  max-width: 600px;
  aspect-ratio: 600 / 540;
  justify-self: center;
}

.scene-floor {
  position: absolute;
  left: -30%;
  right: -30%;
  bottom: -26%;
  height: 62%;
  background-image:
    linear-gradient(rgb(var(--brand-300-rgb) / 0.22) 1px, transparent 1px),
    linear-gradient(90deg, rgb(var(--brand-300-rgb) / 0.22) 1px, transparent 1px);
  background-size: 44px 44px;
  transform: perspective(420px) rotateX(64deg);
  transform-origin: 50% 0%;
  -webkit-mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.6) 40%, transparent 92%);
  mask-image: linear-gradient(to top, #000 0%, rgba(0, 0, 0, 0.6) 40%, transparent 92%);
  animation: floor-travel 3.2s linear infinite;
  pointer-events: none;
}

.scene-wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.wire {
  fill: none;
  stroke: rgb(var(--brand-300-rgb) / 0.55);
  stroke-width: 1.5;
  stroke-dasharray: 5 9;
  animation: wire-flow 1.4s linear infinite;
}

.code-window {
  position: absolute;
  left: 0;
  top: 6%;
  width: 76%;
  border-radius: 18px;
  background: rgb(var(--brand-950-rgb) / 0.72);
  border: 1px solid rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow:
    0 40px 80px -30px rgba(0, 0, 0, 0.8),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  overflow: hidden;
  z-index: 1;
}

.code-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 12px 16px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.03);
}

.code-bar i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
}

.code-bar i:nth-child(1) {
  background: #e0776f;
}
.code-bar i:nth-child(2) {
  background: #e3b560;
}
.code-bar i:nth-child(3) {
  background: #5fc28a;
}

.code-bar span {
  margin-left: 10px;
  font-family: var(--mono);
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}

.code {
  margin: 0;
  padding: 18px 20px 22px;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--stage-secondary);
  white-space: pre;
  overflow: hidden;
}

.code code {
  font: inherit;
}

.cl {
  display: block;
  animation: line-in 480ms var(--ease-out) both;
}

.l1 {
  animation-delay: 300ms;
}
.l2 {
  animation-delay: 450ms;
}
.l3 {
  animation-delay: 600ms;
}
.l4 {
  animation-delay: 750ms;
}
.l5 {
  animation-delay: 850ms;
}
.l6 {
  animation-delay: 950ms;
}
.l7 {
  animation-delay: 1100ms;
}
.l8 {
  animation-delay: 1250ms;
}
.l9 {
  animation-delay: 1400ms;
}

.tk {
  color: var(--brand-300);
}
.tf {
  color: var(--brand-200);
}
.tt {
  color: #f0c27b;
}
.ts {
  color: #b5e48c;
}
.tc {
  color: #7f9a8e;
  font-style: italic;
}

.caret {
  display: inline-block;
  width: 8px;
  height: 15px;
  margin-left: 2px;
  vertical-align: -2px;
  background: var(--brand-300);
  animation: blink 1.05s steps(1) infinite;
}

.scene-phone {
  position: absolute;
  right: 0;
  top: 16%;
  width: 40%;
  z-index: 2;
  animation: bob 7s var(--ease) infinite alternate;
}

.scene-phone .device {
  max-width: none;
  width: 100%;
}

/* Floating facts. Glass, one icon, one short line — each on its own slow bob so
   they never move together. */
.chip-float {
  position: absolute;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px 10px 12px;
  border-radius: var(--r-pill);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text);
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  box-shadow: var(--glass-shadow);
  animation: bob 6s var(--ease) infinite alternate;
}

.chip-float .icon {
  width: 18px;
  height: 18px;
  color: var(--primary-ink);
}

.scene .chip-float {
  color: var(--brand-50);
  background: rgb(var(--brand-950-rgb) / 0.55);
  border-color: rgba(255, 255, 255, 0.14);
}

.scene .chip-float .icon {
  color: var(--brand-300);
}

.cf1 {
  top: -2%;
  right: 8%;
  animation-delay: -1s;
}
.cf2 {
  left: 2%;
  bottom: 12%;
  animation-delay: -3s;
}
.cf3 {
  right: 30%;
  bottom: 0%;
  animation-delay: -5s;
}

/* ======================================================= 6 home sections */

/* --------------------------------------------------------------- bento */

.section-head {
  max-width: 760px;
  margin-bottom: var(--s6);
}

.section-head p {
  max-width: 60ch;
  font-size: 1.125rem;
}

.bento {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  min-height: 320px;
  padding: 30px;
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  isolation: isolate;
  transition:
    transform 220ms var(--ease),
    box-shadow 220ms var(--ease),
    border-color 220ms var(--ease);
}

.tile:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
  border-color: var(--border-strong);
}

.t-wide {
  grid-column: span 2;
  flex-direction: row;
  align-items: center;
}

.t-wide .tile-copy {
  flex: 1 1 0;
}

.t-wide .bento-art {
  flex: 1 1 0;
  margin: 0;
}

/* The light that follows the pointer. --mx/--my are set by site.js; without
   it the light sits in the centre and only appears on hover. */
.spot::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(
    440px circle at var(--mx, 50%) var(--my, 50%),
    rgb(var(--brand-500-rgb) / 0.16),
    transparent 45%
  );
  opacity: 0;
  transition: opacity 300ms var(--ease);
  pointer-events: none;
}

.spot:hover::before {
  opacity: 1;
}

.tile-icon {
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 14px;
  background: var(--primary-soft);
  color: var(--primary-ink);
  margin-bottom: var(--s4);
}

.tile-icon .icon {
  width: 22px;
  height: 22px;
}

.tile p {
  margin: 0;
  max-width: 44ch;
}

.bento-art {
  display: block;
  width: 100%;
  max-width: 340px;
  height: auto;
  margin: auto auto 0;
  overflow: visible;
}

/* SVG art, coloured from the theme so it is right in light and dark. */
.bento-art .win {
  fill: var(--surface-alt);
  stroke: var(--border);
}
.bento-art .dot {
  fill: var(--border-strong);
}
.bento-art .bar-url {
  fill: var(--border);
}
.bento-art .axis {
  stroke: var(--border-strong);
  stroke-width: 1.5;
}
.bento-art .bar {
  fill: var(--primary);
  opacity: 0.85;
  transform-box: fill-box;
  transform-origin: 50% 100%;
}
.bento-art .trend {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 260;
  stroke-dashoffset: 0;
}

.bento-art .flow-line {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 2;
  stroke-linecap: round;
}
.bento-art .node {
  fill: var(--surface);
  stroke: var(--border-strong);
  stroke-width: 1.5;
}
.bento-art .node-hot {
  fill: var(--primary-soft);
  stroke: var(--primary);
}
.bento-art .pulse {
  fill: var(--primary);
}

.bento-art .track {
  stroke: var(--border);
  stroke-width: 3;
  stroke-linecap: round;
}
.bento-art .track-fill {
  stroke: var(--primary);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-dasharray: 210;
  stroke-dashoffset: 210;
  animation: track 6s var(--ease) infinite;
}
.bento-art .ring {
  fill: var(--surface);
  stroke: var(--border-strong);
  stroke-width: 2;
}
.bento-art .tick {
  fill: none;
  stroke: var(--primary);
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
  animation: tick 6s var(--ease) infinite;
}
.bento-art .stage-node text {
  font-family: var(--font);
  font-size: 12px;
  font-weight: 600;
  fill: var(--text-secondary);
}
.bento-art .s1 .tick {
  animation-delay: 0.6s;
}
.bento-art .s2 .tick {
  animation-delay: 1.6s;
}
.bento-art .s3 .tick {
  animation-delay: 2.6s;
}
.bento-art .s4 .tick {
  animation-delay: 3.6s;
}

.bento-art .body {
  fill: var(--surface-alt);
  stroke: var(--border-strong);
  stroke-width: 1.5;
}
.bento-art .ui {
  fill: var(--border);
}
.bento-art .ui-hot {
  fill: var(--primary-soft);
}
.bento-art .ph {
  animation: bob 6s var(--ease) infinite alternate;
}
.bento-art .ph2 {
  animation-delay: -3s;
}

.bento-art .rows rect {
  fill: var(--surface-alt);
  stroke: var(--border);
}
.bento-art .shield {
  fill: var(--primary-soft);
  stroke: var(--primary);
  stroke-width: 2;
  stroke-linejoin: round;
}
.bento-art .lock {
  fill: var(--primary);
}
.bento-art .shackle {
  fill: none;
  stroke: var(--primary);
  stroke-width: 3.5;
  stroke-linecap: round;
}

/* Bars grow and the trend line draws when the tile is revealed. */
.js-reveal .tile .bar {
  transform: scaleY(0.12);
}
.js-reveal .tile.revealed .bar {
  transform: none;
  transition: transform 900ms var(--ease-out);
}
.js-reveal .tile.revealed .b2 {
  transition-delay: 60ms;
}
.js-reveal .tile.revealed .b3 {
  transition-delay: 120ms;
}
.js-reveal .tile.revealed .b4 {
  transition-delay: 180ms;
}
.js-reveal .tile.revealed .b5 {
  transition-delay: 240ms;
}
.js-reveal .tile.revealed .b6 {
  transition-delay: 300ms;
}
.js-reveal .tile.revealed .b7 {
  transition-delay: 360ms;
}
.js-reveal .tile .trend {
  stroke-dashoffset: 260;
}
.js-reveal .tile.revealed .trend {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1400ms var(--ease-out) 400ms;
}

/* --------------------------------------------------------------- bands */

.band {
  background:
    radial-gradient(60rem 30rem at 90% 0%, rgb(var(--brand-500-rgb) / 0.22), transparent 60%),
    linear-gradient(180deg, var(--stage-bg), var(--stage-bg-2));
  color: var(--stage-text);
  padding: var(--s7) 0;
  margin: 0 0 var(--s7);
  overflow: hidden;
}

section + .band {
  padding-top: var(--s7);
}

/* .band .card h3 too: .card h3 comes later in the file at the same weight
   and would otherwise paint the card titles dark-on-dark in the light theme. */
.band h2,
.band h3,
.band .card h3,
.band strong {
  color: var(--stage-text);
}

.band p,
.band li {
  color: var(--stage-secondary);
}

.band .eyebrow {
  color: var(--stage-accent);
}

.band .card {
  background: rgba(255, 255, 255, 0.045);
  border-color: rgba(255, 255, 255, 0.1);
  box-shadow: none;
}

.band .card:hover {
  border-color: rgb(var(--brand-300-rgb) / 0.35);
}

/* ------------------------------------------------------------ timeline */

.timeline {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0 0 0 52px;
  max-width: 780px;
  --progress: 1;
}

.js-timeline .timeline {
  --progress: 0;
}

.timeline::before,
.timeline::after {
  content: '';
  position: absolute;
  left: 11px;
  top: 8px;
  width: 2px;
  border-radius: 2px;
}

.timeline::before {
  bottom: 8px;
  background: var(--stage-line);
}

.timeline::after {
  height: calc((100% - 16px) * var(--progress));
  background: linear-gradient(180deg, var(--brand-200), var(--brand-500));
  box-shadow: 0 0 12px rgb(var(--brand-500-rgb) / 0.6);
}

.tl-step {
  position: relative;
  margin: 0;
  padding-bottom: 52px;
}

.tl-step:last-child {
  padding-bottom: 0;
}

.tl-dot {
  position: absolute;
  left: -52px;
  top: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--stage-bg);
  border: 2px solid var(--brand-500);
  box-shadow:
    0 0 0 5px rgb(var(--brand-500-rgb) / 0.12),
    0 0 18px rgb(var(--brand-500-rgb) / 0.45);
  z-index: 1;
}

.step-n {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--stage-accent);
  margin-bottom: 10px;
  font-variant-numeric: tabular-nums;
}

.tl-step h3 {
  font-size: 1.45rem;
  margin-bottom: 10px;
}

.tl-step p {
  max-width: 54ch;
  margin: 0;
}

/* --------------------------------------------------------------- split */

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
  align-items: center;
}

.checks {
  list-style: none;
  padding: 0;
  margin: var(--s4) 0 0;
}

.checks li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 14px;
  color: var(--text);
  font-weight: 500;
}

.checks .icon {
  width: 22px;
  height: 22px;
  padding: 3px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-ink);
  margin-top: 1px;
}

/* --------------------------------------------------------------- orbit */

.orbit {
  position: relative;
  width: 100%;
  max-width: 460px;
  aspect-ratio: 1;
  margin: 0 auto;
}

.orbit::before {
  content: '';
  position: absolute;
  inset: 20%;
  border-radius: 50%;
  background: radial-gradient(circle, rgb(var(--brand-500-rgb) / 0.22), transparent 70%);
  filter: blur(20px);
}

.orbit-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 104px;
  height: 104px;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  border-radius: 30px;
  background: var(--glass-bg);
  border: 1px solid var(--glass-line);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: var(--glass-shadow);
  z-index: 2;
}

.orbit-core .logo {
  width: 52px;
  height: 52px;
}

.orbit-ring {
  position: absolute;
  list-style: none;
  margin: 0;
  padding: 0;
  border-radius: 50%;
  border: 1px dashed color-mix(in srgb, var(--primary) 35%, transparent);
  animation: spin 60s linear infinite;
}

.ring-in {
  inset: 24%;
}

.ring-out {
  inset: 3%;
  animation-duration: 90s;
  animation-direction: reverse;
}

.orbit-item {
  position: absolute;
  margin: 0;
  transform: translate(-50%, -50%);
}

/* Counter-rotation keeps every label upright while its ring turns. */
.orbit-item span {
  display: inline-block;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  animation: spin 60s linear infinite reverse;
}

.ring-out .orbit-item span {
  animation-duration: 90s;
  animation-direction: normal;
}

/* Points on a circle: left = 50% + 50%·cos θ, top = 50% + 50%·sin θ. */
.o1 {
  left: 50%;
  top: 0%;
}
.o2 {
  left: 93.3%;
  top: 75%;
}
.o3 {
  left: 6.7%;
  top: 75%;
}
.o4 {
  left: 50%;
  top: 0%;
}
.o5 {
  left: 97.6%;
  top: 34.5%;
}
.o6 {
  left: 79.4%;
  top: 90.5%;
}
.o7 {
  left: 20.6%;
  top: 90.5%;
}
.o8 {
  left: 2.4%;
  top: 34.5%;
}

/* ----------------------------------------------------------- work card */

.work-card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  gap: var(--s6);
  align-items: center;
  padding: 64px;
  border-radius: var(--r-2xl);
  background:
    radial-gradient(40rem 26rem at 100% 100%, rgb(var(--brand-500-rgb) / 0.14), transparent 60%),
    var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  isolation: isolate;
}

.work-copy p {
  max-width: 46ch;
}

/* Three phones fanned out, the middle one lifted. */
.fan {
  position: relative;
  height: 470px;
}

.fan .device {
  position: absolute;
  width: 196px;
  max-width: none;
  top: 50px;
  transition: transform 500ms var(--ease-out);
}

.fan .device:nth-child(1) {
  left: 2%;
  transform: rotate(-9deg);
}

.fan .device:nth-child(2) {
  left: 50%;
  top: 0;
  width: 214px;
  transform: translateX(-50%);
  z-index: 2;
}

.fan .device:nth-child(3) {
  right: 2%;
  transform: rotate(9deg);
}

.work-card:hover .fan .device:nth-child(1) {
  transform: rotate(-13deg) translateX(-12px);
}

.work-card:hover .fan .device:nth-child(2) {
  transform: translateX(-50%) translateY(-10px);
}

.work-card:hover .fan .device:nth-child(3) {
  transform: rotate(13deg) translateX(12px);
}

/* ----------------------------------------------------------------- CTA */

@property --angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.cta-card {
  position: relative;
  text-align: center;
  padding: 88px 40px;
  border-radius: var(--r-2xl);
  background:
    radial-gradient(40rem 20rem at 50% 0%, rgb(var(--brand-500-rgb) / 0.16), transparent 70%),
    var(--surface);
  box-shadow: var(--shadow-card);
}

.cta-card .lede {
  margin-left: auto;
  margin-right: auto;
}

.cta-card .actions {
  justify-content: center;
}

/* A light travelling round the border. The fill is painted on the padding box
   and the conic sweep on the border box, so only the 1px edge shows it. */
.glow-border {
  border: 1px solid transparent;
  background:
    radial-gradient(40rem 20rem at 50% 0%, rgb(var(--brand-500-rgb) / 0.16), transparent 70%) padding-box,
    linear-gradient(var(--surface), var(--surface)) padding-box,
    conic-gradient(
        from var(--angle),
        var(--border) 0deg,
        var(--border) 250deg,
        var(--brand-500) 300deg,
        var(--brand-200) 330deg,
        var(--border) 360deg
      )
      border-box;
  animation: angle 7s linear infinite;
}

/* ------------------------------------------------------------ services */

/* Under the home bento: the way on to the full list. */
.section-more {
  margin-top: var(--s5);
}

/* Three commitments under the services hero, each one already made elsewhere
   on the site. A row on a desk, a list on a phone. */
.facts {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 28px;
  list-style: none;
  padding: var(--s4) 0 0;
  margin: var(--s5) 0 0;
  border-top: 1px solid var(--border);
}

.facts li {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
}

.facts .icon {
  width: 20px;
  height: 20px;
  color: var(--primary-ink);
}

/* Two columns of cards. The fifth, alone on its row, takes the full width
   and lays itself out in two columns — what it is on the left, what it
   includes on the right — rather than leaving half a card empty. */
.service-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}

.service {
  display: flex;
  flex-direction: column;
}

.service:last-child:nth-child(odd) {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto 1fr auto;
  column-gap: var(--s6);
}

.service:last-child:nth-child(odd) > .checks {
  grid-column: 2;
  grid-row: 1 / span 4;
  align-self: center;
  margin: 0;
}

.service:last-child:nth-child(odd) > .tile-icon {
  justify-self: start;
}

.service h3 {
  font-size: 1.35rem;
}

.service > p {
  max-width: 52ch;
}

.service .checks {
  margin: var(--s2) 0 var(--s4);
}

.service .checks li {
  font-size: 15.5px;
  margin-bottom: 10px;
}

/* margin-top:auto pins the link to the foot of the card, so links in a row
   line up however long the lists above them are. */
.service-link {
  margin-top: auto;
  align-self: flex-start;
  font-weight: 600;
}

.grid.reasons {
  grid-template-columns: repeat(2, 1fr);
}

/* Common questions: native <details>, so they open and close with no script
   and a keyboard or screen reader gets the expanded state for free. */
.faq-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: var(--s6);
  align-items: start;
}

.faq-wrap .section-head {
  margin-bottom: 0;
}

.faq details {
  border-bottom: 1px solid var(--border);
}

.faq details:first-child {
  border-top: 1px solid var(--border);
}

.faq summary {
  position: relative;
  padding: 20px 40px 20px 0;
  color: var(--text);
  font-size: 1.1rem;
  font-weight: 650;
  line-height: 1.4;
  list-style: none;
  cursor: pointer;
}

.faq summary::-webkit-details-marker {
  display: none;
}

/* A plus that turns into a minus: the horizontal bar stays, the vertical one
   goes when the answer is open. */
.faq summary::before,
.faq summary::after {
  content: '';
  position: absolute;
  right: 6px;
  top: 50%;
  width: 14px;
  height: 2px;
  border-radius: 1px;
  background: var(--primary-ink);
}

.faq summary::after {
  transform: rotate(90deg);
}

.faq details[open] summary::after {
  display: none;
}

.faq details p {
  margin: 0 0 22px;
  max-width: 60ch;
}

/* ---------------------------------------------------- sap business one */

/* The six add-ons under the two apps: three across, smaller type, so the
   apps read as the larger pieces of work they are. */
.addon-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 18px;
}

.addon-grid .service {
  padding: var(--s4);
}

.addon-grid .service h3 {
  font-size: 1.15rem;
}

.addon-grid .service > p {
  font-size: 15.5px;
}

.addon-grid .service .checks li {
  font-size: 14.5px;
}

.built-to-order h2 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
}

.built-to-order > p {
  max-width: 62ch;
}

.built-to-order .checks {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--s5);
}

/* On the home page: the apps and add-ons by name, beside the pitch. */
.addon-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.addon-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
}

.addon-list .icon {
  color: var(--primary-ink);
}

/* ------------------------------------------------------ the story pages */

/* A light band between plain sections — the rhythm of .band without going
   dark. The same spacing rules as .band, for the same reasons. */
.tint {
  background: var(--surface);
  border-block: 1px solid var(--border);
  padding: var(--s7) 0;
  margin: 0 0 var(--s7);
}

section + .tint {
  padding-top: var(--s7);
}

/* Two bands back to back meet edge to edge, not across a strip of page. */
.tint:has(+ .band),
.band:has(+ .tint),
.band:has(+ .band),
.tint:has(+ .tint) {
  margin-bottom: 0;
}

/* After the dark hero the next section needs its own top space: the hero's
   padding is inside the dark, not between it and what follows. */
.hero-dark + section:not(.band):not(.tint) {
  padding-top: var(--s7);
}

/* How a project runs: the heading on the left, the four stages beside it. */
.process {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.2fr);
  gap: var(--s6);
  align-items: start;
}

.process .section-head {
  margin-bottom: 0;
}

.band .checks li {
  color: var(--stage-text);
}

.band .checks .icon {
  background: rgb(var(--brand-300-rgb) / 0.14);
  color: var(--stage-accent);
}

/* Cards that are one big link: the heading's link stretches over the whole
   card, so the card is one tab stop with a sensible name, and the ring goes
   round the card rather than round two words of its title. */
.pillar,
.addon-tile,
.industry {
  position: relative;
}

.pillar h3 a,
.addon-tile h3 a,
.industry h3 a {
  color: var(--text);
  text-decoration: none;
}

.pillar h3 a::after,
.addon-tile h3 a::after,
.industry h3 a::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.pillar h3 a:focus-visible,
.addon-tile h3 a:focus-visible,
.industry h3 a:focus-visible {
  outline: none;
}

.pillar:has(a:focus-visible),
.addon-tile:has(a:focus-visible),
.industry:has(a:focus-visible) {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* --- the home hero: a dashboard, and an approval waiting on a phone */

.erp-scene .dash-window {
  width: 66%;
  top: 4%;
}

.erp-scene .scene-phone {
  width: 37%;
  top: 14%;
  z-index: 2;
}

.dash {
  padding: 16px 18px 18px;
}

.kpis {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

.kpi {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 11px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.07);
  min-width: 0;
}

.kpi span {
  font-size: 10px;
  line-height: 1.3;
  color: var(--stage-secondary);
}

.kpi b {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--stage-text);
  white-space: nowrap;
}

.kpi em {
  font-style: normal;
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-300);
}

.dash-chart {
  display: block;
  width: 100%;
  height: 92px;
  margin: 14px 0 8px;
}

.eb {
  fill: rgb(var(--brand-300-rgb) / 0.26);
}

.eb.now {
  fill: var(--brand-500);
}

.eline {
  fill: none;
  stroke: var(--brand-200);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.dash-rows {
  list-style: none;
  margin: 0;
  padding: 0;
}

.dash-rows li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 7px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 11px;
  color: var(--stage-secondary);
}

.dash-rows i {
  flex: none;
  font-style: normal;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: var(--r-pill);
}

.dash-rows .ok {
  color: var(--brand-200);
  background: rgb(var(--brand-300-rgb) / 0.12);
}

.dash-rows .wait {
  color: #f0c27b;
  background: rgba(240, 194, 123, 0.12);
}

/* A phone drawn in markup, always in the app's light theme: it is a picture
   of a screen, and a light screen on the dark hero reads as a device. */
.mock-phone {
  aspect-ratio: 9 / 18.5;
  padding: 8px;
  border-radius: 34px;
  background: var(--bezel);
  box-shadow:
    var(--shadow-device),
    inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.mock-screen {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
  padding: 30px 11px 12px;
  border-radius: 27px;
  background: #f5f5f4;
  overflow: hidden;
}

.mock-screen .mp-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 2px 2px;
  font-size: 15px;
  font-weight: 700;
  color: #1c1917;
}

.mp-title span {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  border-radius: 9px;
  background: var(--brand-700);
  color: #fff;
  font-size: 10px;
}

.mp-card {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 12px;
  border-radius: 14px;
  background: #fff;
  border: 1px solid #e7e5e4;
  box-shadow: 0 6px 16px -10px rgba(28, 25, 23, 0.3);
}

.mp-tag {
  font-size: 10px;
  font-weight: 700;
  color: var(--brand-700);
}

.mp-card b {
  font-size: 17px;
  letter-spacing: -0.01em;
  color: #1c1917;
}

.mp-sub {
  font-size: 10px;
  color: #6b6560;
}

.mp-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 8px;
}

.mp-actions span {
  padding: 7px 0;
  border-radius: var(--r-pill);
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
}

.mp-yes {
  background: var(--brand-700);
  color: #fff;
}

.mp-no {
  background: #ecebe9;
  color: #57534e;
}

.mp-dim {
  opacity: 0.8;
}

.mock-screen .mp-label {
  margin: 4px 2px 0;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6b6560;
}

.mp-done .mp-sub {
  color: var(--brand-700);
  font-weight: 600;
}

.erp-scene .cf2 {
  bottom: 3%;
}

/* --- SAP Business One as a hub, and its modules */

.module-map {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  margin: 0 auto;
  overflow: visible;
}

.mm-glow {
  fill: rgb(var(--brand-500-rgb) / 0.1);
}

.mm-ring {
  fill: none;
  stroke: color-mix(in srgb, var(--primary) 30%, transparent);
  stroke-dasharray: 4 6;
}

.mm-line {
  stroke: color-mix(in srgb, var(--primary) 38%, transparent);
  stroke-width: 1.5;
}

/* The centre is the same deep teal in both themes, with white words on it. */
.mm-core {
  fill: var(--brand-800);
}

.mm-core-t {
  fill: #fff;
  font: 700 20px var(--font);
  letter-spacing: -0.01em;
}

.mm-core-s {
  fill: rgba(255, 255, 255, 0.82);
  font: 500 13px var(--font);
}

.mm-node {
  fill: var(--surface);
  stroke: var(--border-strong);
}

.mm-ico {
  color: var(--primary-ink);
}

.mm-label {
  fill: var(--text);
  font: 600 14px var(--font);
}

.module-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.module {
  padding: var(--s4);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--border);
}

.module .tile-icon {
  margin-bottom: var(--s3);
}

.module h3 {
  font-size: 1.08rem;
  margin-bottom: 6px;
}

.module p {
  margin: 0;
  font-size: 14.5px;
}

/* --- one document becomes the next */

.flows {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.flow {
  padding: var(--s4) var(--s5);
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}

.flow h3 {
  font-size: 1.1rem;
  margin-bottom: var(--s3);
}

.flow ol {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: step;
}

.flow li {
  position: relative;
  margin: 0;
  padding: 12px 14px;
  border-radius: 12px;
  background: var(--primary-soft);
  color: var(--text);
  font-size: 14.5px;
  font-weight: 600;
  line-height: 1.3;
  counter-increment: step;
}

.flow li::before {
  content: counter(step);
  display: block;
  margin-bottom: 2px;
  font-size: 11px;
  font-weight: 700;
  color: var(--primary-ink);
}

/* A chevron in the gap, pointing at the next document. */
.flow li:not(:last-child)::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -19px;
  width: 9px;
  height: 9px;
  border-top: 2px solid var(--primary-ink);
  border-right: 2px solid var(--primary-ink);
  transform: translateY(-50%) rotate(45deg);
}

/* --- reporting and analytics, in the dark band */

.analytics-art {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  margin: 0 auto;
}

.an-card {
  fill: rgba(255, 255, 255, 0.05);
  stroke: rgba(255, 255, 255, 0.12);
}

.an-h {
  fill: var(--stage-text);
  font: 700 16px var(--font);
}

.an-kpi {
  fill: rgba(255, 255, 255, 0.05);
  stroke: rgba(255, 255, 255, 0.08);
}

.an-k {
  fill: var(--stage-secondary);
  font: 500 11px var(--font);
}

.an-v {
  fill: var(--stage-text);
  font: 700 17px var(--font);
}

.an-grid {
  stroke: rgba(255, 255, 255, 0.07);
}

.an-area {
  fill: rgb(var(--brand-500-rgb) / 0.16);
}

.an-line {
  fill: none;
  stroke: var(--brand-300);
  stroke-width: 2.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.an-dot {
  fill: var(--stage-bg);
  stroke: var(--brand-300);
  stroke-width: 2;
}

.an-track,
.an-s1,
.an-s2,
.an-s3 {
  fill: none;
  stroke-width: 16;
}

.an-track {
  stroke: rgba(255, 255, 255, 0.08);
}

.an-s1 {
  stroke: var(--brand-500);
}

.an-s2 {
  stroke: var(--brand-200);
}

.an-s3 {
  stroke: #e0a455;
}

.ag1 {
  fill: var(--brand-500);
}

.ag2 {
  fill: var(--brand-300);
}

.ag3 {
  fill: #e0a455;
}

.ag4 {
  fill: #dd6e66;
}

/* --- the problems the home page opens with */

.pain-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}

.pain {
  padding: var(--s4);
  border-radius: var(--r-xl);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
}

.pain-icon {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: var(--s3);
  border-radius: 14px;
  background: var(--accent-soft);
  color: var(--accent-ink);
}

.pain-icon .icon {
  width: 22px;
  height: 22px;
}

.pain h3 {
  font-size: 1.08rem;
}

.pain p {
  margin: 0;
  font-size: 15.5px;
}

.pain-turn {
  max-width: 60ch;
  margin: var(--s5) 0 0;
  color: var(--text);
  font-size: 1.2rem;
  font-weight: 600;
}

/* --- three ways in */

.pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}

.pillar {
  display: flex;
  flex-direction: column;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition:
    transform 200ms var(--ease),
    box-shadow 200ms var(--ease);
}

.pillar:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

.pillar-art {
  display: grid;
  place-items: center;
  min-height: 210px;
  padding: 28px 24px 12px;
  background:
    radial-gradient(22rem 12rem at 50% 0%, rgb(var(--brand-500-rgb) / 0.18), transparent 70%),
    var(--surface-alt);
}

.pillar-art .bento-art {
  max-width: 280px;
  margin: 0;
}

.pillar-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: var(--s4) var(--s4) var(--s5);
}

.pillar h3 {
  font-size: 1.35rem;
}

.pillar-body p {
  flex: 1;
}

.pillar-more {
  font-weight: 600;
  color: var(--primary-ink);
}

/* --- apps and add-ons as tiles */

.addon-tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.addon-tile {
  padding: var(--s4);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition:
    transform 200ms var(--ease),
    border-color 200ms var(--ease);
}

.addon-tile:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
}

.addon-tile .tile-icon {
  margin-bottom: var(--s3);
}

.addon-tile h3 {
  font-size: 1.05rem;
  margin-bottom: 6px;
}

.addon-tile p {
  margin: 0;
  font-size: 14.5px;
}

/* --- industries: a picture for each, drawn from a gradient, a grid and an icon */

.industry-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}

.industry {
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  transition:
    transform 200ms var(--ease),
    box-shadow 200ms var(--ease);
}

.industry:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
}

.industry-art {
  position: relative;
  display: grid;
  place-items: center;
  height: 150px;
  overflow: hidden;
  color: rgba(255, 255, 255, 0.94);
  isolation: isolate;
}

.industry-art::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.09) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.09) 1px, transparent 1px);
  background-size: 28px 28px;
  -webkit-mask-image: radial-gradient(circle at 70% 30%, #000, transparent 75%);
  mask-image: radial-gradient(circle at 70% 30%, #000, transparent 75%);
}

.industry-art::after {
  content: '';
  position: absolute;
  z-index: -1;
  width: 220px;
  height: 220px;
  right: -60px;
  top: -80px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.22), transparent 65%);
}

.industry-art .icon {
  width: 64px;
  height: 64px;
  stroke-width: 1.3;
}

.ind-manufacturing .industry-art {
  background: linear-gradient(135deg, var(--brand-950), var(--brand-800) 60%, var(--brand-600));
}

.ind-distribution .industry-art {
  background: linear-gradient(135deg, #12403c, #0f766e 60%, #14a394);
}

.ind-food .industry-art {
  background: linear-gradient(135deg, #1b3a22, #3a7449 60%, #5e9e6b);
}

.ind-process .industry-art {
  background: linear-gradient(135deg, #261d42, #54428a 60%, #8a6bc0);
}

.ind-engineering .industry-art {
  background: linear-gradient(135deg, #3a2410, #8f5714 60%, #c77f2e);
}

.ind-trading .industry-art {
  background: linear-gradient(135deg, #1f2a24, #3e5a4c 60%, #6b8f7a);
}

.industry-body {
  padding: var(--s4);
}

.industry h3 {
  font-size: 1.2rem;
  margin-bottom: 4px;
}

.industry-body p {
  margin: 0;
  font-size: 15.5px;
}

/* The industries page: one wide card per industry, picture on the left. */
.industry-list {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
}

.industry-detail {
  display: grid;
  grid-template-columns: 260px 1fr;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  scroll-margin-top: 90px;
}

.industry-detail .industry-art {
  height: auto;
  min-height: 220px;
}

.industry-detail .industry-art .icon {
  width: 84px;
  height: 84px;
}

.industry-copy {
  padding: var(--s5);
}

.industry-copy h2 {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  margin-bottom: 6px;
}

.industry-line {
  margin-bottom: var(--s4);
  font-size: 1.1rem;
}

.industry-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s5);
}

.industry-cols h3 {
  margin-bottom: var(--s3);
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

.industry-cols ul:not(.checks) {
  margin: 0;
  padding-left: 1.1em;
}

.industry-cols .checks {
  margin: 0;
}

.industry-cols .checks li {
  margin-bottom: 10px;
  font-size: 15.5px;
}

.industry-note {
  font-size: 1.05rem;
}

/* --- pictures for the inner pages' heroes */

/* The facts row on the dark hero (custom software). */
.hero-dark .facts {
  border-top-color: rgba(255, 255, 255, 0.12);
}

.hero-dark .facts li {
  color: var(--stage-text);
}

.hero-dark .facts .icon {
  color: var(--stage-accent);
}

/* SAP Business One at a glance: a definition list as a fact sheet. */
.spec {
  margin: 0;
  padding: var(--s3) var(--s5);
  border-radius: var(--r-xl);
  background: var(--bg);
  border: 1px solid var(--border);
}

.spec div {
  display: grid;
  grid-template-columns: 9.5rem 1fr;
  gap: var(--s3);
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.spec div:last-child {
  border-bottom: 0;
}

.spec dt {
  color: var(--text-secondary);
  font-size: 14px;
  font-weight: 600;
}

.spec dd {
  margin: 0;
  color: var(--text);
  font-weight: 600;
}

/* The add-ons page: all eight by name, standing in for a picture. */
.addon-hero li {
  padding: 18px 18px;
  font-size: 15.5px;
  box-shadow: var(--shadow-card);
}

.addon-hero .icon {
  width: 22px;
  height: 22px;
}

/* The industries page: the six pictures as a mosaic. */
.ind-mosaic {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.ind-mosaic li {
  margin: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}

.ind-mosaic .industry-art {
  height: 150px;
  align-content: center;
  gap: 10px;
  text-align: center;
}

.ind-mosaic .industry-art .icon {
  width: 40px;
  height: 40px;
}

.ind-mosaic span {
  padding: 0 10px;
  font-size: 13px;
  font-weight: 650;
  line-height: 1.3;
  color: #fff;
}

.erp-scene .cf3 {
  right: auto;
  left: 6%;
  bottom: auto;
  top: -2%;
}

/* ============================================================== 7 product */

.hero-copy .mark,
.prose > .mark {
  display: block;
  height: 44px;
  width: auto;
  color: var(--primary);
  margin-bottom: var(--s4);
}

.phone-stage {
  position: relative;
  justify-self: center;
  width: 100%;
  max-width: 330px;
}

.phone-stage .device {
  max-width: 300px;
  margin: 0 auto;
}

.pf1 {
  top: 14%;
  left: -18%;
}
.pf2 {
  top: 48%;
  right: -22%;
  animation-delay: -2.5s;
}
.pf3 {
  bottom: 12%;
  left: -14%;
  animation-delay: -4.5s;
}

/* ------------------------------------------------------------ the story */

/*
  Without JavaScript, or on a narrow screen, the story is a column of steps,
  each with its own phone. With JavaScript on a wide screen (.js-story), the
  inline phones hide, one pinned phone appears beside the text, and site.js
  cross-fades its screen as each step reaches the middle of the viewport.
*/
.story-section {
  padding-top: var(--s6);
}

.story {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
}

.story-step {
  padding: var(--s6) 0;
}

.story-step p {
  max-width: 46ch;
}

.story-step .device {
  margin: var(--s5) auto 0;
  max-width: 280px;
}

.story-stage {
  display: none;
}

.js-story .story-step {
  min-height: 86vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0.25;
  transition: opacity 450ms var(--ease);
}

.js-story .story-step.active {
  opacity: 1;
}

.js-story .story-step .device {
  display: none;
}

.js-story .story-stage {
  display: block;
  position: sticky;
  top: calc(50vh - 320px);
  align-self: start;
  height: 660px;
}

.story-device {
  position: relative;
  max-width: 304px;
  margin: 0 auto;
}

.story-device .story-screen {
  position: absolute;
  inset: 9px;
  width: auto;
  height: auto;
  border-radius: 38px;
  overflow: hidden;
  opacity: 0;
  transform: scale(1.02);
  transition:
    opacity 550ms var(--ease),
    transform 700ms var(--ease-out);
}

.story-device .story-screen.active {
  opacity: 1;
  transform: none;
}

.story-screen img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
}

/* ============================================================== 8 contact */

.contact-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: var(--s6);
  align-items: start;
}

.next {
  list-style: none;
  padding: 0;
  margin: var(--s5) 0;
}

.next li {
  display: flex;
  gap: 16px;
  margin-bottom: 20px;
}

.next li > span {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-ink);
  font-weight: 700;
  font-size: 14px;
}

.next strong {
  display: block;
  margin-bottom: 2px;
}

.next p {
  margin: 0;
  font-size: 15px;
}

.contact-direct {
  font-size: 15px;
}

.enquiry {
  padding: 36px;
  border-radius: var(--r-2xl);
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-bottom: 18px;
  min-width: 0;
}

.field label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}

.field .opt {
  font-weight: 500;
  color: var(--text-muted);
  font-size: 12.5px;
  margin-left: 4px;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  font: inherit;
  font-size: 16px; /* 16px stops iOS zooming into the field on focus */
  padding: 12px 14px;
  border-radius: 13px;
  border: 1px solid var(--field-line);
  background: var(--surface);
  color: var(--text);
  transition:
    border-color 150ms var(--ease),
    box-shadow 150ms var(--ease);
}

.field textarea {
  resize: vertical;
  min-height: 140px;
  line-height: 1.55;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--text-muted);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: var(--primary-ink);
}

.field-error {
  display: none;
  font-size: 13px;
  color: var(--danger);
}

/* Server-side refusals (site.js marks .invalid) and the browser's own
   validation once the person has interacted (:user-invalid) look the same. */
.field.invalid input,
.field.invalid select,
.field.invalid textarea,
.field :user-invalid {
  border-color: var(--danger);
}

.field.invalid .field-error,
.field:has(:user-invalid) .field-error {
  display: block;
}

/* The honeypot: off-screen rather than display:none, which some bots skip. */
.hp {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  flex-wrap: wrap;
  margin-top: 6px;
}

.consent {
  font-size: 13.5px;
  margin: 0;
  max-width: 38ch;
}

.form-status {
  margin: 16px 0 0;
  min-height: 1.5em;
  font-size: 15px;
  font-weight: 500;
}

.form-status[data-kind='pending'] {
  color: var(--text-muted);
}
.form-status[data-kind='ok'] {
  color: var(--success);
}
.form-status[data-kind='error'] {
  color: var(--danger);
}

.enquiry.sent .form-status {
  padding: 14px 16px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--success) 12%, transparent);
}

/* ======================================================== 9 shared pieces */

.glass {
  background: var(--glass-bg);
  backdrop-filter: blur(22px) saturate(180%);
  -webkit-backdrop-filter: blur(22px) saturate(180%);
  border: 1px solid var(--glass-line);
  box-shadow: var(--glass-shadow);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
}

.grid.two {
  grid-template-columns: repeat(2, 1fr);
}

/* The Hiyava plans: three across on a desktop, two over one below 1040px,
   one column on a phone (section 11). */
.grid.plans {
  grid-template-columns: repeat(3, 1fr);
}

.plans-note {
  margin-top: var(--s4);
  color: var(--text-secondary);
  font-size: 15px;
}

.card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--s5);
  box-shadow: var(--shadow-card);
  transition:
    transform 200ms var(--ease),
    box-shadow 200ms var(--ease),
    border-color 200ms var(--ease);
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lift);
}

.card p:last-child {
  margin-bottom: 0;
}

.card h3 {
  color: var(--text);
}

.panel {
  background: var(--surface-alt);
  border-radius: var(--r-2xl);
  padding: var(--s6) var(--s5);
}

.panel p:last-child,
.panel ul:last-child {
  margin-bottom: 0;
}

.about-mark {
  justify-self: center;
  width: min(260px, 60%);
  filter: drop-shadow(0 30px 40px rgb(var(--brand-500-rgb) / 0.35));
}

.about-mark .logo {
  width: 100%;
  height: auto;
  display: block;
}

/* A phone, drawn in CSS around a real screenshot. The aspect ratio is the
   capture viewport (390x844), so the frame never reflows when the PNG lands. */
.device {
  margin: 0;
  width: 100%;
  max-width: 300px;
  aspect-ratio: 390 / 844;
  padding: 9px;
  border-radius: 46px;
  background: var(--bezel);
  box-shadow:
    var(--shadow-device),
    inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.device > picture,
.device > img,
.device > picture img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 38px;
  object-fit: cover;
  object-position: top;
}

/* ------------------------------------------------------- legal documents */

.doc-meta {
  color: var(--text-muted);
  font-size: 14px;
  margin: 0 0 var(--s5);
}

.doc h1 {
  font-size: clamp(2.2rem, 5vw, 3.4rem);
}

.doc h2 {
  font-size: 1.3rem;
  letter-spacing: -0.01em;
  margin-top: var(--s5);
  margin-bottom: var(--s2);
}

.doc .intro {
  font-size: 1.0625rem;
  color: var(--text);
  margin-bottom: var(--s5);
}

.prose h2 {
  font-size: clamp(1.5rem, 2.6vw, 2rem);
  margin-top: var(--s6);
}

.prose h2:first-child {
  margin-top: 0;
}

/* ================================================================ 10 motion */

/*
  The revealed state ends at transform:none, so never put data-reveal on an
  element that is positioned by its own transform — the fanned phones, the
  centred middle one, anything rotated. Reveal its container instead. Phone
  figures do not carry it for exactly this reason: the fan lost its rotation
  and its centring, and the middle phone landed on top of the third.
*/
.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(28px);
}

.js-reveal [data-reveal].revealed {
  opacity: 1;
  transform: none;
  transition:
    opacity 700ms var(--ease-out),
    transform 800ms var(--ease-out);
}

/* Siblings stagger, capped so the last never keeps anyone waiting. */
.js-reveal [data-reveal]:nth-child(2).revealed {
  transition-delay: 70ms;
}
.js-reveal [data-reveal]:nth-child(3).revealed {
  transition-delay: 140ms;
}
.js-reveal [data-reveal]:nth-child(4).revealed {
  transition-delay: 210ms;
}
.js-reveal [data-reveal]:nth-child(5).revealed {
  transition-delay: 280ms;
}
.js-reveal [data-reveal]:nth-child(6).revealed {
  transition-delay: 350ms;
}

@keyframes drift-a {
  to {
    transform: translate3d(-3%, 2%, 0) scale(1.08);
  }
}

@keyframes drift-b {
  to {
    transform: translate3d(-8%, 6%, 0) scale(1.14);
  }
}

@keyframes ping {
  0% {
    box-shadow: 0 0 0 0 rgb(var(--brand-500-rgb) / 0.6);
  }
  70%,
  100% {
    box-shadow: 0 0 0 10px rgb(var(--brand-500-rgb) / 0);
  }
}

@keyframes line-in {
  from {
    opacity: 0;
    transform: translateX(-8px);
  }
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

@keyframes bob {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(-10px);
  }
}

@keyframes floor-travel {
  to {
    background-position: 0 44px;
  }
}

@keyframes wire-flow {
  to {
    stroke-dashoffset: -28;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes angle {
  to {
    --angle: 360deg;
  }
}

@keyframes track {
  0%,
  8% {
    stroke-dashoffset: 210;
  }
  70%,
  100% {
    stroke-dashoffset: 0;
  }
}

@keyframes tick {
  0% {
    opacity: 0;
  }
  8%,
  88% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/*
  Somebody who has asked their system for less motion gets the finished page
  with nothing moving. site.js also skips its reveals, story and timeline in
  this case; the form keeps working.
*/
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
  }

  .bento-art .pulse {
    display: none;
  }

  .bento-art .tick {
    opacity: 1;
  }

  .bento-art .track-fill {
    stroke-dashoffset: 0;
  }

}

/* ============================================================ 11 responsive */

@media (max-width: 1040px) {
  .bento {
    grid-template-columns: repeat(2, 1fr);
  }

  .t-wide {
    grid-column: span 2;
  }

  .work-card {
    padding: 48px;
  }

  .grid.plans {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Free and Family side by side, centres and schools across both. */
  .grid.plans > :nth-child(3) {
    grid-column: span 2;
  }
}

@media (max-width: 1040px) {
  .grid.reasons,
  .addon-grid,
  .pain-grid,
  .addon-tiles {
    grid-template-columns: repeat(2, 1fr);
  }

  .module-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  /* Five documents no longer fit a row: they stack, and the chevrons turn
     to point down the list. */
  .flow ol {
    grid-template-columns: 1fr;
    gap: 22px;
    max-width: 420px;
  }

  .flow li:not(:last-child)::after {
    top: auto;
    right: auto;
    bottom: -17px;
    left: 24px;
    transform: rotate(135deg);
  }
}

@media (max-width: 900px) {
  .pillars,
  .process {
    grid-template-columns: 1fr;
  }

  .industry-grid,
  .module-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .industry-detail {
    grid-template-columns: 1fr;
  }

  .industry-detail .industry-art {
    min-height: 150px;
  }

  .industry-cols {
    grid-template-columns: 1fr;
    gap: var(--s4);
  }

  .erp-scene {
    max-width: 520px;
  }
}

@media (max-width: 640px) {
  /* The hero picture at phone size: fewer figures, so what is left can be read. */
  .erp-scene .dash-window {
    width: 70%;
  }

  .erp-scene .scene-phone {
    width: 42%;
  }

  .erp-scene .kpi:nth-child(3),
  .erp-scene .dash-rows li:nth-child(n + 3),
  .erp-scene .mp-dim,
  .erp-scene .mp-label,
  .erp-scene .mp-done,
  .erp-scene .cf3 {
    display: none;
  }

  .kpis {
    grid-template-columns: 1fr 1fr;
  }

  .dash {
    padding: 12px;
  }

  .mock-screen {
    padding: 22px 8px 8px;
  }

  .mp-card {
    padding: 9px;
  }

  .mp-card b {
    font-size: 14px;
  }

  .mp-actions {
    grid-template-columns: 1fr;
  }

  .ind-mosaic .industry-art {
    height: 112px;
  }

  .ind-mosaic span {
    font-size: 11.5px;
  }

  .spec {
    padding: var(--s2) var(--s4);
  }

  .spec div {
    grid-template-columns: 1fr;
    gap: 2px;
  }

  .grid.reasons,
  .pain-grid,
  .addon-tiles,
  .industry-grid,
  .module-grid {
    grid-template-columns: 1fr;
  }

  .industry-copy {
    padding: var(--s4);
  }
}

@media (max-width: 900px) {
  .service-grid,
  .faq-wrap {
    grid-template-columns: 1fr;
  }

  .service:last-child:nth-child(odd) {
    display: flex;
  }

  .service:last-child:nth-child(odd) > .checks {
    margin: var(--s2) 0 var(--s4);
  }

  .faq-wrap {
    gap: var(--s4);
  }

  .built-to-order .checks {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .addon-grid,
  .addon-list {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 900px) {
  .hero-grid,
  .split,
  .work-card,
  .contact-grid,
  .story {
    grid-template-columns: 1fr;
  }

  .hero {
    padding-top: 96px;
  }

  .hero-dark {
    padding-top: 144px;
  }

  .scene {
    max-width: 520px;
  }

  .phone-stage {
    max-width: 280px;
  }

  .fan {
    height: 420px;
    max-width: 520px;
    margin: 0 auto;
    width: 100%;
  }

  .lede,
  .lede.wide {
    max-width: 58ch;
  }

  footer.site .cols {
    grid-template-columns: repeat(2, 1fr);
  }

  .about-mark {
    display: none;
  }
}

@media (max-width: 940px) {
  nav.site a:not(.nav-cta) {
    display: none;
  }

  .menu {
    display: block;
  }

  /* Wordmark, Contact and the menu button share one row: measured at 330px
     of the 343 a 375px phone leaves inside its gutters. */
  header.site .wrap {
    gap: 8px;
  }

  nav.site .nav-cta {
    padding: 7px 14px;
    font-size: 14px;
  }
}

/* Smaller phones: a smaller wordmark at 360px, and the monogram alone on the
   narrowest, so the menu button never leaves the screen. */
@media (max-width: 380px) {
  .wordmark span {
    font-size: 14px;
  }
}

@media (max-width: 340px) {
  .wordmark span {
    display: none;
  }
}

@media (max-width: 640px) {
  .grid.reasons {
    grid-template-columns: 1fr;
  }

  .facts {
    flex-direction: column;
  }
}

@media (max-width: 640px) {
  body {
    font-size: 16px;
  }

  :root {
    --s7: 72px;
  }

  .wrap {
    padding: 0 var(--s3);
  }

  header.site .wrap {
    min-height: 58px;
  }

  .hero-dark {
    margin-top: -58px;
    padding-top: 120px;
  }

  .bento,
  .grid.two,
  .grid.plans,
  .field-row {
    grid-template-columns: 1fr;
  }

  .grid.plans > :nth-child(3) {
    grid-column: auto;
  }

  .t-wide {
    grid-column: auto;
    flex-direction: column;
    align-items: stretch;
  }

  .tile {
    min-height: 0;
    padding: 24px;
  }

  .work-card {
    padding: 28px 22px;
  }

  .fan {
    height: 360px;
  }

  .fan .device {
    width: 150px;
    top: 40px;
  }

  .fan .device:nth-child(2) {
    width: 166px;
  }

  .code {
    font-size: 10.5px;
    padding: 14px;
  }

  .scene-wires,
  .cf3 {
    display: none;
  }

  .chip-float {
    font-size: 11.5px;
    padding: 7px 12px 7px 9px;
  }

  .pf1 {
    left: -6%;
  }
  .pf2 {
    right: -6%;
  }
  .pf3 {
    left: -4%;
  }

  .timeline {
    padding-left: 42px;
  }

  .tl-dot {
    left: -42px;
  }

  .cta-card {
    padding: 56px 22px;
  }

  .enquiry {
    padding: 24px 18px;
  }

  .actions .btn {
    flex: 1 1 100%;
  }

  footer.site .cols {
    grid-template-columns: 1fr;
  }
}

/* ----------------------------------------------- header over a dark hero */

/*
  On pages that open on the dark stage, the header is clear and light-on-dark
  until the reader scrolls past the hero; then it becomes the ordinary glass
  bar. site.js moves the "scrolled" threshold to the hero's bottom edge on
  these pages, so the switch happens where the background changes rather than
  eight pixels in, which would put a pale bar over a dark picture.
*/
/* Dark glass rather than none: at the top it disappears into the dark hero,
   and when the hero scrolls under it the content is blurred instead of
   colliding with the navigation. */
.has-dark-hero header.site:not(.scrolled) {
  background: rgb(var(--brand-950-rgb) / 0.42);
  backdrop-filter: saturate(160%) blur(18px);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  border-bottom-color: rgba(255, 255, 255, 0.06);
}

.has-dark-hero header.site:not(.scrolled) .wordmark {
  color: var(--stage-text);
}

.has-dark-hero header.site:not(.scrolled) .wordmark .logo {
  filter: brightness(1.35);
}

.has-dark-hero header.site:not(.scrolled) nav.site a {
  color: rgb(236 253 245 / 0.72);
}

.has-dark-hero header.site:not(.scrolled) nav.site a:hover {
  color: var(--stage-text);
}

.has-dark-hero header.site:not(.scrolled) nav.site .nav-cta {
  background: var(--stage-text);
  color: var(--stage-bg);
}

.has-dark-hero header.site:not(.scrolled) .menu > summary {
  color: var(--stage-text);
  border-color: rgba(255, 255, 255, 0.18);
}

/* ----------------------------------------------- no sideways scroll, ever */

/*
  A safety net under every page: nothing inside <main> may widen the document.
  `clip`, not `hidden` — clip does not create a scroll container, so the
  pinned phone in the product page story still sticks to the viewport. (hidden
  would silently break position:sticky for everything inside.)

  Found by measuring, not by eye: on a 390px phone the orbit's outer labels,
  swinging past the ring's edge as it turns, made the page 414px wide.
*/
main {
  overflow-x: clip;
}

@media (max-width: 640px) {
  /* Room for the labels to swing out without reaching the edge at all. */
  .orbit {
    max-width: calc(100% - 96px);
  }

  .orbit-item span {
    font-size: 11.5px;
    padding: 5px 10px;
  }
}
