/* custom.css — Don's Service design layer.
 *
 * A 1:1 port of the original SvelteKit landing page (fixitdon.com). That site
 * was shadcn + Tailwind v3; this one is server-rendered HTML + Tailwind v4, so
 * the *look* is reproduced here rather than the class soup. Loads after
 * site.css and theme.css, so everything below wins.
 *
 * Brand: navy #020075 (primary) / red #D90000 (secondary).
 * Type:  Lato for body, Bevan for the display numerals — same pairing as the
 *        source, which used @fontsource/bevan plus a Lato body rule.
 *
 * The Google Fonts request USED to live here as an @import, which forced the
 * browser to fetch this file, parse it, and only then discover the font CSS —
 * a three-deep serial chain on the critical path. It now loads from a
 * preconnected <link> in views/layout.html so the request starts alongside
 * this stylesheet instead of after it (§5).
 */

:root {
  --dons-navy: #020075;
  --dons-navy-deep: #000537;
  --dons-red: #d90000;
  /* Source header measures ~62px on phones and grows on desktop. */
  --dons-header-h: 3.9rem;
}
@media (min-width: 768px) {
  :root { --dons-header-h: 5rem; }
}

body {
  font-family: "Lato", ui-sans-serif, system-ui, sans-serif;
}

/* Bevan is a display face — used only for phone numbers and the form's
   primary buttons, exactly where the source used it. */
.zk-phone-num,
.zk-dons-form .btn-primary {
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  letter-spacing: 0.01em;
}
/* Bevan reads cramped inside the kit's stock 12px/24px button box — give
   the stepped form's Continue/Back/Submit more room to breathe. */
.zk-dons-form .btn-primary { padding: 0.85rem 2rem; }

/* ── header ──────────────────────────────────────────────────────────
   The original floats a translucent navy bar over the hero photo and
   shrinks the wordmark on scroll. site.js does not emit a scroll class,
   so the shrink is handled with a scroll-timeline-free approach: the bar
   keeps one height and the logo sizes down only on small screens. */
body > header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--dons-header-h);
  /* Solid navy is the DEFAULT. The translucent treatment below only works
     when there is a dark photo behind it; on the blog, contact and privacy
     pages the light page background showed through the 25% gap and turned
     the bar a washed-out indigo. */
  background: var(--dons-navy);
  border-bottom: 0;
  box-shadow: 0 4px 16px rgb(0 0 0 / 0.18);
}
/* Landing only — the hero photo bleeds under the bar, so the glass effect
   has something to act on. Keyed off the same .zk-dons marker the padding
   rule below uses, so the two can never disagree about which page this is. */
body:has(main#app > .zk-dons) > header {
  background: color-mix(in srgb, var(--dons-navy) 75%, transparent);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
body > header > div {
  height: var(--dons-header-h);
  max-width: 96rem;
}
/* The wordmark is a wide SVG, not the kit's square avatar. */
.zk-header-logo {
  height: 2.35rem;
  width: auto;
  transition: height 0.3s ease;
}
@media (min-width: 768px) {
  .zk-header-logo { height: 3.5rem; }
}
/* Phones get less horizontal padding, as the source does, so the wordmark
   and the call button both fit on one line at 390px. */
@media (max-width: 640px) {
  body > header > div { padding-left: 0.75rem; padding-right: 0.75rem; }
}
/* The logo IS the site name here — drop the duplicated text. */
body > header [data-site-title] { display: none; }
body > header nav a { color: #fff; }
body > header nav a:hover { color: #fff; opacity: 0.75; }
body > header .zk-ibtn,
body > header .zk-mnav-btn { color: #fff; }

/* The header floats, so pages must clear it themselves. The Don's landing
   is the exception: its hero photo bleeds full-bleed UNDER the translucent
   bar (as the source does), and the hero card's own top margin does the
   clearing — so that page gets no padding. */
main#app { padding-top: var(--dons-header-h); }
main#app:has(> .zk-dons) { padding-top: 0; }

/* The original has NO header nav on the LANDING — just the wordmark and the
   call button, with the footer carrying the links. Interior pages are not
   one-pagers though: without a nav, /blog and a post had no route to Contact
   and no way back to the index. So everywhere else the kit's responsive nav
   (desktop row + <details> drawer on phones) is left alone to do its job.

   The landing keeps that stripped header with ONE exception: a lone Blog
   link, because otherwise the blog was reachable from the home page only by
   scrolling the entire one-pager down to the footer.

   This MUST be done in CSS rather than by rendering a different nav for the
   landing. The header lives outside #app and hx-boost only swaps #app, so the
   header's markup is frozen at first page load — a landing-specific nav would
   follow you onto every interior page you clicked through to. `:has()` re-runs
   on each boosted swap, so the same full menu can be pared down here and
   restored the moment #app stops being the landing.

   The surviving link sits inline at EVERY width, overriding Tailwind's
   `hidden md:flex`, which exists to fold a MULTI-item nav into a drawer on
   phones. One short word needs no drawer, so .zk-mnav stays hidden here and
   takes the mobile panel with it. */
body:has(main#app > .zk-dons) > header nav[data-nav] { display: flex; }
body:has(main#app > .zk-dons) > header nav[data-nav] > :not([data-nav-path="/blog"]) { display: none; }
body:has(main#app > .zk-dons) > header .zk-mnav { display: none; }

/* Interior nav sits on solid navy, so the links are white with a subtle
   pill on hover and a filled pill for the current page.
   NOTE the colours are set on .navlink, not on `header nav a` — site.css
   styles .navlink with `color: var(--color-secondary)`, and in this theme
   --color-secondary is the brand RED, which rendered the nav red-on-navy
   (illegible, and nowhere near a passing contrast ratio). A bare element
   selector loses to that class; these rules carry it. */
body > header nav[data-nav] .navlink,
body > header .zk-mnav-panel .navlink {
  color: #fff;
  padding: 0.4rem 0.7rem;
  border-radius: 0.375rem;
  font-weight: 700;
  transition: background-color 0.15s ease, color 0.15s ease;
}
body > header nav[data-nav] .navlink:hover,
body > header .zk-mnav-panel .navlink:hover {
  color: #fff;
  background: rgb(255 255 255 / 0.14);
  opacity: 1;
}
body > header nav[data-nav] .navlink-active,
body > header .zk-mnav-panel .navlink-active {
  color: #fff;
  background: rgb(255 255 255 / 0.22);
}
/* site.css draws a --color-primary underline under the active link; that is
   navy-on-navy here, so the filled pill above stands in for it. */
body > header .navlink-active::after { display: none; }

/* The mobile drawer drops out of the fixed header, so it needs its own
   navy panel rather than the kit's light one. */
body > header .zk-mnav-panel {
  background: var(--dons-navy);
  border: 1px solid rgb(255 255 255 / 0.15);
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.3);
}
body > header .zk-mnav-panel a { color: #fff; display: block; }
body > header .zk-mnav-panel a:hover { background: rgb(255 255 255 / 0.14); }

/* Footer: the original is a small centred credit line sitting on the page
   background, not the kit's dark three-column block. */
body > footer {
  background: transparent;
  color: inherit;
}
.zk-dons-footer {
  color: color-mix(in srgb, var(--dons-navy-deep) 60%, transparent);
  padding-top: 1rem;
}
[data-theme="dark"] .zk-dons-footer { color: rgb(255 255 255 / 0.6); }
.zk-dons-footer a {
  text-decoration: underline;
  text-underline-offset: 4px;
  color: inherit;
}
.zk-dons-footer a:hover { color: var(--dons-navy); }
[data-theme="dark"] .zk-dons-footer a:hover { color: #fff; }
.zk-dons-footer .zk-sep { margin: 0 0.5rem; opacity: 0.6; }

/* The source page sits on a very soft neutral→red wash rather than flat
   white (its wrapper: from-neutral-200 via-neutral-100 to-red-100). */
body {
  background-image: linear-gradient(
    to bottom right,
    #f2f2f3 0%,
    var(--color-surface) 45%,
    color-mix(in srgb, var(--dons-red) 7%, var(--color-surface)) 100%
  );
  background-attachment: fixed;
}
[data-theme="dark"] body {
  background-image: linear-gradient(
    to bottom right,
    #000 0%, #000 45%,
    color-mix(in srgb, var(--dons-red) 18%, #000) 100%
  );
}

/* ── call button ─────────────────────────────────────────────────── */
.zk-btn-call {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1.25rem;
  border-radius: 9999px;
  background: var(--dons-red);
  color: #fff;
  font-weight: 700;
  line-height: 1;
  transition: transform 0.3s ease, background-color 0.2s ease;
}
.zk-btn-call:hover { transform: translateY(-2px); color: #fff; }
.zk-btn-call--sm { padding: 0.45rem 0.9rem; font-size: 0.9rem; }
/* The source keeps the number visible on phones — it is the primary CTA on
   a site people call. Shrink it to fit rather than hiding it. */
@media (max-width: 640px) {
  .zk-btn-call--sm { padding: 0.4rem 0.7rem; font-size: 0.72rem; gap: 0.35rem; }
  .zk-btn-call--sm svg { height: 0.9rem; width: 0.9rem; }
}

/* ── hero ────────────────────────────────────────────────────────── */
.zk-dons-hero {
  background-size: cover;
  position: relative;
}
.zk-hero-card {
  background: color-mix(in srgb, var(--color-surface) 72%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.zk-hero-card h1 { color: var(--dons-navy-deep); }
.zk-hero-card .article { color: var(--dons-navy-deep); }
/* site.css gives .article prose spacing; its trailing margin left a large
   gap above the Call Now button that the source doesn't have. */
.zk-hero-card .article > :last-child { margin-bottom: 0; }
@media (max-width: 767px) {
  /* Tighter hero on phones — the source's is noticeably more compact.
     The h1 matches the source's text-3xl (1.875rem): the earlier 1.5rem
     left the page title SMALLER than the section headings below it. */
  .zk-hero-card { padding: 1.25rem; margin-bottom: 1rem; }
  .zk-hero-card h1 { font-size: 1.875rem; line-height: 1.2; }
}
[data-theme="dark"] .zk-hero-card { background: color-mix(in srgb, #0b1020 78%, transparent); }
[data-theme="dark"] .zk-hero-card h1,
[data-theme="dark"] .zk-hero-card .article { color: #e5e7eb; }

/* ── appliance repair row ────────────────────────────────────────── */
.zk-dons-repair { padding-block: 2.5rem 1rem; }
.zk-repair-head { color: var(--dons-navy-deep); }
[data-theme="dark"] .zk-repair-head { color: #fff; }
.zk-repair-head {
  border-bottom: 2px solid var(--dons-red);
}
@media (min-width: 768px) {
  .zk-repair-head {
    border-bottom: 0;
    border-right: 2px solid var(--dons-red);
  }
}
.zk-appliance-icon { margin-inline: auto; }

/* ── about row ───────────────────────────────────────────────────── */
.zk-about-veil { background: rgb(255 255 255 / 0.8); }
/* Dark needs the DEEP navy at ~91%: the brand navy at 83% let bright photo
   regions bleed through and washed the white heading out. */
[data-theme="dark"] .zk-about-veil { background: #000537e8; }

/* "Schedule Appliance Repair" is brand navy via text-[var(--color-primary)]
   in the markup — invisible on the dark background. */
[data-theme="dark"] .zk-dons-contact h2 { color: #fff; }
.zk-about-left { color: var(--dons-navy); }
[data-theme="dark"] .zk-about-left { color: #fff; }
/* The source keeps "About Don's Service" on one line down to 390px; at the
   desktop 38px it would wrap, so step it down on small screens. */
@media (max-width: 767px) {
  .zk-about-left h2 { font-size: 1.6rem; margin-bottom: 1rem; }
  .zk-about-left .h-20 { height: 4rem; width: 4rem; }
}
.zk-about-right { background: #f0f0f0; }
[data-theme="dark"] .zk-about-right { background: #414141; }

/* ── FAQ band ────────────────────────────────────────────────────── */
.zk-dons-faq { background: var(--dons-navy); margin-top: -1.5rem; }

/* Smooth answer rollout, like the source site. Native <details> snaps
   open; modern CSS animates ::details-content height instead. Everything
   sits behind one @supports so browsers without it keep the instant
   toggle — and with no JS involved the accordion works either way. */
@supports selector(::details-content) {
  .zk-faq-item { interpolate-size: allow-keywords; }
  .zk-faq-item::details-content {
    block-size: 0;
    overflow-y: clip;
    transition: block-size 0.32s ease, content-visibility 0.32s allow-discrete;
  }
  .zk-faq-item[open]::details-content { block-size: auto; }
}
.zk-dons-faq-grid .zk-faq-list {
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 1fr;
  /* site.css caps the stock FAQ list at 48rem for readability; the Don's
     band is a full-width two-column grid, so lift the cap. */
  max-width: none;
  margin-top: 0;
}
@media (min-width: 768px) {
  .zk-dons-faq-grid .zk-faq-list { grid-template-columns: 1fr 1fr; }
}
.zk-dons-faq-grid .zk-faq-item {
  background: #fff;
  border-radius: 0.5rem;
  overflow: hidden;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
  align-self: start;
}
.zk-dons-faq-grid .zk-faq-q {
  color: var(--dons-navy);
  font-weight: 600;
  font-size: 1.125rem;
  padding: 1rem;
}
.zk-dons-faq-grid .zk-faq-a {
  background: #f9fafb;
  color: var(--dons-navy);
  padding: 1rem;
}

/* ── contact ─────────────────────────────────────────────────────── */
.zk-contact-line {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.25rem;
  color: var(--dons-navy);
}
[data-theme="dark"] .zk-contact-line { color: #fff; }
/* Never break a phone number across lines — at tablet widths this column is
   narrow enough that it otherwise splits as "676-" / "3361". */
.zk-contact-line .zk-phone-num { white-space: nowrap; }
.zk-contact-line svg { flex: none; }
@media (min-width: 768px) and (max-width: 1100px) {
  .zk-contact-line { font-size: 1rem; }
  .zk-contact-line svg { height: 2rem; width: 2rem; }
}

/* ── two-step form ───────────────────────────────────────────────── */
.zk-dons-form {
  background: #fff;
  border: 1px solid rgb(0 0 0 / 0.1);
  border-radius: 0.5rem;
  padding: 1.5rem;
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.05);
}
[data-theme="dark"] .zk-dons-form {
  background: #1f2937;
  border-color: #374151;
}
/* Required-field marker, as the source form shows. */
.zk-req { color: var(--dons-red); }

/* The source centres the contact intro under the heading. */
.zk-contact-intro { text-align: center; }
@media (max-width: 768px) {
  .zk-contact-intro { text-align: left; }
}
.zk-check {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid rgb(0 0 0 / 0.12);
  border-radius: 0.5rem;
  cursor: pointer;
}
.zk-check:hover { border-color: var(--dons-red); }
.zk-check input { accent-color: var(--dons-red); width: 1.1rem; height: 1.1rem; }
[data-theme="dark"] .zk-check { border-color: #374151; }
.zk-dons-form .btn-primary {
  background: var(--dons-navy);
  color: #fff;
  border-radius: 0.375rem;
}
.zk-dons-form .btn-primary:hover { background: color-mix(in srgb, var(--dons-navy) 90%, #fff); }
.zk-dons-form .zk-btn-back { background: transparent; color: var(--dons-navy); border: 1px solid var(--dons-navy); }
[data-theme="dark"] .zk-dons-form .zk-btn-back { color: #fff; border-color: #fff; }

/* Touch targets + no iOS zoom-on-focus, carried over from the source. */
@media (max-width: 640px) {
  .zk-dons-form input,
  .zk-dons-form select,
  .zk-dons-form textarea { font-size: 16px; }
  .zk-dons-form button,
  .zk-check input { min-height: 44px; }
  .zk-check input { min-height: 1.1rem; }
}

/* ── floating "jump to contact" pill ─────────────────────────────────
   The source's contact button: a fixed circle below the header on the
   right, brand-red ring and glyph on the page background. It stays put
   while the form is far away and clears out as you reach it (custom.js
   toggles [hidden] / .is-visible). */
.zk-jump-contact {
  position: fixed;
  top: calc(var(--dons-header-h) + 1.25rem);
  right: 0.5rem;
  z-index: 50;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;          /* 44px — a real touch target */
  height: 2.75rem;
  padding: 0.25rem;
  border-radius: 9999px;
  border: 1px solid var(--dons-red);
  background: var(--color-surface);
  color: var(--dons-red);
  box-shadow: 0 4px 14px rgb(0 0 0 / 0.14);
  /* Matches the source's fly({y:100, duration:200}). */
  transform: translateY(100px);
  opacity: 0;
  transition: transform 0.2s ease, opacity 0.2s ease, background-color 0.2s ease;
}
.zk-jump-contact.is-visible { transform: translateY(0); opacity: 1; }
.zk-jump-contact:hover { background: color-mix(in srgb, var(--dons-red) 10%, var(--color-surface)); }
.zk-jump-contact:focus-visible { outline: 2px solid var(--dons-red); outline-offset: 2px; }
[data-theme="dark"] .zk-jump-contact { background: var(--dons-navy-deep); }

/* [hidden] must win over the inline-flex above, or the pill would still
   occupy the corner on pages with no contact form. */
.zk-jump-contact[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .zk-jump-contact { transition: opacity 0.2s ease; transform: none; }
}

/* The header is fixed, so an anchor jump would tuck the heading under it. */
#contact-form { scroll-margin-top: calc(var(--dons-header-h) + 1rem); }
#contact-form:focus { outline: none; }

/* ── blog pagination ─────────────────────────────────────────────────
   Replaces the old JavaScript "Load more" button: real links, so every
   page is crawlable, bookmarkable and works with JavaScript off. */
.zk-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.375rem;
  margin-top: 3rem;
}
.zk-page-nums { display: inline-flex; align-items: center; gap: 0.375rem; flex-wrap: wrap; }
.zk-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-width: 2.5rem;   /* 40px — comfortable tap target */
  height: 2.5rem;
  padding: 0 0.75rem;
  border-radius: 0.375rem;
  border: 1px solid color-mix(in srgb, var(--dons-navy) 25%, transparent);
  color: var(--dons-navy);
  font-weight: 700;
  line-height: 1;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.zk-page:hover { background: var(--dons-navy); color: #fff; border-color: var(--dons-navy); }
.zk-page.is-current {
  background: var(--dons-navy);
  color: #fff;
  border-color: var(--dons-navy);
  cursor: default;
}
/* Prev/Next at the ends stay in place when there is nowhere to go, so the
   row doesn't reflow between pages. */
.zk-page.is-disabled { opacity: 0.35; pointer-events: none; }
.zk-page-gap { padding: 0 0.15rem; opacity: 0.5; }
.zk-page:focus-visible { outline: 2px solid var(--dons-red); outline-offset: 2px; }

[data-theme="dark"] .zk-page { color: #fff; border-color: rgb(255 255 255 / 0.3); }
[data-theme="dark"] .zk-page:hover,
[data-theme="dark"] .zk-page.is-current { background: #fff; color: var(--dons-navy); border-color: #fff; }

/* Phones: the word labels push the row to two lines — keep the arrows. */
@media (max-width: 480px) {
  .zk-page-arrow span { display: none; }
  .zk-page-arrow { min-width: 2.5rem; padding: 0 0.5rem; }
}

/* ── post byline, tags, related ──────────────────────────────────────── */
.zk-byline { font-weight: 700; }

.zk-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid color-mix(in srgb, var(--dons-navy) 15%, transparent);
  list-style: none;
  padding-left: 0;
}
.zk-tag {
  display: inline-block;
  padding: 0.3rem 0.7rem;
  border-radius: 9999px;
  border: 1px solid color-mix(in srgb, var(--dons-navy) 25%, transparent);
  color: var(--dons-navy);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.4;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.zk-tag:hover { background: var(--dons-navy); color: #fff; border-color: var(--dons-navy); }
.zk-tag:focus-visible { outline: 2px solid var(--dons-red); outline-offset: 2px; }
[data-theme="dark"] .zk-tags { border-top-color: rgb(255 255 255 / 0.15); }
[data-theme="dark"] .zk-tag { color: #fff; border-color: rgb(255 255 255 / 0.3); }
[data-theme="dark"] .zk-tag:hover { background: #fff; color: var(--dons-navy); border-color: #fff; }

/* The related band closes the article, so it gets a rule above it rather
   than floating between two white expanses. */
.zk-related { border-top: 1px solid color-mix(in srgb, var(--dons-navy) 12%, transparent); padding-top: 3rem; }
[data-theme="dark"] .zk-related { border-top-color: rgb(255 255 255 / 0.12); }

/* The kit uses --color-secondary for muted card text, but this theme maps
   that token to the brand RED — post summaries were rendering red. Muted
   grey is what the card wants; red stays for accents that mean something. */
.zk-post-card p.text-\[var\(--color-secondary\)\] {
  color: color-mix(in srgb, var(--dons-navy-deep) 65%, transparent);
}
[data-theme="dark"] .zk-post-card p.text-\[var\(--color-secondary\)\] { color: rgb(255 255 255 / 0.65); }

/* ── blog post page — the "service manual" treatment ─────────────────────
   A post reads like a page from a well-kept appliance service manual:
   navy blueprint-grid masthead, stamped kicker, Bevan display headline,
   an overlapping "work order" strip, numbered section headings, a drop
   cap, shop-tip callouts, and a CSS-only reading-progress rule. Markup
   comes from postMastheadHtml()/postBody() in zk_render.js. */

/* Masthead. Blends down from the header's navy so the two read as one
   plate; the faint grid is drawn in CSS, so a post with a real cover
   photo (inline style from the hook) simply replaces it under the same
   navy scrim and nothing else changes. */
.zk-postmast {
  position: relative;
  color: #fff;
  background-color: var(--dons-navy-deep);
  background-image:
    linear-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgb(255 255 255 / 0.05) 1px, transparent 1px),
    linear-gradient(180deg, var(--dons-navy) 0%, var(--dons-navy-deep) 78%);
  background-size: 34px 34px, 34px 34px, auto;
  padding: 3rem 0 4.5rem;
}
.zk-postmast::after {
  /* the red spine along the bottom of the plate */
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  background: var(--dons-red);
}
.zk-postmast-top a {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.85rem; font-weight: 700;
  color: rgb(255 255 255 / 0.65);
  transition: color 0.15s ease;
}
.zk-postmast-top a:hover { color: #fff; }
.zk-postmast-kicker {
  display: inline-block;
  margin-top: 2.4rem;
  padding: 0.28rem 0.65rem;
  border: 2px solid #ff7a7a;
  border-radius: 2px;
  transform: rotate(-1.4deg);
  font-size: 0.75rem; font-weight: 900;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: #ff7a7a;
}
.zk-postmast-title {
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.85rem, 1.1rem + 3vw, 3.05rem);
  line-height: 1.2;
  margin-top: 1.1rem;
  max-width: 46rem;
  text-wrap: balance;
}
.zk-postmast-deck {
  margin-top: 1.2rem;
  max-width: 38rem;
  font-size: 1.125rem; font-style: italic; line-height: 1.65;
  color: rgb(255 255 255 / 0.78);
}

/* Work-order strip — half on the navy plate, half on the page. */
.zk-post-wrap { padding-bottom: 2.5rem; }
.zk-workorder {
  position: relative;
  margin-top: -1.45rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.55rem 0.9rem;
  padding: 0.8rem 1.15rem;
  background: var(--color-surface);
  border: 1px solid color-mix(in srgb, var(--dons-navy) 25%, transparent);
  border-radius: 0.5rem;
  box-shadow: 0 12px 28px rgb(0 5 55 / 0.14);
  font-size: 0.78rem; font-weight: 800;
  letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--dons-navy);
}
.zk-workorder .zk-byline { font-weight: 800; }
.zk-wo-sep {
  width: 5px; height: 5px;
  background: var(--dons-red);
  transform: rotate(45deg);
}
[data-theme="dark"] .zk-workorder {
  color: #c6cdf5;
  border-color: rgb(255 255 255 / 0.16);
  box-shadow: 0 12px 28px rgb(0 0 0 / 0.45);
}

/* Reading progress — a red rule under the fixed header that fills as you
   read. Scroll-driven animation, zero JS; browsers without support never
   show the element at all. */
.zk-read-progress { display: none; }
@supports (animation-timeline: scroll()) {
  .zk-read-progress {
    display: block;
    position: fixed; top: var(--dons-header-h); left: 0; right: 0;
    height: 3px; z-index: 35;
    background: var(--dons-red);
    transform-origin: 0 50%; transform: scaleX(0);
    animation: zk-read-grow linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes zk-read-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* Article body. site.css .article supplies the base prose rhythm; this
   layer adds the manual's voice. */
.zk-post-body {
  counter-reset: zk-sec;
  margin-top: 2.25rem;
  font-size: 1.0625rem;
  line-height: 1.8;
}
.zk-post-body > p:first-child::first-letter {
  font-family: "Bevan", Georgia, serif;
  float: left;
  font-size: 3.3em; line-height: 0.82;
  padding: 0.06em 0.14em 0 0;
  color: var(--dons-navy);
}
/* Numbered section headings — an index number in red above a Bevan title,
   separated from the previous section by a hairline. */
.zk-post-body h2 {
  counter-increment: zk-sec;
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  font-size: 1.4rem; line-height: 1.32;
  color: var(--dons-navy);
  border-top: 1px solid color-mix(in srgb, var(--dons-navy) 14%, transparent);
  margin: 2.7rem 0 0.9rem;
  padding-top: 1.05rem;
}
.zk-post-body h2::before {
  content: "No. " counter(zk-sec, decimal-leading-zero);
  display: block;
  margin-bottom: 0.4rem;
  font-family: "Lato", sans-serif;
  font-size: 0.72rem; font-weight: 900;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--dons-red);
}
.zk-post-body h3 { color: var(--dons-navy); }
.zk-post-body a { color: var(--dons-red); font-weight: 700; }
.zk-post-body a:hover { color: var(--dons-navy); }
.zk-post-body strong { color: var(--dons-navy); }
.zk-post-body ul { list-style: square; }
.zk-post-body li::marker { color: var(--dons-red); }
/* Blockquotes become shop tips — the one style of aside this content has. */
.zk-post-body blockquote {
  margin: 1.75rem 0;
  padding: 1rem 1.25rem 1.1rem;
  border-left: 4px solid var(--dons-red);
  border-radius: 0 0.5rem 0.5rem 0;
  background: color-mix(in srgb, var(--dons-navy) 5%, transparent);
  font-style: normal;
}
.zk-post-body blockquote::before {
  content: "Shop tip";
  display: block;
  margin-bottom: 0.35rem;
  font-size: 0.72rem; font-weight: 900;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--dons-red);
}
.zk-post-body img {
  border: 1px solid color-mix(in srgb, var(--dons-navy) 15%, transparent);
  box-shadow: 0 10px 24px rgb(0 5 55 / 0.1);
}
.zk-post-body hr {
  border: 0; height: 4px; width: 5rem;
  margin: 2.5rem auto;
  background: var(--dons-red);
}
[data-theme="dark"] .zk-post-body > p:first-child::first-letter,
[data-theme="dark"] .zk-post-body h2,
[data-theme="dark"] .zk-post-body h3,
[data-theme="dark"] .zk-post-body strong { color: #aab6ff; }
[data-theme="dark"] .zk-post-body h2 { border-top-color: rgb(255 255 255 / 0.14); }
[data-theme="dark"] .zk-post-body a { color: #ff8a8a; }
[data-theme="dark"] .zk-post-body a:hover { color: #fff; }
[data-theme="dark"] .zk-post-body blockquote { background: rgb(255 255 255 / 0.06); }

/* "Keep reading" gets the same manual heading voice as the sections. */
.zk-related > h2 {
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  color: var(--dons-navy);
  position: relative;
  padding-top: 1rem;
}
.zk-related > h2::before {
  content: "";
  position: absolute; top: 0; left: 0;
  width: 2.5rem; height: 4px;
  background: var(--dons-red);
}
[data-theme="dark"] .zk-related > h2 { color: #aab6ff; }

/* ── blog index — the manual's table of contents ─────────────────────────
   Markup from tocFeatureHtml()/tocRowHtml()/blogIndexBody() in zk_render.js.
   The newest post is a featured navy plate stamped "Latest"; the rest run
   as a numbered ledger. No cover photos required by design. */

/* Kicker without a back-link above it sits closer to the plate's top. */
.zk-postmast-kicker--solo { margin-top: 0.5rem; }

/* Index masthead — nothing overlaps it, so it needs no overlap allowance. */
.zk-postmast--flush { padding-bottom: 3rem; }

/* Featured plate. Sits BELOW the masthead on the page background — navy on
   navy overlapping the masthead just melted into it, so the plate now gets
   clear ground to stand on. With a cover photo (.zk-feat--media) the plate
   splits: copy on navy, photo filling the other half. */
.zk-feat {
  position: relative;
  display: block;
  margin-top: 2.4rem;
  overflow: hidden;
  border-left: 5px solid var(--dons-red);
  border-radius: 0.5rem;
  background-color: var(--dons-navy-deep);
  background-image:
    linear-gradient(rgb(255 255 255 / 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgb(255 255 255 / 0.05) 1px, transparent 1px);
  background-size: 34px 34px;
  color: #fff;
  box-shadow: 0 16px 36px rgb(0 5 55 / 0.24);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.zk-feat-body { display: block; padding: 1.9rem 2rem 1.7rem; }
.zk-feat--media { display: grid; }
.zk-feat-media { display: block; }
.zk-feat-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
@media (min-width: 768px) {
  /* photo right, copy left; the photo edge meets the plate edge */
  .zk-feat--media { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .zk-feat--media .zk-feat-media { order: 2; min-height: 100%; }
  .zk-feat--media .zk-feat-body { order: 1; }
}
@media (max-width: 767.98px) {
  /* photo on top, like a manual figure above its caption */
  .zk-feat-media { aspect-ratio: 16 / 9; }
}
.zk-feat:hover {
  transform: translateY(-3px);
  box-shadow: 0 22px 44px rgb(0 5 55 / 0.3);
}
.zk-feat-stamp {
  display: inline-block;
  padding: 0.24rem 0.6rem;
  border: 2px solid #ff7a7a;
  border-radius: 2px;
  transform: rotate(1.1deg);
  font-size: 0.7rem; font-weight: 900;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: #ff7a7a;
}
.zk-feat-title {
  display: block;
  margin-top: 0.9rem;
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.35rem, 1rem + 1.6vw, 1.9rem);
  line-height: 1.28;
  text-wrap: balance;
}
.zk-feat-deck {
  display: block;
  margin-top: 0.7rem;
  max-width: 40rem;
  font-size: 1rem; line-height: 1.6;
  color: rgb(255 255 255 / 0.75);
}
.zk-feat-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.55rem 0.9rem;
  margin-top: 1.1rem;
  font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgb(255 255 255 / 0.7);
}
.zk-feat-go {
  display: inline-flex; align-items: center; gap: 0.35rem;
  margin-left: auto;
  color: #ff7a7a;
}
.zk-feat-go svg { transition: transform 0.18s ease; }
.zk-feat:hover .zk-feat-go svg { transform: translateX(4px); }

/* The ledger. */
.zk-toc { padding-bottom: 4rem; }
.zk-toc-list { margin-top: 1.6rem; list-style: none; padding: 0; }
.zk-toc-row + .zk-toc-row {
  border-top: 1px solid color-mix(in srgb, var(--dons-navy) 14%, transparent);
}
.zk-toc-row > a {
  display: grid;
  grid-template-columns: 3.4rem 1fr auto;
  align-items: center;
  gap: 1rem;
  padding: 1.35rem 1rem;
  margin-inline: -1rem;
  border-radius: 0.5rem;
  transition: background-color 0.15s ease;
}
.zk-toc-row > a:hover { background: color-mix(in srgb, var(--dons-navy) 4%, transparent); }
.zk-toc-num {
  font-family: "Bevan", Georgia, serif;
  font-size: 1.45rem; line-height: 1;
  color: var(--dons-red);
}
.zk-toc-title {
  display: block;
  font-family: "Bevan", Georgia, serif;
  font-weight: 400;
  font-size: 1.2rem; line-height: 1.32;
  color: var(--dons-navy);
  transition: color 0.15s ease;
}
.zk-toc-row > a:hover .zk-toc-title { color: var(--dons-red); }
.zk-toc-desc {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.95rem; line-height: 1.55;
  color: color-mix(in srgb, var(--dons-navy-deep) 72%, transparent);
}
.zk-toc-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.8rem;
  margin-top: 0.55rem;
  font-size: 0.7rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: color-mix(in srgb, var(--dons-navy) 55%, transparent);
}
.zk-toc-arrow {
  color: color-mix(in srgb, var(--dons-navy) 35%, transparent);
  transition: color 0.15s ease, transform 0.18s ease;
}
.zk-toc-row > a:hover .zk-toc-arrow {
  color: var(--dons-red);
  transform: translateX(4px);
}
/* Cover thumbnail in a ledger row — a small framed plate. */
.zk-toc-row--thumb > a { grid-template-columns: 3.4rem 6.5rem 1fr auto; }
.zk-toc-thumb {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 0.375rem;
  border: 1px solid color-mix(in srgb, var(--dons-navy) 18%, transparent);
  box-shadow: 0 6px 14px rgb(0 5 55 / 0.12);
}
.zk-toc-thumb img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform 0.25s ease;
}
.zk-toc-row > a:hover .zk-toc-thumb img { transform: scale(1.05); }
[data-theme="dark"] .zk-toc-thumb { border-color: rgb(255 255 255 / 0.15); }

.zk-toc-empty {
  padding: 3rem 0;
  color: color-mix(in srgb, var(--dons-navy-deep) 60%, transparent);
}
@media (max-width: 640px) {
  .zk-toc-row > a { grid-template-columns: 2.6rem 1fr; }
  .zk-toc-row--thumb > a { grid-template-columns: 2.6rem 4.4rem 1fr; }
  .zk-toc-arrow { display: none; }
  .zk-feat-body { padding: 1.5rem 1.35rem 1.4rem; }
}

[data-theme="dark"] .zk-toc-row + .zk-toc-row { border-top-color: rgb(255 255 255 / 0.12); }
[data-theme="dark"] .zk-toc-row > a:hover { background: rgb(255 255 255 / 0.05); }
[data-theme="dark"] .zk-toc-num { color: #ff8a8a; }
[data-theme="dark"] .zk-toc-title { color: #aab6ff; }
[data-theme="dark"] .zk-toc-row > a:hover .zk-toc-title { color: #ff8a8a; }
[data-theme="dark"] .zk-toc-desc { color: rgb(255 255 255 / 0.68); }
[data-theme="dark"] .zk-toc-meta { color: rgb(255 255 255 / 0.5); }
[data-theme="dark"] .zk-toc-arrow { color: rgb(255 255 255 / 0.35); }
[data-theme="dark"] /* Cover thumbnail in a ledger row — a small framed plate. */
.zk-toc-row--thumb > a { grid-template-columns: 3.4rem 6.5rem 1fr auto; }
.zk-toc-thumb {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 0.375rem;
  border: 1px solid color-mix(in srgb, var(--dons-navy) 18%, transparent);
  box-shadow: 0 6px 14px rgb(0 5 55 / 0.12);
}
.zk-toc-thumb img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform 0.25s ease;
}
.zk-toc-row > a:hover .zk-toc-thumb img { transform: scale(1.05); }
[data-theme="dark"] .zk-toc-thumb { border-color: rgb(255 255 255 / 0.15); }

.zk-toc-empty { color: rgb(255 255 255 / 0.6); }
