/*
 * zipcodemaps.com brand tokens (multi-site Z4, docs/MULTI-SITE.md §3).
 *
 * HOW THIS WORKS. Styles/tailwind.css compiles its @theme into
 * `@layer theme { :root, :host { --color-brand-600: … } }`, and every utility references
 * `var(--color-…)`. This file is UNLAYERED, so its `:root` declarations win over the layered
 * theme regardless of load order -- one Tailwind build, one small token sheet per site.
 * _Head.cshtml links it after site.css when SiteOptions.TokenStylesheet is set; MM sets none
 * and its HTML is byte-identical. Redefine ONLY --color-brand-* (and --font-* if a site ever
 * needs it); accent/ink/surface/success tokens are shared and stay in tailwind.css.
 * ZcmTokenSheetTests parses this file and enforces both the shape and the ratios below.
 *
 * The one exception to "tokens only" is the PER-SITE COMPONENT OVERRIDES block at the bottom
 * (the nav band, 2026-09-04; the footer's dark band, 2026-09-15; the footer's sales-code popup,
 * 2026-09-17; the announcement bar's height, 2026-09-21; the nav band's height, 2026-09-22) --
 * read the comment there before adding another.
 *
 * PALETTE: carried from the legacy zipcodemaps.com site (owner, 2026-09-03; source
 * C:\CodeFiles\Projects\ZIPCodeMaps_Old\ZipCodeMaps\css\master.css), whose three blues were
 *   #5386a4  the primary header band and link colour   -> brand-500
 *   #30607e  the dark nav band                          -> brand-700
 *   #003471  heading text                               -> brand-900, SUPERSEDED
 * BRAND-900 IS NO LONGER A LEGACY ANCHOR (owner, 2026-09-08): it ships #132a45, a darker,
 * less saturated navy than the legacy #003471, and every pair it appears in gets BETTER
 * (12.14 -> 14.53 on white). Two of the three blues are still carried verbatim, so
 * ZcmTokenSheetTests pins 500 and 700 as legacy anchors and 900 in its own assertion --
 * changing one of these is still a palette decision, not a tidy-up.
 * The other seven shades are interpolated in the same hue (~203°). #5386a4 is only 3.95:1 on
 * white, so -- exactly like accent-600 on MM -- brand-500 is for large fills and non-text
 * accents ONLY; text uses 600+ (the MM views already do).
 *
 * WCAG 2.2 AA, measured (ZcmTokenSheetTests re-measures on every run):
 *   on white:      brand-600 5.37 · brand-700 6.77 · brand-800 10.09 · brand-900 14.53
 *   white on:      brand-600 5.37 · brand-700 6.77 · brand-800 10.09 · brand-900 14.53
 *   on brand-50:   ink 7.94 · brand-600 4.80 · brand-700 6.05 · brand-800 9.01 · brand-900 12.99
 *                  success-700 6.37 · accent-700 5.78
 *   on brand-100:  ink 6.97
 *   band (#48758f, the nav AND the footer since 2026-09-15):
 *                  white 4.98 · white underline 4.98 · brand-100 3.91 (FAILS -- why the footer's
 *                  text is repainted white) · brand-300 divider 2.25 · brand-700 divider 1.36
 *   ink-muted on brand-50 is 4.14 -- the SAME AA failure as on MM (4.15); TintedSurfaceContrast
 *   guards it by class name and applies to ZCM pages unchanged.
 */
:root {
  --color-brand-50: #edf3f7;
  --color-brand-100: #d8e6ee;
  --color-brand-200: #b5cede;
  --color-brand-300: #90b4cb;
  --color-brand-400: #6c9ab7;
  --color-brand-500: #5386a4; /* legacy primary band -- large fills / accents only, 3.95:1 */
  --color-brand-600: #3b7091;
  --color-brand-700: #30607e; /* legacy dark band */
  /* Do NOT set this to the legacy #5386a4 (that is brand-500). brand-800 is a DARK
     band fill -- _Header's primary nav and _SpecialistCta are bg-brand-800 with white
     text, _Footer puts brand-100 on it -- and ZCM's own views use it as body/heading
     text on white and brand-50. At #5386a4 all four pairs drop to 3.1-4.0:1, an AA
     failure on every page; ZcmTokenSheetTests fails three ways. */
  --color-brand-800: #204560;
  --color-brand-900: #132a45; /* heading navy -- NOT the legacy #003471, see PALETTE above */

  /* THE BAND COLOUR, and the ONE custom property here that is not a Tailwind token. It is not a
     shade of the scale (see THE BAND below for why the scale cannot supply it) and no utility
     reads it, so it re-themes nothing -- which is the only reason the "--color-brand-* and
     nothing else" shape rule admits it (ZcmTokenSheetTests allows this name explicitly).
     IT EXISTS SO THE NAV AND THE FOOTER CANNOT DRIFT APART (owner, 2026-09-15: "use the same
     colour in the footer as in the header navigation bar"). Both bands read this one
     declaration; a second literal would make that request true only until someone retuned one
     of them. Every ratio in the header comment's `band` row is measured against this value. */
  --zcm-band: #48758f;
}

/*
 * PER-SITE COMPONENT OVERRIDES -- the two BANDS, the SALES-CODE POPUP and the ANNOUNCEMENT BAR's
 * HEIGHT, and nothing else: the tier-3 primary nav (four rules since 2026-09-22 -- fill, row
 * gap + the padding under the links, current-item underline, and the link height that holds the
 * band at MM's 48px); since 2026-09-15, the footer's dark band (three rules -- fill,
 * text, dividers), which takes the SAME `--zcm-band` fill by the owner's decision; since
 * 2026-09-17 the sales-code popup (three rules -- the positioned wrapper, the panel, its open
 * state), which is a ZCM-only control to begin with; and since 2026-09-21 the tier-1
 * announcement bar's padding (one rule, inside the sheet's ONLY @media block -- the first
 * override here that was geometry rather than colour or a ZCM-only control; the nav band's
 * height is the second).
 *
 * WHY IT IS HERE AND NOT IN MARKUP: Views/Shared/_Header.cshtml and _Footer.cshtml are shared, and
 * marketmaps.com must stay byte-identical through the multi-site track (gate:
 * tools/SiteSnapshot vs baseline-z2). A site-conditional class on that <nav> changes MM's
 * rendered HTML; a rule in a sheet MM never links does not. This file is UNLAYERED, so
 * these rules beat the `bg-brand-800` / `gap-x-6 xl:gap-x-10` / `border-accent-600` /
 * `bg-brand-900` / `text-brand-100` / `border-brand-700` utilities in @layer utilities without
 * !important and without touching a token -- the same mechanism the :root block above relies on.
 *
 * KEEP THIS SECTION TINY. A rule here is invisible to every server-side assertion in the
 * suite (they can only read markup), which is why ZcmTokenSheetTests pins the selector set
 * and re-measures every pair. Every colour rule here arrived the same way -- measured first --
 * and so did both geometry rules; a THIRTEENTH needs that same treatment.
 */

/* THE BAND (owner, 2026-09-04): zipcodemaps.com's legacy header blue #5386a4, darkened 13%
   (each channel x0.87) to clear AA.
   #5386a4 ITSELF CANNOT CARRY THIS BAND. Its labels are 14px BOLD white uppercase
   (_PrimaryNavLinks.cshtml) -- normal text, so the floor is 4.5:1, not the 3:1 large-text
   one -- and white on #5386a4 is 3.95. No foreground rescues it either: brand-900 3.07,
   brand-800 2.55, ink 2.25. #48758f is the same hue (~203deg) at 4.98:1 with white; the
   minimal darkening that clears the floor (#4d7c98, 4.51) was rejected for sitting on the
   line, as brand-500 was for the newsletter input's boundary (FooterNewsletterTests).
   brand-500 stays the legacy #5386a4 -- it is still the anchor, for non-text accents.
   THE LITERAL MOVED TO --zcm-band 2026-09-15 so the footer's band can read the same declaration;
   the value is unchanged and every ratio above still applies. */
.site-nav {
  background-color: var(--zcm-band);
}

/* THE ROW'S GAP IS 20px, NOT _Header's `gap-x-6 xl:gap-x-10` (24/40px) -- owner's label changes,
   2026-09-08. ZCM's five product items read "State ZIP Code Maps" … "Metro Area ZIP Code Maps"
   and "Custom ZIP Code Maps" (SiteCopy.NavFamilyLabelFormat): 1063px of uppercase 14px/700
   Segoe UI against MM's 700px. Measured in headless Edge, per label:
     163 State · 181 County · 153 City · 216 Metro Area · 182 Custom · 75 About Us · 93 Contact Us
   The container is 1216px (max-w-7xl minus px-8) at the design width, so the six gaps are the
   only lever:  40px -> 1303 WRAPS  ·  24px -> 1207 fits by 9px  ·  20px -> 1183 fits by 33px.
   THE FIRST VERSION OF THIS RULE WAS 24px and shipped before "Custom Maps" was renamed too;
   9px of slack is not shippable -- a visitor without Segoe UI renders the whole row in a
   different stack. 20px is one row from 1247px up, verified in the browser at 1280.
   BETWEEN lg (1024, where the band appears) AND ~1246 IT WRAPS TO TWO CENTERED ROWS,
   deliberately: no gap fits 1063px of labels into a 960px container, and killing the 0.05em
   tracking or dropping to 13px buys ~80px, nowhere near enough. That is what the <ul>'s
   flex-wrap is for, and two centered rows degrade far better than a horizontal overflow.
   RE-MEASURE IN A BROWSER IF THE LABELS CHANGE AGAIN -- no test in the suite can see this.
   The DRAWER is unaffected -- it is #mobile-nav, full-width block rows, not .site-nav. */
/* THE BAND IS MM's 48px AND THE CURRENT-ITEM UNDERLINE STILL SITS INSIDE IT (owner, 2026-09-22:
   "For ZCM make the blue nav bar the same height as MM"). Two declarations do it and they work
   only as a PAIR:
     .site-nav ul { padding-bottom: 4px }    4px of band beneath the marker
     .site-nav a  { min-height: 2.75rem }    44px links, over _PrimaryNavLinks' min-h-12 (48px)
   44 + 4 = 48 = MM's band (MM: 48 rows of #1c3b63 under an 80px tier 2, measured in headless
   Edge at 1440 on /state-maps/). ZCM measured 54 the same way before this, 48 after.

   ⚠ BOTH NUMBERS HAVE MOVED, so date any comment about this band's height. From 2026-09-15 this
   rule carried `padding-bottom: 6px` under 48px links -- a 54px band -- and that padding was the
   fix for the marker READING AS A BITE TAKEN OUT OF THE BAND: _PrimaryNavLinks gives each link
   `min-h-12` so its `border-b-[3px]` lands on the band's base, correct on MM where the border is
   accent-600 red over a white page, but on THIS band the border is white (rule below) and the
   page beneath is white too, so marker and page met with no boundary. Band colour under the
   marker makes the band itself the separator, and that premise is unchanged; only the split is.
   COLOUR ALONE CANNOT DO IT, measured across hues before geometry was chosen: the band is
   mid-luminance, so anything light enough to clear 1.4.11's 3:1 ON the band is within 1.6:1 of
   the white page, and anything dark enough to separate from the page fails on the band
   (underline vs band / vs page: white 4.98 / 1.00 · brand-100 3.91 / 1.27 · brand-200 3.05 /
   1.63 · brand-900 2.92 / 14.53 · brand-800 2.03 / 10.09 · gold #f0c674 3.09 / 1.61). brand-200
   is the only near-miss and sits ON the line, the objection that rejected #4d7c98 for the fill.

   WHY THE LINK SHRINKS RATHER THAN THE PADDING GOING. Dropping the padding alone reaches 48px
   and reopens the bite. Keeping 6px under 42px links keeps the look but takes the link under the
   44px target floor STYLE-GUIDE.md sets for coarse pointers, and this band IS on an iPad in
   landscape (it appears at lg = 1024). 44 + 4 is the one split of 48 that keeps both: the marker
   has 4px of band beneath it, more than its own 3px, and the link stays on the floor. Labels are
   centred in the 44px link, i.e. 2px above the band's optical centre -- closer than the 3px the
   54px band accepted. Two-row wrap zone (lg to ~1246, gap rule above): 88 + 4 = 92px; MM never
   wraps, so there is nothing to match there.

   ⚠ 2.75rem IS TAILWIND'S OWN min-h-11, the floor the rest of the site spells that way; it beats
   the `min-h-12` utility on the <a> by the unlayered mechanism every rule here uses. `.site-nav a`
   reaches exactly the seven links -- the <nav> holds one <ul> of <li><a> and nothing else -- and
   NOT the drawer, which is #mobile-nav. ZcmTokenSheetTests pins BOTH declarations as one
   arithmetic (The_nav_band_is_MMs_48px_with_the_underline_still_inside_it), because either alone
   silently ships 44 or 52, and it names the retired 6px as the failure mode.
   WHY NOT A `::after` OR A TRANSPARENT BORDER: the same test reads `border-bottom-color` as a
   literal it re-measures against the band; either alternative breaks that read. */
.site-nav ul {
  column-gap: 1.25rem;
  padding-bottom: 4px;
}

.site-nav a {
  min-height: 2.75rem;
}

/* THE CURRENT ITEM'S UNDERLINE goes white on this band. accent-600 (#ed1c24) is 1.14:1 on
   #48758f -- the only visual marker of the current section, effectively erased. White is
   4.98:1. (The red is already just 2.30:1 on MM's darker brand-800, under WCAG 1.4.11's
   3:1 for a state indicator; that is Phase 8's audit to settle, not this change's to make
   worse.) Non-current items keep hover:border-white/60, which blends to ~2.6:1 against the
   band -- transient, and visibly dimmer than the solid current one. */
.site-nav [aria-current="page"] {
  border-bottom-color: #ffffff;
}

/* ---- THE FOOTER'S DARK BAND IS THE NAV BAND (owner, 2026-09-15) ----
   _Footer.cshtml's utility band is `on-dark bg-brand-900 text-brand-100` -- MM's near-black
   navy. On ZCM it takes the SAME steel blue as the tier-3 nav, so the page opens and closes on
   one colour. It reads --zcm-band rather than a second literal precisely because "the same
   colour as the header navigation bar" is the request: one declaration owns both, and retuning
   the nav moves the footer with it.

   THREE RULES, BECAUSE LIGHTENING THE BAND MOVES EVERY FOREGROUND ON IT. The fill goes from
   brand-900 (relative luminance 0.022) to #48758f (0.161) -- a ~7x jump -- so the two colours
   MM tuned against the navy have to be RE-MEASURED, not carried across:
                              on brand-900      on #48758f
     text   brand-100 #d8e6ee      11.40            3.91   <- AA FAIL (14px/12px, normal weight)
            white                  14.53            4.98   <- passes
     rule   brand-700 #30607e       2.14            1.36   <- effectively invisible
            brand-300 #90b4cb          -            2.25   <- reproduces MM's own 2.14
   So the copy goes WHITE (the four column headings and the phone link already are; what moves
   is the link/address text and the copyright row) and the column-heading underlines plus the
   copyright's top border go brand-300.
   THE DIVIDERS ARE DECORATIVE and are matched to MM's weight, not to a floor. WCAG 1.4.11's
   3:1 governs UI components and state indicators -- the nav's current-item underline is one,
   which is why THAT had to be white -- not a hairline under a column heading. Aiming 3:1 here
   would draw a rule far heavier than the footer mock's.

   WHY THREE SELECTORS AND NOT ONE. `text-brand-100` sits on TWO elements (the band itself and
   the copyright row) and `border-brand-700` on five (four headings + the copyright row); an
   unlayered `footer .on-dark` reaches only the band element, and colour does not inherit past a
   descendant that sets its own. So each utility is re-pointed INSIDE the band's scope instead.
   THE SCOPE IS EXACTLY THIS BAND: <footer> exists only in _Footer.cshtml (the admin layout has
   no footer element) and .on-dark appears once inside it. brand-900, brand-100 and brand-700
   keep their meaning everywhere else on the site -- the gallery pill, the toolbar's hover, the
   ZCM views' heading text -- and no token is re-themed.
   NOT TOUCHED, deliberately: the light "Stay Connected" band above it (surface-muted, with its
   own measured pairs and FooterNewsletterTests' input boundary), the payment chips (bg-white/90
   blends to #edf1f4 over this band, and brand-900 on that is 12.77), and .on-dark's white focus
   ring (4.98 here, as on the nav). */
footer .on-dark {
  background-color: var(--zcm-band);
  color: #ffffff;
}

footer .on-dark .text-brand-100 {
  color: #ffffff;
}

footer .on-dark .border-brand-700 {
  border-color: var(--color-brand-300);
}

/* ---- THE SALES-CODE POPUP OPENS OVER THE PAGE (owner, 2026-09-17) ----
   "When the user clicks the phone icon, the popup needs to slide up on top of the page like it
   does in the legacy site." This WITHDRAWS the 2026-09-17 morning deviation that shipped the
   panel as a disclosure in the footer's flow (docs/ZCM-URL-MODEL.md §6 item 14) -- in flow it
   pushed the payment chips and the copyright row down as it opened, which is not what the
   legacy control does and not what was asked for.

   LEGACY, for the record (javascript/sales-code.js): #SalesInformation is `position: absolute`
   in the BODY, and on every click the script measured the footer address's offset and set
   `top = offset.top - panel.height() - 28; left = offset.left - 100`, then jQuery `show("normal")`
   grew it into place. We reproduce the RESULT -- a panel that overlays the page just above the
   icon, with a short motion -- WITHOUT the measurement: `bottom: calc(100% + 0.5rem)` on a
   relatively positioned wrapper is the same geometry expressed once, and it cannot land
   off-screen on a phone or go stale when the footer reflows.

   ⚠ WHY THIS IS IN THIS SHEET AND NOT IN THE MARKUP -- the same reason as the two bands above,
   and it is the whole design constraint of this feature. Views/Shared/_Footer.cshtml is SHARED:
   Tailwind scans it whether or not the `@if (site.SalesCode.IsOffered)` block renders, so a
   single new utility class there (`absolute`, `bottom-full`, `w-60` -- all three verified ABSENT
   from the compiled sheet) adds rules to site.css, whose fingerprint rides on every one of
   marketmaps.com's ~95,600 pages. Every hook below is an attribute the markup already carries,
   so the markup is untouched and site.css does not move. The partial's own `mt-2`/`max-w-md`
   are overridden here rather than deleted for the same reason -- removing a utility can change
   the compiled sheet just as adding one can.

   THE MOTION IS A TWO-STATE TRANSITION, driven by site.js: the panel's resting state is the
   CLOSED one (transparent, 12px low) and `[data-open]` is the open one, which is the same shape
   as the mobile drawer's `.open` in Styles/tailwind.css. site.js unhides the panel and sets the
   attribute on the NEXT FRAME so the browser has a closed state to animate from; under
   prefers-reduced-motion it sets it in the same task instead, so no intermediate style is ever
   computed and there is no transition at all. That is why there is no @media block here -- the
   reduced-motion branch is the absence of a frame boundary, not a second rule.

   ⚠ `hidden` STILL DOES THE SHOWING AND HIDING. The UA's `[hidden] { display: none }` is what
   keeps the closed panel out of the accessibility tree and off the tab order; nothing below sets
   `display`, deliberately, so the attribute cannot be beaten by these rules. Opacity alone would
   leave a fully interactive invisible panel over the footer's links. */
[data-sales-code] {
  position: relative;
}

[data-sales-code-panel] {
  position: absolute;
  bottom: calc(100% + 0.5rem);
  left: 0;
  z-index: 30;
  width: 15rem;
  margin: 0;
  /* It floats over a mid-luminance band now, so it needs a reason to read as "above" the page.
     The border (border-brand-200) is the panel's own edge; this is depth, not contrast -- the
     white fill against #48758f is already 4.98:1 the other way round. */
  box-shadow: 0 10px 24px rgb(0 0 0 / 0.35);
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 180ms ease-out, transform 180ms ease-out;
}

[data-sales-code-panel][data-open] {
  opacity: 1;
  transform: translateY(0);
}

/* ---- THE ANNOUNCEMENT BAR IS 35px FROM sm (owner, 2026-09-21) ----
   "The height of the top bar with the gray background for ZCM should match the height of the
   light gray section in the TopBar.png image" -- the tier-1 strip carrying Free Shipping /
   Delivered as Fast as Same Day / Satisfaction Guaranteed. It was 40px: _PromoBar's inner div is
   `py-2 sm:py-2.5`, so 10px + 10px around a 20px line box.

   MEASURED OFF THE MOCK, AND THE SCALE IS THE WHOLE OF THE WORK -- the number is not readable
   off the file without it. TopBar.PNG is a 162x47 crop of the bar's left end (only "FREE
   SHIPPING *" is in frame), fill #dfe4ea, text #ea282c. In the file the band is 43.6px
   (it starts 3.25 rows down, where #444 blends 75% into the fill, and the crop's last row is
   87.5% fill, i.e. the image ends on the band's bottom edge) and the cap height of
   "FREE SHIPPING" is 12.5px (rows 19-30 solid, 3% of row 18, 49% of row 31).

   ⚠ THE CROP MATCHES NO SOURCE WE HAVE, so its scale had to be inferred and the two readings
   point OPPOSITE WAYS. It is not legacy zipcodemaps.com (that strip is .header-top2-wrap:
   white, blue Arial 18.67px, an explicit height: 40px), not ZipCodeMaps_OldRedesign's
   .top-header (#bdc1c8), and not live marketmaps.com (.fs-text is 10px #154d7c). At 1:1 the
   crop's type works out to ~17.5px and the band to 44px, i.e. this bar would GROW 4px; read as
   a 125% capture the type is exactly 14px -- the size this bar already sets -- and the band is
   43.6 / 1.25 = 34.9px, i.e. it SHRINKS. The owner chose the 125% reading (2026-09-21), which
   is also the self-consistent one: it is the only scale at which the mock's type lands on a
   value we already use.

   SO: 35px, as 7.5px + 7.5px around a 20px line box. The half-pixel is the arithmetic,
   not a fudge -- 35 is odd and the line box is even. It is expressed as PADDING rather than a
   height because this bar WRAPS: below sm its three items run to two and three lines, and a
   fixed height would clip them.

   ⚠ THIS RULE ALSO SETS THE TYPE, SINCE 2026-09-21 (evening), AND THAT IS WHAT KEEPS THE 35px
   TRUE. It originally set padding alone and took the 20px line box from the shared partial's
   `sm:text-sm`. Hours later MM's approved cart mock made that bar COMPACT -- `py-1.5 text-xs`
   at every width, ~28px, with the sm type and padding steps dropped -- which would have left
   ZCM at 7.5 + 16 + 7.5 = 31px and its type at 12px, silently undoing BOTH halves of the
   owner's TopBar.PNG reading on the same day it was taken.

   Restoring the premise here rather than compensating for its loss is deliberate: 14px is the
   size the 125% reading of the crop actually resolved to, so this rule now states it instead
   of inheriting it. Compensating with ~9.5px of padding would have landed the same 35px band
   around 12px type -- the right height around the wrong type, and nothing would have said so.

   The two sites' announcement bars are therefore independent now, which is the honest state:
   MM's is a 12px/28px strip from the cart mock, ZCM's a 14px/35px strip from TopBar.PNG.

   ⚠ sm AND UP ONLY, which is why this is the sheet's first @media block. The crop is a desktop
   one and 14px is the `sm:text-sm` regime; below sm the bar sets 12px/16px with `py-2` and was
   never in the brief, so it is left exactly as it is. The at-rule prelude is read as a selector
   by ZcmTokenSheetTests' closed set, which now names it.

   ⚠ THE HOOK IS `bg-brand-50`, A CLASS THE SHARED MARKUP ALREADY CARRIES -- the same constraint
   as every rule above: Views/Shared/_PromoBar.cshtml is shared with MM, Tailwind scans it either
   way, and a data attribute added for this would move site.css and therefore every
   marketmaps.com page's fingerprint. That class is the bar's own tint and appears nowhere else
   inside <header>, so the selector is unambiguous today -- and because a rename would silently
   kill this rule with no test able to see it, ZcmPromoBarTests asserts the class is still there
   from the markup side. */
@media (min-width: 40rem) {
  header > .bg-brand-50 > div {
    padding-top: 7.5px;
    padding-bottom: 7.5px;
    font-size: 0.875rem;
    line-height: 1.25rem;
  }
}
