/* ==========================================================================
   Technovative design system
   Redesign: homepage + global shell. Loaded on every page, last, so it owns
   the shell everywhere; main.css is loaded before it on pages outside this
   round's scope and still supplies their page-specific components.
   ========================================================================== *//* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */:root{color-scheme:light;/* Type */--font-sans:"Archivo",system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;--font-serif:"Source Serif 4",Georgia,"Times New Roman",serif;/* Ink — all navy-cast, never neutral grey */--ink:#0b1220;--ink-2:#44536b;--ink-3:#5e6c82;--ink-on-brand:#ffffff;--ink-on-brand-2:#a8c0e8;/* Brand — the single committed colour */--brand:#003b93;--brand-deep:#002a6b;--brand-bright:#0051c3;--brand-wash:#eef3fb;/* Grounds */--ground:#ffffff;--ground-sunken:#f5f7fa;--ground-deep:#0b1220;/* Lines — boundaries are tone shifts; hairlines only where a real edge exists */--hairline:rgba(11, 18, 32, 0.1);--hairline-strong:rgba(11, 18, 32, 0.16);--hairline-on-dark:rgba(255, 255, 255, 0.14);/* Semantic, data only — never decoration */--positive:#0a7a3d;--negative:#b20f03;/* Space — 8pt */--space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:24px;--space-6:32px;--space-7:48px;--space-8:64px;--space-9:96px;--space-10:128px;/* Radius */--radius-sm:6px;--radius:10px;--radius-lg:14px;/* Elevation — offset + blur, tinted from the brand hue */--shadow-sm:0 1px 2px rgba(11, 18, 32, 0.06),0 1px 3px rgba(11, 18, 32, 0.07);--shadow-md:0 2px 4px rgba(11, 18, 32, 0.04),0 6px 16px rgba(11, 18, 32, 0.08);--shadow-lg:0 4px 8px rgba(11, 18, 32, 0.05),0 16px 40px rgba(11, 18, 32, 0.1);/* Motion */--ease:cubic-bezier(0.16, 1, 0.3, 1);--dur:200ms;/* Layout */--measure:68ch;--shell-h:68px;/* The 12-column gutter. It has to shrink on small screens: eleven 24px
     gutters eat 264px of a 320px viewport, collapsing every track to zero. */--gutter:24px}@media (max-width: 767.98px){:root{--gutter:16px}}@media (max-width: 575.98px){:root{--gutter:12px}}/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */*,*::before,*::after{box-sizing:border-box}html{scroll-behavior:smooth;scroll-padding-top:calc(var(--shell-h) + var(--space-5));-webkit-text-size-adjust:100%;/* Not on body: setting only overflow-x there (leaving overflow-y at its
     default) makes the browser auto-promote body's overflow-y from visible
     to auto per the CSS Overflow spec, which makes Bootstrap's Scrollspy
     treat body - not the viewport - as the IntersectionObserver root, so it
     only ever activates once and never updates on scroll. */overflow-x:hidden}body{margin:0;background:var(--ground);color:var(--ink);font-family:var(--font-sans);font-size:1.0625rem;line-height:1.65;font-weight:400;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-synthesis-weight:none}/* Browser surfaces — the parts we did not draw still carry the design. */::selection{background:var(--brand);color:#fff}body{caret-color:var(--brand);scrollbar-color:var(--hairline-strong) transparent;scrollbar-width:thin}::-webkit-scrollbar{width:11px;height:11px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--hairline-strong);border:3px solid var(--ground);border-radius:99px}::-webkit-scrollbar-thumb:hover{background:var(--ink-3)}:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:3px}:focus:not(:focus-visible){outline:none}img,svg,iframe{max-width:100%}img{height:auto}h1,h2,h3,h4,h5,h6{font-family:var(--font-sans);color:var(--ink);font-weight:600;line-height:1.15;letter-spacing:-0.022em;text-wrap:balance}/* Content resets are scoped to the page this system fully owns. Applied
   globally they strip Bootstrap's paragraph and heading flow from every route
   main.css still styles (blog, careers, service-details, legal). */.system-page h1,.system-page h2,.system-page h3,.system-page h4,.system-page h5,.system-page h6,.system-page p{margin:0}/* The shell renders on every page, so its own spacing is explicit. */.site-header h1,.site-header p,.site-footer h2,.site-footer p{margin:0}.site-footer .footer-col h2{margin-bottom:var(--space-4)}.site-footer .footer-about p{margin-top:var(--space-4)}a{color:var(--brand);text-decoration:none;text-underline-offset:3px;text-decoration-thickness:1px;transition:color var(--dur) var(--ease)}a:hover{color:var(--brand-bright);text-decoration:underline}/* Tabular figures wherever a number is being compared or counted. */.tnum,.metric-value,.stat-value{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}/* Skip link — self-contained; the homepage does not load Bootstrap. */.skip-link{position:absolute;left:var(--space-4);top:var(--space-4);z-index:2000;padding:var(--space-3) var(--space-5);background:var(--brand);color:#fff;font-weight:600;border-radius:var(--radius);box-shadow:var(--shadow-lg);transform:translateY(-200%);transition:transform var(--dur) var(--ease)}.skip-link:focus{transform:none;color:#fff;text-decoration:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}/* The shell header is sticky and in-flow. main.css still carries a 112px
   top offset sized for the old fixed header, which double-counts on every
   page it still styles (blog, careers, service-details, legal). */main.main{padding-top:0}/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */.shell{width:100%;max-width:1200px;margin-inline:auto;padding-inline:var(--space-5)}@media (max-width: 575.98px){.shell{padding-inline:var(--space-4)}}.band{padding-block:var(--space-9)}.band--sunken{background:var(--ground-sunken)}.band--deep{background:var(--ground-deep);color:var(--ink-on-brand)}.band--tight{padding-block:var(--space-8)}@media (max-width: 767.98px){.band{padding-block:var(--space-8)}.band--tight{padding-block:var(--space-7)}}/* Section heading: no eyebrow, no rule, no centred stack. The heading carries
   its own weight and the lede sits directly under it at reading measure. */.band-head{margin-bottom:var(--space-7)}/* The cap is a reading measure and belongs to the lede. Applied to the whole
   block it also throttled the heading, breaking short section titles onto two
   lines with half the screen empty beside them. */.band-head h2{font-size:clamp(1.75rem, 3.4vw, 2.5rem);letter-spacing:-0.028em/* max-width: 34ch; */}.band-head p{margin-top:var(--space-4);color:var(--ink-3);font-size:1.0625rem;max-width:54ch}.band--deep .band-head h2{color:var(--ink-on-brand)}.band--deep .band-head p{color:var(--ink-on-brand-2)}.prose{font-family:var(--font-serif);font-size:1.125rem;line-height:1.7;color:var(--ink-2);max-width:var(--measure)}.prose p + p{margin-top:var(--space-4)}.stack-top{margin-top:var(--space-5)}.stack-top-lg{margin-top:var(--space-7)}/* --------------------------------------------------------------------------
   4. Controls
   -------------------------------------------------------------------------- */.btn-solid,.btn-line{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);min-height:48px;padding:0 var(--space-6);border-radius:var(--radius);border:1px solid transparent;font-family:var(--font-sans);font-size:1rem;font-weight:600;letter-spacing:-0.006em;text-decoration:none;cursor:pointer;white-space:nowrap;transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease),box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}.btn-solid{background:var(--brand);color:#fff;box-shadow:var(--shadow-sm)}.btn-solid:hover{background:var(--brand-deep);color:#fff;text-decoration:none;box-shadow:var(--shadow-md)}.btn-solid:active{transform:translateY(1px);box-shadow:var(--shadow-sm)}.btn-line{background:transparent;color:var(--ink);border-color:var(--hairline-strong)}.btn-line:hover{background:var(--ground-sunken);border-color:var(--ink-3);color:var(--ink);text-decoration:none}.band--deep .btn-line{color:#fff;border-color:var(--hairline-on-dark)}.band--deep .btn-line:hover{background:rgba(255, 255, 255, 0.08);border-color:rgba(255, 255, 255, 0.34);color:#fff}.btn-solid:disabled,.btn-line:disabled,.btn-solid[aria-busy="true"],.btn-solid[aria-disabled="true"]{opacity:0.45;cursor:not-allowed;box-shadow:none;transform:none}/* Text action with a travelling arrow — the one repeated micro-state. */.action{display:inline-flex;align-items:center;gap:var(--space-2);font-weight:600;font-size:1rem;color:var(--brand);min-height:44px}.action:hover{text-decoration:none;color:var(--brand-bright)}.action i,.action .arw{transition:transform var(--dur) var(--ease)}.action:hover i,.action:hover .arw{transform:translateX(4px)}/* Bootstrap buttons on the routes main.css still styles. There are ~147 of
   them across service-details and the blog, so they are re-themed through
   Bootstrap's own --bs-btn-* variables rather than by editing markup. The
   homepage never loads Bootstrap, so none of this reaches it.
   Higher-specificity rules elsewhere (e.g. main.css's .blog category chips)
   still win, which is intended. */.btn{--bs-btn-font-family:var(--font-sans);--bs-btn-font-weight:600;--bs-btn-font-size:0.9375rem;--bs-btn-border-radius:var(--radius);--bs-btn-padding-x:var(--space-5);--bs-btn-padding-y:10px;--bs-btn-focus-shadow-rgb:0,59,147;letter-spacing:-0.006em;transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease),color var(--dur) var(--ease)}.btn-primary{--bs-btn-color:#fff;--bs-btn-bg:var(--brand);--bs-btn-border-color:var(--brand);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--brand-deep);--bs-btn-hover-border-color:var(--brand-deep);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--brand-deep);--bs-btn-active-border-color:var(--brand-deep);--bs-btn-disabled-color:#fff;--bs-btn-disabled-bg:var(--brand);--bs-btn-disabled-border-color:var(--brand)}.btn-outline-primary{--bs-btn-color:var(--brand);--bs-btn-border-color:var(--brand);--bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--brand);--bs-btn-hover-border-color:var(--brand);--bs-btn-active-color:#fff;--bs-btn-active-bg:var(--brand-deep);--bs-btn-active-border-color:var(--brand-deep);--bs-btn-disabled-color:var(--brand);--bs-btn-disabled-border-color:var(--brand)}/* The system owns no grey, so the secondary pair is drawn from the ink ramp
   and the sunken ground rather than Bootstrap's #6c757d. */.btn-secondary{--bs-btn-color:var(--ink);--bs-btn-bg:var(--ground-sunken);--bs-btn-border-color:var(--hairline-strong);--bs-btn-hover-color:var(--ink);--bs-btn-hover-bg:#e9edf3;--bs-btn-hover-border-color:var(--ink-3);--bs-btn-active-color:var(--ink);--bs-btn-active-bg:#e9edf3;--bs-btn-active-border-color:var(--ink-3);--bs-btn-disabled-color:var(--ink-3);--bs-btn-disabled-bg:var(--ground-sunken);--bs-btn-disabled-border-color:var(--hairline-strong)}.btn-outline-secondary{--bs-btn-color:var(--ink-2);--bs-btn-border-color:var(--hairline-strong);--bs-btn-hover-color:var(--ink);--bs-btn-hover-bg:var(--ground-sunken);--bs-btn-hover-border-color:var(--ink-3);--bs-btn-active-color:var(--ink);--bs-btn-active-bg:var(--ground-sunken);--bs-btn-active-border-color:var(--ink-3);--bs-btn-disabled-color:var(--ink-3);--bs-btn-disabled-border-color:var(--hairline)}/* --------------------------------------------------------------------------
   5. Wordmark — the orbit device, preserved
   -------------------------------------------------------------------------- */.brand-ai{display:inline-block;position:relative;color:var(--brand);font-weight:inherit}/* Navy reads on the white header; on the near-black footer it would vanish,
   so the device switches to the light tint instead of disappearing. */.site-footer .brand-ai{color:var(--ink-on-brand-2)}.brand-orbit-pivot{position:relative;display:inline-block}@property --orbit-sweep{syntax:"<angle>";inherits:false;initial-value:0deg}.brand-orbit-ring{position:absolute;left:50%;top:50%;width:0.84em;height:1.64em;transform:translate(-50%, -50%) rotate(20deg);border-radius:50%;opacity:0;pointer-events:none;--orbit-sweep:0deg;--orbit-color:var(--brand);background:conic-gradient(from 270deg, var(--orbit-color) var(--orbit-sweep), transparent var(--orbit-sweep)),conic-gradient(from 90deg, var(--orbit-color) var(--orbit-sweep), transparent var(--orbit-sweep));-webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));mask:radial-gradient(farthest-side, transparent calc(100% - 2px), #000 calc(100% - 2px))}.site-footer .brand-orbit-ring{--orbit-color:var(--ink-on-brand-2)}@keyframes brand-orbit-ring-play{0%{opacity:0;--orbit-sweep:0deg}8%{opacity:1}85%{opacity:1}100%{opacity:0;--orbit-sweep:360deg}}@keyframes brand-orbit-a{0%{transform:translate(0em, 0em)}8.33%{transform:translate(0.108em, -0.131em)}16.67%{transform:translate(0.292em, -0.189em)}25%{transform:translate(0.504em, -0.157em)}33.33%{transform:translate(0.687em, -0.045em)}41.67%{transform:translate(0.791em, 0.118em)}50%{transform:translate(0.789em, 0.287em)}58.33%{transform:translate(0.682em, 0.418em)}66.67%{transform:translate(0.497em, 0.476em)}75%{transform:translate(0.285em, 0.444em)}83.33%{transform:translate(0.103em, 0.332em)}91.67%{transform:translate(-0.002em, 0.17em)}100%{transform:translate(0em, 0em)}}@keyframes brand-orbit-i{0%{transform:translate(0em, 0em)}8.33%{transform:translate(-0.108em, 0.131em)}16.67%{transform:translate(-0.292em, 0.189em)}25%{transform:translate(-0.504em, 0.157em)}33.33%{transform:translate(-0.687em, -0.045em)}41.67%{transform:translate(-0.791em, -0.118em)}50%{transform:translate(-0.789em, -0.287em)}58.33%{transform:translate(-0.682em, -0.418em)}66.67%{transform:translate(-0.497em, -0.476em)}75%{transform:translate(-0.285em, -0.444em)}83.33%{transform:translate(-0.103em, -0.332em)}91.67%{transform:translate(0.002em, -0.17em)}100%{transform:translate(0em, 0em)}}.brand-orbit-zone:hover .brand-ai-a,.brand-orbit-zone.orbiting .brand-ai-a{animation:brand-orbit-a 1.6s ease-in-out}.brand-orbit-zone:hover .brand-ai-i,.brand-orbit-zone.orbiting .brand-ai-i{animation:brand-orbit-i 1.6s ease-in-out}.brand-orbit-zone:hover .brand-orbit-ring,.brand-orbit-zone.orbiting .brand-orbit-ring{animation:brand-orbit-ring-play 1.6s ease-in-out}/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */.site-header{position:sticky;top:0;z-index:1030;background:rgba(255, 255, 255, 0.86);-webkit-backdrop-filter:saturate(180%) blur(12px);backdrop-filter:saturate(180%) blur(12px);border-bottom:1px solid transparent;transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}.scrolled .site-header{border-bottom-color:var(--hairline)}.site-header .shell{display:flex;align-items:center;gap:var(--space-6);min-height:var(--shell-h)}.brandmark{display:inline-flex;align-items:center;gap:var(--space-3);margin-right:auto;color:var(--ink);text-decoration:none;flex-shrink:0}.brandmark:hover{color:var(--ink);text-decoration:none}.brandmark img{width:28px;height:28px;object-fit:contain}.brandmark .sitename{margin:0;font-size:1.1875rem;font-weight:700;letter-spacing:-0.028em;line-height:1;color:var(--ink)}/* Nav *//* #navmenu carries Bootstrap's .collapse class so the mobile toggle can
   drive it (see header.njk); .collapse:not(.show) is display:none by
   default in bootstrap.min.css, so force it back on above the lg
   breakpoint - the desktop layout is never actually "collapsed". */.nav-primary{display:flex !important;align-items:center;gap:var(--space-5)}.nav-primary > ul{display:flex;align-items:center;gap:var(--space-1);list-style:none;margin:0;padding:0}.nav-primary ul a{display:inline-flex;align-items:center;gap:var(--space-1);padding:var(--space-2) var(--space-3);border-radius:var(--radius-sm);font-size:0.9375rem;font-weight:500;letter-spacing:-0.004em;color:var(--ink-2);white-space:nowrap}.nav-primary ul a:hover{color:var(--ink);background:var(--ground-sunken);text-decoration:none}.nav-primary ul .active > a{color:var(--brand)}.nav-primary .has-sub{position:relative}.nav-primary .has-sub > a i{font-size:0.75rem;transition:transform var(--dur) var(--ease)}.nav-primary .sub{position:absolute;top:calc(100% + 6px);left:0;min-width:232px;margin:0;padding:var(--space-2);list-style:none;background:var(--ground);border:1px solid var(--hairline);border-radius:var(--radius);box-shadow:var(--shadow-lg);opacity:0;visibility:hidden;transform:translateY(-4px);transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility var(--dur) var(--ease)}.nav-primary .sub.show,.nav-primary .has-sub:hover > .sub,.nav-primary .has-sub:focus-within > .sub{opacity:1;visibility:visible;transform:translateY(0)}.nav-primary .has-sub:hover > a i,.nav-primary .has-sub:focus-within > a i{transform:rotate(180deg)}.nav-primary .sub a{display:block;padding:var(--space-2) var(--space-3);font-size:0.9375rem;color:var(--ink-2)}/* Dropdown triggers are buttons, and must match their sibling links exactly. */.nav-primary .sub-toggle{display:inline-flex;align-items:center;gap:var(--space-1);padding:var(--space-2) var(--space-3);background:transparent;border:0;border-radius:var(--radius-sm);font-family:var(--font-sans);font-size:0.9375rem;font-weight:500;letter-spacing:-0.004em;color:var(--ink-2);white-space:nowrap;cursor:pointer}.nav-primary .sub-toggle:hover{color:var(--ink);background:var(--ground-sunken)}.nav-primary .sub-toggle i{font-size:0.75rem;transition:transform var(--dur) var(--ease)}.nav-primary .has-sub:hover > .sub-toggle i,.nav-primary .has-sub:focus-within > .sub-toggle i,.nav-primary .sub-toggle.show i{transform:rotate(180deg)}.header-cta{flex-shrink:0;min-height:40px;padding:0 var(--space-5);font-size:0.9375rem}.nav-toggle{display:none;align-items:center;justify-content:center;width:44px;height:44px;margin-left:var(--space-2);padding:0;background:transparent;border:1px solid var(--hairline);border-radius:var(--radius-sm);color:var(--ink);font-size:1.375rem;cursor:pointer}@media (max-width: 991.98px){.site-header .shell{gap:var(--space-3)}.nav-toggle{display:inline-flex}.header-cta{display:none}.nav-primary{flex-direction:column;align-items:stretch;gap:0;position:fixed;top:var(--shell-h);left:0;right:0;/* Not bottom:0 - .site-header's backdrop-filter makes it the containing
       block for this fixed element, so bottom:0 would resolve against the
       ~68px header box instead of the viewport. 100vh is always
       viewport-relative regardless of containing block. */height:calc(100vh - var(--shell-h));background:var(--ground);padding:var(--space-5) var(--space-4) var(--space-8);overflow-y:auto;opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility var(--dur) var(--ease)}/* Bootstrap's Collapse plugin drives #navmenu's show/hide state; this panel
     fades/slides in on top of Collapse's own height transition. */.nav-primary.show,.nav-primary.collapsing{opacity:1;visibility:visible;transform:translateY(0)}.nav-open{overflow:hidden}.nav-primary > ul{flex-direction:column;align-items:stretch;gap:0}.nav-primary > ul > li{border-bottom:1px solid var(--hairline)}.nav-primary ul a{padding:var(--space-4) var(--space-2);font-size:1.0625rem;min-height:52px;border-radius:0}.nav-primary .sub{position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:0;border-radius:0;padding:0 0 var(--space-3) var(--space-4);min-width:0;display:none}.nav-primary .sub.show{display:block}.nav-primary .sub-toggle.show i{transform:rotate(180deg)}.nav-primary .nav-mobile-cta{display:flex;width:100%;margin-top:var(--space-6)}}.nav-primary .nav-mobile-cta{display:none}/* --------------------------------------------------------------------------
   7. Hero — typography only
   -------------------------------------------------------------------------- */.hero{/* Backdrop tuning. Tints are brand-derived (color-mix), never new colours. */--hero-tint-strong:26%;/* peak brand alpha of the main glow */--hero-tint-soft:15%;/* peak alpha of the secondary glows */--hero-drift:18s;/* one full drift cycle, alternating */--hero-fade-start:55%;/* where the mesh starts dissolving into --ground */--hero-grid-cell:var(--space-8);/* ledger grid pitch, on the spacing scale */--hero-grid-tint:9%;/* resting brand alpha of the grid hairlines */--hero-scan-tint:32%;/* peak alpha where the scan band crosses a line */--hero-scan-cycle:14s;/* one sweep plus its off-screen rest */position:relative;isolation:isolate;overflow:hidden;padding-block:clamp(var(--space-7), 5.5vw, 88px) var(--space-9);background:var(--ground);border-bottom:1px solid var(--hairline)}/* Backdrop: three soft brand-navy glows, oversized so drifting never exposes
   an edge. Purely decorative and behind the copy (z-index -1 in the hero's own
   stacking context). Design exception, see design.md "Hero backdrop". */.hero::before{content:"";position:absolute;inset:-20%;z-index:-1;pointer-events:none;background:radial-gradient(38% 42% at 78% 22%, color-mix(in srgb, var(--brand-bright) var(--hero-tint-strong), transparent), transparent),radial-gradient(34% 40% at 92% 70%, color-mix(in srgb, var(--brand) var(--hero-tint-soft), transparent), transparent),radial-gradient(40% 44% at 58% 4%, color-mix(in srgb, var(--brand-bright) var(--hero-tint-soft), transparent), transparent);-webkit-mask-image:linear-gradient(to bottom, #000 var(--hero-fade-start), transparent);mask-image:linear-gradient(to bottom, #000 var(--hero-fade-start), transparent)}/* Ledger grid: brand hairlines on a square pitch, drawn above the glows and
   behind the copy. The element is a flat tint; the line pattern lives in the
   mask, intersected with a fade anchored top-right so the grid dissolves
   before it reaches the headline and the record band. Because the mask sits
   on the parent, the ::before scan band only ever lights the lines themselves.
   Design exception, see design.md "Hero backdrop". */.hero-grid{position:absolute;inset:0;z-index:-1;overflow:hidden;pointer-events:none;background:color-mix(in srgb, var(--brand) var(--hero-grid-tint), transparent);-webkit-mask-image:radial-gradient(ellipse 70% 95% at 88% 8%, #000 15%, transparent 72%),repeating-linear-gradient(to right, #000 0 1px, transparent 1px var(--hero-grid-cell)),repeating-linear-gradient(to bottom, #000 0 1px, transparent 1px var(--hero-grid-cell));-webkit-mask-composite:source-in,source-over,source-over;mask-image:radial-gradient(ellipse 70% 95% at 88% 8%, #000 15%, transparent 72%),repeating-linear-gradient(to right, #000 0 1px, transparent 1px var(--hero-grid-cell)),repeating-linear-gradient(to bottom, #000 0 1px, transparent 1px var(--hero-grid-cell));mask-composite:intersect,add,add}/* Scan band: a soft column of brighter brand light that crosses the grid.
   Full-width with the band in its middle third, so translating by its own
   width carries the band from off-left to off-right. */.hero-grid::before{content:"";position:absolute;inset:0;background:linear-gradient(
    to right,
    transparent 33%,
    color-mix(in srgb, var(--brand-bright) var(--hero-scan-tint), transparent) 50%,
    transparent 67%
  );transform:translate3d(-100%, 0, 0)}.hero-copy{max-width:100%}.hero h1{font-size:clamp(2.5rem, 6.4vw, 4.25rem);font-weight:700;letter-spacing:-0.036em;line-height:1.04;color:var(--ink);max-width:13em}.hero-lede{margin-top:var(--space-5);max-width:54ch;font-size:clamp(1.0625rem, 1.6vw, 1.25rem);line-height:1.55;color:var(--ink-3);text-wrap:pretty}.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-4);margin-top:var(--space-6)}/* Record band — counted evidence, above the fold. */.record{row-gap:var(--space-6);margin-top:var(--space-8);padding-top:var(--space-6);border-top:1px solid var(--hairline)}.record-item{min-width:0}.record-value{display:block;font-size:clamp(2rem, 3.6vw, 2.75rem);font-weight:700;letter-spacing:-0.034em;line-height:1;color:var(--ink);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.record-value .unit{font-size:0.5em;font-weight:600;letter-spacing:-0.01em;color:var(--ink-3);margin-left:2px}.record-label{display:block;/* <dd> ships a 40px inline-start margin; the label must align to its number. */margin:var(--space-3) 0 0;font-size:0.9375rem;line-height:1.4;color:var(--ink-3);text-wrap:pretty}@media (max-width: 767.98px){.record{margin-top:var(--space-8)}}/* The one authored moment: the hero settles in on first paint. */@media (prefers-reduced-motion: no-preference){.hero h1,.hero-lede,.hero-actions,.record-item{animation:settle 520ms var(--ease) both}.hero h1{animation-delay:0ms}.hero-lede{animation-delay:60ms}.hero-actions{animation-delay:120ms}.record-item:nth-child(1){animation-delay:170ms}.record-item:nth-child(2){animation-delay:200ms}.record-item:nth-child(3){animation-delay:230ms}.record-item:nth-child(4){animation-delay:260ms}}/* Backdrop drift: transform only (compositor-cheap), slow and alternating so
   it reads as ambient light rather than motion. Static for reduced-motion. */@media (prefers-reduced-motion: no-preference){.hero::before{animation:hero-drift var(--hero-drift) ease-in-out infinite alternate;will-change:transform}}/* Grid scan: sweeps for ~65% of the cycle, then rests off-screen so it reads
   as an occasional pass rather than a constant loop. Reduced-motion visitors
   get the static grid with no band. */@media (prefers-reduced-motion: no-preference){.hero-grid::before{animation:hero-scan var(--hero-scan-cycle) ease-in-out infinite;will-change:transform}}@keyframes hero-scan{0%{transform:translate3d(-100%, 0, 0)}65%{transform:translate3d(100%, 0, 0)}100%{transform:translate3d(100%, 0, 0)}}@keyframes hero-drift{from{transform:translate3d(-6%, 4%, 0) scale(1)}to{transform:translate3d(7%, -6%, 0) scale(1.15)}}/* Starts mostly-visible and settles, rather than fading up from nothing: the
   whole run is resolved inside ~0.8s and no text is ever unreadable. */@keyframes settle{from{opacity:0.35;transform:translateY(10px)}to{opacity:1;transform:none}}/* --------------------------------------------------------------------------
   8. Practice list (what we do) — a typographic list, not icon cards
   -------------------------------------------------------------------------- */.practice{border-top:1px solid var(--hairline)}.practice-row{align-items:baseline;padding-block:var(--space-6);/* Bleeds past the text column so the hover wash reads as a row, not a box. */padding-inline:var(--space-4);margin-inline:calc(var(--space-4) * -1);border-bottom:1px solid var(--hairline);row-gap:var(--space-2);transition:background-color var(--dur) var(--ease)}.practice-row:hover{background:var(--brand-wash)}.practice-row h3{font-size:1.3125rem;font-weight:600;letter-spacing:-0.024em}.practice-row p{color:var(--ink-3);max-width:var(--measure)}@media (max-width: 767.98px){.practice-row{padding-block:var(--space-5)}}/* --------------------------------------------------------------------------
   9. Work cards
   -------------------------------------------------------------------------- */.work-grid{row-gap:var(--space-5)}.work-card{position:relative;display:flex;flex-direction:column;gap:var(--space-3);padding:var(--space-6);background:var(--ground);border:1px solid var(--hairline);border-radius:var(--radius-lg);transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease),transform var(--dur) var(--ease)}.work-card:hover{border-color:transparent;box-shadow:var(--shadow-lg);transform:translateY(-2px)}.work-card h3{font-size:1.125rem;font-weight:600;letter-spacing:-0.02em;line-height:1.3}.work-card h3 a{color:var(--ink)}.work-card:hover h3 a{color:var(--brand);text-decoration:none}.work-card p{color:var(--ink-3);font-size:0.9375rem;line-height:1.6}.work-card .arw{margin-top:auto;padding-top:var(--space-3);color:var(--brand);font-size:1rem;transition:transform var(--dur) var(--ease)}.work-card:hover .arw{transform:translateX(4px)}.work-card a.stretched-link::after{content:"";position:absolute;inset:0;border-radius:inherit}/* --------------------------------------------------------------------------
   10. Pull quote + about
   -------------------------------------------------------------------------- */.pullquote{margin:0 0 var(--space-8);font-family:var(--font-serif);font-size:clamp(1.5rem, 3.4vw, 2.125rem);line-height:1.28;letter-spacing:-0.018em;font-weight:400;color:var(--ink);max-width:24ch;text-wrap:balance}.about-cols{row-gap:var(--space-7)}.checklist{list-style:none;margin:var(--space-5) 0 0;padding:0;display:grid;gap:var(--space-4)}.checklist li{display:grid;grid-template-columns:20px 1fr;gap:var(--space-3);align-items:start;color:var(--ink-2);font-size:1rem}.checklist i{color:var(--brand);font-size:1.125rem;line-height:1.45}.checklist b{color:var(--ink);font-weight:600}/* --------------------------------------------------------------------------
   11. Clients
   -------------------------------------------------------------------------- *//* Mixed wordmarks and square marks sit on one optical baseline: every cell is
   the same height and each mark is centred inside it. */.client-rail{row-gap:var(--space-6);align-items:center}.client-rail img{display:block;/* Padding (not a taller box) keeps every mark on the same 76px band while
     the image itself stays capped at 44px, mirroring the old fixed-height
     grid track without distorting replaced-element sizing. */padding-block:16px;width:auto;max-width:100%;max-height:44px;margin-inline:auto;filter:grayscale(1) contrast(1.15);opacity:0.9;transition:filter var(--dur) var(--ease),opacity var(--dur) var(--ease)}/* A wordmark carries its mass in width, a badge in height. Capping both at
   the same height shrinks every badge to an illegible speck, so the badges get
   their own cap and the two shapes land at comparable visual weight. */.client-rail .mark-badge{padding-block:6px;max-height:64px}.client-rail img:hover{filter:none;opacity:1}/* Coarse pointers get no hover, so the marks ship in full colour there. */@media (hover: none){.client-rail img{filter:none;opacity:1}}.rail-label{margin-bottom:var(--space-6);font-size:0.9375rem;color:var(--ink-3)}/* --------------------------------------------------------------------------
   12. Testimonials (dark band)
   -------------------------------------------------------------------------- */.quote-card{display:flex;flex-direction:column;height:auto;padding:var(--space-6);background:rgba(255, 255, 255, 0.04);border:1px solid var(--hairline-on-dark);border-radius:var(--radius-lg)}.quote-card blockquote{margin:0;font-family:var(--font-serif);font-size:1.0625rem;line-height:1.6;color:#fff}.quote-card blockquote::before{content:"\201C";display:block;font-size:2.75rem;line-height:0.6;margin-bottom:var(--space-3);color:var(--ink-on-brand-2)}.quote-attr{margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--hairline-on-dark)}.quote-attr .who{display:block;font-size:0.9375rem;font-weight:600;color:#fff}.quote-attr .where{display:block;margin-top:2px;font-size:0.875rem;color:var(--ink-on-brand-2)}.testimonials .carousel-indicators{position:static;width:auto;margin:0}/* The active dot stretches into a pill. The whole track reserves the wide
   size and the stretch is drawn with transform, so nothing animates layout. */.testimonials .carousel-indicators [data-bs-target]{width:22px;height:7px;padding:0;border:0;border-radius:99px;background:rgba(255, 255, 255, 0.34);opacity:1;transform:scaleX(0.32);transform-origin:center;transition:background-color var(--dur) var(--ease),transform var(--dur) var(--ease)}.testimonials .carousel-indicators [data-bs-target].active{background:#fff;transform:scaleX(1)}/* Autoplay must be stoppable: WCAG 2.2.2 is Level A. */.carousel-controls{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-4);margin-top:var(--space-6)}.carousel-pause{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);min-height:44px;padding:0 var(--space-4);background:transparent;border:1px solid var(--hairline-on-dark);border-radius:var(--radius-sm);color:#fff;font-family:var(--font-sans);font-size:0.875rem;font-weight:600;cursor:pointer;transition:background-color var(--dur) var(--ease),border-color var(--dur) var(--ease)}.carousel-pause:hover{background:rgba(255, 255, 255, 0.1);border-color:rgba(255, 255, 255, 0.36)}/* --------------------------------------------------------------------------
   13. Team
   -------------------------------------------------------------------------- */.team-layout{row-gap:var(--space-7);align-items:start}@media (max-width: 767.98px){.person img{display:block;margin-inline:auto}}.person figure{margin:0}.person img{width:100%;max-width:220px;aspect-ratio:1;object-fit:cover;border-radius:var(--radius-lg);background:var(--ground-sunken)}.person figcaption{margin-top:var(--space-4)}.person .name{display:block;font-size:1.0625rem;font-weight:600;color:var(--ink)}.person .role{display:block;margin-top:2px;font-size:0.9375rem;color:var(--ink-3)}.person-links{display:flex;gap:var(--space-2);margin-top:var(--space-4)}.person-links a{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid var(--hairline);border-radius:var(--radius-sm);color:var(--ink-2);font-size:1rem}.person-links a:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-wash)}.bio-details{margin-top:var(--space-4)}.bio-details[open] > p{margin-top:var(--space-4)}.bio-details summary{display:inline-flex;align-items:center;gap:var(--space-2);min-height:44px;font-family:var(--font-sans);font-size:1rem;font-weight:600;color:var(--brand);cursor:pointer;list-style:none}.bio-details summary::-webkit-details-marker,.bio-details summary::marker{display:none;content:""}.bio-details summary i{font-size:0.8rem;transition:transform var(--dur) var(--ease)}.bio-details[open] summary i{transform:rotate(180deg)}/* --------------------------------------------------------------------------
   14. Writing (blog teaser)
   -------------------------------------------------------------------------- */.writing-grid{row-gap:var(--space-6)}.writing-card{display:flex;flex-direction:column;gap:var(--space-3);padding-top:var(--space-5);border-top:2px solid var(--ink)}.writing-meta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);font-size:0.8125rem;color:var(--ink-3)}.writing-meta .topic{font-weight:600;color:var(--brand)}.writing-meta .dot{color:var(--hairline-strong)}.writing-card h3{font-size:1.1875rem;font-weight:600;letter-spacing:-0.022em;line-height:1.3}.writing-card h3 a{color:var(--ink)}.writing-card h3 a:hover{color:var(--brand);text-decoration:none}.writing-card p{color:var(--ink-3);font-size:0.9375rem;line-height:1.6}/* --------------------------------------------------------------------------
   15. Contact
   -------------------------------------------------------------------------- */.contact-layout{row-gap:var(--space-7);align-items:start}.contact-lines{display:grid;gap:var(--space-5);margin:0}.contact-lines dt{font-size:0.8125rem;font-weight:600;letter-spacing:0.02em;text-transform:uppercase;color:var(--ink-3)}.contact-lines dd{margin:var(--space-2) 0 0;font-size:1rem;color:var(--ink);line-height:1.55}.contact-map{width:100%;height:240px;margin-top:var(--space-6);border:0;border-radius:var(--radius-lg);filter:grayscale(1) contrast(1.05)}.field-grid{row-gap:var(--space-4)}.field label{display:block;margin-bottom:var(--space-2);font-size:0.875rem;font-weight:600;color:var(--ink-2)}.field label .optional{font-weight:400;color:var(--ink-3)}.form-field{width:100%;min-height:48px;padding:var(--space-3) var(--space-4);background:var(--ground);border:1px solid var(--hairline-strong);border-radius:var(--radius);font-family:var(--font-sans);font-size:1rem;color:var(--ink);transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}textarea.form-field{min-height:132px;resize:vertical;line-height:1.6}.form-field::placeholder{color:var(--ink-3);opacity:1}.form-field:hover{border-color:var(--ink-3)}.form-field:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-wash)}.form-field:disabled{background:var(--ground-sunken);color:var(--ink-3);cursor:not-allowed}.form-note{margin-top:var(--space-3);font-size:0.875rem;line-height:1.5;color:var(--ink-3)}.form-note a{color:var(--ink-2);text-decoration:underline}.php-email-form .loading,.php-email-form .error-message,.php-email-form .sent-message{display:none;padding:var(--space-4);border-radius:var(--radius);font-size:0.9375rem;line-height:1.5}.php-email-form .loading{background:var(--ground-sunken);color:var(--ink-2)}.php-email-form .error-message{background:rgba(178, 15, 3, 0.07);border:1px solid rgba(178, 15, 3, 0.24);color:var(--negative)}.php-email-form .sent-message{background:rgba(10, 122, 61, 0.07);border:1px solid rgba(10, 122, 61, 0.24);color:var(--positive)}.php-email-form .loading.d-block,.php-email-form .error-message.d-block,.php-email-form .sent-message.d-block{display:block}.recaptcha-disclosure{margin-top:var(--space-4);font-size:0.8125rem;line-height:1.5;color:var(--ink-3)}.recaptcha-disclosure a{color:var(--ink-2);text-decoration:underline}/* Data tables in articles must not lose columns on a phone. Making the table
   its own scroll container keeps every cell reachable instead of clipping the
   right-hand ones against the viewport. */@media (max-width: 767.98px){.metric-table,.blog-post-full table{display:block;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}.metric-table thead,.blog-post-full table thead{white-space:nowrap}}/* --------------------------------------------------------------------------
   16. Footer
   -------------------------------------------------------------------------- */.site-footer{/* Extra bottom room so the fixed back-to-top control never lands on the
     copyright line. */padding-block:var(--space-9) calc(var(--space-6) + 44px);background:var(--ground-deep);color:var(--ink-on-brand-2);font-size:0.9375rem}.footer-grid{row-gap:var(--space-8)}.site-footer .brandmark{color:#fff;margin-right:0}.site-footer .brandmark .sitename{color:#fff;font-size:1.125rem}.footer-about p{margin-top:var(--space-4);max-width:42ch;line-height:1.6}.social-links{display:flex;gap:var(--space-2);margin-top:var(--space-5)}.social-links a{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:1px solid var(--hairline-on-dark);border-radius:var(--radius-sm);color:#fff;font-size:1rem}.social-links a:hover{background:rgba(255, 255, 255, 0.1);border-color:rgba(255, 255, 255, 0.36);color:#fff}.footer-col h2{margin-bottom:var(--space-4);font-size:0.8125rem;font-weight:600;letter-spacing:0.04em;text-transform:uppercase;color:#fff}.footer-col ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-2)}.footer-col a,.footer-col address{color:var(--ink-on-brand-2);font-style:normal;line-height:1.6}.footer-col a:hover{color:#fff;text-decoration:underline}.footer-base{margin-top:var(--space-8);padding-top:var(--space-5);border-top:1px solid var(--hairline-on-dark);display:flex;flex-wrap:wrap;gap:var(--space-3) var(--space-5);align-items:center;justify-content:space-between;font-size:0.875rem}.footer-base p{margin:0}.footer-legal{display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-5);list-style:none;margin:0;padding:0}@media (max-width: 575.98px){.footer-legal{gap:var(--space-2) var(--space-4)}}/* Long unbroken strings (the email address) must not push the column open. */.footer-col a,.footer-contact-list a{overflow-wrap:anywhere}.footer-contact-list{margin-top:var(--space-4)}/* --------------------------------------------------------------------------
   17. Scroll-to-top
   -------------------------------------------------------------------------- */.scroll-top{position:fixed;right:var(--space-5);bottom:var(--space-5);z-index:1020;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;background:var(--ground);color:var(--ink);border:0;border-radius:50%;box-shadow:var(--shadow-md);opacity:0;visibility:hidden;transform:translateY(8px);transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease),visibility var(--dur) var(--ease),border-color var(--dur) var(--ease)}.scroll-top.active{opacity:1;visibility:visible;transform:none}.scroll-top:hover{color:var(--brand);box-shadow:var(--shadow-lg)}/* --------------------------------------------------------------------------
   18. Reduced motion
   -------------------------------------------------------------------------- */@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}*,*::before,*::after{animation-duration:0.01ms !important;animation-iteration-count:1 !important;transition-duration:0.01ms !important}}