/* ==================================================================
   ZIP-Codes.com PRODUCT SYSTEM v5
   Shared look for product pages: ZIP Code Database, ZIP+4, Canadian,
   Boundary, Area Code (and their sub-pages).

   Extracted 2026-08-10 from free-zip-code-database.v5.1.asp.
   Spec: docs/superpowers/specs/2026-08-10-product-system-v5-extraction-design.md

   ------------------------------------------------------------------
   THE THREE RULES - read before adding anything
   ------------------------------------------------------------------
   1. EVERY selector begins with .zcp5 (the page scope class, set on
      <body>). No bare global selectors. Unscoped globals are exactly
      what made products.css leak across the whole site.

   2. NEVER style site chrome. #top-nav and the site footer belong to
      the site theme, not to this system. The button system in section 2
      carries a :not(#top-nav *) guard for this reason.
      History: without that guard, the page-wide .btn-primary reset
      flattened the header's Login button (purple #5053b0, set by .mr-22
      in style.css) and phone button (green #406020, from .btn-primary)
      to black-on-white. Do not remove the guard.

   3. SECTION 5 CLASS NAMES ARE A CONTRACT WITH products.js.
      It binds #modal-purchase, #license-tabs, #proceed-checkout,
      #product-class, #product-name, .term-option, .single-option,
      .selected, .month-selector. Section 5 may be RE-SCOPED but never
      renamed or redesigned.

   ------------------------------------------------------------------
   SECTION ORDER - put new work in the right section, not at the end
   ------------------------------------------------------------------
     1. TOKENS        2. PRIMITIVES     3. LAYOUT
     4. COMPONENTS    5. PURCHASE       6. UTILITIES     7. RESPONSIVE
   ================================================================== */


/* ==================================================================
   1. TOKENS
   ================================================================== */
.zcp5{
  --zcp-ink:#0f172a;
  --zcp-mut:#64748b;
  --zcp-line:#e2e8f0;
  --zcp-navy:#091122;
  --zcp-accent:#0ea5e9;
  --zcp-go:#3d9c40;

  /* TYPE SCALE. Three sizes, and components reference these rather than
     inventing their own. --zcp-fs is the body size for section content;
     -sm is for supporting text (labels, spec values, list items); -xs is
     for the quiet stuff (meta lines, captions, tags). */
  --zcp-fs:.86rem;
  --zcp-fs-sm:.78rem;
  --zcp-fs-xs:.73rem;
}

/* ------------------------------------------------------------------
   ONE TYPE BASE, INHERITED.
   Content ported from older pages carries no size of its own, so it
   fell back to the site's 1rem while everything written for v5.1 set
   its own .82-.86rem - two type sizes on one page, and no single place
   to fix it.

   Setting the base HERE and letting inheritance do the work means new
   markup needs no font-size at all: write a <p> and it is already
   right. Components that genuinely need a different size (the data
   dictionary, chips) still declare one, and a declared value always
   beats an inherited one - so this cannot fight them.

   Deliberately NOT setting `color` or heading sizes: dark sections set
   their own color on the section element, and heading sizes come from
   .display-* utilities that this would outrank.
   ------------------------------------------------------------------ */
.zcp5 section{ font-size:var(--zcp-fs); line-height:1.6; }

/* section lede - the line under an h2. Same everywhere, so it stops
   being re-specified inline on every section. */
.zcp5 .zcp-lede-sm{
  font-size:var(--zcp-fs); color:var(--zcp-mut); line-height:1.6; max-width:62rem;
}


/* ==================================================================
   2. PRIMITIVES
   ================================================================== */
.zcp5 .zcp-kick{
  font-size:.68rem; letter-spacing:.15em; text-transform:uppercase;
  opacity:.85; margin-bottom:.6rem;
}
.zcp5 .zcp-cta{
  display:inline-block; padding:.7rem 1.35rem; border-radius:.45rem;
  font-size:1rem; font-weight:700; text-decoration:none;
  background:var(--zcp-go); color:#fff; border:0;
}
.zcp5 .zcp-cta:hover{ filter:brightness(1.08); color:#fff; }
.zcp5 .zcp-undercta{ font-size:.72rem; opacity:.75; margin-top:.55rem; }

/* ------------------------------------------------------------------
   ONE BUTTON SYSTEM.
   Product pages inherit green, orange, black, red (.btn-primary) and
   .btn-success all acting as buttons - five colors competing for the
   same eye. Here: green means "go" and is reserved for real conversion
   actions; everything else is a calm neutral so it reads as secondary
   instead of shouting.
   (Small jump-nav pills are navigation, not buttons - left alone.)

   SCOPE: page content only. See RULE 2 in the file header - the
   :not(#top-nav *) guard keeps this out of the site header.
   ------------------------------------------------------------------ */
.zcp5 .button.green:not(#top-nav *),
.zcp5 .btn-success:not(#top-nav *){
  background:var(--zcp-go) !important; border-color:var(--zcp-go) !important;
  color:#fff !important;
}
.zcp5 .button.green:not(#top-nav *):hover,
.zcp5 .btn-success:not(#top-nav *):hover{ filter:brightness(1.08); color:#fff !important; }

.zcp5 .button.orange:not(#top-nav *),
.zcp5 .button.black:not(#top-nav *),
.zcp5 .button.blue:not(#top-nav *),
.zcp5 .btn-primary:not(.btn-close):not(#top-nav *),
.zcp5 .btn-secondary:not(#top-nav *){
  background:#fff !important;
  border:1.5px solid #cbd5e1 !important;
  color:var(--zcp-ink) !important;
  box-shadow:none !important;
}
.zcp5 .button.orange:not(#top-nav *):hover,
.zcp5 .button.black:not(#top-nav *):hover,
.zcp5 .button.blue:not(#top-nav *):hover,
.zcp5 .btn-primary:not(.btn-close):not(#top-nav *):hover,
.zcp5 .btn-secondary:not(#top-nav *):hover{
  background:#f1f5f9 !important; border-color:#94a3b8 !important;
  color:var(--zcp-ink) !important;
}


/* ------------------------------------------------------------------
   2.1 PRODUCT BAR
   Adopts the /api portal-api-bar pattern (wwwroot/css/portal.css on the
   API site) so a product page reads as its own dedicated product, not a
   page buried in the catalog. Tokens copied from that file verbatim:
   background #f8f4f3, 1px #e8eaee rule, 52px min-height, 1320px inner.

   It replaces THREE stacked rows on the old page - breadcrumbs, the
   product-page tabs, and the "Jump to:" strip - with one:
     · the breadcrumb doubles as the bar's brand/identity (left)
     · product-page links sit where the API's page links sit (right)
     · in-page jumps collapse into an "On this page" disclosure, so they
       cost one control instead of a whole row, and simply do not render
       on sub-pages that have no sections.

   Sticky is opt-in: add .is-sticky. It is off by default because the
   site's own #top-nav is already sticky-top and the two would overlap;
   --zcp-topnav-h is the offset to sit beneath it.
   ------------------------------------------------------------------ */
.zcp5 .zcp-bar{
  background:#f8f4f3; border-bottom:1px solid #e8eaee;
  box-shadow:0 1px 3px rgba(0,0,0,.06); position:relative;
  /* MUST stay below the site header. Do not assume Bootstrap's 1020 here -
     this site overrides #top-nav to z-index:9, so anything in the 1000s
     paints ON TOP of the header the moment the two overlap. 8 keeps the bar
     tucked underneath. Verified against #top-nav's computed z-index, not
     against the framework default. */
  z-index:8;
}
/* Pins beneath the site header. --zcp-topnav-h is measured from #top-nav at
   runtime (product-system.v5.js) because the header's height changes with
   breakpoint; the 76px fallback only applies if that script never runs. */
.zcp5 .zcp-bar.is-sticky{ position:sticky; top:var(--zcp-topnav-h, 76px); }
.zcp5 .zcp-bar-inner{
  display:flex; align-items:center; min-height:52px;
  padding:0 16px; max-width:1320px; margin:0 auto;
}

/* product identity - mirrors .portal-api-brand. Breadcrumbs are NOT folded
   in here: they stay in the site-standard #sub-nav row above, because that
   pattern is used across the whole site and the bar should not deviate. */
.zcp5 .zcp-bar-brand{
  font-size:15px; font-weight:600; color:#2c3038; text-decoration:none;
  white-space:nowrap; flex-shrink:0; display:inline-flex;
  align-items:center; gap:7px;
}
.zcp5 .zcp-bar-brand:hover{ color:#2c3038; text-decoration:none; }
.zcp5 .zcp-bar-brand i{ font-size:14px; color:#6b7280; }

/* page links - mirror .portal-api-link exactly */
.zcp5 .zcp-bar-nav{
  display:flex; align-items:center; list-style:none;
  margin:0 0 0 auto; padding:0; gap:0;
}
.zcp5 .zcp-bar-link{
  font-size:14px; font-weight:500; color:#2c3038; text-decoration:none;
  padding:15px 12px; display:inline-block; position:relative;
  white-space:nowrap; transition:color .15s;
}
.zcp5 .zcp-bar-link:hover{ color:#1a1a1a; }
.zcp5 .zcp-bar-link.active{ color:#1a1a1a; font-weight:700; }
.zcp5 .zcp-bar-link.active::after{
  content:''; position:absolute; bottom:0; left:0; right:0;
  height:2px; background:#1a1a1a;
}

/* "On this page" - a <details> so it needs no JS and stays keyboard
   accessible; closes on outside click via a tiny handler, not required */
.zcp5 .zcp-jump{ position:relative; margin-left:.35rem; }
.zcp5 .zcp-jump > summary{
  list-style:none; cursor:pointer; white-space:nowrap;
  font-size:13px; font-weight:600; color:#2c3038;
  border:1.5px solid #9ca3af; border-radius:5px; padding:5px 12px;
}
.zcp5 .zcp-jump > summary::-webkit-details-marker{ display:none; }
.zcp5 .zcp-jump > summary::after{ content:" \25BE"; color:#6b7280; }
.zcp5 .zcp-jump[open] > summary{ background:rgba(0,0,0,.04); border-color:#6b7280; }
.zcp5 .zcp-jump-menu{
  position:absolute; right:0; top:calc(100% + 6px); z-index:1040;
  background:#fff; border:1px solid #e5e7eb; border-radius:8px;
  box-shadow:0 10px 28px rgba(9,17,34,.14);
  min-width:210px; padding:.35rem; display:flex; flex-direction:column;
}
.zcp5 .zcp-jump-menu a{
  font-size:13.5px; color:#374151; text-decoration:none;
  padding:.45rem .6rem; border-radius:5px; white-space:nowrap;
}
.zcp5 .zcp-jump-menu a:hover{ background:#f1f5f9; color:#0f172a; }

/* bar actions */
.zcp5 .zcp-bar-btn{
  display:inline-flex; align-items:center; padding:5px 16px;
  border-radius:5px; font-size:13px; font-weight:600;
  text-decoration:none; white-space:nowrap; margin-left:.5rem;
  color:#fff; background:#e42707; border:1.5px solid #e42707;
}
.zcp5 .zcp-bar-btn:hover{ background:#c92206; color:#fff; }

/* hamburger, matching the API bar's */
.zcp5 .zcp-bar-toggler{
  display:none; background:none; border:1px solid #2c3038;
  border-radius:4px; padding:4px 8px; cursor:pointer; margin-left:auto;
}
.zcp5 .zcp-bar-toggler span{ display:block; width:20px; height:2px; background:#2c3038; margin:4px 0; }

@media (max-width:991.98px){
  .zcp5 .zcp-bar-inner{ flex-wrap:wrap; }
  .zcp5 .zcp-bar-toggler{ display:block; }
  .zcp5 .zcp-bar-nav{
    flex-direction:column; align-items:stretch; width:100%;
    padding:8px 0; border-top:1px solid #dde1e6; margin:8px 0 0; gap:2px;
  }

  /* THE HAMBURGER ACTUALLY COLLAPSES.
     .zcp-bar-nav sets display:flex above, which is (0,2,0) - the same
     weight as Bootstrap's own .collapse:not(.show){display:none} - and
     this file loads after Bootstrap, so on a tie the later rule won and
     the menu was permanently open with a hamburger that did nothing.
     Restated here at (0,4,0) so the collapsed state wins on specificity
     rather than on load order.
     Deliberately matches .collapse and NOT .collapsing: Bootstrap swaps
     .collapse off while the height animates, so the open transition still
     runs through the display:flex above. */
  .zcp5 .zcp-bar-nav.collapse:not(.show){ display:none; }

  .zcp5 .zcp-bar-nav li{ width:100%; }
  .zcp5 .zcp-bar-link{ padding:10px 12px; display:block; border-radius:4px; }
  .zcp5 .zcp-bar-link.active::after{ display:none; }
  .zcp5 .zcp-jump{ margin:.35rem .75rem; }
  .zcp5 .zcp-jump-menu{ position:static; box-shadow:none; margin-top:.35rem; }
  .zcp5 .zcp-bar-btn{ margin:.35rem .75rem; justify-content:center; }

  /* "On this page" is kept on small screens - this is where the page is
     longest and in-page nav matters MOST. But it stops being a dropdown:
     the whole bar is already behind the hamburger, so a disclosure inside
     a disclosure would charge a second tap for nothing. product-system.v5.js
     pre-opens it here and adds .is-inline, and it reads as a labeled group
     in the open menu instead of another button. */
  .zcp5 .zcp-jump.is-inline{ margin:.6rem .75rem .15rem; }
  .zcp5 .zcp-jump.is-inline > summary{
    border:0; background:none; padding:0 0 .35rem;
    font-size:11px; font-weight:700; letter-spacing:.08em;
    text-transform:uppercase; color:#6b7280;
  }
  .zcp5 .zcp-jump.is-inline[open] > summary{ background:none; }
  .zcp5 .zcp-jump.is-inline .zcp-jump-menu{
    border:0; background:none; padding:0; min-width:0; margin-top:0;
  }
  .zcp5 .zcp-jump.is-inline .zcp-jump-menu a{ padding:.5rem .35rem; }
}


/* ==================================================================
   3. LAYOUT
   ================================================================== */
.zcp5 .zcp-hero{ position:relative; overflow:hidden; color:#fff; }
.zcp5 .zcp-hero .zcp-veil{
  position:absolute; inset:0;
  background:linear-gradient(100deg,
    rgba(9,17,34,.94) 0%, rgba(9,17,34,.86) 45%, rgba(9,17,34,.68) 100%);
}
.zcp5 .zcp-hero > .container{ position:relative; z-index:2; }
.zcp5 .zcp-hero h1{
  font-size:clamp(2rem,4.4vw,3rem); line-height:1.06;
  letter-spacing:-.024em; font-weight:700; margin-bottom:.7rem; color:#fff;
}
/* Caveat is a script face: the h1's tight tracking crushes it, and it sits
   optically small at the same size. Opt it out of both. */
.zcp5 .zcp-hero h1 .font-caveat{
  font-size:1.16em; letter-spacing:normal; line-height:.95;
  display:inline-block; vertical-align:baseline; padding-right:.06em;
}
.zcp5 .zcp-lede{ font-size:1rem; line-height:1.55; opacity:.92; max-width:34rem; }

/* ported from products.css - the generic hero lead, still used by the
   #hero section wrapper on pages that have not adopted .zcp-lede */
.zcp5 #hero .lead{
  font-size:1.2em; margin:0 auto 30px; max-width:900px; opacity:.95;
}

.zcp5 .zcp-meta{
  display:flex; flex-wrap:wrap; gap:1.4rem;
  border-top:1px solid rgba(255,255,255,.18);
  padding-top:.9rem; margin:1.1rem 0 1.2rem;
}
.zcp5 .zcp-meta b{ display:block; font-size:1.15rem; font-weight:600; line-height:1.1; }
.zcp5 .zcp-meta span{ font-size:.7rem; opacity:.72; }

/* full-bleed hero background image sitting under the veil */
.zcp5 .zcp-hero-img{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; z-index:0;
}

/* hero action row: one solid "go" + one ghost secondary */
.zcp5 .zcp-ctas{ display:flex; flex-wrap:wrap; gap:.6rem; align-items:center; }
.zcp5 .zcp-btn-ghost{
  display:inline-block; padding:.7rem 1.2rem; border-radius:.45rem;
  font-size:.95rem; font-weight:600; text-decoration:none;
  color:#fff; border:1.5px solid rgba(255,255,255,.42); background:transparent;
}
.zcp5 .zcp-btn-ghost:hover{ background:rgba(255,255,255,.10); color:#fff; }

/* Standalone outline button for use ANYWHERE on a light background.
   Distinct from .zcp-tier .t-btn, which is scoped inside a tier card -
   reusing that class outside a card silently falls back to plain link
   styling, which is exactly what went wrong on the first build. */
.zcp5 .zcp-btn{
  display:inline-block; padding:.62rem 1.15rem; border-radius:.4rem;
  font-size:.88rem; font-weight:700; text-decoration:none; text-align:center;
  background:#fff; color:#3b82f6; border:1.5px solid #3b82f6;
}
.zcp5 .zcp-btn:hover{ background:#eff6ff; color:#3b82f6; text-decoration:none; }

/* "At a glance" spec tile - the product-page counterpart to the free
   page's funnel rail. A product page's visitor asks "what exactly do I
   get", not "where else could I go", so the rail answers that instead. */
.zcp5 .zcp-spec{
  background:rgba(255,255,255,.10); border:1px solid rgba(255,255,255,.22);
  border-radius:.65rem; padding:1.15rem 1.25rem; height:100%;
}
.zcp5 .zcp-spec h2{
  font-size:.62rem; letter-spacing:.13em; text-transform:uppercase;
  opacity:.8; margin:0 0 .75rem; color:#fff; font-weight:600;
}
.zcp5 .zcp-spec dl{ margin:0; }
.zcp5 .zcp-spec .r{
  display:flex; justify-content:space-between; align-items:baseline; gap:1rem;
  padding:.42rem 0; border-bottom:1px solid rgba(255,255,255,.12);
}
.zcp5 .zcp-spec .r:last-child{ border-bottom:0; }
.zcp5 .zcp-spec dt{ font-size:.78rem; opacity:.74; font-weight:400; }
.zcp5 .zcp-spec dd{ margin:0; font-size:.85rem; font-weight:600; text-align:right; }

.zcp5 .zcp-rail{ display:flex; flex-direction:column; gap:.8rem; height:100%; }
.zcp5 .zcp-tile{
  flex:1; padding:1rem 1.1rem; border-radius:.65rem;
  background:rgba(255,255,255,.10); border:1px solid rgba(255,255,255,.22);
  display:flex; flex-direction:column; justify-content:center;
}
.zcp5 .zcp-tile .zcp-tk{
  font-size:.62rem; letter-spacing:.13em; text-transform:uppercase;
  opacity:.8; margin-bottom:.3rem;
}
.zcp5 .zcp-tile h2{ font-size:1rem; font-weight:700; margin:0 0 .3rem; color:#fff; }
.zcp5 .zcp-tile p{ font-size:.78rem; line-height:1.5; opacity:.86; margin:0 0 .5rem; }
.zcp5 .zcp-tile .zcp-price{ font-size:.72rem; opacity:.8; margin-bottom:.4rem; }
.zcp5 .zcp-tile a{ font-size:.78rem; font-weight:700; color:#8fd0ff; text-decoration:none; }
.zcp5 .zcp-tile a:hover{ text-decoration:underline; }
.zcp5 .zcp-tile a.zcp-sec{ display:block; margin-top:.3rem; font-weight:400; opacity:.72; font-size:.72rem; }


/* ==================================================================
   4. COMPONENTS
   ================================================================== */

/* ------------------------------------------------------------------
   4.1 SIGNUP FORM - layout ported from /api/signup.
   The site theme pads form fields 45px on the left to make room for the
   old SVG icons. Those icons are gone, so reclaim it - this is what
   .form-nopad does on the API site.
   ------------------------------------------------------------------ */
.zcp5 .zcp-signup .form-control{ padding-left:.75rem !important; }
.zcp5 .zcp-signup .form-label{
  font-size:.82rem; font-weight:600; color:var(--zcp-navy); margin-bottom:.3rem;
}
.zcp5 .zcp-signup .form-text{ font-size:.75rem; }
.zcp5 .zcp-signup .card{ border:1px solid #e5e7eb; }
.zcp5 .zcp-pwbar{ height:4px; background:#e9ecef; transition:background .15s; }
.zcp5 .zcp-signup #zcpPwReq{ font-size:.72rem; }
.zcp5 .zcp-signup #zcpPwMatch{ font-size:.75rem; }
/* the theme lays fields out as flex rows with inline labels; the ported
   layout stacks them, so opt these groups out */
.zcp5 .zcp-signup .input-group{ flex-wrap:nowrap; }

/* 4.2 API key opt-in - an add-on, not another required hurdle */
.zcp5 .zcp-apiopt{
  background:rgba(14,165,233,.07); border:1px solid rgba(14,165,233,.35);
  border-radius:.5rem; padding:.7rem .85rem;
}
.zcp5 .zcp-apiopt .form-check-label{ font-size:.85rem; line-height:1.45; }
.zcp5 .zcp-apiopt .form-check-label span{ font-size:.78rem; }
.zcp5 .zcp-apiopt .form-check-input{ margin-top:.25rem; }

/* 4.3 "What happens next" - thin strip under the form. Chosen over a
   hover panel because content behind an interaction reassures nobody. */
.zcp5 .zcp-next{
  display:flex; margin-top:.9rem; background:#fff;
  border:1px solid #e5e7eb; border-radius:.5rem; overflow:hidden;
}
.zcp5 .zcp-next > div{
  flex:1; padding:.6rem .6rem; font-size:.7rem; line-height:1.4;
  color:#374151; border-right:1px solid #f1f5f9;
}
.zcp5 .zcp-next > div:last-child{ border-right:0; }
.zcp5 .zcp-next .n{
  display:block; width:17px; height:17px; border-radius:50%;
  background:var(--zcp-navy); color:#fff; font-size:.62rem; font-weight:700;
  text-align:center; line-height:17px; margin-bottom:.3rem;
}

/* ------------------------------------------------------------------
   4.4 COMPARISON TABLE - pattern ported from /api/compare
   (.portal-compare-table in the API site's portal.css), with the accent
   moved onto this system's palette: FREE column tinted green ("you are
   here"), API column tinted cyan as the featured option.
   ------------------------------------------------------------------ */
/* NO overflow on desktop, deliberately - same trap the data dictionary hit.
   This rule used to carry BOTH `overflow:hidden` and `overflow-x:auto`, which
   computes to overflow-y:hidden: a scrollport that never scrolls vertically.
   A sticky <thead> resolves against THAT box and just leaves with the page.
   The table fits above 992px, so the scroll container only exists below it -
   and sticky is switched off there, because down there the wrapper really is
   the scroll container again. */
.zcp5 .zcp-compare-table{ border-radius:10px; border:1px solid #e5e7eb; }
.zcp5 .zcp-compare-table table{ margin-bottom:0; min-width:860px; }

/* Dropping overflow:hidden also dropped the corner clipping it was doing,
   so the corners are rounded on the cells themselves. */
.zcp5 .zcp-compare-table thead th:first-child{ border-top-left-radius:9px; }
.zcp5 .zcp-compare-table thead th:last-child{ border-top-right-radius:9px; }
.zcp5 .zcp-compare-table tbody tr:last-child td:first-child{ border-bottom-left-radius:9px; }
.zcp5 .zcp-compare-table tbody tr:last-child td:last-child{ border-bottom-right-radius:9px; }

.zcp5 .zcp-compare-table thead th{
  /* parks directly under the sticky product bar, hence the calc() */
  position:sticky; top:calc(var(--zcp-topnav-h, 76px) + 52px); z-index:3;
  background:#f8f9fa; border-bottom:2px solid #e5e7eb;
  font-size:.82rem; font-weight:700; color:#374151;
  padding:11px 14px; white-space:nowrap; vertical-align:bottom;
}
/* The header carries the three prices, so once it is stuck it becomes a
   floating price bar over the rows - which is the whole point of making it
   sticky on a table this long. Shadow only once stuck would need JS; a
   permanent hairline reads fine in both states. */
@media (max-width:991.98px){
  .zcp5 .zcp-compare-table{ overflow-x:auto; }
  .zcp5 .zcp-compare-table thead th{ position:static; }
}
/* product columns are centered; only the first column (the capability) is
   left-aligned. Applies to header, body, field-count and buy rows alike. */
.zcp5 .zcp-compare-table thead th,
.zcp5 .zcp-compare-table tbody td{ text-align:center; }
.zcp5 .zcp-compare-table thead th:first-child{ text-align:left; }
.zcp5 .zcp-compare-table thead th .th-sub{
  display:block; font-weight:400; font-size:.66rem; color:#6b7280; margin-top:1px;
}
/* The tinted header cells MUST be opaque now that the header is sticky -
   a translucent header lets the rows scroll visibly through it. Rather than
   hand-flattening each tint against #f8f9fa (easy to get subtly wrong, and
   it would drift if the base ever changes), the tint is layered as a
   gradient over the opaque base. Identical rendering, zero transparency. */
.zcp5 .zcp-compare-table thead th.col-free{
  background:linear-gradient(rgba(61,156,64,.10), rgba(61,156,64,.10)), #f8f9fa;
  color:#1f6b23;
}
.zcp5 .zcp-compare-table thead th.col-free .th-sub{ color:#2f7a33; }
.zcp5 .zcp-compare-table thead th.col-featured{
  background:linear-gradient(rgba(14,165,233,.11), rgba(14,165,233,.11)), #f8f9fa;
  color:#075985;
}
.zcp5 .zcp-compare-table thead th.col-featured .th-sub{ color:#0369a1; }
.zcp5 .zcp-compare-table tbody td{
  padding:9px 14px; font-size:.83rem; color:#374151;
  vertical-align:middle; border-color:#f0f0f0;
}
.zcp5 .zcp-compare-table tbody td:first-child{
  text-align:left; font-weight:600; color:var(--zcp-navy); font-size:.79rem;
}
.zcp5 .zcp-compare-table tbody td.col-free{ background:rgba(61,156,64,.035); }
.zcp5 .zcp-compare-table tbody td.col-featured{ background:rgba(14,165,233,.05); }
.zcp5 .zcp-compare-table tr.grp td{
  font-weight:600; font-size:.7rem; letter-spacing:.06em; text-transform:uppercase;
  background:#f1f5f9 !important; color:#64748b !important; text-align:left;
}
/* --- staircase treatment ---------------------------------------------
   A table cannot have ragged column heights, so instead each column is
   hatched out and rule-capped where it stops. The checkmarks then form a
   descending staircase while row alignment is preserved. ---------------- */
/* opaque for the same reason as .col-free / .col-featured above */
.zcp5 .zcp-compare-table thead th.col-top{
  background:linear-gradient(rgba(9,17,34,.06), rgba(9,17,34,.06)), #f8f9fa;
  color:var(--zcp-navy);
}
.zcp5 .zcp-compare-table td.col-top{ background:rgba(9,17,34,.025); }
.zcp5 .zcp-compare-table td.y{ color:var(--zcp-go); font-size:.9rem; }
/* Default .hint is INLINE - the free database page uses it as a sentence
   continuation ("Classification code (Standard, PO Box, Unique, Military)").
   Do not make this block; it would reflow that live page. */
.zcp5 .zcp-compare-table .hint{ font-weight:400; color:#94a3b8; font-size:.72rem; }

/* .stack = the hint is its own line, not a continuation. Used where the row
   label is a capability and the hint is the field list proving it; inline
   there collides ("Locate and label any ZIPZIP · City · State"). */
.zcp5 .zcp-compare-table .hint.stack{
  display:block; line-height:1.45; margin-top:.2rem;
}

/* top-tier action button - matches the Business accent used by the
   edition cards, so one product is not two colors on one page */
.zcp5 .zcp-tier-btn.tb-top{ background:#AB2827; color:#fff; }
.zcp5 .zcp-tier-btn.tb-top:hover{ filter:brightness(1.1); color:#fff; }
.zcp5 .zcp-compare-table tr.fields td{ background:#f8fafc; }
.zcp5 .zcp-compare-table tr.fields td.col-free{ background:rgba(61,156,64,.09); }
.zcp5 .zcp-compare-table tr.fields td.col-top{ background:rgba(9,17,34,.05); }
.zcp5 .zcp-compare-table .big{ font-weight:800; font-size:1.05rem; letter-spacing:-.02em; color:var(--zcp-navy); }

/* a column that has ended */
.zcp5 .zcp-compare-table td.off{
  background:repeating-linear-gradient(135deg,#fafbfc,#fafbfc 6px,#f3f5f8 6px,#f3f5f8 12px) !important;
  color:#cbd5e1;
}
.zcp5 .zcp-compare-table td.cap{ border-top:3px solid #b45309 !important; }

/* ------------------------------------------------------------------
   QUALITY GRADES  (.zcp-compare-table td.q-base / .q-caution / .q-good)
   For a product whose tiers are not a field-count staircase. ZIP+4
   Premium and Deluxe carry the SAME 40 columns; what you pay more for
   is geocode precision. Hatching a column that is not actually empty
   would misrepresent that, so those rows are GRADED instead: gray for
   the baseline, amber for "works, with caveats", green for "this is
   the good one".

   Color is never the only signal - every graded cell carries the
   figure and a word ("~80%" / "STREET LEVEL"), so the row still reads
   correctly in grayscale, to a screen reader, and to the ~8% of men
   with red-green color vision deficiency.

   !important because .col-top / .col-featured tint the whole column;
   on a graded row the grade is the more specific fact and must win.
   ------------------------------------------------------------------ */
.zcp5 .zcp-compare-table td.q-base{ background:rgba(100,116,139,.09) !important; }
.zcp5 .zcp-compare-table td.q-caution{ background:rgba(217,119,6,.11) !important; }
.zcp5 .zcp-compare-table td.q-good{ background:rgba(61,156,64,.13) !important; }

.zcp5 .zcp-compare-table .qv{
  display:block; font-weight:800; font-size:.95rem; letter-spacing:-.02em; line-height:1.2;
}
.zcp5 .zcp-compare-table td.q-base .qv{ color:#475569; }
.zcp5 .zcp-compare-table td.q-caution .qv{ color:#b45309; }
.zcp5 .zcp-compare-table td.q-good .qv{ color:#2f7a33; }

.zcp5 .zcp-compare-table .ql{
  display:block; font-size:.6rem; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; line-height:1.25; margin-top:.2rem;
}
.zcp5 .zcp-compare-table td.q-base .ql{ color:#64748b; }
.zcp5 .zcp-compare-table td.q-caution .ql{ color:#b45309; }
.zcp5 .zcp-compare-table td.q-good .ql{ color:#2f7a33; }

/* legend, so the scale is stated once rather than inferred three times */
.zcp5 .zcp-qkey{
  display:flex; flex-wrap:wrap; gap:.5rem 1.25rem; align-items:center;
  margin:.9rem 0 0; font-size:.75rem; color:var(--zcp-mut);
}
.zcp5 .zcp-qkey b{ color:var(--zcp-ink); font-weight:700; }
.zcp5 .zcp-qkey span{ display:inline-flex; align-items:center; gap:.4rem; }
.zcp5 .zcp-qkey i{
  width:.85rem; height:.85rem; border-radius:3px; display:inline-block;
  border:1px solid rgba(0,0,0,.08);
}
.zcp5 .zcp-qkey i.k-base{ background:rgba(100,116,139,.28); }
.zcp5 .zcp-qkey i.k-caution{ background:rgba(217,119,6,.34); }
.zcp5 .zcp-qkey i.k-good{ background:rgba(61,156,64,.38); }
.zcp5 .zcp-compare-table .caplbl{
  display:block; font-size:.58rem; font-weight:700; letter-spacing:.05em;
  text-transform:uppercase; color:#b45309; line-height:1.2;
}

/* per-tier action row */
.zcp5 .zcp-compare-table tr.buy td{ padding:.9rem .7rem; border-bottom:0; }
.zcp5 .zcp-compare-table .pricetag{
  display:block; font-weight:800; font-size:1rem; color:var(--zcp-navy);
  letter-spacing:-.02em; margin-bottom:.4rem;
}
.zcp5 .zcp-compare-table .pricetag small{ font-weight:400; font-size:.66rem; color:#6b7280; }
.zcp5 .zcp-tier-btn{
  display:block; font-size:.78rem; font-weight:700; padding:.45rem .4rem;
  border-radius:.35rem; text-decoration:none; white-space:nowrap;
}
.zcp5 .zcp-tier-btn.tb-free{ background:var(--zcp-go); color:#fff; }
.zcp5 .zcp-tier-btn.tb-paid{ background:#fff; color:var(--zcp-ink); border:1.5px solid #cbd5e1; }
.zcp5 .zcp-tier-btn.tb-paid:hover{ background:#f1f5f9; border-color:#94a3b8; }
.zcp5 .zcp-tier-btn.tb-free:hover{ filter:brightness(1.08); color:#fff; }

/* --- API as a distinct column ----------------------------------------
   Deliberately tinted cyan rather than treated as a higher database tier.
   It is a different product line with a different pricing unit, and it
   both adds things no database has and lacks things every database has. */
/* opaque: this is a sticky header cell, see .col-free above. The free page
   is the only page carrying this column, which is why it sits apart from
   the other three - all four must stay opaque together. */
.zcp5 .zcp-compare-table thead th.col-api{
  background:linear-gradient(rgba(14,165,233,.13), rgba(14,165,233,.13)), #f8f9fa;
  color:#075985;
}
.zcp5 .zcp-compare-table thead th.col-api .th-sub{ color:#0369a1; }
.zcp5 .zcp-compare-table td.col-api{ background:rgba(14,165,233,.05); }
.zcp5 .zcp-compare-table tr.fields td.col-api{ background:rgba(14,165,233,.11); }
.zcp5 .zcp-compare-table tr.grp.grp-api td{
  background:rgba(14,165,233,.14) !important; color:#075985 !important;
}
.zcp5 .zcp-compare-table .dash{ color:#cbd5e1; font-size:.85rem; }
.zcp5 .zcp-tier-btn.tb-api{ background:var(--zcp-accent); color:#04263d; }
.zcp5 .zcp-tier-btn.tb-api:hover{ filter:brightness(1.06); color:#04263d; }

.zcp5 .zcp-compare-table .cmp-y{ color:var(--zcp-go); font-size:.9rem; }
.zcp5 .zcp-compare-table .cmp-n{ color:#d1d5db; font-size:.9rem; }
.zcp5 .zcp-compare-table .cmp-v{ font-weight:600; font-size:.78rem; }
/* .t-sample is scoped to .zcp-tier for the edition cards; the comparison
   table's buy row reuses the same markup class, so it needs its own rule. */
.zcp5 .zcp-compare-table .t-sample{
  display:block; margin-top:.45rem; font-size:.72rem; font-weight:600;
  color:#3b82f6; text-decoration:none; white-space:nowrap;
}
.zcp5 .zcp-compare-table .t-sample:hover{ text-decoration:underline; color:#3b82f6; }

.zcp5 .zcp-cmp-cta{ font-size:.76rem; font-weight:700; text-decoration:none; color:#0369a1; white-space:nowrap; }
.zcp5 .zcp-cmp-cta:hover{ text-decoration:underline; }
.zcp5 .zcp-compare-foot{ font-size:.74rem; color:var(--zcp-mut); line-height:1.65; }
.zcp5 .zcp-compare-foot a{ color:#0369a1; }

/* ported from products.css - the plain bordered comparison table still
   used inside modals and secondary sections */
.zcp5 .comparison-table{ margin-top:2rem; }
.zcp5 .comparison-table th,
.zcp5 .comparison-table td{ padding:1rem; vertical-align:middle; }
.zcp5 .comparison-table thead th{ background:#f8f9fa; font-weight:600; }

/* 4.5 API strip - an alternative to folding the API into the table */
.zcp5 .zcp-api-strip{
  margin-top:1.1rem; background:var(--zcp-navy); color:#fff; border-radius:.65rem;
  padding:1rem 1.25rem; display:flex; align-items:center; gap:1.25rem; flex-wrap:wrap;
}
.zcp5 .zcp-api-strip .zcp-kick{ color:#7dd3fc; opacity:1; margin-bottom:.2rem; }
.zcp5 .zcp-api-strip h3{ margin:0 0 .25rem; font-size:1rem; font-weight:700; color:#fff; }
.zcp5 .zcp-api-strip p{ margin:0; font-size:.8rem; opacity:.86; max-width:44rem; }
.zcp5 .zcp-api-strip > a{
  margin-left:auto; background:var(--zcp-accent); color:#04263d; font-weight:700;
  font-size:.82rem; padding:.5rem 1.1rem; border-radius:.4rem; text-decoration:none; white-space:nowrap;
}

/* ------------------------------------------------------------------
   4.6 DATA EXPLORER - reads as one instrument panel continuing the hero,
   rather than a light band that stops it dead.
   Every id, name, for= and onchange that de.js relies on is untouched.

   NOTE: these rules absorb what used to be a products.css base plus a
   v5.1 override fighting it. The elements carry both hooks
   (id="de-controls" class="de-controls"), so the merged rule needs no
   !important at all - which is why this section got shorter, not longer.
   ------------------------------------------------------------------ */
.zcp5 #data-explorer{ background:#eef2f7; padding-top:2.25rem; }
.zcp5 .data-explorer select{ max-width:100%; }
.zcp5 #de-container{
  padding-left:0; padding-right:0; background:#fff;
  border:1px solid #dbe3ec; border-radius:14px; overflow:hidden;
  box-shadow:0 2px 16px rgba(9,17,34,.08);
}
/* navy header carries the hero down into the panel */
.zcp5 .zcp-de-head{ background:var(--zcp-navy); color:#fff; padding:1.35rem 1.5rem 1.2rem; }
.zcp5 .zcp-de-head .zcp-kick{ color:#7dd3fc; opacity:1; margin-bottom:.4rem; }
.zcp5 .zcp-de-head h2{
  color:#fff; margin:0; font-weight:700;
  font-size:clamp(1.3rem,2.4vw,1.75rem); letter-spacing:-.015em;
}
.zcp5 .zcp-de-head h2 .font-caveat{ font-size:1.16em; letter-spacing:normal; }

/* toolbar - flattened into a strip instead of a box inside the panel */
.zcp5 .de-controls{
  background:#fbfcfe; line-height:125%; font-size:.85rem;
  padding:.95rem 1.5rem;
  border:0; border-bottom:1px solid var(--zcp-line); border-radius:0;
}
.zcp5 .zcp-de-intro{ margin:0 0 .7rem; color:var(--zcp-mut); font-size:.85rem; max-width:56rem; }
/* The one tip under the Data Explorer's loading pane. Was a Bootstrap
   alert-info, i.e. a blue box inside a panel that is already a box. */
.zcp5 .zcp-de-tip{
  margin:.75rem 0 0; font-size:.78rem; line-height:1.6; color:var(--zcp-mut);
}
.zcp5 .zcp-de-tip i{ color:#c98a17; margin-right:.35rem; }
.zcp5 .zcp-de-tip b{ color:var(--zcp-ink); }

/* edition switcher as a segmented control - native radios stay in the DOM,
   just visually replaced, so keyboard + screen readers still work */
.zcp5 .de-sel{ line-height:125%; }
.zcp5 .de-sel input[type="radio"]{ position:absolute; opacity:0; width:1px; height:1px; }
.zcp5 .de-sel input[type="radio"] + label{
  display:inline-block; padding:.3rem .7rem; margin:0 .15rem .2rem 0;
  border:1px solid #cbd5e1; border-radius:999px; background:#fff;
  font-size:.78rem; font-weight:600; color:#334155; cursor:pointer;
  transition:background .12s, border-color .12s, color .12s;
}
.zcp5 .de-sel input[type="radio"] + label:hover{ border-color:#94a3b8; }
.zcp5 .de-sel input[type="radio"]:checked + label{
  background:var(--zcp-navy); border-color:var(--zcp-navy); color:#fff;
}
.zcp5 .de-sel #de-form-db-free:checked + label{
  background:var(--zcp-go); border-color:var(--zcp-go);
}
.zcp5 .de-sel input[type="radio"]:focus-visible + label{
  outline:2px solid var(--zcp-accent); outline-offset:2px;
}
.zcp5 .de-sel select{
  border:1px solid #cbd5e1; border-radius:.35rem; padding:.28rem .5rem;
  font-size:.78rem; background:#fff; color:#334155;
}

/* table reads like a data tool: aligned figures, hairlines, sticky header */
.zcp5 #de-table-wrapper{ padding:0 1.5rem 0; height:auto; }
.zcp5 #de-table{ font-size:.8rem; font-variant-numeric:tabular-nums; margin-bottom:0; }
/* ported from products.css - cell size is set on the cells, not the table */
.zcp5 #de-table th,
.zcp5 #de-table td{ font-size:11px; }
.zcp5 #de-table thead th{
  position:sticky; top:0; z-index:1; background:#fff;
  font-size:.66rem; letter-spacing:.07em; text-transform:uppercase;
  color:#64748b; font-weight:600; white-space:nowrap;
  border-bottom:1.5px solid var(--zcp-ink) !important;
}
.zcp5 #de-table tbody td{ border-color:#f1f5f9 !important; color:#334155; padding:.4rem .55rem; }
.zcp5 #de-table tbody tr:hover td{ background:#f6f9fd; }

.zcp5 .dt-column-title,
.zcp5 .dt-search{ font-size:smaller; }
.zcp5 .dt-layout-table{ border-radius:12px; }

/* footer */
.zcp5 #de-footer{ padding:.95rem 1.5rem; border-top:1px solid var(--zcp-line); background:#fbfcfe; font-size:.82rem; }
.zcp5 #de-footer-records{ color:var(--zcp-mut); }

/* .de-loading base, ported from products.css.
   DO NOT merge this into the #de-loading-wrapper-bottom rule below:
   products.js:114 adds/removes .de-loading on #de-loading-wrapper too,
   so more than one element can wear this class at runtime. The two rules
   are deliberately kept apart to reproduce the existing cascade exactly. */
.zcp5 .de-loading{
  background:#f1f5f9; border:2px dashed #cbd5e1; border-radius:8px;
  color:#000; font-size:1.1em; margin-top:15px;
  min-height:325px; padding:80px 20px; text-align:center;
}

/* The pre-load explainer sits above the fold, so it has to stay small.
   The base above is tolerable below the fold; it is not here. */
.zcp5 #de-loading-wrapper-bottom{
  padding:1.25rem 1.5rem; color:var(--zcp-mut); font-size:.85rem;
  min-height:0; margin-top:0;
  border:0; border-radius:0; background:#fff;
}
.zcp5 #de-loading-wrapper-bottom > div{ margin:0; }
.zcp5 #de-loading-wrapper-bottom h3{ font-size:1rem; font-weight:600; color:var(--zcp-ink); }
.zcp5 #de-loading-wrapper-bottom h4{ font-size:.8rem; }
.zcp5 #de-loading-wrapper-bottom .alert{ display:none; }

/* 4.7 USE CASE CARDS - ported from products.css */
.zcp5 .use-case-card{
  background:#f8fafc; border:2px solid #e2e8f0; border-radius:12px;
  height:100%; padding:1rem; transition:all .3s;
}
.zcp5 .use-case-card h3{ color:#1e293b; margin-bottom:1rem; }
.zcp5 .use-case-card i{ color:#3b82f6; font-size:2rem; margin-right:.75rem; }
.zcp5 .use-case-card p{ color:#475569; line-height:1.6; }
.zcp5 .use-case-card:hover{
  border-color:#3b82f6; box-shadow:0 10px 25px rgba(59,130,246,.15);
  transform:translateY(-5px);
}
.zcp5 .use-case-card .card-body{ padding:0; }

/* Lightweight format chip-card, for the boundary Overview's eight-format
   row. Distinct from .zcp-fmtcard, which is the heavy spec-sheet card on
   the technical page: this one is a glance, that one is a reference. */
.zcp5 .zcp-fmtcard-lite{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  padding:1rem .9rem; height:100%; text-align:center;
  transition:border-color .12s, box-shadow .12s, transform .12s;
}
.zcp5 .zcp-fmtcard-lite:hover{
  border-color:#3b82f6; box-shadow:0 8px 20px rgba(59,130,246,.12);
  transform:translateY(-3px);
}
.zcp5 .zcp-fmtcard-lite .card-body{ padding:0; }
.zcp5 .zcp-fmtcard-lite .card-title{
  font-size:.9rem; font-weight:700; color:var(--zcp-ink); margin:0 0 .2rem;
}
.zcp5 .zcp-fmtcard-lite i{ color:#3b82f6; font-size:1.6rem; margin-bottom:.5rem; }
.zcp5 .zcp-card-sub{
  font-size:.72rem; color:var(--zcp-mut); margin:0 0 .5rem;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
}
.zcp5 .zcp-card-txt{
  font-size:.78rem; line-height:1.55; color:#475569; margin:0;
}
/* The "Key fields:" line at the foot of a use case card. It is the part
   that makes the card checkable against an edition, so it gets its own
   quiet treatment rather than being another muted paragraph. */
.zcp5 .use-case-card .zcp-keyfields{
  margin:.75rem 0 0; padding-top:.6rem; border-top:1px solid #e2e8f0;
  font-size:.74rem; line-height:1.5; color:#64748b;
}
.zcp5 .use-case-card .zcp-keyfields b{ color:#475569; font-weight:700; }

/* 4.8 CUSTOMERS scroller - ported from products.css */
.zcp5 .customers{
  width:100%; overflow-x:scroll; overflow-y:hidden; overflow-wrap:normal;
}
.zcp5 .customers .inner{ width:3450px; max-width:none; }
.zcp5 .customers .header-cat-box{ max-width:150px; }

/* 4.9 FAQ ACCORDIONS - ported from products.css */
.zcp5 #faqs .accordion-button,
.zcp5 #technical-faq .accordion-button{ font-size:1rem; font-weight:600; }
.zcp5 #faqs .accordion-item,
.zcp5 #technical-faq .accordion-item{ margin-bottom:0; }
.zcp5 #faqs .accordion-body,
.zcp5 #technical-faq .accordion-body{ font-size:.85rem; padding:1rem; }

/* 4.10 SOURCES / REFERENCES - ported from products.css */
.zcp5 #sources ol.ref{ padding-left:2rem; }
.zcp5 #sources ol.ref li{ margin-bottom:1rem; }
.zcp5 #sources ol.ref ul{ list-style-type:disc; margin-top:.5rem; }
.zcp5 #sources ol.ref ul li{ margin-bottom:.5rem; }


/* ------------------------------------------------------------------
   4.11 EDITION / TIER CARDS
   Pattern adopted from /api/pricing (.portal-plan-card), which already
   solves this well: uniform white cards, and the ONLY color is a thin
   bar across the top of each one.

   That bar is a ramp, not decoration - teal -> blue -> purple - so it
   encodes tier level. Cards are laid out highest-tier-first, so color
   depth, card height and price all descend together and the three
   signals agree instead of competing.

   Card height is deliberately NOT equalised: the taller card genuinely
   has more in it, which is the "bigger = more" cue. Do not add h-100.
   ------------------------------------------------------------------ */
.zcp5 .zcp-tiers{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:1.25rem; align-items:start;      /* align-items:start = ragged heights */
}
/* Two-edition products (Area Code / NPA-NXX). Three columns of card in a
   two-card row leaves a visible hole, and stretching two cards across the
   full width makes each one a billboard. Constrained instead, so the pair
   sits at roughly the width three cards would occupy minus one - the row
   still reads as a set of choices rather than two posters. */
.zcp5 .zcp-tiers.two{
  grid-template-columns:repeat(2,1fr);
  max-width:47rem; margin-left:auto; margin-right:auto;
}
.zcp5 .zcp-tier{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  overflow:hidden; display:flex; flex-direction:column; position:relative;
}
/* Each tier carries ONE accent, set here and reused by its bar, checks,
   button and badge. Within a card that means a single color; across the
   row it is the established Business/Deluxe/Standard brand triad, kept
   from the previous design but reduced from full color-block headers to
   a 4px rule. Same identity, a fraction of the volume. */
.zcp5 .zcp-tier.t-top  { --t-accent:#AB2827; --t-accent-rgb:171,40,39; }  /* Business */
.zcp5 .zcp-tier.t-mid  { --t-accent:#7d9a2e; --t-accent-rgb:125,154,46; } /* Deluxe - #9BBD3C darkened for AA text contrast */
.zcp5 .zcp-tier.t-entry{ --t-accent:#c98a17; --t-accent-rgb:201,138,23; } /* Standard - #F9B73D darkened for AA text contrast */

/* ---- hover focus -----------------------------------------------------
   Ports the lift the old pricing cards had, and adds the part that makes
   it mean something: the OTHER cards recede, so the one under the cursor
   reads as "the one you are considering". Tinted with the card's own
   accent so the cue stays inside the tier's color rather than adding a
   new one. Hover only - never a permanent state. */
.zcp5 .zcp-tier{
  transition:transform .18s ease, box-shadow .18s ease,
             opacity .18s ease, border-color .18s ease;
}
.zcp5 .zcp-tiers:hover .zcp-tier{ opacity:.62; }
.zcp5 .zcp-tiers .zcp-tier:hover{
  opacity:1; transform:translateY(-6px);
  border-color:var(--t-accent);
  box-shadow:0 14px 32px rgba(var(--t-accent-rgb), .26);
}
@media (prefers-reduced-motion:reduce){
  .zcp5 .zcp-tier{ transition:none; }
  .zcp5 .zcp-tiers .zcp-tier:hover{ transform:none; }
}
/* pointer-less devices never hover; make sure nothing is left dimmed */
@media (hover:none){
  .zcp5 .zcp-tiers:hover .zcp-tier{ opacity:1; }
}

.zcp5 .zcp-tier .t-bar{ height:4px; width:100%; background:var(--t-accent); }
.zcp5 .zcp-tier.is-featured .t-bar{ height:6px; }

/* featured lift, straight from /api/pricing.
   The glow uses the card's OWN accent. It was hardcoded to the Business
   red, which is invisible on the Overview page (the featured card IS the
   red one) but wrong the moment a page features a different tier - the
   Historical page features the middle card, and a red glow under a green
   border is the kind of thing nobody can name but everybody sees. */
.zcp5 .zcp-tier.is-featured{
  border:2px solid var(--t-accent);
  box-shadow:0 8px 24px rgba(var(--t-accent-rgb,171,40,39), .15);
}
.zcp5 .zcp-tier .t-badge{
  position:absolute; top:0; left:50%; transform:translateX(-50%);
  background:var(--t-accent); color:#fff; font-size:11px; font-weight:700;
  letter-spacing:.04em; text-transform:uppercase;
  padding:.15rem .7rem; border-radius:0 0 12px 12px; white-space:nowrap;
}
.zcp5 .zcp-tier .t-body{ padding:1.5rem 1.25rem 1.25rem; flex:1; display:flex; flex-direction:column; text-align:center; }
.zcp5 .zcp-tier.is-featured .t-body{ padding-top:1.9rem; }
.zcp5 .zcp-tier h3{
  font-size:1.05rem; font-weight:700; color:var(--zcp-ink);
  margin:0 0 .5rem; letter-spacing:-.01em;
}
.zcp5 .zcp-tier .t-price{
  font-size:2.1rem; font-weight:800; letter-spacing:-.03em;
  color:var(--zcp-ink); line-height:1;
}
.zcp5 .zcp-tier .t-term{ font-size:.74rem; color:var(--zcp-mut); margin-top:.25rem; }
.zcp5 .zcp-tier .t-sub{
  font-size:.78rem; color:var(--zcp-mut); margin:.45rem 0 1.05rem;
  line-height:1.4;
}
.zcp5 .zcp-tier ul{ list-style:none; padding:0; margin:0 0 1.25rem; text-align:left; }
.zcp5 .zcp-tier li{
  font-size:.83rem; color:#374151; line-height:1.45;
  padding:.34rem 0 .34rem 1.4rem; position:relative;
}
.zcp5 .zcp-tier li::before{
  content:"\2713"; position:absolute; left:0; top:.34rem;
  color:var(--t-accent); font-weight:700; font-size:.85rem;
}
.zcp5 .zcp-tier .t-btn{
  display:block; text-align:center; text-decoration:none; margin-top:auto;
  padding:.62rem .5rem; border-radius:.4rem; font-size:.88rem; font-weight:700;
  background:#fff; color:var(--t-accent); border:1.5px solid var(--t-accent);
}
.zcp5 .zcp-tier .t-btn:hover{ background:#fafafa; filter:brightness(.92); }
.zcp5 .zcp-tier.is-featured .t-btn{ background:var(--t-accent); border-color:var(--t-accent); color:#fff; }
.zcp5 .zcp-tier.is-featured .t-btn:hover{ filter:brightness(1.12); color:#fff; background:var(--t-accent); }

/* ------------------------------------------------------------------
   WHOLE-CARD CLICK TARGET  (.t-link)
   Management wants a click anywhere on a product box to reach the
   purchase page.

   This REPLACES an earlier attempt that stretched a transparent ::after
   from the button across the card. That worked, but it was janky in a
   way worth recording: an invisible layer over the content blocks mouse
   text-selection, forces every other control into a z-index fight to
   stay clickable, and leaves two overlapping hit areas whose stacking
   has to be reasoned about rather than seen.

   The honest structure instead: the card IS a link. One <a class="t-link">
   wraps everything, so there is no overlay, nothing to out-stack, and
   text selection behaves normally because selecting inside a link is
   ordinary browser behavior. Middle-click, ctrl-click, "copy link
   address" and the status-bar URL preview all work, because it is a real
   anchor and not a JS click handler pretending to be one.

   Two rules make it hold together:
     - "Purchase Options" becomes a <span>, not an <a>. Nested links are
       invalid HTML and the browser would split them apart. It goes to
       the same URL as the card, so nothing is lost - it is now purely
       the visual affordance it always really was.
     - .t-sample is the ONE genuinely different destination (a file
       download), so it stays a real <a> and lives OUTSIDE .t-link, as a
       sibling inside the card. It therefore needs its own padding, which
       doubles as the larger click target.
   ------------------------------------------------------------------ */
.zcp5 .zcp-tier .t-link{
  /* continues the card's flex column so .t-btn's margin-top:auto still
     pins the button to the floor of a ragged card */
  display:flex; flex-direction:column; flex:1;
  text-decoration:none; color:inherit;
}
.zcp5 .zcp-tier .t-link:hover{ text-decoration:none; color:inherit; }

/* The whole card reads as clickable, and the button lights up with it -
   hovering anywhere is hovering the link that contains the button. */
.zcp5 .zcp-tier .t-link:hover .t-btn{ background:#fafafa; filter:brightness(.92); }
.zcp5 .zcp-tier.is-featured .t-link:hover .t-btn{
  filter:brightness(1.12); background:var(--t-accent);
}
/* keyboard parity: the card link is focusable, so show it */
.zcp5 .zcp-tier .t-link:focus-visible{
  outline:2px solid var(--t-accent); outline-offset:-3px; border-radius:8px;
}

/* ---- nothing competes with the card any more ---------------------
   The sample link used to sit INSIDE the card as a sibling of .t-link.
   Even outside the anchor it was still a second target inside a box
   that is entirely one big click, so a near-miss bought the wrong
   thing. Management will not drop the whole-card click, so the second
   action moves OUT of the box instead: .zcp-tier-cell wraps the card
   plus a link underneath it, clear of the card's hit area.

   The card is now the ONLY target inside its own border. */
.zcp5 .zcp-tier-cell{ display:flex; flex-direction:column; }
.zcp5 .zcp-tier-under{
  display:block; text-align:center; text-decoration:none;
  margin-top:.55rem; padding:.5rem .5rem;
  font-size:.78rem; font-weight:600; color:#3b82f6;
}
.zcp5 .zcp-tier-under:hover{ text-decoration:underline; color:#3b82f6; }
.zcp5 .zcp-tier-under i{ margin-right:.3rem; }

/* sample download - a low-commitment second action under the buy button.
   Deliberately a quiet text link, not a second button: two buttons of
   equal weight make the card ask two questions at once. */
.zcp5 .zcp-tier .t-sample{
  display:block; text-align:center; margin-top:.6rem;
  font-size:.76rem; font-weight:600; color:#3b82f6; text-decoration:none;
}
.zcp5 .zcp-tier .t-sample:hover{ text-decoration:underline; color:#3b82f6; }
.zcp5 .zcp-tier .t-sample .sz{ font-weight:400; color:var(--zcp-mut); }

/* ------------------------------------------------------------------
   4.13 LICENSING PANEL
   Both terms documents surfaced as first-class choices side by side,
   rather than one "Review TOS" link lost in a row of unrelated links.
   Which license a buyer needs is a real decision, so the page states
   that there are two and what separates them.
   ------------------------------------------------------------------ */
.zcp5 .zcp-license{
  display:grid; grid-template-columns:repeat(2,1fr); gap:1rem;
  background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1.25rem;
}
.zcp5 .zcp-license > div{ display:flex; flex-direction:column; }
.zcp5 .zcp-license h4{
  font-size:.92rem; font-weight:700; color:var(--zcp-ink); margin:0 0 .3rem;
}
.zcp5 .zcp-license p{
  font-size:.81rem; color:var(--zcp-mut); line-height:1.5; margin:0 0 .85rem;
}
.zcp5 .zcp-license .zcp-btn{ align-self:flex-start; margin-top:auto; }
@media (max-width:767.98px){ .zcp5 .zcp-license{ grid-template-columns:1fr; } }

/* ------------------------------------------------------------------
   4.12 PREMIUM FEATURES
   Everything that ships with EVERY edition. Replaces a 17-item bullet
   list that read as a wall. Same copy, same tooltips - just given a
   grid of chips so it scans instead of being read line by line.
   ------------------------------------------------------------------ */
.zcp5 .zcp-features{
  display:grid; grid-template-columns:repeat(3,1fr); gap:.5rem;
  list-style:none; padding:0; margin:0;
}
.zcp5 .zcp-features li{ margin:0; }
.zcp5 .zcp-features .f{
  display:flex; align-items:flex-start; gap:.5rem; height:100%;
  background:#fff; border:1px solid #e5e7eb; border-radius:.5rem;
  padding:.6rem .75rem; font-size:.82rem; line-height:1.4; color:#374151;
  cursor:help; transition:border-color .12s, background .12s;
}
.zcp5 .zcp-features .f::before{
  content:"\2713"; color:#3b82f6; font-weight:700; font-size:.85rem; flex:none;
}
.zcp5 .zcp-features .f:hover{ border-color:#3b82f6; background:#f6fbff; }
/* the site's .tool-tip underlines its text. Across 17 chips that reads as
   noise, and the chip border is already the hover affordance. */
.zcp5 .zcp-features .f.tool-tip,
.zcp5 .zcp-features .f .tool-tip{ text-decoration:none; border-bottom:0; }

@media (max-width:991.98px){ .zcp5 .zcp-features{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:575.98px){ .zcp5 .zcp-features{ grid-template-columns:1fr; } }

/* .detail - same chips, but the explanation is ON the chip instead of in
   a tooltip. Used where the sentence IS the argument (Why Choose Us) and
   hiding it behind a hover would lose the page's substance. Two columns,
   because these chips are three or four lines rather than one. */
.zcp5 .zcp-features.detail{ grid-template-columns:repeat(2,1fr); }
.zcp5 .zcp-features.detail .f{ cursor:default; }
/* :first-child - this styles the bold lead-in that OPENS a card, not any
   <b> used for emphasis in the sentences after it. Without the constraint,
   inline emphasis becomes a block and splits the paragraph. */
.zcp5 .zcp-features.detail .f b:first-child{
  display:block; color:var(--zcp-ink); font-weight:700; margin-bottom:.12rem;
}
.zcp5 .zcp-features.detail .f a{ color:#3b82f6; }
@media (max-width:767.98px){ .zcp5 .zcp-features.detail{ grid-template-columns:1fr; } }


/* ------------------------------------------------------------------
   4.135 FEATURE GROUP HEADING  (.zcp-fgroup)
   13 chips in one run is a list you read or skip. Three headed clusters
   let someone find the one thing they care about. Quiet on purpose - it
   is a signpost, not a heading competing with the section title.
   ------------------------------------------------------------------ */
.zcp5 .zcp-fgroup{
  font-size:.68rem; font-weight:700; letter-spacing:.12em;
  text-transform:uppercase; color:var(--zcp-mut);
  margin:1.6rem 0 .6rem;
}
.zcp5 .zcp-fgroup:first-of-type{ margin-top:0; }

/* ------------------------------------------------------------------
   4.136 QUESTION / ANSWER SHEET  (.zcp-qa)
   Used for "questions worth asking any provider". Deliberately NOT a
   competitor comparison table: every row asserts a fact about US, so
   nothing here goes stale or wrong when somebody else changes their
   pricing. Reads as a spec sheet rather than a sales grid.
   ------------------------------------------------------------------ */
.zcp5 .zcp-qa{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  overflow:hidden; margin:0;
}
.zcp5 .zcp-qa > div{
  display:grid; grid-template-columns:1fr 1.35fr; gap:1.25rem;
  padding:.95rem 1.3rem; border-bottom:1px solid #f1f5f9;
}
.zcp5 .zcp-qa > div:last-child{ border-bottom:0; }
.zcp5 .zcp-qa > div:hover{ background:#f8fafc; }
.zcp5 .zcp-qa dt{
  font-size:.86rem; font-weight:700; color:var(--zcp-ink); line-height:1.5;
}
.zcp5 .zcp-qa dd{
  margin:0; font-size:.86rem; line-height:1.6; color:#374151;
}
.zcp5 .zcp-qa dd b{ color:var(--zcp-ink); }
@media (max-width:767.98px){
  .zcp5 .zcp-qa > div{ grid-template-columns:1fr; gap:.3rem; }
}

/* ------------------------------------------------------------------
   4.14 TRUST BLOCK  (Decades of Trust + Trusted by Thousands)
   Same content as the original, restated in the system's card idiom:
   white panel, hairline border, one accent. Replaces a set of inline
   style="color:#3b82f6" links, which is what made the old block hard
   to restyle in the first place.
   ------------------------------------------------------------------ */
/* stretch, not start: these two panels sit side by side and read as a pair,
   so ragged bottoms look like a mistake rather than a signal. (Contrast
   with .zcp-tiers, where the ragged height IS the signal.) */
.zcp5 .zcp-trust{ display:grid; grid-template-columns:1fr 2fr; gap:1.25rem; align-items:stretch; }
.zcp5 .zcp-trust-card{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1.35rem;
  height:100%;
}
.zcp5 .zcp-trust-card h3{
  font-size:1rem; font-weight:700; color:var(--zcp-ink);
  margin:0 0 .8rem; display:flex; align-items:center; gap:.55rem;
}
.zcp5 .zcp-trust-card h3 i{ color:#3b82f6; }
.zcp5 .zcp-trust-card p{ font-size:.86rem; line-height:1.6; color:#374151; }
.zcp5 .zcp-trust-name{ font-weight:700; color:var(--zcp-ink); margin-bottom:.1rem !important; }
.zcp5 .zcp-trust-role{ font-size:.78rem; color:var(--zcp-mut); margin-bottom:.9rem !important; }
.zcp5 .zcp-guarantee{ float:right; margin:0 0 .8rem 1.1rem; }
.zcp5 .zcp-link{ color:#3b82f6; text-decoration:none; font-weight:600; font-size:.85rem; }
.zcp5 .zcp-link:hover{ text-decoration:underline; color:#3b82f6; }

/* Customer logo rail. Grayscale was tried and rejected - these marks are
   recognized at a glance in color, and that familiarity IS the trust
   signal, so it outweighs the tidier monochrome. Left full color. */
.zcp5 .zcp-logos .card{ background:transparent; }
.zcp5 .zcp-logos .company-logo{ opacity:.92; transition:opacity .15s; }
.zcp5 .zcp-logos .card:hover .company-logo{ opacity:1; }

/* ------------------------------------------------------------------
   4.145 TESTIMONIALS
   Quotes are kept in full - they are the evidence, and truncating them
   weakens the section. Easing the type size instead shortens every card
   and narrows the height spread between the longest and shortest review,
   which is what produces the dead space above the carousel dots (Owl
   fixes the stage to the tallest slide).
   Scoped to .testimonial-item so the header's "4.8 out of 5" .fs-5 is
   untouched. !important is required - Bootstrap's .fs-5 carries it.
   ------------------------------------------------------------------ */
.zcp5 #testimonials .testimonial-item .fs-5{
  font-size:1.02rem !important; line-height:1.55;
}
.zcp5 #testimonials .testimonial-item .fs-4{ font-size:1.15rem !important; }

/* style.css puts content:"\f0e0" (fa-envelope) on every .testimonial-item.
   It dates from when these were customer emails; they are Google reviews
   now, so the icon is legacy and misleading. Removed here rather than
   editing the shared style.css, which other pages still rely on. */
.zcp5 #testimonials .testimonial-item::before{ content:none; }

/* Rating is the anchor of this section - it is the one claim a visitor
   can verify independently, so it gets the size. It replaced three
   self-asserted trust badges ("100% Verified Reviews" etc.), which stated
   what the rating already proves. */
.zcp5 #testimonials .tm-head{ margin-top:.35rem; }
.zcp5 #testimonials .tm-rating{
  display:flex; align-items:baseline; justify-content:center;
  gap:.55rem; flex-wrap:wrap;
}
.zcp5 #testimonials .tm-stars{ color:#ffc107; font-size:1.7rem; letter-spacing:.08em; line-height:1; }
.zcp5 #testimonials .tm-score{
  font-size:2.4rem; font-weight:800; color:#fff; line-height:1; letter-spacing:-.02em;
}
.zcp5 #testimonials .tm-outof{ font-size:.95rem; color:rgba(255,255,255,.72); }
.zcp5 #testimonials .tm-sub{
  margin:.5rem 0 0; font-size:.84rem; color:rgba(255,255,255,.68);
}
/* The rating is the one claim a reader can go and check, so the link to
   it is real rather than decorative. Underlined because on a photographic
   background color alone is not a reliable affordance. */
.zcp5 #testimonials .tm-sub a{
  color:#fff; text-decoration:underline; text-underline-offset:2px;
}
.zcp5 #testimonials .tm-sub a:hover{ color:#fff; opacity:.85; }

/* Nav arrows default to floating over the middle of the slides. The cards
   fill almost the whole stage (972px stage, 481px cards), so there is no
   margin to push them into - they were sitting 50px over the quote text and
   clipping it. Moved below the carousel, next to the dots, where they
   overlap nothing. */
.zcp5 #testimonials .owl-nav{
  position:static; display:flex; justify-content:center; gap:.75rem;
  margin-top:.9rem;
}
.zcp5 #testimonials .owl-nav button.owl-prev,
.zcp5 #testimonials .owl-nav button.owl-next{
  position:static !important; transform:none !important;
  margin:0 !important; width:38px; height:38px; border-radius:50%;
  background:rgba(255,255,255,.14) !important;
  border:1px solid rgba(255,255,255,.3) !important;
  color:#fff !important; display:inline-flex; align-items:center; justify-content:center;
}
.zcp5 #testimonials .owl-nav button:hover{ background:rgba(255,255,255,.26) !important; }
.zcp5 #testimonials .owl-dots{ margin-top:.6rem; }

/* "Local Guide · N reviews" moved off the top badge row and onto the
   reviewer's name, where it qualifies the person instead of competing
   with the quote. Deliberately quiet: it is a credential, not a claim. */
.zcp5 #testimonials .tm-guide{
  display:block; margin-top:.2rem;
  font-size:.7rem; font-weight:400; letter-spacing:.02em;
  color:rgba(255,255,255,.62); text-transform:none;
}
.zcp5 #testimonials .tm-guide::before{
  content:"\f3ed";                      /* fa-shield-halved */
  font-family:"Font Awesome 6 Free"; font-weight:900;
  margin-right:.3rem; opacity:.7;
}

/* Date line under the attribution. Used by the Google reviews on the
   overview page and by the e-mail testimonials; quiet on purpose, it
   dates the quote without competing with it. */
.zcp5 #testimonials .testimonial-date{
  font-size:.72rem; color:rgba(255,255,255,.55); letter-spacing:.02em;
}

/* ------------------------------------------------------------------
   4.146 CUSTOMER E-MAIL TESTIMONIALS   (.zcp-emails)
   The Why Choose Us page carries 84 e-mails customers actually sent.
   Same carousel as the Google reviews, three differences:

     - the envelope glyph is KEPT. On the overview page it is legacy
       (those are Google reviews); here it is accurate, so it stays.
       It needs re-enabling explicitly because 4.145 turns it off for
       #testimonials globally - hence #testimonials.zcp-emails, which
       outscores that rule rather than fighting it with !important.
     - style.css declares font-family:FontAwesome (a Font Awesome 4
       name). The site ships Font Awesome 6, where that family does not
       resolve, so the glyph never rendered. Restated correctly here.
     - .testimonial-item is not positioned in style.css, so its
       absolutely-positioned ::before escaped to the carousel stage.
       position:relative pins it to its own card.
   ------------------------------------------------------------------ */
/* "N of 84 emails" - replaces 42 wrapped dots. Sits under the arrows,
   which .owl-nav has already moved below the stage. */
.zcp5 #testimonials.zcp-emails .zcp-owl-count{
  text-align:center; margin-top:.55rem;
  font-size:.74rem; letter-spacing:.03em; color:rgba(255,255,255,.55);
}

.zcp5 #testimonials.zcp-emails .testimonial-item{ position:relative; }
.zcp5 #testimonials.zcp-emails .testimonial-item::before{
  content:"\f0e0";
  font-family:"Font Awesome 6 Free"; font-weight:900;
  position:absolute; top:.6rem; right:.8rem;
  font-size:1rem; line-height:1; color:rgba(255,255,255,.30);
}

/* ------------------------------------------------------------------
   4.147 REASONS RAIL   (.zcp-reasons)
   Numbered points inside a hero .zcp-spec panel. Replaces three full
   width numbered circles that ate a screen on their own; the numbers
   were the only thing carrying meaning, so they are what survives.
   ------------------------------------------------------------------ */
.zcp5 .zcp-reasons{ list-style:none; margin:0; padding:0; display:grid; gap:.95rem; }
.zcp5 .zcp-reasons li{ display:flex; gap:.75rem; align-items:flex-start; }
.zcp5 .zcp-reasons .n{
  flex:none; width:1.7rem; height:1.7rem; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(255,255,255,.14); border:1px solid rgba(255,255,255,.28);
  font-size:.8rem; font-weight:700; line-height:1;
}
.zcp5 .zcp-reasons b{ display:block; font-size:.88rem; font-weight:700; margin-bottom:.1rem; }
.zcp5 .zcp-reasons .t{ display:block; font-size:.78rem; line-height:1.5; opacity:.78; }

/* ------------------------------------------------------------------
   4.148 CONTACT CARDS   (.zcp-contact)
   Two equal cards - the phone number and the address ARE the content,
   so they get the size instead of a heading above them.
   ------------------------------------------------------------------ */
.zcp5 .zcp-contact{ display:grid; grid-template-columns:1fr 1fr; gap:1.25rem; }
.zcp5 .zcp-contact .big{
  display:block; text-align:center; text-decoration:none;
  font-size:1.55rem; font-weight:700; letter-spacing:-.01em;
  color:var(--zcp-ink); margin:.4rem 0 .15rem;
}
.zcp5 .zcp-contact .big:hover{ color:#3b82f6; }
/* .sub, not .note: style.min.css already owns .note as a site-wide
   callout box (8px left rule, border, padding) and it hijacked this line. */
.zcp5 .zcp-contact .sub{ text-align:center; font-size:.76rem; color:var(--zcp-mut); margin:0; }
@media (max-width:767.98px){ .zcp5 .zcp-contact{ grid-template-columns:1fr; } }

/* ------------------------------------------------------------------
   4.149 CUSTOMER NAME LIST   (.zcp-namelist)
   ~106 company names. As a single scrolling column they read as a wall
   and most were below the fold; set in columns the whole list is
   visible at once, which is the only thing a list like this is for.
   ------------------------------------------------------------------ */
.zcp5 .zcp-namelist{
  list-style:none; margin:0; padding:0;
  columns:5; column-gap:1.75rem;
  font-size:.78rem; line-height:1.8; color:#374151;
}
/* Bullets, but not the browser's. Two things the default disc gets wrong
   here: it is too heavy next to .78rem type, and a name that wraps
   ("Social Security Administration") sets its second line flush under the
   bullet instead of under the name. A positioned marker plus a matching
   padding-left gives a proper hanging indent, so every column reads as one
   clean edge whether its names wrap or not.
   Dot is aligned to the FIRST line, not centered on the item - centering
   drifts down on any two-line entry. calc keeps it correct if the
   line-height above ever changes. */
.zcp5 .zcp-namelist li{
  break-inside:avoid;
  position:relative; padding-left:.85rem;
}
.zcp5 .zcp-namelist li::before{
  content:""; position:absolute; left:.1rem; top:calc(.9em - 2px);
  width:4px; height:4px; border-radius:50%;
  background:#b6c0cd;
}
.zcp5 .zcp-namelist mark{
  background:#fef3c7; color:#78350f; padding:0 .25rem; border-radius:3px; font-weight:600;
}
@media (max-width:1199.98px){ .zcp5 .zcp-namelist{ columns:4; } }
@media (max-width:991.98px) { .zcp5 .zcp-namelist{ columns:3; } }
@media (max-width:575.98px) { .zcp5 .zcp-namelist{ columns:2; } }

/* Expert head-shot inside a .zcp-trust-card. Float, not grid: the bio
   is long enough to wrap under the photo and a fixed column would
   leave a ragged gap. */
.zcp5 .zcp-expert-photo{
  float:left; width:72px; height:72px; border-radius:50%;
  object-fit:cover; margin:.15rem .9rem .4rem 0;
  border:2px solid var(--zcp-line);
}

/* Even split for pairs of trust cards that carry equal weight
   (contact, experts). The 1fr 2fr default is for the overview page,
   where the two panels deliberately are not equals. */
.zcp5 .zcp-trust.even{ grid-template-columns:1fr 1fr; }

/* ------------------------------------------------------------------
   4.16 DATA DICTIONARY  (.zcp-dict)
   85 rows in ONE table, replacing an 8-panel accordion. The accordion
   was hiding the argument: you cannot see that Business carries three
   times what Standard does when seven of eight groups are shut.

   Two things make one long table survivable, and both are required:
     - a sticky <thead>, so the edition columns never scroll away. It
       parks below the sticky product bar, hence the calc().
     - a filter, so 85 rows behave like a lookup instead of a scroll.
   ------------------------------------------------------------------ */
/* The one thing a reader must not get wrong, so it sits above the table
   rather than inside it. Amber, not red: this is a caution about shape,
   not an error. */
.zcp5 .zcp-keynote{
  background:#fffbeb; border:1px solid #fde68a; border-left:4px solid #d97706;
  border-radius:8px; padding:.85rem 1.1rem; margin:1.5rem 0 1rem;
  font-size:.84rem; line-height:1.65; color:#3f2d0b;
}
/* Shipped margin:0 0 1rem for a long time, which left every keynote flush
   against whatever came before it - a table, a card grid, a buy box. The
   top margin belongs on the component, not patched in page by page. Reset
   it when the keynote opens its container, where the gap would be stray. */
.zcp5 .zcp-keynote:first-child{ margin-top:0; }
.zcp5 .zcp-keynote code{
  background:#fef3c7; color:#78350f; padding:.08rem .35rem; border-radius:3px;
  font-size:.8rem;
}

/* Tone variants. The default keynote is amber - "pay attention to this".
   These three carry the severities the technical FAQ actually needs, and
   each keeps the left rule as the loudest signal so they still read as
   the same component rather than four unrelated boxes. Color is never
   the only cue: every one of these opens with a bolded lead-in that
   says what kind of note it is. */
.zcp5 .zcp-keynote.good{
  background:#f0fdf4; border-color:#bbf7d0; border-left-color:#16a34a; color:#14342a;
}
.zcp5 .zcp-keynote.good code{ background:#dcfce7; color:#14532d; }

.zcp5 .zcp-keynote.info{
  background:#f0f7ff; border-color:#bfdbfe; border-left-color:#3b82f6; color:#16304d;
}
.zcp5 .zcp-keynote.info code{ background:#dbeafe; color:#1e3a8a; }

.zcp5 .zcp-keynote.bad{
  background:#fef2f2; border-color:#fecaca; border-left-color:#dc2626; color:#4a1414;
}
.zcp5 .zcp-keynote.bad code{ background:#fee2e2; color:#7f1d1d; }

/* An alert-heading inside one of these was an <h4>/<h5>/<h6>; it needs to
   read as a lead-in, not as a document heading. */
.zcp5 .zcp-keynote > :first-child{ margin-top:0; }
.zcp5 .zcp-keynote > :last-child{ margin-bottom:0; }
.zcp5 .zcp-keynote .kn-head{
  display:block; font-weight:700; font-size:.86rem; margin-bottom:.3rem;
}

.zcp5 .zcp-dict-tools{
  display:flex; align-items:center; gap:.75rem; flex-wrap:wrap; margin-bottom:.6rem;
}
.zcp5 .zcp-dict-filter{
  flex:1 1 22rem; max-width:30rem;
  border:1.5px solid #cbd5e1; border-radius:.45rem;
  padding:.5rem .8rem; font-size:.86rem; color:var(--zcp-ink); background:#fff;
}
.zcp5 .zcp-dict-filter:focus{
  outline:none; border-color:#3b82f6; box-shadow:0 0 0 3px rgba(59,130,246,.15);
}
.zcp5 .zcp-dict-count{ font-size:.78rem; color:var(--zcp-mut); }

/* NO overflow here on desktop, deliberately. Setting overflow-x:auto makes
   the computed overflow-y `auto` as well (CSS spec: one axis non-visible
   forces the other), which turns this div into the scroll container - and
   a sticky <thead> then sticks to a box that never scrolls vertically, so
   it just leaves with the page. Measured: header at -3444px.
   The table fits its column widths at >=992px, so the wrapper only becomes
   scrollable below that, where the header is not sticky anyway. */
.zcp5 .zcp-dict-wrap{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
}
@media (max-width:991.98px){
  .zcp5 .zcp-dict-wrap{ overflow-x:auto; }
  .zcp5 .zcp-dict thead th,
  .zcp5 .zcp-dict tr.grp th{ position:static; }   /* honest: cannot stick in a scroller */
}
.zcp5 .zcp-dict{ width:100%; border-collapse:collapse; font-size:.82rem; margin:0; }
.zcp5 .zcp-dict th, .zcp5 .zcp-dict td{ padding:.5rem .75rem; text-align:left; }

/* Sticky header. 52px is the product bar; --zcp-topnav-h is measured off
   the site header at runtime, so this follows both. */
.zcp5 .zcp-dict thead th{
  position:sticky; top:calc(var(--zcp-topnav-h, 76px) + 52px); z-index:2;
  background:#f1f5f9; border-bottom:1px solid #cbd5e1;
  font-size:.72rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--zcp-mut); font-weight:700; white-space:nowrap;
}
.zcp5 .zcp-dict thead th.ed, .zcp5 .zcp-dict td:nth-child(n+4){ text-align:center; }

/* group band - carries the per-edition counts, which is where the
   Standard -> Business delta becomes visible */
.zcp5 .zcp-dict tr.grp th{
  position:sticky; top:calc(var(--zcp-topnav-h, 76px) + 82px); z-index:1;
  background:#eef2f7; color:var(--zcp-ink); font-size:.78rem; font-weight:700;
  border-top:1px solid #dbe3ec; border-bottom:1px solid #dbe3ec; text-transform:none;
  letter-spacing:0;
}
.zcp5 .zcp-dict tr.grp td{
  background:#eef2f7; border-top:1px solid #dbe3ec; border-bottom:1px solid #dbe3ec;
  font-size:.74rem; font-weight:700; color:var(--zcp-mut); text-align:center;
}
.zcp5 .zcp-dict tr.grp .n{ font-weight:400; color:var(--zcp-mut); font-size:.72rem; }
.zcp5 .zcp-dict tr.grp .delta{
  display:inline-block; margin-left:.5rem; padding:.05rem .4rem; border-radius:3px;
  background:#dcfce7; color:#166534; font-size:.66rem; font-weight:700;
  letter-spacing:.02em; text-transform:none;
}

.zcp5 .zcp-dict tbody tr:not(.grp){ border-bottom:1px solid #f1f5f9; }
.zcp5 .zcp-dict tbody tr:not(.grp):hover{ background:#f8fafc; }

/* the column name is the row's identity - it must be copyable and it must
   read as code, because it IS the string you type into your import */
.zcp5 .zcp-dict .fname{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.78rem; color:#0f172a; background:#f1f5f9;
  padding:.12rem .4rem; border-radius:3px; white-space:nowrap;
}
.zcp5 .zcp-dict td.d{ color:#374151; line-height:1.5; min-width:20rem; }
.zcp5 .zcp-dict .ex{ display:block; color:var(--zcp-mut); font-size:.74rem; margin-top:.15rem; }
.zcp5 .zcp-dict .ty{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.72rem; color:var(--zcp-mut); white-space:nowrap;
}
/* A second badge on the type cell, for a column the customer receives but
   should not build on - always empty, dated, or barely populated. Amber
   rather than red: the column is not broken, it just is not what the name
   promises. The word itself carries the meaning, so this still reads with
   color off. */
.zcp5 .zcp-dict .ty.warn{
  display:inline-block; margin-top:.2rem;
  background:#fffbeb; border:1px solid #fde68a; color:#92400e;
  padding:.02rem .3rem; border-radius:3px; font-weight:600;
}

/* ------------------------------------------------------------------
   Data caveat pill, shown at the START of the description.

   These used to be a second <span class="ty"> in the Type cell. Because
   .ty is nowrap, two of them stacked forced the Type column to ~182px
   and pushed the whole table past its container - which is what made
   the sticky header and group rows appear to sit outside the table.

   A caveat is not a type. It belongs with the description, where the
   person reading about the column will actually see it, and where it
   can wrap like everything else.
   ------------------------------------------------------------------ */
.zcp5 .zcp-dict .flag{
  display:inline-block; vertical-align:baseline;
  margin:0 .4rem .15rem 0; padding:.04rem .38rem;
  border-radius:3px; font-size:.68rem; font-weight:700;
  letter-spacing:.02em; white-space:nowrap;
  background:#f1f5f9; border:1px solid #e2e8f0; color:#475569;
}
.zcp5 .zcp-dict .flag.f-warn{ background:#fffbeb; border-color:#fde68a; color:#92400e; }
.zcp5 .zcp-dict .flag.f-legacy{ background:#f5f3ff; border-color:#ddd6fe; color:#5b21b6; }
.zcp5 .zcp-dict td .fa-check{ color:var(--zcp-go); }
.zcp5 .zcp-dict .no{ color:#cbd5e1; }
.zcp5 .zcp-dict-foot{ font-size:.75rem; color:var(--zcp-mut); margin:.7rem 0 0; line-height:1.6; }
.zcp5 .zcp-dict tr[hidden]{ display:none; }

@media (max-width:767.98px){
  .zcp5 .zcp-dict{ font-size:.78rem; }
  .zcp5 .zcp-dict td.d{ min-width:16rem; }
}

/* ------------------------------------------------------------------
   4.17 DOWNLOAD MANIFEST  (.zcp-manifest)
   Business ships six files and 1,014 columns; the page used to
   describe one table. Same table idiom as the dictionary so the two
   read as one document.
   ------------------------------------------------------------------ */
.zcp5 .zcp-manifest{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px; overflow-x:auto;
}
.zcp5 .zcp-manifest table{ width:100%; border-collapse:collapse; font-size:.82rem; margin:0; }
.zcp5 .zcp-manifest th, .zcp5 .zcp-manifest td{ padding:.55rem .8rem; text-align:left; }
.zcp5 .zcp-manifest thead th{
  background:#f1f5f9; border-bottom:1px solid #cbd5e1; color:var(--zcp-mut);
  font-size:.72rem; letter-spacing:.06em; text-transform:uppercase; white-space:nowrap;
}
.zcp5 .zcp-manifest tbody tr{ border-bottom:1px solid #f1f5f9; }
.zcp5 .zcp-manifest tbody tr:last-child{ border-bottom:0; }
.zcp5 .zcp-manifest tr.hi{ background:#f8fafc; }
.zcp5 .zcp-manifest .num, .zcp5 .zcp-manifest .ed{ text-align:right; white-space:nowrap; }
.zcp5 .zcp-manifest .ed{ text-align:center; color:var(--zcp-mut); font-size:.75rem; }
.zcp5 .zcp-manifest code{
  font-size:.76rem; color:#0f172a; background:#f1f5f9;
  padding:.12rem .4rem; border-radius:3px;
}

/* ------------------------------------------------------------------
   4.175 SAMPLE CARDS  (.zcp-samples)
   Three editions, three equal cards. The previous version was Bootstrap
   .card with a "Most Popular" badge on the Business one - a marketing
   sticker on a free evaluation download, where popularity is irrelevant:
   you take the sample for the edition you are assessing.
   Column counts come from the dictionary above, so the three cards say
   28 / 57 / 85 rather than repeating a bullet list of field names.
   ------------------------------------------------------------------ */
.zcp5 .zcp-samples{ display:grid; grid-template-columns:repeat(3,1fr); gap:1rem; align-items:stretch; }
.zcp5 .zcp-sample{
  display:flex; flex-direction:column;
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  border-top:3px solid var(--t-accent,#94a3b8); padding:1.15rem 1.25rem 1.25rem;
}
.zcp5 .zcp-sample.t-entry{ --t-accent:#c98a17; }
.zcp5 .zcp-sample.t-mid  { --t-accent:#7d9a2e; }
.zcp5 .zcp-sample.t-top  { --t-accent:#AB2827; }
.zcp5 .zcp-sample h3{
  font-size:1rem; font-weight:700; color:var(--zcp-ink); margin:0 0 .2rem;
}
.zcp5 .zcp-sample .cols{ font-size:var(--zcp-fs-sm); color:var(--zcp-mut); margin:0 0 .6rem; }
.zcp5 .zcp-sample .cols b{ color:var(--t-accent); font-size:1rem; }
.zcp5 .zcp-sample .what{ margin:0 0 .8rem; color:#374151; }
.zcp5 .zcp-sample .fmts{
  font-size:var(--zcp-fs-xs); color:var(--zcp-mut); letter-spacing:.03em;
  margin:0 0 1rem; padding-top:.7rem; border-top:1px solid #f1f5f9;
}
/* the button sits on the card floor so three ragged bodies still line up */
.zcp5 .zcp-sample .zcp-btn{ margin-top:auto; text-align:center; justify-content:center; }
.zcp5 .zcp-sample .zcp-btn span{
  display:block; font-size:var(--zcp-fs-xs); font-weight:400; color:var(--zcp-mut);
}
/* Two-edition products (Area Code). Three columns of card with only two
   cards leaves a hole on the right; constrained and centered instead, the
   same fix .zcp-tiers.two carries. */
.zcp5 .zcp-samples.two{
  grid-template-columns:repeat(2,1fr);
  max-width:44rem; margin-left:auto; margin-right:auto;
}

/* Four samples in a 3-up grid strands one card on its own row. Two rows of two
   reads as a set, and the wider column suits cards that carry a paragraph. */
.zcp5 .zcp-samples.four{
  grid-template-columns:repeat(2,1fr);
  max-width:56rem; margin-left:auto; margin-right:auto;
}

@media (max-width:991.98px){ .zcp5 .zcp-samples{ grid-template-columns:1fr; } }
@media (max-width:991.98px){ .zcp5 .zcp-samples.two{ grid-template-columns:1fr; } }
@media (max-width:767.98px){ .zcp5 .zcp-samples.four{ grid-template-columns:1fr; } }

/* ------------------------------------------------------------------
   4.176 SUPPLEMENTAL FILES  (.zcp-supp)
   The five Business-only datasets. Deliberately brief - what it is,
   how big, and which column you join on. Anything deeper belongs in
   the Census subject definitions that ship with the bundle.
   ------------------------------------------------------------------ */
.zcp5 .zcp-supp{ display:grid; grid-template-columns:repeat(2,1fr); gap:.85rem; }
.zcp5 .zcp-supp > div{
  background:#fff; border:1px solid #e5e7eb; border-radius:8px; padding:.9rem 1.1rem;
}
.zcp5 .zcp-supp > div.wide{ grid-column:1 / -1; }
.zcp5 .zcp-supp > div > code{
  display:inline-block; font-size:.78rem; color:#0f172a; background:#f1f5f9;
  padding:.15rem .45rem; border-radius:3px; margin-bottom:.45rem; word-break:break-all;
}
.zcp5 .zcp-supp p{ font-size:.83rem; line-height:1.6; color:#374151; margin:0 0 .45rem; }
.zcp5 .zcp-supp p code{
  background:#f1f5f9; padding:.05rem .3rem; border-radius:3px; font-size:.78rem;
}
.zcp5 .zcp-supp .m{ font-size:.74rem; color:var(--zcp-mut); }
.zcp5 .zcp-supp .m code{
  background:#f1f5f9; padding:.05rem .3rem; border-radius:3px; font-size:.72rem; color:#0f172a;
}
@media (max-width:767.98px){ .zcp5 .zcp-supp{ grid-template-columns:1fr; } }

/* ------------------------------------------------------------------
   4.18 FORMAT SPEC CARDS  (.zcp-fmtcard)
   Four formats, each a run of label/value pairs - so this is the same
   shape as .zcp-spec in the hero, and it is built the same way: a <dl>
   with hairline rows, label left, value right.

   Replaces four Bootstrap cards that wrapped a <table> to lay out two
   columns. Those ran ~600px tall each because long values wrapped in a
   40% column; here the label column is fixed and narrow, so values get
   the room they need.

   Color maps to file type - the one thing worth keeping from the old
   design. NOTE: the earlier port applied .f-* classes positionally and
   got the mapping WRONG (SQL wore Excel's color, Access wore SQL's).
   Mapped explicitly in the markup now, and checked.
   ------------------------------------------------------------------ */
.zcp5 .zcp-fmtgrid{ display:grid; grid-template-columns:repeat(2,1fr); gap:1rem; }
/* Same problem, and the same fix, as .zcp-rules > .wide below: with an ODD
   number of format cards the last one sits alone in a half-width column and
   reads as a mistake. The Canadian product ships three formats, not four
   (there is no SQL build), so its Access card closes the row instead. */
.zcp5 .zcp-fmtgrid > .zcp-fmtcard.wide{ grid-column:1 / -1; }
/* .eight - the boundary Overview's eight formats, as .zcp-fmtcard-lite
   glances rather than spec sheets. Four across keeps two tidy rows; the
   two-column default would run them down the page as a list. */
.zcp5 .zcp-fmtgrid.eight{ grid-template-columns:repeat(4,1fr); }
@media (max-width:991.98px){ .zcp5 .zcp-fmtgrid.eight{ grid-template-columns:repeat(2,1fr); } }
@media (max-width:479.98px){ .zcp5 .zcp-fmtgrid.eight{ grid-template-columns:1fr; } }
.zcp5 .zcp-fmtcard{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  border-left:4px solid var(--f-accent,#94a3b8); overflow:hidden;
}
.zcp5 .zcp-fmtcard.f-csv{ --f-accent:#3b82f6; }   /* universal / plain text */
.zcp5 .zcp-fmtcard.f-xls{ --f-accent:#7d9a2e; }   /* Excel green          */
.zcp5 .zcp-fmtcard.f-mdb{ --f-accent:#AB2827; }   /* Access red           */
.zcp5 .zcp-fmtcard.f-sql{ --f-accent:#c98a17; }   /* SQL amber            */
.zcp5 .zcp-fmtcard.f-tab{ --f-accent:#0f766e; }   /* tab-delimited teal   */

.zcp5 .zcp-fmtcard > header{
  display:flex; align-items:center; gap:.6rem; flex-wrap:wrap;
  padding:.8rem 1.1rem; border-bottom:1px solid #f1f5f9;
  font-size:.95rem; font-weight:700; color:var(--zcp-ink);
}
/* the extension as a token, not an icon font - it IS the identifier */
.zcp5 .zcp-fmtcard > header .tok{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.7rem; font-weight:700; letter-spacing:.06em;
  color:#fff; background:var(--f-accent); padding:.18rem .45rem; border-radius:3px;
}
.zcp5 .zcp-fmtcard > header .tag{
  margin-left:auto; font-style:normal; font-size:var(--zcp-fs-xs); font-weight:700;
  color:#166534; background:#dcfce7; padding:.12rem .45rem; border-radius:3px;
}
.zcp5 .zcp-fmtcard dl{ margin:0; padding:.35rem 1.1rem .8rem; }
.zcp5 .zcp-fmtcard dl > div{
  display:grid; grid-template-columns:9.5rem 1fr; gap:.9rem;
  padding:.45rem 0; border-bottom:1px solid #f8fafc;
}
.zcp5 .zcp-fmtcard dl > div:last-child{ border-bottom:0; }
.zcp5 .zcp-fmtcard dt{ font-size:var(--zcp-fs-sm); color:var(--zcp-mut); font-weight:400; }
.zcp5 .zcp-fmtcard dd{ margin:0; font-size:var(--zcp-fs-sm); color:#374151; line-height:1.55; }
.zcp5 .zcp-fmtcard code{
  background:#f1f5f9; color:#0f172a; padding:.05rem .3rem; border-radius:3px; font-size:.74rem;
}
.zcp5 .zcp-fmt-note{ font-size:var(--zcp-fs-xs); color:var(--zcp-mut); margin:.8rem 0 0; line-height:1.6; }

@media (max-width:1199.98px){ .zcp5 .zcp-fmtgrid:not(.eight){ grid-template-columns:1fr; } }
@media (max-width:575.98px){
  .zcp5 .zcp-fmtcard dl > div{ grid-template-columns:1fr; gap:.1rem; }
}

/* ------------------------------------------------------------------
   4.185 IMPORT RULES  (.zcp-rules)
   Was a Bootstrap alert box holding four bullet lists with orange
   headings - i.e. a callout wrapping four callouts. Flattened to four
   plain blocks under one quiet group label.
   ------------------------------------------------------------------ */
.zcp5 .zcp-rules{ display:grid; grid-template-columns:repeat(2,1fr); gap:1rem; }
/* With an odd number of blocks the last one sits alone in a half-width
   column and reads as a mistake. .wide lets it close the row instead. */
.zcp5 .zcp-rules > div.wide{ grid-column:1 / -1; }
.zcp5 .zcp-rules > div{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1rem 1.2rem;
}
.zcp5 .zcp-rules h4{
  font-size:.88rem; font-weight:700; color:var(--zcp-ink); margin:0 0 .5rem;
}
.zcp5 .zcp-rules ul{ margin:0; padding:0; list-style:none; }
.zcp5 .zcp-rules li{
  position:relative; padding-left:.9rem; margin-bottom:.4rem;
  font-size:var(--zcp-fs-sm); line-height:1.6; color:#374151;
}
.zcp5 .zcp-rules li:last-child{ margin-bottom:0; }
.zcp5 .zcp-rules li::before{
  content:""; position:absolute; left:0; top:calc(.8em - 2px);
  width:4px; height:4px; border-radius:50%; background:#b6c0cd;
}
.zcp5 .zcp-rules code{
  background:#f1f5f9; color:#0f172a; padding:.05rem .3rem; border-radius:3px; font-size:.74rem;
}
@media (max-width:767.98px){ .zcp5 .zcp-rules{ grid-template-columns:1fr; } }


/* ------------------------------------------------------------------
   4.186 CODE SAMPLES  (.zcp-code)
   Six languages showing the same lookup. Was Bootstrap nav-tabs over
   <pre class="bg-light p-3 rounded">, which had two problems: the tab
   strip wrapped to three rows on a phone, and the <pre> had no
   overflow rule, so a long line scrolled the whole PAGE sideways.

   Here the tab strip scrolls horizontally as one line, and the code
   block owns its own scrollbar. Dark panel because that is what a
   developer's editor looks like, and it separates "this is code you
   copy" from the prose around it without needing a heading to say so.
   ------------------------------------------------------------------ */
.zcp5 .zcp-code{
  background:#0f172a; border:1px solid #1e293b; border-radius:10px;
  overflow:hidden;
}
.zcp5 .zcp-code-tabs{
  display:flex; gap:0; overflow-x:auto; background:#111c33;
  border-bottom:1px solid #1e293b; scrollbar-width:thin;
}
.zcp5 .zcp-code-tabs button{
  flex:none; background:none; border:0; border-bottom:2px solid transparent;
  color:#94a3b8; font:600 .78rem/1 system-ui,sans-serif;
  padding:.7rem .95rem; cursor:pointer; white-space:nowrap;
  transition:color .12s, border-color .12s, background .12s;
}
.zcp5 .zcp-code-tabs button:hover{ color:#e2e8f0; background:rgba(255,255,255,.04); }
.zcp5 .zcp-code-tabs button[aria-selected="true"]{
  color:#fff; border-bottom-color:#3b82f6; background:rgba(59,130,246,.12);
}
.zcp5 .zcp-code-tabs button:focus-visible{ outline:2px solid #7dd3fc; outline-offset:-2px; }

.zcp5 .zcp-code-panel[hidden]{ display:none; }
.zcp5 .zcp-code-panel > h4{
  margin:0; padding:.85rem 1.1rem .1rem;
  font:700 .84rem/1.4 system-ui,sans-serif; color:#e2e8f0;
}
.zcp5 .zcp-code-panel > pre{
  margin:0; padding:.85rem 1.1rem 1.1rem; overflow-x:auto;
  background:none; border:0; border-radius:0;
}
.zcp5 .zcp-code-panel > pre code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.76rem; line-height:1.65; color:#cbd5e1;
  background:none; padding:0; white-space:pre; display:block;
}
/* the one note under each sample. Sits INSIDE the dark panel so it is
   read as part of the sample rather than as page prose. */
.zcp5 .zcp-code-note{
  margin:0; padding:.7rem 1.1rem; background:#111c33;
  border-top:1px solid #1e293b;
  font-size:.76rem; line-height:1.6; color:#94a3b8;
}
.zcp5 .zcp-code-note b{ color:#e2e8f0; }
.zcp5 .zcp-code-note code{
  background:rgba(255,255,255,.07); color:#e2e8f0;
  padding:.05rem .3rem; border-radius:3px; font-size:.72rem;
}
@media (max-width:575.98px){
  .zcp5 .zcp-code-panel > pre code{ font-size:.71rem; }
}

/* ------------------------------------------------------------------
   4.15 SOURCES & REFERENCES
   A trust signal, so it is presented as a document rather than a
   footnote dump: panelled, tighter type, real citation spacing.
   ------------------------------------------------------------------ */
.zcp5 .zcp-sources{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px; padding:1.5rem 1.75rem;
}
.zcp5 .zcp-sources > p{ font-size:.86rem; line-height:1.6; color:#374151; }
.zcp5 .zcp-sources ol.ref li{ font-size:.82rem; line-height:1.55; color:#374151; }
.zcp5 .zcp-sources a{ color:#3b82f6; word-break:break-word; }

/* ------------------------------------------------------------------
   PARKED — NOT CURRENTLY USED BY ANY PAGE
   Lifted out of an inline <style> block on the Overview page when its
   dev scaffolding was stripped. Kept because both are wanted later:

     .devnote  - the amber review-note strip used during design review.
                 Never ship it on a public page.
     .hx-pick  - the edition picker rail from the hero variant that lost.
                 Self-contained; drop the markup back in and it works.

   If either is still unused a few releases from now, delete it. Parked
   CSS that nobody revives is just weight on every page load.
   ------------------------------------------------------------------ */
.zcp5 .devnote,
.devnote{
  background:#fff7ed; border-bottom:1px solid #fed7aa; color:#7c2d12;
  padding:.75rem 1.25rem; font:400 .82rem/1.5 system-ui,sans-serif;
}
.zcp5 .hx-pick{ display:flex; flex-direction:column; gap:.5rem; height:100%; justify-content:center; }
.zcp5 .hx-pick a{
  display:flex; align-items:center; justify-content:space-between; gap:.75rem;
  background:rgba(255,255,255,.09); border:1px solid rgba(255,255,255,.20);
  border-radius:.5rem; padding:.65rem .85rem; text-decoration:none; color:#fff;
  transition:background .12s, border-color .12s;
}
.zcp5 .hx-pick a:hover{ background:rgba(255,255,255,.16); border-color:rgba(255,255,255,.42); color:#fff; }
.zcp5 .hx-pick a.is-rec{ border-color:#7dd3fc; background:rgba(14,165,233,.16); }
.zcp5 .hx-pick .nm{ font-size:.88rem; font-weight:700; }
.zcp5 .hx-pick .fl{ display:block; font-size:.7rem; opacity:.72; font-weight:400; }
.zcp5 .hx-pick .pr{ font-size:1rem; font-weight:700; white-space:nowrap; }
.zcp5 .hx-pick .pr small{ display:block; font-size:.62rem; opacity:.7; font-weight:400; text-align:right; }
.zcp5 .hx-pick .rec{
  font-size:.56rem; letter-spacing:.09em; text-transform:uppercase;
  color:#7dd3fc; font-weight:700; display:block;
}
@media (max-width:991.98px){ .zcp5 .hx-pick{ margin-top:1.5rem; } }

/* ------------------------------------------------------------------
   4.187 PRICED CONFIGURATOR  (.zcp-config)
   For the boundary products, which are not sold as editions: the price
   is a function of seats and geography and is calculated live.

   The inner class names are the ORIGINAL ones from products.css so the
   existing markup and its count.update() handlers keep working
   untouched - only the presentation is restated in the v5 language.

   Layout is options-left / sticky-summary-right on desktop, and the
   summary FIRST on mobile, because on a phone the running price is the
   thing you want in view while you change the inputs.
   ------------------------------------------------------------------ */
.zcp5 .zcp-config{ display:grid; grid-template-columns:1fr 20rem; gap:1.25rem; align-items:start; }
@media (max-width:991.98px){
  .zcp5 .zcp-config{ grid-template-columns:1fr; }
  .zcp5 .zcp-config .zcp-config-sum{ order:-1; position:static; }
}

/* ---- the options panel ---- */
.zcp5 .zcp-config .options-card{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  padding:1.25rem 1.4rem; margin:0;
}
.zcp5 .zcp-config .options-card h3{
  font-size:.95rem; font-weight:700; color:var(--zcp-ink);
  margin:1.75rem 0 .75rem; padding:0; border:0;
}
.zcp5 .zcp-config .options-card h3:first-of-type{ margin-top:0; }
.zcp5 .zcp-config .options-card h3 small{
  display:block; font-size:.76rem; font-weight:400; color:var(--zcp-mut);
  margin-top:.15rem; letter-spacing:0;
}
.zcp5 .zcp-config .form-section-divider{
  height:1px; background:#f1f5f9; border:0; margin:1.5rem 0;
}
.zcp5 .zcp-config .license-group-header{
  font-size:.68rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color:var(--zcp-mut); margin:1.1rem 0 .5rem;
}
.zcp5 .zcp-config .license-group-header:first-of-type{ margin-top:0; }

/* ---- one choice ----
   The whole row is the target, not just the 13px radio. */
.zcp5 .zcp-config .radio-option{
  border:1px solid #e5e7eb; border-radius:.5rem; margin:0 0 .4rem;
  transition:border-color .12s, background .12s;
}
.zcp5 .zcp-config .radio-option:hover{ border-color:#3b82f6; background:#f6fbff; }
.zcp5 .zcp-config .radio-option label{
  display:flex; align-items:center; gap:.6rem; width:100%; margin:0;
  padding:.6rem .8rem; cursor:pointer; font-size:.85rem; color:#374151;
}
.zcp5 .zcp-config .radio-option input[type="radio"]{
  flex:none; width:1rem; height:1rem; margin:0; accent-color:#3b82f6;
  /* products.css put .form-control on these, which stretches a radio to
     full width and pushes the label off the row. */
  padding:0; border:0; box-shadow:none; background:none; display:inline-block;
}
.zcp5 .zcp-config .radio-option:has(input:checked){
  border-color:#3b82f6; background:#f0f7ff;
}
.zcp5 .zcp-config .radio-option a.tool-tip{
  color:inherit; text-decoration:none; border-bottom:1px dotted #cbd5e1;
}
/* ---- the license list, two abreast ----
   Eleven choices stacked one per row made this the tallest thing on the
   page, and pushed the Enterprise group so far down that the two groups
   could not be compared without scrolling. Two columns halves the height.
   Headings, the transition note and the call-us tier still span the full
   width, so the grouping reads exactly as before. */
.zcp5 .zcp-config .license-section{
  display:grid; grid-template-columns:repeat(2,1fr); gap:.4rem .5rem;
  /* stretch, not start: the "Most Popular" badge makes one option taller
     than the one beside it, and a ragged row reads as a rendering fault */
  align-items:stretch;
}
.zcp5 .zcp-config .license-section > .radio-option{ display:flex; }
.zcp5 .zcp-config .license-section > .radio-option > label{ flex:1 1 auto; }
.zcp5 .zcp-config .license-section > h3,
.zcp5 .zcp-config .license-section > .license-group-header,
.zcp5 .zcp-config .license-section > .license-note{ grid-column:1 / -1; }
.zcp5 .zcp-config .license-section > .radio-option{ margin:0; }
/* Tier 5 carries a phone number on a second line - it needs the full row */
.zcp5 .zcp-config .license-section > .radio-option:last-of-type{ grid-column:1 / -1; }
@media (max-width:575.98px){
  .zcp5 .zcp-config .license-section{ grid-template-columns:1fr; }
}

.zcp5 .zcp-config .popular-badge{
  display:inline-block; margin-left:.45rem; padding:.05rem .4rem; border-radius:3px;
  background:#eef6ff; border:1px solid #bfdbfe; color:#1d4ed8;
  font-size:.6rem; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  vertical-align:middle;
}

/* ---- the geography inputs ---- */
.zcp5 .zcp-config .geography-selector{
  display:none; margin:.15rem 0 .6rem; padding:.75rem .8rem;
  background:#f8fafc; border:1px solid #e5e7eb; border-radius:.5rem;
}
.zcp5 .zcp-config .geography-selector.active{ display:block; }
.zcp5 .zcp-config .geography-selector select,
.zcp5 .zcp-config .geography-selector textarea{
  width:100%; font-size:.85rem; padding:.45rem .6rem; color:#0f172a;
  border:1px solid #cbd5e1; border-radius:.4rem; background:#fff;
}
.zcp5 .zcp-config .geography-selector select:focus,
.zcp5 .zcp-config .geography-selector textarea:focus{
  outline:0; border-color:#3b82f6; box-shadow:0 0 0 3px rgba(59,130,246,.15);
}
.zcp5 .zcp-config .geography-helper,
.zcp5 .zcp-config .license-note{
  font-size:.73rem; line-height:1.55; color:var(--zcp-mut); margin:.45rem 0 0;
}

/* ---- the running total ----
   Sticky, because the inputs are long enough to scroll the price out of
   view, and the price is the whole point of the section. */
.zcp5 .zcp-config-sum{ position:sticky; top:5.5rem; }
.zcp5 .zcp-config .count-display,
.zcp5 .zcp-config .price-display{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  padding:.9rem 1rem; margin:0 0 .6rem; text-align:center;
}
.zcp5 .zcp-config .price-display{
  border-color:#bfdbfe; background:linear-gradient(180deg,#f8fbff,#fff);
}
.zcp5 .zcp-config .count-label,
.zcp5 .zcp-config .price-label{
  display:block; font-size:.65rem; font-weight:700; letter-spacing:.1em;
  text-transform:uppercase; color:var(--zcp-mut); margin-bottom:.2rem;
}
.zcp5 .zcp-config .count-value{
  display:block; font-size:1.35rem; font-weight:800; color:var(--zcp-ink);
  letter-spacing:-.02em; line-height:1.15;
}
.zcp5 .zcp-config .price-amount{
  display:block; font-size:2rem; font-weight:800; color:var(--zcp-ink);
  letter-spacing:-.03em; line-height:1.1;
}
.zcp5 .zcp-config .btn-buy{
  display:block; width:100%; text-align:center; border:0; cursor:pointer;
  background:#AB2827; color:#fff; border-radius:.5rem;
  padding:.7rem 1rem; font-size:.9rem; font-weight:700; text-decoration:none;
  transition:background .12s, transform .12s;
}
.zcp5 .zcp-config .btn-buy:hover{ background:#8e2120; color:#fff; transform:translateY(-1px); }
.zcp5 .zcp-config .btn-buy:disabled,
.zcp5 .zcp-config .btn-buy[disabled]{
  background:#cbd5e1; cursor:not-allowed; transform:none;
}
.zcp5 .zcp-config .btn-reassurance{
  margin:.6rem 0 0; font-size:.72rem; line-height:1.6; color:var(--zcp-mut); text-align:center;
}
.zcp5 .zcp-config .btn-reassurance i{ color:var(--zcp-go); }

/* the quote errors were Bootstrap alert-danger inside the form */
.zcp5 .zcp-config-err{
  background:#fef2f2; border:1px solid #fecaca; border-left:4px solid #dc2626;
  border-radius:8px; padding:.7rem 1rem; margin:0 0 1rem;
  font-size:.84rem; color:#4a1414;
}

/* ------------------------------------------------------------------
   4.188 REASON CARDS  (.zcp-why)
   For "why would I want this?" sections: a small grid of claims, each
   with an icon, a short argument and a concrete example.

   Replaces .use-case-card on these, which set no font-size on its h3 -
   so the titles inherited the site's default heading size and came out
   roughly twice the scale of everything around them, with a 2rem icon
   to match. Same content, same icons, system typography.

   The icon sits in a tinted disc rather than running inline at 2rem:
   at this size a bare glyph next to bold text reads as an accident,
   while a disc reads as a deliberate marker and gives the eye a
   consistent left edge to scan down.
   ------------------------------------------------------------------ */
.zcp5 .zcp-why{
  display:grid; grid-template-columns:repeat(2,1fr); gap:1rem; align-items:stretch;
}
.zcp5 .zcp-why > .r{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  padding:1.15rem 1.25rem; height:100%;
  display:flex; flex-direction:column;
  transition:border-color .14s, box-shadow .14s, transform .14s;
}
.zcp5 .zcp-why > .r:hover{
  border-color:#3b82f6; box-shadow:0 10px 24px rgba(59,130,246,.10);
  transform:translateY(-3px);
}
.zcp5 .zcp-why h3{
  display:flex; align-items:center; gap:.6rem;
  font-size:1rem; font-weight:700; color:var(--zcp-ink);
  margin:0 0 .6rem; letter-spacing:-.01em; line-height:1.3;
}
.zcp5 .zcp-why h3 i{
  flex:none; width:2rem; height:2rem; border-radius:50%;
  background:#eef6ff; color:#3b82f6; font-size:.95rem;
  display:inline-flex; align-items:center; justify-content:center;
  margin:0;                       /* the old rule pushed 2rem icons right */
}
.zcp5 .zcp-why p{
  font-size:var(--zcp-fs); line-height:1.6; color:#374151; margin:0 0 .7rem;
}
/* The example is evidence for the claim above it, so it is set apart
   rather than just made smaller - a rule and a tint, the same move the
   dictionary uses for its own examples. */
.zcp5 .zcp-why .ex{
  margin:auto 0 0; padding:.6rem .75rem;
  background:#f8fafc; border-left:3px solid #e2e8f0; border-radius:0 6px 6px 0;
  font-size:var(--zcp-fs-sm); line-height:1.55; color:#475569;
}
.zcp5 .zcp-why .ex b{ color:var(--zcp-ink); }
.zcp5 .zcp-why .tag{
  align-self:flex-start; margin-top:.6rem;
  background:#f0fdf4; border:1px solid #bbf7d0; color:#166534;
  font-size:var(--zcp-fs-xs); font-weight:700; letter-spacing:.03em;
  padding:.12rem .5rem; border-radius:4px;
}
/* Three-up, for sections with six or nine reasons rather than four.
   Nine cards in a two-column grid leaves an orphan on the last row. */
.zcp5 .zcp-why.three{ grid-template-columns:repeat(3,1fr); }
@media (max-width:1199.98px){
  .zcp5 .zcp-why.three{ grid-template-columns:repeat(2,1fr); }
}

/* Edition markers. Neutral rather than alarming - this is wayfinding,
   not a warning, so it uses the tier accents the pricing cards already
   established rather than the amber caution tone. */
.zcp5 .zcp-why .tag.t-dlx{
  background:#f6faef; border-color:#d9e8b8; color:#4d6218;
}
.zcp5 .zcp-why .tag.t-std{
  background:#fdf6e8; border-color:#f2ddb0; color:#8a5f10;
}

@media (max-width:767.98px){
  .zcp5 .zcp-why,
  .zcp5 .zcp-why.three{ grid-template-columns:1fr; }
}

/* Catalog: three across, then two, then one. The stat pairs stay two
   across all the way down - they are short, and stacking them makes the
   card twice as tall for no gain. */
@media (max-width:991.98px){
  .zcp5 .zcp-catalog{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:575.98px){
  .zcp5 .zcp-catalog,
  .zcp5 .zcp-catalog.two{ grid-template-columns:1fr; max-width:none; }
}
@media (max-width:768px){
  .zcp5 .zcp-hero.compact{ padding:30px 0 26px; }
  .zcp5 .zcp-hero-sub{ font-size:.94rem; }
}

/* ------------------------------------------------------------------
   4.05 COMPACT HERO  (.zcp-hero.compact)
   Promoted from boundary-demo.v5.css (.bd-hero-compact), unchanged in
   effect. The full hero carries a lede, a stat strip, two CTAs and a
   spec panel; a page that is itself an index has none of that to say
   about itself, and padding a hero out with generalities is how a
   catalog page ends up saying nothing on its first screen.

   The veil is re-angled to vertical. The full hero's diagonal exists to
   keep the left column readable while the art breathes on the right;
   centered text needs the opposite - even cover, darkest where the
   content sits.
   ------------------------------------------------------------------ */
.zcp5 .zcp-hero.compact{ padding:46px 0 40px; text-align:center; }
.zcp5 .zcp-hero.compact .zcp-veil{
  background:linear-gradient(180deg,
    rgba(9,17,34,.70) 0%, rgba(9,17,34,.85) 52%, rgba(9,17,34,.92) 100%);
}
.zcp5 .zcp-hero.compact h1{ margin-bottom:.5rem; }
.zcp5 .zcp-hero-sub{
  margin:0 auto; max-width:46rem;
  font-size:1.02rem; line-height:1.55; color:#cbd5e1;
}

/* ------------------------------------------------------------------
   4.06 TASK ROUTER  (.zcp-router)
   Cards keyed to a job rather than to a product name. The old products
   page listed thirteen databases in one flat run and left the visitor
   to work out that address validation means ZIP+4 while territory
   mapping means Boundary Data - vocabulary you only have once you
   already own the thing.

   So the card leads with the task, in the buyer's words, and names the
   product underneath as the answer. Reading order is deliberate:
   question, then answer, then the one line that justifies it.

   auto-fit rather than a fixed column count: the set of jobs worth
   listing will change, and a fixed grid strands the last card whenever
   the count stops dividing.
   ------------------------------------------------------------------ */
.zcp5 .zcp-router{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));
  gap:.85rem; align-items:stretch;
}
.zcp5 .zcp-router a{
  display:flex; flex-direction:column; gap:.3rem;
  background:#fff; border:1px solid var(--zcp-line); border-radius:10px;
  padding:1rem 1.1rem 1.05rem; text-decoration:none;
  transition:border-color .13s ease, box-shadow .13s ease, transform .13s ease;
}
.zcp5 .zcp-router a:hover{
  border-color:#c7d2e0; box-shadow:0 4px 14px rgba(15,23,42,.09);
  transform:translateY(-2px);
}
.zcp5 .zcp-router .r-task{
  font-size:.95rem; font-weight:700; color:var(--zcp-ink); line-height:1.3;
}
.zcp5 .zcp-router .r-goes{
  display:flex; align-items:center; gap:.36rem;
  font-size:var(--zcp-fs-sm); font-weight:600; color:#0b6ea8;
}
.zcp5 .zcp-router .r-goes i{ font-size:.7rem; opacity:.75; }
.zcp5 .zcp-router .r-why{
  margin:.1rem 0 0; font-size:var(--zcp-fs-sm);
  color:var(--zcp-mut); line-height:1.5;
}

/* ------------------------------------------------------------------
   4.07 PRODUCT CARDS  (.zcp-catalog)
   One card per product, grouped into families by a .zcp-fgroup heading
   above each grid.

   What the old cards carried: a stock photograph of a street, a
   "Featured" badge on every single one, a sentence, and a Read More
   button. Nothing separable, nothing priced, and a badge that means
   nothing once everything wears it.

   What these carry instead: three or four measured figures and the
   entry price. Those are the terms people actually choose on, and they
   are the same figures the product page's own stat strip states, so the
   catalog cannot drift away from the pages it indexes.

   .c-stats is a dl because that is what it is - a term and its value,
   repeated. It reads correctly to a screen reader in a way a run of
   divs does not.
   ------------------------------------------------------------------ */
.zcp5 .zcp-catalog{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:1rem; align-items:stretch;
}
.zcp5 .zcp-catalog.two{ grid-template-columns:repeat(2,1fr); max-width:44rem; }
.zcp5 .zcp-cat{
  display:flex; flex-direction:column;
  background:#fff; border:1px solid var(--zcp-line); border-radius:10px;
  border-top:3px solid var(--t-accent,#94a3b8);
  padding:1.1rem 1.2rem 1.2rem;
}
/* Family accents. Same three-step ladder the tier and sample cards use,
   so a color means the same thing everywhere on the system. */
.zcp5 .zcp-cat.f-zip  { --t-accent:#AB2827; }
.zcp5 .zcp-cat.f-bdry { --t-accent:#E67700; }
.zcp5 .zcp-cat.f-intl { --t-accent:#7d9a2e; }
.zcp5 .zcp-cat.f-hist { --t-accent:#5b6b8c; }
.zcp5 .zcp-cat.f-tool { --t-accent:#0b6ea8; }

.zcp5 .zcp-cat h3{
  font-size:1.02rem; font-weight:700; color:var(--zcp-ink);
  margin:0 0 .3rem; line-height:1.25;
}
.zcp5 .zcp-cat .c-what{
  margin:0 0 .8rem; font-size:var(--zcp-fs-sm);
  color:var(--zcp-mut); line-height:1.55;
}
.zcp5 .zcp-cat .c-stats{
  display:grid; grid-template-columns:repeat(2,1fr);
  gap:.5rem .8rem; margin:0 0 .95rem;
  padding-top:.75rem; border-top:1px solid var(--zcp-line);
}
.zcp5 .zcp-cat .c-stats > div{ min-width:0; }
.zcp5 .zcp-cat .c-stats dt{
  font-size:var(--zcp-fs-xs); font-weight:400; color:var(--zcp-mut);
  text-transform:uppercase; letter-spacing:.03em; line-height:1.3;
}
.zcp5 .zcp-cat .c-stats dd{
  margin:0; font-size:var(--zcp-fs); font-weight:600;
  color:var(--zcp-ink); line-height:1.3;
  font-variant-numeric:tabular-nums;
}
/* Foot is pushed down by margin-top:auto so cards in a row line their
   prices and buttons up regardless of how long the description ran. */
.zcp5 .zcp-cat .c-foot{
  margin-top:auto; display:flex; align-items:center;
  justify-content:space-between; gap:.6rem; flex-wrap:wrap;
}
.zcp5 .zcp-cat .c-price{
  font-size:var(--zcp-fs-sm); color:var(--zcp-mut); line-height:1.25;
}
.zcp5 .zcp-cat .c-price b{
  display:block; font-size:1.02rem; font-weight:700; color:var(--zcp-ink);
}
.zcp5 .zcp-cat .c-price.free b{ color:var(--zcp-go); }

/* ------------------------------------------------------------------
   4.195 SECTION CLOSER  (.zcp-closer)
   For pages where PRICING sits near the top. That ordering inverts the
   page's gravity: instead of every section feeding downhill into the
   buy action, every section below pricing leads AWAY from it. A reader
   who resolves their last doubt in the FAQ then has nowhere to go.

   So each section that settles a real purchase question ends with one
   action and one line saying which question it just settled. One per
   section, never two - a page that asks on every scroll stops being
   read as information.
   ------------------------------------------------------------------ */
.zcp5 .zcp-closer{
  display:flex; align-items:center; justify-content:center;
  gap:.9rem 1.1rem; flex-wrap:wrap; text-align:center; margin-top:1.6rem;
}
.zcp5 .zcp-closer p{
  margin:0; font-size:var(--zcp-fs-sm); color:var(--zcp-mut); line-height:1.5;
}
.zcp5 .zcp-closer p b{ color:var(--zcp-ink); }

/* ------------------------------------------------------------------
   4.19 ARCHIVE COVERAGE TIMELINE  (.zcp-tl)
   Built for the Historical page. The archive IS the product, and the
   old page only ever asserted it ("20+ years", "250+ months") - words
   a buyer has to take on faith. This draws the same span to scale, so
   the Census-era boundaries and the growing tail are visible instead.

   Segment widths arrive as inline style="width:N%" computed in ASP from
   the live month list, so the newest segment widens by itself every
   month. Nothing here is a maintained number.

   The ramp is gray light-to-dark, not three hues: it encodes older ->
   newer, and this page already spends its color budget on the tier
   cards. Adding a fourth and fifth hue here would undo that.
   ------------------------------------------------------------------ */
.zcp5 .zcp-tl{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  padding:1.25rem 1.5rem 1.15rem;
}
.zcp5 .zcp-tl-track{
  display:flex; width:100%; border-radius:6px; overflow:hidden;
  border:1px solid #e5e7eb;
}
.zcp5 .zcp-tl-seg{
  min-width:0;                       /* lets a narrow segment ellipsis instead of forcing the track wide */
  padding:.7rem .8rem; color:#fff; background:var(--s-accent,#94a3b8);
  border-right:1px solid rgba(255,255,255,.4);
}
.zcp5 .zcp-tl-seg:last-child{ border-right:0; }
.zcp5 .zcp-tl-seg b,
.zcp5 .zcp-tl-seg span{
  display:block; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.zcp5 .zcp-tl-seg b{ font-size:var(--zcp-fs-sm); font-weight:700; line-height:1.25; }
.zcp5 .zcp-tl-seg span{ font-size:var(--zcp-fs-xs); opacity:.85; }
.zcp5 .zcp-tl-seg.e00{ --s-accent:#94a3b8; }
.zcp5 .zcp-tl-seg.e10{ --s-accent:#64748b; }
.zcp5 .zcp-tl-seg.e20{ --s-accent:#334155; }

/* A second track on the SAME scale, for a second variable (edition, where
   the first track carries Census era). Two aligned rows against one x-axis
   is a small multiple: it lets the eye read "the field set changed HERE and
   the Census changed THERE" without either strip explaining the other.

   Slim, and labels only - the sub-track's job is where the boundary falls,
   not what the dates are. Those are on the scale below both tracks. */
.zcp5 .zcp-tl-track.slim{ margin-top:.35rem; }
.zcp5 .zcp-tl-track.slim .zcp-tl-seg{ padding:.4rem .8rem; }
.zcp5 .zcp-tl-track.slim .zcp-tl-seg span{ display:none; }
.zcp5 .zcp-tl-seg.ed-old{ --s-accent:#b6c0cd; }
.zcp5 .zcp-tl-seg.ed-new{ --s-accent:#64748b; }

/* Row caption. Quiet enough to label a track without competing with it. */
.zcp5 .zcp-tl-cap{
  font-size:var(--zcp-fs-xs); font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--zcp-mut); margin:0 0 .3rem;
}
.zcp5 .zcp-tl-cap + .zcp-tl-track{ margin-top:0; }
.zcp5 .zcp-tl-track + .zcp-tl-cap{ margin-top:.9rem; }

.zcp5 .zcp-tl-scale{
  display:flex; justify-content:space-between;
  font-size:var(--zcp-fs-xs); color:var(--zcp-mut); margin-top:.4rem;
}
.zcp5 .zcp-tl-foot{
  font-size:var(--zcp-fs-xs); color:var(--zcp-mut);
  line-height:1.6; margin:.85rem 0 0;
}

/* Below 768px the segments are too narrow to carry a label, so the bar
   stops being a bar and becomes a list. The inline width from ASP has to
   be beaten here - hence !important, the one place in this file it is
   justified: the declaration it overrides is on the element itself. */
@media (max-width:767.98px){
  .zcp5 .zcp-tl{ padding:1rem 1.1rem; }
  .zcp5 .zcp-tl-track{ flex-direction:column; }
  .zcp5 .zcp-tl-seg{
    width:auto !important; border-right:0;
    border-bottom:1px solid rgba(255,255,255,.4);
  }
  .zcp5 .zcp-tl-seg:last-child{ border-bottom:0; }
  .zcp5 .zcp-tl-seg b, .zcp5 .zcp-tl-seg span{ white-space:normal; }
  .zcp5 .zcp-tl-scale{ display:none; }
}

@media (max-width:991.98px){
  /* .even is listed explicitly: it is a class more than the base rule,
     and a media query adds no specificity of its own. */
  .zcp5 .zcp-trust,
  .zcp5 .zcp-trust.even{ grid-template-columns:1fr; }
}


/* ==================================================================
   5. PURCHASE MACHINERY
   ------------------------------------------------------------------
   RULE 3 APPLIES HERE. Every class name below is a contract with
   products.js, which BUILDS this markup at runtime into
   #regular-options / #redistribution-options and toggles .selected on
   click. Names are re-scoped under .zcp5 and restyled - never renamed,
   never restructured. If you rename anything here, the cart breaks
   silently: the modal still opens, it just stops responding.

   Bound by products.js:
     #modal-purchase #license-tabs #proceed-checkout
     #product-class #product-name #modal-purchase select
     #regular-tos-container #redistribution-tos-container
     #license-footer-redistribution
     .term-option .single-option .selected .month-selector
   ================================================================== */
.zcp5 .purchase .modal-body{ max-height:calc(100vh - 200px); overflow-y:auto; }
.zcp5 .purchase .modal-footer{ background:#fff; bottom:0; position:sticky; z-index:10; }

/* header carries the same navy as the hero and the explorer panel */
.zcp5 .purchase .modal-header{ background:var(--zcp-navy); border-bottom:0; }
.zcp5 .purchase .modal-header .modal-title{ color:#fff; font-size:1rem; font-weight:700; }
.zcp5 .purchase .modal-header #product-name{ opacity:.85; font-weight:400; }
.zcp5 .purchase .modal-header .btn-close{ filter:invert(1) grayscale(1) brightness(2); }

/* license tabs as a segmented control, matching the explorer's edition
   switcher rather than Bootstrap's default underlined tabs */
/* The color here MUST be !important. style.min.css carries
   `.nav .nav-item button { color:#fff !important }`, so an inactive tab
   renders white-on-white and becomes unreadable without this. products.css
   used to counterweight it with `.purchase .nav .nav-item button{color:#000}`;
   dropping products.css removed that, so the counterweight lives here now. */
.zcp5 .purchase .nav-tabs{ border-bottom:1px solid var(--zcp-line); gap:.35rem; }
.zcp5 .purchase .nav-tabs .nav-link{
  border:1px solid #cbd5e1; border-radius:999px; background:#fff;
  color:#334155 !important; font-size:.82rem; font-weight:600; padding:.35rem .9rem;
  margin-bottom:.4rem;
}
.zcp5 .purchase .nav-tabs .nav-link:hover{ border-color:#94a3b8; background:#f1f5f9; }
.zcp5 .purchase .nav-tabs .nav-link.active{
  background:var(--zcp-navy); border-color:var(--zcp-navy); color:#fff !important;
}

.zcp5 .tab-description{
  padding:.85rem 1rem; background:#f8fafc; border:1px solid #e5e7eb;
  border-left:3px solid var(--zcp-accent); border-radius:.4rem; margin-bottom:1.1rem;
}
.zcp5 .tab-description strong{ font-size:.9rem; color:var(--zcp-ink); }
.zcp5 .tab-description p{ margin:0; color:var(--zcp-mut); }
.zcp5 #product-tos-container{
  padding:.75rem 1rem; background:#f8fafc;
  border-left:3px solid var(--zcp-accent); border-radius:.4rem;
}
.zcp5 #product-tos-container a,
.zcp5 .license-header a,
.zcp5 .single-option-label a{ color:#3b82f6; text-decoration:none; font-size:.85rem; font-weight:500; }
.zcp5 #product-tos-container a:hover,
.zcp5 .license-header a:hover,
.zcp5 .single-option-label a:hover{ text-decoration:underline; }

/* license group */
.zcp5 .license-option{
  background:#fff; border:1px solid #e5e7eb; border-radius:10px;
  margin-bottom:1.25rem; padding:1rem;
}
.zcp5 .license-header{
  display:flex; justify-content:space-between; align-items:center;
  margin-bottom:1rem; padding-bottom:.7rem; border-bottom:1px solid var(--zcp-line);
}
.zcp5 .license-header strong{ color:var(--zcp-ink); font-size:.95rem; display:block; }
.zcp5 .license-header small{ font-size:.8rem; color:var(--zcp-mut); }
.zcp5 .license-header .badge{ font-size:.7rem; padding:.32rem .6rem; }
.zcp5 .license-group-header{
  font-size:1rem; font-weight:600; color:var(--zcp-ink);
  margin:1.5rem 0 .75rem; padding-left:.5rem; border-left:4px solid var(--zcp-accent);
}
.zcp5 .license-group-header:first-of-type{ margin-top:0; }
.zcp5 .license-note{
  background:#f0f9ff; border-left:4px solid var(--zcp-accent);
  padding:.75rem 1rem; margin:1rem 0; font-size:.85rem;
  color:#075985; border-radius:.3rem;
}

/* term / single option rows - selection state must stay .selected */
.zcp5 .term-options{ display:flex; flex-direction:column; gap:.5rem; }
.zcp5 .term-option,
.zcp5 .single-option{
  display:flex; align-items:center; padding:.75rem;
  border:1.5px solid #e5e7eb; border-radius:.5rem; cursor:pointer;
  transition:border-color .15s, background .15s; margin:0; background:#fff;
}
.zcp5 .single-option{ align-items:flex-start; justify-content:space-between; margin-bottom:.75rem; }
.zcp5 .term-option:hover,
.zcp5 .single-option:hover{ border-color:#94a3b8; background:#f8fafc; }
.zcp5 .term-option.selected,
.zcp5 .single-option.selected{ border-color:var(--zcp-accent); background:#f0f9ff; }
.zcp5 .term-option input[type="radio"],
.zcp5 .single-option-content input[type="radio"]{
  cursor:pointer; height:18px; width:18px; margin-right:.75rem; accent-color:var(--zcp-accent);
}
.zcp5 .single-option-content input[type="radio"]{ margin-top:.25rem; }
.zcp5 .term-option input[type="radio"]:checked ~ .term-details{ color:#075985; font-weight:600; }
.zcp5 .term-details{ display:flex; align-items:center; gap:1rem; flex:1; }
.zcp5 .term-label{ font-size:.92rem; font-weight:500; min-width:80px; }
.zcp5 .term-price,
.zcp5 .single-option-price{ color:var(--zcp-ink); font-weight:700; font-size:1.05rem; }
.zcp5 .single-option-price{ font-size:1.15rem; padding-left:1rem; white-space:nowrap; }
.zcp5 .savings{
  background:#e8f5e9; border-radius:4px; color:#1f6b23;
  font-size:.78rem; font-weight:700; margin-left:auto; padding:2px 8px;
}
.zcp5 .single-option-content{ display:flex; align-items:flex-start; flex:1; gap:.75rem; }
.zcp5 .single-option-label{ flex:1; }
.zcp5 .single-option-label strong{ display:block; font-size:.95rem; color:var(--zcp-ink); }
.zcp5 .single-option-label small{ color:var(--zcp-mut); font-size:.85rem; }

.zcp5 .month-selector{ max-width:300px; margin-top:.5rem !important; }
.zcp5 .month-selector:disabled{ opacity:.5; cursor:not-allowed; background-color:#e9ecef; }
.zcp5 .month-selector:not(:disabled){ cursor:pointer; }

/* Checkout is a real conversion action, so it gets the one "go" color.
   NOTE the doubled id. #proceed-checkout is a .btn-primary, so the button
   reset in section 2 also matches it - and that selector scores (1,3,0)
   because the :not(#top-nav *) guard contributes an id. Both rules carry
   !important, so specificity decides and a single-id rule LOSES: the
   button silently renders neutral white. Scoping through #modal-purchase
   takes it to (2,1,0), which wins. Do not "simplify" this to one id. */
.zcp5 #modal-purchase #proceed-checkout{
  background:var(--zcp-go) !important; border-color:var(--zcp-go) !important;
  color:#fff !important; font-weight:700;
}
.zcp5 #modal-purchase #proceed-checkout:disabled{ opacity:.45; }
.zcp5 #modal-purchase #proceed-checkout:not(:disabled):hover{ filter:brightness(1.08); }
.zcp5 .license-footer-redistribution{ margin-top:1rem; }
/* the cross-sell button into the redistribution tab - .btn-outline-primary
   is not covered by the section 2 reset, so it would otherwise keep the
   site theme's red */
.zcp5 #license-footer-redistribution .btn{
  background:#fff !important; color:#3b82f6 !important;
  border:1.5px solid #3b82f6 !important; font-weight:600;
}
.zcp5 #license-footer-redistribution .btn:hover{ background:#eff6ff !important; }

@media (max-width:575.98px){
  .zcp5 .license-header{ flex-direction:column; align-items:flex-start; gap:.5rem; }
  .zcp5 .license-header .badge{ align-self:flex-start; }
  .zcp5 .single-option{ flex-direction:column; gap:.75rem; }
  .zcp5 .single-option-price{ padding-left:0; align-self:flex-start; }
  .zcp5 .term-details{ flex-wrap:wrap; }
  .zcp5 .savings{ margin-left:0; width:100%; }
  .zcp5 .month-selector{ max-width:100%; }
}


/* ==================================================================
   6. UTILITIES
   ================================================================== */
.zcp5 .spinner{
  left:50%; position:absolute; top:50%;
  transform:translate(-50%,-50%); z-index:100;
}
.zcp5 .spinner-container{ position:relative; }
.zcp5 .loader-inline{
  animation:zcp-rotation 1s linear infinite;
  border:2px solid #000; border-bottom-color:transparent; border-radius:50%;
  box-sizing:border-box; display:inline-block; height:15px; width:15px;
}
.zcp5 .thinking-text{
  animation:zcp-shimmer 4.5s linear infinite;
  background:linear-gradient(90deg,#000 0%,#3a3a3a 35%,#bdbdbd 50%,#3a3a3a 65%,#000 100%);
  background-clip:text; -webkit-background-clip:text;
  background-size:300% 100%; background-position:-150% 0;
  -webkit-text-fill-color:transparent;
  font-weight:600; will-change:background-position;
}
.zcp5 .thinking-text2{
  animation:zcp-shimmer 4.5s linear infinite;
  background-color:#f1f5f9; font-weight:600; padding:20px;
  will-change:background-position;
}
.zcp5 .dark-overlay::after{ opacity:.65; }
.zcp5 .no-wrap th,
.zcp5 .no-wrap td{ white-space:nowrap; }
.zcp5 .scroll::-webkit-scrollbar{ width:12px; }
.zcp5 .scroll::-webkit-scrollbar-thumb{
  box-shadow:inset 0 0 6px rgba(0,0,0,.5); border-radius:10px;
}
.zcp5 .scroll::-webkit-scrollbar-track{
  box-shadow:inset 0 0 6px rgba(0,0,0,.3); border-radius:10px;
}
.zcp5 .card-footer,
.zcp5 .card-header{ width:100%; }
.zcp5 .form-control-sm{ transform:scale(.75); }
.zcp5 select{ max-width:100%; }

/* keyframes are global by nature - prefixed so they cannot collide with
   the identically-named ones still in products.css during rollout */
@keyframes zcp-rotation{
  0%   { transform:rotate(0deg); }
  100% { transform:rotate(360deg); }
}
@keyframes zcp-shimmer{
  to { background-position:150% 0; }
}


/* ==================================================================
   7. RESPONSIVE
   ================================================================== */
@media (max-width:991.98px){
  .zcp5 .zcp-rail,
  .zcp5 .zcp-spec{ margin-top:1.5rem; }
  .zcp5 .zcp-tiers{ grid-template-columns:1fr; }
}

@media (max-width:767.98px){
  .zcp5 .zcp-api-strip > a{ margin-left:0; }
}

@media (max-width:575.98px){
  .zcp5 .zcp-next{ flex-wrap:wrap; }
  .zcp5 .zcp-next > div{ flex:1 1 50%; border-bottom:1px solid #f1f5f9; }
}

@media (max-width:576px){
  .zcp5 #hero .lead{ font-size:1rem; }
}

@media (prefers-reduced-motion:reduce){
  .zcp5 .thinking-text{ animation:none; background-position:0 0; }
}
