/* Prevents a browser dark-mode UA canvas (often pure black) from showing through
   any sub-pixel gap at a sticky header's edge — the site has one light theme, not
   a light/dark pair, so the browser should never substitute its own default. */
html{background:var(--surface-page);color-scheme:light}

/* RESPONSIVE LADDER. Five named tiers carry the layout; anything outside them is a
   one-off that should be justified in a comment where it appears.
     1320px  the frame stops being full-width — rails narrow, gutters tighten
     1100px  two-column grids become one on the content-heavy bands
      900px  the tablet break — nav collapses, side-by-side becomes stacked
      700px  single column throughout, type steps down
      520px  small-phone corrections only
   The remaining widths in this file (1500, 1472, 1240, 1180, 1120, 1060, 1024, 1000, 880,
   760, 600, 400) predate the ladder. They are functional and are NOT mechanically merged
   here: collapsing 1472 into 1320, or 1024 into 1100, moves where specific components
   break and needs visual QA at each width rather than a find-and-replace. Migrate them
   one component at a time, verifying that component at the old and new width. */

/* Responsive + interaction layer for the pyxl.com kit.
   The pages are authored at 1472px with inline styles. Rather than fork every
   layout, this sheet reflows the shell at real breakpoints and standardises the
   interaction states that inline styles cannot express (hover, press, focus). */

/* ── Reflow ──────────────────────────────────────────────── */
@media (max-width:1500px) {
  #root { width: 100% !important; }
}
/* Wide-desktop canvas, past the 1500px reflow breakpoint above: #root was pinned to a
   flat 1472px with overflow-x:clip, so every section's background stopped dead at that
   edge on any screen wider than it, leaving bare page-background margins on both sides.
   Letting #root itself go fluid here (matching how it already behaves below 1500px)
   makes every section's background reach the real viewport edge, while Col2/.wk-inner's
   shared 1304px max-width keeps the actual content column exactly as wide as it was
   authored — nothing about layout, spacing or type changes at this width or above. */
#root { width: 100% !important; }
/* The pages pin #root to their design width inline. Below that width the frame
   itself must become fluid, otherwise every child measures outside the viewport
   no matter what the inner rules say. */
@media (max-width:1472px) { #root { width: 100% !important; } }
/* Nothing may create a horizontal scrollbar at any width. */
#root, #root header, #root footer, #root section { max-width: 100%; box-sizing: border-box; }
#root header nav[aria-label="Primary"] { min-width: 0; }
/* Below the design width the 1240px measure becomes a fluid column with gutters. */
@media (max-width:1320px) {
  #root section > div, #root header > div, #root footer > div {
    width: auto !important;
    max-width: 1240px;
    margin-left: auto !important;
    margin-right: auto !important;
    padding-left: 32px !important;
    padding-right: 32px !important;
    box-sizing: border-box;
  }
}
/* Tablet: three- and six-up grids halve. */
@media (max-width:1024px) {
  #root [style*="repeat(6, 1fr)"], #root [style*="repeat(6,1fr)"] { grid-template-columns: repeat(3, 1fr) !important; }
  #root [style*="repeat(5, 1fr)"], #root [style*="repeat(5,1fr)"] { grid-template-columns: repeat(2, 1fr) !important; }
  #root [style*="repeat(3, 1fr)"], #root [style*="repeat(3,1fr)"] { grid-template-columns: repeat(2, 1fr) !important; }
  #root h1 { font-size: 46px !important; line-height: 50px !important; }
  #root h2 { font-size: 38px !important; line-height: 44px !important; }
  /* Header: the four-up pricing row and the tabbed rails halve here too. */
  #root [style*="repeat(4, 1fr)"], #root [style*="repeat(4,1fr)"] { grid-template-columns: repeat(2, 1fr) !important; }
  /* Fixed-px grid tracks cannot shrink. The footer declares two 340px columns,
     which overflow any viewport under ~840px — stack them from tablet down. */
  #root footer > div[style*="grid-template-columns"] { grid-template-columns: 1fr !important; row-gap: 40px; }
  #root footer nav[style*="grid-template-columns"] { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
  /* The review-only page jump has no room once the nav is tight. */
  #root header select { display: none !important; }
  #root header > div { flex-wrap: nowrap !important; }
  #root header nav[aria-label="Primary"] { min-width: 0; gap: 0; }
  #root header nav[aria-label="Primary"] > a { padding-left: 7px !important; padding-right: 7px !important; font-size: 13px !important; }
  /* Footer column rows must wrap rather than push past the gutter. */
  #root footer [style*="display: flex"] { flex-wrap: wrap !important; }
  #root footer > div, #root footer { box-sizing: border-box; }
}
/* ── Header: one bar on a phone, one drawer behind it ─────── */
/* Nine labels plus two buttons cannot be made to fit a phone bar, and a wrapped
   three-row nav is not navigation. Below 900 the bar carries the logo and one
   control; everything else moves into the drawer, which is the only nav surface
   a touch device gets. The desktop mega-panels stay hover-driven above it, with
   a first-tap-opens fallback in the component for touch laptops and tablets. */
@media (max-width:900px) {
  #root header nav[aria-label="Primary"],
  #root header .pyxl-hdr-cta,
  #root header select { display: none !important; }
  #root header .pyxl-burger { display: grid !important; }
  #root header > div { flex-wrap: nowrap !important; padding-top: 13px !important; padding-bottom: 13px !important; }.cmp-toa{grid-template-columns:1fr 40px!important;gap:40px!important}.cmp-toa>p,.cmp-toa>span:last-child{grid-column:1 / -1}}

/* Phone: everything stacks, type steps down, sections lose their tall padding. */
@media (max-width:760px) {
  #root [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
  #root section > div, #root header > div, #root footer > div { padding-left: 20px !important; padding-right: 20px !important; }
  #root section { padding-top: 64px !important; padding-bottom: 60px !important; }
  #root h1 { font-size: 36px !important; line-height: 40px !important; letter-spacing: -0.7px !important; }
  #root h2 { font-size: 30px !important; line-height: 35px !important; letter-spacing: -0.5px !important; }
  #root h3 { font-size: 23px !important; line-height: 28px !important; }
  #root nav[aria-label="Primary"] { display: none !important; }
  #root header select { display: none !important; }
  /* Nothing in the header may exceed the viewport. */
  #root header a[href="/contact"] { max-width: 100%; }
  #root header > div { padding-top: 14px !important; padding-bottom: 14px !important; }
  /* Any element pinned to a design width becomes fluid. */
  #root [style*="maxWidth"], #root [style*="max-width"] { max-width: 100% !important; }
  #root [style*="minHeight: 620"], #root [style*="min-height: 620px"] { min-height: 0 !important; }
  /* Any grid of three or more collapses to two, then one. Written against the
     inline styles the pages actually use rather than a class per case. */
  #root [style*="repeat(4,1fr)"],
  #root [style*="repeat(4, 1fr)"],
  #root [style*="1fr 1fr 1fr 1fr"] { grid-template-columns: 1fr 1fr !important; }
  #root [style*="repeat(3,1fr)"],
  #root [style*="repeat(3, 1fr)"],
  #root [style*="1fr 1fr 1fr"] { grid-template-columns: 1fr 1fr !important; }
}
/* Mega-panel geometry below the design width. The panels are authored as
   `300px 1fr` and `290px 1fr 1fr`. A bare `1fr` track is `minmax(auto,1fr)`, so a
   long client name or a proof figure sets an automatic minimum and the track grows
   past the viewport instead of wrapping — the eCommerce panel measured 1082px of
   content inside a 1024px window. Clearing the automatic minimum on every grid
   item lets the tracks shrink, then the fixed rail narrows and the three-up
   interiors halve before they crowd. The panel can also never be taller than the
   space under the bar. */
.pyxl-navpanel [style*="grid-template-columns"] > *{min-width:0}
.pyxl-navpanel{max-height:calc(100vh - 76px);overflow-y:auto;overscroll-behavior:contain}
@media (max-width:1240px){
  .pyxl-navpanel > div{grid-template-columns:256px minmax(0,1fr)!important;padding:30px 30px 28px!important}
  .pyxl-navpanel .pyxl-nav-stagger[style*="290px 1fr 1fr"]{grid-template-columns:minmax(0,1fr) minmax(0,1fr)!important;gap:40px!important}
  .pyxl-navpanel .pyxl-nav-stagger[style*="repeat(5,minmax(0,1fr))"]{grid-template-columns:repeat(3,minmax(0,1fr))!important}
}
@media (max-width:1060px){
  .pyxl-navpanel > div{grid-template-columns:minmax(0,1fr)!important;row-gap:40px}
  .pyxl-navpanel > div > div:first-child{padding-right:0!important}
  /* Stacked, the divider between rail and content is a rule above, not a rule beside. */
  .pyxl-navpanel > div > div:last-child{padding-left:0!important;border-left:0!important;padding-top:20px;border-top:0.625px solid var(--line-hairline)}
  .pyxl-navpanel .pyxl-nav-stagger[style*="repeat(3,minmax(0,1fr))"]{grid-template-columns:repeat(2,minmax(0,1fr))!important}
}
/* The eCommerce panel's two four-across rows halve rather than crush. */
@media (max-width:1120px){.nav-com-build,.nav-com-wins{grid-template-columns:repeat(2,minmax(0,1fr))!important}.nav-com-wins{gap:40px!important}}
@keyframes pyxl-drawer-in{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
/* Between the design width and the drawer breakpoint the bar has to stay ONE row.
   The inline flexWrap:wrap on the header was dropping the two CTAs onto a second
   line from about 1200 down, which doubled the sticky header's height and pushed
   it over the page. Tighten the nav first, then drop the secondary CTA — it is
   still in the footer and in the drawer — rather than let anything wrap. */
@media (max-width:1320px) and (min-width:901px){
  #root header > div{flex-wrap:nowrap!important}
  #root header nav[aria-label="Primary"]{gap:0;min-width:0}
  #root header nav[aria-label="Primary"] > a{padding-left:8px!important;padding-right:8px!important;font-size:13px!important}
  #root header .pyxl-hdr-cta{gap:40px;flex-wrap:nowrap}
}
@media (max-width:1180px) and (min-width:901px){
  #root header nav[aria-label="Primary"] > a{padding-left:6px!important;padding-right:6px!important;font-size:12.5px!important}
  #root header .pyxl-hdr-cta a{padding-left:13px!important;padding-right:13px!important;font-size:12px!important}
  #root header .pyxl-hdr-cta{gap:40px;flex-wrap:nowrap}
}
/* Both CTAs stay until there is genuinely no room. Below 1000 the secondary drops —
   it is still in the footer and in the phone drawer. */
@media (max-width:1000px) and (min-width:901px){
  #root header .pyxl-hdr-cta a[href="/contact"]{display:none!important}
}
.pyxl-drawer a:active,.pyxl-drawer button:active{opacity:.7}
/* Comparative audit punch list. */

/* ── Interaction states ──────────────────────────────────── */
/* One motion curve across the kit: the brand's fluid ease. */
#root a, #root button { transition: opacity .222s cubic-bezier(0.22,1,0.36,1), background-color .22s cubic-bezier(0.22,1,0.36,1), color .22s cubic-bezier(0.22,1,0.36,1), border-color .22s cubic-bezier(0.22,1,0.36,1), transform .111s ease; }
/* ── The hover language ───────────────────────────────────────────────────────
   One blanket opacity fade used to carry every link on the site. Opacity fade is the
   default of a template, and hover is where a cursor tests whether the craft is real.
   Three treatments now, chosen by what the element IS rather than by what tag it uses.
     PROSE      an underline that draws in from the left, in the link's own colour
     CHROME     nav, footer and index links step to the ground's accent
     OBJECTS    cards, figures and actions keep the treatments they already had
   The residual fade is .9 rather than .72 — a fallback, not a design. */
#root a:hover { opacity: .9; }
#root button:not([role="tab"]):hover { opacity: .86; }

/* 1 · Prose. The underline is always there — removing it would leave colour as the only
   thing marking a link, which fails 1.4.1 and reads as a bug. At rest it is drawn at forty
   percent of the link's own colour; under the cursor it resolves to full strength. The
   affordance never moves, it only firms up. */
#root p a, #root li a, #root td a, #root dd a, #root figcaption a, #root blockquote a, #root .pyxl-prose a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, currentColor 38%, transparent);
  transition: text-decoration-color 220ms cubic-bezier(.22,1,.36,1), text-decoration-thickness 220ms ease, color 180ms ease;
}
#root p a:hover, #root li a:hover, #root td a:hover, #root dd a:hover, #root figcaption a:hover, #root blockquote a:hover, #root .pyxl-prose a:hover {
  text-decoration-color: currentColor; text-decoration-thickness: 1.5px; opacity: 1;
}

/* 2 · Chrome. Inline colour is authored on most of these, so the step needs to win. */
#root header nav[aria-label="Primary"] > a:hover { color: var(--color-electric-blue-500) !important; opacity: 1; }
#root footer a:not([style*="radius-pill"]):hover { color: var(--color-coral-500) !important; opacity: 1; }
#root .pyxl-drawer a:hover { color: var(--color-electric-blue-500) !important; opacity: 1; }

/* 3 · Objects. A card's hairline is what reacts, not the whole card's alpha. */
#root a[style*="border-radius"]:hover, #root a.pyxl-card:hover, #root .pyxl-nextup:hover { opacity: 1; }
#root .pyxl-nextup:hover { border-color: var(--color-electric-blue-500) !important; }
@media (prefers-reduced-motion:reduce) {
  #root p a, #root li a, #root td a, #root figcaption a { transition: none; }
}
/* Press is a 1px settle, never a scale — the layout must not shift. */
#root a:active, #root button:active { transform: translateY(1px); }
/* Cards lift on hover wherever the whole card is a link. */
#root a[style*="border-radius"]:hover, #root a.pyxl-card:hover { opacity: 1; }

@media (prefers-reduced-motion:reduce) {
  #root a, #root button { transition: none; }
  #root a:active, #root button:active { transform: none; }
}

/* Mega-panel reveal. Lives here, not in a page's inline style, so the header
   component's animation reference can never drift from the pages that mount it. */
@keyframes pyxl-nav-curtain{from{clip-path:inset(0 0 100% 0)}to{clip-path:inset(0 0 0 0)}}

/* Mega-panel interior. The container wipes; its contents rise in sequence, which
   is the difference between a div appearing and an interface arriving. */
@keyframes pyxl-nav-rise{from{opacity:0;transform:translateY(11px)}to{opacity:1;transform:none}}
.pyxl-nav-in{animation:pyxl-nav-rise 444ms cubic-bezier(.22,.61,.36,1) both}
.pyxl-nav-stagger>*{animation:pyxl-nav-rise 444ms cubic-bezier(.22,.61,.36,1) both}
.pyxl-nav-stagger>*:nth-child(1){animation-delay:111ms}.pyxl-nav-stagger>*:nth-child(2){animation-delay:111ms}
.pyxl-nav-stagger>*:nth-child(3){animation-delay:222ms}.pyxl-nav-stagger>*:nth-child(4){animation-delay:222ms}
.pyxl-nav-stagger>*:nth-child(5){animation-delay:333ms}.pyxl-nav-stagger>*:nth-child(6){animation-delay:333ms}
.pyxl-nav-stagger>*:nth-child(n+7){animation-delay:444ms}
.pyxl-nav-fig{transition:border-top-color 222ms ease,transform 222ms cubic-bezier(.22,.61,.36,1)}
a.pyxl-nav-fig:hover{border-top-color:var(--color-electric-blue-500);transform:translateY(-3px)}
.pyxl-nav-cell{transition:background 111ms ease}
.pyxl-nav-cell:hover{background:rgba(14,67,227,0.07)!important}
.pyxl-nav-link{transition:color 111ms ease}
.pyxl-nav-link:hover{color:var(--color-electric-blue-500)}
.pyxl-nav-row{transition:padding-left 222ms cubic-bezier(.22,.61,.36,1),border-bottom-color 222ms ease}
.pyxl-nav-row:hover{padding-left:8px;border-bottom-color:var(--color-electric-blue-500)}

/* Case entries: the index numeral is the only thing that reacts, so a long page of
   them stays calm while still feeling alive under the cursor. */
.pyxl-case{transition:border-top-color 222ms ease}
.pyxl-case:hover{border-top-color:var(--color-electric-blue-500)}
.pyxl-case-n{transition:color 222ms ease}
.pyxl-case:hover .pyxl-case-n{color:var(--color-electric-blue-500)}

/* --- mobile pass ------------------------------------------------------------
   Roughly half of first visits are on a phone. Everything below is a phone
   treatment, not a shrunken desktop one. */

@media (max-width:760px) {
  #root [style*="grid-template-columns"] { grid-template-columns: 1fr !important; }
  #root [style*="column-count"] { column-count: 1 !important; }

  /* Inline text links are correct at desktop and below target on a phone.
     A 44px hit area without changing how the line reads. */
  #root main a:not([class*="pyxl-btn"]) {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  #root p a, #root li a, #root figcaption a, #root span a {
    display: inline;
    min-height: 0;
    padding-block: 11px;
  }
  #root button, #root [role="button"], #root input, #root select, #root textarea {
    min-height: 44px;
  }

  /* Type comes down a step so display headlines keep five or six words a line. */
  #root h1 { font-size: clamp(34px, 9vw, 46px) !important; line-height: 1.06 !important; letter-spacing: -1px !important; }
  #root h2 { font-size: clamp(28px, 7.4vw, 36px) !important; line-height: 1.08 !important; letter-spacing: -0.8px !important; }
  #root h3 { font-size: clamp(21px, 5.6vw, 26px) !important; line-height: 1.14 !important; }
  #root p { font-size: 15px !important; line-height: 25px !important; }

  /* Section padding halves; the desktop rhythm is unreadable at this width. */
  #root section { padding-top: 56px !important; padding-bottom: 56px !important; }
  #root section > div { padding-left: 20px !important; padding-right: 20px !important; }

  /* Wide fixed elements: tables, code and diagrams scroll rather than squash. */
  #root pre, #root table { overflow-x: auto; }
  #root [style*="min-width: 7"], #root [style*="minWidth: 7"] { min-width: 0 !important; }

  /* Sonic dots are ambient; at phone width they crowd the text. Targets the motif
     wrapper class — the old selector matched a mask-image implementation that no
     longer exists, so this rule had been dead. */
  #root .pyxl-motif { opacity: 0.5 !important; }  .cl-row{grid-template-columns:minmax(0,1fr);gap:40px}
  .cl-colhead{display:none}
  .cl-sec{padding-left:22px!important;padding-right:22px!important}
  /* The bracket diagram's zone labels are placed by explicit grid-column. Once the cards
     stack, those spans point at columns that no longer exist. */
  #root [style*="grid-column"]{grid-column:1 / -1!important}
  #root section [style*="display: flex"],#root section [style*="display:flex"]{flex-wrap:wrap}
  /* Marker + wrapping-text rows (bullets, numerals, "+"/"−" toggles, price/label pairs)
     must never wrap as whole flex items — that orphans the small marker onto its own
     line above the text once the text needs two lines. The text itself still wraps
     fine internally under nowrap. Scoped to li/summary/button, the three tags every
     bullet list, FAQ accordion and bullet toggle in this codebase uses for this shape. */
  #root section li[style*="display: flex"],#root section li[style*="display:flex"],
  #root section summary[style*="display: flex"],#root section summary[style*="display:flex"],
  #root section button[style*="display: flex"],#root section button[style*="display:flex"]{flex-wrap:nowrap!important}
  #root section a[style*="nowrap"],#root section span[style*="nowrap"],#root section [style*="white-space: nowrap"]{white-space:normal!important}
  #root .cl-nowrap{white-space:nowrap!important}
  #root section a[style*="inline-flex"]{max-width:100%}
  #root footer [style*="nowrap"]{white-space:normal!important}
}

@media (max-width:520px) {
  #root section > div { padding-left: 16px !important; padding-right: 16px !important; }
  #root h1 { font-size: clamp(30px, 8.6vw, 38px) !important; }
}

.pyxl-search::placeholder{color:rgba(2,5,32,.42)}
.pyxl-search:focus{border-color:var(--color-electric-blue-500)!important}

/* Client index. Proportional row tracks so the name column can never floor at zero when
   #root goes fluid, plus the two stacking points the rest of the site already uses. */
.cl-shell{display:grid;grid-template-columns:292px minmax(0,1fr);gap:60px;align-items:start}
.cl-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,0.85fr) minmax(0,1.9fr);gap:40px}
.cl-nowrap{white-space:nowrap}
/* The index scrolls in its own box rather than down the page: the full roster is a scroll
   the page should not own. Letter rail jumps by setting scrollTop, so the page never moves. */
.cl-scroll{position:relative;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.cl-scroll::-webkit-scrollbar{width:10px}
.cl-scroll::-webkit-scrollbar-track{background:var(--surface-inset)}
.cl-scroll::-webkit-scrollbar-thumb{background:rgba(2,5,32,.24);border:3px solid var(--surface-inset)}
.cl-scroll::-webkit-scrollbar-thumb:hover{background:rgba(2,5,32,.42)}
.cl-scroll{scrollbar-width:thin;scrollbar-color:rgba(2,5,32,.28) var(--surface-inset)}
.cl-scroll:focus-visible{outline:2px solid var(--color-electric-blue-500);outline-offset:2px}
.cl-alpha{display:flex;flex-wrap:wrap;gap:2px}
.cl-alpha button{width:22px;height:22px;display:grid;place-items:center;border:none;background:transparent;border-radius:32px;font-family:var(--font-body);font-weight:600;font-size:10.5px;letter-spacing:.4px;color:var(--color-midnight-500);cursor:pointer;transition:background .12s,color .12s}
.cl-alpha button:hover:not(:disabled){background:var(--color-midnight-500);color:var(--color-paper-500)}
.cl-alpha button:disabled{color:var(--text-faint);opacity:.38;cursor:default}
@media (max-width:1100px){
  .cl-shell{grid-template-columns:minmax(0,1fr);gap:40px}
  .cl-rail{position:static!important;max-height:none!important;overflow:visible!important}
  .cl-sec{padding-left:40px!important;padding-right:40px!important}
}

/* Hero scale band. Its own class rather than an inline repeat(5,1fr) string, so the
   global 5-to-2 collapse cannot strand a fifth cell as an empty lit rectangle. */
.hero-scale{grid-template-columns:minmax(0,0.92fr) minmax(0,2fr)}
@media (max-width:900px){.hero-scale{grid-template-columns:minmax(0,1fr)}}
@media (max-width:460px){.hero-scale .hs-rest{grid-template-columns:minmax(0,1fr)!important}}

.pyxl-nextup{transition:border-color .111s,transform .111s}
.pyxl-nextup:hover{transform:translateY(-2px)}
@media (max-width:1100px){.pyxl-nextup{padding:18px 18px 16px!important}}
@media (max-width:900px){[style*="repeat(3, minmax(0,1fr))"]{grid-template-columns:minmax(0,1fr)!important}}

/* The section eyebrow doubles as the way back up. On a section home it is a reset; on a
   child page it is the only breadcrumb there is. */
.pyxl-eyebrow-link{transition:opacity .111s}
.pyxl-eyebrow-link:hover{opacity:.68}
.pyxl-eyebrow-link:hover span:last-child{text-decoration:underline;text-underline-offset:3px}

/* Footer. Explicit tracks rather than a wrapping flex: the rail is fixed, the five link
   columns are container-relative, so long labels wrap inside their track instead of
   pushing the intrinsic width past the container and forcing the rail onto its own line. */
.foot-top{display:grid;grid-template-columns:292px repeat(4,minmax(0,1fr));gap:44px 40px;align-items:start}
.foot-offices{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:40px;align-items:start}
@media (max-width:1240px){.foot-top{grid-template-columns:268px repeat(3,minmax(0,1fr))}.foot-rail{grid-column:1;grid-row:1 / span 2}}
@media (max-width:1000px){.foot-top{grid-template-columns:236px repeat(2,minmax(0,1fr));gap:40px}.foot-rail{grid-column:1;grid-row:1 / span 3}.foot-offices{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:700px){.foot-top{grid-template-columns:repeat(2,minmax(0,1fr))}.foot-rail{grid-column:1 / -1;grid-row:auto}.foot-offices{grid-template-columns:minmax(0,1fr)}}

/* B2B: three moves with the sequence made visible between them. */
.b2b-steps{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr) 28px minmax(0,1fr);gap:0 40px;align-items:stretch}
@media (max-width:1000px){.b2b-steps{grid-template-columns:minmax(0,1fr);gap:40px}.b2b-arrow{display:none}}

/* Volume 03: the three-stage catalog layer flow. */
.rc-flow{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr) 28px minmax(0,1fr);gap:0 40px;align-items:stretch}
@media (max-width:1000px){.rc-flow{grid-template-columns:minmax(0,1fr);gap:40px}.rc-arrow{display:none}}

/* Research: the AI-visibility volumes, three-up at design width and stacking before they crowd.
   Volume 04 sits in its own band below this grid, not as a fourth cell. */
.ins-vols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:40px}
@media (max-width:1320px){.ins-vols{grid-template-columns:repeat(2,minmax(0,1fr));gap:40px}}
@media (max-width:880px){.ins-vols{grid-template-columns:minmax(0,1fr);gap:40px}}

details>summary::-webkit-details-marker{display:none}
details>summary::marker{content:""}
details>summary:focus-visible{outline:2px solid var(--color-electric-blue-500);outline-offset:3px}
details>summary:hover{opacity:.74}

.pyxl-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* WCAG 2.4.7 — one visible focus ring for every interactive element, on both grounds.
   Authored once here rather than per component so an inline style cannot silently drop it. */
a:focus-visible,button:focus-visible,summary:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--color-electric-blue-500);outline-offset:3px;border-radius:32px}
.pyxl-dark a:focus-visible,.pyxl-dark button:focus-visible,.pyxl-dark summary:focus-visible,.pyxl-dark input:focus-visible,.pyxl-dark [tabindex]:focus-visible{outline-color:var(--color-paper-500)}

/* WCAG 2.3.3 — the reveal animation is the only motion on the site that fires unprompted.
   Honor the OS setting by landing every element in its final state immediately. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
  [style*="pyxl-fade"]{opacity:1!important;transform:none!important}
}

/* WCAG 1.4.10 — reflow. At 400% zoom on a 1280 viewport the content box is 320px, so that
   is the real floor. The stacking rules above take everything to one column by 760px; these
   two catch what stacking alone leaves behind. */

/* ── Nothing may sit outside the gutter ──────────────────── */
/* Pill CTAs and label rows are authored nowrap for a wide column. On a phone the
   row wraps and the label wraps with it, rather than a centered row overflowing
   both edges (which put a button at x=-25) or a nowrap caption clearing the
   right gutter. Decorative watermarks are exempt: their sections clip them. */

@media (max-width:400px){
  #root section > div,#root header > div,#root footer > div{padding-left:14px!important;padding-right:14px!important}
  #root h1{font-size:clamp(26px,8.4vw,32px)!important;line-height:1.14!important;letter-spacing:-0.6px!important}
  #root h2{font-size:clamp(22px,7vw,27px)!important;line-height:1.16!important}
  #root h3{font-size:clamp(18px,5.6vw,21px)!important;line-height:1.2!important}
  /* Nothing may scroll sideways at the floor width. */
  #root,#root *{max-width:100%}
  #root [style*="min-width"]{min-width:0!important}
  #root details > p{margin-left:0!important}
}

/* Moments routing band. Two columns at design width, one before the label and the
   imperative would each drop to a single word per line. */
.mom-grid{}
@media (max-width:1000px){.mom-grid{grid-template-columns:minmax(0,1fr)!important;gap:0!important}}
@media (max-width:600px){.mom-grid>div{grid-template-columns:minmax(0,1fr)!important;gap:6px!important}}
/* Topic-selector pills: the site's 40px chip gap is right for cards/tabs, but on a
   narrow phone it strands single-column pills with huge dead space between them. */
@media (max-width:600px){.pyxl-topic-pills{gap:10px!important}}
/* Sector index row: a 250px/1fr/120px/34px grid (name, preview, bar, count) collapses
   to one column on mobile and stacks all four full-width, stranding the count below
   the bar with no visual link back to its own sector name. Keep name+count paired on
   one line, preview text and bar each on their own full-width line beneath. */
@media (max-width:700px){
  .cl-sector-row{grid-template-columns:1fr auto!important;grid-template-rows:auto auto auto!important;column-gap:12px!important;row-gap:6px!important}
  .cl-sector-row>*:nth-child(1){grid-column:1;grid-row:1}
  .cl-sector-row>*:nth-child(4){grid-column:2;grid-row:1;text-align:right}
  .cl-sector-row>*:nth-child(2){grid-column:1 / -1;grid-row:2;white-space:normal!important}
  .cl-sector-row>*:nth-child(3){grid-column:1 / -1;grid-row:3}
}
/* Marker/numeral + wrapping-text grids (bullet dots, "0X" numerals) must keep their
   fixed-width first column at any size — collapsing it to one column (the generic
   grid-template-columns:1fr rule above) stacks the marker alone above the text. Only
   the exact small marker widths this codebase uses are protected; label/photo columns
   (76px+) are left to collapse, since those read fine stacked on a phone.
   Scoped to phone width on purpose — these are substring matches on the inline style
   (`[style*="...56px 1fr"]` matches ANY row starting with that track pair, including a
   3-column `56px 1fr 236px` row), so left unscoped they silently collapse a genuine
   desktop 3-column row to 2 tracks, stranding the third column's content with no track
   to sit in. This exact collision hit the seven-day-prototype deliverables table. */
@media (max-width:760px){
#root [style*="grid-template-columns: 3px 1fr"]{grid-template-columns:3px 1fr!important}
#root [style*="grid-template-columns: 8px 1fr"]{grid-template-columns:8px 1fr!important}
#root [style*="grid-template-columns: 9px 1fr"]{grid-template-columns:9px 1fr!important}
#root [style*="grid-template-columns: 10px 1fr"]{grid-template-columns:10px 1fr!important}
#root [style*="grid-template-columns: 18px 1fr"]{grid-template-columns:18px 1fr!important}
#root [style*="grid-template-columns: 22px 1fr"]{grid-template-columns:22px 1fr!important}
#root [style*="grid-template-columns: 24px 1fr"]{grid-template-columns:24px 1fr!important}
#root [style*="grid-template-columns: 28px 1fr"]{grid-template-columns:28px 1fr!important}
#root [style*="grid-template-columns: 30px 1fr"]{grid-template-columns:30px 1fr!important}
#root [style*="grid-template-columns: 56px 1fr"]{grid-template-columns:56px 1fr!important}
#root [style*="grid-template-columns: 58px 1fr"]{grid-template-columns:58px 1fr!important}
#root [style*="grid-template-columns: 10px minmax(0,1fr)"]{grid-template-columns:10px minmax(0,1fr)!important}
#root [style*="grid-template-columns: auto 1fr auto"]{grid-template-columns:auto 1fr auto!important}
#root [style*="grid-template-columns: auto 1fr"]{grid-template-columns:auto 1fr!important}
#root [style*="grid-template-columns: auto minmax(0,1fr)"]{grid-template-columns:auto minmax(0,1fr)!important}
}
@media (max-width:700px){.eng-why-row,.common-3col-row{gap:6px!important}}
/* The seven-day-prototype deliverables table (numeral / heading+description / format
   badge) is a genuine 3-column row (56px 1fr 236px) that the substring-matching rules
   above would otherwise still collapse to 2 tracks on phone, stranding the badge. Give
   it its own explicit mobile shape instead: numeral stays beside the heading, and the
   format badge drops to a full-width row underneath. */
@media (max-width:760px){
  #root .proto-manifest-row{grid-template-columns:40px 1fr!important;gap:14px!important}
  #root .proto-manifest-fmt{grid-column:1 / -1!important;margin-top:14px!important}
  #root .proto-manifest-head .proto-manifest-fmt{margin-top:0!important}
  /* Same substring-collision family: a fixed multi-track row (numeral + name/tag block +
     paragraph + link, or numeral + title + a metadata column) has no fixed-width column
     worth preserving once it wraps, so a plain full stack reads cleanly with no stranding. */
  #root .gridstack-mobile{grid-template-columns:1fr!important;row-gap:16px!important}
}

/* Work entries. The image column stretches to absorb narrative height, so it stacks
   below the narrative rather than beside it once the row gets narrow. */
.case-body{}
@media (max-width:1000px){.case-body{grid-template-columns:minmax(0,1fr)!important;gap:40px!important}.case-body>div:last-child figure span{min-height:0!important;aspect-ratio:16/9}}
@media (max-width:700px){.case-figs{grid-template-columns:repeat(2,minmax(0,1fr))!important;gap:40px!important}}
@media (max-width:460px){.case-figs{grid-template-columns:minmax(0,1fr)!important}}

/* The weave's fiber-optic bead. Only stroke-dashoffset animates, so the ribbon geometry
   and the four crossing dots never move. Each dash is zero-length with a round cap, which
   paints a dot of the stroke's full diameter rather than a lit stretch of line: a wide soft
   halo, a mid glow in the motion's own hue, and a small paper-white center. B runs against
   A because the two motions run in opposite directions, and the half-cycle offset lands
   the two beads together at the crossings. */
/* A section heading and its photographic vessel share one grid row. The second column is
   fluid so the pairing survives the 1320 reflow instead of vanishing; on phones the row
   stacks and the vessel steps down rather than being removed. */
.pyxl-headrow{display:grid;grid-template-columns:minmax(0,1fr) clamp(190px,23%,300px);gap:clamp(40px,3vw,44px);align-items:center}
@media (max-width:760px){.pyxl-headrow{grid-template-columns:minmax(0,1fr);gap:40px}.pyxl-vessel{max-width:210px!important;justify-self:start!important}}
.wv-run{will-change:stroke-dashoffset}
.wv-halo{stroke-dasharray:0.01 999.99}
.wv-glow{stroke-dasharray:0.01 999.99}
.wv-core{stroke-dasharray:0.01 999.99}
.wv-a{animation:wv-travel 11s linear infinite}
.wv-b{animation:wv-travel 11s linear infinite reverse;animation-delay:-5.5s}
@keyframes wv-travel{from{stroke-dashoffset:1000}to{stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){.wv-run{animation:none;opacity:0}}

/* ── Motion: two additions, both tied to something the reader is doing ───────── */
/* Primary actions rise under the cursor. The kit's buttons carry the pill radius as an
   inline custom property, so one selector reaches every one of them without a class being
   threaded through twenty call sites. A lift is the only place position changes on hover —
   reserved for the elements that are asking for a click. */
#root a[style*="radius-pill"], #root button[style*="radius-pill"], .pyxl-hdr-cta a{transition:transform 222ms cubic-bezier(.22,1,.36,1),box-shadow 222ms cubic-bezier(.22,1,.36,1),opacity .222s cubic-bezier(.22,1,.36,1),background-color .222s cubic-bezier(.22,1,.36,1),color .222s cubic-bezier(.22,1,.36,1)!important}
#root a[style*="radius-pill"]:hover, #root button[style*="radius-pill"]:hover, .pyxl-hdr-cta a:hover{transform:translateY(-2px);box-shadow:0 6px 16px rgba(2,5,32,.16)}
#root a[style*="radius-pill"]:active, #root button[style*="radius-pill"]:active, .pyxl-hdr-cta a:active{transform:translateY(0);box-shadow:none}
/* The sticky bar earns a shadow once there is content behind it, so chrome separates from
   the page instead of floating on it. Shadow only — no height or padding change, so the
   layout cannot shift as it engages. */
.pyxl-hdr-bar{transition:border-color 222ms ease,box-shadow 222ms ease}
body.pyxl-scrolled .pyxl-hdr-bar{box-shadow:0 1px 14px rgba(2,5,32,.11)}
@media (prefers-reduced-motion:reduce){
  #root a[style*="radius-pill"]:hover, #root button[style*="radius-pill"]:hover, .pyxl-hdr-cta a:hover{transform:none}
}

/* Work filter bar. It has to outlive the section it filters, so it sits in .wk-scope
   alongside the records rather than inside a band of its own — a sticky element cannot leave
   its containing block, and the old dark band was 222px tall with overflow:hidden. Stuck, the
   bar sheds its section labels and puts the sector chips on one scrollable line; three rows of
   filters pinned to the top would take a third of the screen. flex-wrap is set here rather
   than inline because the inline declaration would otherwise win. */
.wk-scope{position:relative}
.wk-bar{position:sticky;top:var(--wk-top,64px);z-index:18;background:var(--color-paper-500);padding:22px 0 26px;box-shadow:0 0 0 rgba(2,5,32,0);transition:padding 180ms ease,box-shadow 180ms ease}
.wk-bar>*{position:relative}
/* The column the Band used to supply: same max-width and gutters as every other section, so
   the filters line up with the records they filter. */
.wk-head{background:var(--color-paper-500);padding:58px 0 26px}
.wk-inner{width:100%;max-width:1304px;margin:0 auto;padding:0 32px;box-sizing:border-box}
.wk-sectors{flex-wrap:wrap}
.wk-bar[data-stuck="1"]{padding:10px 0 12px;box-shadow:0 12px 26px rgba(2,5,32,.14)}
.wk-bar[data-stuck="1"] .wk-row1{padding-top:12px!important;border-top-color:transparent!important}
.wk-bar[data-stuck="1"] .wk-lab{display:none}
.wk-bar[data-stuck="1"]{overflow:visible}
.wk-secmenu button:focus-visible{outline:2px solid var(--color-coral-500);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.wk-bar{transition:none}}

/* Services finder — the instrument under the hero. Stacks on narrow viewports, and the
   depth filter drops under the field rather than squeezing it. */
@media (max-width:900px){
  .svc-finder{grid-template-columns:1fr!important;gap:40px!important}
  .svc-finder > div:last-child > div:first-child{grid-template-columns:1fr!important}
  .svc-finder input{font-size:16px!important}
}


/* ── The column gutter ──────────────────────────────────────────────────────────────
   Col2 sets width:100% and max-width:1240 inline. The side gutter has to live here and
   carry !important, because many callers pass a padding shorthand for vertical rhythm
   and an inline shorthand beats an inline paddingInline. Vertical padding therefore stays
   the caller's business; horizontal is always ours. */
.pyxl-col{width:100%;max-width:1304px;margin-inline:auto;box-sizing:border-box;padding-inline:32px!important}
@media (max-width:900px){.pyxl-col{padding-inline:24px!important}}
@media (max-width:600px){.pyxl-col{padding-inline:18px!important}}


/* ── Phone: collapse the grids ───────────────────────────────────────────────────────
   The pages are authored with inline gridTemplateColumns in 27 files — four-, five- and
   seven-column layouts, plus mixed fixed/fluid tracks. Editing each one is 27 files of risk
   for a result CSS can state once: below 700px, content grids inside the page column go to
   a single column. Inline styles win over stylesheets, hence !important.

   Opt out with .pyxl-keep-grid for the few things that MUST stay multi-column at any width
   — the four depth marks, which are a single instrument rather than four items. */
@media (max-width:700px){
  .pyxl-col [style*="grid-template-columns"]:not(.pyxl-keep-grid):not(.pyxl-keep-grid *){grid-template-columns:1fr!important}
  .pyxl-col [style*="grid-template-columns"] > *{min-width:0}
  .pyxl-pair-row{flex-direction:column!important;gap:34px!important}
  .pyxl-pair-divider{width:100%!important;height:0!important;border-left:none!important;border-top:0.625px solid var(--line-hairline)!important}
  .pyxl-pair-divider-label{writing-mode:horizontal-tb!important;position:static!important;top:auto!important;left:auto!important;transform:none!important;display:block!important;width:fit-content!important;margin:-11px auto 0!important;padding:0 10px!important}
}
/* Between tablet and phone, the widest layouts halve rather than stack. */
@media (max-width:1000px) and (min-width:701px){
  .pyxl-col [style*="repeat(5"]:not(.pyxl-keep-grid),
  .pyxl-col [style*="repeat(6"]:not(.pyxl-keep-grid),
  .pyxl-col [style*="repeat(7"]:not(.pyxl-keep-grid){grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .pyxl-col [style*="repeat(4"]:not(.pyxl-keep-grid){grid-template-columns:repeat(2,minmax(0,1fr))!important}
}

/* ── The record rows ─────────────────────────────────────────────────────────────────
   Five tracks — index, problem, depth, evidence, arrow. On a phone the index and the
   problem share the first line and the instruments drop beneath, rather than the whole row
   stacking into five separate lines. */
@media (max-width:700px){
  .cs-row[style*="grid-template-columns"]{grid-template-columns:34px 1fr!important;row-gap:40px!important}
  .cs-row[style*="grid-template-columns"] > *:nth-child(3),
  .cs-row[style*="grid-template-columns"] > *:nth-child(4){grid-column:2}
  .cs-row[style*="grid-template-columns"] > *:nth-child(5){display:none}
}

/* Long-form measure: type set for a 1240px column needs a shorter line on a phone. */
@media (max-width:600px){
  .pyxl-col h1{font-size:38px!important;line-height:40px!important;letter-spacing:-1.1px!important}
  .pyxl-col h2{font-size:31px!important;line-height:34px!important;letter-spacing:-0.8px!important}
  .pyxl-col h3{font-size:20px!important;line-height:25px!important}
}


#root header .pyxl-menu-search{margin-bottom:6px}

@media (max-width:1000px){#root .pyxl-plat-grid{grid-template-columns:repeat(2,1fr)}}
@media (max-width:600px){#root .pyxl-plat-grid{grid-template-columns:1fr}}
#root .pyxl-plat-card:hover{background:var(--color-paper-500)}


/* ── Phone type floor ─────────────────────────────────────────────────────────
   The micro-label is a real device on this site — 9 to 10.5px, uppercase, letterspaced,
   set against a 1240px column where it reads as a caption rather than as body copy. At
   390px it stops being a device and becomes small print: an audit at phone width found
   roughly 1,900 rendered strings below 11px, and 661 of them on the work page alone were
   at 8.5 and 9.5. Nothing on a page that sells digital craft should need to be squinted at.

   The sizes are declared inline by the components, so the floor is applied the same way
   the responsive grid rules in this file are — by matching the inline declaration. Two
   steps only: everything under 10 lands at 11, everything from 10 to 10.5 lands at 11.5.
   Above the phone breakpoint the original scale is untouched. */
@media (max-width:700px) {
  #root [style*="font-size: 8px"],
  #root [style*="font-size: 8.5px"],
  #root [style*="font-size: 9px"],
  #root [style*="font-size: 9.5px"],
  #root [style*="font-size: var(--size-system)"] { font-size: 11px !important; line-height: 1.45 !important; }
  #root [style*="font-size: 10px"],
  #root [style*="font-size: 10.5px"] { font-size: 11.5px !important; }
  #root [style*="letter-spacing: 1.8px"],
  #root [style*="letter-spacing: 1.7px"] { letter-spacing: 1.4px !important; }
}

/* ── Target size ──────────────────────────────────────────────────────────────
   WCAG 2.5.8. Footer and inline list links render at their 14px line box, which leaves a
   13-14px high target with a 9px gap. The links keep their look; the box around them grows
   to 24px. Applied where links stack in a list rather than run inside a sentence. */
#root footer ul a, #root footer .foot-offices a { display: inline-block; padding-block: 5px; }
#root footer ul li { line-height: 0; }

/* ── In-page section index ────────────────────────────────────────────────────
   Sticky strip under the header on the pages that run long. Paper ground, hairline rule,
   coral for the section you are in, and the bottom edge doubling as reading progress. */
.pyxl-secnav { position: sticky; position: -webkit-sticky; top: var(--sn-top, 64px); z-index: 20; background: var(--color-paper-500); border-top: 0.625px solid var(--line-hairline); border-bottom: 0.625px solid var(--line-hairline); transition: box-shadow 222ms ease; }
.pyxl-secnav[data-stuck="1"] { box-shadow: 0 1px 14px rgba(2,5,32,.09); }
.pyxl-secnav-in { display: flex; align-items: center; gap: 18px; min-height: 52px; }
.pyxl-secnav-lab { flex-shrink: 0; font-family: var(--font-body); font-weight: 600; font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--text-faint); }
.pyxl-secnav-rail { display: flex; align-items: stretch; gap: 2px; min-width: 0; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.pyxl-secnav-rail::-webkit-scrollbar { display: none; }
.pyxl-secnav-item { display: flex; align-items: center; flex-shrink: 0; min-height: 44px; padding: 0 11px; font-family: var(--font-body); font-size: 12.5px; line-height: 18px; white-space: nowrap; text-decoration: none; color: var(--text-muted); box-shadow: inset 0 -1.5px 0 transparent; transition: color 160ms ease, box-shadow 160ms ease; }
.pyxl-secnav-item:hover { color: var(--color-midnight-500); opacity: 1; }
.pyxl-secnav-item[data-on="1"] { font-weight: 600; color: var(--color-midnight-500); box-shadow: inset 0 -1.5px 0 var(--color-electric-blue-500); }
.pyxl-secnav-item:focus-visible { outline: 2px solid var(--color-electric-blue-500); outline-offset: -3px; }
.pyxl-secnav-top { flex-shrink: 0; margin-left: auto; display: flex; align-items: center; min-height: 44px; font-family: var(--font-body); font-weight: 600; font-size: 12px; letter-spacing: 0.2px; color: var(--text-faint); text-decoration: none; }
.pyxl-secnav-top:hover { color: var(--color-midnight-500); opacity: 1; }
.pyxl-secnav-prog { position: absolute; left: 0; bottom: -0.625px; height: 1.5px; width: 100%; background: var(--gradient-coral-to-orange); transform-origin: 0 50%; transform: scaleX(0); }
#root main section[id] { scroll-margin-top: calc(var(--sn-top, 64px) + 60px); }
@media (max-width:820px) {
  .pyxl-secnav-lab, .pyxl-secnav-top { display: none; }
  .pyxl-secnav-in { gap: 0; padding-inline: 8px !important; }
  .pyxl-secnav-item { font-size: 13px; padding: 0 12px; }
}
@media (prefers-reduced-motion:reduce) { .pyxl-secnav-item { transition: none; } }


/* The weave has two forms. Above the tablet break the four crossings are labelled in place
   on the ribbon, which is the whole idea of the drawing. Below it each label column measures
   about seventy pixels — seven lines of 11px type sitting on top of the path and on top of
   each other — so the labels come off, the ribbon flattens into a band and keeps working as
   a mark, and the crossings are read down as a numbered list instead of across. */
.wv-list{display:none}
@media (max-width:900px){
  .wv-abs{display:none!important}
  .wv-list{display:grid!important}
  .wv-fig{aspect-ratio:1240/380!important}
}
@media (max-width:520px){.wv-fig{aspect-ratio:1240/460!important}}
/* The hero footnote rail: label column and prose. On a phone the label sits above. */
@media (max-width:700px){.pyxl-col .hero-foot.hero-foot{grid-template-columns:minmax(0,1fr)!important;gap:4px!important}.hero-foot>span[aria-hidden]{display:none}}


/* ── The primary action ───────────────────────────────────────────────────────
   Two defects, both site-wide. The kit's Button fills with midnight, so on a midnight
   band it disappeared into its own ground and the homepage's single most important
   call to action rendered as bare uppercase text next to a secondary link that had an
   underline — the hierarchy exactly inverted. And at 10px on 9px of padding it was a
   chip rather than a button anywhere.

   One rule for both. The action colour is the coral-to-orange gradient with a midnight
   label on paper — 7.5:1 on the coral stop, 10:1 on the orange — and paper on midnight,
   because on a dark band the brightest object should be the thing you are being asked
   to press. Coral-700 is retired: text accents now clip --gradient-electric-to-coral to
   the glyphs, and fills that carry a label stay coral-to-orange, because a paper label
   fails on that gradient's coral stop and a midnight one fails on its blue stop.

   Scoped to anchors. Filter chips and tabs are <button> and keep their own quiet look. */
#root a[style*="radius-pill"]:not(.pyxl-hdr-cta a):not([data-quiet]) {
  background: var(--gradient-coral-to-orange) !important;
  color: var(--color-midnight-500) !important;
  border-color: transparent !important;
  padding: 13px 26px !important;
  font-size: 12px !important;
  letter-spacing: 0.2px !important;
}
#root .pyxl-dark a[style*="radius-pill"]:not(.pyxl-hdr-cta a):not([data-quiet]),
#root section.pyxl-dark a[style*="radius-pill"]:not([data-quiet]) {
  background: var(--color-paper-500) !important;
  color: var(--color-midnight-500) !important;
}
#root a[style*="radius-pill"]:not(.pyxl-hdr-cta a):hover { box-shadow: 0 8px 20px rgba(2,5,32,.22); }
#root .pyxl-dark a[style*="radius-pill"]:hover { box-shadow: 0 8px 22px rgba(0,0,0,.4); }
@media (max-width:700px){
  #root a[style*="radius-pill"]:not(.pyxl-hdr-cta a){ padding: 14px 22px !important; }
}

/* ── Annotation family ────────────────────────────────────────────────────────
   The margin index is a supplementary rail. It must never sit over the column, so it
   hides as soon as the gutter it lives in stops existing. */
.pyxl-mi{position:fixed;left:16px;top:50%;transform:translateY(-50%);z-index:30;display:grid;gap:2px;padding:11px 9px;background:rgba(251,248,241,.86);backdrop-filter:blur(11px);border:0.625px solid rgba(2,5,32,.12);border-radius:32px}
.pyxl-mi-i{display:flex;align-items:center;gap:8px;padding:3px 2px;text-decoration:none;white-space:nowrap}
.pyxl-mi-i:hover{opacity:1}
.pyxl-mi-n{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px;letter-spacing:.4px;color:rgba(2,5,32,.34);transition:color 222ms ease}
.pyxl-mi-r{width:10px;height:1px;background:rgba(2,5,32,.24);transition:width 222ms cubic-bezier(.22,1,.36,1),height 222ms ease,background 222ms ease}
.pyxl-mi-l{max-width:0;overflow:hidden;font-family:var(--font-body);font-weight:600;font-size:10px;letter-spacing:1.4px;text-transform:uppercase;color:var(--color-midnight-500);opacity:0;transition:max-width 300ms cubic-bezier(.22,1,.36,1),opacity 200ms ease}
.pyxl-mi:hover .pyxl-mi-l{max-width:200px;opacity:1}
.pyxl-mi-i[data-on="1"] .pyxl-mi-n{background-image:var(--gradient-electric-to-coral);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
.pyxl-mi-i[data-on="1"] .pyxl-mi-r{width:22px;height:2px;background:var(--gradient-coral-to-orange)}
.pyxl-mi-i:hover .pyxl-mi-n{color:var(--color-midnight-500)}
@media (max-width:1420px){.pyxl-mi{display:none!important}}
@media (prefers-reduced-motion:reduce){.pyxl-mi-l,.pyxl-mi-r{transition:none}}


/* ── Registration marks on evidence ───────────────────────────────────────────
   The third motif family, applied where it belongs: a live build is a document, and
   a document carries crop marks. Four corner ticks outside the frame, drawn in one
   rule rather than four spans, so every embedded build on the site is registered the
   same way. This is also the site's icon system — it has no icon set and does not need
   one. The vocabulary is a rule, a tick, a dimension cap, an arrow and a dot, all at
   the same weight, and nothing is imported. */
.pyxl-evidence{position:relative}
.pyxl-evidence::after{content:"";position:absolute;inset:-8px;pointer-events:none;--tk:rgba(2,5,32,.28);
  background:
    linear-gradient(var(--tk),var(--tk)) 0 0/10px 1px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 0 0/1px 10px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 100% 0/10px 1px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 100% 0/1px 10px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 0 100%/10px 1px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 0 100%/1px 10px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 100% 100%/10px 1px no-repeat,
    linear-gradient(var(--tk),var(--tk)) 100% 100%/1px 10px no-repeat;
}
.pyxl-dark .pyxl-evidence::after{--tk:rgba(251,248,241,.4)}
@media (max-width:700px){.pyxl-evidence::after{display:none}}


/* ── Where we work: the sector instrument ─────────────────────────────────────
   A ranked list on the left, one panel on the right. The bar length is client count and
   the two segments are the motion split, so both variables in the chart are real and both
   resolve to names in the client index. The list owns its own scroll — twenty-two rows is
   a scroll the page should not inherit, and the same decision the client index already
   makes. Motion is stated in words inside the panel as well as coded in colour. */
.ind-shell{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,0.95fr);gap:54px;align-items:start}
.ind-head{display:grid;grid-template-columns:minmax(120px,1.05fr) minmax(70px,1.3fr) 38px;gap:14px;padding-bottom:10px;border-bottom:1.5px solid var(--color-midnight-500);font-family:var(--font-body);font-weight:600;font-size:10px;letter-spacing:1.8px;text-transform:uppercase;color:var(--text-faint)}
.ind-list{max-height:470px;overflow-y:auto;overscroll-behavior:contain;scrollbar-gutter:stable}
.ind-list::-webkit-scrollbar{width:9px}
.ind-list::-webkit-scrollbar-track{background:rgba(2,5,32,.035)}
.ind-list::-webkit-scrollbar-thumb{background:rgba(2,5,32,.22);border:3px solid var(--color-paper-500)}
.ind-list{scrollbar-width:thin;scrollbar-color:rgba(2,5,32,.24) transparent}
.ind-row{border-radius:var(--radius-pill);display:grid;grid-template-columns:minmax(120px,1.05fr) minmax(70px,1.3fr) 38px;align-items:center;gap:14px;width:100%;min-height:44px;padding:9px 8px 9px 0;border:none;border-bottom:0.625px solid var(--line-hairline);background:transparent;text-align:left;cursor:pointer;transition:background 140ms ease,padding-left 200ms cubic-bezier(.22,1,.36,1)}
.ind-row:hover,.ind-row[data-on="1"]{background:rgba(2,5,32,.035)}
.ind-row[data-on="1"]{padding-left:9px}
.ind-name{font-family:var(--font-body);font-size:13.5px;line-height:18px;color:var(--color-midnight-500);text-wrap:pretty}
.ind-row[data-on="1"] .ind-name{font-weight:600}
.ind-bar{display:block;width:100%;height:5px;background:rgba(2,5,32,.07)}
.ind-bar-in{display:flex;height:100%;transition:opacity 200ms ease;opacity:.5}
.ind-bar-in>span{display:block;height:100%}
.ind-row:hover .ind-bar-in,.ind-row[data-on="1"] .ind-bar-in{opacity:1}
.ind-n{font-family:var(--font-display);font-size:17px;line-height:20px;text-align:right;color:var(--color-midnight-500);font-variant-numeric:tabular-nums}
.ind-panel{position:sticky;top:120px;padding:28px 30px 30px;background:var(--color-paper-200);border:0.625px solid var(--line-hairline);border-radius:32px}
@media (max-width:1000px){
  .ind-shell{grid-template-columns:minmax(0,1fr);gap:40px}
  .ind-panel{position:static}
  .ind-list{max-height:330px}
  .ind-head{font-size:9.5px;letter-spacing:1.3px}
}
@media (max-width:600px){
  .ind-row{grid-template-columns:minmax(0,1fr) 34px;gap:6px 12px;padding-block:11px}
  .ind-row .ind-bar{grid-column:1 / -1;order:3}
  .ind-panel{padding:22px 20px 24px}
}
@media (prefers-reduced-motion:reduce){.ind-row,.ind-bar-in{transition:none}}

/* HubSpot implementation schedule. Three fixed-ish columns at desktop; the week label
   sits above the phase name once there is no room beside it. */
@media (max-width:1000px){.hs-phase{grid-template-columns:100px minmax(0,1fr)!important;gap:40px!important}.hs-phase>span:nth-child(3){grid-column:2}}
@media (max-width:640px){.hs-phase{grid-template-columns:minmax(0,1fr)!important;gap:40px!important;padding:18px 0!important}.hs-phase>span:nth-child(3){grid-column:1}}

/* HubSpot client reviews: two side by side at desktop, stacked once the measure is tight. */
@media (max-width:820px){.hs-reviews{grid-template-columns:minmax(0,1fr)!important;gap:40px!important}}

/* Case-study header figure. Two storefronts over four shared services; both rows
   step down before the columns get too narrow to read. */
@media (max-width:900px){.cs-spine{grid-template-columns:repeat(2,minmax(0,1fr))!important}}
@media (max-width:720px){.cs-fronts,.cs-converge{grid-template-columns:minmax(0,1fr)!important}.cs-converge{height:18px!important}.cs-spine{grid-template-columns:minmax(0,1fr)!important}}
