@charset "UTF-8";
/* ==========================================================================
   Context Hubs — front-end entry point.
   ==========================================================================

   One of exactly two entry points. Layers load in cascade order: settings first
   so every later layer can consume the aliases, then generic, roles, Panels.

   Anything content-facing added below must also be reachable from editor.scss,
   or the editor and the rendered page will disagree.
   ========================================================================== */
/* ==========================================================================
   Brand layer — semantic aliases over theme.json presets.
   ==========================================================================

   theme.json is the single source of design values. WordPress emits them as
   --wp--preset--* and --wp--custom--*. This layer gives them stable semantic
   names so the role and Panel layers never reference a preset slug directly.

   Renaming a preset in theme.json therefore touches this file only, and a
   client re-skin is a theme.json change with no CSS edit at all.

   No literal design values below. If a value is not derivable from theme.json,
   it belongs in theme.json first.
   ========================================================================== */
:root {
  /* Colour */
  --ds-color-base: var(--wp--preset--color--base);
  --ds-color-body: var(--wp--preset--color--contrast);
  --ds-color-primary: var(--wp--preset--color--primary);
  --ds-color-heading: var(--wp--preset--color--accent);
  --ds-color-surface: var(--wp--preset--color--surface);
  --ds-color-muted: var(--wp--preset--color--muted);
  --ds-color-border: var(--wp--preset--color--border);
  --ds-color-inverse-bg: var(--wp--preset--color--contrast);
  --ds-color-on-inverse: var(--wp--preset--color--base);
  /* Typography */
  --ds-font-body: var(--wp--preset--font-family--body);
  --ds-font-heading: var(--wp--preset--font-family--heading);
  --ds-text-small: var(--wp--preset--font-size--small);
  --ds-text-base: var(--wp--preset--font-size--medium);
  --ds-text-large: var(--wp--preset--font-size--large);
  --ds-text-title: var(--wp--preset--font-size--x-large);
  --ds-text-display: var(--wp--preset--font-size--xx-large);
  --ds-weight-regular: var(--wp--custom--typography--weight--regular);
  --ds-weight-semibold: var(--wp--custom--typography--weight--semibold);
  --ds-weight-bold: var(--wp--custom--typography--weight--bold);
  --ds-leading-body: var(--wp--custom--typography--line-height--body);
  --ds-leading-heading: var(--wp--custom--typography--line-height--heading);
  /* Spacing */
  --ds-space-xs: var(--wp--preset--spacing--20);
  --ds-space-sm: var(--wp--preset--spacing--30);
  --ds-space-md: var(--wp--preset--spacing--40);
  --ds-space-lg: var(--wp--preset--spacing--50);
  --ds-space-xl: var(--wp--preset--spacing--60);
  --ds-space-section: var(--wp--preset--spacing--70);
  /* Shape and depth */
  --ds-radius-small: var(--wp--custom--radius--small);
  --ds-radius-card: var(--wp--custom--radius--card);
  --ds-radius-pill: var(--wp--custom--radius--pill);
  --ds-shadow-card: var(--wp--custom--shadow--card);
  /* Layout */
  --ds-measure: var(--wp--custom--measure);
  --ds-content: var(--wp--style--global--content-size);
  --ds-wide: var(--wp--style--global--wide-size);
}

/* ==========================================================================
   Generic — what the plugin's own CSS assumes, and nothing the parent owns.
   ==========================================================================

   Kadence is the client's frame and ships its own element defaults. This layer
   is not a reset of that frame: an element rule here reaches every element on
   the site, including the ones the parent draws. A global
   `img, svg { display: block }` did exactly that — it took Kadence's inline
   icons and inline images out of their lines, on every page, from a plugin
   whose business is the page content. Component media is styled by the
   component (see components/_banner.scss), never from here.

   What remains is what the plugin's components rely on.
   ========================================================================== */
/* Every width and padding in the role and component layers assumes border-box.
   Kadence resolves to the same box model, so this states the assumption rather
   than changing anything. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Let long words break rather than force a horizontal scrollbar. */
h1,
h2,
h3,
h4,
h5,
h6,
p,
li,
figcaption {
  overflow-wrap: break-word;
}

/* Respect a reduced-motion preference for everything the plugin animates. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important; /* stylelint-disable-line declaration-no-important -- an accessibility preference must beat presentation styles. */
    animation-iteration-count: 1 !important; /* stylelint-disable-line declaration-no-important -- as above. */
    transition-duration: 0.01ms !important; /* stylelint-disable-line declaration-no-important -- as above. */
    scroll-behavior: auto !important; /* stylelint-disable-line declaration-no-important -- as above. */
  }
}
/* ==========================================================================
   Roles — the invariant semantic vocabulary.
   ==========================================================================

   Every class here must have a matching entry in config/vocabulary.json, with
   its allowed blocks, conflicts and purpose. The build fails on a role class
   that is not declared there, and on a declared role with no implementation.

   Roles consume --ds-* only. A role name must never contain a design value:
   .ds-t-display is a role, .ds-text-48 is not.

   The first set is deliberately small and provisional. It was derived from
   semantic concepts in the Ascendant Article Subpages design export, not from
   its fixed pixel utilities or Kadence implementation.
   ========================================================================== */
.ds-t-display {
  color: var(--ds-color-heading);
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-display);
  font-weight: var(--ds-weight-bold);
  line-height: var(--ds-leading-heading);
}

.ds-t-section-title {
  color: var(--ds-color-heading);
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-title);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-heading);
}

.ds-t-subheading {
  color: var(--ds-color-heading);
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-large);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-heading);
}

.ds-t-lead {
  color: var(--ds-color-body);
  font-family: var(--ds-font-body);
  font-size: var(--ds-text-large);
  font-weight: var(--ds-weight-regular);
  line-height: var(--ds-leading-body);
}

.ds-t-longform {
  max-width: var(--ds-measure);
  color: var(--ds-color-body);
  font-family: var(--ds-font-body);
  font-size: var(--ds-text-base);
  font-weight: var(--ds-weight-regular);
  line-height: var(--ds-leading-body);
}

.ds-t-quote {
  color: var(--ds-color-heading);
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-large);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-body);
}

.ds-t-supporting {
  color: var(--ds-color-muted);
  font-family: var(--ds-font-body);
  font-size: var(--ds-text-small);
  font-weight: var(--ds-weight-regular);
  line-height: var(--ds-leading-body);
}

.ds-t-eyebrow {
  color: var(--ds-color-primary);
  font-family: var(--ds-font-heading);
  font-size: var(--ds-text-small);
  font-weight: var(--ds-weight-semibold);
  line-height: var(--ds-leading-heading);
  text-transform: uppercase;
}

.ds-measure {
  max-width: var(--ds-measure);
}

.ds-section-space {
  padding-block: var(--ds-space-section);
}

.ds-stack {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-md);
}

.ds-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ds-space-sm);
}

.ds-inverse {
  color: var(--ds-color-on-inverse);
  background-color: var(--ds-color-inverse-bg);
}

/* ==========================================================================
   Banner — the hooked hero.
   ==========================================================================

   Structure only. Layout, rhythm and shape live here because the plugin owns
   the markup, so it owns the rules targeting it. Colour comes from a role
   token, falling back to the site's own theme.json preset, so the banner
   renders plain but correct on a site with no Chassis tokens and right on one
   with them. No literal values.

   The background image itself is set inline by the renderer, because it is a
   per-page value rather than anything the design system has an opinion about.

   Front-end only: the banner is put into the frame by a placement adapter and
   is never drawn inside the editor canvas, so it is listed in vocabulary.json's
   frontEndOnly and editor.scss does not import it.
   ========================================================================== */
.c-banner {
  background-color: var(--ds-color-surface, var(--wp--preset--color--surface));
  padding-block: var(--ds-space-xl, 3rem);
  padding-inline: var(--ds-space-md, 1.25rem);
}

.c-banner--has-background {
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

/*
   The two grounds.

   Both re-point existing aliases rather than introducing colours, so a site
   that has mapped its tokens gets both variants for nothing and the plugin
   still knows no brand values.

   The roles move as a set — surface and every text role together — because
   changing a ground without the text on it is how a heading ends up at
   1.00:1. That is not hypothetical here: the brush stroke behind a headline
   measures 11.44:1 in ink and 1.47:1 in white against Ascendant's own swipe,
   so the light ground is what makes a swiped heading legible at all.

   Neither is a default. A banner with no ground set keeps whatever the site's
   own rules give it.

   In the light variant `background-image: none` is the load-bearing line. A
   site that wants a dark banner everywhere says so by painting .c-banner —
   Ascendant's token map gives it a gradient — and a light variant has to undo
   that, not merely state a background colour underneath it.
*/
.c-banner--light {
  background-color: var(--ds-color-surface, var(--wp--preset--color--surface));
  background-image: none;
  color: var(--ds-color-body, var(--wp--preset--color--body));
}

.c-banner--inverse {
  background-color: var(--ds-color-inverse-bg, var(--wp--preset--color--contrast));
  color: var(--ds-color-on-inverse, var(--wp--preset--color--base));
}

.c-banner--inverse :is(.c-banner__heading, .c-banner__body) {
  color: var(--ds-color-on-inverse, var(--wp--preset--color--base));
}

.c-banner--light :is(.c-banner__heading, .c-banner__body) {
  color: var(--ds-color-body, var(--wp--preset--color--body));
}

.c-banner__inner {
  display: grid;
  gap: var(--ds-space-lg, 2rem);
  margin-inline: auto;
  max-width: var(--ds-wide, 75rem);
}

/* Two columns once there is room for them, one column below that. */
.c-banner--two-column .c-banner__inner {
  align-items: center;
  grid-template-columns: 1fr;
}

@media (min-width: 48em) {
  .c-banner--two-column .c-banner__inner {
    grid-template-columns: 1fr 1fr;
  }
}
.c-banner__content {
  display: flex;
  flex-direction: column;
  gap: var(--ds-space-sm, 0.75rem);
}

/*
   Typography is repeated here, with fallbacks, on purpose.

   The role layer sets font-size: var(--ds-text-display) with no fallback, so on
   a site carrying no Chassis tokens the declaration is invalid and the heading
   inherits whatever the theme gives it. Measured on a Kadence site with no
   client token file: the display heading rendered at 18px while the body
   rendered at 36px — the hierarchy inverted.

   The component loads after the roles layer, so these win where a token is
   missing and lose to nothing where one is present. Remove them once the role
   layer carries its own fallbacks.
*/
.c-banner__heading {
  font-size: var(--ds-text-display, 2.25rem);
  font-weight: var(--ds-weight-bold, 700);
  line-height: var(--ds-leading-heading, 1.15);
}

.c-banner__body {
  font-size: var(--ds-text-large, 1.125rem);
  line-height: var(--ds-leading-body, 1.6);
  max-width: var(--ds-measure, 60ch);
}

.c-banner__body > p:last-child {
  margin-block-end: 0;
}

.c-banner__media img {
  border-radius: var(--ds-radius-card, 0.5rem);
  display: block;
  height: auto;
  max-width: 100%;
}

/* Breadcrumbs -------------------------------------------------------------- */
.c-banner__breadcrumbs {
  color: var(--ds-color-muted, var(--wp--preset--color--muted));
  display: flex;
  flex-wrap: wrap;
  font-size: var(--ds-text-small, 0.875rem);
  gap: var(--ds-space-xs, 0.5rem);
}

/* The crumbs are links, and nothing here ever said what a link looks like, so
   they took the browser's default underline. Every other link in the banner is
   declared; this one was inherited — the same omission that left the context
   tree taking Kadence's grey. A breadcrumb is orientation, not an invitation,
   so it underlines on hover and not before. */
.c-banner__breadcrumbs a {
  color: inherit;
  text-decoration: none;
}

.c-banner__breadcrumbs a:hover,
.c-banner__breadcrumbs a:focus-visible {
  text-decoration: underline;
}

.c-banner__crumb-sep {
  color: var(--ds-color-border, var(--wp--preset--color--border));
}

/* Geotag ------------------------------------------------------------------- */
.c-banner__geotag {
  color: var(--ds-color-muted, var(--wp--preset--color--muted));
  font-size: var(--ds-text-small, 0.875rem);
}

/* Calls to action ---------------------------------------------------------- */
.c-banner__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ds-space-sm, 0.75rem);
  margin-block-start: var(--ds-space-sm, 0.75rem);
}

/*
   The reassurance line under the actions.

   Muted and small on purpose: it qualifies the buttons rather than competing
   with them, and it is the last thing read before someone decides to click.
   It keeps a measure because it is a sentence, not a label.
*/
.c-banner__actions-note {
  color: var(--ds-color-muted, var(--wp--preset--color--muted));
  font-size: var(--ds-text-small, 0.875rem);
  margin-block-start: var(--ds-space-xs, 0.5rem);
  max-width: var(--ds-measure, 60ch);
}

.c-banner__button {
  border-radius: var(--ds-radius-pill, 2rem);
  display: inline-block;
  font-weight: var(--ds-weight-semibold, 600);
  padding-block: var(--ds-space-xs, 0.5rem);
  padding-inline: var(--ds-space-md, 1.25rem);
  text-decoration: none;
}

/*
   The last fallback is a named colour, not a brand one. A filled button whose
   fill does not resolve renders as transparent with dark text on a dark ground,
   which is the one failure worth spending a literal to avoid. Kadence names its
   palette --global-palette*, so the WordPress preset names do not resolve there
   either — the chain has to end somewhere real.
*/
.c-banner__button--primary {
  background-color: var(--ds-color-primary, var(--wp--preset--color--primary, black));
  color: var(--ds-color-on-inverse, var(--wp--preset--color--base, white));
}

/*
   The secondary action is outlined rather than filled. Two filled buttons of
   equal weight give the reader no steer, which is the point of having a
   second one at all.
*/
.c-banner__button--secondary {
  border: 1px solid var(--ds-color-primary, var(--wp--preset--color--primary, currentColor));
  color: var(--ds-color-primary, var(--wp--preset--color--primary, currentColor));
}

/* Quick links -------------------------------------------------------------- */
/*
   The field is called "Show Mobile Quick Links", and until now it was not
   mobile-only — it rendered at every width.

   On the site this came from, the hiding lived in the Kadence Element that
   carried the banner: it was set to hide on large screens (.kvs-lg-false).
   The chassis banner replaced that Element and inherited the markup but not
   the visibility rule, so every page with the legacy switch on grew a second
   section menu on desktop — the flat list here, plus the sidebar's tree.
   Measured on the clone: 74 published pages have that switch on.

   1025px is the breakpoint the context menu already uses to decide between
   its two presentations, and for the same reason: it is where the sidebar
   stops sitting beside the content. Above it a sidebar can carry the section
   menu, so this one is a duplicate. Below it there is no sidebar beside the
   reader, which is exactly when a menu at the top of the page earns its place.
*/
.c-banner__quick-links {
  margin-block-start: var(--ds-space-md, 1.25rem);
}

@media screen and (min-width: 1025px) {
  .c-banner__quick-links {
    display: none;
  }
}
.c-context-menu__root {
  display: inline-block;
  font-weight: var(--ds-weight-semibold, 600);
  text-decoration: none;
}

/*
   wp_list_pages supplies the list. Its own classes are left alone, so a site
   already styling the retired shortcode keeps the styling it has; only the
   reset below is ours.
*/
.c-context-menu__list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.c-context-menu__list a {
  display: inline-block;
  padding-block: var(--ds-space-xs, 0.5rem);
}/*# sourceMappingURL=main.css.map */
