/* ==========================================================================
   AVERRO TECHNOLOGIES — "ATELIER" DESIGN SYSTEM
   Editorial-luxury direction on warm paper. Brand colours kept (indigo for
   action, cyan for signal); the ground moved off pure white so ink and accent
   both have somewhere to sit.

   This file is keyed to the class vocabulary the existing pages already use,
   so every page picks up the new look without markup surgery. Two conventions
   carry most of the visual weight:

     · Card surfaces get a hairline, a warm inset highlight and a wide, soft
       ambient shadow — never a hard drop shadow.
     · `.btn .arrow` is rendered as a circular icon well inside the button, so
       the existing `<span class="arrow">&rarr;</span>` markup becomes the
       nested-icon CTA with no HTML change.

   Motion rules held throughout:
     · UI feedback stays under 300ms. Scroll reveals are longer by design —
       that is content arriving, not the interface answering a click.
     · Only transform / opacity / clip-path animate. Nothing touches layout.
     · Custom easing only; the stock CSS curves are too weak to read as
       intentional. Never ease-in on UI.
     · Every hover is gated behind (hover:hover) so touch does not fire it.
   ========================================================================== */

/* Generated by fetch-fonts.mjs. Do not edit by hand -- edit the generator.
   Latin subset, self-hosted. font-display:swap so text paints in the fallback
   immediately and reflows once, rather than being invisible while the font
   loads. A weight RANGE on a face means that file is a variable font covering
   the whole range from a single download.
   Both families are SIL OFL 1.1; see OFL.md. */
@font-face{
  font-family:"Newsreader";
  font-style:italic;
  font-weight:400;
  font-display:swap;
  src:url("../fonts/newsreader-400-italic.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:"Newsreader";
  font-style:normal;
  font-weight:400;
  font-display:swap;
  src:url("../fonts/newsreader-400.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face{
  font-family:"Schibsted Grotesk";
  font-style:normal;
  font-weight:400 700;
  font-display:swap;
  src:url("../fonts/schibsted-grotesk-var.woff2") format("woff2");
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root{
  --font-display:"Newsreader",Georgia,"Times New Roman",serif;
  --font-sans:"Schibsted Grotesk",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:ui-monospace,"Cascadia Mono",Consolas,"SF Mono",Menlo,monospace;

  /* Ground: warm paper, not pure white. Ink: deep indigo-black, not #000 —
     on a light page a pure-black slab reads as a hole punched in the sheet. */
  --paper:#FBFAF7;
  --bg:#FBFAF7;
  --bg-2:#F4F1EB;
  --surface:#FFFFFF;
  --surface-2:#F4F1EB;
  --card:#FFFFFF;
  --ink:#14131A;
  --heading:#14131A;
  --text:#3D3B47;
  --text-muted:#6B6875;
  --muted:#6B6875;
  --border:rgba(20,19,26,.09);
  --border-strong:rgba(20,19,26,.16);
  --hair:rgba(20,19,26,.09);
  --hair-2:rgba(20,19,26,.16);

  --primary:#4F46E5;
  --indigo:#4F46E5;
  --primary-2:#3730A3;
  --accent:#0E7490;
  --cyan:#0E7490;
  --on-primary:#ffffff;
  --grad:linear-gradient(120deg,#4F46E5 0%,#3730A3 55%,#0E7490 100%);
  --glow:rgba(79,70,229,.24);
  --ring:rgba(79,70,229,.55);

  /* Ink blocks (footer, CTA bands, bleed statements). */
  --ink-2:#1C1B24;
  --on-ink:#FFFFFF;
  --ink-muted:rgba(255,255,255,.62);
  --ink-border:rgba(255,255,255,.13);
  --accent-on-ink:#67E8F9;

  /* Spacing scale: 4 / 8 / 16 / 24 / 32 / 48 / 64 / 96. Use these, not stray px. */
  --s-1:.25rem; --s-2:.5rem; --s-3:1rem; --s-4:1.5rem;
  --s-5:2rem;   --s-6:3rem;  --s-7:4rem; --s-8:6rem;

  /* Elevation: a tight shadow for the crisp edge plus a wide soft one for
     atmosphere. One shadow alone reads as fog. */
  --sh-1:0 1px 2px rgba(20,19,26,.04);
  --lift-1:0 1px 2px rgba(20,19,26,.04), 0 8px 24px -12px rgba(20,19,26,.10);
  --lift-2:0 2px 4px rgba(20,19,26,.04), 0 24px 56px -24px rgba(20,19,26,.16);
  --lift-3:0 4px 8px rgba(20,19,26,.05), 0 48px 96px -40px rgba(20,19,26,.22);
  --sh-2:var(--lift-1); --sh-3:var(--lift-2); --sh-4:var(--lift-3);
  --card-shadow:var(--lift-1);
  --inner-hi:inset 0 1px 0 rgba(255,255,255,.9);

  --ease-out:cubic-bezier(.23,1,.32,1);
  --ease-in-out:cubic-bezier(.77,0,.175,1);
  --ease-drawer:cubic-bezier(.32,.72,0,1);

  --r-lg:28px; --r-md:20px; --r-sm:12px;
}

/* ---------- Reset & base -------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  margin:0;font-family:var(--font-sans);font-size:1.0625rem;line-height:1.65;
  background:var(--paper);color:var(--text);overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}
/* ---------- Backdrop: the tesseract fall (home page only) -----------------
   The canvas is fixed behind everything and paints --paper itself, so the body
   must stop painting its own ground — a z-index:-1 element sits BEHIND the
   body background and would otherwise never be seen. .has-backdrop is set by
   main.js only when the canvas is actually in the page, so every other page,
   and any browser where the script does not run, keeps the plain paper ground. */
#tunnel{position:fixed;inset:0;width:100%;height:100%;display:block;
  z-index:-1;pointer-events:none}
body.has-backdrop{background:transparent}

img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
::selection{background:rgba(79,70,229,.16)}

/* Film grain. Fixed and pointer-events:none, so it never repaints on scroll. */
body::after{
  content:"";position:fixed;inset:0;z-index:60;pointer-events:none;opacity:.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* The particle-globe canvases belong to the previous direction. Atelier is
   paper and ink; a WebGL-ish starfield fights it. Hidden here so the pages stay
   valid even where the canvas element is still in the markup.

   NOTE: this list is class selectors only. The tesseract backdrop is `#tunnel`
   (an id) and is deliberately live again — see the backdrop block above. Do not
   add `#tunnel` here. */
/* .scene / .tunnel-veil are gone from the markup and scene.js was deleted;
   only .glowball survives, on the contact page's panel. */
.glowball{display:none!important}

/* Leaving the site is information, so mark it. */
a[target="_blank"]:not(.btn)::after{content:"\2197";margin-left:.25em;font-size:.85em;opacity:.6}
.socials a[target="_blank"]::after,
a[target="_blank"] .partner-logo::after,
.marquee a[target="_blank"]::after{content:none}

:focus-visible{outline:2px solid var(--primary);outline-offset:3px;border-radius:4px}

/* ---------- Type ---------------------------------------------------------- */
h1,h2,h3,h4,h5{color:var(--heading);margin:0 0 .45em;font-weight:400}
h1{font-family:var(--font-display);font-size:clamp(2.7rem,6.4vw,5.6rem);line-height:.98;letter-spacing:-.026em}
h2{font-family:var(--font-display);font-size:clamp(2rem,4.2vw,3.5rem);line-height:1.04;letter-spacing:-.021em}
h3{font-family:var(--font-sans);font-size:clamp(1.12rem,1.7vw,1.32rem);line-height:1.26;letter-spacing:-.015em;font-weight:600}
h4,h5{font-family:var(--font-sans);font-size:1rem;line-height:1.3;letter-spacing:-.01em;font-weight:600}
h1 em,h2 em{font-style:italic}
p{margin:0 0 1rem;color:var(--text-muted)}
strong,b{font-weight:600;color:var(--heading)}
.accent-text{color:var(--primary);font-style:italic;font-family:var(--font-display)}
h3 .accent-text,h4 .accent-text{font-family:inherit;font-style:normal}

.container,.wrap{width:min(1240px,90%);margin-inline:auto}
section{position:relative}
.section-pad{padding:clamp(4.5rem,10vw,8.5rem) 0}
.lead,.lede{font-size:clamp(1.04rem,1.5vw,1.26rem);color:var(--text);max-width:56ch;line-height:1.6}
.center{text-align:center}
.center .lead{margin-inline:auto}
.muted{color:var(--text-muted)}
.lbl{font-size:.86rem;color:var(--text-muted)}
.sep{color:var(--border-strong)}
.link-underline{border-bottom:1px solid currentColor;padding-bottom:1px}

/* Section micro-label: an index entry, not a second headline. */
.eyebrow{
  display:inline-flex;align-items:center;gap:.5rem;
  padding:.32rem .75rem;border-radius:999px;
  background:rgba(79,70,229,.07);border:1px solid rgba(79,70,229,.14);
  font-family:var(--font-sans);font-size:.72rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--primary);margin-bottom:1.3rem;
}
.center .eyebrow{justify-content:center}

/* ---------- Buttons ------------------------------------------------------- */
/* `.arrow` is styled as a circular well so the existing markup renders as the
   nested-icon CTA. The glyph never sits naked beside the label. */
.btn{
  display:inline-flex;align-items:center;gap:.7rem;cursor:pointer;
  padding:.62rem .7rem .62rem 1.5rem;border-radius:999px;
  font-family:var(--font-sans);font-size:.95rem;font-weight:600;letter-spacing:-.01em;
  border:1px solid transparent;text-align:left;
  transition:transform 180ms var(--ease-out),box-shadow 180ms var(--ease-out),
             background-color 180ms var(--ease-out),border-color 180ms var(--ease-out),
             color 180ms var(--ease-out);
}
.btn:active{transform:scale(.97)}
.btn .arrow{
  width:32px;height:32px;flex:0 0 32px;border-radius:50%;
  display:inline-grid;place-items:center;font-size:.9rem;line-height:1;
  transition:transform 220ms var(--ease-out),background-color 180ms var(--ease-out);
}
.btn-primary{background:var(--ink);color:#fff;box-shadow:var(--lift-2)}
.btn-primary .arrow{background:rgba(255,255,255,.14)}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--border-strong)}
.btn-ghost .arrow{background:rgba(20,19,26,.05)}
@media (hover:hover) and (pointer:fine){
  .btn-primary:hover{transform:translateY(-2px);box-shadow:var(--lift-3)}
  .btn-primary:hover .arrow{background:rgba(255,255,255,.24)}
  .btn-ghost:hover{border-color:var(--ink);background:rgba(20,19,26,.03);transform:translateY(-2px)}
  .btn:hover .arrow{transform:translate(3px,-1px) scale(1.06)}
}
/* Buttons sitting on an ink ground invert. */
.cta-band .btn-primary,.contact-band .btn-primary,.bleed .btn-primary{background:#fff;color:var(--ink)}
.cta-band .btn-primary .arrow,.contact-band .btn-primary .arrow{background:rgba(20,19,26,.08)}
.cta-band .btn-ghost,.contact-band .btn-ghost{color:var(--on-ink);border-color:var(--ink-border)}
.cta-band .btn-ghost .arrow,.contact-band .btn-ghost .arrow{background:rgba(255,255,255,.1)}

.card-link,.go{
  display:inline-flex;align-items:center;gap:.5rem;
  font-size:.88rem;font-weight:600;color:var(--primary);
}
.card-link .arrow,.go .arrow{width:auto;height:auto;background:none;flex:none}
@media (hover:hover) and (pointer:fine){
  .card:hover .card-link .arrow,.go:hover .arrow{transform:translateX(4px)}
}

/* ---------- Header: floating glass island --------------------------------- */
/* Padding is fixed; the shrink-on-scroll is a transform on the pill. Animating
   padding would relayout the whole bar on every scroll frame. */
.site-header{
  position:fixed;top:0;left:0;right:0;z-index:100;padding:1.15rem 0;
  background:none;border:0;
}
.site-header .nav{
  position:relative;
  width:min(1240px,92%);margin-inline:auto;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  padding:.5rem .5rem .5rem 1.45rem;border-radius:999px;
  background:rgba(251,250,247,.72);
  border:1px solid rgba(255,255,255,.7);
  box-shadow:var(--inner-hi),var(--lift-1);
  transform-origin:top center;
  transition:transform 320ms var(--ease-out),box-shadow 320ms var(--ease-out),
             background-color 320ms var(--ease-out);
}
/* The blur lives on a pseudo-element, NOT on .nav itself. backdrop-filter makes
   an element the containing block for its fixed descendants, and the mobile menu
   is a `position:fixed; inset:0` child of this pill — with the filter on .nav it
   resolved inset:0 against the pill and rendered as a 357x128 box with seven
   links spilling out over the hero. On the pseudo-element the glass looks
   identical and the menu gets the viewport back. */
.site-header .nav::before{
  content:"";position:absolute;inset:0;border-radius:inherit;z-index:-1;
  backdrop-filter:blur(18px) saturate(1.5);
  -webkit-backdrop-filter:blur(18px) saturate(1.5);
}
.site-header.scrolled .nav{
  transform:translateY(-8px) scale(.975);
  background:rgba(251,250,247,.9);
  box-shadow:var(--inner-hi),var(--lift-2);
}
/* Fixed header needs the page pushed clear of it. */
body{padding-top:0}
.hero,.page-hero{padding-top:clamp(8.5rem,15vw,12rem)}

.brand{display:inline-flex;flex-direction:row;align-items:center;gap:.6rem;
  line-height:1;color:var(--heading)}
.brand .wm{font-family:var(--font-sans);font-weight:600;font-size:1.05rem;letter-spacing:.2em}
.brand .wm-sub{display:block;font-weight:600;font-size:.46rem;letter-spacing:.44em;
  color:var(--text-muted);margin-top:.3rem}
.site-footer .brand .wm-sub{color:var(--ink-muted)}
/* 34px box, of which the letter is 87.5% = 29.75px — matched to the wordmark
   block (16.8 cap + 4.8 gap + 7.4 sub ≈ 29px), so the mark reads as the same
   height as the two lines beside it rather than as an icon stuck on the front.
   No fill of its own: currentColor gives it --heading here and #fff in the
   footer, from one piece of markup. */
.brand-mark{width:34px;height:34px;flex:none;display:block}

.nav-links{display:flex;align-items:center;gap:.15rem;list-style:none;margin:0;padding:0}
.nav-links a{
  display:block;padding:.5rem .85rem;border-radius:999px;font-size:.9rem;font-weight:500;
  color:var(--text-muted);transition:color 160ms var(--ease-out),background-color 160ms var(--ease-out);
}
@media (hover:hover) and (pointer:fine){
  .nav-links a:hover{color:var(--heading);background:rgba(20,19,26,.05)}
}
.nav-links a.active{color:var(--heading);background:rgba(20,19,26,.05)}
.nav-links a.btn-primary,.nav-links a.btn-primary:hover{color:#fff;background:var(--ink)}
.nav-links a.btn-ghost,.nav-links a.btn-ghost:hover{color:var(--ink)}

/* Dropdown scales out of its trigger, not out of nowhere. */
.has-dropdown{position:relative}
.dropdown{
  position:absolute;top:calc(100% + 12px);left:0;min-width:310px;padding:.45rem;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:var(--lift-3);
  opacity:0;visibility:hidden;transform:scale(.96) translateY(-4px);transform-origin:top left;
  transition:opacity 180ms var(--ease-out),transform 180ms var(--ease-out),visibility 180ms;
}
.has-dropdown:hover .dropdown,.has-dropdown:focus-within .dropdown{opacity:1;visibility:visible;transform:none}
.dropdown a{display:block;padding:.65rem .8rem;border-radius:var(--r-sm);color:var(--heading);
  font-size:.9rem;font-weight:600;transition:background-color 140ms var(--ease-out)}
.dropdown a span{display:block;font-size:.77rem;color:var(--text-muted);font-weight:400;margin-top:.1rem}
@media (hover:hover) and (pointer:fine){.dropdown a:hover{background:var(--bg-2)}}

.nav-actions{display:flex;align-items:center;gap:.6rem}
.mobile-cta{display:none}
.nav-toggle{
  display:none;width:40px;height:40px;border-radius:999px;
  border:1px solid var(--border-strong);background:transparent;color:var(--ink);cursor:pointer;
  position:relative;
}
.nav-toggle svg{display:none}
.nav-toggle::before,.nav-toggle::after{
  content:"";position:absolute;left:11px;width:18px;height:1.5px;background:var(--ink);
  transition:transform 300ms var(--ease-drawer);
}
.nav-toggle::before{top:15px}
.nav-toggle::after{top:23px}
.nav-toggle[aria-expanded="true"]::before{transform:translateY(4px) rotate(45deg)}
.nav-toggle[aria-expanded="true"]::after{transform:translateY(-4px) rotate(-45deg)}

@media (max-width:940px){
  .desktop-cta{display:none}
  /* The overlay comes after the button in the DOM, so without these it paints
     over it and the menu cannot be closed by tapping the toggle at all — the
     only ways out were picking a nav item or the browser back button. Escape
     is already handled in main.js but there is no Escape key on a phone. */
  .nav-toggle{display:block;z-index:2}
  .nav-links{z-index:1}

  /* No transform on the pill at this breakpoint. THIS IS LOAD-BEARING.
     .nav-links below is `position:fixed; inset:0` to fill the viewport, and a
     transform on ANY ancestor makes that ancestor the containing block for
     fixed descendants — so `inset:0` silently resolves against the little nav
     pill instead of the screen. Scrolling past 20px adds .scrolled, which
     applied translateY+scale, and the full-screen menu collapsed to a 348x125
     box showing two items. The scrolled state keeps its background and shadow
     change; only the transform goes.

     Same trap as the backdrop-filter that used to sit on .nav. Do not add
     transform, filter, backdrop-filter, perspective or will-change to .nav or
     .site-header inside this media query. */
  .site-header.scrolled .nav{transform:none}
  .site-header .nav{padding-left:1.25rem}
  .nav-links{
    position:fixed;inset:0;flex-direction:column;justify-content:center;align-items:stretch;
    gap:.35rem;padding:5rem 8% 3rem;overflow-y:auto;
    background:rgba(251,250,247,.94);backdrop-filter:blur(28px);
    -webkit-backdrop-filter:blur(28px);
    opacity:0;visibility:hidden;transform:none;
    transition:opacity 300ms var(--ease-out),visibility 300ms;
  }
  .nav-links.open{opacity:1;visibility:visible}
  .nav-links > li{opacity:0;transform:translateY(18px);
    transition:opacity 420ms var(--ease-out),transform 420ms var(--ease-out)}
  .nav-links.open > li{opacity:1;transform:none}
  .nav-links.open > li:nth-child(1){transition-delay:60ms}
  .nav-links.open > li:nth-child(2){transition-delay:100ms}
  .nav-links.open > li:nth-child(3){transition-delay:140ms}
  .nav-links.open > li:nth-child(4){transition-delay:180ms}
  .nav-links.open > li:nth-child(5){transition-delay:220ms}
  .nav-links.open > li:nth-child(6){transition-delay:260ms}
  .nav-links.open > li:nth-child(7){transition-delay:300ms}
  .nav-links > li > a{
    font-family:var(--font-display);font-size:1.9rem;text-align:center;color:var(--heading);
    padding:.5rem 1rem;
  }
  .dropdown{position:static;display:none}
  .mobile-cta{display:block;margin-top:1.2rem}
  .mobile-cta .btn{width:100%;justify-content:center}
  .mobile-cta a{font-family:var(--font-sans)!important;font-size:.95rem!important}
}

/* ---------- Hero ---------------------------------------------------------- */
.hero{padding-bottom:clamp(3rem,6vw,5rem);overflow:hidden}
.hero-inner{position:relative;z-index:1}
.hero-split{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(2rem,5vw,4.5rem);align-items:end}
.hero h1{margin-bottom:1.5rem;max-width:15ch}
.hero .lead{margin-bottom:2.2rem}
.hero-cta{display:flex;flex-wrap:wrap;gap:.7rem;margin-bottom:2rem}
.hero-meta{display:flex;flex-wrap:wrap;gap:1.6rem;font-size:.86rem;color:var(--text-muted)}
.hero-meta a{color:var(--heading);border-bottom:1px solid var(--border-strong);padding-bottom:1px}
@media (max-width:900px){.hero-split{grid-template-columns:1fr;gap:2.6rem}}

/* Inner-page hero. Photo backgrounds get a paper scrim so dark text holds. */
.page-hero{padding-bottom:clamp(3rem,6vw,4.5rem);overflow:hidden}
.page-hero .inner{position:relative;z-index:1}
.page-hero h1{max-width:18ch}
.hero-bg{position:absolute;inset:0;z-index:0;pointer-events:none}
/* The hero ground is drawn artwork now, not photography. A stock photo needed
   opacity:.16 and a desaturating filter to stop it shouting; the plates arrive
   already restrained -- ink hairlines at .07-.22 alpha with one lit element --
   so knocking them back again would erase them. They paint at full strength and
   the paper scrim below does the muting.

   `.has-photo` keeps its name: it is on ten pages and in the mobile audit, and
   renaming a class to match a change of medium is churn, not clarity. */
.page-hero.has-photo .hero-bg{
  background-image:var(--hero-img);background-size:cover;background-position:center;
  opacity:1;filter:none;
}
/* Vector strokes stay crisp when the plate is scaled past its 1600x900 box, so
   a wide hero can afford to crop rather than letterbox. */
@media (min-width:1500px){.page-hero.has-photo .hero-bg{background-size:110% auto}}
.page-hero.has-photo::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(180deg,rgba(251,250,247,.78) 0%,rgba(251,250,247,.92) 55%,var(--paper) 100%);
}
.breadcrumb{
  display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;
  font-size:.79rem;color:var(--text-muted);margin-bottom:1.4rem;
}
.breadcrumb a{color:var(--text-muted);border-bottom:1px solid transparent;transition:color 160ms var(--ease-out)}
@media (hover:hover) and (pointer:fine){.breadcrumb a:hover{color:var(--heading);border-bottom-color:var(--border-strong)}}
/* The trail's separators and its current-page label are both bare spans, so
   they cannot be told apart in CSS. Colour them as readable text — the "/"
   glyph reads as a separator on its own, and the current page stays legible
   instead of dropping to hairline grey. */
.breadcrumb span{color:var(--text-muted)}

/* ---------- Surfaces ------------------------------------------------------ */
.card,.plan,.principle,.stage-cell,.ed-tile,.insight-card,.partner-card,.form-card,
.cardpanel,.tile,.visual-panel,.ops,.quiz,.tier{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:var(--inner-hi),var(--lift-1);
}
.card{padding:1.7rem 1.6rem;transition:transform 280ms var(--ease-out),box-shadow 280ms var(--ease-out)}
.card h3{margin-bottom:.5rem}
.card p:last-child{margin-bottom:0}
@media (hover:hover) and (pointer:fine){
  .card:hover,.insight-card:hover,.partner-card:hover{transform:translateY(-4px);box-shadow:var(--inner-hi),var(--lift-3)}
}

.grid{display:grid;gap:1rem}
.cols-2{grid-template-columns:repeat(2,1fr)}
.cols-3{grid-template-columns:repeat(3,1fr)}
@media (max-width:1000px){.cols-3{grid-template-columns:repeat(2,1fr)}}
@media (max-width:700px){.cols-2,.cols-3{grid-template-columns:1fr}}

.split{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,4rem);align-items:center}
.split.reverse > *:first-child{order:2}
@media (max-width:880px){.split{grid-template-columns:1fr}.split.reverse > *:first-child{order:0}}

.band{background:var(--bg-2)}
.band + .band{border-top:1px solid var(--border)}

/* ---------- Media --------------------------------------------------------- */
.media{position:relative;border-radius:var(--r-md);overflow:hidden;border:1px solid var(--border);
  box-shadow:var(--lift-2)}
.media img{width:100%;height:100%;object-fit:cover;display:block}
/* The panels are inline <svg> now, not <img>: an <img> is a closed document
   and no stylesheet outside it can reach in, which makes a scroll-triggered
   animation impossible. Seven of the eight match their container's aspect
   ratio exactly, so the default preserveAspectRatio neither crops nor
   letterboxes; panel-system asks for `slice` in its own markup. */
.media > svg,.bento-media > svg{width:100%;height:100%;display:block}
/* The frame clips already; telling the browser so lets it skip work outside. */
.media,.bento-media{contain:paint}
.media.tall{aspect-ratio:4/5}
.media.wide{aspect-ratio:16/10}
.media-tag{
  position:absolute;left:1rem;bottom:1rem;padding:.35rem .8rem;border-radius:999px;
  background:rgba(251,250,247,.9);backdrop-filter:blur(8px);
  font-size:.74rem;font-weight:600;color:var(--heading);
}
/* The caption sits OUTSIDE the clipped frame. It used to be nested inside
   `.media`, which is a fixed-aspect box with overflow:hidden -- so every caption
   on the site was rendered and then cut off, and none of them had ever been
   read. <figure> wraps the frame and the caption together. */
.media-figure{margin:0;display:grid;gap:.7rem}
.media-caption{font-size:.85rem;line-height:1.45;color:var(--text-muted);margin:0;
  padding-left:.9rem;border-left:2px solid var(--border-strong)}
.section-photo{position:relative;border-radius:var(--r-md);overflow:hidden;
  border:1px solid var(--border);box-shadow:var(--lift-2);isolation:isolate}
/* The band carries a --hero-img too, but had no rule painting it: the property
   was set on ten sections and read by nothing, so every "section-photo" was a
   plain bordered box. It paints the plate now, behind a paper wash strong
   enough that body copy still clears AA on top of it. */
.section-photo::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--hero-img);background-size:cover;background-position:center;
  opacity:.5;
}
.section-photo::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(180deg,rgba(251,250,247,.88),rgba(251,250,247,.94));
}

/* ---------- Trust strip --------------------------------------------------- */
.trustbar{padding:2.2rem 0;border-block:1px solid var(--border);background:var(--bg-2)}
.trustbar-in{display:flex;align-items:center;justify-content:space-between;gap:2rem;flex-wrap:wrap}
.trustbar .lbl{max-width:40ch}
.set,.pills{display:flex;flex-wrap:wrap;gap:.45rem}
/* .tagcloud .t is the same component under a different name — services/index.html
   shipped twenty of them and nothing but .tl-item .t was ever defined, so the
   whole "frameworks and platforms" band rendered as a run-on line of bare text.
   Adding it here rather than renaming the class in the markup keeps one rule. */
.chip,.pill,.tag,.tagcloud .t{
  display:inline-flex;align-items:center;gap:.35rem;
  padding:.38rem .85rem;border-radius:999px;background:var(--surface);
  border:1px solid var(--border);font-size:.78rem;color:var(--text-muted);
  box-shadow:var(--inner-hi);
}
.chip b,.pill b{color:var(--heading);font-weight:600}
.tag{font-size:.72rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent);background:rgba(14,116,144,.07);border-color:rgba(14,116,144,.16)}
.tagcloud{display:flex;flex-wrap:wrap;gap:.4rem}

/* ---------- Statement ----------------------------------------------------- */
.statement-wrap{display:grid;grid-template-columns:1.6fr 1fr;gap:clamp(2rem,6vw,5rem);align-items:start}
.statement-lg{font-size:clamp(2.1rem,4.4vw,3.6rem);max-width:20ch}
/* The column answering the statement. Set as an aside rather than as more body
   copy: a rule above it and a smaller measure, so the eye reads the statement
   first and this second, which is the order the two were written in. */
.statement-aside{padding-top:.7rem;border-top:1px solid var(--border);max-width:44ch}
.statement-aside p{font-size:.98rem}
@media (max-width:860px){.statement-aside{border-top:0;padding-top:0}}
@media (max-width:860px){.statement-wrap{grid-template-columns:1fr}}

/* ---------- Ops panel ----------------------------------------------------- */
.ops{padding:1.5rem 1.6rem}
.ops-head{display:flex;align-items:center;justify-content:space-between;
  padding-bottom:.9rem;border-bottom:1px solid var(--border);margin-bottom:.2rem}
.ops-head b{font-size:.76rem;letter-spacing:.14em;text-transform:uppercase;color:var(--heading)}
.ops-live{display:inline-flex;align-items:center;gap:.45rem;font-size:.72rem;color:var(--accent);font-weight:600}
.ops-live i{width:6px;height:6px;border-radius:50%;background:var(--accent);display:block;
  animation:pulse 2.4s var(--ease-in-out) infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.82)}}
.ops-row{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:.72rem 0;border-bottom:1px solid var(--border);font-size:.88rem}
.ops-row:last-child{border-bottom:0}
.ops-row span{color:var(--text-muted)}
.ops-row b{color:var(--heading);font-variant-numeric:tabular-nums;font-weight:600}

/* ---------- Plans --------------------------------------------------------- */
.plans{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;align-items:start}
.plan{padding:1.9rem 1.7rem;position:relative}
.plan h3{margin-bottom:.5rem}
.plan .who{font-size:.9rem;min-height:3.2em;color:var(--text-muted)}
.plan .price{font-family:var(--font-display);font-size:1.15rem;color:var(--heading);
  padding-bottom:1.1rem;border-bottom:1px solid var(--border);margin-bottom:1.2rem}
.plan ul{list-style:none;padding:0;margin:0 0 1.6rem;display:grid;gap:.55rem;
  font-size:.88rem;color:var(--text)}
.plan li{position:relative;padding-left:1.3rem}
.plan li::before{content:"";position:absolute;left:0;top:.58em;width:7px;height:7px;
  border-radius:50%;background:var(--primary)}
.plan li.off{opacity:.4}
.plan li.off::before{background:var(--text-muted)}
.plan.featured{background:var(--ink-2);border-color:transparent;box-shadow:var(--lift-3)}
.plan.featured h3,.plan.featured .price{color:#fff}
.plan.featured p,.plan.featured li,.plan.featured .who{color:rgba(255,255,255,.68)}
.plan.featured .price{border-bottom-color:rgba(255,255,255,.14)}
.plan.featured li::before{background:var(--accent-on-ink)}
.plan.featured .btn-primary{background:#fff;color:var(--ink)}
.plan.featured .btn-primary .arrow{background:rgba(20,19,26,.08)}
.plan-inline{list-style:none;padding:0;margin:0}
@media (max-width:900px){.plans{grid-template-columns:1fr}}

/* ---------- Stages / steps / timeline ------------------------------------- */
.stages{display:grid;grid-template-columns:repeat(5,1fr);gap:1rem}
.stage-cell{padding:1.5rem 1.4rem}
.stage-cell .n{display:block;font-family:var(--font-mono);font-size:.75rem;color:var(--accent);
  letter-spacing:.06em;margin-bottom:.8rem}
.stage-cell h3{font-size:1.02rem;margin-bottom:.4rem}
.stage-cell p{font-size:.88rem;margin:0}
@media (max-width:1100px){.stages{grid-template-columns:repeat(3,1fr)}}
@media (max-width:760px){.stages{grid-template-columns:1fr}}

.steps{display:grid}
.step-row{
  display:grid;grid-template-columns:96px 1fr auto;gap:clamp(1rem,3vw,2.5rem);
  align-items:baseline;padding:1.85rem 0;border-top:1px solid var(--border);position:relative;
}
.steps .step-row:last-child{border-bottom:1px solid var(--border)}
.step-row .n{font-family:var(--font-mono);font-size:.8rem;color:var(--text-muted);letter-spacing:.04em}
.step-row h3{margin-bottom:.3rem}
.step-row p{margin:0;font-size:.93rem;max-width:60ch}
.step-arrow{color:var(--border-strong);font-size:1.1rem}
/* Ink wash sweeps in from the left on hover; clip-path, so no layout cost. */
.step-row::after{content:"";position:absolute;inset:0;background:var(--bg-2);z-index:-1;
  clip-path:inset(0 100% 0 0);transition:clip-path 380ms var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .step-row:hover::after{clip-path:inset(0 0 0 0)}
  .step-row:hover .n{color:var(--primary)}
}
@media (max-width:720px){.step-row{grid-template-columns:56px 1fr}.step-arrow{display:none}}

.timeline{display:grid}
.tl-item{display:grid;grid-template-columns:200px 1fr;gap:clamp(1rem,3vw,2.5rem);
  padding:1.8rem 0;border-top:1px solid var(--border)}
.timeline .tl-item:last-child{border-bottom:1px solid var(--border)}
.tl-item .t{font-family:var(--font-mono);font-size:.78rem;color:var(--accent);letter-spacing:.03em}
.tl-item h3{margin-bottom:.3rem;font-size:1.06rem}
.tl-item p{margin:0;font-size:.9rem}
@media (max-width:760px){.tl-item{grid-template-columns:1fr;gap:.6rem}}

/* ---------- Principles ---------------------------------------------------- */
.principles{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}
.principle{display:flex;gap:1rem;padding:1.5rem 1.45rem}
.principle svg{width:22px;height:22px;flex:0 0 22px;color:var(--primary);margin-top:.25rem}
.principle h4{margin-bottom:.3rem}
.principle p{font-size:.88rem;margin:0}
@media (max-width:960px){.principles{grid-template-columns:1fr 1fr}}
@media (max-width:640px){.principles{grid-template-columns:1fr}}

/* ---------- Editorial tiles ----------------------------------------------- */
.editorial,.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}
.ed-tile,.tile{padding:1.8rem 1.7rem;min-height:260px;display:flex;flex-direction:column}
.ed-tile h3,.tile h3{font-family:var(--font-display);font-size:1.65rem;font-weight:400;
  line-height:1.14;margin-bottom:.6rem;letter-spacing:-.015em}
.ed-tile p,.tile p{font-size:.94rem;margin-bottom:1rem}
/* This was opacity:0 until hover. The text inside it is not a flourish -- it is
   the argument the tile is making, three sentences of it -- and a visitor who
   does not happen to hover never read a word. Visible by default now; hover
   still lifts it, so the interaction survives without gating the content. */
.ed-more{margin-top:auto;font-size:.87rem;color:var(--text-muted);
  transition:color 300ms var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .ed-tile:hover .ed-more,.ed-tile:focus-within .ed-more{color:var(--text)}
}
@media (max-width:900px){.editorial,.tiles{grid-template-columns:1fr}.ed-tile,.tile{min-height:0}}

/* ---------- Full-bleed statement ------------------------------------------ */
.bleed{background:var(--ink);color:#fff;text-align:center;padding:clamp(5.5rem,11vw,9rem) 0}
.bleed h2{color:#fff;max-width:19ch;margin-inline:auto}
.bleed .accent-text{color:var(--accent-on-ink)}
.bleed p{color:var(--ink-muted);margin-top:1rem}

/* ---------- Bento --------------------------------------------------------- */
.bento{display:grid;grid-template-columns:repeat(6,1fr);gap:1rem}
.bento > *{grid-column:span 2}
.b-wide{grid-column:span 4}
.b-half{grid-column:span 3}
.b-tall{grid-row:span 2}
.bento-media{overflow:hidden;border-radius:var(--r-md)}
@media (max-width:1000px){.bento{grid-template-columns:repeat(2,1fr)}
  .bento > *,.b-wide,.b-half{grid-column:span 1}.b-tall{grid-row:span 1}}
@media (max-width:640px){.bento{grid-template-columns:1fr}}

/* ---------- Pinned services ----------------------------------------------- */
.pin-grid{display:grid;grid-template-columns:.82fr 1.18fr;gap:clamp(2rem,5vw,4.5rem);align-items:start}
.pin-rail{position:sticky;top:120px}
.pin-index{list-style:none;padding:0;margin:1.6rem 0 0;display:grid;gap:.15rem}
.pin-index li a{display:flex;align-items:center;gap:.8rem;padding:.6rem .8rem;border-radius:var(--r-sm);
  font-size:.95rem;font-weight:500;color:var(--text-muted);
  transition:color 200ms var(--ease-out),background-color 200ms var(--ease-out)}
.pin-index li a::before{content:"";width:3px;height:16px;border-radius:2px;background:var(--primary);
  transform:scaleY(0);transform-origin:center;transition:transform 220ms var(--ease-out)}
.pin-index li.on a{color:var(--heading);background:var(--surface);box-shadow:var(--lift-1)}
.pin-index li.on a::before{transform:scaleY(1)}
.pin-panels{display:grid;gap:1rem}
.pin-panel{
  display:block;background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:var(--inner-hi),var(--lift-1);padding:1.8rem 1.7rem 1.6rem;
  transition:transform 280ms var(--ease-out),box-shadow 280ms var(--ease-out);
}
.pin-panel h3{margin-bottom:.5rem}
.pin-panel p{font-size:.93rem;margin-bottom:1.1rem}
@media (hover:hover) and (pointer:fine){
  .pin-panel:hover{transform:translateY(-4px);box-shadow:var(--inner-hi),var(--lift-3)}
}
/* Sparkline signature on service cards. */
/* ---------- Service-card figures ------------------------------------------
   Each card carries an inline <svg class="pin-figure"> diagram rather than the
   row of bars all five used to share. The SVGs contain no CSS of their own —
   they tag elements with one of four class names and a --i stagger index, and
   the whole animation vocabulary lives here, so all five stay in step.

   transform-box:fill-box is not optional: without it transform-origin on an SVG
   child resolves against the viewport, not the element, and "grow from my own
   bottom edge" silently becomes "grow from somewhere off-screen".

   pf-draw relies on pathLength="1" being present on the element, which
   normalises every path to a length of 1 so one dash rule covers shapes of
   wildly different real lengths. It is baked into the markup, not added at
   runtime — doing it in JS would leave the figures un-animated for the first
   frames of every load. If you hand-add a pf-draw element, add pathLength="1"
   with it or it will simply not animate. */
/* Sized to the viewBox's own 200:44 ratio, and capped at one width for every
   card. `width:100%;height:44px` looked right but was not: the default
   preserveAspectRatio fits the viewBox to the SMALLER dimension, so each figure
   painted at 1:1 in a 200px island floating in the middle of a 556px card.
   Letting it fill each card instead would scale the half-width and third-width
   cards differently and render the same 1.5 stroke at two visibly different
   weights, which breaks the set. One fixed size keeps all five identical. */
.pin-figure{display:block;width:min(100%,260px);aspect-ratio:200/44;height:auto;
  margin-bottom:1.2rem;overflow:visible}
.pin-figure .pf-rise,.pin-figure .pf-pop,
.pin-figure .pf-fade,.pin-figure .pf-draw{transform-box:fill-box}

@media (prefers-reduced-motion: no-preference){
  .pin-figure .pf-rise{transform:scaleY(.001);transform-origin:50% 100%;
    transition:transform 620ms var(--ease-out)}
  .pin-figure .pf-pop{transform:scale(.001);transform-origin:50% 50%;
    transition:transform 420ms var(--ease-out)}
  .pin-figure .pf-fade{opacity:0;transition:opacity 520ms var(--ease-out)}
  .pin-figure .pf-draw{stroke-dasharray:1;stroke-dashoffset:1;
    transition:stroke-dashoffset 820ms var(--ease-out)}

  .pin-figure .pf-rise,.pin-figure .pf-pop,
  .pin-figure .pf-fade,.pin-figure .pf-draw{
    transition-delay:calc(var(--i,0) * 70ms)}

  .in .pin-figure .pf-rise,.reveal.in .pin-figure .pf-rise{transform:none}
  .in .pin-figure .pf-pop,.reveal.in .pin-figure .pf-pop{transform:none}
  .in .pin-figure .pf-fade,.reveal.in .pin-figure .pf-fade{opacity:1}
  .in .pin-figure .pf-draw,.reveal.in .pin-figure .pf-draw{stroke-dashoffset:0}
}

/* Section markers. Same family, same optical weight, sized to sit on a label. */
.sec-icon{width:20px;height:20px;flex:none;color:var(--primary);opacity:.85}
.eyebrow .sec-icon{width:14px;height:14px;margin-right:-.1rem}
@media (max-width:900px){.pin-grid{grid-template-columns:1fr}.pin-rail{position:static}.pin-index{display:none}}

/* ---------- Animated figures ----------------------------------------------
   The eight large panels on the service pages, and the five small figures on
   the home page, run one vocabulary. `.pin-figure` above is the small variant
   and keeps its own sizing; everything below is shared.

   WHY THESE ANIMATE AT ALL. Each panel is a diagram that has to be read before
   it means anything: a rack that seats unit by unit, a perimeter that draws
   outside-in, a signal trace that runs left to right and then spikes. Building
   the drawing in the order the thing actually happens is explanation, which is
   the one sanctioned reason to animate on a marketing page. None of them
   animates because motion is nice, and none loops except the two status dots
   that represent something genuinely live.

   HOW IT IS DRIVEN. No new JavaScript. The panel's wrapper already carries
   `.reveal`, which main.js's IntersectionObserver flips to `.reveal.in` once,
   then unobserves. The markup only declares WHICH verb and in WHAT ORDER
   (`--i`); every duration and curve lives here, so the whole system retunes
   from one block.

   transform-box:fill-box is not optional. Without it transform-origin on an SVG
   child resolves against the viewport rather than the element, and "grow from
   my own right edge" silently becomes "grow from somewhere off-screen". */

.fig-anim{display:block;width:100%;height:100%}
.media > .fig-anim,.bento-media > .fig-anim{height:100%}
/* Per-figure stagger step. A fourteen-row register on the 55ms default would
   take three seconds to fill; a five-node diagram on 38ms would look hurried. */
.fig-anim{--step:55ms}
.fig-anim[aria-label*="register"]{--step:38ms}
.fig-anim[aria-label*="operating model"]{--step:62ms}
.fig-anim[aria-label*="detection"]{--step:70ms}

@media (prefers-reduced-motion: no-preference){
  .fig-anim .fa-fade,.fig-anim .fa-rise,.fig-anim .fa-seat,
  .fig-anim .fa-pop,.fig-anim .fa-ring,.fig-anim .fa-grow-r,
  .fig-anim .fa-draw,.fig-anim .fa-trace{transform-box:fill-box}

  /* Resting state. Only transform, opacity and stroke-dashoffset are touched:
     nothing here can trigger layout. */
  .fig-anim .fa-fade{opacity:0}
  .fig-anim .fa-rise{opacity:0;transform:translateY(16px)}
  .fig-anim .fa-seat{opacity:0;transform:translateY(26px)}
  .fig-anim .fa-pop{opacity:0;transform:scale(.92);transform-origin:50% 50%}
  .fig-anim .fa-ring{opacity:0;transform:scale(.88);transform-origin:50% 50%}
  /* Grows from its own right edge rather than fading in, so the replacement
     block widening across five rows reads as one continuous movement. Starts at
     .12 and not 0 — nothing in the real world appears from nothing, and a seed
     the eye can already see is what makes the growth read as growth. */
  .fig-anim .fa-grow-r{opacity:0;transform:scaleX(.12);transform-origin:100% 50%}
  .fig-anim .fa-draw,.fig-anim .fa-trace{stroke-dasharray:1;stroke-dashoffset:1}

  .fig-anim .fa-fade,.fig-anim .fa-rise,.fig-anim .fa-seat,
  .fig-anim .fa-pop,.fig-anim .fa-ring,.fig-anim .fa-grow-r{
    transition-property:opacity,transform;
    transition-timing-function:var(--ease-out);
    transition-delay:calc(var(--i,0) * var(--step));
  }
  .fig-anim .fa-draw,.fig-anim .fa-trace{
    transition-property:stroke-dashoffset;
    transition-delay:calc(var(--i,0) * var(--step));
  }

  .fig-anim .fa-fade   {transition-duration:520ms}
  .fig-anim .fa-rise   {transition-duration:620ms}
  .fig-anim .fa-seat   {transition-duration:560ms}
  .fig-anim .fa-pop    {transition-duration:460ms}
  .fig-anim .fa-ring   {transition-duration:640ms}
  .fig-anim .fa-grow-r {transition-duration:700ms}
  .fig-anim .fa-draw   {transition-duration:720ms;transition-timing-function:var(--ease-out)}
  /* The one long duration on the site. The trace IS the explanation of what
     monitoring does, so it is worth watching run — and it runs at a constant
     rate, because it represents time passing rather than an object arriving. */
  .fig-anim .fa-trace  {transition-duration:1400ms;transition-timing-function:linear}

  /* Arrived state. Keyed off the wrapper, which is where .reveal lives. */
  .reveal.in .fig-anim .fa-fade,
  .reveal.in .fig-anim .fa-rise,
  .reveal.in .fig-anim .fa-seat,
  .reveal.in .fig-anim .fa-pop,
  .reveal.in .fig-anim .fa-ring,
  .reveal.in .fig-anim .fa-grow-r{opacity:1;transform:none}
  .reveal.in .fig-anim .fa-draw,
  .reveal.in .fig-anim .fa-trace{stroke-dashoffset:0}

  /* The only loop. Two status dots on the rack, one core on the perimeter
     diagram, one open control on the register — each of them stands for
     something that is genuinely live, and a static dot claiming "monitored
     24/7" is a weaker drawing. It arrives first, then breathes; the same
     2.4s curve the header's .ops-live indicator already uses, so the two read
     as one signal rather than two different ideas of "live". */
  .reveal.in .fig-anim .fa-live{
    animation:fa-arrive 460ms var(--ease-out) both calc(var(--i,0) * var(--step)),
              pulse 2.6s var(--ease-in-out) infinite calc(var(--i,0) * var(--step) + 460ms);
  }
  .fig-anim .fa-live{opacity:0}
  @keyframes fa-arrive{from{opacity:0;transform:scale(.86)}to{opacity:1;transform:none}}
}

/* Reduced motion: the diagram is still the deliverable, so it is presented
   finished rather than withheld. Nothing moves, nothing loops. */
@media (prefers-reduced-motion: reduce){
  .fig-anim .fa-fade,.fig-anim .fa-rise,.fig-anim .fa-seat,
  .fig-anim .fa-pop,.fig-anim .fa-ring,.fig-anim .fa-grow-r{opacity:1;transform:none}
  .fig-anim .fa-draw,.fig-anim .fa-trace{stroke-dashoffset:0}
  .fig-anim .fa-live{opacity:1;animation:none}
}

/* A figure inside a container that never gets .reveal — or on a browser where
   the observer never runs — must still be visible. This is the no-JS floor. */
.no-js .fig-anim .fa-fade,.no-js .fig-anim .fa-rise,.no-js .fig-anim .fa-seat,
.no-js .fig-anim .fa-pop,.no-js .fig-anim .fa-ring,.no-js .fig-anim .fa-grow-r{
  opacity:1;transform:none}
.no-js .fig-anim .fa-draw,.no-js .fig-anim .fa-trace{stroke-dashoffset:0}
.no-js .fig-anim .fa-live{opacity:1}

/* ---------- FAQ ----------------------------------------------------------- */
.faq{display:grid;grid-template-columns:1fr 1fr;gap:0 clamp(1.5rem,4vw,3rem)}
.faq details{border-top:1px solid var(--border);padding:.3rem 0}
.faq details:last-child{border-bottom:1px solid var(--border)}
.faq summary{
  list-style:none;cursor:pointer;padding:1.1rem 2rem 1.1rem 0;position:relative;
  font-weight:600;color:var(--heading);font-size:1rem;
  transition:color 180ms var(--ease-out);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";position:absolute;right:.35rem;top:50%;width:9px;height:9px;
  border-right:1.5px solid var(--text-muted);border-bottom:1.5px solid var(--text-muted);
  transform:translateY(-70%) rotate(45deg);
  transition:transform 260ms var(--ease-out),border-color 180ms var(--ease-out);
}
.faq details[open] summary::after{transform:translateY(-25%) rotate(-135deg);border-color:var(--primary)}
.faq summary:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
.faq p{margin:0 0 1.2rem;font-size:.94rem;max-width:62ch}
@media (max-width:860px){.faq{grid-template-columns:1fr}}

/* ---------- Insights feed -------------------------------------------------- */
.feed{display:grid;grid-template-columns:1.25fr 1fr;gap:1rem}
.feed-side{display:grid;gap:1rem}
.insight-card{
  display:flex;flex-direction:column;padding:1.7rem;
  transition:transform 280ms var(--ease-out),box-shadow 280ms var(--ease-out);
}
.insight-card h3{font-family:var(--font-display);font-weight:400;font-size:1.5rem;
  line-height:1.16;margin-bottom:.6rem;letter-spacing:-.015em}
.insight-card p{font-size:.92rem}
.insight-card .meta{margin-top:auto;font-size:.78rem;color:var(--text-muted);padding-top:1rem}
.feed-lead h3{font-size:clamp(1.8rem,3vw,2.4rem)}
.feed-lead{min-height:340px}
@media (max-width:900px){.feed{grid-template-columns:1fr}.feed-lead{min-height:0}}

/* ---------- Marquee -------------------------------------------------------- */
.marquee{
  overflow:hidden;padding:1.6rem 0;border-block:1px solid var(--border);
  mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 12%,#000 88%,transparent);
}
.marquee-track{display:flex;align-items:center;gap:4rem;width:max-content;
  animation:slide 42s linear infinite}
.marquee:hover .marquee-track{animation-play-state:paused}
@keyframes slide{to{transform:translateX(-50%)}}
.partner-logo{display:inline-flex;align-items:center;height:30px;opacity:.55;
  filter:grayscale(1);transition:opacity 220ms var(--ease-out),filter 220ms var(--ease-out);
  font-size:1rem;font-weight:600;color:var(--text-muted);white-space:nowrap}
.partner-logo img{height:100%;width:auto;object-fit:contain}
@media (hover:hover) and (pointer:fine){.partner-logo:hover{opacity:1;filter:grayscale(0)}}
.partners-strip{display:flex;flex-wrap:wrap;gap:1rem;align-items:center}
.partner-card{padding:1.5rem;text-align:center}
.logo-wrap{display:grid;place-items:center;height:56px;margin-bottom:1rem}

/* ---------- Contact / CTA bands -------------------------------------------- */
.contact-band,.cta-band{
  background:var(--ink);color:var(--on-ink);border-radius:var(--r-lg);
  padding:clamp(2.2rem,5vw,3.6rem);box-shadow:var(--lift-3);
}
.contact-band h2,.cta-band h2{color:var(--on-ink);max-width:18ch}
.contact-band p,.cta-band p{color:var(--ink-muted)}
.contact-band .accent-text,.cta-band .accent-text{color:var(--accent-on-ink)}
.contact-grid{display:grid;grid-template-columns:1.2fr .8fr;gap:clamp(2rem,5vw,4rem);align-items:center}
.contact-list{display:grid}
.contact-list > *{display:flex;justify-content:space-between;gap:1rem;padding:.85rem 0;
  border-bottom:1px solid var(--ink-border);font-size:.9rem;color:var(--on-ink)}
.contact-list .k{color:var(--ink-muted);font-size:.74rem;letter-spacing:.14em;text-transform:uppercase}
.contact-list a{color:var(--on-ink);font-weight:600}
@media (max-width:860px){.contact-grid{grid-template-columns:1fr}}
.contact-info{display:grid;gap:.8rem}
.info-item{display:flex;gap:.8rem;align-items:flex-start;font-size:.92rem}
.info-item .icon{width:34px;height:34px;flex:0 0 34px;border-radius:10px;display:grid;place-items:center;
  background:rgba(79,70,229,.08);color:var(--primary)}
.info-item .icon svg{width:16px;height:16px}
/* The text column. <strong> is inline by default, so without this the label runs
   straight into the value and reads "Emailcontactus@averrotech.com". Only the
   Hours row looked right, and only because it carried a one-off inline
   style="display:block" on its value — now removed, since this covers every row
   including any added later. min-width:0 plus anywhere stops the long address
   forcing the flex row wider than a narrow viewport. */
.info-item > div:not(.icon){display:flex;flex-direction:column;gap:.15rem;min-width:0}
.info-item > div:not(.icon) strong{color:var(--heading)}
.info-item > div:not(.icon) a{overflow-wrap:anywhere}

/* ---------- Forms ---------------------------------------------------------- */
.form-card{padding:clamp(1.6rem,3vw,2.2rem)}
.field{display:grid;gap:.4rem;margin-bottom:1rem}
.field label,.label{font-size:.8rem;font-weight:600;color:var(--heading);letter-spacing:.01em}
.field input,.field textarea,.field select{
  width:100%;padding:.8rem 1rem;border-radius:var(--r-sm);
  border:1px solid var(--border-strong);background:var(--surface);
  font-family:var(--font-sans);font-size:.95rem;color:var(--text);
  transition:border-color 180ms var(--ease-out),box-shadow 180ms var(--ease-out);
}
.field input:focus,.field textarea:focus,.field select:focus{
  outline:none;border-color:var(--primary);box-shadow:0 0 0 3px rgba(79,70,229,.14);
}
.field textarea{min-height:140px;resize:vertical}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
@media (max-width:640px){.field-row{grid-template-columns:1fr}}
.form-status{font-size:.9rem;margin-top:.8rem;min-height:1.4em}
.form-status.ok{color:#15803D}
.form-status.err{color:#B4483C}

/* ---------- Stats ---------------------------------------------------------- */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem}
.stat{text-align:left;position:relative;padding-top:1.1rem;border-top:1px solid var(--border)}
/* `.num` and `.label` were the markup every page outside the home page actually
   shipped, and neither was in this selector list — so the figures rendered at
   17px body sans instead of the display face. They are the same component; one
   list covers both spellings. */
.stat .v,.stat .n,.stat .num{font-family:var(--font-display);font-size:clamp(2rem,3.6vw,2.9rem);
  color:var(--heading);line-height:1;font-variant-numeric:tabular-nums;display:block;
  letter-spacing:-.02em;font-weight:400}
.stat .k,.stat .l,.stat .label{font-size:.82rem;color:var(--text-muted);margin-top:.5rem;display:block;
  font-weight:400;letter-spacing:0;max-width:22ch}
/* A hairline that fills as the stat arrives. The counter already animates; the
   rule gives the eye something to measure it against. */
.stat::before{content:"";position:absolute;top:-1px;left:0;width:100%;height:1px;
  background:var(--primary);transform:scaleX(0);transform-origin:left;
  transition:transform 900ms var(--ease-out)}
.stat.in::before,.reveal.in .stat::before,.stats.in .stat::before{transform:scaleX(1)}
@media (max-width:820px){.stats{grid-template-columns:repeat(2,1fr)}}

/* ---------- Feature list --------------------------------------------------- */
.feature-list{list-style:none;padding:0;margin:1.4rem 0 0;display:grid;gap:.9rem}
.feature-list li{display:flex;gap:.8rem;align-items:flex-start;font-size:.93rem;color:var(--text)}
.feature-list strong{display:block;margin-bottom:.15rem}
.tick{
  width:22px;height:22px;flex:0 0 22px;border-radius:50%;display:grid;place-items:center;
  background:rgba(14,116,144,.1);color:var(--accent);font-size:.72rem;margin-top:.1rem;
}
.dotc{width:7px;height:7px;border-radius:50%;background:var(--primary);display:inline-block}

/* ---------- Article -------------------------------------------------------- */
.article{max-width:72ch;margin-inline:auto}
.article h2{font-size:clamp(1.7rem,3vw,2.4rem);margin-top:2.4rem}
.article h3{margin-top:1.8rem}
.article p,.article li{font-size:1.03rem;line-height:1.72;color:var(--text)}
.article ul,.article ol{padding-left:1.2rem;display:grid;gap:.5rem;margin:0 0 1.2rem}
.article-meta{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;font-size:.82rem;
  color:var(--text-muted);padding-bottom:1.4rem;border-bottom:1px solid var(--border);
  margin-bottom:2rem}
/* The four article pages separate their meta items with an EMPTY <span class="sep">.
   .sep only ever set a colour, so the separator painted nothing and the three
   items ran together as "Guide 4 min read AI & Automation". Generating the glyph
   from the empty element keeps the markup as shipped. */
.sep:empty::before{content:"\00B7"}
.article-meta .sep{color:var(--border-strong)}
.article-meta > span:first-child{font-family:var(--font-mono);font-size:.72rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--accent)}
/* First paragraph of an article gets the display face and a larger size. The
   drop into body text is what tells the eye the piece has started. */
.article > .lede:first-child{font-family:var(--font-display);font-size:clamp(1.2rem,2.2vw,1.55rem);
  line-height:1.38;letter-spacing:-.015em;color:var(--heading);margin-bottom:1.6rem}
.article h2{scroll-margin-top:120px}
.article-cta{
  margin-top:3rem;padding-top:2rem;border-top:1px solid var(--border);
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1.4rem;
}
.article-cta > div{flex:1;min-width:min(100%,26ch)}
.article-cta p{margin:0;font-size:.93rem}

/* ---------- Quiz ----------------------------------------------------------- */
.quiz{padding:clamp(1.6rem,3vw,2.2rem);max-width:760px;margin-inline:auto}
.quiz-progress{height:3px;border-radius:2px;background:var(--bg-2);overflow:hidden;margin-bottom:1.6rem}
.quiz-progress span{display:block;height:100%;background:var(--primary);
  transform-origin:left;transition:transform 400ms var(--ease-out)}
.quiz-q{font-family:var(--font-display);font-size:1.5rem;color:var(--heading);margin-bottom:1.2rem;
  line-height:1.2}
.quiz-options{display:grid;gap:.5rem;margin-bottom:1.4rem}
.quiz-opt{
  display:flex;align-items:center;gap:.9rem;width:100%;text-align:left;cursor:pointer;
  padding:.9rem 1.1rem;border-radius:var(--r-sm);border:1px solid var(--border-strong);
  background:var(--surface);font-family:var(--font-sans);font-size:.95rem;color:var(--text);
  transition:transform 170ms var(--ease-out),border-color 170ms var(--ease-out),
             background-color 170ms var(--ease-out);
}
.quiz-opt:active{transform:scale(.985)}
.quiz-opt .k{
  width:26px;height:26px;flex:0 0 26px;border-radius:50%;display:grid;place-items:center;
  background:var(--bg-2);font-size:.76rem;font-weight:700;color:var(--text-muted);
}
@media (hover:hover) and (pointer:fine){
  .quiz-opt:hover{border-color:var(--primary);background:rgba(79,70,229,.03)}
  .quiz-opt:hover .k{background:var(--primary);color:#fff}
}
.quiz-foot{display:flex;align-items:center;justify-content:space-between;gap:1rem;
  font-size:.8rem;color:var(--text-muted)}
.quiz-back{background:none;border:0;cursor:pointer;font-family:var(--font-sans);
  font-size:.8rem;color:var(--primary);font-weight:600;padding:.3rem}
.quiz-result{text-align:center}
.quiz-result h3{font-family:var(--font-display);font-weight:400;font-size:2rem;margin:.6rem 0 .4rem}
.quiz-actions{display:flex;gap:.7rem;justify-content:center;flex-wrap:wrap;margin-top:1.4rem}

/* ---------- Footer --------------------------------------------------------- */
.site-footer{background:var(--ink);color:var(--ink-muted);padding:clamp(4rem,8vw,6rem) 0 2.5rem;
  margin-top:0}
.footer-grid{display:grid;grid-template-columns:1.6fr repeat(3,1fr);gap:2.5rem;
  padding-bottom:3rem;border-bottom:1px solid var(--ink-border)}
.site-footer .brand,.site-footer h5{color:#fff}
.site-footer h5{font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;
  margin:0 0 1.1rem;font-weight:600}
/* :not(.brand) — the footer brand is an <a> inside .footer-col too, and this
   rule outranks .brand, so without the exclusion it forces the lockup to
   display:block and the mark stacks above the wordmark. */
.footer-col a:not(.brand){display:block;padding:.32rem 0;font-size:.9rem;
  transition:color 160ms var(--ease-out)}
@media (hover:hover) and (pointer:fine){.footer-col a:hover{color:#fff}}
.footer-brand p{color:rgba(255,255,255,.5);font-size:.9rem;max-width:38ch;margin-top:1.2rem}
.socials{display:flex;gap:.6rem;margin-top:1.2rem}
.socials a{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;
  border:1px solid var(--ink-border);color:var(--ink-muted);
  transition:transform 180ms var(--ease-out),color 180ms var(--ease-out),
             border-color 180ms var(--ease-out)}
.socials a:active{transform:scale(.94)}
@media (hover:hover) and (pointer:fine){
  .socials a:hover{color:#fff;border-color:rgba(255,255,255,.4);transform:translateY(-2px)}
}
.footer-bottom{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  padding-top:1.8rem;font-size:.82rem}
.footer-legal a{margin-left:1.2rem}
@media (max-width:860px){.footer-grid{grid-template-columns:1fr 1fr}}
/* Below ~560px two columns cannot hold. A grid track is min-width:auto by
   default, so it refuses to shrink past its longest unbreakable word — the
   contact email alone forced the column wider than a 320px viewport, pushing
   the whole document 60px sideways. body{overflow-x:hidden} hid the scrollbar
   but not the broken layout. min-width:0 lets the track shrink; anywhere lets
   the address itself wrap. */
@media (max-width:560px){
  .footer-grid{grid-template-columns:1fr;gap:2rem}
  .footer-bottom{flex-direction:column;gap:.6rem}
  .footer-legal a{margin-left:0;margin-right:1.2rem}
}
.footer-col{min-width:0}
.footer-col a{overflow-wrap:anywhere}

/* Touch targets. The stacked footer links were 28-32px tall, under the 44px
   these guidelines ask for; the extra padding only applies where there is no
   fine pointer, so the desktop footer keeps its tighter rhythm. */
@media (pointer:coarse){
  .footer-col a:not(.brand){padding:.62rem 0}
  .footer-legal a{display:inline-flex;align-items:center;min-height:44px}
  /* The inline links — breadcrumbs, hero meta, the "read more" affordance on a
     section — all sit between 19px and 23px tall, which is roughly half the
     44px a finger needs. Height is added rather than padding so nothing in the
     surrounding flex row shifts sideways. Only standalone anchors are touched:
     a .card-link inside an <a class="card"> is decoration, not a second target,
     and giving it a hit area would put two overlapping targets on one card. */
  a.card-link,a.go,.hero-meta a,.breadcrumb a,.article-cta a:not(.btn){
    min-height:44px;display:inline-flex;align-items:center;
  }
  a.chip,a.pill{min-height:44px}
  .socials a{width:44px;height:44px}
  .info-item a{min-height:44px;display:inline-flex;align-items:center}
  .brand{min-height:44px}
  .matrix-key span{min-height:38px}
}

/* ---------- Card icon well ------------------------------------------------
   `<div class="icon"><svg viewBox="0 0 24 24">` is the markup about.html,
   partners.html and services/index.html have always shipped, and nothing in
   this sheet matched it. An <svg> with a viewBox and no width/height has no
   intrinsic size, so it fell back to the default object size and painted at
   316x316 inside a 369px card — fourteen of them across the site. The card
   looked empty because a single hairline glyph the size of a postcard reads as
   a blank panel with a scratch on it.

   Sized against the 34px well the contact page's .info-item already uses, so
   the two read as one component rather than two near-misses. .info-item keeps
   its own rule further down; this one deliberately does not reach into it. */
.card .icon,.ed-tile .icon,.plan .icon,.pin-panel .icon{
  width:44px;height:44px;flex:0 0 44px;border-radius:13px;
  display:grid;place-items:center;margin-bottom:1.15rem;
  background:linear-gradient(150deg,rgba(79,70,229,.10),rgba(14,116,144,.07));
  border:1px solid rgba(79,70,229,.14);color:var(--primary);
  box-shadow:var(--inner-hi);
  transition:transform 320ms var(--ease-out),background-color 320ms var(--ease-out);
}
.card .icon svg,.ed-tile .icon svg,.plan .icon svg,.pin-panel .icon svg{
  width:21px;height:21px;flex:none;display:block;
}
/* Stroke weight travels with size. The source markup asks for stroke-width:2 at
   24px, which at 21px reads heavy beside the 1.5 the section markers use, so it
   is normalised here rather than edited in fourteen places. */
.card .icon svg[stroke-width]{stroke-width:1.7}
@media (hover:hover) and (pointer:fine){
  .card:hover .icon{transform:translateY(-2px) rotate(-3deg)}
}

/* ---------- Offset panel --------------------------------------------------
   Lifts a block off the section ground. It was referenced in service-page
   markup and never defined, so "Platforms we operate" rendered as loose text on
   paper with no container at all. */
.offset-panel{
  position:relative;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:clamp(1.8rem,4vw,3rem);
  box-shadow:var(--inner-hi),var(--lift-2);
}
.offset-panel::before{
  content:"";position:absolute;inset:auto 0 -14px 0;height:28px;z-index:-1;
  border-radius:var(--r-lg);background:var(--bg-2);border:1px solid var(--border);
  transform:scaleX(.94);
}

/* ---------- Spec sheet ----------------------------------------------------
   A datasheet, not a card grid. Mono keys, tabular values, hairline rows. This
   is the device that makes a service page read as engineering rather than
   brochure: it commits to specifics in a shape that is scannable in one column.
   Deliberately inert on hover — a spec is read, not clicked. */
.spec{border-top:1px solid var(--border)}
.spec-row{
  display:grid;grid-template-columns:minmax(140px,.34fr) 1fr;gap:clamp(.8rem,3vw,2rem);
  padding:1.05rem 0;border-bottom:1px solid var(--border);align-items:baseline;
}
.spec-row dt,.spec-row .k{
  font-family:var(--font-mono);font-size:.74rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-muted);margin:0;
}
.spec-row dd,.spec-row .v{margin:0;font-size:.95rem;color:var(--text)}
.spec-row dd strong,.spec-row .v strong{color:var(--heading);font-weight:600}
.spec-row .fig{font-family:var(--font-mono);font-size:.88em;color:var(--accent);
  font-variant-numeric:tabular-nums}
@media (max-width:620px){.spec-row{grid-template-columns:1fr;gap:.3rem}}

/* ---------- Comparison matrix --------------------------------------------
   Five services against what each one actually covers. A real table, because
   the relationship is genuinely two-dimensional and a card grid cannot express
   it. Scrolls inside itself rather than pushing the document wide. */
.matrix-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;
  border:1px solid var(--border);border-radius:var(--r-md);background:var(--surface);
  box-shadow:var(--inner-hi),var(--lift-1)}
.matrix{width:100%;min-width:760px;border-collapse:collapse;font-size:.9rem}
.matrix th,.matrix td{padding:.9rem 1rem;text-align:left;border-bottom:1px solid var(--border)}
.matrix thead th{
  font-family:var(--font-mono);font-size:.7rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--text-muted);font-weight:400;vertical-align:bottom;background:var(--bg-2);
}
.matrix tbody th{font-weight:600;color:var(--heading);font-size:.94rem}
.matrix tbody th span{display:block;font-weight:400;font-size:.8rem;color:var(--text-muted);
  margin-top:.15rem}
.matrix tbody tr:last-child th,.matrix tbody tr:last-child td{border-bottom:0}
.matrix td{text-align:center;width:11%}
.matrix .yes{color:var(--accent);font-size:1rem}
.matrix .part{color:var(--text-muted);opacity:.7}
.matrix .no{color:var(--border-strong)}
@media (hover:hover) and (pointer:fine){.matrix tbody tr:hover{background:var(--bg-2)}}
.matrix-key{display:flex;flex-wrap:wrap;gap:1.2rem;margin-top:.9rem;
  font-size:.78rem;color:var(--text-muted)}
.matrix-key span{display:inline-flex;align-items:center;gap:.4rem}

/* ---------- Callout -------------------------------------------------------
   The one sentence on a page worth stopping at. A left rule in the accent and
   the display face — no box, because a box would make it a card again. */
.callout{
  border-left:2px solid var(--primary);padding:.2rem 0 .2rem 1.4rem;
  margin:2rem 0;max-width:60ch;
}
.callout p{font-family:var(--font-display);font-size:clamp(1.15rem,2vw,1.45rem);
  line-height:1.34;letter-spacing:-.015em;color:var(--heading);margin:0}
.callout cite{display:block;margin-top:.7rem;font-style:normal;font-size:.78rem;
  letter-spacing:.1em;text-transform:uppercase;color:var(--text-muted)}

/* ---------- Figure row ----------------------------------------------------
   Three or four numbers on one line, tabular, hairline-separated. Cheaper than
   a stats grid and better suited to a band that only states a fact in passing.
   Inverts inside an ink block. */
.figrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:1px;background:var(--border);border:1px solid var(--border);
  border-radius:var(--r-md);overflow:hidden}
.figrow > div{background:var(--surface);padding:1.3rem 1.4rem}
.figrow b{display:block;font-family:var(--font-display);font-size:1.85rem;line-height:1;
  color:var(--heading);font-variant-numeric:tabular-nums;letter-spacing:-.02em;font-weight:400}
.figrow span{display:block;margin-top:.45rem;font-size:.8rem;color:var(--text-muted)}
.bleed .figrow,.cta-band .figrow,.contact-band .figrow{background:var(--ink-border);
  border-color:var(--ink-border)}
.bleed .figrow > div,.cta-band .figrow > div,.contact-band .figrow > div{background:var(--ink-2)}
.bleed .figrow b,.cta-band .figrow b,.contact-band .figrow b{color:#fff}
.bleed .figrow span,.cta-band .figrow span,.contact-band .figrow span{color:var(--ink-muted)}

/* ---------- Dense link list -----------------------------------------------
   Navigation between siblings, as rows rather than cards. Same ink wash the
   .step-row uses, so the two devices read as one family. */
.linklist{display:grid;border-top:1px solid var(--border)}
.linklist a{
  position:relative;display:grid;grid-template-columns:auto 1fr auto;
  gap:clamp(.9rem,3vw,2rem);align-items:center;
  padding:1.35rem .9rem;border-bottom:1px solid var(--border);
}
.linklist a::after{content:"";position:absolute;inset:0;background:var(--bg-2);z-index:-1;
  clip-path:inset(0 100% 0 0);transition:clip-path 380ms var(--ease-out)}
.linklist .n{font-family:var(--font-mono);font-size:.75rem;color:var(--text-muted);
  letter-spacing:.04em;min-width:2.4em}
.linklist strong{display:block;color:var(--heading);font-size:1.02rem;font-weight:600;
  letter-spacing:-.012em}
.linklist .d{display:block;font-size:.88rem;color:var(--text-muted);margin-top:.15rem}
.linklist .go-x{color:var(--border-strong);font-size:1.1rem;
  transition:transform 300ms var(--ease-out),color 300ms var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .linklist a:hover::after{clip-path:inset(0 0 0 0)}
  .linklist a:hover .n{color:var(--primary)}
  .linklist a:hover .go-x{color:var(--primary);transform:translateX(4px)}
}
@media (max-width:620px){.linklist a{grid-template-columns:auto 1fr}.linklist .go-x{display:none}}

/* ---------- Blueprint ground ----------------------------------------------
   For bands that are structurally sparse on purpose. A 32px rule grid at very
   low alpha, masked so it fades out before the section edge: something for the
   eye to sit on without becoming a pattern anyone has to look at. */
.ruled{position:relative;isolation:isolate}
.ruled::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background-image:linear-gradient(to right,var(--hair) 1px,transparent 1px),
                   linear-gradient(to bottom,var(--hair) 1px,transparent 1px);
  background-size:32px 32px;opacity:.55;
  -webkit-mask-image:radial-gradient(ellipse 92% 72% at 50% 50%,#000 18%,transparent 76%);
  mask-image:radial-gradient(ellipse 92% 72% at 50% 50%,#000 18%,transparent 76%);
}

/* ---------- Section index -------------------------------------------------
   A running number above a section label. An index, not decoration: the
   sections of a long page genuinely are an ordered set, and this says "four of
   nine" without a progress bar. */
.sec-index{
  display:flex;align-items:center;gap:.8rem;margin-bottom:1.2rem;
  font-family:var(--font-mono);font-size:.72rem;letter-spacing:.1em;
  color:var(--text-muted);text-transform:uppercase;
}
.sec-index::after{content:"";flex:1;height:1px;background:var(--border);max-width:140px}
.center .sec-index{justify-content:center}
.center .sec-index::after{display:none}

/* ---------- Stance --------------------------------------------------------
   A statement Averro makes in its own voice. Deliberately not a testimonial
   slot: there are no client quotes to put here and inventing one would be the
   worst thing on the page. */
.stance{display:grid;grid-template-columns:auto 1fr;gap:clamp(1.2rem,3vw,2.2rem);
  align-items:start;padding:clamp(1.6rem,3vw,2.4rem) 0;border-top:1px solid var(--border)}
.stance .q{font-family:var(--font-display);font-size:3.4rem;line-height:.7;
  color:var(--primary);opacity:.26;user-select:none}
.stance p{font-family:var(--font-display);font-size:clamp(1.2rem,2.2vw,1.6rem);line-height:1.32;
  letter-spacing:-.018em;color:var(--heading);margin:0}
.stance .who{margin-top:.9rem;font-size:.79rem;letter-spacing:.1em;text-transform:uppercase;
  color:var(--text-muted)}

/* ---------- Two-up panel split --------------------------------------------
   A split where one half is a list of specifics rather than a photograph. Used
   to break up pages that would otherwise be four card grids in a row. */
.duo{display:grid;grid-template-columns:1fr 1fr;gap:clamp(1.5rem,4vw,3.5rem);align-items:start}
.duo > .panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
  padding:clamp(1.5rem,3vw,2.1rem);box-shadow:var(--inner-hi),var(--lift-1)}
.duo > .panel h3{margin-bottom:1rem}
@media (max-width:880px){.duo{grid-template-columns:1fr}}

/* ---------- Topic rail ----------------------------------------------------
   Chips that are links, for the insights index. .chip already carries the shape;
   this only adds the interactive half so the two do not diverge. */
a.chip{transition:border-color 200ms var(--ease-out),color 200ms var(--ease-out),
  transform 200ms var(--ease-out)}
a.chip:active{transform:scale(.97)}
@media (hover:hover) and (pointer:fine){
  a.chip:hover{border-color:var(--primary);color:var(--heading)}
}

/* ---------- Misc ----------------------------------------------------------- */
.mark-row{display:flex;flex-wrap:wrap;gap:.6rem;align-items:center}
.concept{padding:1.6rem;border-radius:var(--r-md);background:var(--bg-2);border:1px solid var(--border)}
.visual-panel{padding:1.6rem}
.matches{font-size:.85rem;color:var(--text-muted)}
.file{display:inline-flex;align-items:center;gap:.5rem;font-size:.85rem}
.num{font-variant-numeric:tabular-nums}
.tier{padding:1.5rem}
.has-tunnel{background:var(--paper)}

/* ---------- Legal documents ------------------------------------------------
   Terms of Use, Privacy Policy, Code of Conduct, Accessibility Statement.
   Numbered so a clause can be cited in an email or a contract, and laid out for
   someone hunting one paragraph rather than reading front to back. */
.legal{max-width:76ch;margin-inline:auto}
.legal > section{scroll-margin-top:120px}
.legal h2{
  display:flex;gap:.85rem;align-items:baseline;
  font-size:clamp(1.35rem,2.4vw,1.85rem);line-height:1.18;letter-spacing:-.018em;
  margin:3rem 0 .9rem;padding-top:1.6rem;border-top:1px solid var(--border);
}
.legal > section:first-of-type h2{margin-top:1rem;border-top:0;padding-top:0}
.legal h2 .cn{
  font-family:var(--font-mono);font-size:.78rem;font-weight:400;color:var(--accent);
  letter-spacing:.04em;flex:none;padding-top:.55em;
}
.legal h3{font-size:1.02rem;margin:1.7rem 0 .5rem;letter-spacing:-.01em}
.legal p,.legal li{font-size:1rem;line-height:1.68;color:var(--text)}
.legal ul,.legal ol{padding-left:1.25rem;margin:0 0 1.1rem;display:grid;gap:.5rem}
.legal ol{list-style:decimal}
.legal ol.alpha{list-style:lower-alpha}
.legal dl{margin:0 0 1.2rem}

/* Contents. Two columns on a wide screen because a fifteen-clause policy is a
   long thin list otherwise, and the jump links are the main reason anyone
   scrolls back to the top. */
.legal-toc{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
  box-shadow:var(--inner-hi),var(--lift-1);padding:1.5rem 1.6rem;margin-bottom:2.5rem;
}
.legal-toc b{display:block;font-family:var(--font-mono);font-size:.72rem;letter-spacing:.14em;
  text-transform:uppercase;color:var(--text-muted);margin-bottom:.9rem}
.legal-toc ol{list-style:none;padding:0;margin:0;display:grid;gap:.1rem;
  grid-template-columns:1fr 1fr;counter-reset:toc}
.legal-toc li{counter-increment:toc}
.legal-toc a{display:flex;gap:.7rem;padding:.4rem .1rem;font-size:.92rem;color:var(--text);
  border-bottom:1px solid transparent;transition:color 160ms var(--ease-out)}
.legal-toc a::before{content:counter(toc,decimal-leading-zero);font-family:var(--font-mono);
  font-size:.76rem;color:var(--text-muted);flex:none;padding-top:.16em}
@media (hover:hover) and (pointer:fine){
  .legal-toc a:hover{color:var(--primary)}
  .legal-toc a:hover::before{color:var(--primary)}
}
@media (max-width:700px){.legal-toc ol{grid-template-columns:1fr}}

/* Defined terms, and the status line under the title. */
.legal dfn{font-style:normal;font-weight:600;color:var(--heading)}
.legal-status{
  display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;align-items:center;
  font-family:var(--font-mono);font-size:.76rem;letter-spacing:.04em;color:var(--text-muted);
  padding:.9rem 0;border-block:1px solid var(--border);margin-bottom:2rem;
}
.legal-status b{color:var(--heading);font-weight:600}

/* A clause that carries an obligation on the reader, or a statutory carve-out
   that must not be skimmed past, gets the callout's left rule at body size. */
.legal .note{
  border-left:2px solid var(--accent);padding:.1rem 0 .1rem 1.2rem;margin:1.3rem 0;
  background:none;
}
.legal .note p:last-child{margin-bottom:0}
.legal .note p{font-size:.96rem}

/* Placeholders. Every fact the site cannot know -- ABN, registered address,
   governing jurisdiction -- is marked rather than guessed, and marked loudly
   enough that it cannot go live by accident. Search the tree for "legal-fill"
   before publishing. */
.legal-fill{
  display:inline;background:rgba(180,72,60,.10);border-bottom:2px solid #B4483C;
  color:#8F3226;font-weight:600;padding:.05em .25em;border-radius:3px;
}
.legal-fill::before{content:"\25B8\00A0"}

/* Contact block at the foot of each document. */
.legal-contact{
  margin-top:3rem;padding-top:1.8rem;border-top:1px solid var(--border);
}
.legal-contact dl{display:grid;grid-template-columns:auto 1fr;gap:.55rem 1.6rem;margin:0}
.legal-contact dt{font-family:var(--font-mono);font-size:.74rem;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-muted);padding-top:.2em}
.legal-contact dd{margin:0;font-size:.97rem;color:var(--text)}
@media (max-width:620px){
  .legal-contact dl{grid-template-columns:1fr;gap:.15rem}
  .legal-contact dd{margin-bottom:.7rem}
}

/* Cross-references between the four documents, so each one is a way into the
   others rather than a dead end. */
.legal-siblings{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem;margin-top:2.5rem}
@media (max-width:820px){.legal-siblings{grid-template-columns:1fr}}

@media print{
  .legal-toc,.legal-siblings{display:none}
  .legal h2{page-break-after:avoid}
  .legal-fill{background:none;color:#000;border-bottom:1px solid #000}
}

/* ---------- Paint budget ---------------------------------------------------
   `content-visibility:auto` on the below-fold sections was tried here and
   REMOVED. It is the right tool for a heavy page, and this is not one: the home
   page is 621 DOM nodes, the longest task was already 57ms, and measuring
   before and after showed no improvement outside noise. What it did do was stop
   the skipped sections painting in a full-page capture and in print -- a real
   behaviour traded away for a benefit that could not be measured.

   The two rules below survived because each pays for itself:

   The backdrop canvas is the only element that repaints every frame while the
   page scrolls, so it earns its own compositor layer.

   The marquee's height is reserved before its content lays out, so the strip
   cannot contribute a layout shift on first paint. */
#tunnel{will-change:transform}
.marquee{min-height:62px}

/* ---------- Scroll reveal --------------------------------------------------- */
/* One curve, one distance, blur to soften the arrival. Long by design: this is
   content entering the page, not UI responding to a click. */
.reveal{
  opacity:0;transform:translateY(26px);filter:blur(7px);
  transition:opacity 820ms var(--ease-out),transform 820ms var(--ease-out),filter 820ms var(--ease-out);
}
.reveal.in{opacity:1;transform:none;filter:none}
.d1{transition-delay:70ms}.d2{transition-delay:140ms}.d3{transition-delay:210ms}

/* Above the fold, the reveal has nothing to reveal -- the content is already in
   view when the observer first runs. It keeps a short entrance so the hero still
   assembles rather than snapping in, but at a quarter of the duration and with
   no blur: a 7px filter across a full-width hero is expensive to paint and reads
   as a smear at that size rather than as softness.
   The <h1> is excluded entirely in the markup, because it is the LCP element. */
.hero .reveal,.page-hero .reveal{
  transition-duration:420ms;
  filter:none;
  transform:translateY(12px);
}
.hero .reveal.in,.page-hero .reveal.in{transform:none}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
  .reveal{opacity:1;transform:none;filter:none}
  .pin-figure i{transform:scaleY(1)}
}

@media print{
  .site-header,.site-footer,.marquee,.quiz,body::after{display:none!important}
  body{background:#fff;color:#000}
}

/* ==========================================================================
   Lenis smooth scroll
   Vendored rules from lenis@1.3.26 dist/lenis.css, inlined here so the sheet
   stays a single request. Lenis puts .lenis on <html> only while it is
   running, so none of this applies under prefers-reduced-motion.
   ========================================================================== */
html.lenis,html.lenis body{height:auto}
/* Native smooth scrolling must yield: both animate the same gesture and the
   result is a fight the user can feel. Set at line 89, overridden here. */
html.lenis{scroll-behavior:auto}
.lenis:not(.lenis-autoToggle).lenis-stopped{overflow:clip}
.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch],
.lenis [data-lenis-prevent-vertical],
.lenis [data-lenis-prevent-horizontal]{overscroll-behavior:contain}
.lenis.lenis-smooth iframe{pointer-events:none}
.lenis.lenis-autoToggle{transition-property:overflow;transition-duration:1ms;transition-behavior:allow-discrete}
canvas[data-rive]{display:block;max-width:100%}

/* ==========================================================================
   PAGE TRANSITIONS
   One movement per destination, so moving around the site does not feel like
   the same door every time. motion.js sets data-pt from the DESTINATION's path
   and toggles .pt-out then .pt-in, so the two halves are complements: a page
   that arrives from the right is preceded by one that leaves to the left.

   Applied to `body > *` rather than to a wrapper. Wrapping the page would make
   the wrapper the containing block for the fixed #tunnel canvas and drag the
   backdrop along with the content — the one element that has to stay still.

   Enters use --ease-out. Exits use --ease-in-out, whose accelerating first half
   is what leaving the screen wants; the "never ease-in on UI" rule is about
   interface feedback answering a click, not about content departing.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  body[data-pt].pt-in > *:not(#tunnel),
  body[data-pt].pt-out > *:not(#tunnel){
    animation-fill-mode:both;
    will-change:transform,opacity,clip-path;
  }
  body[data-pt].pt-in  > *:not(#tunnel){animation-duration:400ms;animation-timing-function:var(--ease-out)}
  body[data-pt].pt-out > *:not(#tunnel){animation-duration:170ms;animation-timing-function:var(--ease-in-out)}

  /* home — content lifts into place */
  body[data-pt="rise"].pt-in   > *:not(#tunnel){animation-name:pt-rise-in}
  body[data-pt="rise"].pt-out  > *:not(#tunnel){animation-name:pt-rise-out}
  @keyframes pt-rise-in {from{opacity:0;transform:translate3d(0,20px,0)} to{opacity:1;transform:none}}
  @keyframes pt-rise-out{from{opacity:1;transform:none} to{opacity:0;transform:translate3d(0,-14px,0)}}

  /* services — the catalogue slides across */
  body[data-pt="slide"].pt-in  > *:not(#tunnel){animation-name:pt-slide-in}
  body[data-pt="slide"].pt-out > *:not(#tunnel){animation-name:pt-slide-out}
  @keyframes pt-slide-in {from{opacity:0;transform:translate3d(38px,0,0)} to{opacity:1;transform:none}}
  @keyframes pt-slide-out{from{opacity:1;transform:none} to{opacity:0;transform:translate3d(-32px,0,0)}}

  /* about — wipes down, like a page being turned over */
  body[data-pt="wipe"].pt-in   > *:not(#tunnel){animation-name:pt-wipe-in}
  body[data-pt="wipe"].pt-out  > *:not(#tunnel){animation-name:pt-wipe-out}
  @keyframes pt-wipe-in {from{opacity:.4;clip-path:inset(0 0 100% 0)} to{opacity:1;clip-path:inset(0 0 0 0)}}
  @keyframes pt-wipe-out{from{opacity:1;clip-path:inset(0 0 0 0)} to{opacity:.4;clip-path:inset(100% 0 0 0)}}

  /* insights — opens from the centre, like a spread */
  body[data-pt="unfold"].pt-in  > *:not(#tunnel){animation-name:pt-unfold-in}
  body[data-pt="unfold"].pt-out > *:not(#tunnel){animation-name:pt-unfold-out}
  @keyframes pt-unfold-in {from{opacity:.3;clip-path:inset(0 46% 0 46%)} to{opacity:1;clip-path:inset(0 0 0 0)}}
  @keyframes pt-unfold-out{from{opacity:1;clip-path:inset(0 0 0 0)} to{opacity:.3;clip-path:inset(0 46% 0 46%)}}

  /* partners — settles back from slightly forward */
  body[data-pt="expand"].pt-in  > *:not(#tunnel){animation-name:pt-expand-in}
  body[data-pt="expand"].pt-out > *:not(#tunnel){animation-name:pt-expand-out}
  @keyframes pt-expand-in {from{opacity:0;transform:scale(1.025)} to{opacity:1;transform:none}}
  @keyframes pt-expand-out{from{opacity:1;transform:none} to{opacity:0;transform:scale(.985)}}

  /* contact — comes down to meet you */
  body[data-pt="drop"].pt-in  > *:not(#tunnel){animation-name:pt-drop-in}
  body[data-pt="drop"].pt-out > *:not(#tunnel){animation-name:pt-drop-out}
  @keyframes pt-drop-in {from{opacity:0;transform:translate3d(0,-24px,0)} to{opacity:1;transform:none}}
  @keyframes pt-drop-out{from{opacity:1;transform:none} to{opacity:0;transform:translate3d(0,18px,0)}}

  /* privacy, terms, 404 — deliberately characterless */
  body[data-pt="fade"].pt-in  > *:not(#tunnel){animation-name:pt-fade-in}
  body[data-pt="fade"].pt-out > *:not(#tunnel){animation-name:pt-fade-out}
  @keyframes pt-fade-in {from{opacity:0} to{opacity:1}}
  @keyframes pt-fade-out{from{opacity:1} to{opacity:0}}
}
