/* Hover and focus open the mega panels. CSS-only so the header works with
   JavaScript disabled; view.js only adds Escape-to-close and the arrow-key
   roving tabindex, both of which are enhancements. */

.plinth-menu-panel { display: none; }

@media (min-width: 900px) {
  /* The pointer could not reach an open panel (defect: reported from the live
     header, "the drop down disappears before I can catch it").

     Two dead bands sat between the trigger and the panel. The trigger is a 44px
     box inside a 72px row, so 14px of row showed below it; and the mega panel is
     anchored to .plinth-header__row, not to .plinth-menu, so its top edge is at
     the bottom of the row. Measured at 1440px: .plinth-menu ran y 14-58 and
     x 303-401, the panel started at y 72 and ran x 72-1352. Moving straight down
     left the menu at y 58 and did not enter the panel until y 72; moving
     diagonally towards a first-column link left the menu's left edge at x 303
     while still above y 72. Either way both :hover targets were lost at once,
     and visibility is not an animatable property, so the panel vanished in the
     same frame.

     Fixed in two parts: stretch the wrapper so its hover area meets the panel,
     and give the close a grace period so a diagonal crossing is survivable.
     The wrapper and the nav carry no visual styling of their own and the
     trigger anchor keeps its 44px box, centred as before, so nothing moves. */
  .plinth-header__nav { align-self: stretch; }
  .plinth-menu {
    align-self: stretch;
    display: flex;
    align-items: center;
  }

  .plinth-menu-panel {
    display: block;
    visibility: hidden;
    opacity: 0;
    /* Closing holds for 220ms, fades over 150ms, and only then flips
       visibility, so a pointer that clips an edge on the way down re-enters a
       panel that is still open. Opening stays immediate — see the hover rule. */
    transition: opacity 150ms ease 220ms, visibility 0s linear 370ms;
    /* Above the sibling .plinth-menu wrappers, which are stretched and, from
       the fourth onwards, positioned — so the strip below wins the hit test. */
    z-index: 1;
  }

  /* An open panel also claims the strip of row between the trigger and its own
     top edge, right across the panel's width. Without it, a diagonal aimed at a
     right-hand column crosses a neighbouring trigger on the way down and swaps
     to that neighbour's panel. The strip exists only while the panel is open: a
     closed panel is visibility:hidden, which its children inherit, so it takes
     no pointer events and nothing in the row is blocked. Height is the gap the
     centred 44px trigger leaves in the row, so it tracks the sticky height too. */
  .plinth-menu-panel::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: calc((var(--wp--custom--header--height) - 44px) / 2);
  }
  .plinth-header[data-scrolled="true"] .plinth-menu-panel::before {
    height: calc((var(--wp--custom--header--height-sticky) - 44px) / 2);
  }
  .plinth-menu:hover > .plinth-menu-panel,
  .plinth-menu:focus-within > .plinth-menu-panel,
  .plinth-menu-panel:hover {
    visibility: visible;
    opacity: 1;
    transition: opacity 150ms ease, visibility 0s;
  }
  /* Mega panels span the row, not the trigger.

     These were anchored to .plinth-menu, which sits roughly 450px into the row,
     and then given min-width:680px. That pushed the panel's right edge past the
     viewport on every page between 900px and about 1160px wide. A closed panel
     is visibility:hidden, not display:none, so it still occupies layout and
     still counts toward scrollWidth: the whole document scrolled horizontally
     even though nothing was open. Measured at a 900px viewport before the fix,
     documentElement.scrollWidth was 1155 against a clientWidth of 885.

     Anchoring to the row keeps the panel inside the container at every width.
     Trigger-anchored dropdowns (.plinth-menu-panel--dropdown) are untouched.

     Pre-existing: present since the panels were built, not introduced by the
     CSS-delivery refactor. Found during closure verification at 900px. */
  .plinth-header__row { position: relative; }

  /* WAS nth-child(-n+3), 20 October 2026. That counted positions because, when
     it was written, the first three entries happened to be the mega menus. It
     is a proxy for "is a mega panel", and it broke the moment the menu order
     changed: promoting Integrations to the top level made Resources the fourth
     entry, so it fell out of the set, reverted to trigger-anchored shrink-to-fit
     and — with its columns allowed to shrink to nothing — collapsed to a narrow
     strip that wrapped every label one character per line.

     Selecting the thing itself instead of its position cannot drift that way:
     a mega panel is anchored to the row because it is a mega panel. Dropdowns
     keep their trigger anchoring and their own min-width. */
  .plinth-menu:has( > .plinth-menu-panel:not(.plinth-menu-panel--dropdown) ) { position: static; }
  .plinth-menu > .plinth-menu-panel:not(.plinth-menu-panel--dropdown) {
    left: 0;
    right: 0;
    min-width: 0;
  }
}

/* Sticky state: the design system permits a 150ms border and shadow change and
   caps the sticky row at 64px. Nothing else moves. */
.plinth-header[data-scrolled="true"] {
  border-bottom-color: var(--wp--preset--color--border-strong);
  box-shadow: var(--wp--preset--shadow--raised);
}
.plinth-header[data-scrolled="true"] .plinth-row {
  min-height: var(--wp--custom--header--height-sticky);
}

@media (max-width: 899px) {
  .plinth-header .plinth-row { min-height: var(--wp--custom--header--height-mobile); gap: 8px; }
  .plinth-header nav[aria-label] { display: none; }
}

/* ---------------------------------------------------------------------------
   Presentation moved out of inline style attributes (defect D-18).

   The previous render emitted 17,656 bytes across 152 inline attributes on
   every page, none cacheable, because static declarations sat inside foreach
   loops and repeated per navigation link. Only the mega-panel column count is
   genuinely dynamic; it is passed as the custom property --plinth-mega-cols.
   --------------------------------------------------------------------------- */

.plinth-header {
  position: sticky;
  top: 0;
  z-index: var(--wp--custom--z--header);
  background: var(--wp--preset--color--paper);
  border-bottom: 1px solid var(--wp--preset--color--border);
  transition: border-color 150ms ease, box-shadow 150ms ease;
  min-width: 0;
}

.plinth-header__row {
  max-width: var(--wp--custom--layout--container);
  margin: 0 auto;
  padding: 0 var(--wp--preset--spacing--40);
  min-height: var(--wp--custom--header--height);
  display: flex;
  align-items: center;
  gap: var(--wp--preset--spacing--40);
  min-width: 0;
}

@media (max-width: 1100px) {
  .plinth-header__mega { gap: var(--wp--preset--spacing--24); }
}

.plinth-header__brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  gap: 10px;
  flex: none;
  text-decoration: none;
}

.plinth-header__wordmark {
  font-size: var(--wp--preset--font-size--h4);
  line-height: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--wp--preset--color--navy-900);
}

.plinth-header__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px;
  flex: 1 1 520px;
  min-width: 0;
}

.plinth-header__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 12px;
  border-radius: var(--wp--custom--radius--base);
  font-size: var(--wp--preset--font-size--small);
  font-weight: 500;
  color: var(--wp--preset--color--text-secondary);
  text-decoration: none;
  white-space: nowrap;
}

.plinth-menu { position: relative; min-width: 0; }

.plinth-menu-panel {
  position: absolute;
  left: 0;
  top: 100%;
  background: var(--wp--preset--color--paper);
  border: 1px solid var(--wp--preset--color--border);
  border-radius: 0 0 var(--wp--custom--radius--card) var(--wp--custom--radius--card);
  box-shadow: var(--wp--preset--shadow--raised);
  padding: var(--wp--preset--spacing--32);
  min-width: 0;
}

.plinth-menu-panel--dropdown { min-width: 260px; }

.plinth-header__mega {
  display: grid;
  /* Columns must shrink, not hold a floor: four columns at a 220px minimum
     plus the gaps push the panel past a 1024px viewport, and a closed
     panel still counts toward scrollWidth, so the whole page scrolled
     sideways once a fourth column had live links in it. */
  grid-template-columns: repeat(var(--plinth-mega-cols, 3), minmax(0, 1fr));
  gap: var(--wp--preset--spacing--40);
  min-width: 0;
}

.plinth-header__col { min-width: 0; }

.plinth-header__col-head {
  font-size: var(--wp--preset--font-size--caption);
  line-height: 20px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
  margin: 0 0 12px;
}

.plinth-header__col-link {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--wp--preset--font-size--body);
  color: var(--wp--preset--color--text);
  text-decoration: none;
  min-width: 0;
}

.plinth-header__col-link > span { min-width: 0; overflow-wrap: anywhere; }

/* A described link stacks its label over its description, so it needs to stop
   centring a single line and start at the top of its own box. The 44px floor
   stays: it is the touch target, and a described item is taller than that
   anyway. */
.plinth-header__col-link--described {
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 2px;
  padding: 8px 0;
}

.plinth-header__col-desc {
  font-size: var(--wp--preset--font-size--caption);
  line-height: 18px;
  color: var(--wp--preset--color--text-secondary);
  font-weight: 400;
}

.plinth-header__promo {
  background: var(--wp--preset--color--surface);
  border: 1px solid var(--wp--preset--color--border);
  border-radius: var(--wp--custom--radius--card);
  padding: var(--wp--preset--spacing--24);
  min-width: 0;
}

.plinth-header__promo-title {
  font-size: var(--wp--preset--font-size--h4);
  font-weight: 600;
  margin: 0;
  color: var(--wp--preset--color--text);
  overflow-wrap: anywhere;
}

.plinth-header__promo-body {
  font-size: var(--wp--preset--font-size--small);
  line-height: 22px;
  color: var(--wp--preset--color--text-secondary);
  margin: 8px 0 0;
  overflow-wrap: anywhere;
}

.plinth-header__promo-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
  color: var(--wp--preset--color--rust-600);
  text-decoration: none;
}

/* Addon hover/focus price panels (D-? none — new, 2026-10-25).
   The Addons column's links and these panels sit in different mega-menu
   columns, so :hover ~ sibling selectors cannot reach from one to the
   other. :has() can: it only needs a common ancestor, which .plinth-
   header__mega already is. CSS-only — no script, works with JavaScript
   disabled, and :focus covers keyboard users tabbing through the links. */
.plinth-header__promo-group { min-width: 0; }
.plinth-header__promo--addon { display: none; }

/* Only addons with their own price panel hide the default — a link like
   Client Portal (no WooCommerce listing yet) is still a plain addon-trigger
   for its :hover styling, but has no [data-addon-panel] to swap to, so it
   must not blank the promo column out from under it. */
.plinth-header__mega:has(.addon-trigger--gdpr:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--gdpr:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--slack-teams:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--slack-teams:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--email-triggers:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--email-triggers:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--duplicate-removal:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--duplicate-removal:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--reporting-tools:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--reporting-tools:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--smart-apply:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--smart-apply:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--appointment-scheduler:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--appointment-scheduler:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--lead-pipeline:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--lead-pipeline:focus) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--certification-tracker:hover) .plinth-header__promo--default,
.plinth-header__mega:has(.addon-trigger--certification-tracker:focus) .plinth-header__promo--default {
  display: none;
}

.plinth-header__mega:has(.addon-trigger--gdpr:hover) [data-addon-panel="gdpr"],
.plinth-header__mega:has(.addon-trigger--gdpr:focus) [data-addon-panel="gdpr"],
.plinth-header__mega:has(.addon-trigger--slack-teams:hover) [data-addon-panel="slack-teams"],
.plinth-header__mega:has(.addon-trigger--slack-teams:focus) [data-addon-panel="slack-teams"],
.plinth-header__mega:has(.addon-trigger--email-triggers:hover) [data-addon-panel="email-triggers"],
.plinth-header__mega:has(.addon-trigger--email-triggers:focus) [data-addon-panel="email-triggers"],
.plinth-header__mega:has(.addon-trigger--duplicate-removal:hover) [data-addon-panel="duplicate-removal"],
.plinth-header__mega:has(.addon-trigger--duplicate-removal:focus) [data-addon-panel="duplicate-removal"],
.plinth-header__mega:has(.addon-trigger--reporting-tools:hover) [data-addon-panel="reporting-tools"],
.plinth-header__mega:has(.addon-trigger--reporting-tools:focus) [data-addon-panel="reporting-tools"],
.plinth-header__mega:has(.addon-trigger--smart-apply:hover) [data-addon-panel="smart-apply"],
.plinth-header__mega:has(.addon-trigger--smart-apply:focus) [data-addon-panel="smart-apply"],
.plinth-header__mega:has(.addon-trigger--appointment-scheduler:hover) [data-addon-panel="appointment-scheduler"],
.plinth-header__mega:has(.addon-trigger--appointment-scheduler:focus) [data-addon-panel="appointment-scheduler"],
.plinth-header__mega:has(.addon-trigger--lead-pipeline:hover) [data-addon-panel="lead-pipeline"],
.plinth-header__mega:has(.addon-trigger--lead-pipeline:focus) [data-addon-panel="lead-pipeline"],
.plinth-header__mega:has(.addon-trigger--certification-tracker:hover) [data-addon-panel="certification-tracker"],
.plinth-header__mega:has(.addon-trigger--certification-tracker:focus) [data-addon-panel="certification-tracker"] {
  display: block;
}

.plinth-header__promo-second {
  display: flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--wp--preset--font-size--small);
  color: var(--wp--preset--color--navy-700);
  border-top: 1px solid var(--wp--preset--color--border);
  margin-top: 4px;
  padding-top: 4px;
}

.plinth-header__actions { display: flex; align-items: center; gap: 8px; flex: none; }

.plinth-header__search {
  font-family: inherit;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--wp--preset--color--border);
  border-radius: var(--wp--custom--radius--base);
  color: var(--wp--preset--color--text-secondary);
  cursor: pointer;
}

.plinth-header__docs { color: var(--wp--preset--color--navy-700); }

.plinth-header__buy {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
  color: var(--wp--preset--color--navy-800);
  background: var(--wp--preset--color--paper);
  border: 1px solid var(--wp--preset--color--border-strong);
  border-radius: var(--wp--custom--radius--base);
  text-decoration: none;
  white-space: nowrap;
}
.plinth-header__buy:hover { background: var(--wp--preset--color--surface); }

.plinth-header__cta {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  font-size: var(--wp--preset--font-size--small);
  font-weight: 600;
  color: var(--wp--preset--color--paper);
  background: var(--wp--preset--color--rust-600);
  border-radius: var(--wp--custom--radius--base);
  text-decoration: none;
  white-space: nowrap;
}

/* The sticky and mobile rules above targeted .plinth-row; keep both selectors
   so the refactor does not change behaviour. */
.plinth-header[data-scrolled="true"] .plinth-header__row {
  min-height: var(--wp--custom--header--height-sticky);
}

@media (max-width: 899px) {
  .plinth-header .plinth-header__row {
    min-height: var(--wp--custom--header--height-mobile);
    gap: 8px;
  }
}

/* Mobile menu toggle. Hidden above the mobile breakpoint, where the full
   navigation row is visible instead. */
.plinth-header__burger {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--wp--preset--color--border);
  border-radius: var(--wp--custom--radius--base);
  color: var(--wp--preset--color--text-secondary);
  cursor: pointer;
  flex: none;
}

/* Visually hidden but focusable. NOT display:none and NOT the hidden attribute:
   either removes the input from the focus order, which is what made the mobile
   menu unreachable by keyboard. */
.plinth-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The input is invisible, so its focus ring is drawn on the control the user
   can actually see. */
.plinth-mnav-toggle:focus-visible + .plinth-header__burger {
  outline: 2px solid var(--wp--preset--color--rust-600);
  outline-offset: 2px;
}

/* When the panel is open the header sits behind it, so move the indicator to
   the close control — focus must never be invisible behind the overlay. */
body:has(.plinth-mnav-toggle:focus-visible) .plinth-mnav__close {
  outline: 2px solid var(--wp--preset--color--rust-600);
  outline-offset: 2px;
}

@media (max-width: 899px) {
  .plinth-header__burger { display: inline-flex; }
  /* The bar is brand + burger + search below the breakpoint. Let the brand
     shrink rather than push the controls past the viewport edge. */
  .plinth-header__brand { min-width: 0; }
  .plinth-header__wordmark {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Docs and the demo CTA both live inside the mobile panel — Docs as a row and
     the CTA pinned to its footer. Leaving them in the bar as well overflowed it
     (brand + burger + search + CTA exceeded 375px), which is what introduced
     horizontal scroll when the burger was added. */
  .plinth-header__docs,
  .plinth-header__buy,
  .plinth-header__cta { display: none; }
  /* Controls sit at the right edge, as in the mobile design (V-06). */
  .plinth-header__actions { gap: 6px; margin-left: auto; }
}

/* At 320px the wordmark cannot coexist with the controls. The mark remains and
   the brand link keeps its accessible name, so nothing is lost. */
@media (max-width: 360px) {
  .plinth-header__wordmark { display: none; }
}
