  :root{
    --blueprint:#14304C;
    --blueprint-deep:#0D2138;
    --line-white:#E7EEF5;
    --line-dim:#9FB4C8;
    --paper:#EEF2F5;
    --paper-line:#CBD6DF;
    --ink:#182430;
    --ink-soft:#4B5A68;
    --red:#C23B2D;
    --red-deep:#9C2E23;
  }

  *,*::before,*::after{box-sizing:border-box;}
  html{scroll-behavior:smooth;}
  /* Anchor landing offset for the sticky nav. .nav .wrap wraps, so the bar is NOT
     one height: measured on the live pages with webfonts loaded, it steps at
     338 / 433 / 601 / 806px. Each band is the measured height rounded up + 8px.
       >=806  65.00 -> 73     601-805 107.39 -> 116
       433-600 63.39 -> 72    338-432 104.19 -> 113    <=337 134.58 -> 143
     Ordered widest-first so the narrowest matching max-width rule wins. */
  html{ scroll-padding-top:73px; }
  @media (max-width:805px){ html{ scroll-padding-top:116px; } }
  @media (max-width:600px){ html{ scroll-padding-top:72px; } }
  @media (max-width:432px){ html{ scroll-padding-top:113px; } }
  @media (max-width:337px){ html{ scroll-padding-top:143px; } }
  @media (prefers-reduced-motion: reduce){
    html{scroll-behavior:auto;}
    *{animation-duration:0.001ms !important; transition-duration:0.001ms !important;}
  }

  body{
    margin:0;
    background:var(--paper);
    color:var(--ink);
    font-family:'IBM Plex Sans', system-ui, sans-serif;
    font-size:20px;
    line-height:1.6;
  }

  h1,h2,h3{
    font-family:'Big Shoulders Display', sans-serif;
    font-weight:700;
    letter-spacing:0.01em;
    margin:0;
    color:inherit;
  }

  a{color:var(--blueprint);}
  a:focus-visible, button:focus-visible{ outline:3px solid var(--red); outline-offset:2px; }

  .wrap{max-width:1140px; margin:0 auto; padding:0 32px;}
  /* keeps a place name such as "St Louis" together, so the St never strands at a
     line end. A span rather than a non-breaking space: the visible FAQ text must
     stay equal to its JSON-LD, and U+00A0 would not be. */
  .nb{ white-space:nowrap; }

  /* ---------- NAV ---------- */
  /* sticky sitewide: the bar is opaque (--blueprint-deep) so content scrolls under it
     cleanly. position:sticky still establishes the containing block that
     .nav-mobile-list's absolute top:100% depends on, so the mobile menu keeps
     anchoring to the bottom of the bar. Paired with html{scroll-padding-top}
     below so in-page anchors do not land underneath it. */
  .nav{ background:var(--blueprint-deep); border-bottom:1px solid #24435F; position:sticky; top:0; z-index:100; }
  .nav .wrap{ display:flex; align-items:center; justify-content:space-between; gap:12px 24px; flex-wrap:wrap; padding-top:16px; padding-bottom:16px; }
  /* the name block is the home link. On screens under 600px the nav links are
     hidden, so this and the burger are the only nav affordances there. */
  .nav-name{ font-family:'Big Shoulders Display', sans-serif; font-weight:700; font-size:19px; color:var(--line-white); letter-spacing:0.02em; text-decoration:none; }
  .nav-name:hover{ color:#FFFFFF; }
  .nav-name:focus-visible{ outline:3px solid var(--red); outline-offset:3px; }
  .nav-name span{color:var(--red);}
  .nav-links{display:flex; gap:24px; list-style:none; margin:0; padding:0;}
  .nav-links a{ color:var(--line-dim); text-decoration:none; font-size:15px; font-weight:500; }
  .nav-links a:hover{color:var(--line-white);}

  /* services dropdown: CSS only, no JS. :focus-within opens it from the
     keyboard because the toggle link is itself a descendant of the li,
     so tabbing to it reveals the submenu and the submenu links then
     become focusable in document order. */
  .nav-links .has-drop{ position:relative; }
  /* the caret is part of the word: without this it orphans to a second line
     in the narrow desktop band and doubles the nav height */
  .nav-links .drop-toggle{ white-space:nowrap; }
  /* the Locations toggle is a <button>: there is no /locations index page, so a
     real href would be misleading, and on touch a link navigates away instead
     of opening the menu. Focus still drives :focus-within, so it opens from the
     keyboard exactly like the Services toggle. */
  .nav-links button.drop-toggle{
    font-family:inherit; font-size:15px; font-weight:500; line-height:inherit;
    color:var(--line-dim); background:none; border:0; padding:0; margin:0;
    cursor:pointer;
  }
  .nav-links button.drop-toggle:hover{ color:var(--line-white); }
  .nav-links .drop-toggle::after{
    content:""; display:inline-block; margin-left:7px; vertical-align:2px;
    border-left:4px solid transparent; border-right:4px solid transparent;
    border-top:4px solid currentColor;
  }
  .nav-drop{
    display:none; position:absolute; top:100%; left:-18px; z-index:60;
    min-width:232px; margin:0; padding:8px 0; list-style:none;
    background:var(--blueprint-deep); border:1px solid #24435F; border-top:none;
  }
  .nav-links .has-drop:hover > .nav-drop,
  .nav-links .has-drop:focus-within > .nav-drop{ display:block; }
  /* bridges the 16px nav padding so the menu survives the pointer crossing it */
  .nav-links .has-drop::after{ content:""; position:absolute; left:0; right:0; top:100%; height:16px; }
  .nav-drop li{ display:block; }
  .nav-drop a{
    display:block; padding:9px 18px; font-size:14.5px; white-space:nowrap;
    border-left:2px solid transparent;
  }
  .nav-drop a:hover, .nav-drop a:focus-visible{ color:var(--line-white); border-left-color:var(--red); }

  /* mobile menu: <details> disclosure, no JS */
  .nav-mobile{ display:none; }
  .nav-mobile > summary{
    list-style:none; cursor:pointer; display:flex; align-items:center; gap:10px;
    font-family:'IBM Plex Mono', monospace; font-size:13px; letter-spacing:0.08em;
    color:var(--line-dim); padding:4px 2px;
  }
  .nav-mobile > summary::-webkit-details-marker{ display:none; }
  .nav-mobile > summary:focus-visible{ outline:3px solid var(--red); outline-offset:2px; }
  .nav-burger{ display:block; position:relative; width:22px; height:2px; background:var(--line-white); }
  .nav-burger::before, .nav-burger::after{
    content:""; position:absolute; left:0; width:22px; height:2px; background:var(--line-white);
    transition:transform 0.15s ease, top 0.15s ease;
  }
  .nav-burger::before{ top:-7px; }
  .nav-burger::after{ top:7px; }
  .nav-mobile[open] > summary .nav-burger{ background:transparent; }
  .nav-mobile[open] > summary .nav-burger::before{ top:0; transform:rotate(45deg); }
  .nav-mobile[open] > summary .nav-burger::after{ top:0; transform:rotate(-45deg); }
  /* The list is absolutely positioned against .nav, which is now sticky, so it
     travels WITH the bar instead of scrolling away with the page. At 18 items it
     is taller than a phone viewport, and before this cap the items below the fold
     were unreachable at any scroll position. The percentage in the calc resolves
     against the containing block (the nav's padding box), so this is exactly the
     space left under the bar; dvh keeps it honest as mobile browser chrome moves. */
  .nav-mobile-list{
    position:absolute; left:0; right:0; top:100%; z-index:70;
    margin:0; padding:10px 0 14px; list-style:none;
    background:var(--blueprint-deep); border-bottom:1px solid #24435F;
    max-height:calc(100vh - 100%);
    max-height:calc(100dvh - 100%);
    overflow-y:auto;
    overscroll-behavior:contain;
  }
  .nav-mobile-list a{
    display:block; padding:11px 32px; font-size:16px; font-weight:500;
    color:var(--line-dim); text-decoration:none; border-left:2px solid transparent;
  }
  .nav-mobile-list a:hover, .nav-mobile-list a:focus-visible{ color:var(--line-white); border-left-color:var(--red); }
  .nav-m-label{
    padding:14px 32px 6px; font-family:'IBM Plex Mono', monospace;
    font-size:12px; letter-spacing:0.09em; color:var(--line-dim);
  }
  .nav-m-sub a{ padding-left:48px; font-size:15px; }

  @media (max-width:600px){
    .nav-links{ display:none; }
    .nav-mobile{ display:block; }
  }

  /* ---------- HERO (photo band) ---------- */
  .hero{
    position:relative;
    background-color:var(--blueprint);
    /* end-stop 0.58 (was 0.5): at 0.5 the lede, which keeps its 0.94 opacity here,
       fell to 4.09:1 around 400px viewport. 0.58 is Tim's chosen value; he finds the
       banners dark already, so it is deliberately the lightest stop that clears AA,
       not the 0.68 the banners use. */
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.58) 100%),
      url('/images/hero.jpg');
    background-size:cover;
    background-position:center;
    color:var(--line-white);
    padding:110px 0 90px;
    border-bottom:6px solid var(--blueprint-deep);
  }
  .hero-corner{ position:absolute; width:26px; height:26px; border-color:var(--line-dim); opacity:0.6; }
  .hero-corner.tl{top:20px; left:20px; border-top:2px solid; border-left:2px solid;}
  .hero-corner.tr{top:20px; right:20px; border-top:2px solid; border-right:2px solid;}
  .hero-inner{max-width:600px;}
  /* homepage hero logo. Beside the text only where it fits without touching the
     600px text column or the hero height: flex-basis is its 170px-tall width, and
     it shrinks with the free space down to its 120px-tall width. 1013px is where
     600 + the 48px gap + the 120px-tall logo still fit inside a 17px classic
     scrollbar; narrower than that, phones included, it is hidden. */
  .hero-logo{ display:none; }
  @media (min-width:1013px){
    .hero .wrap{ display:flex; align-items:center; justify-content:space-between; gap:48px; }
    .hero-inner{ flex:0 0 600px; }
    .hero-logo{ display:block; flex:0 1 calc(170px * 802 / 340); min-width:calc(120px * 802 / 340); height:auto; }
  }
  .eyebrow-line{
    display:flex; align-items:center; gap:10px;
    font-family:'IBM Plex Mono', monospace; font-size:12.5px; color:var(--line-dim); margin-bottom:18px;
  }
  .eyebrow-line::before{ content:""; width:28px; height:1px; background:var(--line-dim); }
  .hero h1{ font-size:clamp(32px, 5.4vw, 50px); line-height:1.06; }
  .hero p.lede{ margin-top:20px; max-width:46ch; font-size:21px; color:var(--line-white); opacity:0.94; }
  .hero-ctas{margin-top:30px; display:flex; gap:14px; flex-wrap:wrap;}
  .btn{ display:inline-block; font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:16.5px; padding:14px 24px; text-decoration:none; border:2px solid transparent; }
  /* The closing band's email address is one unbreakable string, 318px wide at
     the normal size, so below 345px it ran past the right edge and every page
     scrolled sideways. Slightly smaller type and padding keep it on one line
     down to 320px. Scoped to the closing band and to 345px and below, so no
     button at any wider width moves. */
  @media (max-width:345px){ #contact .btn{ font-size:15px; padding:14px 20px; } }
  .btn-primary{background:var(--red); color:#fff; border-color:var(--red);}
  .btn-primary:hover{background:var(--red-deep); border-color:var(--red-deep);}
  .btn-ghost{color:var(--line-white); border-color:var(--line-dim);}
  .btn-ghost:hover{border-color:var(--line-white);}

  /* ---------- TITLE BLOCK ---------- */
  .titleblock{ background:var(--paper); border-bottom:1px solid var(--paper-line); }
  .tb-grid{ display:grid; grid-template-columns:repeat(4, 1fr); }
  .tb-cell{ border-right:1px solid var(--paper-line); padding:20px 18px; }
  .tb-cell:last-child{border-right:none;}
  .tb-label{ font-family:'IBM Plex Mono', monospace; font-size:12.5px; letter-spacing:0.08em; color:var(--ink-soft); margin-bottom:6px; }
  .tb-value{ font-family:'Big Shoulders Display', sans-serif; font-weight:700; font-size:24px; color:var(--blueprint); }
  @media (max-width:700px){ .tb-grid{grid-template-columns:repeat(2,1fr);} .tb-cell:nth-child(2){border-right:none;} }

  /* ---------- SECTIONS ---------- */
  section{padding:64px 0;}
  .section-head{margin-bottom:34px; max-width:60ch;}
  .kicker{ font-family:'IBM Plex Mono', monospace; font-size:14px; color:var(--red-deep); margin-bottom:10px; display:block; }
  h2{font-size:clamp(28px,3.6vw,38px); color:var(--blueprint);}
  .section-head p{color:var(--ink-soft); margin-top:12px; font-size:19px; max-width:56ch;}

  /* services list */
  .svc-list{list-style:none; margin:0; padding:0;}
  .svc-list li{ display:flex; gap:16px; padding:20px 0; border-top:1px solid var(--paper-line); }
  .svc-list li:last-child{border-bottom:1px solid var(--paper-line);}
  .svc-mark{flex:none; width:26px; height:26px; margin-top:2px;}
  .svc-body h3{font-size:22px; font-weight:600; font-family:'IBM Plex Sans'; color:var(--ink);}
  /* a linked card heading keeps the heading's own colour and gains the house
     red underline on hover; the whole heading is the hit area */
  .svc-body h3 a{ color:inherit; text-decoration:none; border-bottom:2px solid transparent; }
  .svc-body h3 a:hover{ border-bottom-color:var(--red); }
  .svc-body h3 a:focus-visible{ outline:3px solid var(--red); outline-offset:3px; }
  .svc-body p{margin:6px 0 0; color:var(--ink-soft); font-size:18px; max-width:58ch;}

  /* why on-site: text + true-position diagram */
  .why{background:#fff; border-top:1px solid var(--paper-line); border-bottom:1px solid var(--paper-line);}
  .why-grid{display:grid; grid-template-columns:1fr 230px; gap:44px; align-items:center;}
  @media (max-width:700px){ .why-grid{grid-template-columns:1fr;} .why-art{order:-1; max-width:190px; margin:0 auto;} }
  .why p.sub{margin-top:20px; color:var(--ink-soft); font-size:19px; max-width:60ch;}
  .why p.sub + p.sub{margin-top:14px;}
  .why-art svg{width:100%; height:auto; display:block;}

  /* rate frame: fixed alignment */
  .rate-frame{
    display:flex; align-items:stretch;
    border:2px solid var(--blueprint);
    width:100%; max-width:700px;
  }
  .rate-cell{ display:flex; align-items:center; padding:22px 24px; border-right:2px solid var(--blueprint); }
  .rate-cell:last-child{border-right:none;}
  .rate-cell.sym{ justify-content:center; flex:0 0 70px; padding:22px 10px; }
  .rate-cell.num{ flex:0 0 auto; }
  .rate-cell.note{ flex:1 1 auto; }
  .rate-num{ font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:38px; color:var(--blueprint); line-height:1; white-space:nowrap; font-variant-numeric:tabular-nums; }
  .rate-num small{font-size:16px; font-weight:500; color:var(--ink-soft);}
  .rate-note{ font-family:'IBM Plex Sans'; font-size:17px; color:var(--ink-soft); white-space:nowrap; }
  .rate-footnote{margin-top:18px; color:var(--ink-soft); font-size:17px;}
  @media (max-width:560px){
    .rate-frame{flex-direction:column; max-width:100%;}
    .rate-cell{border-right:none; border-bottom:2px solid var(--blueprint); width:100%;}
    .rate-cell:last-child{border-bottom:none;}
    .rate-cell.sym{flex:none; padding:16px;}
  }

  /* industries: photo tiles */
  .industry-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:24px; margin-top:8px; }
  @media (max-width:640px){ .industry-grid{grid-template-columns:1fr;} }
  .industry-tile{ margin:0; }
  .industry-tile img{
    width:100%; aspect-ratio:4/3; object-fit:cover; display:block;
    border:2px solid var(--blueprint);
  }
  .industry-tile figcaption{
    margin-top:10px; font-family:'IBM Plex Mono', monospace; font-size:14px;
    letter-spacing:0.04em; color:var(--ink-soft); text-align:center;
  }

  /* about */
  .about p{color:var(--ink-soft); font-size:19px; max-width:62ch;}
  .about p + p{margin-top:14px;}
  .about-grid{display:grid; grid-template-columns:1fr 220px; gap:32px; align-items:start;}
  .about-timeline{display:flex; flex-direction:column; gap:18px;}
  .about-timeline img{width:100%; height:auto; display:block; border:2px solid var(--blueprint);}
  .about-timeline figcaption{margin-top:8px; font-family:'IBM Plex Mono', monospace; font-size:12.5px; letter-spacing:0.05em; color:var(--ink-soft); text-align:center;}
  @media (max-width:700px){
    .about-grid{grid-template-columns:1fr;}
    .about-timeline{flex-direction:row; flex-wrap:wrap; justify-content:center; gap:16px; margin-top:28px;}
    .about-timeline figure{width:140px; margin:0;}
  }

  /* faq - native <details> accordions, no JS.
     summary keeps the old dt treatment, .faq-answer keeps the old dd treatment,
     and the row separators stay where the dt border-tops used to be. */
  .faq-list{border-bottom:1px solid var(--paper-line); margin:0;}
  .faq-list details{border-top:1px solid var(--paper-line);}
  .faq-list details:first-of-type{border-top:none;}
  .faq-list summary{
    display:flex; align-items:flex-start; justify-content:space-between; gap:20px;
    font-weight:600; font-size:20px; color:var(--ink);
    padding:20px 0; margin:0; cursor:pointer;
    list-style:none; /* suppress the default disclosure triangle */
  }
  .faq-list summary::-webkit-details-marker{display:none;}
  .faq-list details:first-of-type summary{padding-top:0;}
  /* closed, the summary carries the 20px that the answer used to contribute, so the
     separator stays centred between rows; open, it drops to the old dd margin-top */
  .faq-list details[open] summary{padding-bottom:8px;}
  /* custom indicator, right-aligned: + closed, minus sign open */
  .faq-list summary::after{
    content:"+";
    flex:none;
    font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:20px;
    color:var(--red-deep);
  }
  .faq-list details[open] summary::after{content:"\2212";}
  .faq-list summary:focus-visible{outline:3px solid var(--red); outline-offset:2px;}
  .faq-answer{margin:0 0 20px; color:var(--ink-soft); font-size:18px; max-width:60ch;}
  /* an answer whose supporting detail runs to a second paragraph */
  .faq-answer p{ margin:0; }
  .faq-answer p + p{ margin-top:12px; }

  /* numbered process steps (service pages) */
  .process-list{list-style:none; counter-reset:step; margin:0; padding:0;}
  .process-list li{
    counter-increment:step;
    display:flex; gap:18px; padding:20px 0;
    border-top:1px solid var(--paper-line);
  }
  .process-list li:last-child{border-bottom:1px solid var(--paper-line);}
  .process-list li::before{
    content:counter(step);
    flex:none; width:38px; height:38px;
    display:flex; align-items:center; justify-content:center;
    border:2px solid var(--blueprint);
    font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:16px;
    color:var(--blueprint); line-height:1;
  }
  .process-body h3{font-size:22px; font-weight:600; font-family:'IBM Plex Sans'; color:var(--ink);}
  .process-body p{margin:6px 0 0; color:var(--ink-soft); font-size:18px; max-width:58ch;}

  /* band-blue: reusable full-blue section treatment (contact, travel, etc.) / footer */
  .band-blue{ background:var(--blueprint); color:var(--line-white); }
  .band-blue h2{color:var(--line-white);}
  .band-blue p.lede{color:var(--line-dim); max-width:50ch; margin-top:12px; font-size:19px;}
  .band-blue .hero-ctas{margin-top:26px;}
  /* inline link inside a blue band: the default link blue is invisible on it */
  .band-blue p.lede a{ color:var(--line-white); font-weight:600; text-decoration:none; border-bottom:2px solid var(--red); }
  .band-blue p.lede a:hover{ color:#fff; border-bottom-color:var(--line-white); }

  /* closing contact band logo, decorative (alt="", aria-hidden). Stacked under the
     button, left-aligned, by default. Beside the copy from 1080px: the narrowest
     width where the longest band heading (the city pages) still clears the
     120px-tall logo plus a 48px gap, measured with a 15px scrollbar, so no text
     rewraps. max-width only bites below ~347px, where the column is narrower than
     the logo; object-fit then scales the artwork inside the 120px box, left-aligned,
     rather than distort it or scroll sideways. */
  /* the logo links home for pointer users only: tabindex -1 and aria-hidden keep
     it decorative, since the nav name already gives keyboard and screen-reader
     users that link. max-content keeps the hit area to the logo itself. */
  .band-logo-link{ display:block; width:max-content; max-width:100%; margin-top:32px; }
  .band-logo{ display:block; height:120px; width:auto; max-width:100%; object-fit:contain; object-position:left center; }
  @media (min-width:1080px){
    #contact .wrap{ display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:48px; }
    #contact .wrap > *{ grid-column:1; }
    #contact .wrap > .band-logo-link{ grid-column:2; grid-row:1 / span 4; align-self:center; margin-top:0; }
    /* grid items do not collapse margins: without this the lede's 1em bottom
       margin would add to the button's 26px top margin instead of merging */
    #contact .wrap > p.lede{ margin-bottom:0; }
  }

  .sheet-footer{ background:var(--blueprint-deep); color:var(--line-dim); font-family:'IBM Plex Mono', monospace; font-size:13.5px; }
  .sheet-footer .wrap{ display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px; padding:16px 28px; }

  /* footer links row (shared across pages). Two groups, pages then locations, so
     the locations always start a line of their own instead of wherever the wrap
     happens to fall; each group still wraps by itself on narrow screens. The
     22px gap between groups matches the gap between wrapped lines. */
  .footer-links{ background:var(--blueprint-deep); border-bottom:1px solid #1B3A56; }
  .footer-links .wrap{ display:flex; flex-direction:column; gap:22px; padding:14px 28px; }
  .footer-group{ display:flex; flex-wrap:wrap; gap:22px; }
  .footer-links a{ font-family:'IBM Plex Mono', monospace; font-size:13px; color:var(--line-dim); text-decoration:none; letter-spacing:0.03em; }
  .footer-links a:hover{ color:var(--line-white); }

  /* footer legal row: a separate line rather than more items in the sitemap
     block, so the sitemap block's wrapping at 375px never strands it */
  .footer-legal{ background:var(--blueprint-deep); border-bottom:1px solid #1B3A56; }
  .footer-legal .wrap{ display:flex; gap:22px; padding:10px 28px; flex-wrap:wrap; }
  .footer-legal a{ font-family:'IBM Plex Mono', monospace; font-size:13px; color:var(--line-dim); text-decoration:none; letter-spacing:0.03em; }
  .footer-legal a:hover{ color:var(--line-white); }

  /* page header band (secondary pages) */
  .page-header{
    position:relative;
    background-color:var(--blueprint);
    color:var(--line-white);
    padding:64px 0 56px;
    border-bottom:6px solid var(--blueprint-deep);
  }
  /* service-page banner variants: same gradient-over-photo pattern as .hero.
     Sources are small, so a 2px blur is baked into each jpg and they read as
     atmosphere rather than detail. Overlay opacity is tuned per image so the
     headline keeps its contrast. */
  .page-header.banner{
    background-size:cover;
    background-position:center;
    background-repeat:no-repeat;
  }
  /* 0.68 rather than the hero's 0.58 tail: measured across all five images, it
     is what keeps the 19px lede (normal-size text) above 4.5:1 at 375px, where
     cover crops hardest into the bright corner. The lede's 0.92 softening is
     also dropped here; it reads as intended on the flat blue headers but costs
     contrast over a photo. */
  .page-header.banner p.lede{ opacity:1; }
  .page-header.banner-flagship{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/flagship.jpg');
  }
  .page-header.banner-contract{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/contract.jpg');
  }
  .page-header.banner-offline{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/offline.jpg');
  }
  .page-header.banner-fai{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/fai.jpg');
  }
  .page-header.banner-training{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/training.jpg');
  }
  .page-header.banner-measuremax{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/measuremax.jpg');
  }
  .page-header.banner-calypso{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/calypso.jpg');
  }
  /* city banners: same 0.68 overlay, but the sources are high-resolution, so no
     blur is baked in. Detail is legible and intended here. Per-image provenance
     and licensing are recorded in CLAUDE.md under Assets. */
  .page-header.banner-indianapolis{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/indianapolis.jpg');
  }
  .page-header.banner-socal{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/socal.jpg');
  }
  .page-header.banner-san-diego{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/san-diego.jpg');
  }
  .page-header.banner-dallas{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/dallas.jpg');
  }
  .page-header.banner-chicago{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/chicago.jpg');
  }
  .page-header.banner-cleveland{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/cleveland.jpg');
  }
  .page-header.banner-cincinnati{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/cincinnati.jpg');
  }
  .page-header.banner-houston{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/houston.jpg');
  }
  .page-header.banner-st-louis{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/st-louis.jpg');
  }
  .page-header.banner-minneapolis{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/minneapolis.jpg');
  }
  .page-header.banner-phoenix{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/phoenix.jpg');
  }
  .page-header.banner-milwaukee{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/milwaukee.jpg');
  }
  .page-header.banner-florida{
    background-image:
      linear-gradient(100deg, rgba(13,33,56,0.94) 30%, rgba(13,33,56,0.68) 100%),
      url('/images/banners/florida.jpg');
  }
  /* Eyebrow colour on PHOTO headers only. .eyebrow-line's default var(--line-dim)
     (#9FB4C8) is 12.5px, which is normal-size text needing 4.5:1, and it was the
     weakest of the three header text roles over a photo: measured worst cases ran
     3.87 (houston) to 6.23 (dallas), so five of the eight city banners failed AA.
     #B5C5D6 clears 4.5:1 at every width on every banner except the two below,
     with the photos and the 0.68 end-stop left alone. Scoped to .page-header and
     .hero deliberately: the --line-dim token is unchanged, so nav, footer and
     kickers keep their colour. */
  .page-header .eyebrow-line,
  .hero .eyebrow-line{ color:#B5C5D6; }
  .page-header .eyebrow-line::before,
  .hero .eyebrow-line::before{ background:#B5C5D6; }
  /* Two of the 2026-10-22 banners put blown highlights (a bright cloud sky, a lit
     skyline) under the right end of the eyebrow, where the overlay has thinned
     toward 0.68, so the shared colour measured below 4.5:1 at some widths (sweep
     of every width 320-1920): St Louis 4.25 at 471px, 52 failing widths between
     470 and 523px; Minneapolis 4.33 at 529px, 6 failing widths, 529-534px. Each
     gets a lighter eyebrow on its own page only, Tim's pick, and now measures
     5.18 (St Louis) and 5.66 (Minneapolis) at its worst width. */
  .page-header.banner-st-louis .eyebrow-line{ color:#CCD8E4; }
  .page-header.banner-st-louis .eyebrow-line::before{ background:#CCD8E4; }
  .page-header.banner-minneapolis .eyebrow-line{ color:#D5DFEA; }
  .page-header.banner-minneapolis .eyebrow-line::before{ background:#D5DFEA; }
  .page-header h1{ font-size:clamp(32px, 5vw, 46px); line-height:1.08; white-space:nowrap; }
  /* long headlines (service pages) wrap instead of forcing one line */
  .page-header h1.allow-wrap{ white-space:normal; }
  .page-header p.lede{ margin-top:16px; max-width:52ch; font-size:19px; color:var(--line-white); opacity:0.92; }

  /* pricing tier cards */
  .tier-grid{ display:grid; grid-template-columns:repeat(2,1fr); gap:24px; margin-top:8px; }
  @media (max-width:800px){ .tier-grid{grid-template-columns:1fr; max-width:440px; margin-left:auto; margin-right:auto;} }
  .tier-card{ border:2px solid var(--blueprint); padding:30px 28px; position:relative; overflow:visible; }
  .tier-card.featured{ border-color:var(--red); }
  .tier-tag{
    position:absolute; top:-12px; left:50%; transform:translateX(-50%);
    background:var(--paper); padding:2px 14px; white-space:nowrap;
    font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.06em; color:var(--red-deep);
  }
  .tier-label{ font-family:'IBM Plex Mono', monospace; font-size:14px; letter-spacing:0.08em; color:var(--ink-soft); margin-bottom:14px; }
  .tier-price{ font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:40px; color:var(--blueprint); line-height:1; font-variant-numeric:tabular-nums; }
  .tier-price small{ font-size:16px; font-weight:500; color:var(--ink-soft); }
  .tier-effective{ margin-top:8px; font-family:'IBM Plex Sans', sans-serif; font-size:14px; color:var(--ink-soft); font-variant-numeric:tabular-nums; }
  .tier-desc{ margin-top:16px; font-size:16.5px; color:var(--ink-soft); }

  /* disclaimer / fine-print note */
  .note-box{ border-left:3px solid var(--ink-soft); padding-left:22px; margin-top:32px; }
  .note-box p{ font-size:15.5px; color:var(--ink-soft); max-width:68ch; margin:0; }
  .note-box p + p{ margin-top:10px; }

  /* special callout (red accent, used sparingly) */
  .special-callout{ border:2px solid var(--red); padding:24px 28px; margin-top:24px; }
  .special-callout .label{ font-family:'IBM Plex Mono', monospace; font-size:13px; letter-spacing:0.07em; color:var(--red-deep); margin-bottom:10px; display:block; }
  .special-callout p{ font-size:17px; color:var(--ink); margin:0; }

  /* compact two-column expense list */
  .expense-list{ list-style:none; margin:18px 0 0; padding:0; columns:2; column-gap:36px; }
  .expense-list li{ font-size:17px; color:var(--ink-soft); padding:7px 0; break-inside:avoid; }
  @media (max-width:560px){ .expense-list{columns:1;} }

  /* rate teaser link (homepage) */
  .rate-more{ margin-top:16px; font-size:18px; color:var(--ink-soft); }
  .rate-more a{ font-weight:600; color:var(--blueprint); text-decoration:none; border-bottom:2px solid var(--red); }
  .rate-more a:hover{ color:var(--red-deep); }

  /* wraps on mobile, forces one line once there's room */
  .nowrap-desktop{ white-space:normal; }
  @media (min-width:640px){ .nowrap-desktop{ white-space:nowrap; } }

  /* ---------- 404 PAGE ONLY (scoped: nothing here applies elsewhere) ---------- */
  .notfound{ text-align:center; }
  .notfound-fig{ margin:0; }
  /* cap the image, not the figure, so the caption can sit on one line */
  .notfound-fig img{
    display:block; margin:0 auto; width:100%; max-width:320px; height:auto;
    border:2px solid var(--blueprint);
  }
  /* matches .page-header p.lede, minus its opacity (that softens white
     text on the blue band and would wash out dark text on paper) */
  .notfound-fig figcaption{
    margin-top:14px; font-family:'IBM Plex Sans', system-ui, sans-serif;
    font-size:19px; letter-spacing:normal; color:var(--ink);
  }
  .notfound-back{ margin-top:30px; }

  /* ---------- /MEASUREMAX FIGURES ONLY (scoped: nothing here applies elsewhere) ----------
     The machine pair sits side by side at one matched height, 238px: the 1808 photo
     is 171x238, so that is its native size and it is never enlarged. The RS-50 is
     scaled down to the same height. Stacked below 480px, where the pair no longer
     fits one row. The splash screen runs up to the section column (about 720px) and
     the full column on a phone. */
  .mm-pair{ display:flex; flex-wrap:wrap; gap:20px; margin:26px 0 8px; align-items:flex-start; }
  .mm-pair figure{ margin:0; }
  .mm-pair img{ display:block; height:238px; width:auto; max-width:100%; border:2px solid var(--blueprint); }
  .mm-splash{ margin:26px 0 8px; max-width:720px; }
  .mm-splash img{ display:block; width:100%; height:auto; border:2px solid var(--blueprint); }
  .mm-pair figcaption, .mm-splash figcaption{
    margin-top:8px; font-family:'IBM Plex Mono', monospace; font-size:12.5px; letter-spacing:0.05em; color:var(--ink-soft);
  }
  @media (max-width:480px){ .mm-pair{ flex-direction:column; } }

  /* ---------- LEGAL LONG-FORM (disclaimer, terms, service agreement) ----------
     A contract is not a marketing page. These documents get their own density:
     16px body on tight leading, minimal list padding, and section gaps about
     half the site's usual rhythm, so the agreement reads as the legal
     instrument it is rather than scrolling like a brochure. The measure is set
     below in ch against the container's own 16px, which works out to a ~91
     character contract column. Everything here is scoped inside .legal-doc and
     applies nowhere else on the site. */
  /* font-size on the container, not just its children: `ch` resolves against
     the element's own font-size, so without this the 92ch measure was being
     computed against the 20px body and the column ran to the full wrap width
     (114 characters a line). At 16px, 92ch is a ~93 character contract column. */
  .legal-doc{ font-size:16px; max-width:92ch; }
  .legal-doc p{ font-size:16px; line-height:1.3; color:var(--ink-soft); margin:0 0 7px; }
  .legal-doc p strong{ color:var(--ink); }
  /* a fill-in blank written as a run of underscores is one unbreakable token
     (33 of them are ~295px bold, ~299px regular); let a paragraph break a token
     that cannot fit, so a phone narrower than ~331px never scrolls sideways.
     Nothing else in the legal documents has an unbreakable token wider than its
     column, so no existing line moves. */
  .legal-doc p{ overflow-wrap:anywhere; }
  /* the body cites full URLs, which are single unbreakable tokens; let them
     wrap so a narrow phone never gets a sideways scroll */
  .legal-doc a{
    color:var(--blueprint); font-weight:500; text-decoration:none;
    border-bottom:1px solid var(--paper-line); overflow-wrap:anywhere;
  }
  .legal-doc a:hover{ border-bottom-color:var(--red); }
  .legal-doc ul, .legal-doc ol{ margin:0 0 7px; padding-left:21px; }
  .legal-doc li{ font-size:16px; line-height:1.3; color:var(--ink-soft); padding:0; margin:0 0 1px; }

  /* the terms are accepted at the "version effective as of the quotation date",
     so the date these pages state is operative text, not decoration */
  .legal-version{
    font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.07em;
    color:var(--ink-soft); margin:0 0 16px; padding-bottom:9px;
    border-bottom:1px solid var(--paper-line);
  }
  /* the agreement's formal title, below the page h1 */
  .legal-doctitle{ font-size:20px; line-height:1.15; color:var(--blueprint); margin:0 0 12px; }
  /* numbered sections: gaps roughly halved against the old 34/18/14 rhythm */
  .legal-doc .legal-sec{
    font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:15px;
    letter-spacing:0.02em; line-height:1.24; color:var(--blueprint);
    margin:12px 0 5px; padding-top:7px; border-top:1px solid var(--paper-line);
  }
  /* a kicker labels the section that follows it, so on pages that use one the
     section rule moves up onto the kicker and the heading drops its own */
  .legal-doc .kicker{
    font-size:12.5px; margin:12px 0 3px; padding-top:7px;
    border-top:1px solid var(--paper-line);
  }
  .legal-doc > .kicker:first-child{ margin-top:0; padding-top:0; border-top:none; }
  .legal-doc .kicker + .legal-sec{ margin-top:0; padding-top:0; border-top:none; }
  /* the all-caps liability blocks. Caps at full body size is a wall; a notch
     down with a little extra leading keeps them readable while they stay
     visibly the emphatic passages they are. */
  .legal-doc p.legal-caps{ font-size:13.5px; line-height:1.42; letter-spacing:0.015em; color:var(--ink); }

  /* download link, floated into the white space beside the opening and closing
     of the document; stacks above the text once the column gets narrow */
  .doc-download{ float:right; margin:0 0 10px 22px; }
  .doc-download a{
    display:inline-block; font-family:'IBM Plex Mono', monospace; font-size:12.5px;
    letter-spacing:0.04em; color:var(--blueprint); text-decoration:none;
    border:1px solid var(--paper-line); border-left:3px solid var(--red);
    padding:8px 14px; background:#fff; white-space:nowrap;
  }
  .doc-download a:hover{ border-color:var(--blueprint); border-left-color:var(--red); }
  .doc-download.bottom{ margin:14px 0 0 22px; }
  @media (max-width:620px){
    .doc-download{ float:none; margin:0 0 14px; }
    .doc-download.bottom{ margin:16px 0 0; }
    .doc-download a{ display:block; text-align:center; white-space:normal; }
  }

  /* acceptance block: the signature section that closes the agreement, on the
     page and in the PDF. Fill-in lines are ruled elements rather than runs of
     underscores, which cannot wrap and would blow out a narrow column. */
  .accept-block{ margin-top:24px; padding-top:14px; border-top:2px solid var(--blueprint); clear:both; }
  .accept-block h3{
    font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:15.5px;
    letter-spacing:0.06em; color:var(--blueprint); margin:0 0 8px;
  }
  .accept-grid{ display:grid; grid-template-columns:1fr 1fr; gap:0 32px; margin-top:16px; }
  /* the widest pre-filled value needs ~350px on one line, which two columns
     only afford above about 820px; below that the block stacks */
  /* screen only: a printed page is ~720px wide, and this must not flatten the
     signature table in the PDF, where two columns do fit at 9.5pt */
  @media screen and (max-width:820px){ .accept-grid{ grid-template-columns:1fr; gap:26px; } }
  .accept-party{ min-width:0; }
  .accept-party .party{
    font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.08em;
    color:var(--red-deep); padding-bottom:6px; margin-bottom:12px;
    border-bottom:1px solid var(--paper-line);
  }
  /* a long party label (a company name with its d/b/a) wraps in a half-width
     column at the usual tracking, which drops that column's rows below its
     neighbor's; no tracking keeps it on one line (346px against a ~355px column
     at 821px, scrollbar included), on screen and in print */
  .accept-party .party.party-tight{ letter-spacing:0; }
  .sig-row{ margin-bottom:14px; }
  /* min-height, not height: an empty rule and a single-line filled rule are
     both exactly 1.5em, which is what keeps the two columns row-aligned, but
     a pre-filled value that wraps pushes its own box open instead of
     printing over the label beneath it. */
  .sig-rule{
    /* content-box so min-height measures the writing line itself, not the line
       plus its border. Under the sitewide border-box an empty rule came out
       1px shorter than a filled one and the two columns drifted apart. */
    box-sizing:content-box;
    font-size:15px; min-height:1.5em; line-height:1.5em;
    border-bottom:1px solid var(--ink-soft);
  }
  /* a line that is pre-filled on the provider side prints its value on the rule */
  .sig-rule.filled{ color:var(--ink); }
  .sig-label{
    display:block; margin-top:4px; font-family:'IBM Plex Sans', sans-serif;
    font-size:12px; letter-spacing:0.03em; color:var(--ink-soft);
  }

  /* ---------- PRINT: legal pages only ----------
     The agreement is also published as a PDF generated from this stylesheet by
     headless print-to-PDF, so these rules are the PDF's layout. Scoped to
     body.legal-page; no other page is affected. */
  @media print{
    body.legal-page{ background:#fff; color:#000; font-size:12pt; }
    body.legal-page .nav,
    body.legal-page .band-blue,
    body.legal-page .footer-links,
    body.legal-page .footer-legal,
    body.legal-page .sheet-footer,
    body.legal-page .doc-download{ display:none; }
    /* the header band keeps its h1 so the document is titled, and loses the
       blue, the eyebrow and the marketing lede */
    body.legal-page .page-header{
      background:#fff; color:#000; padding:0 0 10pt;
      border-bottom:1px solid #000; border-top:none;
    }
    body.legal-page .page-header .eyebrow-line,
    body.legal-page .page-header p.lede{ display:none; }
    body.legal-page .page-header h1{ font-size:16pt; color:#000; white-space:normal; }
    body.legal-page section{ padding:0; }
    body.legal-page .wrap{ max-width:none; padding:0; }
    body.legal-page .legal-doc{ max-width:none; }
    body.legal-page .legal-doc p,
    body.legal-page .legal-doc li{ font-size:9.5pt; line-height:1.34; color:#000; margin-bottom:4pt; }
    body.legal-page .legal-doc li{ margin-bottom:1.5pt; }
    body.legal-page .legal-doc p.legal-caps{ font-size:8.5pt; line-height:1.32; }
    body.legal-page .legal-doc .legal-sec{
      font-size:10pt; color:#000; margin:7pt 0 3pt; padding-top:4pt; break-after:avoid;
    }
    body.legal-page .legal-doctitle{ font-size:13pt; color:#000; margin-bottom:9pt; }
    body.legal-page .legal-version{ font-size:8.5pt; margin-bottom:10pt; padding-bottom:5pt; }
    body.legal-page .legal-doc .kicker{ font-size:8pt; color:#000; margin:7pt 0 2pt; padding-top:4pt; }
    body.legal-page .legal-doc > .kicker:first-child{ margin-top:0; padding-top:0; border-top:none; }
    /* the signature section must not be split across a page break, and must not
       be orphaned from its heading */
    body.legal-page .accept-block{
      break-inside:avoid; page-break-inside:avoid; break-before:auto;
      margin-top:14pt; padding-top:8pt; border-top:1.5pt solid #000;
    }
    body.legal-page .accept-block h3{ font-size:11pt; color:#000; break-after:avoid; }
    body.legal-page .accept-grid{ gap:0 24pt; margin-top:10pt; }
    body.legal-page .accept-party .party{ font-size:8.5pt; color:#000; margin-bottom:9pt; }
    body.legal-page .sig-row{ margin-bottom:11pt; break-inside:avoid; }
    body.legal-page .sig-rule{ box-sizing:content-box; font-size:9.5pt; min-height:1.6em; line-height:1.6em; border-bottom:0.75pt solid #000; }
    body.legal-page .sig-rule.filled{ color:#000; }
    body.legal-page .sig-label{ font-size:8pt; color:#000; }
    body.legal-page h1, body.legal-page h2, body.legal-page h3{ break-after:avoid; }
    /* keep-with-next, so a page never closes on a stranded lead-in or label. A
       paragraph that leads into a list ("...to the best of its knowledge:") stays
       with the first lines of that list, and a kicker stays with the heading it
       labels. The headings above already carry break-after:avoid, so none can be
       the last thing on a page. Where the list runs on as a plain paragraph of
       semicolon-separated items (agreement sections 2, 10 and 11) no selector can
       tell its lead-in from any other paragraph, so those lead-ins carry
       .legal-leadin in the markup. */
    body.legal-page .legal-doc p + ul,
    body.legal-page .legal-doc p + ol{ break-before:avoid; }
    body.legal-page .legal-doc p.legal-leadin,
    body.legal-page .legal-doc .kicker{ break-after:avoid; }
  }
