/*
 * vCloud Vision — base styles.
 * Design system "Altitude / Clear Sky" (HANDOFF.md §4).
 *
 * Loaded after vcv-tokens.css. Every value here comes from a --vcv-* token;
 * raw hex belongs in vcv-tokens.css and nowhere else.
 *
 * Build step 2 of HANDOFF §11: base only. Components land in later steps.
 */

/* ==========================================================================
   Neve bridge
   Neve draws its own base styles from --bodyfontfamily / --bodyfontsize /
   --h1fontsize and friends, generated from Customizer values
   (neve/inc/core/styles/css_vars.php). Pointing those at our tokens means
   Neve's own buttons, forms and widgets follow the design system instead of
   having to be overridden one by one.
   Colour equivalents are already bridged at the bottom of vcv-tokens.css.

   `html:root` rather than `:root` for the same reason as that bridge: Neve emits
   its own `:root{...}` block, and in the Customizer preview it prints after our
   stylesheet, so an equal-specificity selector here loses on source order.
   ========================================================================== */
html:root {
  --bodyfontfamily: var(--vcv-font-body);
  --headingsfontfamily: var(--vcv-font-heading);
  --nv-fallback-ff: system-ui, sans-serif;

  --bodyfontsize: var(--vcv-text-body);
  --bodylineheight: var(--vcv-leading-body);
  --bodyfontweight: var(--vcv-weight-regular);
  --bodyletterspacing: normal;
  --bodytexttransform: none;

  --h1fontsize: var(--vcv-text-h1);
  --h2fontsize: var(--vcv-text-h2);
  --h3fontsize: var(--vcv-text-h3);
  --h4fontsize: var(--vcv-text-h4);
  --h1lineheight: var(--vcv-leading-h1);
  --h2lineheight: var(--vcv-leading-h2);
  --h3lineheight: var(--vcv-leading-h3);
  --h4lineheight: var(--vcv-leading-h4);

  /* Buttons. Neve styles every bare <button> with these, and its defaults are
     background var(--nv-primary-accent) with text hard-coded to #fff — white on
     our accent is about 1.9:1, far under the 4.5 minimum. Any button Neve renders
     that this theme does not style itself would be unreadable, so point them at
     the tokens the same way as everything else (HANDOFF §5.26). */
  --primarybtnbg: var(--vcv-color-accent);
  --primarybtncolor: var(--vcv-color-on-accent);
  --primarybtnhoverbg: var(--vcv-color-accent-hover);
  --primarybtnhovercolor: var(--vcv-color-on-accent);
  --primarybtnborderradius: var(--vcv-radius-md);
  --secondarybtnbg: transparent;
  --secondarybtncolor: var(--vcv-color-text);
  --secondarybtnhoverbg: var(--vcv-color-surface-hover);
  --secondarybtnhovercolor: var(--vcv-color-text);
  --secondarybtnborderradius: var(--vcv-radius-md);
}

/* ==========================================================================
   Document
   ========================================================================== */

/* The sticky header must never cover an element scrolled to by anchor or focus
   (WCAG 2.2 §2.4.11). HANDOFF §8. */
html {
  scroll-padding-top: calc(var(--vcv-header-height) + 16px);
}

body {
  background-color: var(--vcv-color-bg);
  color: var(--vcv-color-text);
  font-family: var(--vcv-font-body);
  font-size: var(--vcv-text-body);
  line-height: var(--vcv-leading-body);
  font-weight: var(--vcv-weight-regular);
  letter-spacing: normal;
  text-transform: none;
}

/* Antialiasing only in dark mode: it thins glyphs, which helps light-on-dark
   and hurts dark-on-light. HANDOFF §4. */
:root:not([data-theme="light"]) body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

[data-theme="light"] body {
  -webkit-font-smoothing: auto;
  -moz-osx-font-smoothing: auto;
}

::selection {
  background: var(--vcv-color-selection);
}

/* One focus treatment for everything interactive. Never remove it without a
   replacement. HANDOFF §3.6. */
:focus-visible {
  outline: var(--vcv-focus-ring);
  outline-offset: var(--vcv-focus-offset);
}

/* ==========================================================================
   Headings
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--vcv-font-heading);
  color: var(--vcv-color-text);
  font-weight: var(--vcv-weight-heading);
}

h1, h2, h3 {
  text-wrap: balance;
}

h1 { font-size: var(--vcv-text-h1); line-height: var(--vcv-leading-h1); letter-spacing: var(--vcv-tracking-h1); }
h2 { font-size: var(--vcv-text-h2); line-height: var(--vcv-leading-h2); letter-spacing: var(--vcv-tracking-h2); }
h3 { font-size: var(--vcv-text-h3); line-height: var(--vcv-leading-h3); letter-spacing: var(--vcv-tracking-h3); font-weight: var(--vcv-weight-bold); }
h4 { font-size: var(--vcv-text-h4); line-height: var(--vcv-leading-h4); letter-spacing: var(--vcv-tracking-h4); font-weight: var(--vcv-weight-bold); }
h5, h6 { font-size: var(--vcv-text-body); line-height: var(--vcv-leading-h4); font-weight: var(--vcv-weight-bold); }

/* Anchor jumps land below the sticky header. */
.entry-content h2,
.entry-content h3 {
  scroll-margin-top: calc(var(--vcv-header-height) + 24px);
}

/* ==========================================================================
   Links
   Underlined always — in body text, colour alone is never the only signal.
   HANDOFF §4.
   ========================================================================== */

a {
  color: var(--vcv-color-link);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--vcv-color-link-hover);
  text-decoration-thickness: 2px;
}

/* ==========================================================================
   Post and page content
   Flow model: every direct child gets its space from the element above it, so
   margins never collapse unpredictably and no element carries a trailing gap.
   Neve sets `p { margin-bottom: 30px }` and `h1-h6 { margin-bottom: 30px }`
   (neve/style-main-new.css:291-304), which this replaces.
   ========================================================================== */

.entry-content > * {
  margin-block: 0;
}

.entry-content > * + * {
  margin-block-start: var(--vcv-flow);
}

.entry-content > h2 {
  margin-block-start: var(--vcv-flow-h2);
}

.entry-content > h3,
.entry-content > h4 {
  margin-block-start: var(--vcv-flow-h3);
}

.entry-content > figure,
.entry-content > pre,
.entry-content > table,
.entry-content > .wp-block-table,
.entry-content > .wp-block-image,
.entry-content > .enlighter-default {
  margin-block: var(--vcv-flow-block);
}

/* A heading that opens the content needs no space above it. */
.entry-content > :first-child {
  margin-block-start: 0;
}

/* Optimal line length for reading. Headings, code and figures keep the full
   column width; running text does not. HANDOFF §4. */
.entry-content > p,
.entry-content > ul,
.entry-content > ol {
  max-width: var(--vcv-measure);
}

.entry-content strong,
.entry-content b {
  font-weight: var(--vcv-weight-bold);
}

.entry-content ul { padding-left: 1.4em; list-style: disc; }
.entry-content ol { padding-left: 1.6em; }
.entry-content li + li { margin-top: 0.375em; }
.entry-content li::marker { color: var(--vcv-color-accent); }
.entry-content ol > li::marker { font-weight: var(--vcv-weight-bold); }

.entry-content hr,
.wp-block-separator {
  border: 0;
  border-top: 1px solid var(--vcv-color-border);
  margin: var(--vcv-space-7) 0;
}

img {
  max-width: 100%;
  height: auto;
}

/* Long hostnames and paths must not overflow on a phone. */
.entry-content {
  overflow-wrap: break-word;
}

/* ==========================================================================
   Inline code and kbd (HANDOFF §5.13)
   Block-level code is Enlighter's and is styled in step 4.
   ========================================================================== */

.entry-content :not(pre) > code {
  font-family: var(--vcv-font-mono);
  font-size: var(--vcv-text-code-inline);
  background: var(--vcv-color-inline-code-bg);
  color: var(--vcv-color-text);
  padding: 0.1em 0.35em;
  border-radius: var(--vcv-radius-xs);
  overflow-wrap: anywhere;
}

kbd {
  font-family: var(--vcv-font-mono);
  font-size: 0.8em;
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--vcv-radius-xs);
  padding: 0.1em 0.45em;
}

/* ==========================================================================
   Single post — layout (HANDOFF §6.2)

   Neve's wrappers are kept so plugins keep finding them; only their geometry is
   replaced. The chain is
     .container.single-post-container > .row > article.nv-single-post-wrap.col
   with `.container { padding: 0 15px }`, `.row { margin: 0 -15px }` and
   `.col { padding: 0 15px; margin: 0 auto }` (neve/style-main-new.css:239-270).
   The two 15px offsets cancel, so the row is exactly the container's width and
   the article can be given the design's own 1280 + gutter box, lining it up
   with the header and footer.

   Two layout modes:
     .vcv-single             one reading column, centred, 720px.
     .vcv-single--has-toc    adds the sticky TOC column at ≥1280 (see below).
   The class is added in inc/single.php via post_class.
   ========================================================================== */

/* `html:root` so this beats Neve's own `.neve-main > .single-post-container
   .nv-single-post-wrap.col { max-width: N% }` (inc/core/styles/frontend.php)
   on specificity rather than on load order — see the bridge note in
   vcv-tokens.css for why order cannot be relied on here. */
html:root .single-post-container .nv-single-post-wrap.col,
html:root .single-page-container .nv-single-page-wrap.col {
  max-width: var(--vcv-width-container);
  padding-inline: var(--vcv-gutter);
  margin-inline: auto;

  /* The article is a flex item of Neve's `.row`. Neve caps it with
     `max-width: 100%`; raising that cap to 1280 removes the only thing that was
     stopping `flex-basis: auto` from sizing it to its *content*. A version
     matrix carries `min-width: 560px` and code blocks are `white-space: pre`,
     so on a phone the article grew past the viewport and the content was
     silently clipped by the `overflow: clip` that protects the header.
     `flex-basis: 100%` plus `min-width: 0` makes it fill the row and shrink
     with it instead. Measured at 390px: article 390, content 358. */
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
}

/* Neve spaces the article's children with a 60px first-child margin and a
   `--spacing` bottom margin on every div (style-main-new.css:1527-1535). The
   design owns this rhythm instead. */
html:root .vcv-single > div:first-child,
html:root .vcv-single > div:not(:last-child),
html:root .vcv-single > div:last-child,
html:root .nv-single-page-wrap > div:first-child,
html:root .nv-single-page-wrap > div:not(:last-child) {
  margin-top: 0;
  margin-bottom: 0;
  padding-bottom: 0;
}

html:root .vcv-single {
  margin-bottom: 0;
  padding-block: var(--vcv-space-6) var(--vcv-space-section);
}

/* Everything in the post is a direct child of the article, so one rule sets the
   reading measure for the header, the TOC fallback, the body and every
   end-of-post component. */
.vcv-single > * {
  max-width: var(--vcv-width-content);
  margin-inline: auto;
}

.vcv-single > * + * {
  margin-block-start: var(--vcv-space-6);
}

/* The body is the one child that is NOT capped at the reading column: its own
   children are. That is what lets a wide block inside it reach the full
   container while the running text around it stays at 720 — at tablet widths
   "wide elements go up to 100% of the container", and on a desktop post with no
   TOC alignwide is centred at up to 1100 (HANDOFF §6.2). */
.vcv-single > .entry-content {
  max-width: none;
}

.vcv-single .entry-content > * {
  max-width: var(--vcv-width-content);
  margin-inline: auto;
}

/* Running text keeps the reading measure; headings, code, figures, tables and
   callouts take the full column (HANDOFF §4). This has to come after the rule
   above, which otherwise widens every paragraph to the full 720.

   `min()` of the two explicit widths, because they disagree: 70ch in Atkinson
   Hyperlegible Next at 18px measures 792px, so the measure alone would make
   running text *wider* than the 720 reading column. Not `100%` — inside the
   TOC grid the containing block is .entry-content, which spans the reading
   column *and* the wide break-out column, so 100% is 948 there and the cap
   would do nothing. */
.vcv-single .entry-content > p,
.vcv-single .entry-content > ul,
.vcv-single .entry-content > ol {
  max-width: min(var(--vcv-measure), var(--vcv-width-content));
}

/* Wide and full-width blocks. Below 1280 — and on any post without a TOC —
   they are simply centred (HANDOFF §6.2).

   `width` and the margins have to be stated, not just `max-width`: Neve sets
   `.alignwide { width: 98vw; margin-inline: calc(50% - 49vw) }`
   (style-main-new.css:525-530), which is a viewport-relative break-out this
   design does not use. Setting only max-width left Neve's 98vw in place, so a
   wide image measured 382px inside a 357px column on a phone. */
.vcv-single .entry-content > .alignwide {
  width: 100%;
  max-width: var(--vcv-width-wide);
  margin-inline: auto;
}

.vcv-single .entry-content > .alignfull {
  max-width: none;
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* ---------- Breadcrumbs (HANDOFF §5.6) ---------- */

.vcv-breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--vcv-text-small);
}

.vcv-breadcrumbs a {
  color: var(--vcv-color-text-muted);
  text-decoration: none;
}

.vcv-breadcrumbs a:hover {
  color: var(--vcv-color-text);
  text-decoration: underline;
}

.vcv-breadcrumbs__item [aria-current="page"],
.vcv-breadcrumbs__sep {
  color: var(--vcv-color-text-muted);
}

/* ---------- Post header (HANDOFF §5.10) ---------- */

.vcv-post-header {
  padding-bottom: var(--vcv-space-5);
  border-bottom: 1px solid var(--vcv-color-border);
}

/* The topic label, also used on cards and search results. */
.vcv-topic {
  display: inline-block;
  font-family: var(--vcv-font-body);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-secondary);
  text-decoration: none;
}

.vcv-topic:hover {
  color: var(--vcv-color-secondary);
  text-decoration: underline;
}

html:root .vcv-post-header__title {
  margin: var(--vcv-space-3) 0 0;
  /* Neve centres every .entry-header (style-main-new.css) — this is a reading
     layout, so it is left-aligned. */
  text-align: left;
}

.vcv-post-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-2);
  margin-top: var(--vcv-space-4);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

.vcv-post-meta__author {
  color: var(--vcv-color-text);
  font-weight: var(--vcv-weight-bold);
  text-decoration: none;
}

.vcv-post-meta__author:hover {
  color: var(--vcv-color-text);
  text-decoration: underline;
}

/* Two authors' avatars overlap by 8px (HANDOFF §5.10). */
.vcv-post-meta__authors {
  display: inline-flex;
  align-items: center;
}

.vcv-post-meta__authors .vcv-avatar + .vcv-avatar {
  margin-left: -8px;
}

.vcv-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--vcv-avatar-size, 40px);
  height: var(--vcv-avatar-size, 40px);
  flex: none;
  border-radius: var(--vcv-radius-full);
  overflow: hidden;
  background: var(--vcv-color-surface-raised);
}

.vcv-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--vcv-radius-full);
}

.vcv-avatar--initials {
  font-family: var(--vcv-font-heading);
  font-weight: var(--vcv-weight-heading);
  font-size: 0.875rem;
  color: var(--vcv-color-text);
  letter-spacing: 0;
}

/* The "Updated" pill, shown only when modified > published + 24h. */
.vcv-pill {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--vcv-radius-full);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
  font-family: var(--vcv-font-mono);
  font-size: 0.75rem;
  font-weight: var(--vcv-weight-bold);
}

/* ---------- Table of contents (HANDOFF §5.11) ---------- */

/* Below 1280 the sticky column does not exist and the <details> takes over.
   Both are always rendered; CSS picks one, so a resized window is never wrong. */
.vcv-toc { display: none; }

.vcv-toc-mobile {
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-md);
}

.vcv-toc-mobile__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--vcv-space-3);
  min-height: 48px;
  padding: 0 var(--vcv-space-4);
  cursor: pointer;
  font-weight: var(--vcv-weight-bold);
  /* The default triangle is replaced by the chevron. */
  list-style: none;
}

.vcv-toc-mobile__summary::-webkit-details-marker { display: none; }

.vcv-toc-mobile__chevron {
  flex: none;
  color: var(--vcv-color-text-muted);
  transition: transform var(--vcv-duration) var(--vcv-ease);
}

.vcv-toc-mobile[open] .vcv-toc-mobile__chevron { transform: rotate(180deg); }

.vcv-toc-mobile__list {
  margin: 0;
  padding: 0 var(--vcv-space-4) var(--vcv-space-3);
  list-style: none;
}

.vcv-toc-mobile__list .vcv-toc__link {
  display: block;
  padding: var(--vcv-space-2) 0;
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-toc-mobile__list .vcv-toc__link:hover { text-decoration: underline; }

/* Shared list styling, used by the sticky column. */
.vcv-toc__label {
  margin: 0 0 var(--vcv-space-2);
  padding-inline: var(--vcv-space-3);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-text-muted);
}

.vcv-toc__list,
.vcv-toc__sub {
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-toc__link {
  display: block;
  padding: 7px 12px;
  border-radius: var(--vcv-radius-sm);
  font-size: 0.9375rem;
  line-height: 1.35;
  color: var(--vcv-color-text-muted);
  text-decoration: none;
}

.vcv-toc__link--sub {
  padding-left: 24px;
  font-size: 0.875rem;
}

.vcv-toc__link:hover {
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
  text-decoration: none;
}

/* Set by the IntersectionObserver in vcv.js; the anchors still work without it. */
.vcv-toc__link[aria-current="location"] {
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
  font-weight: var(--vcv-weight-bold);
}

/* The ring would otherwise be clipped by the column's own overflow. */
.vcv-toc__link:focus-visible { outline-offset: -2px; }

/* ==========================================================================
   Code blocks (HANDOFF §5.12)

   One treatment for all three sources: enlighter/codeblock, core/code and
   core/preformatted, each wrapped in figure.vcv-code by inc/code.php.

   Replaces assets/css/legacy-enlighter.css, which is deleted. That file styled
   Enlighter's output in place; this styles our own frame and then neutralises
   Enlighter's theme inside it, so the two cannot disagree.

   NO ENLIGHTER PLUGIN SETTING IS CHANGED — they are site-wide and would restyle
   the live Hestia site the moment they were saved. Line numbers, the hover
   toolbar and the "break" overflow mode are all switched off here in CSS.
   ========================================================================== */

.vcv-code {
  position: relative;
  margin: var(--vcv-flow-block) 0;
  border: 1px solid var(--vcv-color-code-border);
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-color-code-bg);
  overflow: hidden;
}

/* ---------- Header bar ---------- */

.vcv-code__bar {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-2);
  min-height: 36px;
  padding: 6px 96px 6px 16px;   /* right padding clears the copy button */
  background: var(--vcv-color-code-header-bg);
  border-bottom: 1px solid var(--vcv-color-code-border);
}

.vcv-code__lang {
  font-family: var(--vcv-font-mono);
  font-size: 0.75rem;
  font-weight: var(--vcv-weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--vcv-tracking-label);
  color: var(--vcv-color-code-label);
}

.vcv-code__title {
  font-family: var(--vcv-font-mono);
  font-size: 0.75rem;
  color: var(--vcv-color-code-label);
}

.vcv-code__title::before { content: "· "; }

/* ---------- Copy button ----------
   Absolutely positioned so an untagged block (no header bar — most of the
   archive) still gets the button in the same place. */

.vcv-code__actions {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
}

.vcv-code__copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--vcv-space-1);
  /* 36px is the one place the design goes below 44 (HANDOFF §8); it keeps a
     44px minimum width through its padding, and it is not a primary target. */
  height: 36px;
  min-width: 44px;
  padding: 0 10px;
  border: 1px solid var(--vcv-color-code-button-border);
  border-radius: var(--vcv-radius-sm);
  /* Pinned, not themed. --vcv-color-code-header-bg is dark in both modes but not
     the SAME dark (#0B1626 / #13223A), so the button visibly tracked the theme on
     a code block that does not. Its own tokens keep it identical in both.
     appearance:none for the reason the footer cookie button needed it: a button
     can otherwise paint native chrome over what the stylesheet asks for. */
  appearance: none;
  -webkit-appearance: none;
  background: var(--vcv-color-code-button-bg);
  color: var(--vcv-color-code-button-text);
  font-family: var(--vcv-font-body);
  font-size: 0.8125rem;
  font-weight: var(--vcv-weight-bold);
  cursor: pointer;
}

/* Hover is the same in both modes by design (HANDOFF §5.12): the code block is
   dark in light mode too, so flipping this control with the theme put white text
   on a white background there. These two tokens deliberately do not flip. */
.vcv-code__copy:hover {
  background: var(--vcv-color-code-button-hover-bg);
  color: var(--vcv-color-code-button-hover-text);
  border-color: var(--vcv-color-border-strong);
}

.vcv-code__copy-check { display: none; }

.vcv-code__copy.is-copied {
  background: var(--vcv-color-success-bg);
  border-color: var(--vcv-color-success-border);
  color: var(--vcv-color-success);
}

.vcv-code__copy.is-copied .vcv-icon:not(.vcv-code__copy-check) { display: none; }
.vcv-code__copy.is-copied .vcv-code__copy-check { display: block; }

/* ---------- Body ---------- */

.vcv-code__body {
  padding: var(--vcv-space-4);
  overflow-x: auto;
  /* A visible scrollbar: a code block that silently cuts off is worse than one
     that shows it can be scrolled. */
  scrollbar-color: var(--vcv-color-border-strong) var(--vcv-color-code-header-bg);
  scrollbar-width: thin;
}

.vcv-code__body::-webkit-scrollbar { height: 6px; }
.vcv-code__body::-webkit-scrollbar-track { background: var(--vcv-color-code-header-bg); }
.vcv-code__body::-webkit-scrollbar-thumb {
  background: var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-full);
}

/* The scroll region is focusable, so it needs a ring that is not clipped. */
.vcv-code__body:focus-visible { outline-offset: -2px; }

/* Every renderer's code element, reset to one treatment. The !important on
   white-space is Enlighter's own: its stylesheet sets `white-space: pre-wrap`
   with !important in the default "break" overflow mode, which is a plugin-wide
   setting we are not allowed to change. */
html:root .vcv-code pre,
html:root .vcv-code code,
html:root .vcv-code .enlighter,
html:root .vcv-code .enlighter > div > div,
html:root .vcv-code .enlighter-raw {
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: var(--vcv-font-mono);
  font-size: var(--vcv-text-code);
  line-height: var(--vcv-leading-code);
  color: var(--vcv-color-code-text);
  white-space: pre !important;
  word-wrap: normal !important;
  overflow-wrap: normal;
  border-radius: 0;
}

/* core/code wraps in <code>; make it a block so padding and scrolling behave. */
html:root .vcv-code pre > code { display: block; }

/* ---------- Enlighter, neutralised inside our frame ----------
   Class names verified against Enlighter 4.7.0 / EnlighterJS 3.6.0. */

html:root .vcv-code .enlighter-default,
html:root .vcv-code .enlighter-code {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--vcv-color-code-text);
  overflow: visible;        /* our .vcv-code__body owns the scrolling */
}

/* Enlighter's own toolbar is replaced by the header bar, so it is removed
   rather than left to appear on hover over ours. */
html:root .vcv-code .enlighter-toolbar { display: none !important; }

/* No line numbers (HANDOFF §1). The gutter is a ::before on each row and the
   plugin setting that controls it is site-wide, so it is suppressed here. */
html:root .vcv-code .enlighter > div::before {
  display: none !important;
  content: none !important;
}

html:root .vcv-code .enlighter > div {
  border: 0;
  background: transparent;
  color: var(--vcv-color-code-text);
}

/* Enlighter's own theme highlights the hovered line in #fffcd3 and an
   author-highlighted line in #fdf5f0 — a yellow and a pink that are wrong on a
   dark block in both modes.

   SPECIFICITY, NOT LOAD ORDER. Enlighter's hover rule is
   `.enlighter-t-enlighter.enlighter-hover.enlighter-linenumbers div.enlighter>div:hover`
   at (0,5,2). The first version of this rule was written as
   `.vcv-code .enlighter-hover .enlighter > div:hover`, which is *also* (0,5,2) —
   a tie, decided by whichever stylesheet loads last, and Enlighter won. The
   selectors below compound `.enlighter-default` (always on the wrapper) and
   qualify `div.enlighter` to reach (0,6,3) and (0,4,3), which win outright.
   `tools/check-enlighter-specificity.py` checks this mechanically.

   The hover is kept rather than removed: it helps track a line across a wide
   log dump. Only the colour changes, to the one surface token that stays dark
   in both themes. Delete the first rule to switch it off entirely. */
html:root .vcv-code .enlighter-default.enlighter-hover div.enlighter > div:hover {
  background: var(--vcv-color-code-header-bg);
  color: inherit;
}

/* A line the author marked with data-enlighter-highlight. No post uses this
   today (all 177 blocks have it empty), but it is one attribute away. The
   --vcv-syntax-* family is the one documented as "identical in both modes, sits
   on code-bg", so it is what an accent on a code line has to come from.
   box-shadow rather than border-left: a border would shift the line's text. */
html:root .vcv-code div.enlighter > div.enlighter-special {
  background: var(--vcv-color-code-header-bg);
  box-shadow: inset 2px 0 0 var(--vcv-syntax-keyword);
}

/* ---------- Syntax (HANDOFF §5.12) ----------
   EXACT class names, never substring matching. `[class*="enlighter-t"]` also
   matches `enlighter-text`, `enlighter-toolbar` and every theme class
   (`enlighter-t-enlighter` and friends); `[class*="enlighter-c"]` matches
   `enlighter-code` and `enlighter-collapse`. Those attribute selectors carry the
   same (0,3,1) specificity as the rules above them, so they won on source order
   and repainted the code container and all of its text. The 56 token classes
   below are the full set EnlighterJS can emit, read out of its own stylesheet and
   bundle, plus x16 which the bundle emits but the stylesheet never styles.

   Families, confirmed from the bundle's own rules rather than assumed:
     k  keyword      m  method        s  string     n  number
     e  escape       c  comment       g  generic/operators
     t  type/markup  x  language-specific
   Markup tags come through as ["g1","x1","text","g1"] — the tag NAME is x1, its
   brackets are g1 — so x1 and the t-family markup tokens are keywords here.
   The diff engine maps `^(+.*)` to t5 and `^(-.*)` to t6, which is where
   --vcv-syntax-error belongs: t6 is a deleted line.

   `.enlighter-text` is a TOKEN class, not structural: the `raw` language emits
   `type:"text"` for every line. It is listed first and nothing below may shadow it.

   Correcting an earlier note in this file: the `generic` engine is not inert. It
   emits c0, e0, e1, g0, k0, k1, k4, k6, k7, k9, n1, n2, n3 and s2, so the 163
   untagged blocks DO get comments, strings, numbers, operators and keywords
   coloured. Tagging a block adds language-specific precision; it is not the
   difference between colour and no colour. */

html:root .vcv-code .enlighter-text {
  color: var(--vcv-syntax-text);
  font-weight: 400;
}

/* keyword */
html:root .vcv-code .enlighter-k0,
html:root .vcv-code .enlighter-k1,
html:root .vcv-code .enlighter-k2,
html:root .vcv-code .enlighter-k3,
html:root .vcv-code .enlighter-k4,
html:root .vcv-code .enlighter-k5,
html:root .vcv-code .enlighter-k6,
html:root .vcv-code .enlighter-k7,
html:root .vcv-code .enlighter-k8,
html:root .vcv-code .enlighter-k9,
html:root .vcv-code .enlighter-k10,
html:root .vcv-code .enlighter-k11,
html:root .vcv-code .enlighter-x1,
html:root .vcv-code .enlighter-t1,
html:root .vcv-code .enlighter-t2,
html:root .vcv-code .enlighter-t3,
html:root .vcv-code .enlighter-t4 {
  color: var(--vcv-syntax-keyword);
  font-weight: var(--vcv-weight-bold);
}

/* param */
html:root .vcv-code .enlighter-m0,
html:root .vcv-code .enlighter-m1,
html:root .vcv-code .enlighter-m2,
html:root .vcv-code .enlighter-m3,
html:root .vcv-code .enlighter-x2,
html:root .vcv-code .enlighter-x10,
html:root .vcv-code .enlighter-x11,
html:root .vcv-code .enlighter-x12,
html:root .vcv-code .enlighter-x13,
html:root .vcv-code .enlighter-x14,
html:root .vcv-code .enlighter-x15,
html:root .vcv-code .enlighter-x16 {
  color: var(--vcv-syntax-param);
  font-weight: 400;
}

/* string */
html:root .vcv-code .enlighter-s0,
html:root .vcv-code .enlighter-s1,
html:root .vcv-code .enlighter-s2,
html:root .vcv-code .enlighter-s3,
html:root .vcv-code .enlighter-s4,
html:root .vcv-code .enlighter-s5,
html:root .vcv-code .enlighter-t5 {
  color: var(--vcv-syntax-string);
  font-weight: 400;
}

/* number */
html:root .vcv-code .enlighter-n0,
html:root .vcv-code .enlighter-n1,
html:root .vcv-code .enlighter-n2,
html:root .vcv-code .enlighter-n3,
html:root .vcv-code .enlighter-n4,
html:root .vcv-code .enlighter-n5 {
  color: var(--vcv-syntax-number);
  font-weight: 400;
}

/* variable */
html:root .vcv-code .enlighter-e0,
html:root .vcv-code .enlighter-e1,
html:root .vcv-code .enlighter-e2,
html:root .vcv-code .enlighter-e3,
html:root .vcv-code .enlighter-e4 {
  color: var(--vcv-syntax-variable);
  font-weight: 400;
}

/* punctuation */
html:root .vcv-code .enlighter-g0,
html:root .vcv-code .enlighter-g1,
html:root .vcv-code .enlighter-t0,
html:root .vcv-code .enlighter-t7,
html:root .vcv-code .enlighter-t8 {
  color: var(--vcv-syntax-punctuation);
  font-weight: 400;
}

/* error */
html:root .vcv-code .enlighter-t6 {
  color: var(--vcv-syntax-error);
  font-weight: 400;
}

/* comment */
html:root .vcv-code .enlighter-c0,
html:root .vcv-code .enlighter-c1,
html:root .vcv-code .enlighter-c2,
html:root .vcv-code .enlighter-c9 {
  color: var(--vcv-syntax-comment);
  font-style: italic;
  font-weight: 400;
}

/* The original <pre> Enlighter hides once its JS has run. Keeping it hidden
   avoids showing the sample twice. */
html:root .vcv-code .enlighter-origin { display: none !important; }

/* Without JavaScript Enlighter never runs, so the original <pre> is all there
   is — and it must be visible. */
html .no-js .vcv-code .enlighter-origin,
.no-js .vcv-code .enlighter-origin { display: block !important; }

/* A live region for "Code copied" / "Link copied", added once by vcv.js. */
.vcv-live-region {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==========================================================================
   Callouts (HANDOFF §5.14)

   core/group + a registered block style. inc/blocks.php swaps the wrapper to
   <aside role="note">, injects the icon and wraps the author's blocks in the
   content column. No coloured left border — the whole panel is tinted.

   The seven variants differ only in which token triple they point the three
   local properties at, so the anatomy is written once.
   ========================================================================== */

.vcv-callout {
  display: flex;
  gap: var(--vcv-space-3);
  margin-block: var(--vcv-flow-block);
  padding: 16px 18px;
  border: 1px solid var(--vcv-callout-border, var(--vcv-color-border));
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-callout-bg, var(--vcv-color-surface));
}

.vcv-callout__icon {
  flex: none;
  color: var(--vcv-callout-fg, var(--vcv-color-text));
  margin-top: 2px;
}

.vcv-callout__content { min-width: 0; }

/* The first paragraph is the title (HANDOFF §5.14), which authors write in
   bold; it takes the callout's own colour so the panel reads as one thing. */
.vcv-callout__content > :first-child { margin-top: 0; }
.vcv-callout__content > :last-child { margin-bottom: 0; }

.vcv-callout__content > p:first-child strong,
.vcv-callout__content > h2:first-child,
.vcv-callout__content > h3:first-child,
.vcv-callout__content > h4:first-child {
  color: var(--vcv-callout-fg, var(--vcv-color-text));
  font-weight: var(--vcv-weight-bold);
}

.vcv-callout__content > * {
  font-size: 1rem;
  line-height: 1.55;
  color: var(--vcv-color-text);
  /* The callout is already a narrow column; the reading measure would fight it. */
  max-width: none;
}

.vcv-callout__content > * + * { margin-top: var(--vcv-space-2); }

.is-style-vcv-fix {
  --vcv-callout-fg: var(--vcv-color-success);
  --vcv-callout-bg: var(--vcv-color-success-bg);
  --vcv-callout-border: var(--vcv-color-success-border);
}

.is-style-vcv-info {
  --vcv-callout-fg: var(--vcv-color-info);
  --vcv-callout-bg: var(--vcv-color-info-bg);
  --vcv-callout-border: var(--vcv-color-info-border);
}

.is-style-vcv-warning {
  --vcv-callout-fg: var(--vcv-color-warning);
  --vcv-callout-bg: var(--vcv-color-warning-bg);
  --vcv-callout-border: var(--vcv-color-warning-border);
}

.is-style-vcv-danger {
  --vcv-callout-fg: var(--vcv-color-danger);
  --vcv-callout-bg: var(--vcv-color-danger-bg);
  --vcv-callout-border: var(--vcv-color-danger-border);
}

.is-style-vcv-tip {
  --vcv-callout-fg: var(--vcv-color-tip);
  --vcv-callout-bg: var(--vcv-color-tip-bg);
  --vcv-callout-border: var(--vcv-color-tip-border);
}

/* "Tested on" and "KB reference" are neutral panels (HANDOFF §5.14). */
.is-style-vcv-tested,
.is-style-vcv-kb {
  --vcv-callout-fg: var(--vcv-color-text);
  --vcv-callout-bg: var(--vcv-color-surface);
  --vcv-callout-border: var(--vcv-color-border);
}

.is-style-vcv-kb a {
  color: var(--vcv-color-accent);
  font-weight: var(--vcv-weight-bold);
}

/* Version chips inside a "Tested on" callout. */
.is-style-vcv-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.is-style-vcv-chips li {
  margin: 0;
  padding: 2px 12px;
  border-radius: var(--vcv-radius-full);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
  font-family: var(--vcv-font-mono);
  font-size: 0.8125rem;
}

.is-style-vcv-chips li::marker { content: none; }

/* ==========================================================================
   Figures and the lightbox (HANDOFF §5.15)
   ========================================================================== */

.entry-content figure.wp-block-image { margin-block: var(--vcv-flow-block); }

.entry-content figure.wp-block-image img {
  border: 1px solid var(--vcv-color-figure-border);
  border-radius: var(--vcv-radius-lg);
  display: block;
}

html:root .entry-content figcaption,
html:root .entry-content .wp-element-caption,
html:root .entry-content .wp-caption-text {
  margin-top: 10px;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);

  /* Neve sets `figcaption { opacity: 0.75 }` (style-main-new.css:1820), which
     dilutes whatever colour we set. --vcv-color-text-muted is 6.5:1 on the light
     background, but rendered at 75% it came out as #758295 — 3.65:1, a real AA
     failure that axe caught in light mode and that no amount of reading the
     token file would have shown, because the computed `color` is still correct.
     The muting is in the token; it must not also be in the opacity. */
  opacity: 1;
}

/* The zoom affordance. The button wraps the image rather than overlaying it, so
   the whole screenshot is the target and there is one tab stop, not two. */
.vcv-zoom {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: var(--vcv-radius-lg);
}

.vcv-zoom__badge {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--vcv-radius-sm);
  background: var(--vcv-color-bg);
  color: var(--vcv-color-text);
  border: 1px solid var(--vcv-color-border);
  opacity: 0;
  transition: opacity var(--vcv-duration) var(--vcv-ease);
}

.vcv-zoom:hover .vcv-zoom__badge,
.vcv-zoom:focus-visible .vcv-zoom__badge { opacity: 1; }

/* Touch has no hover, so the badge is the only cue the image can be enlarged. */
@media (hover: none) {
  .vcv-zoom__badge { opacity: 1; }
}

.vcv-lightbox {
  width: auto;
  max-width: 96vw;
  max-height: 90vh;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--vcv-color-text);
  overflow: visible;
}

.vcv-lightbox::backdrop { background: var(--vcv-backdrop); }

.vcv-lightbox__image {
  display: block;
  max-width: 96vw;
  max-height: 80vh;
  object-fit: contain;
  border-radius: var(--vcv-radius-lg);
}

.vcv-lightbox__caption {
  margin: var(--vcv-space-3) 0 0;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
  text-align: center;
}

.vcv-lightbox__close {
  position: absolute;
  top: -52px;
  right: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-color-surface);
  color: var(--vcv-color-text);
  cursor: pointer;
}

.vcv-lightbox__close:hover {
  background: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
}

/* ==========================================================================
   Tables (HANDOFF §5.16)
   ========================================================================== */

.entry-content .wp-block-table {
  margin-block: var(--vcv-flow-block);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-md);
  /* The box scrolls, the page does not. */
  overflow-x: auto;
}

.entry-content .wp-block-table table {
  width: 100%;
  border-collapse: collapse;
  /* Below this a version matrix stops being readable and should scroll instead. */
  min-width: 560px;
}

.entry-content .wp-block-table caption {
  caption-side: top;
  padding: var(--vcv-space-3) var(--vcv-space-4);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
  text-align: left;
}

html:root .entry-content .wp-block-table th,
html:root .entry-content .wp-block-table td {
  padding: 10px 14px;
  border: 0;
  border-bottom: 1px solid var(--vcv-color-border);
  text-align: left;
  vertical-align: top;
}

html:root .entry-content .wp-block-table thead th {
  background: var(--vcv-color-surface);
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
}

html:root .entry-content .wp-block-table tbody tr:last-child td { border-bottom: 0; }

.entry-content .wp-block-table.is-style-stripes tbody tr:nth-child(odd),
.entry-content .wp-block-table.is-style-vcv-matrix tbody tr:nth-child(odd) {
  background: var(--vcv-color-zebra);
}

/* Version numbers read better as mono. In a matrix the first column is the
   label and the rest are versions (HANDOFF §5.16). */
.entry-content .wp-block-table.is-style-vcv-matrix td:not(:first-child),
.entry-content .wp-block-table .has-mono {
  font-family: var(--vcv-font-mono);
  font-size: var(--vcv-text-small);
}

/* ==========================================================================
   Quotes (HANDOFF §5.17)
   ========================================================================== */

html:root .entry-content blockquote,
html:root .entry-content .wp-block-quote {
  margin-block: var(--vcv-flow-block);
  padding: 0 0 0 20px;
  border: 0;
  border-left: 3px solid var(--vcv-color-secondary);
  background: none;
  font-size: 1.1875rem;
  font-style: italic;
  color: var(--vcv-color-text);
}

.entry-content blockquote cite,
.entry-content .wp-block-quote cite {
  display: block;
  margin-top: var(--vcv-space-2);
  font-size: var(--vcv-text-small);
  font-style: normal;
  color: var(--vcv-color-text-muted);
}

.entry-content blockquote cite::before { content: "— "; }

/* ==========================================================================
   Buttons in content (HANDOFF §5.26)
   ========================================================================== */

html:root .entry-content .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 18px;
  border: 1px solid transparent;
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-color-accent);
  color: var(--vcv-color-on-accent);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  text-decoration: none;
}

html:root .entry-content .wp-block-button__link:hover {
  background: var(--vcv-color-accent-hover);
  color: var(--vcv-color-on-accent);
}

html:root .entry-content .is-style-vcv-secondary .wp-block-button__link {
  background: transparent;
  color: var(--vcv-color-text);
  border-color: var(--vcv-color-border-strong);
}

html:root .entry-content .is-style-vcv-secondary .wp-block-button__link:hover {
  background: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
  color: var(--vcv-color-text);
}

/* ==========================================================================
   End of post (HANDOFF §5.18 – §5.22)
   ========================================================================== */

/* ---------- Tags (§5.19) ---------- */

.vcv-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-tag {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-sm);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
  text-decoration: none;
}

.vcv-tag:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
  text-decoration: none;
}

/* ---------- Share (§5.20) ---------- */

.vcv-share {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-2);
}

.vcv-share__label {
  font-size: var(--vcv-text-small);
  font-weight: var(--vcv-weight-bold);
  margin-right: var(--vcv-space-1);
}

.vcv-share__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  background: transparent;
  color: var(--vcv-color-text);
  cursor: pointer;
}

.vcv-share__link:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
}

.vcv-share__check { display: none; }

.vcv-share__copy.is-copied {
  background: var(--vcv-color-success-bg);
  border-color: var(--vcv-color-success-border);
  color: var(--vcv-color-success);
}

.vcv-share__copy.is-copied .vcv-icon:not(.vcv-share__check) { display: none; }
.vcv-share__copy.is-copied .vcv-share__check { display: block; }

/* ---------- Author box (§5.18) ---------- */

.vcv-author {
  display: flex;
  gap: var(--vcv-space-4);
  padding: var(--vcv-space-5);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
}

.vcv-author__body { min-width: 0; }

.vcv-author__eyebrow {
  margin: 0;
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-text-muted);
}

.vcv-author__name {
  margin: var(--vcv-space-1) 0 0;
  font-family: var(--vcv-font-heading);
  font-size: 1.25rem;
  font-weight: var(--vcv-weight-heading);
  letter-spacing: var(--vcv-tracking-h3);
}

.vcv-author__bio {
  margin: var(--vcv-space-2) 0 0;
  font-size: 0.9375rem;
  color: var(--vcv-color-text-soft);
}

.vcv-author__link {
  margin-top: var(--vcv-space-4);
  height: 40px;
}

/* ---------- Previous / next (§5.22) ---------- */

.vcv-post-nav {
  display: grid;
  gap: var(--vcv-space-4);
}

.vcv-post-nav__card {
  display: flex;
  flex-direction: column;
  gap: var(--vcv-space-2);
  padding: var(--vcv-space-4);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
  text-decoration: none;
  color: var(--vcv-color-text);
}

.vcv-post-nav__card:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-post-nav__label {
  font-size: 0.8125rem;
  color: var(--vcv-color-text-muted);
}

.vcv-post-nav__title {
  font-family: var(--vcv-font-heading);
  font-size: 1rem;
  font-weight: var(--vcv-weight-heading);
  line-height: 1.3;
}

/* ---------- Related posts (§5.21) ---------- */

html:root .vcv-related__heading {
  margin: 0 0 var(--vcv-space-3);
  font-size: var(--vcv-text-h2);
}

.vcv-related__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-related__item {
  padding: 14px 0;
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-related__item:first-child { border-top: 1px solid var(--vcv-color-border); }

.vcv-related__link {
  font-family: var(--vcv-font-heading);
  font-size: 1.0625rem;
  font-weight: var(--vcv-weight-heading);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-related__link:hover {
  color: var(--vcv-color-text);
  text-decoration: underline;
}

.vcv-related__meta {
  margin: var(--vcv-space-1) 0 0;
  font-size: 0.8125rem;
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Comments (HANDOFF §5.24)
   Native WordPress comments, restyled. The markup is WordPress's own, so the
   selectors are its class names.
   ========================================================================== */

html:root .vcv-comments__heading {
  margin: 0 0 var(--vcv-space-4);
  font-size: 1.5rem;
}

.vcv-comment-list,
.vcv-comment-list .children {
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-comment-list > li + li { margin-top: var(--vcv-space-4); }

.vcv-comment-list .children {
  margin-top: var(--vcv-space-4);
  /* Thread depth is 2, so this indent only ever applies once. */
  padding-left: 16px;
}

html:root .vcv-comment-list .comment-body,
html:root .vcv-comment-list .comment .comment-body {
  padding: 18px;
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
}

.vcv-comment-list .comment-meta,
.vcv-comment-list .comment-author {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-2);
  margin-bottom: var(--vcv-space-2);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

html:root .vcv-comment-list .comment-author img,
html:root .vcv-comment-list .avatar {
  width: 36px;
  height: 36px;
  border-radius: var(--vcv-radius-full);
}

.vcv-comment-list .fn,
.vcv-comment-list .comment-author .fn {
  font-style: normal;
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
}

.vcv-comment-list .says { display: none; }

/* The post author's own replies, so a reader can tell them apart at a glance. */
.vcv-comment-list .bypostauthor > .comment-body .fn::after {
  content: "AUTHOR";
  display: inline-block;
  margin-left: var(--vcv-space-2);
  padding: 1px 8px;
  border-radius: var(--vcv-radius-full);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
  font-family: var(--vcv-font-mono);
  font-size: 0.6875rem;
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  vertical-align: middle;
}

.vcv-comment-list .comment-content { font-size: 1rem; line-height: 1.6; }
.vcv-comment-list .comment-content > :first-child { margin-top: 0; }
.vcv-comment-list .comment-content > :last-child { margin-bottom: 0; }

.vcv-comment__reply,
.vcv-comment-list .comment-reply-link {
  display: inline-block;
  margin-top: var(--vcv-space-3);
  font-size: var(--vcv-text-small);
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-accent);
}

.vcv-comments__closed,
.vcv-comments__notes {
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

/* ---------- Form (HANDOFF §5.24, §5.27) ---------- */

html:root .vcv-comments .comment-respond {
  margin-top: var(--vcv-space-6);
  padding: var(--vcv-space-5);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
}

.vcv-comments .comment-form {
  display: grid;
  gap: var(--vcv-space-4);
}

.vcv-field { margin: 0; }

html:root .vcv-field label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--vcv-text-small);
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
}

.vcv-field__required { color: var(--vcv-color-danger); }

html:root .vcv-comments input[type="text"],
html:root .vcv-comments input[type="email"],
html:root .vcv-comments input[type="url"],
html:root .vcv-comments textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  /* The panel is `surface`, so the inputs sit on `bg` to stay distinguishable
     (HANDOFF §5.27). */
  background: var(--vcv-color-bg);
  color: var(--vcv-color-text);
  font-family: var(--vcv-font-body);
  /* 16px exactly: iOS zooms the page for anything smaller. */
  font-size: 16px;
  line-height: 1.5;
}

html:root .vcv-comments textarea {
  min-height: 7em;
  resize: vertical;
}

html:root .vcv-comments input:focus,
html:root .vcv-comments textarea:focus { border-color: var(--vcv-color-accent); }

html:root .vcv-comments [aria-invalid="true"] {
  border-width: 2px;
  border-color: var(--vcv-color-danger);
}

.vcv-field--consent {
  display: flex;
  align-items: flex-start;
  gap: var(--vcv-space-2);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-soft);
}

html:root .vcv-field--consent label {
  margin: 0;
  font-weight: var(--vcv-weight-regular);
  font-size: var(--vcv-text-small);
}

html:root .vcv-comments input[type="checkbox"] {
  width: 20px;
  height: 20px;
  min-height: 0;
  flex: none;
  accent-color: var(--vcv-color-accent);
}

html:root .vcv-comments .form-submit { margin: 0; }

html:root .vcv-comments .form-submit input[type="submit"],
html:root .vcv-comments .vcv-button--primary {
  width: auto;
  min-height: 44px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-color-accent);
  color: var(--vcv-color-on-accent);
  font-family: var(--vcv-font-body);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  cursor: pointer;
}

html:root .vcv-comments .form-submit input[type="submit"]:hover {
  background: var(--vcv-color-accent-hover);
}

/* ==========================================================================
   Listing pages — shared shell (HANDOFF §6.1, §6.3, §6.4, §6.6)

   Neve's wrappers are kept (`.archive-container`, `.nv-index-posts.blog.col`),
   so the same geometry fix the single post needs applies here: the column is a
   flex item of `.row`, and raising Neve's `max-width: 100%` without giving it a
   flex basis lets it size to its content. See the note in the single-post
   section.
   ========================================================================== */

html:root .vcv-listing .col {
  max-width: var(--vcv-width-container);
  padding-inline: var(--vcv-gutter);
  margin-inline: auto;
  flex: 1 1 100%;
  width: 100%;
  min-width: 0;
}

/* Neve's `.row { margin: 0 -15px }` is deliberately LEFT IN PLACE, exactly as on
   the single post. It cancels `.container`'s own 15px padding, so the row — and
   with it the column — spans the container's full 1280 and lines up with the
   header and footer above and below.

   Zeroing it instead inset the whole listing by 47px on each side against the
   header: the row then measured 1250, not 1280. Measured at 1440: header padding
   box 73..1353, card grid 120..1306. */

.vcv-listing .col > * + * {
  margin-block-start: var(--vcv-space-section);
}

html:root .vcv-listing .nv-index-posts {
  padding-block: var(--vcv-space-6) var(--vcv-space-section);
  margin-bottom: 0;
}

/* Search keeps a single reading column, left-aligned with the container. */
.vcv-listing--narrow .vcv-search-results,
.vcv-listing--narrow .vcv-archive-header,
.vcv-listing--narrow .vcv-search-form,
.vcv-listing--narrow .vcv-empty {
  max-width: var(--vcv-width-content);
}

/* ---------- Section headings ---------- */

.vcv-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--vcv-space-4);
  margin-bottom: var(--vcv-space-4);
}

html:root .vcv-section-heading {
  margin: 0 0 var(--vcv-space-4);
  font-size: var(--vcv-text-h2);
}

html:root .vcv-section-head .vcv-section-heading { margin-bottom: 0; }

.vcv-section-link {
  flex: none;
  font-size: var(--vcv-text-small);
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-accent);
  text-decoration: none;
}

.vcv-section-link:hover { text-decoration: underline; }

/* ---------- Archive header (HANDOFF §6.3) ---------- */

.vcv-archive-header__label {
  margin: 0;
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-text-muted);
}

html:root .vcv-archive-header__title {
  margin: var(--vcv-space-2) 0 0;
  text-align: left;
}

.vcv-archive-header__desc {
  margin-top: var(--vcv-space-3);
  max-width: 70ch;
  font-size: 1.0625rem;
  color: var(--vcv-color-text-soft);
}

.vcv-archive-header__count {
  margin: var(--vcv-space-3) 0 0;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Post card (HANDOFF §5.7) — text-only, never a featured image
   ========================================================================== */

.vcv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  gap: var(--vcv-space-5);
}

.vcv-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--vcv-space-2);
  padding: var(--vcv-space-5);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
}

.vcv-card:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-surface-hover);
}

.vcv-card:hover .vcv-card__link { text-decoration: underline; }

/* The topic sits above the stretched link so it stays separately clickable. */
.vcv-card__topic {
  position: relative;
  z-index: 1;
  align-self: flex-start;
}

html:root .vcv-card__title {
  margin: 0;
  font-size: 1.1875rem;
  line-height: 1.3;
  font-weight: var(--vcv-weight-heading);
}

.vcv-card__link {
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-card__link:hover { color: var(--vcv-color-text); }

/* Stretched link: the whole card is the target, with one tab stop. */
.vcv-card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.vcv-card__excerpt {
  margin: 0;
  font-size: 0.9375rem;
  color: var(--vcv-color-text-soft);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.vcv-card__meta {
  margin: auto 0 0;
  padding-top: var(--vcv-space-2);
  font-size: 0.8125rem;
  color: var(--vcv-color-text-muted);
}

/* The ring belongs around the card, not around the invisible stretched link. */
.vcv-card:has(.vcv-card__link:focus-visible) {
  outline: var(--vcv-focus-ring);
  outline-offset: var(--vcv-focus-offset);
}

.vcv-card:has(.vcv-card__link:focus-visible) .vcv-card__link:focus-visible {
  outline: none;
}

/* ==========================================================================
   Featured post (HANDOFF §5.8)
   ========================================================================== */

.vcv-featured {
  position: relative;
  max-width: 900px;
  padding: var(--vcv-space-6);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
}

.vcv-featured__bar {
  position: absolute;
  top: 0;
  left: var(--vcv-space-6);
  right: var(--vcv-space-6);
  height: 3px;
  background: var(--vcv-color-accent);
  border-radius: 0 0 3px 3px;
}

.vcv-featured__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-2);
  margin: 0 0 var(--vcv-space-3);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
}

.vcv-featured__latest { color: var(--vcv-color-text-muted); }

html:root .vcv-featured__title {
  margin: 0;
  font-size: var(--vcv-text-h2);
  line-height: var(--vcv-leading-h2);
}

.vcv-featured__link {
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-featured__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.vcv-featured:hover { border-color: var(--vcv-color-accent); }
.vcv-featured:hover .vcv-featured__link { text-decoration: underline; }

.vcv-featured__excerpt {
  margin: var(--vcv-space-3) 0 0;
  font-size: 1.0625rem;
  color: var(--vcv-color-text-soft);
  max-width: 70ch;
}

.vcv-featured__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--vcv-space-4);
  margin-top: var(--vcv-space-5);
}

.vcv-featured__meta {
  margin: 0;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

.vcv-featured:has(.vcv-featured__link:focus-visible) {
  outline: var(--vcv-focus-ring);
  outline-offset: var(--vcv-focus-offset);
}

/* ==========================================================================
   Topic tile (HANDOFF §5.9)
   ========================================================================== */

.vcv-topic-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--vcv-space-4);
}

.vcv-topic-tile {
  display: flex;
  flex-direction: column;
  gap: var(--vcv-space-2);
  min-height: 96px;
  padding: var(--vcv-space-5);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-topic-tile:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-topic-tile__name {
  font-family: var(--vcv-font-heading);
  font-size: 1.25rem;
  font-weight: var(--vcv-weight-heading);
  letter-spacing: var(--vcv-tracking-h3);
}

/* The horizon line under the name, echoing the wordmark. */
.vcv-topic-tile__line {
  display: block;
  width: 28px;
  height: 2px;
  background: var(--vcv-color-accent);
}

.vcv-topic-tile__desc {
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vcv-topic-tile__count {
  margin-top: auto;
  font-family: var(--vcv-font-mono);
  font-size: 0.8125rem;
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Start here (HANDOFF §6.1 section 5)
   ========================================================================== */

.vcv-start__list {
  margin: 0;
  padding: var(--vcv-space-2) var(--vcv-space-5);
  list-style: none;
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-lg);
}

.vcv-start__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--vcv-space-3);
  padding: var(--vcv-space-3) 0;
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-start__item:last-child { border-bottom: 0; }

.vcv-start__link {
  font-family: var(--vcv-font-heading);
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-start__link:hover { color: var(--vcv-color-text); text-decoration: underline; }

.vcv-start__meta {
  font-size: 0.8125rem;
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Homepage intro (HANDOFF §6.1 section 1)
   ========================================================================== */

html:root .vcv-home__title {
  margin: 0;
  font-size: var(--vcv-text-display);
  line-height: var(--vcv-leading-display);
  letter-spacing: var(--vcv-tracking-display);
  text-align: left;
}

.vcv-home__lede {
  margin-top: var(--vcv-space-4);
  max-width: 70ch;
  font-size: 1.0625rem;
  color: var(--vcv-color-text-soft);
}

.vcv-home__lede > * + * { margin-top: var(--vcv-space-3); }

/* ==========================================================================
   Search results (HANDOFF §5.25)
   ========================================================================== */

.vcv-search-item {
  padding: var(--vcv-space-4) 0;
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-search-item:first-child { border-top: 1px solid var(--vcv-color-border); }

.vcv-search-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-2);
  margin: 0;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

html:root .vcv-search-item__title {
  margin: var(--vcv-space-2) 0 0;
  font-size: 1.1875rem;
  line-height: 1.3;
}

.vcv-search-item__title a {
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-search-item__title a:hover { color: var(--vcv-color-text); text-decoration: underline; }

.vcv-search-item__excerpt {
  margin: var(--vcv-space-2) 0 0;
  font-size: 0.9375rem;
  color: var(--vcv-color-text-soft);
}

html:root .vcv-search-item mark,
html:root .entry-content mark {
  background: var(--vcv-color-mark);
  color: var(--vcv-color-text);
  border-radius: 3px;
  padding: 0 2px;
}

/* ==========================================================================
   Empty states (HANDOFF §5.25) and 404 (HANDOFF §5.30)
   ========================================================================== */

.vcv-empty {
  padding: 28px;
  border: 1px dashed var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-lg);
}

html:root .vcv-empty__title {
  margin: 0;
  font-size: var(--vcv-text-h2);
  text-align: left;
}

.vcv-empty__tip {
  margin: var(--vcv-space-3) 0 var(--vcv-space-4);
  color: var(--vcv-color-text-soft);
}

.vcv-empty .vcv-search-form { margin-top: var(--vcv-space-4); }

.vcv-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-chip {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-sm);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-chip:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
}

.vcv-404 {
  max-width: var(--vcv-width-content);
  padding: 36px 28px;
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
}

.vcv-404__code {
  margin: 0;
  font-family: var(--vcv-font-heading);
  /* 72px flat (HANDOFF §5.30), not the fluid display size, which topped out at
     60. Three digits at 72px are ~130px wide, so it still fits a 375 screen. */
  font-size: 4.5rem;
  font-weight: var(--vcv-weight-heading);
  line-height: 1;
  letter-spacing: var(--vcv-tracking-display);
}

.vcv-404__line {
  display: block;
  width: 72px;
  height: 3px;
  margin-top: var(--vcv-space-3);
  background: var(--vcv-color-accent);
}

html:root .vcv-404__title {
  margin: var(--vcv-space-5) 0 0;
  text-align: left;
}

.vcv-404__text {
  margin: var(--vcv-space-3) 0 var(--vcv-space-5);
  color: var(--vcv-color-text-soft);
  max-width: 60ch;
}

.vcv-404__home { margin-top: var(--vcv-space-4); }

/* ==========================================================================
   Pagination (HANDOFF §5.23)
   ========================================================================== */

html:root .vcv-pagination ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

html:root .vcv-pagination li { margin: 0; }

html:root .vcv-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--vcv-space-1);
  min-width: 44px;
  height: 44px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: var(--vcv-radius-md);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
  text-decoration: none;
}

html:root .vcv-pagination a.page-numbers:hover {
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
}

html:root .vcv-pagination .page-numbers.current {
  background: var(--vcv-color-accent-soft);
  border-color: var(--vcv-color-accent);
  color: var(--vcv-color-accent);
}

html:root .vcv-pagination .page-numbers.dots {
  min-width: 0;
  padding: 0 4px;
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Utilities
   ========================================================================== */

/* Visible only to screen readers, but focusable when it needs to be. */
.vcv-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Controls that do nothing without JavaScript are not rendered to the user.
   `no-js` is on <html> server-side and removed by the inline head script. */
.no-js [data-vcv-requires-js] {
  display: none !important;
}

/* ==========================================================================
   Theme toggle (HANDOFF §5.4)
   The button states the action it performs, not the state it is in: a sun in
   dark mode (press to go light), a moon in light mode. Only one icon is ever
   rendered visible, so assistive technology reads the label, not both icons.
   ========================================================================== */

.vcv-theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  color: var(--vcv-color-text);
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  cursor: pointer;
}

.vcv-theme-toggle:hover {
  background: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
}

.vcv-theme-toggle__icon {
  display: none;
  line-height: 0;
}

/* Dark is the default, so the sun (the action) shows unless light is active. */
:root:not([data-theme="light"]) .vcv-theme-toggle__icon--sun,
[data-theme="light"] .vcv-theme-toggle__icon--moon {
  display: block;
}

/* No transition on the colour swap: a cross-fade of every surface at once reads
   as a flash rather than as motion. HANDOFF §5.4. */
.vcv-theme-toggle,
.vcv-theme-toggle * {
  transition: none;
}

/* ==========================================================================
   Buttons (HANDOFF §5.26)
   ========================================================================== */

.vcv-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--vcv-space-2);
  height: 44px;
  padding: 0 18px;
  border-radius: var(--vcv-radius-md);
  font-family: var(--vcv-font-body);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
}

.vcv-button--primary {
  background: var(--vcv-color-accent);
  color: var(--vcv-color-on-accent);
}

.vcv-button--primary:hover { background: var(--vcv-color-accent-hover); color: var(--vcv-color-on-accent); }
.vcv-button--primary:active { background: var(--vcv-color-accent-active); }

.vcv-button--secondary {
  background: transparent;
  color: var(--vcv-color-text);
  border-color: var(--vcv-color-border-strong);
}

.vcv-button--secondary:hover {
  background: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
  color: var(--vcv-color-text);
}

.vcv-button[disabled] {
  background: var(--vcv-color-surface-raised);
  color: var(--vcv-color-text-disabled);
  cursor: not-allowed;
}

/* ==========================================================================
   Skip link
   Neve prints it and targets its own <main id="content"> (neve/header.php:123);
   this only restyles it. HANDOFF §8.
   ========================================================================== */

.neve-skip-link.show-on-focus {
  position: absolute;
  left: -9999px;
  z-index: calc(var(--vcv-z-header) + 1);
}

.neve-skip-link.show-on-focus:focus {
  left: var(--vcv-gutter);
  top: var(--vcv-space-2);
  padding: var(--vcv-space-3) var(--vcv-space-4);
  background: var(--vcv-color-accent);
  color: var(--vcv-color-on-accent);
  border-radius: var(--vcv-radius-md);
  text-decoration: none;
  font-weight: var(--vcv-weight-bold);
}

/* ==========================================================================
   Header (HANDOFF §5.1, §5.2)
   Mobile first: the 60px bar with a menu button. The 72px desktop header with
   inline navigation starts at 1280.
   ========================================================================== */

:root { --vcv-header-height: 60px; }

/* Neve makes two of the header's ancestors scroll containers, and `position: sticky`
   only sticks within its nearest scrollport — so inside them the header scrolls away
   with the page:
     body                                      { overflow-x: hidden }  (style-main-new.css:285)
     body > .wrapper:not(.et-fb-iframe-ancestor) { overflow: hidden }  (style-main-new.css:1123)
   `.wrapper` is the header's direct parent (neve/header.php:68-78), so that one is
   decisive. Both exist to stop a wide block giving the page a horizontal scrollbar.

   `overflow: clip` clips exactly the same way but does NOT create a scroll container,
   so the sticky header resolves against the viewport again and the horizontal-overflow
   protection is kept. Browsers without `clip` (pre-Safari 16) simply drop these
   declarations and keep Neve's `hidden`: the header stops sticking, nothing breaks.

   Specificity, not load order. An earlier version of this matched Neve's selectors
   exactly and relied on loading later. The .wrapper rule won that way, but the body
   rule did not: on the real site something re-asserts `body { overflow-x: hidden }`
   after this stylesheet, and at equal specificity last-one-wins went the other way.
   `html:root body` is (0,1,2), which beats a bare `body` (0,0,1) and a single-class
   `body.something` (0,1,1) no matter what order the sheets arrive in. */
html:root body { overflow-x: clip; }
html:root body > .wrapper:not(.et-fb-iframe-ancestor) { overflow: clip; }

.vcv-header {
  position: sticky;
  top: 0;
  z-index: var(--vcv-z-header);
  background: var(--vcv-color-surface);
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--vcv-space-4);
  max-width: var(--vcv-width-container);
  min-height: var(--vcv-header-height);
  margin: 0 auto;
  padding-inline: var(--vcv-gutter);
}

/* Hide on scroll down, show on scroll up. Under reduced motion the class just
   hides it outright rather than sliding. HANDOFF §5.1. */
.vcv-header { transition: transform var(--vcv-duration) var(--vcv-ease); }
.vcv-header--hidden { transform: translateY(-100%); }

@media (prefers-reduced-motion: reduce) {
  .vcv-header { transition: none; }
  .vcv-header--hidden { transform: none; visibility: hidden; }
}

/* ---------- Logo (HANDOFF §5.1, §5.5, §12) ----------
   Symbol plus live text. The text is real HTML, not an image or outlined paths,
   so it stays selectable, searchable and scales with the reader's font size.
   The symbol fills from --vcv-color-accent and --vcv-color-text, so it follows
   the theme toggle without swapping files.

   The horizon line that used to sit under the wordmark is gone (HANDOFF §1).
   The topic tiles keep theirs — §5.9 is unchanged, and the symbol's three
   fading bars are the same idea, so they still echo each other. */

.vcv-logo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  font-family: var(--vcv-font-heading);
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--vcv-color-text);
  flex: none;
}

.vcv-logo:hover { color: var(--vcv-color-text); text-decoration: none; }
.vcv-logo__accent { color: var(--vcv-color-accent); }

/* Height drives it; width follows the viewBox ratio. flex: none stops the
   symbol being squeezed when the header runs out of room on a small screen. */
.vcv-logo__symbol {
  height: 34px;
  width: auto;
  flex: none;
}

/* Stacked: symbol above the text, for the footer and other square spaces.
   Two classes so it keeps its 56px symbol inside the desktop media query
   below, rather than depending on which rule comes last. */
/* Stacked follows canvas board W4: the symbol stays on the LEFT and the wordmark
   breaks onto two lines beside it. That is not §12's symbol-above-text reading of
   "stacked" — Bryan's call, 2026-10-21.
   The text becomes a flex column, so the anonymous whitespace between the two
   spans is dropped rather than rendering as a stray space, and the two lines sit
   on the tight 0.95 leading the board shows. */
.vcv-logo--stacked {
  flex-direction: row;
  align-items: center;
  gap: 12px;
}

.vcv-logo.vcv-logo--stacked .vcv-logo__symbol { height: 56px; }

.vcv-logo--stacked .vcv-logo__text {
  display: flex;
  flex-direction: column;
  line-height: 0.95;
}

/* ---------- Primary navigation ---------- */

.vcv-nav { display: none; }

.vcv-menu {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-menu a {
  display: block;
  padding: 10px 16px;
  border-radius: var(--vcv-radius-full);
  font-size: 1rem;
  font-weight: var(--vcv-weight-bold);
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-menu a:hover {
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
}

/* WordPress marks the whole trail, not just the leaf: a single post inside a
   category gives its parent item current-menu-parent / current-menu-ancestor,
   and a child page gives current_page_parent / current_page_ancestor. Without
   these the nav goes blank the moment a reader opens a post. */
.vcv-menu .current-menu-item > a,
.vcv-menu .current-menu-parent > a,
.vcv-menu .current-menu-ancestor > a,
.vcv-menu .current_page_item > a,
.vcv-menu .current_page_parent > a,
.vcv-menu .current_page_ancestor > a,
.vcv-menu a[aria-current="page"] {
  background: var(--vcv-color-accent);
  color: var(--vcv-color-on-accent);
}

/* ---------- Header actions ---------- */

.vcv-header__actions {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-2);
  flex: none;
}

.vcv-search-trigger,
.vcv-menu-toggle,
.vcv-search-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--vcv-radius-md);
  color: var(--vcv-color-text);
  cursor: pointer;
}

.vcv-search-trigger:hover,
.vcv-menu-toggle:hover,
.vcv-search-link:hover { background: var(--vcv-color-surface-hover); color: var(--vcv-color-text); }

/* The label and shortcut hint only exist in the wide desktop trigger. */
.vcv-search-trigger__label,
.vcv-search-trigger__kbd { display: none; }

/* Search falls back to a plain link to the search page when JS is unavailable. */
.vcv-search-link { display: none; }
.no-js .vcv-search-link { display: inline-flex; }

/* The theme toggle lives in the mobile menu below 1280. */
.vcv-header__actions .vcv-theme-toggle { display: none; }

.vcv-menu-toggle__icon { display: none; line-height: 0; }
.vcv-menu-toggle__icon--open { display: block; }
.vcv-menu-toggle[aria-expanded="true"] .vcv-menu-toggle__icon--open { display: none; }
.vcv-menu-toggle[aria-expanded="true"] .vcv-menu-toggle__icon--close { display: block; }

/* ---------- Search panel (HANDOFF §5.3) ---------- */

.vcv-search-panel {
  background: var(--vcv-color-surface);
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-search-panel__inner {
  max-width: var(--vcv-width-container);
  margin: 0 auto;
  padding: var(--vcv-space-3) var(--vcv-gutter);
}

.vcv-search-form { display: flex; gap: var(--vcv-space-2); }

.vcv-search-form__input {
  flex: 1 1 auto;
  min-width: 0;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  background: var(--vcv-color-bg);
  color: var(--vcv-color-text);
  /* 16px exactly: iOS zooms the page for anything smaller. */
  font-size: 16px;
  font-family: inherit;
}

.vcv-search-form__input:focus {
  border-color: var(--vcv-color-accent);
}

.vcv-search-form__submit { flex: none; }

/* ---------- Mobile menu (HANDOFF §5.2) ---------- */

.vcv-mobile-menu {
  position: fixed;
  inset: var(--vcv-header-height) 0 0;
  z-index: var(--vcv-z-header);
  overflow-y: auto;
  background: var(--vcv-color-surface-raised);
  padding: var(--vcv-space-4) var(--vcv-gutter) var(--vcv-space-6);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--vcv-space-6);
}

.vcv-menu--mobile {
  flex-direction: column;
  align-items: stretch;
  gap: var(--vcv-space-1);
}

.vcv-menu--mobile a {
  font-family: var(--vcv-font-heading);
  font-weight: 800;
  font-size: 20px;
  padding: 12px;
  border-radius: var(--vcv-radius-md);
}

.vcv-menu--mobile .current-menu-item > a,
.vcv-menu--mobile .current-menu-parent > a,
.vcv-menu--mobile .current-menu-ancestor > a,
.vcv-menu--mobile .current_page_item > a,
.vcv-menu--mobile .current_page_parent > a,
.vcv-menu--mobile .current_page_ancestor > a,
.vcv-menu--mobile a[aria-current="page"] {
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
}

.vcv-mobile-menu__theme {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--vcv-space-4);
  padding-top: var(--vcv-space-4);
  border-top: 1px solid var(--vcv-color-border);
}

.vcv-mobile-menu__theme-label {
  font-weight: var(--vcv-weight-bold);
}

.vcv-theme-pill {
  min-height: 44px;
  padding: 0 18px;
  border-radius: var(--vcv-radius-full);
  border: 1px solid var(--vcv-color-border-strong);
  background: transparent;
  color: var(--vcv-color-text);
  font: inherit;
  font-weight: var(--vcv-weight-bold);
  cursor: pointer;
}

.vcv-theme-pill:hover {
  background: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
}

/* ---------- No-JavaScript navigation (HANDOFF §7) ----------
   Below 1280 the navigation lives behind the menu button, and that button is
   hidden without JS because it could never open anything. That would leave a
   reader with no navigation at all, so the primary list renders in the flow
   instead — wrapped onto its own row under the wordmark and search link.

   Scoped below 1280 on purpose: from 1280 up .vcv-nav is already visible and
   these rules would stretch it across the header.

   The mobile panel itself stays `hidden`; this is a replacement for it, not a
   way of revealing it. */
@media (max-width: 1279px) {
  .no-js .vcv-header__inner { flex-wrap: wrap; }

  .no-js .vcv-nav {
    display: block;
    order: 3;
    width: 100%;
  }

  .no-js .vcv-menu {
    flex-wrap: wrap;
    justify-content: center;
    padding-bottom: var(--vcv-space-2);
  }
}

/* Scroll lock while the menu is open. */
html.vcv-scroll-locked,
html.vcv-scroll-locked body { overflow: hidden; }

/* [hidden] has to beat the display rules above. */
[hidden] { display: none !important; }

/* ==========================================================================
   Footer (HANDOFF §5.5)
   ========================================================================== */

.vcv-footer {
  background: var(--vcv-color-surface);
  border-top: 1px solid var(--vcv-color-border);
  margin-top: var(--vcv-space-section);
}

.vcv-footer__inner {
  display: grid;
  gap: var(--vcv-space-5);
  max-width: var(--vcv-width-container);
  margin: 0 auto;
  padding: var(--vcv-space-5) var(--vcv-gutter);
}

.vcv-footer__tagline {
  margin: var(--vcv-space-2) 0 0;
  color: var(--vcv-color-text-muted);
}

.vcv-footer__nav .vcv-menu,
.vcv-footer__nav .vcv-menu--footer {
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
}

.vcv-footer__nav a,
.vcv-footer__cookie a,
.vcv-footer__cookie-button {
  padding: var(--vcv-space-2) 0;
  border-radius: 0;
  color: var(--vcv-color-text-muted);
  font-weight: var(--vcv-weight-regular);
  text-decoration: none;
}

.vcv-footer__nav a:hover,
.vcv-footer__cookie a:hover,
.vcv-footer__cookie-button:hover {
  background: none;
  color: var(--vcv-color-text);
  text-decoration: underline;
}

.vcv-footer__cookie { margin: 0; }

/* The footer menu reuses .vcv-menu, so it was also inheriting the header's
   current-item treatment — on the About page the footer's "About" link rendered
   as a filled accent pill. In the header that pill marks where you are among a
   row of tabs; in a plain footer column it just looks like a highlighted word.
   Reset it here rather than un-sharing .vcv-menu, which the header still wants. */
html:root .vcv-footer__nav .vcv-menu .current-menu-item > a,
html:root .vcv-footer__nav .vcv-menu .current-menu-parent > a,
html:root .vcv-footer__nav .vcv-menu .current-menu-ancestor > a,
html:root .vcv-footer__nav .vcv-menu .current_page_item > a,
html:root .vcv-footer__nav .vcv-menu .current_page_parent > a,
html:root .vcv-footer__nav .vcv-menu .current_page_ancestor > a,
html:root .vcv-footer__nav .vcv-menu a[aria-current="page"] {
  background: none;
  color: var(--vcv-color-text);
}

/* The cookie-settings control is a button, not a link — it opens the consent
   plugin's dialog rather than navigating (see vcv_cookie_settings_link()) — so
   it has to be unstyled back down to the look of its neighbours. */
/* !important is load-bearing here, and is the only thing that works.
   cookie-law-info's own JS writes an inline style on anything carrying
   .cli_settings_button — live it was `color:#fff; background-color:#000`, taken
   from the plugin's button colour settings — and an inline style beats every
   selector. Our footer control has to keep that class because the plugin binds
   its open-preferences handler to it, so the class cannot simply be dropped. */
html:root .vcv-footer .vcv-footer__cookie-button {
  /* appearance:none first — without it some engines keep native button chrome
     regardless of background, and under color-scheme: dark that chrome is a dark
     box with white text, which is exactly how this rendered in testing.
     background-color is set explicitly as well as the shorthand, and the colour is
     restated here, so this does not depend on the grouped footer-link rule above
     winning its own cascade. html:root keeps it above anything Neve or a plugin
     applies to a bare `button`, per the house rule of winning on specificity
     rather than load order. */
  appearance: none;
  -webkit-appearance: none;
  display: inline-block;
  margin: 0;
  padding: var(--vcv-space-2) 0;
  background: none !important;
  background-color: transparent !important;
  color: var(--vcv-color-text-muted) !important;
  border: 0;
  border-radius: 0;
  font-family: inherit;
  font-size: inherit;
  font-weight: var(--vcv-weight-regular);
  line-height: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

html:root .vcv-footer .vcv-footer__cookie-button:hover {
  background-color: transparent !important;
  color: var(--vcv-color-text) !important;
  text-decoration: underline;
}

.vcv-social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vcv-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.vcv-social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  color: var(--vcv-color-text);
}

/* A raster brand mark. The global `img { height: auto }` would otherwise let the
   natural size win over the height attribute, so pin it here; (0,1,0) beats the
   element selector regardless of order. */
.vcv-icon--raster {
  height: 20px;
  width: auto;
}

.vcv-social-link:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-surface-hover);
  color: var(--vcv-color-text);
}

.vcv-footer__legal {
  border-top: 1px solid var(--vcv-color-border);
}

.vcv-footer__legal p {
  max-width: var(--vcv-width-container);
  margin: 0 auto;
  padding: var(--vcv-space-4) var(--vcv-gutter);
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

/* ==========================================================================
   Cookie banner and preferences modal (HANDOFF §5.29)
   Plugin: cookie-law-info ("CookieYes" / WebToffee) 3.5.7, legacy bar.

   Everything below was read out of the running plugin on 2026-10-21, not out of
   its documentation: the rendered markup on https://vcloudvision.com/, its
   stylesheets, its public JS, and the matching 3.5.7 tag on plugins.svn.wordpress.org.

   WHY OVERRIDE AND NOT DEQUEUE. Dequeuing cookie-law-info-css / -gdpr-css would
   take the *settings modal's* entire layout with it (its grid, its accordion, the
   toggle switches, the modal's show/hide transforms) and we would have to rebuild
   a consent dialog we are not allowed to change the behaviour of. The plugin's
   banner rules are weak — `#cookie-law-info-bar` (1,0,0) and single classes for
   the buttons, with no `!important` on anything we touch — so overriding wins
   cleanly. Same lesson as Neve and Enlighter: win on SPECIFICITY, never on load
   order. Every rule here is prefixed `html:root`, so the bar rules sit at (1,1,1)
   against the plugin's (1,0,0) and the button rules far above theirs.

   WHERE `!important` IS UNAVOIDABLE. The plugin's JS writes *inline* styles onto
   the bar and its buttons from the admin's colour settings, and inline styles beat
   any selector:
     - bar: `position`, `bottom`, `background-color`, `color`, `font-family`
       (cookie-law-info-public.js:559-574, `configBar`),
     - buttons: `color` always and `background-color` when the button is set to
       render "as a button", plus mouseenter/mouseleave handlers that rewrite
       `background-color` on hover (`configButtons`, :359-446).
   Those exact properties are therefore forced; nothing else is.

   WHAT IS NOT TOUCHED. `display` on `#cookie-law-info-bar` belongs to the plugin:
   it ships `display: none`, jQuery `.hide()`/`.show()` write it inline, and after
   a `.show()` the element is left with an inline `display: block`. Anything we set
   there would either be overridden or would leave the bar visible to someone who
   has already consented. The layout is therefore built on the inner `<span>`,
   which no script touches. Consent logic, cookies and settings are untouched.

   MARKUP, verified (class-cookie-law-info-public.php:236-240 and the live page):
     <div id="cookie-law-info-bar" data-nosnippet="true">
       <h5 class="cli_messagebar_head">…</h5>      ← only when a heading is set
       <span> message text, then whatever shortcodes the message contains </span>
     </div>
   The message's buttons are siblings inside that one span — there is no wrapper
   around them — which is why the span is a wrapping flex container: the message
   text is an anonymous flex item whose max-content width is far wider than the
   480px panel, so it always takes the first line on its own, and the buttons then
   share the next line at equal widths. A message short enough to fit beside the
   buttons would put them on one line; that degrades sensibly and no other layout
   is expressible without adding markup we do not own.

   THE THREE BUTTONS. §5.29 asks for Reject / Settings / Accept at equal visual
   weight, Accept deliberately not filled. **Only Accept and the "Read More" link
   are rendered today**: the bar's contents are the admin's message text, and that
   text contains `[cookie_button]` and `[cookie_link]` only. The remaining two come
   from `[cookie_reject]` and `[cookie_settings]`
   (modules/shortcode/shortcode.php:37-41), which is a plugin setting and so
   Bryan's call, not ours — see README. The rules below are written for all four
   action buttons the plugin can emit, matched on the classes its own JS binds to
   (cookie-law-info-public.js:84-88), so the row is correct the moment they appear.
   ========================================================================== */

html:root #cookie-law-info-bar {
  position: fixed !important;       /* inline from configBar */
  left: var(--vcv-space-4);
  right: var(--vcv-space-4);
  bottom: var(--vcv-space-4) !important;
  width: auto;                      /* with left+right set: viewport − 32 … */
  max-width: 480px;                 /* … clamped to 480, so the box stays left */
  box-sizing: border-box;
  margin: 0;
  padding: 20px;
  background-color: var(--vcv-color-surface-raised) !important;
  color: var(--vcv-color-text) !important;
  font-family: var(--vcv-font-body) !important;
  font-size: var(--vcv-text-small);
  font-weight: var(--vcv-weight-regular);
  line-height: 1.55;
  text-align: left;
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
  box-shadow: var(--vcv-shadow-md);
  z-index: var(--vcv-z-cookie);
}

/* Rendered only when "Cookie bar heading text" is filled in (it is empty today). */
html:root #cookie-law-info-bar .cli_messagebar_head {
  margin: 0 0 var(--vcv-space-2);
  font-family: var(--vcv-font-heading);
  font-size: 1.125rem;
  font-weight: var(--vcv-weight-heading);
  line-height: 1.3;
  color: var(--vcv-color-text);
}

html:root #cookie-law-info-bar > span {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-3);
  color: var(--vcv-color-text-soft);
}

/* The plugin runs the message through nl2br(), so every newline the admin types
   becomes a <br> — and a <br> inside a flex container is a flex item of its own,
   zero wide but still taking a 12px gap. Measured: one newline before the button
   row indented it by 12px and shrank all three buttons from 138 to 134. The flex
   lines already break where they should, so the <br> has nothing to contribute.
   A heading belongs in the plugin's "Message Heading" field, which renders as
   .cli_messagebar_head above, not in the message itself. */
html:root #cookie-law-info-bar > span br { display: none; }

/* The privacy link stays a link, not a fourth button (§5.29). It takes a line of
   its own because it is a sibling of the buttons, not part of the sentence. */
html:root #cookie-law-info-bar .cli-plugin-main-link {
  flex: 1 0 100%;
  margin: 0;
  padding: 0;
  background-color: transparent !important;
  color: var(--vcv-color-accent) !important;
  font-weight: var(--vcv-weight-bold);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Reject / Settings / Accept — one style, one size, no privileged option.
   Stacked below 520px, where three columns cannot hold the labels. */
html:root #cookie-law-info-bar .wt-cli-accept-btn,
html:root #cookie-law-info-bar .wt-cli-accept-all-btn,
html:root #cookie-law-info-bar .wt-cli-reject-btn,
html:root #cookie-law-info-bar .cli_settings_button {
  flex: 1 0 100%;
  box-sizing: border-box;
  height: 44px;
  min-width: 0;
  margin: 0;
  padding: 0 12px;
  background-color: transparent !important;
  color: var(--vcv-color-text) !important;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  font-family: var(--vcv-font-body);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  line-height: 42px;                /* 44 − the two 1px borders */
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}

html:root #cookie-law-info-bar .wt-cli-accept-btn:hover,
html:root #cookie-law-info-bar .wt-cli-accept-all-btn:hover,
html:root #cookie-law-info-bar .wt-cli-reject-btn:hover,
html:root #cookie-law-info-bar .cli_settings_button:hover {
  background-color: var(--vcv-color-surface-hover) !important;
  border-color: var(--vcv-color-accent);
  color: var(--vcv-color-text) !important;
  text-decoration: none;
}

@media (min-width: 520px) {
  html:root #cookie-law-info-bar .wt-cli-accept-btn,
  html:root #cookie-law-info-bar .wt-cli-accept-all-btn,
  html:root #cookie-law-info-bar .wt-cli-reject-btn,
  html:root #cookie-law-info-bar .cli_settings_button {
    flex: 1 1 0;
  }
}

/* ---------- Preferences modal (#cliSettingsPopup) ----------
   Not in §5.29, but the footer's "Cookie settings" link opens it, so it cannot
   stay a white dialog on a dark site. Colour only: its layout, its accordion and
   its toggle switches are left exactly as the plugin ships them. The JS writes no
   inline styles here, so none of this needs `!important`. */

html:root .cli-modal .cli-modal-dialog { color: var(--vcv-color-text); }

html:root .cli-modal .cli-modal-content {
  background-color: var(--vcv-color-surface-raised);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
}

html:root .cli-modal .cli-modal-close { color: var(--vcv-color-text); }
html:root .cli-modal .cli-modal-close svg { fill: currentColor; }

html:root .cli-modal .cli-tab-header { background-color: var(--vcv-color-surface); }
html:root .cli-modal .cli-tab-header a.cli-nav-link { color: var(--vcv-color-text); }
html:root .cli-modal .cli-tab-header a.cli-nav-link::before {
  border-right-color: currentColor;
  border-bottom-color: currentColor;
}

html:root .cli-modal .cli-tab-content { background: transparent; }

html:root .cli-modal .cli-tab-container p,
html:root .cli-modal .cli-privacy-content-text,
html:root .cli-modal .wt-cli-cookie-description {
  color: var(--vcv-color-text-soft);
}

html:root .cli-modal a.cli-privacy-readmore { color: var(--vcv-color-accent); }
html:root .cli-modal span.cli-necessary-caption { color: var(--vcv-color-text-muted); }

/* The toggle keeps its on/off distinction: border-strong when off, accent when
   on, with the knob in the panel colour so it reads against both. */
html:root .cli-modal .cli-switch .cli-slider { background-color: var(--vcv-color-border-strong); }
html:root .cli-modal .cli-switch input:checked + .cli-slider { background-color: var(--vcv-color-accent); }
html:root .cli-modal .cli-switch .cli-slider::before { background-color: var(--vcv-color-surface-raised); }
html:root .cli-modal .cli-switch .cli-slider::after { color: var(--vcv-color-text-soft); }

/* "Save & accept" takes the same secondary style as the bar's buttons — the same
   consent-design reason: the accepting action is not visually privileged. */
html:root .cli-modal .cli-tab-footer .cli-btn,
html:root .cli-modal .cli-tab-footer .wt-cli-privacy-accept-btn {
  height: 44px;
  padding: 0 18px;
  background-color: transparent;
  color: var(--vcv-color-text);
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-md);
  font-family: var(--vcv-font-body);
  font-size: 0.9375rem;
  font-weight: var(--vcv-weight-bold);
  line-height: 42px;
  cursor: pointer;
}

html:root .cli-modal .cli-tab-footer .cli-btn:hover,
html:root .cli-modal .cli-tab-footer .wt-cli-privacy-accept-btn:hover {
  background-color: var(--vcv-color-surface-hover);
  border-color: var(--vcv-color-accent);
  color: var(--vcv-color-text);
}

/* The plugin ships two bits of motion of its own: the dialog's scale-in and
   scale-out keyframes, and the toggle switch's 0.4s slide. Both are purely
   decorative — the dialog is shown and hidden by `display` on
   `.cli-modal.cli-show` (cookie-law-info-gdpr.css:402), and a transition only
   changes how a value is reached, never the value — so switching them off
   cannot leave anything stuck half-open. The banner itself has no motion. */
@media (prefers-reduced-motion: reduce) {
  html:root .cli-modal.cli-blowup .cli-modal-dialog,
  html:root .cli-modal.cli-blowup.cli-out .cli-modal-dialog { animation: none; }

  html:root .cli-modal .cli-switch .cli-slider,
  html:root .cli-modal .cli-switch .cli-slider::before { transition: none; }
}

/* ==========================================================================
   Desktop (≥1280): inline navigation, taller header, wide search trigger
   ========================================================================== */

@media (min-width: 768px) {
  .vcv-post-nav { grid-template-columns: 1fr 1fr; }

  .vcv-topic-tile { min-height: 112px; }

  /* Name and email share a row; the comment, consent and submit span both
     (HANDOFF §5.24). */
  .vcv-comments .comment-form { grid-template-columns: 1fr 1fr; }
  .vcv-comments .comment-form > *:not(.vcv-field--author):not(.vcv-field--email) {
    grid-column: 1 / -1;
  }

  /* The right-hand card is right-aligned so the pair reads outward from the
     centre, matching the arrow directions (HANDOFF §5.22). */
  .vcv-post-nav__card--next { text-align: right; align-items: flex-end; }
}

@media (min-width: 1280px) {
  :root { --vcv-header-height: 72px; }

  /* 4 topic tiles across (HANDOFF §5.9); the card grid is auto-fill, so it
     reaches 3 columns on its own at this width. */
  .vcv-topic-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  .vcv-header__inner { gap: var(--vcv-space-6); }

  .vcv-logo { font-size: 22px; gap: 10px; }
  .vcv-logo__symbol { height: 40px; }

  .vcv-nav { display: block; }
  .vcv-menu-toggle { display: none; }
  .vcv-mobile-menu { display: none !important; }

  .vcv-header__actions .vcv-theme-toggle { display: inline-flex; }

  .vcv-search-trigger {
    width: 240px;
    justify-content: flex-start;
    gap: var(--vcv-space-2);
    padding: 0 12px;
    background: var(--vcv-color-bg);
    border: 1px solid var(--vcv-color-border-strong);
    color: var(--vcv-color-text-muted);
  }

  .vcv-search-trigger__label { display: block; flex: 1 1 auto; text-align: left; }
  .vcv-search-trigger__kbd { display: block; }

  .vcv-footer__inner { grid-template-columns: 2fr 1fr 1fr; gap: var(--vcv-space-6); }
  .vcv-footer__inner { padding-block: var(--vcv-space-6); }

  /* ---------- Single-post grid with the sticky TOC (HANDOFF §6.2) ----------
     220px TOC · 48px gutter · 720px reading column · the rest.

     Only posts with a TOC become a grid; everything else keeps the centred
     reading column, so there is no empty 268px indent on short posts.

     The TOC spans every row so its grid *area* is the full height of the
     article; `align-self: start` keeps the nav itself its natural height, and
     `position: sticky` then resolves against the viewport inside that area.
     `span 999` rather than `1 / -1`: with only implicit rows, line -1 resolves
     back to line 1 and the span collapses.

     This sticks only because the child switches Neve's `overflow: hidden` on
     body and body > .wrapper to `overflow: clip` (see the note above the header
     rules). Undo that and the TOC scrolls away with the page. */
  html:root .vcv-single--has-toc {
    display: grid;
    grid-template-columns: var(--vcv-width-toc) 48px minmax(0, var(--vcv-width-content)) 1fr;
    align-content: start;
  }

  /* The 720 cap comes from the grid track now (column 3 is
     `minmax(0, 720px)`), so the one on .vcv-single > * has to be lifted —
     otherwise it also caps .entry-content, which spans two columns, and the
     wide break-out below silently does nothing. */
  .vcv-single--has-toc > * {
    grid-column: 3;
    margin-inline: 0;
    min-width: 0;
    max-width: none;
  }

  /* Rows come from the grid, so the generic sibling margin would double up. */
  .vcv-single--has-toc > * + * { margin-block-start: 0; }
  .vcv-single--has-toc { row-gap: var(--vcv-space-6); }

  .vcv-single--has-toc > .vcv-toc {
    display: block;
    grid-column: 1;
    grid-row: 1 / span 999;
    align-self: start;
    position: sticky;
    top: calc(var(--vcv-header-height) + 24px);
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    max-width: none;
  }

  .vcv-single--has-toc > .vcv-toc-mobile { display: none; }

  /* The body spans the reading column *and* the free column to its right, so a
     wide block grows to the right only and never slides under the sticky TOC
     (HANDOFF §6.2). Normal blocks stay capped at the 720 reading column. */
  .vcv-single--has-toc > .entry-content { grid-column: 3 / -1; }

  .vcv-single--has-toc .entry-content > * { margin-inline: 0; }

  .vcv-single--has-toc .entry-content > .alignwide {
    width: 100%;
    max-width: var(--vcv-width-wide);
  }

  /* alignfull cannot use the 100vw trick inside a grid column without going
     off-centre, so inside the grid it spans the article instead. */
  .vcv-single--has-toc > .entry-content > .alignfull {
    width: 100%;
    margin-inline: 0;
  }
}

/* ==========================================================================
   About page (HANDOFF §13)
   An ordinary page built from block patterns, so everything here styles core
   blocks by class rather than assuming a template. The 900px breakpoint is
   §13.3's, not the 1280 used elsewhere: this page's columns stack earlier
   because two author cards at 440px minimum need the room.
   ========================================================================== */

.is-style-vcv-section { padding-top: 88px; }
.is-style-vcv-section:first-child { padding-top: 0; }

.vcv-eyebrow {
  margin: 0 0 var(--vcv-space-2);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-secondary);
}

/* ---------- Intro ---------- */

.vcv-about-title { font-size: 52px; }

.vcv-about-lede {
  font-size: 1.1875rem;
  color: var(--vcv-color-text-soft);
  max-width: 68ch;
}

.vcv-about-panel {
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
  padding: 28px;
}

.vcv-about-panel__symbol { display: block; line-height: 0; }
.vcv-about-panel__symbol .vcv-logo__symbol { height: 120px; width: auto; }

.vcv-about-panel__label {
  margin: var(--vcv-space-4) 0 var(--vcv-space-3);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-text-muted);
}

/* ---------- Chips, shared by the panel and the author cards ---------- */

/* html:root because these lists live inside .entry-content, where the base
   rules `.entry-content ul { list-style: disc; padding-left: 1.4em }` and
   `.entry-content li + li { margin-top: .375em }` are (0,1,1) and would
   otherwise win — which put bullet markers on every chip and badge. */
html:root .vcv-topic-chips,
html:root .vcv-author-card__chips,
html:root .vcv-author-card__badges {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vcv-space-2);
  padding: 0;
  list-style: none;
}

html:root .vcv-topic-chips,
html:root .vcv-author-card__chips { margin: 0; }

html:root .vcv-topic-chips > li,
html:root .vcv-author-card__chips > li,
html:root .vcv-author-card__badges > li,
html:root .is-style-vcv-timeline > li { margin-top: 0; }

.vcv-chip {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 12px;
  background: var(--vcv-color-bg);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-sm);
  font-size: 0.875rem;
  color: var(--vcv-color-text);
  text-decoration: none;
}

.vcv-chip--link:hover {
  border-color: var(--vcv-color-accent);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
}

/* ---------- Author cards (§13.2) ---------- */

.vcv-author-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr));
  gap: var(--vcv-space-5);
  align-items: stretch;
}

/* The grid is a core/group, so it keeps WordPress's `is-layout-flow` class and
   with it the flow-layout rule that puts a block-gap margin on every child after
   the first. Inside a grid that margin insets the item within its row: measured
   live, card 2 had margin-top 22.5px and came out 514px tall against card 1's
   537px, sitting 22px lower. `align-items: stretch` does not help — stretch fills
   the area minus margins. The row gap already provides the spacing.

   html:root so this beats core's own layout rules whatever their specificity,
   rather than depending on stylesheet order.

   The flex rules below also let a card survive being wrapped in another group in
   the editor: the wrapper passes the stretch through instead of absorbing it. */
html:root .vcv-author-grid > * {
  margin-block: 0;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

html:root .vcv-author-grid > * > .vcv-author-card { flex: 1 1 auto; }

.vcv-author-card {
  display: flex;
  flex-direction: column;
  gap: var(--vcv-space-5);
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
  padding: 32px;
}

.vcv-author-card__top {
  display: flex;
  align-items: center;
  gap: var(--vcv-space-4);
}

.vcv-author-card__photo-wrap { flex: none; }

.vcv-author-card__photo {
  display: block;
  width: 104px;
  height: 104px;
  border-radius: var(--vcv-radius-full);
  border: 2px solid var(--vcv-color-accent);
  object-fit: cover;
}

.vcv-author-card__photo--initials {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--vcv-color-surface-raised);
  font-family: var(--vcv-font-heading);
  font-weight: 800;
  font-size: 32px;
  color: var(--vcv-color-text);
}

html:root .vcv-author-card__name {
  margin: 0;
  font-size: 26px;
  font-weight: 800;
}

.vcv-author-card__role {
  margin: var(--vcv-space-1) 0 0;
  font-size: 0.9375rem;
  color: var(--vcv-color-text-muted);
}

html:root .vcv-author-card__badges { margin: var(--vcv-space-3) 0 0; }

.vcv-badge {
  font-family: var(--vcv-font-mono);
  font-size: 0.75rem;
  font-weight: var(--vcv-weight-bold);
  padding: 2px 10px;
  border-radius: var(--vcv-radius-full);
  background: var(--vcv-color-accent-soft);
  color: var(--vcv-color-accent);
}

.vcv-author-card__bio {
  margin: 0;
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--vcv-color-text-soft);
}

.vcv-author-card__focus { margin: 0; }

.vcv-author-card__focus-label {
  margin: 0 0 var(--vcv-space-2);
  font-size: var(--vcv-text-label);
  font-weight: var(--vcv-weight-bold);
  letter-spacing: var(--vcv-tracking-label);
  text-transform: uppercase;
  color: var(--vcv-color-text-muted);
}

.vcv-author-card__chips .vcv-chip {
  height: auto;
  padding: 4px 12px;
}

/* margin-top:auto pins the actions to the bottom, so two cards with bios of
   different lengths still line their buttons up (§13.2). */
.vcv-author-card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--vcv-space-4);
  margin-top: auto;
}

/* One link, 44px tall, with only the first name bold and underlined (§13.2).
   The emphasis is carried by <strong> in the markup rather than by position, so
   it survives translation and still reads without CSS. */
.vcv-author-card__posts {
  display: inline-flex;
  align-items: center;
  gap: var(--vcv-space-1);
  min-height: 44px;
  font-weight: var(--vcv-weight-regular);
  color: var(--vcv-color-link);
  text-decoration: none;
}

.vcv-author-card__posts strong {
  font-weight: var(--vcv-weight-bold);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.vcv-author-card__posts:hover strong { text-decoration-thickness: 2px; }
.vcv-author-card__arrow { flex: none; }

/* ---------- Talks (§13.1) ---------- */

html:root .is-style-vcv-timeline {
  margin: var(--vcv-space-5) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--vcv-color-border);
}

html:root .is-style-vcv-timeline > li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--vcv-space-3);
  margin: 0;
  padding: var(--vcv-space-4) 0;
  border-bottom: 1px solid var(--vcv-color-border);
}

.vcv-talk__date {
  flex: none;
  width: 110px;
  font-family: var(--vcv-font-mono);
  font-size: 0.875rem;
  color: var(--vcv-color-text-muted);
}

.vcv-talk__body { flex: 1 1 260px; display: block; }

.vcv-talk__title {
  display: block;
  font-family: var(--vcv-font-heading);
  font-weight: 800;
  font-size: 18px;
}

.vcv-talk__meta {
  display: block;
  font-size: 0.9375rem;
  color: var(--vcv-color-text-muted);
}

.vcv-talk__type {
  flex: none;
  font-family: var(--vcv-font-mono);
  font-size: 0.75rem;
  padding: 2px 10px;
  border: 1px solid var(--vcv-color-border-strong);
  border-radius: var(--vcv-radius-full);
  color: var(--vcv-color-text-muted);
}

.vcv-talk__link { flex: none; color: var(--vcv-color-link); }

/* ---------- Contact CTA (§13.1) ---------- */

.vcv-cta {
  position: relative;
  overflow: hidden;
  background: var(--vcv-color-surface);
  border: 1px solid var(--vcv-color-border);
  border-radius: var(--vcv-radius-xl);
  padding: 40px;
}

/* The 3px accent bar, matching the featured card (§5.8). */
.vcv-cta::before {
  content: "";
  position: absolute;
  inset: 0 32px auto 32px;
  height: 3px;
  background: var(--vcv-color-accent);
  border-radius: 0 0 3px 3px;
}

html:root .vcv-cta__title { margin: 0; font-size: 28px; }

.vcv-cta__text {
  margin: var(--vcv-space-3) 0 var(--vcv-space-5);
  color: var(--vcv-color-text-soft);
}

/* ---------- Disclaimer (§13.1) ---------- */

.vcv-disclaimer {
  max-width: 80ch;
  font-size: var(--vcv-text-small);
  color: var(--vcv-color-text-muted);
}

.vcv-disclaimer strong { color: var(--vcv-color-text); }

/* ---------- Below 900px (§13.3) ---------- */

@media (max-width: 899px) {
  .is-style-vcv-section { padding-top: 56px; }

  .vcv-about-title { font-size: 34px; }

  /* core/columns only stacks at 781px by default; §13.3 wants 900. */
  .vcv-about-intro.wp-block-columns { flex-wrap: wrap; }
  .vcv-about-intro > .wp-block-column { flex-basis: 100% !important; }

  .vcv-author-card,
  .vcv-cta { padding: 22px; }

  .vcv-cta::before { inset: 0 22px auto 22px; }

  .vcv-talk__date { width: auto; }
}
