/* ==========================================================================
   Dakota Ridge Complete Automotive — site.css
   Design system locked 2026-07-30 (client-supplied brand spec, verified
   against the live site with computed styles).
   Header + hero approved 2026-08-14. Footer approved 2026-08-14.

   Type: Oswald 700 (all headings) · Open Sans 400/600/700 (body)

   RULE: no hardcoded colour below :root. Every component reads a token.
   Two documented exceptions: plain #fff for text and rules sitting on dark
   bands, and rgba() literals that are alpha variants of --ink, --accent or
   white (CSS cannot derive an alpha from a hex custom property without
   color-mix, and color-mix is newer than the browsers some of these customers
   are running). Both are deliberate; everything else is a bug.

   Check after any token swap:
     grep -o 'var(--[a-z-]*' css/site.css | sort -u
   ========================================================================== */

@font-face { font-family: 'Oswald'; font-weight: 400; font-display: swap;
  src: url('../fonts/oswald-latin-400-normal.woff2') format('woff2'); }
@font-face { font-family: 'Oswald'; font-weight: 700; font-display: swap;
  src: url('../fonts/oswald-latin-700-normal.woff2') format('woff2'); }
@font-face { font-family: 'Open Sans'; font-weight: 400; font-display: swap;
  src: url('../fonts/open-sans-latin-400-normal.woff2') format('woff2'); }
@font-face { font-family: 'Open Sans'; font-weight: 600; font-display: swap;
  src: url('../fonts/open-sans-latin-600-normal.woff2') format('woff2'); }
@font-face { font-family: 'Open Sans'; font-weight: 700; font-display: swap;
  src: url('../fonts/open-sans-latin-700-normal.woff2') format('woff2'); }

:root {
  /* ---- Dakota Ridge brand palette (client spec) ---- */
  --dakota-red:         #B02633;
  --dakota-dark-blue:   #1F2E60;
  --dakota-light-blue:  #C9DAF5;
  --dakota-medium-blue: #558ADA;

  /* ---- Semantic roles ----
     Derived from the four brand colours above, so the palette has exactly one
     point of change. Components read these, never the --dakota-* names. */
  --ink:          var(--dakota-dark-blue);   /* headings, dark bands, primary text */
  --ink-deep:     #16224A;   /* legal bar, one step darker than --ink */
  --body-ink:     #000000;   /* long-form body copy. 21:1 on white */
  --accent:       var(--dakota-red);         /* CTAs, active states, rules */
  --accent-dark:  #8F1A25;   /* accent hover / secondary CTA */
  --link:         var(--dakota-dark-blue);
  --link-hover:   var(--dakota-red);
  --paper:        #ffffff;
  --panel:        var(--dakota-light-blue);   /* tinted chips and panels */
  --panel-soft:   #eef3fb;
  --rule:         #d6e0f0;
  /* Secondary text. Was #5a6470 at 6.0:1 — passed AA and no more, and it was
     the lowest-contrast text on the site by a wide margin. Now black; the
     hierarchy between primary and secondary copy is carried by size and
     weight rather than by fading the words out. 21:1 on white. */
  --soft:         #000000;   /* secondary text */
  --band-text:    #C9DAF5;   /* accent text on dark bands */
  --band-body:    #dbe6f7;   /* body copy on dark bands */
  --legal-text:   #a9bde0;   /* legal bar text */
  --err-bg:       #fdf2f2;   /* form error slot */
  /* Star gold sits outside the brand palette on purpose. Rating stars are a
     universal convention; painting them Dakota red would cost recognition for
     nothing. This is the one deliberate off-palette colour on the site. */
  --star:         #E8A317;

  /* ---- Type ---- */
  --display: 'Oswald', 'Arial Narrow', Impact, sans-serif;
  --body: 'Open Sans', system-ui, -apple-system, sans-serif;
  --body-size: 16px;
  --body-line-height: 28px;

  /* ---- Heading scale (client spec, locked) ---- */
  --h-weight: 700;
  --h1-size: 30px;
  --h2-size: 26px;
  --h3-size: 22px;
  --h4-size: 20px;
  --h5-size: 18px;
  --h6-size: 16px;
  --h1-letter-spacing: 0.03em;
  --h-letter-spacing: 0em;
  --h-margin-bottom: 1.5rem;
  --h-margin-top: 2.25rem;

  --wrap: 1120px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { font-family: var(--body); background: var(--paper); color: var(--body-ink);
  font-size: var(--body-size); line-height: var(--body-line-height);
  -webkit-font-smoothing: antialiased; }
img, svg { max-width: 100%; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 28px; }

/* ---------- Headings ----------
   Top margin as well as bottom. Bottom alone leaves every heading crowded
   against the paragraph above it, which reads as a bug on a real page. */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--display); font-weight: var(--h-weight); color: var(--ink);
  letter-spacing: var(--h-letter-spacing); line-height: 1.4;
  margin-bottom: var(--h-margin-bottom); margin-top: var(--h-margin-top);
}
h1 { font-size: var(--h1-size); text-transform: uppercase;
     letter-spacing: var(--h1-letter-spacing); margin-top: 0; }
h2 { font-size: var(--h2-size); }
h3 { font-size: var(--h3-size); }
h4 { font-size: var(--h4-size); }
h5 { font-size: var(--h5-size); }
h6 { font-size: var(--h6-size); }
main > section > .wrap > *:first-child { margin-top: 0; }

p { margin: 0 0 1.1rem; }
p.lede { font-size: 1.06rem; color: var(--soft); line-height: 1.7; }
a { color: var(--link); }
a:hover { color: var(--link-hover); }
ul, ol { margin: 0 0 1.1rem 1.2rem; }
li { margin-bottom: .45rem; }
strong { color: var(--ink); }

.skip { position: absolute; left: -9999px; top: 0; background: var(--accent); color: #fff;
  padding: 10px 18px; z-index: 200; font-weight: 700; }
.skip:focus { left: 0; }

/* ==========================================================================
   HEADER — three rows, mirrors the structure of the current site
   ========================================================================== */

/* ==========================================================================
   Masthead — sticks and compresses
   ==========================================================================
   All three header rows stick together and shrink once the page scrolls, so
   the logo, the phone number and the nav are all still reachable after the
   reader has moved down the page. That is the whole point: nobody looks for
   the phone number before they have read anything.

   `overflow-anchor: none` on <html> is MANDATORY and is not optional styling.
   Chrome's scroll anchoring tries to hold visible content still when something
   above it changes size. A masthead that shrinks by ~200px makes Chrome scroll
   the page to compensate, which moves the scroll position back across the
   trigger, which restores the header, which moves it again. The symptom is a
   hyperfast flicker in a narrow scroll band and it reads exactly like a
   JavaScript bug. It is not one. */
html { overflow-anchor: none; }

.masthead { position: sticky; top: 0; z-index: 60; }
.masthead .util,
.masthead .idband .wrap,
.masthead .idband .brand img,
.masthead .idband .tel { transition: all .18s ease; }

/* The compact state. Everything load-bearing survives it: logo, phone, nav. */
.masthead.compact .util { display: none; }
.masthead.compact .idband .wrap { padding-top: 8px; padding-bottom: 8px; }
/* Compact logo is HALF the at-rest height at every breakpoint. The at-rest
   size differs per breakpoint (196 / 150 / 72), so the compact value is set
   alongside each one rather than derived — CSS cannot halve a value another
   rule set, and a single number here would be half of one breakpoint and a
   random fraction of the other two. */
.masthead.compact .idband .brand img { height: 98px; }   /* 50% of 196 */
.masthead.compact .idband .brand .tag { display: none; }
.masthead.compact .idband .warr { display: none; }
.masthead.compact .idband .meta { display: none; }
.masthead.compact .idband .tel { font-size: 1.6rem; margin-bottom: 0; }
.masthead.compact .mainnav .wrap { padding-top: 7px; padding-bottom: 7px; }
.masthead.compact { box-shadow: 0 4px 18px rgba(31, 46, 96, .35); }

/* The class still toggles under reduced motion — the size change still
   happens, it just does not animate. Removing the behaviour entirely would
   take the phone number away from exactly the people most likely to want it. */
@media (prefers-reduced-motion: reduce) {
  .masthead .util,
  .masthead .idband .wrap,
  .masthead .idband .brand img,
  .masthead .idband .tel { transition: none; }
}

/* Row 1 — white utility strip */
.util { background: var(--paper); border-bottom: 1px solid var(--rule); }
.util .wrap { display: flex; align-items: center; justify-content: space-between;
  gap: 18px; padding-top: 12px; padding-bottom: 12px; flex-wrap: wrap; }
.util .claim { font-family: var(--display); font-weight: 700; font-size: 1.18rem;
  color: var(--ink); letter-spacing: .01em; }
.util .acts { display: flex; gap: 12px; flex-wrap: wrap; }
.util .acts a { background: var(--accent); color: #fff; text-decoration: none;
  font-weight: 700; font-size: .88rem; padding: 12px 22px; border-radius: 3px;
  white-space: nowrap; transition: background .15s; }
.util .acts a:hover { background: var(--ink); color: #fff; }
/* Both utility CTAs sit at --accent. The second one used to be --accent-dark,
   which read as a disabled or secondary state rather than a deliberate
   hierarchy — two reds a shade apart look like a mistake, not a choice. The
   .alt class stays on the markup so the pair can be differentiated later if
   there is ever a real reason to rank them. */
.util .acts a.alt { background: var(--accent); }
.util .acts a.alt:hover { background: var(--ink); }
.mbr { display: none; }

/* Row 2 — light-blue identity band */
.idband { background: var(--dakota-light-blue); }
.idband .wrap { display: grid; grid-template-columns: 1fr 1fr; gap: 30px;
  align-items: center; padding-top: 26px; padding-bottom: 26px; }
/* Left-aligned, not centred. Centring inside a 1fr column parks the logo in
   the middle of the left half with white space either side, and it reads as
   floating rather than as the anchor of the masthead. It stays centred below
   860px, where the two columns stack and centred is correct. */
.idband .brand { text-align: left; }
.idband .brand img { height: 196px; width: auto; display: inline-block; }
.idband .brand .tag { font-family: var(--display); font-weight: 700; color: var(--ink);
  font-size: 1.18rem; line-height: 1.35; margin-top: 14px; }
.idband .info { text-align: right; color: var(--ink); font-weight: 600; line-height: 1.6; }
.idband .warr { font-family: var(--display); font-weight: 700; font-size: 1.3rem; margin-bottom: 9px; }
.idband .tel { font-family: var(--display); font-weight: 700; font-size: 2.5rem; color: var(--ink);
  text-decoration: none; display: inline-block; margin-bottom: 11px; letter-spacing: .01em;
  line-height: 1.05; }
.idband .tel:hover { color: var(--accent); }
.idband .meta { font-size: 1.08rem; margin-bottom: 5px; }
.idband .meta svg { width: 16px; height: 16px; vertical-align: -2px; margin-right: 5px; fill: var(--ink); }

/* Row 3 — navy nav with pill buttons */
/* Not sticky on its own any more — .masthead above sticks for all three rows.
   Two sticky ancestors fight over the same top:0 and the inner one wins,
   which is what used to leave the logo and phone number behind. */
.mainnav { background: var(--ink); z-index: 60; }
.mainnav .wrap { padding-top: 11px; padding-bottom: 11px; }
.mainnav nav { display: flex; gap: 22px; flex-wrap: wrap; justify-content: center; }
.mainnav a { background: var(--dakota-medium-blue); color: #fff; text-decoration: none;
  font-family: var(--body); font-weight: 700; font-size: .94rem;
  padding: 9px 20px; border-radius: 5px; transition: background .15s; }
.mainnav a:hover, .mainnav a[aria-current="page"] { background: var(--accent); color: #fff; }
.mainnav a.exp { background: var(--accent); }
.mainnav a.exp:hover { background: var(--accent-dark); }

/* ---------- Nav dropdowns ----------
   The panel hangs off the pill rather than floating above the bar as a
   separate piece of UI. Depth comes from a darker shade of the bar's own
   colour plus a deep shadow, never a light border.

   --ink-deep is one step darker than --ink, which is the bar. Using a
   different colour, or white, would read as a second component landing on top
   of the nav instead of the nav extending downward.

   The parent pill keeps its hover state while the panel is open, so the two
   read as one object. There is deliberately NO border-top on the panel: the
   pill already provides the edge, and stacking one under the other is most of
   why a dropdown feels heavy. */
.mainnav .navitem { position: relative; }
.mainnav .navitem > a { display: inline-flex; align-items: center; gap: 7px; }
.mainnav .caret { width: 9px; height: 6px; fill: currentColor; opacity: .85;
  transition: transform .15s; }
.mainnav .navitem:hover > a,
.mainnav .navitem:focus-within > a,
.mainnav a.here { background: var(--accent); color: #fff; }
.mainnav .navitem:hover .caret,
.mainnav .navitem:focus-within .caret { transform: rotate(180deg); }

.mainnav .subnav {
  display: none; position: absolute; top: 100%; left: 0; z-index: 70;
  min-width: 268px; padding: 7px 0; margin-top: 6px;
  background: var(--ink-deep);
  box-shadow: 0 18px 42px rgba(0, 0, 0, .5);
  border-radius: 5px;
}
.mainnav .navitem:hover .subnav,
.mainnav .navitem:focus-within .subnav { display: block; }

/* A row is something to scan, not a stack of buttons — so no pill background,
   no radius, and a body-font weight. ~39px tall. */
.mainnav .subnav a {
  display: block; background: none; border-radius: 0;
  font-family: var(--body); font-weight: 500; font-size: .9rem;
  padding: 9px 22px; white-space: nowrap; color: #fff;
  /* The body line-height of 28px made these 46px rows — ten of them is a
     474px panel, which reads as a page rather than a menu. 1.35 brings a row
     to ~39px, which is the height you can scan down quickly. */
  line-height: 1.35;
}
.mainnav .subnav a:hover,
.mainnav .subnav a[aria-current="page"] {
  background: var(--accent); color: #fff;
}

/* The gap between pill and panel would close the menu on the way down, because
   the pointer leaves both elements. This bridges it without a visible change. */
.mainnav .navitem::after {
  content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 8px;
}

/* Hamburger — never shown above 860px. The button itself lives in every page
   so screen readers and the DOM stay identical; only the breakpoint reveals it. */
.navtoggle { display: none; }
.navtoggle .hb { position: relative; display: inline-block; width: 20px; height: 14px; }
.navtoggle .hb span { position: absolute; left: 0; width: 100%; height: 2px;
  background: currentColor; border-radius: 2px; }
.navtoggle .hb span:nth-child(1) { top: 0; }
.navtoggle .hb span:nth-child(2) { top: 6px; }
.navtoggle .hb span:nth-child(3) { top: 12px; }
.navtoggle[aria-expanded="true"] .hb span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navtoggle[aria-expanded="true"] .hb span:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] .hb span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ==========================================================================
   HERO — Dakota Ridge hogback (home page)
   ========================================================================== */
.rhero { position: relative; overflow: hidden; background: var(--ink); }
.rhero picture, .rhero img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 42%; }
.rhero .scrim { position: absolute; inset: 0; background: linear-gradient(100deg,
  rgba(31, 46, 96, .95) 0%, rgba(31, 46, 96, .88) 34%,
  rgba(31, 46, 96, .55) 60%, rgba(31, 46, 96, .18) 100%); }
.rhero .wrap { position: relative; z-index: 2; padding-top: 44px; padding-bottom: 40px; }
.rhero h1 { color: #fff; margin-bottom: .7rem; max-width: 19ch; text-shadow: 0 2px 14px rgba(0, 0, 0, .35); }
.rhero .lede { color: #fff; max-width: 46ch; margin-bottom: 1.3rem; font-size: 1.02rem; opacity: .96; }
.rhero .btn-ghost { color: #fff; box-shadow: inset 0 0 0 2px #fff; background: transparent; }
.rhero .btn-ghost:hover { background: #fff; color: var(--ink); }
.rhero .strip { display: flex; gap: 24px; flex-wrap: wrap; margin-top: 22px; padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, .28); font-family: var(--display); font-weight: 700;
  font-size: .85rem; letter-spacing: .06em; text-transform: uppercase; color: var(--dakota-light-blue); }

/* ---------- Interior page hero ---------- */
.page-hero { background: var(--ink); color: #fff; }
.page-hero .wrap { padding-top: 34px; padding-bottom: 34px; }
.page-hero h1 { color: #fff; margin-bottom: .6rem; max-width: 24ch; }
.page-hero .lede { color: var(--band-body); max-width: 62ch; margin-bottom: 0; }
.crumbs { font-size: .84rem; color: var(--band-text); margin-bottom: 14px; letter-spacing: .02em; }
.crumbs a { color: var(--band-text); text-decoration: none; }
.crumbs a:hover { color: #fff; text-decoration: underline; }
.crumbs .sep { opacity: .55; margin: 0 6px; }

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn { display: inline-block; background: var(--ink); color: #fff; padding: 16px 30px;
  text-decoration: none; font-family: var(--display); font-weight: 700; font-size: 1.35rem;
  text-transform: uppercase; letter-spacing: .04em; border: 0; cursor: pointer;
  transition: background .15s ease, transform .15s ease; }
.btn:hover { background: var(--accent); color: #fff; transform: translateY(-2px); }
.btn-appt { background: var(--accent); padding: 13px 22px; font-size: .95rem; white-space: nowrap; }
.btn-appt:hover { background: var(--ink); }
.btn-ghost { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 2px var(--ink); }
.btn-ghost:hover { background: var(--ink); color: #fff; }
.btn-sm { padding: 13px 24px; font-size: .95rem; }
.cta-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }

/* ==========================================================================
   Sections and shared blocks
   ========================================================================== */
section { padding: 48px 0; }
section.tint { background: var(--panel-soft); }
section.band { background: var(--ink); color: #fff; }
section.band h2, section.band h3 { color: #fff; }
section.band p { color: var(--band-body); }
section.band .lede { color: var(--band-text); }
section.final { background: var(--ink); color: #fff; }
section.final h2 { color: #fff; }
section.final .lede { color: var(--band-text); }
section.final .btn-ghost { color: #fff; box-shadow: inset 0 0 0 2px #fff; background: transparent; }
section.final .btn-ghost:hover { background: #fff; color: var(--ink); }
.aside-note { display: block; margin-top: 16px; color: var(--band-text); font-size: .92rem; line-height: 1.6; }

/* P6. Small print that still has to be read: consent notices, warranty
   conditions. Quieter than body copy but never small enough to be called
   inconspicuous — .88rem lands at about 14px against a 16px base, and a
   consent notice a court would call hidden is worse than no notice at all.
   Reads a token rather than hardcoding a colour, like everything below :root. */
.fineprint { margin-top: 14px; font-size: .88rem; line-height: 1.65; color: var(--soft); }
.fineprint a { color: var(--soft); text-decoration: underline; }
.fineprint a:hover { color: var(--accent); }

/* P7. Google attribution on the reviews block. The G sits on a white chip
   because Google's brand rules ask for white or black backgrounds and this
   block renders on --panel-soft. The chip keeps that true in any section
   colour. No padding on the img: the asset already carries its own clear
   space, which is Google's width-of-the-G requirement built into the file. */
.src-google { display: flex; align-items: center; gap: 14px; margin: -4px 0 24px;
  font-size: 1.06rem; font-weight: 700; color: var(--ink); }
/* The mark was 34px inside a 58px circle — the G was 59% of the chip and the
   white ring was doing most of the talking. Now 46 inside 56, so the ring is a
   5px surround rather than a badge in its own right and the G is what you see.
   The asset carries Google's width-of-the-G clear space inside the file, so no
   padding is added here and the image is never cropped. */
.g-chip { display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; background: #fff; border: 1px solid var(--rule);
  border-radius: 50%; flex: 0 0 56px; box-shadow: 0 1px 3px rgba(31,46,96,.08); }
.g-chip img { display: block; width: 46px; height: 46px; }

/* Proof strip */
.proof { display: flex; flex-wrap: wrap; gap: 10px 26px; padding: 18px 0;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; font-size: .92rem; color: var(--ink); }
.proof span::before { content: "\2022"; color: var(--accent); margin-right: 9px; }
.proof span:first-child::before { content: none; }

/* Two equal doors: repair and express */
.doors { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; margin: 34px 0; }
.door { border: 1px solid var(--rule); border-top: 5px solid var(--ink); border-radius: 4px;
  padding: 26px 28px; background: var(--paper);
  transition: transform .22s ease, box-shadow .22s ease, border-color .22s ease; }
.door.express { border-top-color: var(--accent); }
.door:hover { transform: translateY(-5px); box-shadow: 0 14px 30px rgba(31, 46, 96, .10); }
.door h2 { margin-top: 0; margin-bottom: .6rem; }
.door p { color: var(--soft); margin-bottom: 1.1rem; }

/* Cards */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 22px; margin: 28px 0; }
.card { border: 1px solid var(--rule); border-top: 4px solid var(--ink); border-radius: 4px;
  padding: 24px; background: var(--paper); }
.card h3 { margin-top: 0; }
.card p:last-child { margin-bottom: 0; }
.card .num { display: block; font-family: var(--display); font-weight: 700; font-size: 2.4rem;
  line-height: 1; color: var(--accent); margin-bottom: 8px; }

/* Panel / callout */
.panel { background: var(--panel-soft); border-left: 4px solid var(--accent);
  border-radius: 0 4px 4px 0; padding: 22px 26px; margin: 26px 0; }
.panel > :last-child { margin-bottom: 0; }
.panel h3 { margin-top: 0; }

/* Definition rows — what is covered and what is not */
.terms { list-style: none; margin: 22px 0; padding: 0; }
.terms li { display: flex; gap: 14px; align-items: flex-start; padding: 13px 0;
  border-bottom: 1px solid var(--rule); margin: 0; }
.terms li:last-child { border-bottom: none; }
.terms .yes, .terms .no { flex: 0 0 22px; font-family: var(--display); font-weight: 700;
  font-size: 1.15rem; line-height: 1.5; }
.terms .yes { color: var(--accent); }
.terms .no { color: var(--soft); }
.terms b { display: block; font-family: var(--display); font-weight: 700;
  font-size: 1.05rem; color: var(--ink); }
.terms span.d { display: block; color: var(--soft); font-size: .96rem; line-height: 1.6; }

/* Numbered steps */
.steps { list-style: none; counter-reset: s; margin: 24px 0; padding: 0; }
.steps li { counter-increment: s; position: relative; padding: 0 0 22px 52px; margin: 0 0 0 15px;
  border-left: 2px solid var(--rule); }
.steps li:last-child { border-left-color: transparent; padding-bottom: 0; }
.steps li::before { content: counter(s); position: absolute; left: -17px; top: -4px;
  width: 32px; height: 32px; border-radius: 50%; background: var(--ink); color: #fff;
  font-family: var(--display); font-weight: 700; font-size: 1rem;
  display: flex; align-items: center; justify-content: center; }
.steps b { display: block; font-family: var(--display); font-weight: 700;
  font-size: 1.1rem; color: var(--ink); margin-bottom: 4px; }
.steps p { color: var(--soft); margin-bottom: 0; }

/* ---------- Coverage bars ----------
   A picture made of real text. Search engines and AI assistants read every
   word of this, it weighs nothing, it stays sharp on any screen, and when the
   terms change it changes in one place. A JPEG of the same idea does none of
   those things. Widths are inline styles because they encode the DATA, not
   the design — 48 months is twice the bar of 24 months, and that proportion
   is the whole argument. */
.bars { margin: 28px 0; }
.bars .row { margin-bottom: 18px; }
.bars .row:last-child { margin-bottom: 0; }
.bars .lbl { display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
  flex-wrap: wrap; margin-bottom: 6px; }
.bars .who { font-family: var(--display); font-weight: 700; font-size: 1.02rem; color: var(--ink); }
.bars .term { font-size: .92rem; color: var(--soft); font-weight: 600; }
.bars .track { background: var(--rule); border-radius: 3px; height: 26px; overflow: hidden; }
.bars .fill { height: 100%; background: var(--dakota-medium-blue); border-radius: 3px; }
.bars .row.us .who { font-size: 1.18rem; }
.bars .row.us .term { color: var(--accent); font-weight: 700; }
.bars .row.us .fill { background: var(--accent); }
.bars .scale { display: flex; justify-content: space-between; font-size: .78rem; color: var(--soft);
  border-top: 1px solid var(--rule); padding-top: 6px; margin-top: 16px; letter-spacing: .03em; }

/* Photo with a caption that does work. A caption is the cheapest place on a
   page to put a fact, and it is read far more often than body copy. */
figure.shot { margin: 28px 0; }
/* The native-size cap is an inline max-width on the FIGURE, emitted by
   buildpages.figure() from the file's real dimensions. It is not done here
   with attr(), which is CSS Values 5 and only lands in recent Chrome. */
figure.shot img { display: block; width: 100%; height: auto; border-radius: 4px; }
figure.shot figcaption { font-size: .9rem; color: var(--soft); line-height: 1.6; margin-top: 10px;
  border-left: 3px solid var(--accent); padding-left: 12px; }
figure.shot.right { float: right; width: 42%; margin: 6px 0 20px 28px; }
@media (max-width: 760px) { figure.shot.right { float: none; width: 100%; margin: 28px 0; } }

/* ---------- Star ratings ----------
   Two stacked rows of five stars; the gold row is clipped by percentage, so
   whole numbers and fractions use one code path. The stars are decorative and
   aria-hidden — the visible "4.6 out of 5" beside them carries the meaning for
   screen readers, crawlers and AI assistants alike. */
.rate { display: inline-flex; align-items: center; gap: 8px; }
.stars { position: relative; display: inline-block; line-height: 0; white-space: nowrap; }
.stars .s-bg, .stars .s-fg { display: block; white-space: nowrap; }
.stars .s-fg { position: absolute; inset: 0 auto 0 0; overflow: hidden; }
.stars svg { width: 17px; height: 17px; display: inline-block; }
.stars .s-bg svg { fill: var(--rule); }
.stars .s-fg svg { fill: var(--star); }
.rate-text { font-size: .84rem; font-weight: 700; color: var(--soft); white-space: nowrap; }

/* ---------- Review cards ---------- */
.revs { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px; margin-top: 26px; }
.rev { margin: 0; background: var(--paper); border: 1px solid var(--rule);
  border-top: 4px solid var(--star); border-radius: 4px; padding: 22px 24px;
  display: flex; flex-direction: column; }
.rev blockquote { margin: 14px 0 16px; }
.rev blockquote p { margin: 0; color: var(--body-ink); font-size: .97rem; line-height: 1.65; }
.rev blockquote p::before { content: "\201C"; }
.rev blockquote p::after { content: "\201D"; }
.rev figcaption { margin-top: auto; border-top: 1px solid var(--rule); padding-top: 12px; }
.rev figcaption b { display: block; font-family: var(--display); font-weight: 700;
  font-size: 1rem; color: var(--ink); }
.rev figcaption span { font-size: .82rem; color: var(--soft); }
.rev figcaption a, .rev blockquote a { color: var(--accent); font-weight: 600; }
.rev-all { margin: 22px 0 0; font-weight: 600; }

/* Placeholder standing in for artwork that has not arrived. Deliberately
   unmissable — nothing here should ever survive to launch by accident. */
.ph { display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px; text-align: center; padding: 18px; border: 2px dashed var(--accent);
  border-radius: 4px; background: repeating-linear-gradient(45deg,
    var(--panel-soft), var(--panel-soft) 12px, var(--paper) 12px, var(--paper) 24px); }
.ph b { font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--accent); font-size: 1rem; }
.ph span { font-size: .86rem; color: var(--soft); line-height: 1.4; max-width: 34ch; }
.ph .dim { font-weight: 700; letter-spacing: .06em; }

/* ---------- Coupons ----------
   Text, not a JPEG. The offer, the terms and the expiry are all real words a
   search engine and an AI assistant can read, and the code is something a
   customer says out loud to a service advisor instead of printing. */
.coupons { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 22px; margin-top: 28px; }
.coupon { background: var(--paper); border: 1px solid var(--rule);
  border-radius: 4px; overflow: hidden; display: flex; flex-direction: column; }
/* The red shout, at H1 size. This is the badge off the old print artwork,
   rebuilt as live text — same job, but readable by a search engine. */
.coupon .shout { background: var(--accent); color: #fff; padding: 16px 22px;
  font-family: var(--display); font-weight: var(--h-weight);
  font-size: var(--h1-size); line-height: 1.08; text-transform: uppercase;
  letter-spacing: var(--h1-letter-spacing); }
.coupon .cbody { padding: 22px 24px 24px; display: flex; flex-direction: column; flex: 1; }
.coupon h3 { margin: 0 0 .4rem; font-size: 1.15rem; }
.coupon .offer { font-family: var(--display); font-weight: 700; font-size: 1.6rem;
  line-height: 1.2; color: var(--accent); margin: 0 0 .9rem; }
.coupon .code { margin: 0 0 .9rem; font-size: .9rem; color: var(--soft); }
.coupon .code b { display: inline-block; font-family: var(--display); font-size: 1.15rem;
  letter-spacing: .12em; color: var(--ink); background: var(--panel);
  padding: 3px 12px; border-radius: 3px; margin-left: 6px; }
.coupon .code .ref { display: block; font-size: .72rem; color: var(--soft);
  letter-spacing: .04em; margin-top: 5px; font-weight: 600; }
.coupon .incl { list-style: none; margin: 0 0 .9rem; padding: 0; }
.coupon .incl li { font-size: .9rem; color: var(--body-ink); line-height: 1.5;
  padding-left: 16px; position: relative; margin-bottom: .28rem; }
.coupon .incl li::before { content: "\2713"; position: absolute; left: 0;
  color: var(--accent); font-weight: 700; }
.coupon .fine { font-size: .78rem; color: var(--soft); line-height: 1.5; margin: 0 0 .8rem; }
.coupon .exp { font-size: .82rem; color: var(--soft); margin: 0 0 1.1rem; font-weight: 600; }
.coupon .btn { margin-top: auto; align-self: flex-start; }
.coupon .copied { display: block; margin-top: 10px; font-size: .82rem; font-weight: 700;
  color: var(--accent); }
.coupon .copied[hidden] { display: none; }

/* ---------- Price tiers ---------- */
.tiers { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 22px; margin: 28px 0; align-items: start; }
.tier { border: 1px solid var(--rule); border-top: 5px solid var(--ink);
  border-radius: 4px; background: var(--paper); padding: 26px 24px; position: relative; }
.tier.flag { border-top-color: var(--accent); background: var(--panel-soft); }
.tier .tag { position: absolute; top: -13px; left: 22px; background: var(--accent); color: #fff;
  font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; font-size: .78rem; padding: 3px 11px; border-radius: 3px; }
.tier h3 { margin: 0 0 .2rem; font-size: 1.25rem; }
.tier .price { font-family: var(--display); font-weight: 700; font-size: 2.5rem;
  color: var(--accent); line-height: 1.1; margin-bottom: .2rem; }
.tier .price small { font-size: .95rem; color: var(--soft); font-family: var(--body);
  font-weight: 600; display: block; margin-top: 2px; }
.tier .fit { color: var(--soft); font-size: .92rem; font-style: italic;
  line-height: 1.5; margin: 10px 0 0; }
.tier ul { list-style: none; margin: 14px 0 0; padding: 0; }
.tier li { padding: 8px 0 8px 18px; border-top: 1px solid var(--rule); color: var(--soft);
  font-size: .92rem; line-height: 1.45; position: relative; margin: 0; }
.tier li::before { content: "\2713"; position: absolute; left: 0; color: var(--accent); font-weight: 700; }

/* ---------- Callout band ---------- */
.pull { border-left: 5px solid var(--accent); padding: 4px 0 4px 22px; margin: 26px 0;
  font-family: var(--display); font-weight: 700; font-size: 1.35rem; line-height: 1.35;
  color: var(--ink); }

/* Comparison table */
table.cmp { width: 100%; border-collapse: collapse; margin: 24px 0; font-size: .96rem; }
table.cmp caption { caption-side: bottom; text-align: left; color: var(--soft);
  font-size: .86rem; padding-top: 10px; line-height: 1.6; }
table.cmp th, table.cmp td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--rule); }
table.cmp thead th { background: var(--ink); color: #fff; font-family: var(--display);
  font-weight: 700; text-transform: uppercase; letter-spacing: .04em; font-size: .88rem; }
table.cmp tbody th { font-family: var(--body); font-weight: 600; color: var(--ink); }
table.cmp tr.us td, table.cmp tr.us th { background: var(--panel-soft); font-weight: 700; color: var(--ink); }
table.cmp tr.us th { box-shadow: inset 4px 0 0 var(--accent); }

/* FAQ */
.faq { border-top: 1px solid var(--rule); padding: 0; }
.faq:first-of-type { border-top: none; }
.faq:last-of-type { border-bottom: 1px solid var(--rule); }

/* <details>/<summary> accordion, 1 Sep 2026. No JavaScript: the browser
   already gives us the toggle, the keyboard behaviour and the screen reader
   announcement, and the answers stay in the DOM either way so schema and
   crawlers see what a reader sees.

   list-style on the summary is reset in two ways because Safari still uses the
   non-standard ::-webkit-details-marker rather than list-style. Missing one
   leaves a stray triangle next to our own chevron. */
.faq summary { display: flex; align-items: flex-start; gap: 14px;
  cursor: pointer; padding: 20px 0; list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary h3 { margin: 0; flex: 1; font-size: 1.06rem; line-height: 1.45; }
.faq summary:hover h3 { color: var(--accent); }
.faq summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Chevron drawn in CSS rather than shipped as an asset. Rotates on open. */
.faq summary::after { content: ""; flex: none; width: 10px; height: 10px;
  margin-top: 6px; border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent); transform: rotate(45deg);
  transition: transform .18s ease; }
.faq[open] summary::after { transform: rotate(225deg); margin-top: 10px; }

.faq-a { padding: 0 0 20px; }
.faq p { color: var(--soft); margin: 0 0 .8rem; }
.faq p:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .faq summary::after { transition: none; }
}

/* ==========================================================================
   FOOTER — trust bar, four columns, neighborhood row, legal bar
   ========================================================================== */
.trustbar { background: var(--panel-soft); border-top: 3px solid var(--accent);
  border-bottom: 1px solid var(--rule); }
.trustbar .wrap { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 18px;
  padding-top: 22px; padding-bottom: 22px; }
.tb { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 150px; }
.tb .mark { width: 42px; height: 42px; flex: 0 0 42px; border-radius: 50%;
  background: var(--ink); color: #fff; display: flex; align-items: center; justify-content: center;
  font-family: var(--display); font-weight: 700; font-size: .72rem; letter-spacing: .02em; }
.tb .mark.red { background: var(--accent); }
.tb b { display: block; font-family: var(--display); font-weight: 700; font-size: .95rem;
  color: var(--ink); line-height: 1.2; }
.tb span { display: block; font-size: .78rem; color: var(--soft); line-height: 1.3; margin-top: 2px; }
/* A linked trust-bar item (AAA, 2026-09-12) reads exactly like the others
   until hovered, so the row stays one row and not four labels and a link. */
a.tb { text-decoration: none; }
a.tb:hover b { color: var(--accent); }

.sitefoot { background: var(--ink); color: #fff; }
.sitefoot .wrap { padding-top: 40px; padding-bottom: 30px; }
/* Two children now, not four: the brand block and one capped link list.
   The list flows into two sub-columns so seven links read as a block rather
   than a thin ribbon down one side of a wide footer. */
.fgrid { display: grid; grid-template-columns: 1.35fr 2fr; gap: 34px; }
.fnav ul { columns: 2; column-gap: 34px; }
.fnav li { break-inside: avoid; }
.sitefoot h3 { color: #fff; font-size: 1rem; margin: 0 0 14px; letter-spacing: .05em;
  padding-bottom: 9px; border-bottom: 1px solid rgba(255, 255, 255, .2); }
.sitefoot ul { list-style: none; margin: 0; padding: 0; }
.sitefoot li { margin-bottom: 8px; line-height: 1.35; }
.sitefoot a { color: var(--dakota-light-blue); text-decoration: none; font-size: .9rem; }
.sitefoot a:hover { color: #fff; text-decoration: underline; }
.fbrand img { height: 96px; width: auto; display: block; margin-bottom: 14px; }
.fbrand .addr { font-size: .92rem; line-height: 1.65; color: var(--band-body); }
.fbrand .ftel { font-family: var(--display); font-weight: 700; font-size: 1.72rem; color: #fff;
  text-decoration: none; display: inline-block; margin: 10px 0 4px; }
.fbrand .ftel:hover { color: var(--dakota-light-blue); }
.fbrand .hrs { font-size: .88rem; color: var(--dakota-light-blue); margin-top: 8px; line-height: 1.5; }
.social { display: flex; gap: 10px; margin-top: 16px; }
.social a { width: 36px; height: 36px; border-radius: 50%; background: rgba(255, 255, 255, .12);
  display: flex; align-items: center; justify-content: center; transition: background .15s; }
.social a:hover { background: var(--accent); }
.social svg { width: 17px; height: 17px; fill: #fff; }
.expblock { background: rgba(176, 38, 51, .18); border-left: 3px solid var(--accent);
  padding: 12px 14px; margin-bottom: 16px; border-radius: 0 4px 4px 0; }
.expblock b { display: block; font-family: var(--display); font-size: .98rem; color: #fff; margin-bottom: 3px; }
.expblock span { font-size: .82rem; color: var(--dakota-light-blue); line-height: 1.4; display: block; }
.hood { margin-top: 30px; padding-top: 20px; border-top: 1px solid rgba(255, 255, 255, .16); }
.hood h3 { border: 0; padding: 0; margin-bottom: 10px; }
.hood p { font-size: .9rem; line-height: 2; margin: 0; }

.legal { background: var(--ink-deep); color: var(--legal-text); font-size: .82rem; }
.legal .wrap { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px;
  padding-top: 16px; padding-bottom: 16px; }
.legal a { color: var(--legal-text); text-decoration: none; }
.legal a:hover { color: #fff; text-decoration: underline; }
.legal .links a { margin-left: 16px; }

/* ==========================================================================
   Contact form
   ========================================================================== */
/* ---------- Contact form ----------
   Structure measured off the Frontier quote form (cistemp3) so the two sites
   share a pattern: a bordered card, labels above fields, short fields paired
   on one row, and a button sized to its text rather than the full width.
   Palette is Dakota's, not Frontier's — same skeleton, different clothes.

   The red top rule is kept from the old card. It is the one thing that says
   "this is the Dakota Ridge form" rather than a generic one. */
.formcard { border: 1px solid var(--rule); border-top: 4px solid var(--accent);
  padding: 26px 26px 28px; background: var(--panel-soft); border-radius: 4px; }
.formcard h3 { margin: 0 0 18px; font-size: 1.5rem; }

.formcard label { display: block; margin-top: 15px; margin-bottom: 6px;
  font-weight: 600; font-size: .92rem; color: var(--ink); }
.formcard .req { color: var(--accent); font-weight: 700; }

.formcard input, .formcard select, .formcard textarea {
  width: 100%; padding: 12px 13px; border: 1px solid var(--rule);
  border-radius: 3px; font-family: var(--body); font-size: .97rem;
  background: var(--paper); color: var(--body-ink); }
.formcard textarea { min-height: 132px; resize: vertical; line-height: 1.55; }
.formcard input::placeholder, .formcard textarea::placeholder { color: #6b7280; }

/* Focus has to be VISIBLE. The default outline is removed by nothing here, but
   a 1px border change is not enough of a signal for anybody tabbing through. */
.formcard input:focus, .formcard select:focus, .formcard textarea:focus {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent); }

/* Two short fields per row. Collapses to one column below 560px, where side by
   side would leave both too narrow to type a phone number into comfortably. */
.formcard .frow { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
.formcard .frow label { margin-top: 15px; }

/* Sized to its text, like the Frontier button. A full-bleed submit on a card
   this narrow reads as a banner rather than a control. */
.formcard .btn { margin-top: 22px; width: auto; display: inline-block; }

.panel.easypay { overflow: hidden; }
/* Floated right so the copy wraps around it rather than being pushed down.
   Capped at its native 395px for the same reason as the warranty badge: a
   stretched card looks like a picture of a card rather than the card. */
.cardart { float: right; width: 220px; max-width: 40%; height: auto;
  margin: 2px 0 12px 22px; border-radius: 7px;
  box-shadow: 0 2px 10px rgba(31, 46, 96, .18); }
@media (max-width: 560px) {
  .cardart { float: none; display: block; width: 200px; max-width: 100%;
    margin: 0 0 16px; }
}

.formsplit { display: grid; grid-template-columns: 1fr 1.05fr; gap: 44px;
  align-items: start; }
.formaside h3 { margin-top: 0; font-size: 1.22rem; }
.formaside h3 + p { margin-bottom: 26px; }
.formaside h3 ~ h3 { margin-top: 0; }
.bigtel { font-family: var(--display); font-weight: 700; font-size: 1.9rem;
  color: var(--ink); text-decoration: none; line-height: 1.1;
  display: inline-block; margin-bottom: 4px; }
.bigtel:hover { color: var(--accent); }

.formnote { margin: 16px 0 0; font-size: .82rem; line-height: 1.6;
  color: var(--soft); }
.formnote a { color: var(--soft); text-decoration: underline; }

.hp { position: absolute; left: -9999px; }
.src-row { display: flex; align-items: flex-start; gap: 10px; padding: 7px 0; }
.src-row input[type="checkbox"] { width: auto; margin-top: 3px; accent-color: var(--accent); transform: scale(1.25); }
.src-row label { display: inline; margin: 0; font-weight: 500; font-size: .95rem; color: var(--ink); }
.src-row label small { color: var(--soft); }
/* Driven by the native `hidden` ATTRIBUTE, not a .show class.
   The old pair was `.followup { display:none }` plus `.followup.show`, which
   meant JS toggling `hidden` did nothing at all — an explicit display:none
   beats the attribute every time, and the field simply never appeared.
   Keying off [hidden] makes the attribute the single source of truth, and it
   fails safe: if the JS never runs, the field stays hidden rather than
   showing a question nobody was asked. */
.followup { display: block; margin: 4px 0 6px 0; }
.followup[hidden] { display: none; }
.followup label { font-weight: 500; font-size: .88rem; color: var(--soft); margin-top: 0; }
.form-err { margin: 14px 0 4px; padding: 12px 14px; background: var(--err-bg);
  border-left: 3px solid var(--accent); font-weight: 600; }

/* ==========================================================================
   Blog
   ========================================================================== */
.post-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 28px; }
.post-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.post-card { display: block; text-decoration: none; background: var(--paper);
  border: 1px solid var(--rule); border-top: 4px solid var(--ink); padding: 26px 26px 22px;
  border-radius: 4px; transition: transform .22s ease, box-shadow .22s ease; }
.post-card:hover { transform: translateY(-5px); box-shadow: 0 14px 30px rgba(31, 46, 96, .10); }
.post-card .post-date { font-family: var(--display); font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--accent); font-size: .9rem; }
.post-card h3 { margin-top: 8px; margin-bottom: 0; }
.post-card p { margin-top: 10px; color: var(--soft); font-size: .97rem; line-height: 1.6; }
.post-card .read { display: inline-block; margin-top: 6px; color: var(--accent); font-weight: 700; }
.earlier { list-style: none; margin: 20px 0 0; padding: 0; }
.earlier li { display: flex; justify-content: space-between; gap: 16px;
  border-bottom: 1px solid var(--rule); padding: 12px 0; margin: 0; }
.earlier a { color: var(--ink); font-weight: 600; text-decoration: none; }
.earlier a:hover { color: var(--accent); }
.earlier span { color: var(--soft); font-size: .9rem; white-space: nowrap; }
.post-meta { margin-top: 14px; color: var(--soft); font-weight: 600; }
.post-body p { color: var(--body-ink); line-height: 1.75; }
.post-cta { margin-top: 40px; display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }

/* ==========================================================================
   Motion — everything gated on prefers-reduced-motion
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .navtoggle .hb span { transition: transform .18s ease, opacity .18s ease; }
  .reveal { opacity: 0; transform: translateY(22px); transition: opacity .6s ease, transform .6s ease; }
  .reveal.in { opacity: 1; transform: none; }
  .reveal.d1 { transition-delay: .12s; }
  .reveal.d2 { transition-delay: .24s; }
  .reveal.d3 { transition-delay: .36s; }
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1 !important; transform: none !important; }
  .btn:hover, .door:hover, .post-card:hover { transform: none; }
  html { scroll-behavior: auto; }
}

/* ---------- Trust band: claims above, marks below, both centred ---------- */
/* Light blue, Mark 1 Sep 2026, full viewport width.

   The colour lives on section.sky rather than on .trustband, so the blue runs
   edge to edge while the content stays inside the normal wrap. Putting it on
   the inner div and stretching it with negative margins against 100vw is the
   other way to do this, and it is wrong: 100vw includes the scrollbar, so it
   produces a horizontal scroll on any platform that reserves gutter space.

   The border-top went with the fill. A section that changes colour already
   separates itself; keeping the rule as well puts a line on top of an edge. */
section.sky { background: var(--dakota-light-blue); }
.trustband { text-align: center; }

/* The neighbourhood line sits under the badge row and was butting straight
   into the labels - .trustsub carries margin:0 auto, which is right for the
   line above the badges and wrong for the one below them. Spacing the second
   one by position rather than adding a class keeps one rule for both. */
.badgerow + .trustsub { margin-top: 26px; }

.trustlede { margin: 0 0 8px; font-size: 1.45rem; }
.trustsub { color: var(--soft); margin: 0 auto; max-width: 46ch; font-size: .95rem; }

.badgerow { display: flex; flex-wrap: wrap; justify-content: center;
  align-items: flex-end; gap: 34px 46px; margin-top: 26px; }
.badge { display: flex; flex-direction: column; align-items: center; gap: 10px;
  text-decoration: none; color: var(--soft); min-width: 96px; }
a.badge:hover { color: var(--accent); }
a.badge:hover img { transform: translateY(-2px); }
.badge img { width: auto; object-fit: contain; transition: transform .15s; }   /* height comes from the markup, per-logo optical sizing */
.badge-label { font-family: var(--body); font-weight: 600; font-size: .8rem;
  letter-spacing: .02em; line-height: 1.3; max-width: 130px; }

/* The years badge has no mark, because it is a number rather than a logo.
   Setting it in the display face at the logo height keeps the row's baseline
   even instead of leaving one item visibly short. */
.badge-num { display: flex; align-items: center; justify-content: center;
  height: 54px; font-family: var(--display); font-weight: 700;
  font-size: 2.6rem; line-height: 1; color: var(--accent); }

/* Placeholder for a logo that has not landed yet. Deliberately visible and
   deliberately the exact height of a real badge, so the row being reviewed is
   the row that ships and a late file cannot reflow the page. */
.badge-slot { display: flex; align-items: center; justify-content: center;
  width: 96px; border: 1px dashed var(--rule); border-radius: 4px;
  background: var(--panel-soft); color: var(--soft);
  font-size: .62rem; letter-spacing: .01em; padding: 0 6px;
  word-break: break-all; text-align: center; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 900px) {
  .fgrid { grid-template-columns: 1fr 1fr; gap: 28px; }
  .fbrand { grid-column: 1 / -1; text-align: center; }
  .fbrand img { margin-left: auto; margin-right: auto; }
  .social { justify-content: center; }
}
@media (max-width: 860px) {
  .idband .wrap { grid-template-columns: 1fr; gap: 16px; text-align: center;
    padding-top: 16px; padding-bottom: 16px; }
  .idband .info { text-align: center; }
  /* Restated, not inherited. .idband .brand carries text-align:left at desktop
     so the logo anchors the left edge; that selector is more specific than the
     `text-align: center` on .idband .wrap here, so without this line the phone
     logo silently went left-aligned when the desktop fix landed. */
  .idband .brand { text-align: center; }
  .idband .brand img { height: 150px; }
  .masthead.compact .idband .brand img { height: 75px; }   /* 50% of 150 */
  .idband .brand .tag { font-size: 1.05rem; margin-top: 10px; }
  .idband .warr { font-size: 1.12rem; line-height: 1.3; }
  .idband .tel { font-size: 2.1rem; margin-bottom: 7px; }
  .idband .meta { font-size: .98rem; }

  .rhero .scrim { background: linear-gradient(180deg, rgba(31, 46, 96, .88) 0%, rgba(31, 46, 96, .93) 100%); }
  .rhero h1, .rhero .lede { max-width: none; }
  .page-hero h1, .page-hero .lede { max-width: none; }

  /* utility strip: bigger claim, everything centred */
  .util .wrap { flex-direction: column; align-items: center; text-align: center; gap: 14px;
    padding-top: 16px; padding-bottom: 16px; }
  .util .claim { font-size: 1.72rem; line-height: 1.2; max-width: none; margin: 0 auto; }
  .mbr { display: inline; }
  .util .acts { justify-content: center; width: 100%; gap: 10px; }
  .util .acts a { flex: 1 1 auto; min-width: 150px; text-align: center; font-size: .92rem; padding: 13px 16px; }

  /* nav pills: centred, even rows. This is what a no-JS phone still gets. */
  .mainnav .wrap { padding-left: 14px; padding-right: 14px; }
  .mainnav nav { justify-content: center; gap: 8px; }
  .mainnav a { font-size: .88rem; padding: 9px 16px; }

  /* Hamburger. .nav-js is added by site.js — without it none of this applies
     and the pills above stand, which is the correct no-JS fallback. */
  .mainnav.nav-js .navtoggle { display: flex; align-items: center; justify-content: center;
    gap: 10px; width: 100%; background: var(--dakota-medium-blue); color: #fff;
    border: 0; border-radius: 5px; padding: 13px 16px; cursor: pointer;
    font-family: var(--body); font-weight: 700; font-size: 1rem; letter-spacing: .02em; }
  .mainnav.nav-js .navtoggle[aria-expanded="true"] { background: var(--accent); }
  .mainnav.nav-js nav { display: none; }
  /* The bar is sticky, so a tall open menu has to scroll inside itself rather
     than run off the bottom of the screen with links nobody can reach. */
  /* flex-wrap MUST be restated. The base .mainnav nav rule sets `wrap`, and a
     later block only replaces the properties it names — so a column container
     with wrapping still on hits max-height and wraps into extra COLUMNS, which
     puts half the menu off the right edge of the phone. It looks like a
     layout bug in the dropdown and it is not: it is one unrestated property. */
  .mainnav.nav-js nav.open { display: flex; flex-direction: column; flex-wrap: nowrap;
    align-items: stretch; justify-content: flex-start;
    gap: 6px; padding-top: 10px; max-height: calc(100vh - 132px); overflow-y: auto;
    -webkit-overflow-scrolling: touch; }
  .mainnav.nav-js nav.open a { text-align: center; font-size: 1rem; padding: 13px 16px; }

  /* Dropdowns on touch. There is no hover on a phone, so the children are
     ALWAYS visible and indented under their parent rather than hidden behind
     an interaction the device cannot perform. Same dark treatment and same
     red hover as the desktop panel — one design for one component, not two.
     The absolute positioning and the hover bridge both come off. */
  .mainnav.nav-js nav.open .navitem { display: flex; flex-direction: column;
    gap: 6px; position: static; }
  /* The desktop rule makes the parent link inline-flex so the caret sits
     beside the label. Left alone, that beats `text-align: center` here and
     the dropdown parents read left-aligned while every other item is
     centred — two treatments for one component. */
  .mainnav.nav-js nav.open .navitem > a { display: flex; justify-content: center; }
  .mainnav.nav-js nav.open .navitem::after { display: none; }
  .mainnav.nav-js nav.open .subnav { display: block; position: static;
    margin: 0; padding: 4px 0; min-width: 0; box-shadow: none;
    background: var(--ink-deep); border-radius: 5px; }
  .mainnav.nav-js nav.open .subnav a { text-align: center; font-size: .95rem;
    padding: 11px 16px; white-space: normal; }
  .mainnav.nav-js nav.open .caret { display: none; }

  .formsplit { grid-template-columns: 1fr; gap: 30px; }
  .doors { grid-template-columns: 1fr; }
  .post-grid, .post-grid.cols-3 { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  section { padding: 38px 0; }
  table.cmp { display: block; overflow-x: auto; white-space: nowrap; font-size: .88rem; }
  table.cmp th, table.cmp td { padding: 10px 12px; }
  .btn { font-size: 1.15rem; padding: 14px 24px; }
}
@media (max-width: 560px) {
  /* The masthead has to FIT ON THE PHONE. Measured at 375x667 it was 719px at
     rest — taller than the whole viewport — which put the h1 at 801px and gave
     a phone visitor a first screen containing nothing but header. No headline,
     nothing about the business, nothing to tap.
     util 223 + idband 426 + nav 70. All three come down here, and the numbers
     are checked by qa/masthead.js rather than eyeballed. */
  .util .wrap { gap: 8px; padding-top: 8px; padding-bottom: 8px; }
  /* Two decorative lines come out on a phone. Neither carries information the
     page does not repeat immediately below: .claim is a tagline and the h1
     says the same thing, .tag restates the services the nav lists. The two
     CTA buttons stay — those are the conversion path. */
  .util .claim { display: none; }
  .idband .brand .tag { display: none; }
  /* NOTE for anyone tempted to put these two buttons side by side on a phone:
     don't, and read @media (max-width: 420px) further down first. It sets
     flex-direction: column deliberately, so the CTAs are full-width tap
     targets on small screens. Since 375px matches BOTH blocks and that one
     comes later, a `flex-direction: row` here is silently overridden below
     420px and appears to do nothing at all.
     Two lessons, both already in the playbook: a later rule only replaces the
     properties it restates, and the property that decides the layout is the
     one to read first. Measured, not guessed. */
  .util .acts { gap: 8px; }
  .util .acts a { font-size: .84rem; padding: 10px 12px; }
  .idband .wrap { gap: 8px; padding-top: 10px; padding-bottom: 10px; }
  /* Mark, 1 Sep 2026: the phone logo was too small. 72 -> 115, +60%.
     Only this block moves. A phone matches 860, 620, 560 and 420, and the
     narrowest wins per property, so 560 is what a handset actually gets;
     the 860 block is tablets and 150 -> 240 there would be absurd. */
  .idband .brand img { height: 115px; }
  .idband .warr { font-size: .98rem; margin-bottom: 5px; }
  .idband .tel { font-size: 1.85rem; margin-bottom: 4px; }
  .idband .meta { font-size: .88rem; margin-bottom: 2px; }
  .mainnav .wrap { padding-top: 8px; padding-bottom: 8px; }
  /* Compact on a phone is a bar, not a second header. */
  /* Compact +25%, 36 -> 45. NOTE this deliberately breaks the "compact is
     half the at-rest height" rule the other two breakpoints follow: 45 of
     115 is 39%. That is the instruction, not a slip - a phone header that
     halves a 115px logo leaves a mark too small to read at arm's length,
     which is the whole reason the at-rest size went up. */
  .masthead.compact .idband .brand img { height: 45px; }   /* 39% of 115 */
  .masthead.compact .idband .tel { font-size: 1.3rem; }

  .fgrid { grid-template-columns: 1fr; gap: 24px; }
  /* Two sub-columns of link text on a 375px screen is two thin ribbons.
     The footer is the flat tappable list a phone user relies on, so it
     collapses to one column with full-width tap targets. */
  .fnav ul { columns: 1; }
  .formcard { padding: 20px 18px 22px; }
  .formcard .frow { grid-template-columns: 1fr; }
  .formcard .btn { width: 100%; }   /* full width is right on a phone */
  .trustbar .wrap { gap: 14px; }
  .tb { flex: 1 1 45%; min-width: 135px; }
  .legal .wrap { flex-direction: column; text-align: center; }
  .legal .links a { margin: 0 8px; }
}
@media (max-width: 420px) {
  .util .claim { font-size: 1.5rem; }
  .util .acts { flex-direction: column; }
  .util .acts a { width: 100%; }
}
@media print {
  .util .acts, .mainnav, .skip, .social { display: none; }
  body { font-size: 12pt; }
}


/* ---------------------------------------------------------------------------
   Blog post hero.

   Capped at 800px because the source photographs ARE 800x533 - Mark, 1 Sep
   2026. Letting the figure fill the article column would stretch every one of
   them roughly 1.3x and soften the first thing anybody sees on the post.

   aspect-ratio holds the box before the file arrives so the text below does
   not jump. The img already carries width and height attributes, which handles
   this on its own in a modern browser; the ratio is belt and braces for the
   case where CSS loads and the attributes are ever dropped.

   Appended at the very end of the file on purpose. Two rules with the same
   selector merge per property in this stylesheet, and anything a later block
   forgets to restate keeps the older value - that has bitten this project four
   times. Last in the file means nothing downstream can quietly win.
--------------------------------------------------------------------------- */
.post-hero { margin: 0 0 1.6rem; max-width: 800px; }
.post-hero img { display: block; width: 100%; height: auto;
                 aspect-ratio: 800 / 533; border-radius: 6px;
                 background: #eee; }

/* Post card thumbnail and blog pagination. Added 1 Sep 2026 - the home page
   cards and /blog/ were running text-only while every post had a hero sitting
   unused.

   The card is a single <a>. Padding moves off the anchor and onto an inner
   .post-body so the image can go full bleed to the card edge instead of
   floating in a 26px frame. Cards without an image keep the old look, which is
   why .has-img gates the change rather than restyling every card. */
.post-card.has-img { padding: 0; overflow: hidden; }
.post-card.has-img .post-body { display: block; padding: 20px 26px 22px; }
.post-card-img { display: block; width: 100%; height: auto;
  aspect-ratio: 400 / 267; object-fit: cover; background: #eee; }

.pager { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin-top: 30px; }
.pager a, .pager-now { display: inline-block; min-width: 40px; text-align: center;
  padding: 8px 12px; border: 1px solid var(--rule); border-radius: 4px;
  text-decoration: none; font-weight: 700; }
.pager a:hover { border-color: var(--ink); }
.pager-now { background: var(--ink); color: #fff; border-color: var(--ink); }
.pager-prev, .pager-next { min-width: 0; }
@media (max-width: 620px) {
  .pager a, .pager-now { min-width: 34px; padding: 7px 9px; font-size: .92rem; }
}

/* Contains a float that is taller than the copy beside it.

   figure.shot.right is used on service pages where the body runs long enough
   to enclose it. On the home page owner section the photo is portrait - about
   625px rendered - against roughly 230px of copy, so without this the bottom
   400px of the image would hang down into the FAQ section underneath.

   display: flow-root rather than a clearfix pseudo-element or overflow:hidden.
   It establishes a block formatting context, which is exactly the thing being
   asked for, and it does it without the side effects the other two carry -
   overflow:hidden also clips, and ::after clearfix collapses margins
   differently. Scoped to a class, not applied to every .wrap, because changing
   margin collapsing site-wide to fix one section is how spacing bugs get
   introduced three pages away. */
.wrap.holds-float { display: flow-root; }

/* Full-width Google map. The section carries no vertical padding because the
   map IS the section - padding would frame it in white and lose the edge to
   edge effect that makes it read as part of the page rather than a widget
   dropped into it. */
.mapband { padding: 0; line-height: 0; }
.mapband iframe { display: block; width: 100%; height: 400px; border: 0; }
@media (max-width: 620px) { .mapband iframe { height: 320px; } }

/* Images inside a post body. Three posts came out of WordPress with their own
   picture at the top of the article, and those get no allocated hero - the
   writer's own image is more topical and already in the right place. They still
   need the hero's sizing rules, or they load at whatever the browser guesses
   and shove the text down when they arrive. */
.article > p > img,
.article > img { display: block; max-width: 800px; width: 100%; height: auto;
  margin: 0 0 1.6rem; border-radius: 6px; background: #eee; }

/* Address as a tap-for-directions link, masthead and footer.

   Inherits colour and drops the underline, because the address should still
   read as the address rather than as a blue link in the middle of the header.
   The affordance is on hover and focus instead - and on a phone, where hover
   does not exist, the whole block is simply tappable, which is the case that
   actually matters for somebody sitting in a car park.

   display:block so the entire two-line address is the target, not just the
   text baseline. That is the difference between a comfortable thumb target and
   a fiddly one. */
.maplink { color: inherit; text-decoration: none; display: block; }
/* Hover colour depends on which band the link sits on.

   Masthead is the light blue, so the red accent reads: 6.6:1 against it.
   The FOOTER is dark navy, where that same red drops to 2.0:1 and effectively
   disappears - which is what Mark saw.

   The footer hover brightens to white rather than to the palette light blue.
   The footer address is already --band-body #dbe6f7, so #C9DAF5 would be
   DARKER than the text it replaces: a hover that dims by 32 units out of 765
   and reads as a rendering glitch rather than a response. White is 13:1 on the
   band and moves in the direction a hover should. */
.maplink:hover .meta { color: var(--accent); }
.maplink:hover .meta svg { fill: var(--accent); }
footer .maplink:hover .addr { color: #fff; }
.maplink:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px;
  border-radius: 3px; }


/* ---- Staff bio cards (/our-technicians/) ------------------------------
   The black-framed card from the outgoing site, which the client likes,
   rebuilt so the words are text. Black card, thin white keyline around
   both the photo and the bio, cyan labels. 2026-09-08. */
.staff { list-style: none; margin: 28px 0 0; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 28px; }
.staffcard { background: #000; padding: 12px; border-radius: 2px;
  display: flex; flex-direction: column; gap: 12px; }
.staffcard .frame { border: 1px solid #fff; padding: 6px; }
.staffcard .frame img { display: block; width: 100%; height: auto; }
.staffcard .frame .ph { margin: 0; }
.staffcard .bio { color: #fff; padding: 14px 12px 12px; flex: 1; }
.staffcard .bio h3 { color: #fff; font-size: 1.55rem; margin: 0 0 2px;
  text-align: center; letter-spacing: .02em; }
.staffcard .bio .role { text-align: center; color: #fff; margin: 0 0 12px;
  font-size: .95rem; }
.staffcard .bio p { color: #fff; font-size: .86rem; line-height: 1.5;
  margin: 0 0 6px; }
.staffcard .bio p b { color: #3FC1F2; font-weight: 700; }

/* Badges on the solar page: two drawn SVG marks stacked down the right of
   the list, the way figure.shot.right sits beside prose. Centred in a row
   on their own they read as thrown in. Mobile puts them in a row above. */
.badges { float: right; display: flex; flex-direction: column; gap: 18px;
  width: 170px; margin: 0 0 20px 40px; }
.badges img { width: 170px; height: auto; }
.badges + .terms { overflow: hidden; }
@media (max-width: 760px) {
  .badges { float: none; flex-direction: row; justify-content: center;
    width: auto; margin: 8px 0 22px; }
  .badges img { width: 140px; }
}

/* Trust badges read small on desktop next to the heading; a third larger
   there. Mobile keeps the markup height, where they already fit. */
@media (min-width: 761px) {
  .badge img { height: calc(var(--bh, 54px) * 1.33); }
  .badge-num { height: 72px; font-size: 3.45rem; }
  .badge-label { font-size: .9rem; max-width: 150px; }
  .badgerow { gap: 34px 56px; }
}

/* "(if you have one)" beside the offer code label. */
.formcard label .opt { font-weight: 400; color: var(--soft); font-size: .9em; }

/* The two words on the warranty page that people get caught by. */
b.loud { font-size: 1.25em; font-weight: 800; letter-spacing: .02em; color: var(--accent); }

/* Staff page banner: everybody's auto repair years added up. Dark band
   above the cards, big number left, one line right. */
.staffstat { display: flex; align-items: center; gap: 22px; background: var(--ink);
  color: #fff; border-radius: 4px; padding: 20px 28px; margin: 26px 0 30px; }
.staffstat .num { font-family: var(--display); font-weight: 700; font-size: 3.4rem;
  line-height: 1; color: #fff; }
.staffstat .txt { font-size: 1.15rem; line-height: 1.4; max-width: 34ch; }
@media (max-width: 560px) {
  .staffstat { flex-direction: column; text-align: center; gap: 8px; }
  .staffstat .num { font-size: 2.8rem; }
}
