/* =====================================================================
   enaloo theme: main.css. Loaded on every page and in the editor.
   Source: the CSS of design/index.html (the approved prototype), with
   these WordPress changes:
   * Palette tokens alias the theme.json presets (--bg is
     var(--wp--preset--color--bg) and so on). Dark and print values
     override the presets, so core color classes switch too.
   * Font families come from the theme.json presets (self hosted
     WOFF2 files), with metric matched fallback faces.
   * Core block markup gets the prototype look: buttons, groups, lists,
     the header and footer template parts.
   * .nav-links a[aria-current] covers "true" (scroll spy) and "page"
     (the blog link on blog views).
   * Plain page views (page.html, index.html, 404.html) at the end.
   The blog views add covers.css and blog.css (loaded only there).
   ===================================================================== */

/* ---------- Fallback faces with matched metrics, so text does not jump when the web fonts load ---------- */
@font-face {
  font-family: 'IBM Plex Sans Fallback';
  src: local('Arial'), local('ArialMT');
  size-adjust: 101.17%; ascent-override: 101.32%; descent-override: 27.18%; line-gap-override: 0%;
}
@font-face {
  font-family: 'Space Grotesk Fallback';
  src: local('Arial'), local('ArialMT');
  size-adjust: 109.69%; ascent-override: 89.71%; descent-override: 26.62%; line-gap-override: 0%;
}
@font-face {
  font-family: 'IBM Plex Mono Fallback';
  src: local('Courier New'), local('CourierNewPSMT');
  size-adjust: 99.98%; ascent-override: 102.52%; descent-override: 27.5%; line-gap-override: 0%;
}

/* ---------- Tokens: light is the base, dark follows the system or the switch ----------
   Palette tokens are aliases of the theme.json presets. The values live in theme.json (light)
   and in the dark and print blocks below, which override the presets themselves.
   The accent can be changed in the plugin settings (enaloo core, Colors). The plugin prints <style id="enaloo-accent">
   after this file, with the same selectors as the blocks below. It sets --accent, --accent-ink, --accent-soft and --glow
   (and the matching presets), so use only those four for anything in the accent color: never a hex or rgba of the green. */
:root {
  --bg: var(--wp--preset--color--bg);
  --bg2: var(--wp--preset--color--bg-2);
  --line: var(--wp--preset--color--line);
  --line2: var(--wp--preset--color--line-2);
  --field-line: var(--wp--preset--color--field-line);
  --seg: var(--wp--preset--color--seg);
  --text: var(--wp--preset--color--text);
  --muted: var(--wp--preset--color--muted);
  --accent: var(--wp--preset--color--accent);
  --accent-ink: var(--wp--preset--color--accent-ink);
  --accent-soft: var(--wp--preset--color--accent-soft);
  --cipher: var(--wp--preset--color--cipher);
  --danger: var(--wp--preset--color--danger);
  --chip: var(--wp--preset--color--chip);
  --grid: var(--wp--preset--color--grid);
  --glow: var(--wp--preset--color--glow);
  --font-sans: var(--wp--preset--font-family--sans);
  --font-display: var(--wp--preset--font-family--display);
  --font-mono: var(--wp--preset--font-family--mono);
  /* Outside the editor palette (design-system.md, WordPress mapping). */
  --panel: #FFFFFF;
  --panel2: #F2F4F6;
  --panel-line: #E1E5E9;
  --panel-text: #0E1216;
  --panel-muted: #55606B;
  --panel-accent: var(--accent);
  --panel-cipher: #5B4BC4;
  --panel-shadow: 0 30px 60px -30px rgba(14, 18, 22, .22), 0 1px 3px rgba(14, 18, 22, .06);
  --menu-shadow: 0 16px 32px -16px rgba(14, 18, 22, .28);
  /* Light uses bg2 as the base, so secondary text stays at 7:1 on the hover tint. */
  --ext-hover: color-mix(in srgb, var(--accent) 5%, var(--bg2));
  --header-h: 68px;
  --ease-out: cubic-bezier(.23, 1, .32, 1);
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --wp--preset--color--bg: #0A0C0F; --wp--preset--color--bg-2: #11151A; --wp--preset--color--line: #1F262E; --wp--preset--color--line-2: #2C353F;
    --wp--preset--color--field-line: #64707C; --wp--preset--color--seg: #252D37; --wp--preset--color--text: #E6EAEE; --wp--preset--color--muted: #9AA4AE;
    --wp--preset--color--accent: #5EE6B0; --wp--preset--color--accent-ink: #062A1C; --wp--preset--color--accent-soft: rgba(94, 230, 176, .08); --wp--preset--color--cipher: #A99BFF;
    --wp--preset--color--danger: #FF8A80; --wp--preset--color--chip: #151B21; --wp--preset--color--grid: rgba(230, 234, 238, .10); --wp--preset--color--glow: rgba(94, 230, 176, .12);
    --panel: #0E1217; --panel2: #141A21; --panel-line: #222B34; --panel-text: #E6EAEE; --panel-muted: #8E98A2; --panel-accent: var(--accent); --panel-cipher: #B3A6FF;
    --panel-shadow: 0 40px 90px -40px rgba(0, 0, 0, .85), 0 0 0 1px rgba(255, 255, 255, .02);
    --menu-shadow: 0 24px 40px -16px rgba(0, 0, 0, .95); --ext-hover: color-mix(in srgb, var(--accent) 5%, var(--bg));
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --wp--preset--color--bg: #0A0C0F; --wp--preset--color--bg-2: #11151A; --wp--preset--color--line: #1F262E; --wp--preset--color--line-2: #2C353F;
  --wp--preset--color--field-line: #64707C; --wp--preset--color--seg: #252D37; --wp--preset--color--text: #E6EAEE; --wp--preset--color--muted: #9AA4AE;
  --wp--preset--color--accent: #5EE6B0; --wp--preset--color--accent-ink: #062A1C; --wp--preset--color--accent-soft: rgba(94, 230, 176, .08); --wp--preset--color--cipher: #A99BFF;
  --wp--preset--color--danger: #FF8A80; --wp--preset--color--chip: #151B21; --wp--preset--color--grid: rgba(230, 234, 238, .10); --wp--preset--color--glow: rgba(94, 230, 176, .12);
  --panel: #0E1217; --panel2: #141A21; --panel-line: #222B34; --panel-text: #E6EAEE; --panel-muted: #8E98A2; --panel-accent: var(--accent); --panel-cipher: #B3A6FF;
  --panel-shadow: 0 40px 90px -40px rgba(0, 0, 0, .85), 0 0 0 1px rgba(255, 255, 255, .02);
  --menu-shadow: 0 24px 40px -16px rgba(0, 0, 0, .95); --ext-hover: color-mix(in srgb, var(--accent) 5%, var(--bg));
  color-scheme: dark;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--header-h) + 16px); }
/* Smooth scrolling starts after the page has loaded (theme.js adds is-loaded). A link with a #hash then jumps to its target at once,
   even while a late font is still moving the layout. */
@media (prefers-reduced-motion: no-preference) {
  html.is-loaded { scroll-behavior: smooth; }
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 1.0625rem/1.6 var(--font-sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
a { color: var(--accent); text-underline-offset: 3px; }
svg { flex: none; }
::selection { background: var(--accent); color: var(--accent-ink); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
.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; }
.wrap { max-width: 1200px; margin-inline: auto; padding-inline: clamp(16px, 4vw, 32px); }
.skip {
  position: absolute; left: 16px; top: -60px; z-index: 50; padding: 12px 16px; border-radius: 10px;
  background: var(--accent); color: var(--accent-ink); font-weight: 600; text-decoration: none;
}
.skip:focus { top: 12px; }
main:focus { outline: none; }

/* Note for administrators when the enaloo core plugin is not active (inc/plugin-check.php). */
.plugin-note { margin: 0; padding: 12px clamp(16px, 4vw, 32px); border-bottom: 2px solid var(--danger); background: var(--bg2); color: var(--text); font-size: .9375rem; }

/* WordPress: the logged in toolbar sits above the sticky header (fixed from 601px, part of the page below). */
html:has(> body.admin-bar) { scroll-padding-top: calc(var(--header-h) + 16px + var(--wp-admin--admin-bar--height, 0px)); }
.admin-bar .skip:focus { top: calc(12px + var(--wp-admin--admin-bar--height, 0px)); }

/* ---------- Header (template part "header": header.wp-block-template-part.site-header) ---------- */
.site-header {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.admin-bar .site-header { top: var(--wp-admin--admin-bar--height, 0px); }
@media screen and (max-width: 600px) {
  .admin-bar .site-header { top: 0; }
}
.site-header.is-stuck { border-bottom-color: var(--line); }
/* The row is one line of --header-h. When the brand and the tools do not fit (a large default font in the browser, a 320px screen), the tools wrap under the brand. */
.header-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; min-height: var(--header-h); padding-block: 4px; }
.brand {
  display: inline-flex; align-items: center; min-height: 44px;
  font: 500 .9375rem/1 var(--font-mono); color: var(--text); text-decoration: none;
}
.brand b { color: var(--accent); font-weight: 500; }
.header-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.nav-links { display: flex; align-items: center; gap: 2px; margin: 0; padding: 0; list-style: none; }
.nav-links a {
  position: relative; display: inline-flex; align-items: center; min-height: 40px; padding: 0 11px; border-radius: 8px;
  font: 400 .8125rem/1 var(--font-mono); color: var(--muted); text-decoration: none;
  transition: color .15s ease, background-color .15s ease;
}
.nav-links a:hover { color: var(--text); background: var(--chip); }
/* "true": the scroll spy on the home page, and the blog link on posts, archives and search. "page": the posts page. */
.nav-links a[aria-current="true"], .nav-links a[aria-current="page"] { color: var(--text); }
.nav-links a[aria-current="true"]::before, .nav-links a[aria-current="page"]::before {
  content: ""; position: absolute; left: 50%; bottom: 3px; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%; background: var(--accent);
}
/* A link to another page (Blog) sits after a small gap. */
.nav-links .nav-page { margin-left: 12px; }
.theme-switch {
  display: inline-flex; gap: 2px; margin: 0 0 0 6px; padding: 3px; min-width: 0;
  border: 1px solid var(--line); border-radius: 12px; background: var(--chip);
}
.theme-switch label {
  position: relative; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px;
  color: var(--muted); cursor: pointer; transition: color .15s ease, background-color .15s ease;
}
.theme-switch label:hover { color: var(--text); }
.theme-switch input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.theme-switch label:has(input:checked) {
  color: var(--text); background: var(--seg); outline: 1px solid var(--accent); outline-offset: -1px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .08);
}
.theme-switch label:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }
html:not(.js) .theme-switch { display: none; }
.menu-btn {
  display: none; align-items: center; justify-content: center; gap: 8px; min-width: 44px; min-height: 44px; padding: 0 14px; border-radius: 10px;
  border: 1px solid var(--line); background: var(--chip); color: var(--text); cursor: pointer;
  font: 500 .8125rem/1 var(--font-mono);
}
/* The header is sticky: focusing its controls must not scroll the page. */
.brand, .menu-btn, .theme-switch input { scroll-margin-top: calc(-1 * (var(--header-h) + 16px)); }
@media (min-width: 861px) {
  .nav-links a { scroll-margin-top: calc(-1 * (var(--header-h) + 16px)); }
}
@media (max-width: 860px) {
  .js .menu-btn { display: inline-flex; }
  .js .menu-btn[aria-expanded="true"] { border-color: var(--accent); }
  .js .nav-links {
    display: none; position: absolute; top: 100%; left: 0; right: 0; flex-direction: column; align-items: stretch; gap: 0;
    max-height: calc(100dvh - var(--header-h)); overflow-y: auto; overscroll-behavior: contain;
    padding: 8px clamp(16px, 4vw, 32px) 16px; background: var(--bg); border-bottom: 1px solid var(--line2);
    box-shadow: var(--menu-shadow);
  }
  .js .nav-links.is-open { display: flex; }
  .js .nav-links a { display: flex; min-height: 48px; padding: 0 4px; font-size: .9375rem; border-radius: 0; border-bottom: 1px solid var(--line); }
  .js .nav-links li:last-child a { border-bottom: 0; }
  .js .nav-links .nav-page { margin: 8px 0 0; }
  .js .nav-links a:hover { background: transparent; }
  .js .nav-links a[aria-current="true"]::before, .js .nav-links a[aria-current="page"]::before { left: auto; right: 6px; bottom: auto; top: 50%; margin: -2px 0 0; }
  html:not(.js) .site-header { position: static; }
  html:not(.js) .header-row { padding-block: 10px; }
  html:not(.js) .nav-links { flex-wrap: wrap; }
}
@media (max-width: 400px) {
  .header-row { column-gap: 8px; }
  .header-tools { gap: 6px; }
  .theme-switch { margin-left: 0; }
  .menu-btn { padding: 0 12px; }
  .menu-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
}
/* Touch screens: every control is at least 44px */
@media (pointer: coarse) {
  .theme-switch { padding: 0; gap: 0; }
  .theme-switch label { width: 44px; height: 44px; border-radius: 11px; }
  .nav-links a { min-height: 44px; }
}

/* ---------- Hero ---------- */
.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
  background-image: linear-gradient(var(--grid) 1px, transparent 1px), linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 48px 48px; background-position: center -1px;
  /* Fade in from the top (no hard edge under the header), then the soft radial falloff. */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 160px), radial-gradient(ellipse 75% 80% at 68% 42%, #000 25%, transparent 78%);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(to bottom, transparent, #000 160px), radial-gradient(ellipse 75% 80% at 68% 42%, #000 25%, transparent 78%);
  mask-composite: intersect;
}
.hero::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  width: min(820px, 120vw); aspect-ratio: 1; right: -12%; top: 0;
  background: radial-gradient(closest-side, var(--glow), transparent);
}
@media (min-width: 961px) {
  /* Centered near the inspector at any width */
  .hero::after { width: 700px; right: calc(50% - 725px); top: 50%; translate: 0 -50%; }
}
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.04fr) minmax(0, .96fr); gap: clamp(40px, 6vw, 84px); align-items: center;
  padding-block: clamp(48px, 8vw, 112px) clamp(56px, 7vw, 96px);
}
.eyebrow { margin: 0 0 22px; font: 500 .8125rem/1.4 var(--font-mono); color: color-mix(in srgb, var(--accent) 85%, var(--text)); }
.name {
  margin: 0; font: 600 clamp(3.5rem, 6.4vw, 5rem)/.9 var(--font-display); letter-spacing: -.045em;
  overflow-wrap: anywhere; hyphens: auto;
}
.name span { display: block; }
/* One accent dot after the name. It is decoration, not text: the empty alt text keeps it out of the heading,
   the document title and screen readers. The first content line is the fallback for browsers without alt text. */
.name span:last-child::after { content: "."; content: "." / ""; color: var(--accent); }
.lead { margin: 30px 0 0; max-width: 30ch; font-size: clamp(1.25rem, 2vw, 1.4375rem); font-weight: 300; line-height: 1.5; }
/* A bit darker than muted, so it stays at 7:1 over the hero glow and grid. */
.meta { margin: 16px 0 0; font: 400 .875rem/1.5 var(--font-mono); color: color-mix(in srgb, var(--muted) 80%, var(--text)); }
/* Very narrow screens: each part on its own line, without a "·" left at a line end. */
@media (max-width: 359px) {
  .eyebrow .sep, .meta .sep { display: none; }
  .eyebrow .part, .meta .part { display: block; }
}
.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }

/* Buttons. The prototype classes (.btn, .btn-primary, .btn-ghost) stay for plugin markup
   (contact form, consent banner, author card). Core buttons get the same look:
   a core button is the primary button, the "Outline" style (is-style-outline) is the ghost button.
   is-style-ghost is the same ghost button, for markup that names it so. */
.btn, .wp-block-button > .wp-block-button__link {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 48px; padding: 0 22px;
  border-radius: 10px; font: 600 1rem/1 var(--font-sans); text-decoration: none; cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .1s ease;
}
.btn:active, .wp-block-button > .wp-block-button__link:active { transform: translateY(1px); }
.btn-primary, .wp-block-button > .wp-block-button__link { background: var(--accent); color: var(--accent-ink); border: 0; }
.btn-primary:hover, .wp-block-button > .wp-block-button__link:hover { background: color-mix(in srgb, var(--accent) 86%, var(--text)); color: var(--accent-ink); }
.btn-ghost, .wp-block-button.is-style-outline > .wp-block-button__link, .wp-block-button.is-style-ghost > .wp-block-button__link {
  border: 1px solid var(--line2); color: var(--text); font-weight: 500; background: color-mix(in srgb, var(--bg2) 55%, transparent);
}
.btn-ghost:hover, .wp-block-button.is-style-outline > .wp-block-button__link:hover, .wp-block-button.is-style-ghost > .wp-block-button__link:hover {
  border-color: var(--text); color: var(--text);
}
@media (max-width: 480px) {
  .actions, body .actions.is-layout-flex { display: grid; grid-template-columns: 1fr 1fr; }
  .actions .btn-primary, .actions > .wp-block-button:not(.is-style-outline):not(.is-style-ghost) { grid-column: 1 / -1; }
}
@media (max-width: 960px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero::before {
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 120px), radial-gradient(ellipse 120% 70% at 50% 30%, #000 20%, transparent 75%);
    mask-image: linear-gradient(to bottom, transparent, #000 120px), radial-gradient(ellipse 120% 70% at 50% 30%, #000 20%, transparent 75%);
  }
  .name { font-size: clamp(2.875rem, 17vw, 5rem); }
}

/* ---------- Frame inspector (hero visual, block enaloo/inspector) ---------- */
.inspector {
  margin: 0; overflow: hidden; border-radius: 20px; border: 1px solid var(--panel-line);
  background: var(--panel); color: var(--panel-text); box-shadow: var(--panel-shadow);
  font: 400 .8125rem/1.5 var(--font-mono);
}
.insp-bar { display: flex; align-items: center; gap: 14px; min-height: 57px; padding: 6px 6px 6px 18px; border-bottom: 1px solid var(--panel-line); color: var(--panel-muted); font-size: .78125rem; }
/* No pause button (reduced motion or no JavaScript): same height, same side gaps. */
.insp-bar:has(.insp-pause[hidden]), html:not(.js) .insp-bar { padding-right: 18px; }
.insp-url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.insp-live { display: inline-flex; align-items: center; gap: 8px; color: var(--panel-accent); }
.live-dot { position: relative; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.live-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1px solid currentColor; animation: ring 2.2s ease-out infinite; }
.insp-pause {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--panel-line); background: var(--panel2); color: var(--panel-text);
  transition: border-color .15s ease;
}
.insp-pause:hover { border-color: var(--panel-muted); }
.insp-pause:focus-visible { outline-color: var(--panel-accent); }
.insp-pause .i-play { display: none; }
.insp-pause[aria-pressed="true"] .i-play { display: block; }
.insp-pause[aria-pressed="true"] .i-pause { display: none; }
.insp-cols, .frame { display: grid; grid-template-columns: 20px minmax(0, 1fr) 70px 56px; gap: 10px; align-items: center; }
.insp-cols { padding: 12px 18px 6px; font-size: .71875rem; color: var(--panel-muted); }
.insp-cols span:nth-child(n+3), .frame .r { text-align: right; }
.frames-view {
  height: 160px; overflow: hidden; padding: 0 8px; display: flex; flex-direction: column; justify-content: flex-end;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 30px); mask-image: linear-gradient(to bottom, transparent, #000 30px);
}
.frames { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.frame { flex: none; height: 32px; padding: 0 10px 0 10px; border-radius: 8px; color: var(--panel-muted); transition: background-color .4s ease, color .4s ease; }
.frame.is-new { background: color-mix(in srgb, var(--panel-accent) 9%, transparent); color: var(--panel-text); }
.dir { display: grid; place-items: center; }
.dir-in { color: var(--panel-accent); }
.dir-out { color: var(--panel-cipher); }
.insp-detail { display: grid; gap: 8px; margin: 10px 0 0; padding: 16px 18px 14px; border-top: 1px solid var(--panel-line); }
.insp-detail > div { display: grid; grid-template-columns: 70px minmax(0, 1fr); gap: 10px; }
.insp-detail dt { color: var(--panel-muted); }
.insp-detail dd { margin: 0; min-width: 0; }
.inspector { container-type: inline-size; }
.hex, .dec { min-height: 1.5em; }
.hex { overflow-wrap: anywhere; }
.dec { word-break: break-all; }
@container (max-width: 460px) { .hex, .dec { min-height: 3em; } }
.hex { color: var(--panel-cipher); }
.dec .ok { color: var(--panel-accent); }
.dec .enc { color: var(--panel-cipher); }
.wire { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px; align-items: center; margin: 2px 18px 0; font-size: .71875rem; color: var(--panel-muted); }
.wire-track { position: relative; height: 26px; border-radius: 7px; background: var(--panel2); overflow: hidden; }
.wire-track::before { content: ""; position: absolute; left: 10px; right: 10px; top: 50%; height: 1px; background: var(--panel-line); }
.pkt { position: absolute; left: 0; top: 8px; height: 10px; border-radius: 3px; background: var(--panel-accent); will-change: transform; }
.pkt.out { background: var(--panel-cipher); }
.pkt.ctl { top: 10px; height: 6px; opacity: .85; }
.insp-prompt { margin: 0; padding: 14px 18px 18px; color: var(--panel-muted); }
.insp-prompt b { font-weight: 400; color: var(--panel-accent); }
.caret { color: var(--panel-accent); animation: blink 1.05s steps(1) infinite; }
.inspector.is-paused *, .inspector.is-paused *::after { animation-play-state: paused !important; }
html:not(.js) .insp-pause { display: none; }
html:not(.js) .inspector *, html:not(.js) .inspector *::after { animation: none; }
/* Short laptop screens: keep the hero inside the first view */
@media (min-width: 961px) and (max-height: 880px) {
  .hero-grid { padding-block: 40px 48px; }
  .frames-view { height: 128px; }
}
@keyframes blink { 50% { opacity: 0; } }
@keyframes ring { from { transform: scale(1); opacity: .8; } to { transform: scale(2.8); opacity: 0; } }

/* ---------- Numbers band (enaloo/stats, enaloo/stat) ---------- */
.band { background: var(--bg2); border-block: 1px solid var(--line); }
.stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.stat { margin: 0; padding: 30px 24px 32px; }
.stat:first-child { padding-left: 0; }
.stat + .stat { border-left: 1px solid var(--line); }
.stat-num { display: block; font: 600 clamp(2.375rem, 4.2vw, 3.375rem)/1 var(--font-display); letter-spacing: -.035em; font-variant-numeric: tabular-nums; }
.stat-label { display: block; margin-top: 10px; max-width: 22ch; color: var(--muted); font-size: .9375rem; line-height: 1.45; text-wrap: balance; }
/* Count up is visual only: the real number stays in the HTML (transparent while counting),
   and a pseudo-element shows the moving value. The empty alt text keeps it out of screen readers. */
.stat-num.is-counting { position: relative; color: transparent; }
.stat-num.is-counting::after {
  content: attr(data-show); content: attr(data-show) / "";
  position: absolute; left: 0; top: 0; color: var(--text);
}
@media (max-width: 860px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stat:nth-child(odd) { padding-left: 0; border-left: 0; }
  .stat:nth-child(even) { padding-right: 0; }
  .stat:nth-child(n+3) { border-top: 1px solid var(--line); }
}

/* ---------- Sections (enaloo/section) ---------- */
.section { padding-top: clamp(84px, 11vw, 144px); }
.sec-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(16px, 3vw, 32px); }
.sec-head { grid-column: 1 / span 4; }
.sec-body { grid-column: 5 / -1; min-width: 0; }
.h2 { margin: 0; font: 600 clamp(1.875rem, 3.4vw, 2.625rem)/1.08 var(--font-display); letter-spacing: -.028em; overflow-wrap: anywhere; }
.h3 { margin: 0; font: 600 1.5rem/1.2 var(--font-display); letter-spacing: -.015em; }
.sec-note { margin: 14px 0 0; color: var(--muted); font-size: 1rem; max-width: 30ch; }
@media (min-width: 961px) {
  .sec-head.is-sticky { position: sticky; top: calc(var(--header-h) + 40px); align-self: start; }
}
@media (max-width: 960px) {
  .sec-head, .sec-body { grid-column: 1 / -1; }
  .sec-head { margin-bottom: 30px; }
  .sec-note { margin-top: 0; }
}

/* About */
.about-lead { margin: 0; max-width: 32ch; font-size: clamp(1.5rem, 2.7vw, 2.0625rem); line-height: 1.38; font-weight: 300; letter-spacing: -.01em; }
.about-text { margin: 28px 0 0; max-width: 58ch; color: var(--muted); font-size: 1.125rem; }

/* How I work: pipeline (enaloo/steps, enaloo/step). The step number comes from a counter ("01" to "04"). */
.pipeline {
  --track: 7px;
  position: relative; list-style: none; margin: 56px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(20px, 3vw, 36px);
  counter-reset: step;
}
.pipeline::before, .pipeline::after { content: ""; position: absolute; left: 0; right: 0; top: var(--track); height: 1px; }
.pipeline::before { background: var(--line2); }
.pipeline::after { background: var(--accent); transform-origin: left center; transform: scaleX(1); }
.js .pipeline:not(.is-on)::after { transform: scaleX(0); }
.pipeline.is-on::after { transition: transform 2s linear; }
.pipe-packet {
  position: absolute; left: 0; top: calc(var(--track) - 3px); width: 20px; height: 7px; border-radius: 4px;
  background: var(--accent); box-shadow: 0 0 14px var(--accent); opacity: 0; pointer-events: none;
}
.step { position: relative; counter-increment: step; }
.node {
  position: relative; z-index: 1; display: block; width: 15px; height: 15px; border-radius: 50%;
  background: var(--accent); border: 1px solid var(--accent); box-shadow: 0 0 0 5px var(--accent-soft);
  transition: background-color .3s ease, border-color .3s ease, box-shadow .3s ease;
}
.js .step:not(.lit) .node { background: var(--bg); border-color: var(--line2); box-shadow: none; }
.step-n { display: block; margin-top: 26px; font: 500 .8125rem/1 var(--font-mono); color: var(--accent); transition: color .3s ease; }
.step-n::before { content: counter(step, decimal-leading-zero); }
.js .step:not(.lit) .step-n { color: var(--muted); }
.step h3 { margin: 14px 0 10px; font: 600 1.375rem/1.2 var(--font-display); letter-spacing: -.012em; }
.step p { margin: 0; color: var(--muted); font-size: 1rem; }
@media (max-width: 960px) {
  .pipeline { margin-top: 8px; }
}
@media (max-width: 760px) {
  .pipeline { grid-template-columns: minmax(0, 1fr); gap: 40px; padding-left: 44px; }
  .pipeline::before, .pipeline::after { left: 7px; right: auto; top: 8px; bottom: 8px; width: 1px; height: auto; }
  .pipeline::after { transform-origin: center top; transform: scaleY(1); }
  .js .pipeline:not(.is-on)::after { transform: scaleY(0); }
  .pipe-packet { left: 4px; top: 0; width: 7px; height: 20px; }
  .node { position: absolute; left: -44px; top: 2px; }
  .step-n { margin-top: 0; }
}

/* Experience: timeline (enaloo/timeline, enaloo/timeline-item). Each item is a native disclosure (details). The summary row is the toggle. */
.timeline { position: relative; list-style: none; margin: 0; padding: 0; }
.timeline::before { content: ""; position: absolute; left: 5px; top: 12px; bottom: 12px; width: 1px; background: linear-gradient(var(--accent), var(--line2) 22%); }
.tl-item { position: relative; padding: 0 0 40px 42px; }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: 0; top: 6px; width: 11px; height: 11px; border-radius: 50%; background: var(--bg); border: 1px solid var(--line2); }
.is-current .tl-dot { background: var(--accent); border-color: var(--accent); }
.is-current .tl-dot::after { content: ""; position: absolute; inset: -1px; border-radius: 50%; border: 1px solid var(--accent); opacity: 0; }
/* Pulses twice when it comes into view (4.8 s, under the 5 s limit of WCAG 2.2.2), then stays still. */
.is-current.is-seen .tl-dot::after { animation: ring 2.4s ease-out 2; }
.tl-details { max-width: 62ch; }
/* The summary holds the h3 and phrasing content only (HTML rule), so it is a grid: the heading comes first in the HTML,
   the date line is shown above it, and the chevron sits in its own column. */
.tl-summary {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "when chev" "org chev" "role chev";
  column-gap: 16px; align-items: start; list-style: none; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
/* An item with no text is not a disclosure: plain divs, no chevron. The editor canvas uses plain divs too. */
div.tl-summary { cursor: default; }
.tl-summary::-webkit-details-marker { display: none; }
.tl-summary::marker { content: ""; }
/* The same accent ring as everywhere (global :focus-visible), a little further out so it does not touch the text. */
.tl-summary:focus-visible { outline-offset: 6px; border-radius: 10px; }
.tl-meta { grid-area: when; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: 22px; margin: 0 0 4px; }
.tl-when { font: 400 .8125rem/1.4 var(--font-mono); color: var(--muted); }
.tl-org { grid-area: org; margin: 0; font: 600 1.375rem/1.25 var(--font-display); letter-spacing: -.012em; overflow-wrap: anywhere; }
.tl-role { grid-area: role; margin: 3px 0 0; color: var(--accent); font-size: 1rem; font-weight: 500; overflow-wrap: anywhere; }
.tl-chev { grid-area: chev; align-self: center; width: 24px; height: 24px; color: var(--muted); }
.tl-details[open] > .tl-summary .tl-chev { transform: rotate(180deg); }
.tl-text { margin: 0; padding-top: 12px; color: var(--muted); }
/* Type chips: mono pills. Neutral by default, accent for the current role. Real text, so screen readers read them. */
.tl-chip {
  display: inline-flex; align-items: center; padding: 1px 9px; border: 1px solid var(--line2); border-radius: 999px;
  background: var(--chip); color: color-mix(in srgb, var(--muted) 80%, var(--text));
  font: 500 .75rem/1.4 var(--font-mono); white-space: nowrap;
}
.tl-chip.is-accent {
  background: color-mix(in srgb, var(--accent) 11%, var(--bg)); border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  color: color-mix(in srgb, var(--accent) 85%, var(--text));
}
@media (hover: hover) and (pointer: fine) {
  .tl-summary:hover .tl-chev { color: var(--text); }
}
@media (pointer: coarse) {
  .tl-summary { min-height: 44px; }
}
@media screen and (prefers-reduced-motion: no-preference) {
  .tl-chev { transition: transform .2s var(--ease-out), color .15s ease; }
  /* Height animation is an extra for browsers that can animate to auto. Others open and close instantly. */
  @supports (interpolate-size: allow-keywords) and selector(::details-content) {
    .tl-details { interpolate-size: allow-keywords; }
    .tl-details::details-content {
      block-size: 0; overflow-y: clip; opacity: 0;
      transition: block-size .24s var(--ease-out), opacity .2s ease-out, content-visibility .24s allow-discrete;
    }
    .tl-details[open]::details-content { block-size: auto; opacity: 1; }
  }
  /* The line fills as you scroll. No JavaScript, so it follows the entries when they open and close. The track stays a hairline.
     The accent fill grows from the top until the end of the list reaches the middle of the screen, and each dot lights when the
     fill gets to it. It is decoration (pseudo-elements only). Where animation-timeline is not supported, with reduced motion
     and in print, the static line above stays. */
  @supports (animation-timeline: view()) {
    /* The inset is 0, so the page scroll-padding for the sticky header does not move the range. */
    .timeline { isolation: isolate; view-timeline: --tl block; view-timeline-inset: 0; }
    .timeline::before { z-index: -2; background: var(--line2); }
    .timeline::after {
      content: ""; position: absolute; z-index: -1; left: 5px; top: 12px; bottom: 12px; width: 1px; background: var(--accent);
      transform-origin: top; animation: tl-fill linear both; animation-timeline: --tl; animation-range: cover 50vh cover calc(100% - 50vh);
    }
    .tl-item:not(.is-current) .tl-dot::before {
      content: ""; position: absolute; inset: -1px; border-radius: 50%; background: var(--accent);
      opacity: 0; animation: tl-dot-on linear both; animation-timeline: view(block 0); animation-range: cover 50vh cover calc(50vh + 24px);
    }
    @keyframes tl-fill { from { transform: scaleY(0); } to { transform: scaleY(1); } }
    @keyframes tl-dot-on { from { opacity: 0; } to { opacity: 1; } }
  }
}

/* Selected work (enaloo/work-tiles, work-list, link-cards) */
.work-major { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 3vw, 32px); margin-top: 56px; }
.tile {
  display: flex; flex-direction: column; padding: 28px 28px 30px;
  border: 1px solid var(--line); border-radius: 20px; background: var(--bg2);
}
.tile-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tile-icon { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 13px; background: var(--accent-soft); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); }
.tile-cat { font: 400 .8125rem/1.4 var(--font-mono); color: var(--muted); }
.tile h3 { margin: 0 0 8px; padding-top: 40px; font: 600 1.5rem/1.18 var(--font-display); letter-spacing: -.018em; }
.tile p { margin: 0; color: var(--muted); font-size: 1rem; }
.lineage { display: flex; flex-wrap: wrap; align-items: center; row-gap: 8px; margin-top: auto; padding-top: 22px; font: 400 .8125rem/1 var(--font-mono); color: var(--muted); }
/* Desktop: titles and text line up across the three tiles */
@media (min-width: 961px) {
  .work-major { grid-template-rows: auto auto 1fr auto; row-gap: 0; }
  .tile { display: grid; grid-row: span 4; grid-template-rows: subgrid; row-gap: 0; }
}
.lineage span { padding: 6px 10px; border: 1px solid var(--line2); border-radius: 999px; white-space: nowrap; }
.lineage span:last-child { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.lineage i { flex: 1 1 auto; min-width: 10px; height: 1px; background: var(--line2); }
.work-minor { list-style: none; margin: 16px 0 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border: 1px solid var(--line); border-radius: 20px; }
.minor { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 16px; padding: 26px 26px 28px; }
.minor + .minor { border-left: 1px solid var(--line); }
.minor-icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 11px; border: 1px solid var(--line); color: var(--muted); }
/* Icon sizes per place, so any icon works in any block. */
.tile-icon svg, .topic-icon svg { width: 24px; height: 24px; }
.minor-icon svg { width: 20px; height: 20px; }
.minor h3 { margin: 2px 0 6px; font: 600 1.1875rem/1.25 var(--font-display); letter-spacing: -.01em; }
.minor p { margin: 0; color: var(--muted); font-size: 1rem; }
.minor .tile-cat { display: block; margin-top: 12px; }
.ext-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 16px; margin: 80px 0 22px; }
.ext-tag { margin: 0; font: 400 .8125rem/1.4 var(--font-mono); color: var(--muted); }
.ext-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(16px, 3vw, 32px); }
/* The card is the li. The main link (a.ext-link) is stretched over the whole card with its ::after. The extra links
   (span.ext-links > a.ext-alt: GitHub, and later the Edge and Firefox stores) sit in a row under it, above the stretched link.
   Links are never nested. */
.ext {
  position: relative; display: flex; flex-direction: column; padding: 24px 24px 22px; border-radius: 16px;
  border: 1px solid var(--line); color: var(--text);
  transition: border-color .2s ease, background-color .2s ease;
}
.ext:hover { border-color: var(--accent); background: var(--ext-hover); }
.ext-link { flex: 1; display: flex; flex-direction: column; color: inherit; text-decoration: none; }
a.ext-link::after { content: ""; position: absolute; inset: -1px; border-radius: 16px; }
/* The ring is drawn on the stretched ::after, 3px outside the card. */
a.ext-link:focus-visible { outline: 0; }
a.ext-link:focus-visible::after { outline: 2px solid var(--accent); outline-offset: 3px; }
.ext-name { font: 600 1.1875rem/1.25 var(--font-display); letter-spacing: -.01em; }
.ext-desc { flex: 1; margin-top: 6px; color: var(--muted); font-size: 1rem; }
.ext-langs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; }
.ext-lang { padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); font: 400 .75rem/1.4 var(--font-mono); }
.ext-go { display: inline-flex; align-items: center; gap: 6px; margin-top: 22px; font: 400 .8125rem/1 var(--font-mono); color: var(--accent); }
.ext-go svg, .ext-alt svg { transition: transform .2s ease; }
.ext:hover:not(:has(.ext-alt:hover)) .ext-go svg, .ext-alt:hover svg { transform: translate(2px, -2px); }
/* The row wraps, so four links fit at 320px. Each link is 26px high with a mouse and 44px on touch screens (the padding is pulled back
   with a negative margin, so the text keeps its place). */
.ext-links { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 0 20px; margin: 4px 0 -6px; }
.ext-alt {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 0;
  font: 400 .8125rem/1 var(--font-mono); color: var(--accent); text-decoration: none;
}
.ext-alt:hover { text-decoration: underline; text-underline-offset: 3px; }
@media (pointer: coarse) {
  .ext-links { margin-bottom: -15px; }
  .ext-alt { padding: 15px 0; }
}
@media (max-width: 960px) {
  .work-major, .work-minor, .ext-list { grid-template-columns: minmax(0, 1fr); }
  .tile h3 { padding-top: 32px; }
  .minor + .minor { border-left: 0; border-top: 1px solid var(--line); }
}

/* Research (enaloo/topics, core/list "tools") */
.research-lead { margin: 0; max-width: 34ch; font-size: clamp(1.25rem, 2vw, 1.4375rem); font-weight: 300; line-height: 1.5; }
.topics { list-style: none; margin: 40px 0 0; padding: 0; border: 1px solid var(--line); border-radius: 20px; background: var(--bg2); }
.topic { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 18px; padding: 20px 24px; }
.topic + .topic { border-top: 1px solid var(--line); }
.topic-icon { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 13px; color: var(--cipher); background: color-mix(in srgb, var(--cipher) 10%, transparent); }
.topic-name { font-size: 1.125rem; font-weight: 500; overflow-wrap: anywhere; }
.topic-code { padding: 5px 10px; border-radius: 999px; font: 500 .8125rem/1 var(--font-mono); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
@media (max-width: 480px) {
  .topic { grid-template-columns: auto minmax(0, 1fr); row-gap: 8px; }
  .topic-code { grid-column: 2; justify-self: start; }
}
.tools { list-style: none; margin: 28px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.tools li { margin: 0; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font: 400 .8125rem/1.2 var(--font-mono); color: var(--muted); }

/* Contact (enaloo/section "free" with the contact-intro group, enaloo/contact-form) */
.contact { padding-bottom: clamp(84px, 11vw, 144px); }
.contact-intro { grid-column: 1 / span 5; }
.contact-form { grid-column: 7 / -1; min-width: 0; }
.big { margin: 0; font: 600 clamp(2.875rem, 6.4vw, 5rem)/1 var(--font-display); letter-spacing: -.038em; }
.contact-text { margin: 22px 0 30px; max-width: 36ch; color: var(--muted); font-size: 1.125rem; }
.form, .form-done { display: grid; gap: 18px; padding: clamp(22px, 3vw, 32px); border: 1px solid var(--line); border-radius: 20px; background: var(--bg2); }
.field { display: grid; gap: 8px; }
.field label { font-size: .9375rem; font-weight: 500; }
.input {
  width: 100%; min-height: 48px; padding: 12px 14px; border-radius: 10px; border: 1px solid var(--field-line);
  background: var(--bg); color: var(--text); font: inherit; font-size: 1rem; line-height: 1.4;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.input:hover { border-color: color-mix(in srgb, var(--text) 40%, var(--field-line)); }
.input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), 0 0 0 4px var(--accent-soft); }
.input[aria-invalid="true"] { border-color: var(--danger); }
textarea.input { min-height: 150px; resize: vertical; }
.field-error { margin: 0; color: var(--danger); font-size: .875rem; }
/* The form level error has both classes (.field-error .form-error). Like the done heading, it takes focus from the script after a failed send. */
.form-error:focus { outline: none; }
.form-note { margin: 0; color: var(--muted); font-size: .875rem; }
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.form-done { place-items: start; }
.form-done h3:focus { outline: none; }
@media (min-width: 961px) {
  .form .btn-primary { justify-self: start; padding-inline: 28px; }
}
.done-icon { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); }
.form-done h3 { margin: 4px 0 0; font: 600 1.5rem/1.2 var(--font-display); }
.form-done p { margin: 0; color: var(--muted); }
@media (max-width: 960px) {
  .contact-intro, .contact-form { grid-column: 1 / -1; }
  .contact-form { margin-top: 40px; }
}

/* ---------- Footer (template part "footer": footer.wp-block-template-part.site-footer) ---------- */
.site-footer { border-top: 1px solid var(--line); }
.footer-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 24px; padding-block: 18px; font: 400 .8125rem/1.5 var(--font-mono); color: var(--muted); }
.footer-row p { margin: 0; }
.footer-links { display: flex; flex-wrap: wrap; align-items: center; gap: 0 20px; margin: 0; padding: 0; list-style: none; }
/* The privacy policy link sits in a paragraph block: no extra line box around the 44px link. */
.footer-links li > p { display: flex; }
/* Without JavaScript the privacy settings button is hidden: its list item goes too. */
html:not(.js) .footer-links li:has([data-consent-open]) { display: none; }
.footer-links a, .link-btn {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: var(--muted); text-decoration: underline; text-decoration-color: var(--line2); text-underline-offset: 4px;
}
.footer-links a:hover, .link-btn:hover { color: var(--text); text-decoration-color: currentColor; }
html:not(.js) [data-consent-open] { display: none; }
@media (max-width: 760px) {
  .footer-row { flex-direction: column; align-items: flex-start; }
}

/* Analytics consent banner (enaloo core, printed on wp_body_open): a labelled region, not a modal.
   It sits under the header layer (z-index 30), so the open mobile menu paints over it.
   It is never taller than the space below the header; long content scrolls inside it. */
.consent {
  position: fixed; z-index: 25; left: clamp(16px, 4vw, 32px); bottom: clamp(16px, 3vw, 24px); width: min(420px, calc(100% - 32px));
  max-height: calc(100dvh - var(--header-h) - 2 * clamp(16px, 3vw, 24px)); overflow-y: auto; overscroll-behavior: contain;
  padding: 20px 22px 22px; border: 1px solid var(--line2); border-radius: 16px; background: var(--bg2); color: var(--text);
  box-shadow: 0 24px 60px -24px rgba(14, 18, 22, .45), 0 2px 6px rgba(14, 18, 22, .06);
}
.consent-title { margin: 0; font: 600 1.125rem/1.3 var(--font-display); letter-spacing: -.01em; }
.consent-text { margin: 8px 0 0; color: var(--muted); font-size: .9375rem; line-height: 1.5; }
.consent-link { display: inline-block; margin-top: 8px; font-size: .9375rem; }
@media (pointer: coarse) {
  .consent-link { display: inline-flex; align-items: center; min-height: 44px; margin-top: 0; }
}
.consent-actions { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 10px; margin-top: 18px; }
.consent-actions .btn { padding: 0 16px; }
html.consent-open { scroll-padding-bottom: calc(var(--consent-h, 0px) + 32px); }
html.consent-open body { padding-bottom: calc(var(--consent-h, 0px) + 32px); }
@media (max-width: 480px) {
  .consent { left: 16px; right: 16px; width: auto; bottom: 16px; }
}
/* Short screens (landscape, 200% zoom): the banner joins the page flow at the top, so it never covers the page. */
@media (max-height: 500px) {
  .consent { position: static; width: auto; max-height: none; overflow: visible; margin: 16px clamp(16px, 4vw, 32px) 0; box-shadow: none; }
  html.consent-open { scroll-padding-bottom: 0; }
  html.consent-open body { padding-bottom: 0; }
}

/* ---------- Plain views: pages (page.html), the fallback list (index.html) and the 404 page ----------
   A page is one home style section: the title in columns 1 to 4 (sticky on desktop), the text in 5 to 12. */
.page-section { padding-block: clamp(48px, 8vw, 112px) clamp(84px, 11vw, 144px); }
.page-title { overflow-wrap: anywhere; }
.page-content { font-size: 1.125rem; line-height: 1.7; }
.page-content > * { margin-block: 0; }
.page-content > * + * { margin-top: 1.1em; }
.page-content > :where(p, ul, ol, h2, h3, h4, blockquote, dl, .wp-block-buttons) { max-width: 36em; }
.page-content > :first-child { margin-top: 0; }
.page-content h2 { margin-top: 2em; font: 600 clamp(1.625rem, 2.6vw, 2rem)/1.2 var(--font-display); letter-spacing: -.02em; }
.page-content h3 { margin-top: 1.7em; font: 600 1.375rem/1.25 var(--font-display); letter-spacing: -.012em; }
.page-content h4 { margin-top: 1.6em; font: 600 1.125rem/1.3 var(--font-display); }
.page-content :is(h2, h3, h4) + * { margin-top: .6em; }
.page-content a:where(:not(.wp-block-button__link)) {
  color: var(--text); text-decoration-line: underline; text-decoration-color: var(--accent);
  text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.page-content a:where(:not(.wp-block-button__link)):hover { text-decoration-thickness: 2px; }
.page-content :is(ul, ol) { padding-left: 1.4em; }
.page-content li + li { margin-top: .4em; }
.page-content li::marker { color: var(--muted); }
.page-content strong { font-weight: 600; }
.page-content :not(pre) > code {
  padding: .1em .35em; border: 1px solid var(--line); border-radius: 6px; background: var(--chip);
  font: 400 .85em/1.4 var(--font-mono); overflow-wrap: anywhere;
}
.page-content pre {
  overflow-x: auto; padding: 18px 20px; border: 1px solid var(--panel-line); border-radius: 16px;
  background: var(--panel); color: var(--panel-text); font: 400 .875rem/1.7 var(--font-mono);
}
.page-content blockquote { margin-inline: 0; padding-left: 20px; border-left: 1px solid var(--line2); }
.page-content blockquote p { font-size: 1.25rem; font-weight: 300; line-height: 1.5; }
.page-content hr { height: 0; border: 0; border-top: 1px solid var(--line); }
.page-content img, .page-content video { max-width: 100%; height: auto; }
.page-content figure { margin-inline: 0; }
.page-content figcaption { margin-top: 10px; color: var(--muted); font-size: .9375rem; }
.page-content table { width: 100%; border-collapse: collapse; font-size: 1rem; }
.page-content :is(th, td) { padding: 10px 12px 10px 0; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.page-content th { font: 500 .8125rem/1.4 var(--font-mono); color: var(--muted); }
.page-content .wp-block-table { overflow-x: auto; }

/* index.html: the fallback list of posts */
.index-list { list-style: none; margin: 0; padding: 0; }
.index-list > li { margin: 0; padding-block: 28px; border-top: 1px solid var(--line); }
.index-list > li:first-child { padding-top: 0; border-top: 0; }
.index-title { margin: 0; font: 600 1.5rem/1.2 var(--font-display); letter-spacing: -.015em; overflow-wrap: anywhere; }
.index-title a { color: var(--text); text-decoration-color: var(--accent); text-decoration-thickness: 1px; }
.index-excerpt { margin-top: 8px; max-width: 36em; color: var(--muted); }
.index-excerpt p { margin: 0; }
.index-empty { margin: 0; color: var(--muted); }
.index-pager { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; margin-top: 40px; font: 400 .8125rem/1.4 var(--font-mono); }
.index-pager a, .index-pager .page-numbers { display: inline-flex; align-items: center; min-height: 44px; color: var(--text); }
.index-pager .current { color: var(--accent); }

/* 404.html */
.not-found { padding-block: clamp(48px, 8vw, 112px) clamp(84px, 11vw, 144px); }
.not-found .big { max-width: 14ch; }
.nf-text { margin: 22px 0 0; max-width: 36ch; color: var(--muted); font-size: 1.125rem; }

/* ---------- One orchestrated page-load moment ---------- */
@media (prefers-reduced-motion: no-preference) {
  .js .hero-copy > * { opacity: 0; transform: translateY(14px); animation: rise .8s cubic-bezier(.2, .7, .2, 1) forwards; }
  .js .hero-copy > :nth-child(2) { animation-delay: .08s; }
  .js .hero-copy > :nth-child(3) { animation-delay: .16s; }
  .js .hero-copy > :nth-child(4) { animation-delay: .22s; }
  .js .hero-copy > :nth-child(5) { animation-delay: .28s; }
  .js .inspector { opacity: 0; transform: translateY(20px) scale(.985); animation: rise 1s cubic-bezier(.2, .7, .2, 1) .3s forwards; }
}
@keyframes rise { to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .live-dot::after, .is-current .tl-dot::after { display: none; }
  /* The timeline chevron and the open and close do not animate at all. */
  .tl-chev { transition: none; }
}

/* ---------- Windows High Contrast (forced colors) ---------- */
@media (forced-colors: active) {
  .hero::before, .hero::after { display: none; }
  .site-header { background: Canvas; -webkit-backdrop-filter: none; backdrop-filter: none; }
  /* Selected segment: a Highlight fill. Keyboard focus: a separate ring, so the two never look the same. */
  .theme-switch label:has(input:checked) { forced-color-adjust: none; background: Highlight; color: HighlightText; outline: 0; }
  .theme-switch label:has(input:focus-visible) { outline: 2px solid CanvasText; outline-offset: 1px; }
  .input:focus { outline: 2px solid Highlight; outline-offset: 2px; }
  .nav-links a[aria-current="true"]::before, .nav-links a[aria-current="page"]::before { forced-color-adjust: none; background: Highlight; }
  .pipeline::before, .pipeline::after, .pipe-packet, .node, .timeline::before, .timeline::after, .tl-dot, .lineage i,
  .live-dot, .wire-track::before, .pkt { forced-color-adjust: none; }
  .pipeline::before, .timeline::before, .lineage i, .wire-track::before { background: GrayText; }
  /* Extension cards: the focus ring of the stretched main link uses a system color. */
  a.ext-link:focus-visible::after { outline-color: Highlight; }
  .pipeline::after, .pipe-packet, .live-dot, .pkt, .pkt.out, .timeline::after { background: Highlight; box-shadow: none; }
  .tl-item:not(.is-current) .tl-dot::before { background: Highlight; }
  .node, .tl-dot { background: Canvas; border-color: CanvasText; box-shadow: none; }
  .step.lit .node, .is-current .tl-dot { background: Highlight; border-color: Highlight; }
  .js .step:not(.lit) .node { background: Canvas; border-color: GrayText; }
  .is-current .tl-dot::after { border-color: Highlight; }
  .btn-primary, .wp-block-button > .wp-block-button__link { border: 1px solid; }
  /* Timeline disclosure: the chevron follows the text color, the chips keep their border, and the focus ring is a system color. */
  .tl-chev { color: CanvasText; }
  .tl-summary:focus-visible { outline-color: Highlight; }
  .stat-num.is-counting { color: CanvasText; }
  .stat-num.is-counting::after { content: none; }
}

@media print {
  /* Paper is white in every theme: browsers drop backgrounds in print, so dark theme text would print faint. */
  :root, :root:not([data-theme="light"]), :root[data-theme="dark"] {
    --wp--preset--color--bg: #FFFFFF; --wp--preset--color--bg-2: #FFFFFF; --wp--preset--color--line: #CBD2D9; --wp--preset--color--line-2: #9AA4AE;
    --wp--preset--color--field-line: #7F8A95; --wp--preset--color--seg: #FFFFFF; --wp--preset--color--text: #0E1216; --wp--preset--color--muted: #4A545E;
    --wp--preset--color--accent: #077A50; --wp--preset--color--accent-ink: #FFFFFF; --wp--preset--color--accent-soft: transparent; --wp--preset--color--cipher: #5B4BC4;
    --wp--preset--color--danger: #B42318; --wp--preset--color--chip: #FFFFFF; --wp--preset--color--grid: transparent; --wp--preset--color--glow: transparent;
    --panel: #FFFFFF; --panel2: #FFFFFF; --panel-line: #CBD2D9; --panel-text: #0E1216; --panel-muted: #4A545E; --panel-accent: var(--accent); --panel-cipher: #5B4BC4; --panel-shadow: none;
    color-scheme: light;
  }
  .site-header { position: static; }
  .consent, .theme-switch, .menu-btn, .insp-pause, .skip, .plugin-note { display: none !important; }
  .btn-primary, .wp-block-button:not(.is-style-outline):not(.is-style-ghost) > .wp-block-button__link { background: none; color: var(--text); border: 1px solid var(--line2); }
  .stat-num.is-counting { color: inherit; }
  .stat-num.is-counting::after { content: none; }
  /* Keep each block, and each heading with its content, on one page. */
  .stat, .step, .tl-item, .tile, .minor, .ext, .topic, .inspector, .form { break-inside: avoid; }
  .sec-grid { display: block; }
  .sec-head, .ext-head { break-after: avoid; }
  /* Every timeline item prints open. The script also opens them on beforeprint; the next rule covers a page without it. */
  .tl-chev { display: none; }
  /* The scroll fill is for the screen. Print keeps the static line. */
  .timeline::after, .tl-dot::before { display: none; }
}
@media print {
  .tl-details::details-content { content-visibility: visible; block-size: auto; opacity: 1; transition: none; }
}

/* Theme switch reveal */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

/* ---------- Editor only ----------
   The editor canvas has no "js" class on html, so it shows the static state. The theme switch
   needs JavaScript on the front end, but it stays visible in the editor, so it can be selected. */
.theme-switch.wp-block.block-editor-block-list__block { display: inline-flex; }
/* Rich text keeps white space in the editor (pre-wrap), so the space between the two name lines
   would add an empty line. In a flex column a white space only text run is not rendered. */
.name.block-editor-rich-text__editable { display: flex; flex-direction: column; }
/* The scroll driven timeline line is for the front end: the canvas keeps the static line and no lit dots. */
.editor-styles-wrapper .timeline { isolation: auto; }
.editor-styles-wrapper .timeline::before { z-index: auto; background: linear-gradient(var(--accent), var(--line2) 22%); }
.editor-styles-wrapper .timeline::after, .editor-styles-wrapper .tl-dot::before { display: none; }
