/* ============================================================
   Public chrome — the ONE shared stylesheet.
   ============================================================
   Header, footer, back to top, cookie consent banner, skip link, hovertip.
   Consumed by BOTH public surfaces from a single source:
     - the marketing SPA imports it via src/index.css;
     - the Hono SSR blog concatenates it ahead of its page styles in the
       /blog-assets/blog.css response.

   Surface variance is a PALETTE PRESET expressed as a class on the chrome root:
     .tkgc-preset-marketing  -> the marketing white / gray-900 bar
     .tkgc-preset-blog       -> the blog emerald-paper / deep-slate bar
   The bar is translucent on both presets so the page background (marketing
   gradient, or the blog per-template washes) reads through the backdrop blur.

   Every -webkit-backdrop-filter precedes its standard backdrop-filter (Lightning
   CSS / the Turbopack transformer keeps only the LATER of the two aliases, so
   the standard property must come last or Chromium computes backdrop-filter:none
   and the bar stops blurring).

   Rationalized z-scale: header 100, back to top 90, skip link 200, consent
   1000. The deploy banner (src/lib/deploy-banner) stays z 120, between the
   header and the skip link.
   ============================================================ */

/* ---- preset palettes (self-contained; do not depend on blog.css tokens) ---- */
.tkgc-preset-marketing {
  --tkgc-bar-bg: rgba(255, 255, 255, 0.8);
  --tkgc-bar-bg-glass: rgba(255, 255, 255, 0.7);
  /* The open mobile drawer is a solid navigation surface (NOT the translucent
     header glass): a see-through drawer let the hero/body text behind it bleed
     through and garble the drawer's own links. Solid fill + blur = a distinct
     panel. */
  --tkgc-menu-bg: #ffffff;
  /* Header hairline = the SPA --border token (border-b border-border). */
  --tkgc-bar-border: #cad5e1;
  /* Footer restores the SPA look: slate-50 -> slate-50 -> emerald-50/20
     gradient, gray-200/50 top border + inner divider. (Footer surface is a
     documented INTENTIONAL per-preset difference: SPA gradient vs blog solid
     bar.) */
  --tkgc-footer-surface: linear-gradient(135deg, #f8fafc 0%, #f8fafc 50%, rgba(236, 253, 245, 0.2) 100%);
  --tkgc-footer-border: rgba(229, 231, 235, 0.5);
  --tkgc-footer-divider: rgba(229, 231, 235, 0.5);
  --tkgc-wordmark-from: #111827;
  --tkgc-wordmark-to: #374151;
  --tkgc-nav-ink: #374151;
  --tkgc-nav-ink-hover: #059669;
  --tkgc-nav-hover-bg: #f3f4f6;
  --tkgc-toggle-from: #f3f4f6;
  --tkgc-toggle-to: #e5e7eb;
  --tkgc-toggle-ink: #374151;
  --tkgc-foot-heading: #111827;
  --tkgc-foot-ink: #4b5563;
  --tkgc-foot-ink-hover: #059669;
  --tkgc-foot-copy: #6b7280;
  --tkgc-underline: #059669;
  --tkgc-consent-surface: #ffffff;
  --tkgc-consent-ink: #0f172a;
  --tkgc-consent-border: rgba(15, 23, 42, 0.12);
  --tkgc-consent-shadow: 0 -8px 30px rgba(2, 6, 23, 0.18);
  --tkgc-consent-decline-border: rgba(15, 23, 42, 0.25);
  --tkgc-tip-bg: #0f172a;
  --tkgc-tip-ink: #ffffff;
  --tkgc-skip-bg: #0f172a;
  --tkgc-skip-ink: #ffffff;
  --tkgc-shadow-emerald: 0 10px 40px -10px rgba(16, 185, 129, 0.3);
}
html.dark .tkgc-preset-marketing {
  --tkgc-bar-bg: rgba(17, 24, 39, 0.8);
  --tkgc-bar-bg-glass: rgba(30, 41, 59, 0.7);
  --tkgc-menu-bg: #111827;
  /* Header hairline = the SPA dark --border token. */
  --tkgc-bar-border: rgba(255, 255, 255, 0.1);
  /* Footer: gray-900 -> slate-900 -> emerald-950/10 gradient, gray-700/50
     top border + inner divider (SPA dark baseline). */
  --tkgc-footer-surface: linear-gradient(135deg, #111827 0%, #0f172a 50%, rgba(2, 44, 34, 0.1) 100%);
  --tkgc-footer-border: rgba(55, 65, 81, 0.5);
  --tkgc-footer-divider: rgba(55, 65, 81, 0.5);
  --tkgc-wordmark-from: #ffffff;
  --tkgc-wordmark-to: #d1d5db;
  --tkgc-nav-ink: #d1d5db;
  --tkgc-nav-ink-hover: #34d399;
  --tkgc-nav-hover-bg: #1f2937;
  --tkgc-toggle-from: #1f2937;
  --tkgc-toggle-to: #374151;
  --tkgc-toggle-ink: #e5e7eb;
  --tkgc-foot-heading: #ffffff;
  --tkgc-foot-ink: #9ca3af;
  --tkgc-foot-ink-hover: #34d399;
  --tkgc-foot-copy: #9ca3af;
  --tkgc-underline: #34d399;
  --tkgc-consent-surface: #0f172a;
  --tkgc-consent-ink: #e5edf5;
  --tkgc-consent-border: rgba(255, 255, 255, 0.14);
  --tkgc-consent-shadow: 0 -8px 30px rgba(0, 0, 0, 0.5);
  --tkgc-consent-decline-border: rgba(255, 255, 255, 0.28);
  --tkgc-tip-bg: #e5edf5;
  --tkgc-tip-ink: #0f172a;
  --tkgc-skip-bg: #ecfdf5;
  --tkgc-skip-ink: #052e23;
  --tkgc-shadow-emerald: 0 10px 40px -10px rgba(16, 185, 129, 0.4);
}
.tkgc-preset-blog {
  --tkgc-bar-bg: rgba(236, 253, 245, 0.82);
  --tkgc-bar-bg-glass: rgba(236, 253, 245, 0.7);
  --tkgc-menu-bg: #ecfdf5;
  --tkgc-bar-border: rgba(5, 46, 35, 0.1);
  /* Blog footer keeps its solid translucent bar (the documented INTENTIONAL
     per-preset difference) and the bar hairline for its borders. */
  --tkgc-footer-surface: var(--tkgc-bar-bg);
  --tkgc-footer-border: var(--tkgc-bar-border);
  --tkgc-footer-divider: var(--tkgc-bar-border);
  --tkgc-wordmark-from: #111827;
  --tkgc-wordmark-to: #374151;
  --tkgc-nav-ink: #374151;
  --tkgc-nav-ink-hover: #059669;
  --tkgc-nav-hover-bg: #f3f4f6;
  --tkgc-toggle-from: #f3f4f6;
  --tkgc-toggle-to: #e5e7eb;
  --tkgc-toggle-ink: #374151;
  --tkgc-foot-heading: #111827;
  --tkgc-foot-ink: #4b5563;
  --tkgc-foot-ink-hover: #059669;
  --tkgc-foot-copy: #6b7280;
  --tkgc-underline: #059669;
  --tkgc-consent-surface: #ffffff;
  --tkgc-consent-ink: #0f172a;
  --tkgc-consent-border: rgba(15, 23, 42, 0.12);
  --tkgc-consent-shadow: 0 -8px 30px rgba(2, 6, 23, 0.18);
  --tkgc-consent-decline-border: rgba(15, 23, 42, 0.25);
  --tkgc-tip-bg: #052e23;
  --tkgc-tip-ink: #ecfdf5;
  --tkgc-skip-bg: #052e23;
  --tkgc-skip-ink: #ecfdf5;
  --tkgc-shadow-emerald: 0 10px 40px -10px rgba(16, 185, 129, 0.3);
}
html.dark .tkgc-preset-blog {
  --tkgc-bar-bg: rgba(11, 20, 38, 0.82);
  --tkgc-bar-bg-glass: rgba(11, 20, 38, 0.7);
  --tkgc-menu-bg: #0b1426;
  --tkgc-bar-border: rgba(255, 255, 255, 0.1);
  --tkgc-footer-surface: var(--tkgc-bar-bg);
  --tkgc-footer-border: var(--tkgc-bar-border);
  --tkgc-footer-divider: var(--tkgc-bar-border);
  --tkgc-wordmark-from: #ffffff;
  --tkgc-wordmark-to: #d1d5db;
  --tkgc-nav-ink: #d1d5db;
  --tkgc-nav-ink-hover: #34d399;
  --tkgc-nav-hover-bg: #1f2937;
  --tkgc-toggle-from: #1f2937;
  --tkgc-toggle-to: #374151;
  --tkgc-toggle-ink: #e5e7eb;
  --tkgc-foot-heading: #ffffff;
  --tkgc-foot-ink: #9ca3af;
  --tkgc-foot-ink-hover: #34d399;
  --tkgc-foot-copy: #9ca3af;
  --tkgc-underline: #34d399;
  --tkgc-consent-surface: #0f172a;
  --tkgc-consent-ink: #e5edf5;
  --tkgc-consent-border: rgba(255, 255, 255, 0.14);
  --tkgc-consent-shadow: 0 -8px 30px rgba(0, 0, 0, 0.5);
  --tkgc-consent-decline-border: rgba(255, 255, 255, 0.28);
  --tkgc-tip-bg: #e5edf5;
  --tkgc-tip-ink: #0f172a;
  --tkgc-skip-bg: #ecfdf5;
  --tkgc-skip-ink: #052e23;
  --tkgc-shadow-emerald: 0 10px 40px -10px rgba(16, 185, 129, 0.4);
}

/* shared emerald gradient constants */
.tkgc-preset-marketing, .tkgc-preset-blog {
  --tkgc-emerald-grad: linear-gradient(90deg, #10b981 0%, #059669 100%);
  --tkgc-emerald-grad-135: linear-gradient(135deg, #10b981 0%, #059669 100%);
}

/* ---- skip link (both surfaces) ---- */
.tkgc-skip {
  position: absolute;
  left: 16px;
  top: -60px;
  background: var(--tkgc-skip-bg);
  color: var(--tkgc-skip-ink);
  padding: 10px 16px;
  border-radius: 10px;
  z-index: 200;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: top 0.2s ease;
}
.tkgc-skip:focus { top: 14px; }

/* ---- shared container (1280px, px-6 / lg:px-8, narrow-phone trim) ---- */
.tkgc-wrap {
  width: 100%;
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: 24px;
}
@media (max-width: 420px) {
  .tkgc-wrap { padding-inline: 14px; }
}
@media (min-width: 1024px) {
  .tkgc-wrap { padding-inline: 32px; }
}

/* ---- deploy banner clearance ----
   The deploy banner (src/lib/deploy-banner, position:fixed, top:0, z 120) cannot
   push flow, so without an offset it overlaps the sticky-top:0 header on both
   surfaces. When it is showing, syncDeployBanner marks <html data-tkg-deploy-banner>
   and publishes its height in --tkg-deploy-banner-h (re-measured on resize so a
   wrap at narrow widths keeps a correct offset). Clearance has TWO halves:
     (1) push ONLY the chrome preset roots down by the banner height so the header
         starts below the banner at scroll 0 (the marketing SPA layout div carries
         the header inside it; the blog <body> carries .blog-shell);
     (2) raise the sticky threshold of .tkgc-nav to the banner height, because a
         `position:sticky; top:0` header re-pins to VIEWPORT top 0 once scrolled
         past the banner and slides back UNDER the fixed z-120 banner. Setting
         top:var(--tkg-deploy-banner-h) keeps it pinned below the banner while
         scrolling; at scroll 0 the flow position (from the root padding) already
         equals that threshold, so nothing shifts. The absolutely-positioned mobile
         drawer (top:80px inside the header) follows automatically.
   Scoped to the presets so non-chrome surfaces (admin, survey) are never shifted. */
html[data-tkg-deploy-banner] .tkgc-preset-marketing,
html[data-tkg-deploy-banner] .tkgc-preset-blog {
  padding-top: var(--tkg-deploy-banner-h, 0px);
}
html[data-tkg-deploy-banner] .tkgc-preset-marketing .tkgc-nav,
html[data-tkg-deploy-banner] .tkgc-preset-blog .tkgc-nav {
  top: var(--tkg-deploy-banner-h, 0px);
}

/* ============================ HEADER ============================ */
.tkgc-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--tkgc-bar-bg);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  border-bottom: 1px solid var(--tkgc-bar-border);
  transition: background-color 0.5s ease, border-color 0.5s ease, box-shadow 0.3s ease;
}
.tkgc-nav.scrolled {
  background: var(--tkgc-bar-bg-glass);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: 0 10px 15px -3px rgba(15, 23, 42, 0.12), 0 4px 6px -2px rgba(15, 23, 42, 0.06);
}
html.dark .tkgc-nav.scrolled {
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
}
.tkgc-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 80px;
}

/* brand */
.tkgc-brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  white-space: nowrap;
  /* Allow the brand anchor to shrink below its content width as a flex item of
     the header row, so at extreme narrow widths (<=340px) the wordmark ellipsis
     floor actually engages (the anchor's default min-width:auto would otherwise
     clamp it to its content and force the header to overflow). The logo stays a
     non-shrink 44px item, so only the wordmark TEXT gives way. Harmless in the
     footer, where the brand sits in a grid cell and the wordmark wraps. */
  min-width: 0;
}
/* Logo aspect lock (both surfaces, header + footer): the logo box never shrinks
   and never distorts at any width. The brand-logo span is a non-shrink flex item
   (flex:0 0 auto) so a tight row/column cannot compress it, and the img is
   exempted from BOTH surfaces' global `img { max-width: 100% }` reset (Tailwind
   preflight on the SPA, blog.css on the blog) via max-width:none, so a constrained
   parent can never narrow the img WIDTH while its fixed height stays pinned (which
   is what crushed the square logo into a squashed rectangle). width:auto keeps the
   intrinsic 1:1 ratio; height:44px is the fixed size on both header and footer.
   Safe in the header now that the drawer owns the 768 to 1023 band, where the full
   row previously over-constrained the logo. */
.tkgc-brand-logo { position: relative; display: inline-flex; flex: 0 0 auto; }
.tkgc-logo { height: 44px; width: auto; max-width: none; flex: 0 0 auto; transition: transform 0.3s ease; }
.tkgc-brand:hover .tkgc-logo { transform: scale(1.05); }
.tkgc-brand-glow {
  position: absolute;
  inset: -8px;
  border-radius: 9999px;
  background: linear-gradient(90deg, rgba(16, 185, 129, 0.2) 0%, rgba(5, 150, 105, 0.2) 100%);
  filter: blur(16px);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.tkgc-brand:hover .tkgc-brand-glow { opacity: 1; }
.tkgc-brand-name {
  /* Wordmark: responsive 16 / 18 / 20px with the SPA tracking (tracking-tight). */
  font-weight: 600;
  font-size: 1rem;
  /* Explicit line-height so the wordmark box height does not inherit each
     surface's differing body line-height (SPA 1.5 preflight vs blog ~1.7): the
     ellipsis floor below makes this span a block box whose used height equals its
     line-height, and overflow:hidden clips anything outside that box, so an
     inherited line-height would make the box (and its centered y in the brand
     anchor) differ across surfaces. The value must ALSO clear DM Sans' ink:
     its normal line box is ~1.302em, so line-height below ~1.31 clips the g/p
     descenders of "Knowledge"/"Group" under overflow:hidden. 1.5 (matching the
     rest of the chrome text) clears the descenders and is identical on both
     surfaces, keeping the wordmark pixel-identical everywhere. */
  line-height: 1.5;
  letter-spacing: -0.025em;
  background: linear-gradient(90deg, var(--tkgc-wordmark-from) 0%, var(--tkgc-wordmark-to) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  transition: all 0.3s ease;
  /* Ellipsis floor (the header context): at extreme narrow widths (<=340px) the
     wordmark TEXT truncates with an ellipsis instead of forcing the row wider or
     letting the logo distort. min-width:0 lets this flex item shrink below its
     content width; overflow+ellipsis need the nowrap inherited from .tkgc-brand.
     The footer overrides white-space to normal so its wordmark WRAPs (its floor)
     rather than truncating. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (min-width: 640px) { .tkgc-brand-name { font-size: 1.125rem; } }
@media (min-width: 1024px) { .tkgc-brand-name { font-size: 1.25rem; } }

/* right cluster + nav links */
.tkgc-nav-cluster { display: flex; align-items: center; gap: 24px; }
.tkgc-nav-links { display: flex; align-items: center; gap: 8px; }
.tkgc-nav-link {
  text-decoration: none;
  color: var(--tkgc-nav-ink);
  font-weight: 500;
  font-size: 0.875rem;
  /* Explicit line-height: chrome text must NOT inherit each host's body
     line-height (marketing SPA 1.5 vs blog ~1.7), or the pill box heights (and
     their y in the 80px row) would differ across surfaces and break the
     cross-surface pixel parity. 1.5 matches the marketing SPA reference. */
  line-height: 1.5;
  padding: 8px 16px;
  /* Full pill: the active-page highlight, the inactive-link hover highlight, and
     (in the drawer) the active item all read as fully rounded capsules. 9999px
     clamps to half the box height so the ends are perfect semicircles at any
     link size. Radius is a paint property, so this cannot shift the row layout;
     the padding/gap/font-size above stay the zero-shift row geometry. */
  border-radius: 9999px;
  transition: color 0.3s, background-color 0.3s;
  position: relative;
}
.tkgc-nav-link:hover {
  color: var(--tkgc-nav-ink-hover);
  background: var(--tkgc-nav-hover-bg);
}
.tkgc-nav-link.active,
.tkgc-nav-link.active:hover {
  color: #fff;
  background: var(--tkgc-emerald-grad);
  box-shadow: var(--tkgc-shadow-emerald);
}
.tkgc-nav-link.cta {
  margin-left: 8px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 24px;
  /* Full pill for the Contact CTA (desktop) and the drawer Contact button, which
     inherits this rule. Matches the pill on the plain nav links; paint only, so
     the 10px 24px padding stays the zero-shift geometry. */
  border-radius: 9999px;
  background: var(--tkgc-emerald-grad);
  color: #fff;
  font-weight: 500;
  box-shadow: var(--tkgc-shadow-emerald);
  transition: transform 0.3s, box-shadow 0.3s, color 0.3s;
}
.tkgc-nav-link.cta:hover {
  color: #fff;
  transform: scale(1.05);
  box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.12), 0 8px 10px -6px rgba(15, 23, 42, 0.06);
}
html.dark .tkgc-nav-link.cta:hover {
  /* SPA dark shadow-xl (xl geometry with the xl alphas 0.6 / 0.4). */
  box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.6), 0 8px 10px -6px rgb(0 0 0 / 0.4);
}
.tkgc-nav-link.cta .tkgc-spark { width: 16px; height: 16px; opacity: 0.7; transition: opacity 0.3s; }
.tkgc-nav-link.cta:hover .tkgc-spark { opacity: 1; }

/* theme toggle */
.tkgc-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  border-radius: 12px;
  border: 0;
  cursor: pointer;
  background: linear-gradient(135deg, var(--tkgc-toggle-from) 0%, var(--tkgc-toggle-to) 100%);
  color: var(--tkgc-toggle-ink);
  overflow: hidden;
  transition: transform 0.3s, box-shadow 0.3s, background-color 0.5s, color 0.5s;
}
.tkgc-toggle:hover {
  transform: scale(1.05);
  box-shadow: 0 10px 15px -3px rgba(15, 23, 42, 0.12), 0 4px 6px -2px rgba(15, 23, 42, 0.06);
}
html.dark .tkgc-toggle:hover {
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3);
}
.tkgc-toggle-glow {
  position: absolute;
  inset: 0;
  border-radius: 12px;
  background: linear-gradient(90deg, rgba(16, 185, 129, 0.2) 0%, rgba(5, 150, 105, 0.2) 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.tkgc-toggle:hover .tkgc-toggle-glow { opacity: 1; }
.tkgc-toggle .tkgc-ico { position: relative; z-index: 10; width: 20px; height: 20px; display: block; }

/* hamburger (wrapped in a hovertip-wrap for the 350ms tooltip; the WRAP is
   hidden on desktop so it reserves no flex gap in the cluster, and appears with
   the button below the md breakpoint). */
.tkgc-hovertip-wrap:has(.tkgc-hamburger) { display: none; }
.tkgc-hamburger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--tkgc-nav-ink);
  border: 0;
  border-radius: 8px;
  width: 44px;
  height: 44px;
  cursor: pointer;
  transition: background-color 0.3s, color 0.3s;
}
.tkgc-hamburger:hover { background: var(--tkgc-nav-hover-bg); }
.tkgc-hamburger svg { width: 24px; height: 24px; }
/* Icon swap: on the SPA, Tailwind's preflight sets `svg{display:block}`
   (specificity 0,0,1) while its own `[hidden]` reset uses `:where()`
   (specificity 0,0,0), so a hidden inline SVG icon would still render. This
   attribute-specificity rule (0,1,1) guarantees a [hidden] chrome icon actually
   hides on both surfaces so the hamburger swaps to the X when the drawer opens. */
.tkgc-nav svg[hidden],
.tkgc-toggle [hidden] { display: none !important; }

/* mobile drawer (always in the DOM; toggled by .open) */
.tkgc-mobile-menu { display: none; }
.tkgc-mobile-menu.open {
  display: block;
  position: absolute;
  top: 80px;
  left: 0;
  right: 0;
  z-index: 100;
  /* Solid distinct surface (not the translucent header glass) so hero/body text
     behind the drawer does not bleed through and overlap the drawer links. */
  background: var(--tkgc-menu-bg);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--tkgc-bar-border);
  box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.25);
  animation: tkgcSlideInTop 0.3s cubic-bezier(0.2, 0.7, 0.3, 1);
}
html.dark .tkgc-mobile-menu.open { box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.8); }
@keyframes tkgcSlideInTop {
  from { opacity: 0; transform: translateY(-8px); }
  to { opacity: 1; transform: none; }
}
.tkgc-mobile-menu nav { display: flex; flex-direction: column; gap: 8px; padding: 24px 0; }
.tkgc-mobile-menu .tkgc-nav-link { display: block; padding: 12px 16px; }
.tkgc-mobile-menu .tkgc-nav-link.cta { margin-top: 8px; margin-left: 0; text-align: center; justify-content: center; }

/* Drawer breakpoint (both surfaces): the pill nav hides and the hamburger +
   drawer take over below 1024px. Above 1024px the full pill row returns and
   fits. The tablet band (768 to 1023px) cannot fit the full row with an
   unshrinkable 44px logo, so it belongs to the drawer, which also lets the logo
   aspect lock hold at every width. */
@media (max-width: 1023px) {
  .tkgc-nav-links { display: none; }
  .tkgc-hovertip-wrap:has(.tkgc-hamburger) { display: inline-flex; }
}
@media (min-width: 1024px) {
  .tkgc-mobile-menu.open { display: none; }
}

/* ============================ FOOTER ============================ */
.tkgc-footer {
  position: relative;
  margin-top: auto;
  padding-top: 64px;
  background: var(--tkgc-footer-surface);
  border-top: 1px solid var(--tkgc-footer-border);
  transition: background-color 0.5s ease, border-color 0.5s ease;
}
.tkgc-footer-decor {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background: radial-gradient(circle at center, rgba(16, 185, 129, 0.1) 0%, transparent 70%);
}
.tkgc-footer .tkgc-wrap { position: relative; }
.tkgc-footer-grid {
  display: grid;
  /* Brand column is content-sized (auto) so the wordmark renders on ONE line at
     every desktop width; the three link columns share the remainder equally.
     The auto track resolves to the BRAND ANCHOR width (~284px: 44px logo + 12px
     gap + the 20px/700 wordmark) because the tagline paragraph below is capped to
     that same width (.tkgc-footer-brand p max-width) and wraps under the brand
     instead of stretching the track to its ~337px single-line width.
     Arithmetic (measured): at 1440 the ~1216px inner width leaves ~262px per link
     column; at 1024 the ~943px inner width leaves ~171px per link column, against
     ~150px of link content, so nothing is starved. Below 1024 the grid stacks to
     one column (media query at the end of the footer block). */
  grid-template-columns: auto 1fr 1fr 1fr;
  gap: 48px;
  padding-top: 64px;
  /* SPA baseline: 48px (mb-12) below the grid, above the divider. */
  padding-bottom: 48px;
}
/* Footer brand: the logo aspect lock + non-shrink span now live in the BASE
   .tkgc-logo / .tkgc-brand-logo rules (shared by header and footer, both at 44px),
   so the footer no longer duplicates them. The footer keeps only its two genuine
   differences: the wordmark WRAPs under the logo (white-space:normal, and the
   base ellipsis floor reset to clip so a wrapped multi-line wordmark is never
   truncated) instead of ellipsis-truncating like the header, and the wordmark is
   larger/bolder than the header. */
.tkgc-footer-brand .tkgc-brand { margin-bottom: 16px; white-space: normal; }
.tkgc-footer-brand .tkgc-brand-name { font-weight: 700; font-size: 1.25rem; line-height: 1.2; overflow: visible; text-overflow: clip; }
/* Cap the tagline to the brand anchor width (~284px) so the auto grid track
   above is sized by the brand anchor, NOT by the tagline's ~337px single-line
   width. Without this the auto column stretched to the tagline and starved the
   three link columns; capped, the tagline wraps under the brand as before and
   the link columns keep their full share. */
.tkgc-footer-brand p { color: var(--tkgc-foot-ink); margin: 0; max-width: 284px; font-size: 0.875rem; line-height: 1.625; }
.tkgc-foot-col h4 {
  font-weight: 700;
  font-size: 0.875rem;
  /* Explicit line-height so the footer text boxes are surface-independent (see
     .tkgc-nav-link); 1.5 matches the marketing SPA reference. */
  line-height: 1.5;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--tkgc-foot-heading);
  margin: 0 0 16px;
}
.tkgc-foot-col a {
  display: flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: var(--tkgc-foot-ink);
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 6px 0;
  transition: color 0.3s;
}
.tkgc-foot-col a:hover { color: var(--tkgc-foot-ink-hover); }
.tkgc-foot-col a .tkgc-underline {
  display: inline-block;
  width: 0;
  height: 2px;
  background: var(--tkgc-underline);
  border-radius: 2px;
  transition: width 0.3s ease;
}
.tkgc-foot-col a:hover .tkgc-underline { width: 16px; }
.tkgc-footer-bottom {
  display: flex;
  justify-content: center;
  /* SPA baseline: 32px (pt-8) above the copyright, 64px (the wrap py-16 bottom)
     below it at the page end. */
  padding: 32px 0 64px;
  border-top: 1px solid var(--tkgc-footer-divider);
  font-size: 0.875rem;
  /* Explicit line-height so the copyright box is surface-independent (see
     .tkgc-nav-link); 1.5 matches the marketing SPA reference. */
  line-height: 1.5;
  color: var(--tkgc-foot-copy);
}
.tkgc-footer-bottom span { text-align: center; }
/* Below 1024px the footer stacks to one column (matches the header drawer
   breakpoint): the four column content-sized-brand layout cannot fit the tablet
   band, and stacking keeps the brand on one line at every phone/tablet width. */
@media (max-width: 1023px) {
  .tkgc-footer-grid { grid-template-columns: 1fr; gap: 48px; }
}

/* ============================ BACK TO TOP ============================ */
.tkgc-back-to-top {
  /* SPA baseline look: 90deg (to right) emerald gradient, neutral shadow-lg at
     rest, emerald glow ONLY on hover, hover scale(1.1) with NO translateY lift.
     Geometry (32px offsets, 44px, white icon both themes) and the blog behavior
     (bfcache safety, tabindex) are kept from the reconciliation. */
  position: fixed;
  bottom: 32px;
  right: 32px;
  z-index: 90;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
  color: #fff;
  background: var(--tkgc-emerald-grad);
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}
.tkgc-back-to-top.visible { opacity: 1; transform: none; pointer-events: auto; }
.tkgc-back-to-top:hover {
  transform: scale(1.1);
  box-shadow: var(--tkgc-shadow-emerald);
}
.tkgc-back-to-top svg { width: 20px; height: 20px; }

/* ============================ HOVER TIP ============================ */
.tkgc-hovertip-wrap { position: relative; display: inline-flex; }
.tkgc-hovertip-bubble {
  /* The header tips (theme toggle, hamburger) live in the 80px sticky bar at the
     very top of the page, so the bubble is anchored BELOW its button (anchoring
     it above pushed it to a negative y, off the top of the viewport, so it never
     showed). The back-to-top tip is separately anchored to the bottom corner. */
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--tkgc-tip-bg);
  color: var(--tkgc-tip-ink);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  padding: 7px 12px;
  border-radius: 9px;
  box-shadow: 0 8px 24px -12px rgba(2, 6, 23, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  z-index: 120;
}
/* Edge-aware anchoring for the RIGHT-cluster header tips (theme toggle,
   hamburger). A centered bubble (left:50% / translateX(-50%)) on a button near
   the right viewport edge extends ~half the bubble width past the edge, which
   was the ~10px horizontal overflow at 390px. Right-aligning the bubble to its
   button's right edge makes it grow LEFTWARD, so it can never cross the right
   edge at any width. */
.tkgc-hovertip-wrap:has([data-tkgc-theme-toggle]) .tkgc-hovertip-bubble,
.tkgc-hovertip-wrap:has([data-tkgc-hamburger]) .tkgc-hovertip-bubble {
  left: auto;
  right: 0;
  transform: none;
}
/* the back-to-top tip sits ABOVE its fixed button (fixed origin), so anchor it
   to the viewport corner instead of below the wrap. */
.tkgc-hovertip-wrap:has(.tkgc-back-to-top) .tkgc-hovertip-bubble {
  position: fixed;
  bottom: 84px;
  top: auto;
  right: 24px;
  left: auto;
  transform: none;
}
.tkgc-hovertip-bubble.show { opacity: 1; }
/* Gate the tooltips on hover CAPABILITY, not viewport width. Tooltips are a
   pointer affordance, so touch devices (no hover) get none; but a narrow
   hover-capable window (exactly where the hamburger appears, below 1024px) KEEPS
   its tooltips, so the hamburger tip stays reachable and the back-to-top tip is
   not lost on narrow desktop windows. The edge-aware anchoring above (not a
   width hide) is what removes the 390px overflow, so the bubbles stay in flow. */
@media (hover: none) {
  .tkgc-hovertip-bubble { display: none; }
}

/* ============================ CONSENT BANNER ============================ */
#tkg-consent-banner.tkgc-consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1000;
  background: var(--tkgc-consent-surface);
  color: var(--tkgc-consent-ink);
  border-top: 1px solid var(--tkgc-consent-border);
  box-shadow: var(--tkgc-consent-shadow);
  padding: 1rem;
  animation: tkgcConsentUp 0.35s ease both;
}
@keyframes tkgcConsentUp {
  from { transform: translateY(100%); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
#tkg-consent-banner .tkgc-consent-inner {
  max-width: 72rem;
  margin: 0 auto;
  display: flex;
  gap: 1rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}
#tkg-consent-banner .tkgc-consent-text { margin: 0; font-size: 0.9rem; line-height: 1.5; flex: 1 1 22rem; min-width: 0; }
#tkg-consent-banner .tkgc-consent-link { color: #10b981; font-weight: 600; text-decoration: underline; }
html.dark #tkg-consent-banner .tkgc-consent-link { color: #34d399; }
#tkg-consent-banner .tkgc-consent-actions { display: flex; gap: 0.6rem; flex: 0 0 auto; }
#tkg-consent-banner .tkgc-consent-btn {
  height: 2.5rem;
  padding: 0 1.1rem;
  border-radius: 0.6rem;
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
  transition: filter 0.2s, background 0.2s;
}
#tkg-consent-banner .tkgc-consent-decline {
  background: transparent;
  color: inherit;
  border-color: var(--tkgc-consent-decline-border);
}
#tkg-consent-banner .tkgc-consent-decline:hover { background: rgba(127, 127, 127, 0.12); }
#tkg-consent-banner .tkgc-consent-accept { background: var(--tkgc-emerald-grad-135); color: #fff; }
#tkg-consent-banner .tkgc-consent-accept:hover { filter: brightness(1.06); }
@media (max-width: 640px) {
  #tkg-consent-banner .tkgc-consent-actions { width: 100%; }
  #tkg-consent-banner .tkgc-consent-btn { flex: 1 1 0; }
}

/* ============================ REDUCED MOTION ============================ */
@media (prefers-reduced-motion: reduce) {
  .tkgc-nav,
  .tkgc-nav.scrolled,
  .tkgc-brand .tkgc-logo,
  .tkgc-brand-glow,
  .tkgc-nav-link,
  .tkgc-nav-link.cta,
  .tkgc-toggle,
  .tkgc-toggle-glow,
  .tkgc-hamburger,
  .tkgc-mobile-menu.open,
  .tkgc-foot-col a,
  .tkgc-foot-col a .tkgc-underline,
  .tkgc-back-to-top,
  .tkgc-hovertip-bubble,
  #tkg-consent-banner.tkgc-consent {
    transition-duration: 0.001ms !important;
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ============================================================
   Public blog PAGE stylesheet (article body, listing cards, per-template
   textures, blog design tokens). Served by the in-app Hono SSR at
   /blog-assets/blog.css, where the shared public-chrome stylesheet
   (src/lib/public-chrome/chrome.css: header, footer, back to top, cookie
   consent, skip link, hovertip) is concatenated AHEAD of it in the SAME
   response. The chrome is NO LONGER defined in this file: it moved to the ONE
   shared slice consumed by both the marketing SPA and this blog SSR.

   Font sourcing: DM Sans + Playfair Display are loaded by a <link> in the blog
   document head (server/src/services/blog/chrome.ts, consuming
   CHROME_FONTS_STYLESHEET_URL), NOT by an @import here. An @import in this file
   lands after the chrome rules in the concatenated response, where CSS makes it
   invalid so browsers drop it and the blog renders in the system fallback. The
   two CSS variables the tokens consume are still defined below.

   This stylesheet is emitted ONLY into the SSR blog document; it is NOT imported
   by the SPA admin bundle, so the blog's dark tokens never leak into /admin.
   ============================================================ */
:root {
  --font-dm-sans: 'DM Sans';
  --font-playfair: 'Playfair Display';
}

/* ============================================================
   THRIVE KNOWLEDGE GROUP — public blog page design tokens.
   Built on the SITE theming mechanism: a `.dark` class on <html> (NOT
   [data-theme]), localStorage key "darkMode", default dark.

   :root  = LIGHT theme (greenish-to-white paper + emerald accents)
   .dark  = DARK theme  (gray-950 / slate-900 / emerald-950 gradient)

   Fonts (DM Sans + Playfair Display) load via the blog document-head <link>
   (see the file header) and are exposed to the tokens below as --font-dm-sans /
   --font-playfair. Emitted only into the SSR blog document, never into the SPA
   admin bundle (see the file header).
   ============================================================ */

:root {
  /* ---- LIGHT THEME ---- */
  --paper: #ecfdf5; /* emerald-50 base */
  --paper-2: #f0fdf4; /* secondary green wash */
  --surface: #ffffff; /* lifted card surface */
  --surface-2: #ffffff; /* highest surface */
  --ink: #052e23; /* deep emerald-ink body text */
  --ink-soft: #3f5b51; /* muted ink, meta/caption */
  --ink-faint: #5d756c; /* faintest legible ink */

  /* brand emerald */
  --emerald: #10b981; /* emerald-500 primary */
  --emerald-deep: #059669; /* emerald-600 (AA text on white) */
  --emerald-soft: #047857; /* emerald-700, body-grade AA */
  /* warm amber (matches the site "1M+" stat gradient) */
  --amber: #f59e0b; /* amber-500 */
  --amber-deep: #d97706; /* amber-600 */
  --amber-text: #b45309; /* amber-700, AA text on white */
  --grape: #7c5cc4; /* sparing cosmic violet */

  --line: #c7ead9; /* hairline border on green paper */
  --line-strong: #a7d7c2;
  --chip-bg: #ffffff;
  --chip-ink: #047857;

  --ring: #059669; /* focus ring */
  --shadow-1: 0 1px 0 rgba(5, 46, 35, 0.04), 0 8px 24px -12px rgba(5, 46, 35, 0.22);
  --shadow-2: 0 2px 0 rgba(5, 46, 35, 0.05), 0 22px 50px -24px rgba(5, 46, 35, 0.32);

  --grain-op: 0.045;

  --maxw: 1180px;
  --measure: 68ch;
  --radius: 22px;
  --radius-sm: 14px;
  --radius-pill: 999px;

  /* font stacks (next/font supplies the variable fonts) */
  --font-body: var(--font-dm-sans), "Segoe UI", system-ui, sans-serif;
  --font-display: var(--font-playfair), Georgia, "Times New Roman", serif;

  color-scheme: light;
}

html.dark {
  /* ---- DARK THEME ---- */
  --paper: #030712; /* gray-950 base */
  --paper-2: #0b1220; /* slightly lifted */
  --surface: #0f172a; /* slate-900 card surface */
  --surface-2: #16223c; /* highest surface */
  --ink: #ecfdf5; /* soft warm white (high contrast) */
  --ink-soft: #b6cabf; /* muted (>=8:1) */
  --ink-faint: #8aa79b; /* faint but >=4.5:1 */

  --emerald: #34d399; /* emerald-400 (legible on dark) */
  --emerald-deep: #34d399; /* keep bright on dark */
  --emerald-soft: #6ee7b7; /* emerald-300 for links */
  --amber: #fbbf24; /* amber-400 glow */
  --amber-deep: #fcd34d; /* amber-300 */
  --amber-text: #fbbf24; /* amber reads fine on dark */
  --grape: #b68bff; /* cosmic violet glow */

  --line: #1e293b; /* hairline border on slate */
  --line-strong: #2c3e54;
  --chip-bg: #16223c;
  --chip-ink: #6ee7b7;

  --ring: #34d399;
  --shadow-1: 0 1px 0 rgba(0, 0, 0, 0.2), 0 10px 30px -14px rgba(0, 0, 0, 0.66);
  --shadow-2: 0 2px 0 rgba(0, 0, 0, 0.24), 0 28px 60px -24px rgba(0, 0, 0, 0.8);

  --grain-op: 0.06;

  color-scheme: dark;
}

/* ----------------------------- reset ----------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
body {
  margin: 0;
  /* `position: relative` so the IN-FLOW background layers below stretch to the
     body's full scroll height (inset:0 on an absolute child). */
  position: relative;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  transition: background-color 0.5s ease, color 0.5s ease;
}

/* ---- page background gradient (LIGHT: emerald-50 -> white) ----
   IN-FLOW (position: absolute, NOT fixed): the gradient + grid below stretch to
   the body's full scroll height and SCROLL WITH the content, so the shared
   sticky chrome bar's (.tkgc-nav) backdrop-filter has moving content to blur
   (matching the public SPA, which paints its gradient on an in-flow ancestor).
   A fixed layer would be a static wash the bar could never visibly blur. The
   decorative `.sunburst` stays fixed (z-index:-1) and still sits behind
   content. */
body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background: linear-gradient(135deg, #ecfdf5 0%, #f3fdf8 42%, #ffffff 100%);
  transition: opacity 0.5s ease, background 0.5s ease;
  pointer-events: none;
}
/* ---- DARK: gray-950 -> slate-900 -> faint emerald-950 corner ---- */
html.dark body::before {
  background:
    radial-gradient(120% 120% at 100% 100%, rgba(2, 44, 34, 0.3) 0%, transparent 55%),
    linear-gradient(135deg, #030712 0%, #0f172a 58%, #0a1a22 100%);
}

/* fine grid texture (also IN-FLOW so it scrolls under the bar) */
body::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--ink) 100%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--ink) 100%, transparent) 1px, transparent 1px);
  background-size: 60px 60px;
  opacity: var(--grain-op);
  transition: opacity 0.5s ease;
}

::selection {
  background: var(--emerald);
  color: #042f24;
}
html.dark ::selection {
  background: var(--emerald);
  color: #03130d;
}

a {
  color: var(--emerald-soft);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 0.08em;
}

img {
  display: block;
  max-width: 100%;
}

:focus-visible {
  outline: 3px solid var(--ring);
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---- shared emerald text-gradient for big accent words (light) ---- */
.accent-grad {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
/* dark mode: solid emerald-400 for legibility */
html.dark .accent-grad {
  background: none;
  -webkit-text-fill-color: #34d399;
  color: #34d399;
}

/* ---- shared warm-amber text-gradient for stat-like meta (both themes) ---- */
.amber-grad {
  background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
html.dark .amber-grad {
  background: linear-gradient(135deg, #fbbf24 0%, #fcd34d 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 56px);
}

/* ---- blog shell: min-height flex column so the footer pins to the viewport
   bottom on short pages (mirrors the SPA's min-h-screen flex flex-col + main
   flex-1 + footer mt-auto). Scoped to the /blog chrome ONLY; the bare cms `/`
   health splash uses its own layout and is unaffected. ---- */
.blog-shell {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.blog-shell > main#main {
  flex: 1 1 auto;
}

/* EMBED MODE (cycle 47, E-15): the admin inline device preview frames the post
   document with no blog chrome (header/footer/back-to-top suppressed). Keep the
   post content readable inside the frame with a little breathing room top/bottom. */
body.blog-embed {
  min-height: 100vh;
  min-height: 100dvh;
}
body.blog-embed > main#main {
  padding-top: 16px;
  padding-bottom: 48px;
}

/* visually-hidden helper for a11y labels */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* ============================ POST HEADER ============================ */
main {
  display: block;
}

.post-head {
  position: relative;
  padding-top: clamp(40px, 7vw, 86px);
  padding-bottom: 8px;
}

/* Decorative sun, anchored to the BROWSER VIEWPORT top-right (full browser
   width), not the centered 1180px content column. Fixed so it tracks the
   viewport; behind all content; non-interactive; aria-hidden in markup. The
   spin clamps to a single frame under prefers-reduced-motion (global rule). */
.sunburst {
  position: fixed;
  top: -150px;
  right: -150px;
  width: 520px;
  height: 520px;
  max-width: 60vw;
  max-height: 60vw;
  z-index: -1;
  pointer-events: none;
  opacity: 0.85;
}
.sunburst svg {
  width: 100%;
  height: 100%;
  animation: spin 120s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* The eyebrow is its OWN block row (full width) so it never shares a line with
   the category chip below it; the chip then gets its own top margin. This keeps
   the two clearly separated on every list-head and the post head. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--emerald-soft);
  margin: 0 0 18px;
}
html.dark .eyebrow {
  color: var(--emerald);
}
.eyebrow .dash {
  flex: 0 0 38px;
  width: 38px;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
}

.chip-cat {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  background: linear-gradient(135deg, var(--emerald) 0%, var(--emerald-deep) 100%);
  color: #fff;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 7px 16px;
  border-radius: var(--radius-pill);
  box-shadow: 0 6px 18px -8px color-mix(in srgb, var(--emerald) 80%, transparent);
  text-decoration: none;
}
html.dark .chip-cat {
  color: #03130d;
}
.chip-cat .orbit {
  width: 13px;
  height: 13px;
}

h1.title {
  font-family: var(--font-display);
  font-weight: 800;
  /* #4: reduced ceiling (was up to 5rem) so a long H1 is not giant. It still
     scales fluidly and WRAPS (never truncates) since this is the page H1. */
  font-size: clamp(2.1rem, 4.8vw, 3.5rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 22px 0 0;
  /* No width cap: the article title spans the full content/card-row width (the
     shared `.wrap`), so a long title wraps onto fewer, wider lines instead of an
     early 16ch break. `text-wrap: balance` still evens the line lengths. */
  color: var(--ink);
  text-wrap: balance;
}
h1.title .glow {
  font-family: var(--font-display);
  font-weight: 800;
  position: relative;
  padding-bottom: 0.02em;
}
html.dark h1.title .glow {
  text-shadow: 0 0 38px color-mix(in srgb, #34d399 45%, transparent);
}

.dek {
  font-size: clamp(1.12rem, 2.2vw, 1.42rem);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 24px 0 0;
  max-width: 46ch;
  font-weight: 400;
}
/* The ARTICLE subtitle spans the full content/card-row width, matching the
   uncapped article title above it. Scoped to `.post-head` so the index +
   category/tag list heads keep the readable 46ch base `.dek` measure. */
.post-head .dek {
  max-width: none;
}

.byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  margin-top: 34px;
  padding-bottom: 30px;
  font-family: var(--font-body);
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--ink-soft);
}
.byline .who {
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: 11px;
  /* The byline name is now a link to the author archive; keep it reading as the
     name (inherit the byline ink, no underline) with a subtle emerald hover. */
  text-decoration: none;
  transition: color 0.2s ease;
}
.byline a.who:hover {
  color: var(--emerald-deep);
}
html.dark .byline a.who:hover {
  color: var(--emerald);
}
.byline .who .avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--amber);
  background: var(--paper-2);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--emerald-deep);
}
html.dark .byline .who .avatar {
  color: var(--emerald);
}
.byline .sep {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--emerald);
}
.byline .read {
  font-weight: 700;
}
.byline .updated {
  font-style: italic;
  color: var(--ink-faint);
}
/* Share control (#11): a quiet inline byline button (icon + label) that copies
   the post link / opens the native share sheet. Reads in light + dark; the label
   swaps to "Link copied" briefly via the island script. */
.byline .blog-share {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  font-family: var(--font-body);
  font-size: 0.86rem;
  font-weight: 700;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.byline .blog-share svg {
  width: 15px;
  height: 15px;
}
.byline .blog-share:hover {
  color: var(--emerald-deep);
  border-color: var(--emerald);
  background: color-mix(in srgb, var(--emerald) 8%, transparent);
}
html.dark .byline .blog-share:hover {
  color: var(--emerald);
}

/* ============================ HERO ============================ */
.hero {
  margin: 14px 0 4px;
}
.hero figure {
  margin: 0;
}
.hero .frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  border: 2px solid var(--ink);
  box-shadow: var(--shadow-2);
  background: linear-gradient(135deg, var(--amber) 0%, var(--emerald) 60%, var(--emerald-deep) 100%);
  aspect-ratio: 16 / 9;
}
html.dark .hero .frame {
  border-color: var(--line-strong);
}
.hero .frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero .frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 70%, color-mix(in srgb, var(--ink) 30%, transparent) 100%);
  mix-blend-mode: multiply;
}
.hero .badge {
  position: absolute;
  left: 18px;
  bottom: 18px;
  z-index: 2;
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  padding: 8px 14px;
  border-radius: var(--radius-pill);
  border: 1.5px solid var(--line-strong);
  box-shadow: var(--shadow-1);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.hero .badge .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--emerald);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--emerald) 35%, transparent);
}
figcaption {
  margin-top: 12px;
  font-style: italic;
  font-size: 0.96rem;
  color: var(--ink-faint);
  text-align: center;
  max-width: 60ch;
  margin-inline: auto;
}

/* ============================ ARTICLE BODY ============================ */
.article {
  max-width: var(--measure);
  margin: clamp(40px, 6vw, 70px) auto 0;
  position: relative;
}
.article p,
.article ul,
.article ol {
  margin: 0 0 1.5em;
}
.article ul,
.article ol {
  padding-left: 1.4em;
}
.article li {
  margin-bottom: 0.5em;
}

.article h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.4vw, 2.3rem);
  line-height: 1.14;
  letter-spacing: -0.01em;
  margin: 2.2em 0 0.55em;
  color: var(--ink);
  position: relative;
  padding-top: 0.3em;
}
.article h2::before {
  content: "";
  display: block;
  width: 54px;
  height: 6px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--emerald), var(--amber));
  margin-bottom: 18px;
}
.article h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.3rem, 2.6vw, 1.7rem);
  line-height: 1.2;
  margin: 1.6em 0 0.5em;
  color: var(--ink);
}
.article h4 {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1.1rem;
  margin: 1.4em 0 0.5em;
  color: var(--ink);
}

.article strong {
  color: var(--ink);
  font-weight: 700;
}
.article em {
  color: var(--ink-soft);
}
.article a {
  color: var(--emerald-deep);
  font-weight: 600;
}
html.dark .article a {
  color: var(--emerald-soft);
}
.article blockquote:not(.pullquote) {
  margin: 1.8em 0;
  padding: 4px 0 4px 24px;
  border-left: 4px solid var(--emerald);
  color: var(--ink-soft);
  font-style: italic;
}

/* nested richText inside blocks renders unwrapped */
.rt-nested > :first-child {
  margin-top: 0;
}
.rt-nested > :last-child {
  margin-bottom: 0;
}

/* ============================ BLOCK: pull quote ============================ */
.pullquote {
  margin: 2.4em 0;
  padding: 0;
  border: 0;
  position: relative;
  text-align: center;
}
.pullquote p {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.7rem, 3.8vw, 2.5rem);
  line-height: 1.22;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}
.pullquote .mark {
  font-size: 3.6rem;
  line-height: 0;
  color: var(--emerald);
  display: block;
  font-family: var(--font-display);
  margin-bottom: 0.1em;
}
.pullquote cite {
  display: block;
  margin-top: 18px;
  font-style: normal;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.92rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ============================ BLOCK: callout ============================ */
.callout {
  margin: 2.4em 0;
  padding: 26px 28px;
  background: var(--surface);
  border-radius: var(--radius-sm);
  border: 2px solid var(--line-strong);
  box-shadow: var(--shadow-1);
  position: relative;
  overflow: hidden;
}
.callout::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 7px;
  background: linear-gradient(180deg, var(--emerald), var(--amber));
}
/* warning variant leans amber; note/info/tip lean emerald */
.callout.callout-warning::before {
  background: linear-gradient(180deg, var(--amber), var(--amber-deep));
}
.callout.callout-tip::before {
  background: linear-gradient(180deg, var(--emerald), var(--amber));
}
.callout .tag {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--emerald-soft);
  margin-bottom: 12px;
}
html.dark .callout .tag {
  color: var(--emerald);
}
.callout.callout-warning .tag {
  color: var(--amber-text);
}
html.dark .callout.callout-warning .tag {
  color: var(--amber);
}
.callout .tag svg {
  width: 20px;
  height: 20px;
}
.callout .callout-body p {
  margin: 0 0 0.8em;
  font-size: 1.04rem;
  color: var(--ink-soft);
}
.callout .callout-body p:last-child {
  margin-bottom: 0;
}
.callout .callout-body strong {
  color: var(--ink);
}

/* ============================ BLOCK: two column ============================ */
.two-col {
  margin: 2.4em 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
}
.two-col .col > :first-child {
  margin-top: 0;
}
.two-col .col > :last-child {
  margin-bottom: 0;
}
@media (max-width: 760px) {
  .two-col {
    grid-template-columns: 1fr;
    gap: 18px;
  }
}

/* ============================ BLOCK: cta ============================ */
.cta-block {
  margin: 2.4em 0;
  text-align: center;
}
.cta-pill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.01em;
  padding: 14px 30px;
  border-radius: var(--radius-pill);
  transition: transform 0.2s, box-shadow 0.25s, border-color 0.2s;
}
.cta-pill.primary {
  color: #fff;
  background: linear-gradient(135deg, var(--emerald) 0%, var(--emerald-deep) 100%);
  box-shadow: 0 12px 28px -12px color-mix(in srgb, var(--emerald) 80%, transparent);
}
html.dark .cta-pill.primary {
  color: #03130d;
}
.cta-pill.secondary {
  color: var(--emerald-deep);
  background: var(--surface);
  border: 2px solid var(--line-strong);
}
html.dark .cta-pill.secondary {
  color: var(--emerald);
}
.cta-pill:hover {
  transform: translateY(-3px);
}
.cta-pill.secondary:hover {
  border-color: var(--emerald);
}

/* ============================ BLOCK: accordion ============================ */
.accordion {
  margin: 2.4em 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.accordion details {
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.accordion summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 22px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--ink);
}
.accordion summary::-webkit-details-marker {
  display: none;
}
.accordion summary .chev {
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  color: var(--emerald-deep);
  transition: transform 0.3s ease;
}
html.dark .accordion summary .chev {
  color: var(--emerald);
}
.accordion details[open] summary .chev {
  transform: rotate(180deg);
}
.accordion .acc-body {
  padding: 0 22px 20px;
  color: var(--ink-soft);
}
.accordion .acc-body > :first-child {
  margin-top: 0;
}

/* ============================ BLOCK: tabs ============================ */
.tabs {
  margin: 2.4em 0;
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.tabs [role="tablist"] {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 10px 10px 0;
  border-bottom: 1.5px solid var(--line);
}
.tabs [role="tab"] {
  appearance: none;
  border: 0;
  background: transparent;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--ink-soft);
  padding: 12px 18px;
  border-radius: 12px 12px 0 0;
  border-bottom: 3px solid transparent;
  transition: color 0.2s, background-color 0.2s, border-color 0.2s;
}
.tabs [role="tab"]:hover {
  color: var(--ink);
  background: color-mix(in srgb, var(--emerald) 10%, transparent);
}
.tabs [role="tab"][aria-selected="true"] {
  color: var(--emerald-deep);
  border-bottom-color: var(--emerald);
}
html.dark .tabs [role="tab"][aria-selected="true"] {
  color: var(--emerald);
}
.tabs [role="tabpanel"] {
  padding: 22px;
  color: var(--ink-soft);
}
.tabs [role="tabpanel"] > :first-child {
  margin-top: 0;
}
.tabs [role="tabpanel"] > :last-child {
  margin-bottom: 0;
}

/* ============================ BLOCK: image with caption ============================ */
.inline-fig {
  margin: 2.4em 0;
}
.inline-fig .frame {
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 2px solid var(--ink);
  box-shadow: var(--shadow-1);
  background: var(--paper-2);
}
html.dark .inline-fig .frame {
  border-color: var(--line-strong);
}
.inline-fig img {
  width: 100%;
  height: auto;
  display: block;
}

/* ============================ TAGS (filed under) ============================ */
.filed {
  max-width: var(--measure);
  margin: clamp(40px, 5vw, 56px) auto 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding-top: 28px;
  border-top: 2px dashed var(--line-strong);
}
.filed .lab {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-right: 4px;
}
.tag-chip {
  text-decoration: none;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--chip-ink);
  background: var(--chip-bg);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-pill);
  padding: 7px 16px;
  transition: transform 0.18s, border-color 0.2s, color 0.2s;
}
.tag-chip:hover {
  transform: translateY(-2px);
  border-color: var(--emerald);
  color: var(--emerald-deep);
}
html.dark .tag-chip:hover {
  color: var(--emerald);
}

/* ============================ RELATED + CARD GRID ============================ */
.related {
  margin-top: clamp(64px, 9vw, 110px);
  /* Breathing room below the "Keep Exploring" cards so they never abut the
     footer's top border (same rhythm as the listing pages' .list-section).
     The footer is pinned on short pages by the shell's `main { flex: 1 }`, not
     by this margin, so the bottom margin spaces the cards without unpinning. */
  margin-bottom: clamp(48px, 6vw, 80px);
}
/* When a post has NO related posts, the <article> is the last element before
   the footer; give it the same bottom breathing room so its "Filed under" chips
   don't abut the footer. Match the article as the last child of ITS parent, not
   only of main#main: the STANDARD template appends the article directly under
   <main>, but the EDITORIAL templates nest it inside a `.post--feature` wrapper,
   so a `main#main > article` selector missed the editorial case and left the tag
   chips flush against the footer. (With related posts present, .related follows
   the article and carries the margin instead, so the article is not :last-child
   and this rule does not double up.) */
article.wrap:last-child {
  margin-bottom: clamp(48px, 6vw, 80px);
}
.sect-head {
  display: flex;
  align-items: baseline;
  gap: 18px;
  margin-bottom: 30px;
}
.sect-head h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.7rem, 4vw, 2.6rem);
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--ink);
}
.sect-head .rule {
  flex: 1;
  height: 2px;
  background: var(--line-strong);
  border-radius: 2px;
}
.sect-head .star {
  color: var(--amber-text);
  font-size: 1.4rem;
}
html.dark .sect-head .star {
  color: var(--amber);
}

.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.cards.cards-2 {
  grid-template-columns: repeat(2, 1fr);
}
.card {
  text-decoration: none;
  color: inherit;
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-1);
  transition: transform 0.25s cubic-bezier(0.2, 0.7, 0.3, 1), box-shadow 0.25s, border-color 0.25s;
  display: flex;
  flex-direction: column;
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-2);
  border-color: var(--emerald);
}
.card .thumb {
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: linear-gradient(135deg, var(--amber) 0%, var(--emerald) 60%, var(--emerald-deep) 100%);
}
.card .thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}
.card:hover .thumb img {
  transform: scale(1.06);
}
.card .body {
  padding: 20px 20px 24px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}
.card .cat {
  align-self: flex-start;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--emerald-soft);
  background: var(--chip-bg);
  border: 1.5px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 4px 11px;
}
html.dark .card .cat {
  color: var(--emerald);
}
.card .pin {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--amber-text);
}
html.dark .card .pin {
  color: var(--amber);
}
.card .pin svg {
  width: 13px;
  height: 13px;
}
/* Gated "Members" marker — mirrors .card .pin (amber, uppercase chip). Only
   rendered on a gated card, which only reaches a signed-in member viewer. */
.card .members {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--amber-text);
}
html.dark .card .members {
  color: var(--amber);
}
.card .members svg {
  width: 13px;
  height: 13px;
}
.card h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.28rem;
  line-height: 1.2;
  margin: 2px 0 0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.card .excerpt {
  font-size: 0.95rem;
  color: var(--ink-soft);
  line-height: 1.55;
  margin: 0;
}
.card .read {
  margin-top: auto;
  font-size: 0.86rem;
  color: var(--ink-faint);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-body);
  font-weight: 600;
}
.card .read svg {
  width: 15px;
  height: 15px;
  color: var(--emerald-soft);
}
html.dark .card .read svg {
  color: var(--emerald);
}

@media (max-width: 880px) {
  .cards,
  .cards.cards-2 {
    grid-template-columns: 1fr;
    max-width: 520px;
    margin-inline: auto;
  }
}

/* ============================ INDEX / ARCHIVE PAGE HEAD ============================ */
.list-head {
  position: relative;
  /* Tighter gap between the header bar and "The Almanac" eyebrow (item 7). */
  padding-top: clamp(28px, 5vw, 56px);
  padding-bottom: clamp(28px, 4vw, 44px);
}
.list-head h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 6vw, 4.4rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  margin: 18px 0 0;
  color: var(--ink);
  text-wrap: balance;
}
.list-head .dek {
  margin-top: 18px;
}
/* Author archive heading: an initials monogram (matching the byline avatar)
   inline before the author name. */
.author-head {
  display: inline-flex;
  align-items: center;
  gap: 16px;
}
.author-head-avatar {
  flex: 0 0 auto;
  width: clamp(48px, 8vw, 64px);
  height: clamp(48px, 8vw, 64px);
  border-radius: 50%;
  border: 2px solid var(--amber);
  background: var(--paper-2);
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.2rem, 3vw, 1.6rem);
  color: var(--emerald-deep);
}
html.dark .author-head-avatar {
  color: var(--emerald);
}
.list-section {
  /* Cards sit closer under the search field (item 1). */
  margin-top: clamp(16px, 2vw, 24px);
  /* Breathing room below the last card row / pagination so the card's bottom
     border never abuts the footer's top border (item 2). */
  margin-bottom: clamp(48px, 6vw, 80px);
}

/* ============================ PAGINATION ============================ */
.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: clamp(44px, 6vw, 72px) 0 0;
}
.pagination a,
.pagination span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  height: 44px;
  padding: 0 14px;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  text-decoration: none;
  border: 1.5px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink-soft);
  transition: transform 0.18s, border-color 0.2s, color 0.2s, background-color 0.2s;
}
.pagination a:hover {
  transform: translateY(-2px);
  border-color: var(--emerald);
  color: var(--ink);
}
.pagination .current {
  background: linear-gradient(135deg, var(--emerald) 0%, var(--emerald-deep) 100%);
  color: #fff;
  border-color: transparent;
}
html.dark .pagination .current {
  color: #03130d;
}
.pagination .disabled {
  opacity: 0.4;
  pointer-events: none;
}
.pagination .gap {
  border: 0;
  background: transparent;
  min-width: 20px;
}

/* ============================ EMPTY STATE ============================ */
.empty {
  max-width: 560px;
  margin: clamp(40px, 6vw, 80px) auto;
  text-align: center;
  background: var(--surface);
  border: 2px solid var(--line-strong);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  padding: clamp(36px, 6vw, 60px) clamp(24px, 4vw, 44px);
}
.empty .glyph {
  width: 64px;
  height: 64px;
  margin: 0 auto 22px;
  color: var(--emerald-deep);
}
html.dark .empty .glyph {
  color: var(--emerald);
}
.empty h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  margin: 0 0 12px;
  color: var(--ink);
}
.empty p {
  margin: 0 0 26px;
  color: var(--ink-soft);
  font-size: 1.05rem;
}

/* ============================ SHARED BUTTON ============================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1rem;
  padding: 13px 28px;
  border-radius: var(--radius-pill);
  border: 0;
  transition: transform 0.2s, box-shadow 0.25s;
}
.btn-primary {
  color: #fff;
  background: linear-gradient(135deg, var(--emerald) 0%, var(--emerald-deep) 100%);
  box-shadow: 0 12px 28px -12px color-mix(in srgb, var(--emerald) 80%, transparent);
}
html.dark .btn-primary {
  color: #03130d;
}
.btn-primary:hover {
  transform: translateY(-3px);
}

/* ============================ INLINE INDEX SEARCH ============================
   A round, wide, glass-background search control above the /blog index cards.
   Live search: as the user types, the client debounces and fetches the
   same-origin /api/search route, then live-replaces the index grid with the
   matches and opens an autocomplete suggestions dropdown under the field. There
   is no submit, no Search button, no ?q URL, and no server search branch; the
   field clears via its own control to restore the paginated index. */
/* The search field + its autocomplete dropdown share one positioning wrap so
   the dropdown anchors to the field. The wrap is the full content width (it
   equals the card row, which fills the same `.wrap`). More top margin lifts it
   away from the title/subtitle; the cards below sit closer via a reduced
   `.list-section` top margin. */
.index-search-wrap {
  position: relative;
  width: 100%;
  /* Distance above the field (from the title/subtitle); the `.list-head`
     padding-bottom adds to this, so a moderate value reads as a clear gap
     (item 4c: farther from the title, closer to the cards below). */
  margin-top: clamp(20px, 3vw, 36px);
}
.index-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px 9px 20px;
  /* More transparent than before (~55% surface) so the page grid texture shows
     through subtly; the backdrop blur keeps the text legible over it. */
  background: color-mix(in srgb, var(--surface) 55%, transparent);
  /* -webkit- alias FIRST, standard LAST: the Lightning CSS transformer keeps
     only the LATER backdrop-filter alias, so the standard property must come
     last or it is stripped and the blur is lost. */
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  backdrop-filter: saturate(1.4) blur(14px);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-pill);
  box-shadow: var(--shadow-1);
  transition: border-color 0.2s, box-shadow 0.2s;
}
.index-search:focus-within {
  border-color: var(--emerald);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--emerald) 18%, transparent);
}
.index-search-icon {
  flex: 0 0 auto;
  display: inline-flex;
  color: var(--ink-faint);
}
.index-search-icon svg {
  width: 19px;
  height: 19px;
}
.index-search input[type="text"] {
  flex: 1;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 1.02rem;
  color: var(--ink);
  background: transparent;
  border: 0;
  outline: none;
  padding: 9px 4px;
}
.index-search input[type="text"]::placeholder {
  color: var(--ink-faint);
}
/* Round clear ("x") button, shown only when the field has a value. */
.index-search-clear {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  cursor: pointer;
  color: var(--ink-faint);
  background: transparent;
  border: 0;
  border-radius: 999px;
  transition: color 0.2s, background-color 0.2s;
}
.index-search-clear:hover {
  color: var(--ink);
  background: var(--chip-bg);
}
.index-search-clear svg {
  width: 17px;
  height: 17px;
}

/* Autocomplete suggestions dropdown: a glass panel matching the card surface,
   anchored under the field. */
.search-suggest {
  position: absolute;
  z-index: 40;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  margin: 0;
  padding: 6px;
  list-style: none;
  max-height: min(60vh, 420px);
  overflow-y: auto;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  /* -webkit- alias FIRST, standard LAST: the Lightning CSS transformer keeps
     only the LATER backdrop-filter alias, so the standard property must come
     last or it is stripped and the blur is lost. */
  -webkit-backdrop-filter: saturate(1.4) blur(16px);
  backdrop-filter: saturate(1.4) blur(16px);
  border: 1.5px solid var(--line-strong);
  border-radius: 18px;
  box-shadow: var(--shadow-2);
}
.search-suggest-item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 14px;
  text-decoration: none;
  color: inherit;
  border-radius: 12px;
  transition: background-color 0.15s;
}
.search-suggest-item:hover,
.search-suggest-item.is-active {
  background: var(--chip-bg);
}
.search-suggest-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.25;
  color: var(--ink);
  min-width: 0;
}
.search-suggest-meta {
  flex: 0 0 auto;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--emerald-soft);
  white-space: nowrap;
}
html.dark .search-suggest-meta {
  color: var(--emerald);
}

/* The article-count line on the category / tag ARCHIVE headers. (The /blog
   index moved its count into the search-field placeholder, so the index no
   longer renders this line, but the archives still do.) */
.search-count {
  margin-top: 26px;
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--ink-soft);
}
.search-count strong {
  color: var(--ink);
}

/* ============================ 404 / ERROR RECOVERY ============================
   Mirrors the public marketing SPA recovery design (src/components/NotFound.tsx
   + the production ErrorFallback): a label pill, an explorer image, a heading
   with an emerald gradient accent, recovery destination cards, and a Go Back +
   Home action pair. Shared by NotFoundContent (404) and the Next error
   boundaries (error.tsx / global-error.tsx). Themed with the blog tokens. */
.recovery {
  max-width: 640px;
  margin-inline: auto;
  text-align: center;
  padding: clamp(48px, 9vw, 100px) 0 clamp(48px, 8vw, 90px);
}
.recovery-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 28px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--emerald) 14%, transparent);
  color: var(--emerald-soft);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
html.dark .recovery-pill {
  color: var(--emerald);
}
.recovery-pill svg {
  width: 15px;
  height: 15px;
}
.recovery-figure {
  position: relative;
  max-width: 420px;
  margin: 0 auto 36px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 2px solid var(--line-strong);
  box-shadow: var(--shadow-2);
  transform: rotate(1deg);
  transition: transform 0.5s ease;
}
.recovery-figure:hover {
  transform: rotate(0deg);
}
.recovery-figure img {
  width: 100%;
  height: auto;
  display: block;
}
.recovery-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 70%, color-mix(in srgb, var(--ink) 24%, transparent) 100%);
}
.recovery-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.9rem, 4.4vw, 2.9rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 16px;
  text-wrap: balance;
}
.recovery-lede {
  color: var(--ink-soft);
  font-size: 1.08rem;
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 auto 28px;
}
.recovery-prompt {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-faint);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.92rem;
  margin: 0 0 22px;
}
.recovery-prompt svg {
  width: 16px;
  height: 16px;
  color: var(--emerald);
}
.recovery-cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin: 0 auto 36px;
  text-align: left;
}
.recovery-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-decoration: none;
  background: var(--surface);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
  padding: 16px 18px;
  transition: transform 0.2s, border-color 0.2s, box-shadow 0.2s;
}
.recovery-card:hover {
  transform: translateY(-3px);
  border-color: var(--emerald);
  box-shadow: var(--shadow-2);
}
.recovery-card-title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink);
}
.recovery-card:hover .recovery-card-title {
  color: var(--emerald-deep);
}
html.dark .recovery-card:hover .recovery-card-title {
  color: var(--emerald);
}
.recovery-card-blurb {
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--ink-soft);
}
.recovery-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
}
.recovery-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 1rem;
  padding: 13px 26px;
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  border: 1.5px solid var(--line-strong);
  transition: transform 0.2s, border-color 0.2s;
}
.recovery-back:hover {
  transform: translateY(-3px);
  border-color: var(--emerald);
}
.recovery-back svg,
.recovery-actions .btn svg {
  width: 17px;
  height: 17px;
}
@media (max-width: 560px) {
  .recovery-cards {
    grid-template-columns: 1fr;
  }
}

/* The dev-only raw error panel (error.tsx / global-error.tsx, NODE_ENV !==
   'production'). Never rendered in production. A monospace, scrollable dump. */
.recovery-detail {
  margin: 30px auto 0;
  max-width: 100%;
  text-align: left;
  background: color-mix(in srgb, var(--ink) 6%, transparent);
  border: 1.5px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
}
.recovery-detail summary {
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.recovery-detail pre {
  margin: 14px 0 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink);
  max-height: 22rem;
  overflow-y: auto;
}

/* ============================ LOGIN GATE ============================ */
.gate {
  max-width: 640px;
  margin: clamp(40px, 7vw, 90px) auto;
  text-align: center;
  background:
    radial-gradient(140% 120% at 100% 0%, color-mix(in srgb, var(--emerald) 16%, transparent), transparent 55%),
    var(--surface);
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
  padding: clamp(34px, 6vw, 60px) clamp(24px, 5vw, 52px);
  position: relative;
  overflow: hidden;
}
html.dark .gate {
  border-color: var(--line-strong);
}
.gate .lock {
  width: 56px;
  height: 56px;
  margin: 0 auto 22px;
  color: var(--emerald-deep);
}
html.dark .gate .lock {
  color: var(--emerald);
}
.gate .chip-cat {
  margin-bottom: 20px;
}
.gate h1 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  line-height: 1.08;
  color: var(--ink);
  margin: 0 0 16px;
  text-wrap: balance;
}
.gate .gate-excerpt {
  color: var(--ink-soft);
  font-size: 1.12rem;
  line-height: 1.6;
  max-width: 48ch;
  margin: 0 auto 28px;
}
.gate .gate-hero {
  margin: 0 0 28px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 2px solid var(--line-strong);
  aspect-ratio: 16 / 9;
  background: linear-gradient(135deg, var(--amber) 0%, var(--emerald) 60%, var(--emerald-deep) 100%);
}
.gate .gate-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gate .note {
  margin-top: 18px;
  font-size: 0.92rem;
  color: var(--ink-faint);
}

/* Gate loading state (gated body fetch in flight). Mirrors the gate's emerald
   accent; the spinner reuses the shared `spin` keyframe. Reduced-motion is
   handled globally by the clamp at the top of this file. */
.gate-loading {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 6px;
  color: var(--ink-soft);
  font-family: var(--font-body);
  font-weight: 600;
}
.gate-spinner {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--emerald) 28%, transparent);
  border-top-color: var(--emerald);
  animation: spin 0.8s linear infinite;
}
html.dark .gate-spinner {
  border-color: color-mix(in srgb, var(--emerald) 34%, transparent);
  border-top-color: var(--emerald);
}
.gate-loading-text {
  font-size: 1rem;
}

/* ============================ PAGE LOAD REVEAL ============================ */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  animation: rise 0.8s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes rise {
  to {
    opacity: 1;
    transform: none;
  }
}
.d1 {
  animation-delay: 0.05s;
}
.d2 {
  animation-delay: 0.14s;
}
.d3 {
  animation-delay: 0.23s;
}
.d4 {
  animation-delay: 0.32s;
}
.d5 {
  animation-delay: 0.42s;
}

/* ============================================================
   SHARED EDITORIAL SCOPE  (.post--feature)
   ============================================================
   The shared base for the two EDITORIAL templates (Editorial Text Left =
   `wide-feature`, Editorial Image Left = `editorial-image-left`). Every rule is
   scoped under `.post--feature` so the standard template's
   `.hero/.title/.article/.pullquote/.filed` rules are untouched (additive only).
   The shared Lexical body, byline, related grid, and tokens are reused; the
   scoped treatments here are:
     - a larger display title (the editorial feature-title),
     - a wider article measure (86ch vs the standard 68ch),
     - stronger section-divider rhythm above body headings,
     - a more prominent, card-style pull quote.
   The two-column band itself lives in the `.post--editorial` block below. Reads
   in light + dark and collapses gracefully on mobile. */

/* feature article measure: wider single column than the standard 68ch. The
   `.post--feature` scope is now shared by the two EDITORIAL templates (see the
   `.post--editorial` block below): they reuse this measure, the section-divider
   rhythm, and the card pull quote, and add their own two-column band. The old
   full-bleed `.feature-hero` band was removed when `wide-feature` became the
   editorial layout. */
.post--feature {
  --feature-measure: 86ch;
}

/* feature head spacing (shared by both editorial templates' text column). */
.post--feature .feature-head {
  padding-top: clamp(28px, 4.5vw, 56px);
}

/* display title for the editorial templates: still a touch larger than the
   standard h1.title, but #4 reduces the giant ceiling (was up to 6rem). It keeps
   the inherited text-wrap:balance + wrapping (no truncation; it is the H1). */
.post--feature .feature-title {
  font-size: clamp(2.4rem, 5.6vw, 4.25rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

/* wider article measure */
.post--feature .feature-article {
  max-width: var(--feature-measure);
}
/* the "Filed under" row under the feature article matches the wider measure */
.post--feature .filed {
  max-width: var(--feature-measure);
}

/* stronger section-divider rhythm: a full-measure gradient rule above each
   body H2 (the standard template uses a short 54px tick). Overrides the short
   tick ONLY inside the feature article. */
.post--feature .feature-article h2 {
  margin-top: 2.8em;
}
.post--feature .feature-article h2::before {
  width: 100%;
  height: 3px;
  margin-bottom: 26px;
  opacity: 0.85;
}

/* prominent feature pull quote: a card with a left accent bar, larger type, and
   an emerald-tinted surface, distinct from the standard centered pull quote. */
.post--feature .pullquote {
  margin: 2.8em 0;
  padding: 30px 34px;
  text-align: left;
  background: color-mix(in srgb, var(--emerald) 7%, var(--surface));
  border-left: 6px solid var(--emerald);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
}
html.dark .post--feature .pullquote {
  background: color-mix(in srgb, var(--emerald) 12%, var(--surface));
}
.post--feature .pullquote .mark {
  text-align: left;
  margin-bottom: 0;
}
.post--feature .pullquote p {
  font-size: clamp(1.6rem, 3.4vw, 2.3rem);
  line-height: 1.25;
  text-align: left;
}
.post--feature .pullquote cite {
  color: var(--emerald-deep);
}
html.dark .post--feature .pullquote cite {
  color: var(--emerald);
}

/* ---- mobile: the display title scales down via its own clamp above; the
   pull quote tightens its padding (the editorial two-column band stacks via the
   `.post--editorial` mobile rules below) ---- */
@media (max-width: 760px) {
  .post--feature .pullquote {
    padding: 22px 22px;
  }
}

/* ============================================================
   TEMPLATES: Editorial Text Left (id: wide-feature)
              Editorial Image Left (id: editorial-image-left)
   ============================================================
   A two-column "magazine" layout (#5/#6). Both editorial templates share these
   rules (scoped under `.post--editorial`, which is ALSO `.post--feature` so the
   wider measure / section rhythm / card pull quote are reused) and differ only
   by the `.post--editorial-img-<side>` modifier that flips the column order. The
   markup order is always text-then-image (heading leads the outline); the CSS
   `order` puts the image left for the mirror template. Below 760px both collapse
   to a single stacked column (text first, then image) so nothing overflows. */

/* the top band: a balanced two-column grid (text + image). The image column is
   ~40% (D1); the text column takes the rest. */
.post--editorial .editorial-band {
  display: grid;
  grid-template-columns: 1fr minmax(0, 40%);
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  margin-top: clamp(20px, 3vw, 40px);
}
/* a no-image editorial post: the text spans the full row (no empty column). */
.post--editorial .editorial-band-noimg {
  grid-template-columns: 1fr;
}
.post--editorial .editorial-text {
  padding-top: 0;
  min-width: 0;
}
/* the dek wraps fuller inside the narrower text column than the standard 46ch. */
.post--editorial .editorial-text .dek {
  max-width: 52ch;
}
.post--editorial .editorial-media {
  min-width: 0;
}
.post--editorial .editorial-frame {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: 2px solid var(--ink);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-2);
  background: linear-gradient(135deg, var(--amber) 0%, var(--emerald) 60%, var(--emerald-deep) 100%);
}
html.dark .post--editorial .editorial-frame {
  border-color: var(--line-strong);
}
.post--editorial .editorial-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* IMAGE-RIGHT (Editorial Text Left): text column first, image second (markup
   order), which is the default — no order override needed. */

/* IMAGE-LEFT (Editorial Image Left): flip the visual order so the image sits on
   the left while the heading still leads the document outline. */
.post--editorial-img-left .editorial-text { order: 2; }
.post--editorial-img-left .editorial-media { order: 1; }

@media (max-width: 760px) {
  /* stack to one column on mobile: text first, then image, regardless of side. */
  .post--editorial .editorial-band {
    grid-template-columns: 1fr;
    gap: clamp(18px, 5vw, 28px);
  }
  .post--editorial-img-left .editorial-text { order: 1; }
  .post--editorial-img-left .editorial-media { order: 2; }
  .post--editorial .editorial-frame {
    aspect-ratio: 16 / 10;
  }
}

/* ============================================================
   PER-TEMPLATE PAGE TEXTURE (#13)
   ============================================================
   The SSR threads a `post-tpl--<id>` body class for the editorial templates so
   the GLOBAL grid (`body::after`) + wash (`body::before`) are recolored per
   template, and the in-content motif (.tpl-motif) replaces the global sunburst.
   Non-editorial pages emit no body class and keep the global texture + sunburst.

   The motif host mirrors `.sunburst`'s placement (fixed, top-right, behind
   content) so it occupies the SAME visual slot the sun used. */
.tpl-motif {
  position: fixed;
  top: -150px;
  right: -150px;
  width: 520px;
  height: 520px;
  max-width: 60vw;
  max-height: 60vw;
  z-index: -1;
  pointer-events: none;
  opacity: 0.8;
}
.tpl-motif svg {
  width: 100%;
  height: 100%;
}

/* Editorial Text Left (wide-feature): a cooler emerald-led grid + wash. */
body.post-tpl--wide-feature::after {
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--emerald) 100%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--emerald) 100%, transparent) 1px, transparent 1px);
  background-size: 72px 72px;
  opacity: calc(var(--grain-op) * 1.5);
}
body.post-tpl--wide-feature::before {
  background: linear-gradient(135deg, #ecfdf5 0%, #eafaf3 46%, #ffffff 100%);
}
html.dark body.post-tpl--wide-feature::before {
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(4, 60, 46, 0.34) 0%, transparent 56%),
    linear-gradient(135deg, #030712 0%, #0d1a20 58%, #07171b 100%);
}

/* Editorial Image Left (editorial-image-left): a warmer amber-led grid + wash,
   subtly different from the text-left treatment. */
body.post-tpl--editorial-image-left::after {
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--amber) 100%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--amber) 100%, transparent) 1px, transparent 1px);
  background-size: 72px 72px;
  opacity: calc(var(--grain-op) * 1.5);
}
body.post-tpl--editorial-image-left::before {
  background: linear-gradient(135deg, #fffbeb 0%, #fdf6e9 46%, #ffffff 100%);
}
html.dark body.post-tpl--editorial-image-left::before {
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(66, 45, 6, 0.32) 0%, transparent 56%),
    linear-gradient(135deg, #0a0a06 0%, #1a160d 58%, #1b1407 100%);
}
