@charset "UTF-8";
/* !! THIS FILE IS SCSS SOURCE, NOT THE CSS THE BROWSER GETS.
 *
 * Snippet 20778 is authored in SCSS on purpose: its ASE `options` meta carries
 * `language: css` + `compile_scss: yes`, and ASE runs its own compiler on an
 * admin-screen save (admin-site-enhancements-pro/functions.php:2481-2491).
 * The nesting, `@mixin`, `@function` and `&--modifier` syntax below is correct
 * and intentional — do NOT "fix" it into flat CSS.
 *
 * !! NEVER copy this file straight into wp-content/uploads/code-snippets/.
 * That is the right mechanic for the PHP snippet (20776) and WRONG here: it
 * bypasses the compiler, so raw SCSS gets SERVED as CSS. Browsers then silently
 * drop every nested rule — `.ps-grid` loses its `gap`, `.ps-btn--primary` never
 * exists, `.ps-card--report` never applies — and the pages look degraded with
 * no error anywhere. That is exactly what happened between #45 and #47.
 *
 * To publish a change here, run it through ASE's OWN compiler and write the
 * result (see the #47 changelog entry for the script), then bump the stored
 * cachebuster — which lives in the option
 * `admin_site_enhancements_extra['code_snippets']['css'][20778]['filename']`
 * (e.g. `20778.css?v=4797`), NOT the sibling top-level `cachebuster` key.
 * Verify in a browser that `getComputedStyle(document.querySelector('.ps-grid')).gap`
 * is a real length and not `normal`.
 */
/* =========
   TOKENS
   ========= */
:root {
  /* BRAND COLORS */
  --ps-color-primary: #E1493C;
  --ps-color-primary-strong: #E1493C;
  /* hover/active */
  --ps-color-accent: #E1493C;
  /* alt primary (used in .ps-btn--primary bg) */
  --ps-color-bg: #ffffff;
  --ps-color-surface: #ffffff;
  --ps-color-border: #eeeeee;
  --ps-color-border-strong: #dddddd;
  --ps-color-text: #111111;
  --ps-color-text-muted: #666666;
  /* TYPOGRAPHY */
  --ps-font-size-xs: 0.75rem;
  --ps-font-size-sm: 0.875rem;
  --ps-font-size-base: 1rem;
  --ps-font-size-lg: 1.125rem;
  --ps-line-tight: 1.2;
  --ps-line-normal: 1.5;
  /* SPACING SCALE */
  --ps-space-1: 0.25rem;
  --ps-space-2: 0.5rem;
  --ps-space-3: 0.75rem;
  --ps-space-4: 1rem;
  --ps-space-5: 1.25rem;
  --ps-space-6: 1.5rem;
  --ps-space-7: 1.75rem;
  --ps-space-8: 2rem;
  /* RADII */
  --ps-radius-s: 4px;
  --ps-radius-m: 6px;
  --ps-radius-l: 8px;
  --ps-radius-pill: 999px;
  /* SHADOWS */
  --ps-shadow-s: 0 2px 6px rgba(0,0,0,.06);
  --ps-shadow-m: 0 4px 12px rgba(0,0,0,.08);
  /* TRANSITIONS */
  --ps-ease-fast: 0.15s ease;
  --ps-ease-med: 0.2s ease;
  /* GRID DEFAULTS */
  --ps-gap: 1.5rem;
  --ps-columns: 3;
  /* SLIDER UI */
  --ps-arrow-size: 40px;
  --ps-arrows-gap: 12px;
  --ps-arrows-right: 12px;
  --ps-arrows-bottom: 12px;
  --ps-pagination-offset: 30px;
  /* COMPONENT TOKENS (overridable per-variant) */
  --ps-card-bg: var(--ps-color-surface);
  --ps-card-border: var(--ps-color-border);
  --ps-card-radius: var(--ps-radius-l);
  --ps-card-title-size: var(--ps-font-size-lg);
  --ps-card-title-hover: var(--ps-color-primary);
  /* Unreferenced since the hardcoded testimonial block was removed (#44), kept
     deliberately: these are the brand's testimonial colours (and their dark
     variants below), which a generic-card testimonial would want. Tokens are
     cheap; re-deciding a brand colour is not. */
  --ps-testimonial-bg: #2b87da;
  --ps-testimonial-text: #ffffff;
  --ps-btn-primary-bg: var(--ps-color-accent);
  --ps-btn-primary-border: var(--ps-color-primary);
  --ps-btn-primary-hover: var(--ps-color-primary-strong);
  --ps-btn-muted-bg: #eef2f5;
  --ps-btn-muted-border: #d9dee3;
  --ps-btn-muted-text: #111111;
}
/* Optional: dark theme example */
[data-theme="dark"] {
  --ps-color-bg: #0f1115;
  --ps-color-surface: #161a22;
  --ps-color-border: #232733;
  --ps-color-border-strong: #2d3342;
  --ps-color-text: #e6e8ee;
  --ps-color-text-muted: #aab0bf;
  --ps-card-bg: var(--ps-color-surface);
  --ps-card-border: var(--ps-color-border);
  --ps-card-title-hover: #5bb8ff;
  --ps-testimonial-bg: #1f6bb0;
  --ps-testimonial-text: #eaf3ff;
  --ps-btn-muted-bg: #222837;
  --ps-btn-muted-border: #2f3750;
  --ps-btn-muted-text: #e6e8ee;
}
/* =========
   SCSS HELPERS
   ========= */
/* Breakpoints as tokens for consistent media queries */
/* Grid defaults (synced to CSS vars for runtime overrides if needed) */
/* Quick media-down mixin */
/* Utility: pull a CSS variable with a SCSS fallback */
/* ==== Grid ==== */
.ps-grid {
  display: grid;
  gap: var(--ps-gap, var(--ps-gap));
  grid-template-columns: repeat(var(--ps-columns, var(--ps-columns)), 1fr);
  /* Low-specificity modifiers */
}
.ps-grid:where(.columns-1) {
  grid-template-columns: 1fr;
}
.ps-grid:where(.columns-2) {
  grid-template-columns: repeat(2, 1fr);
}
.ps-grid:where(.columns-3) {
  grid-template-columns: repeat(3, 1fr);
}
.ps-grid:where(.columns-4) {
  grid-template-columns: repeat(4, 1fr);
}
.ps-grid:where(.columns-5) {
  grid-template-columns: repeat(5, 1fr);
}
@media (max-width: 1199px) {
  .ps-grid:where(.columns-4) {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 1023px) {
  .ps-grid:where(.columns-4) {
    grid-template-columns: repeat(2, 1fr);
  }
  .ps-grid:where(.columns-3) {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 767px) {
  .ps-grid {
    grid-template-columns: 1fr;
  }
}
/* ==== Default card ==== */
.ps-card {
  background: var(--ps-card-bg);
  border: 1px solid var(--ps-card-border);
  border-radius: var(--ps-card-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform var(--ps-ease-med), box-shadow var(--ps-ease-med);
}
.ps-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--ps-shadow-m);
}
.ps-card .ps-card-thumb {
  display: block;
  aspect-ratio: 1.7777777778;
  overflow: hidden;
  position: relative;
}
.ps-card .ps-card-thumb .ps-card-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ps-card .ps-card-body {
  padding: var(--ps-space-4);
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.ps-card .ps-card-body .ps-card-title {
  font-size: var(--ps-card-title-size);
  margin: 0 0 var(--ps-space-2);
  line-height: 1.3;
}
.ps-card .ps-card-body .ps-card-title a {
  text-decoration: none;
  color: inherit;
}
.ps-card .ps-card-body .ps-card-title a:hover {
  color: var(--ps-card-title-hover);
}
.ps-card .ps-card-body .ps-card-date {
  font-size: var(--ps-font-size-sm);
  color: var(--ps-color-text-muted);
  margin-top: auto;
}
.ps-card .ps-card-body .ps-card-meta {
  margin-top: auto;
  display: flex;
  gap: var(--ps-space-2);
  flex-wrap: wrap;
}
.ps-card .ps-card-actions {
  padding-top: var(--ps-space-3);
  margin-top: auto;
}
/* ==== Numbered pagination (grid) ==== */
.ps-pagination {
  margin-top: var(--ps-space-8);
  text-align: center;
}
.ps-pagination .page-numbers {
  display: inline-block;
  margin: 0 var(--ps-space-1);
  padding: var(--ps-space-2) var(--ps-space-3);
  border: 1px solid var(--ps-color-border-strong);
  border-radius: var(--ps-radius-s);
  text-decoration: none;
  color: var(--ps-color-text);
}
.ps-pagination .page-numbers.current {
  background: var(--ps-color-primary);
  color: #fff;
  border-color: var(--ps-color-primary);
}
.ps-pagination .page-numbers:hover {
  background: #f5f5f5;
}
/* Visible to screen readers only — the load-more status message (#54).
   Clipped rather than display:none, which would remove it from the
   accessibility tree and silence the announcement entirely. */
.ps-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* ==== Load More button (grid) — issue #54 ====
   DM renders `<div class="dmach-loadmore et_pb_button" tabindex="0">`: a div
   with a tabindex, so it is neither a link nor a button and carries no role.
   This ships an <a href> to the next page instead — same look, but it is
   focusable, announced, and still works with JS off, which DM's never did. */
.ps-loadmore {
  margin-top: var(--ps-space-8);
  text-align: center;
}
.ps-loadmore-button {
  display: inline-block;
  padding: var(--ps-space-2) var(--ps-space-6);
  border: 1px solid var(--ps-color-primary);
  border-radius: var(--ps-radius-s);
  background: var(--ps-color-primary);
  color: #fff;
  text-decoration: none;
  cursor: pointer;
}
.ps-loadmore-button:hover, .ps-loadmore-button:focus-visible {
  background: var(--ps-color-primary-strong);
  border-color: var(--ps-color-primary-strong);
}
/* The results region dims while a request is in flight (.is-loading). During
   an APPEND the cards already on screen are real content the visitor is still
   reading, so only the pending control is dimmed, not the whole set. */
.ps-loop-results.is-loading .ps-loadmore-button {
  opacity: 0.6;
  pointer-events: none;
}
/* The testimonial-card rules were removed with the hardcoded `testimonial`
   template block (issue #44) — a testimonial now renders through the generic
   card, whose quote uses `tag=blockquote`. Verified free: none of the deleted
   blocks' classes are referenced anywhere else on the site. */
/* ==== Swiper slider: equal height + UI placement ==== */
.ps-slider {
  position: relative;
  overflow: visible;
  /* equal-height slides */
  /* space for arrows + room for bullets */
  padding-bottom: calc(var(--ps-arrow-size) + var(--ps-arrows-bottom) + 8px) !important;
  margin-bottom: calc(var(--ps-pagination-offset) + 16px);
}
.ps-slider .swiper-wrapper {
  align-items: stretch;
}
.ps-slider .swiper-slide {
  height: auto;
}
.ps-slider .ps-card {
  height: 100%;
}
/* bullets under the card area */
.ps-slider .ps-swiper-pagination {
  bottom: calc(-1 * var(--ps-pagination-offset));
  width: auto !important;
}
/* bullets style */
.ps-swiper-pagination .swiper-pagination-bullet {
  background: #ddd;
}
.ps-swiper-pagination .swiper-pagination-bullet-active {
  background: var(--ps-color-primary);
}
/* nav buttons base look */
.ps-swiper-button-prev, .ps-swiper-button-next {
  color: var(--ps-color-primary) !important;
  border: 1px solid var(--ps-color-border-strong);
  background: var(--ps-color-bg);
  width: var(--ps-arrow-size) !important;
  height: var(--ps-arrow-size) !important;
  border-radius: var(--ps-radius-pill);
  box-shadow: var(--ps-shadow-s);
  padding: 8px;
}
.ps-swiper-button-prev:after, .ps-swiper-button-next:after {
  font-size: 16px !important;
}
/* pin both arrows bottom-right, side-by-side */
.ps-slider .ps-swiper-button-prev, .ps-slider .ps-swiper-button-next {
  position: absolute;
  z-index: 5;
  pointer-events: all;
  top: auto;
  left: auto;
  bottom: var(--ps-arrows-bottom);
}
.ps-slider .ps-swiper-button-next {
  right: var(--ps-arrows-right);
}
.ps-slider .ps-swiper-button-prev {
  right: calc(var(--ps-arrows-right) + var(--ps-arrow-size) + var(--ps-arrows-gap));
}
/* FOUC Guard */
.ps-slider {
  min-height: var(--ps-min-h, 280px);
  opacity: 0;
  transition: opacity var(--ps-ease-med);
}
.ps-slider.swiper-initialized {
  opacity: 1;
}
.ps-slider .ps-swiper-button-prev, .ps-slider .ps-swiper-button-next, .ps-slider .ps-swiper-pagination {
  opacity: 0;
  visibility: hidden;
}
.ps-slider.swiper-initialized .ps-swiper-button-prev, .ps-slider.swiper-initialized .ps-swiper-button-next, .ps-slider.swiper-initialized .ps-swiper-pagination {
  opacity: 1;
  visibility: visible;
}
/* Minimal pre-init layout */
.ps-slider .swiper-wrapper {
  display: flex;
}
.ps-slider .swiper-slide {
  flex: 0 0 auto;
}
@media (max-width: 600px) {
  .ps-slider {
    --ps-arrow-size: 34px;
    --ps-arrows-gap: 6px;
    --ps-arrows-right: 8px;
    --ps-arrows-bottom: 8px;
    --ps-pagination-offset: 20px;
    min-height: var(--ps-min-h-mobile, 240px);
  }
}
/* ==== Buttons used inside cards ==== */
.ps-btn {
  display: inline-block;
  padding: 0.6rem 0.9rem;
  min-width: 128px;
  text-align: center;
  border-radius: var(--ps-radius-s);
  text-decoration: none;
  font-weight: 600;
  line-height: 1;
  border: 1px solid transparent;
  transition: background var(--ps-ease-fast), color var(--ps-ease-fast), border-color var(--ps-ease-fast);
}
.ps-btn--primary {
  background: var(--ps-btn-primary-bg);
  color: #fff;
  border-color: var(--ps-btn-primary-border);
}
.ps-btn--primary:hover {
  background: var(--ps-btn-primary-hover);
  border-color: var(--ps-btn-primary-hover);
}
.ps-btn--muted {
  background: var(--ps-btn-muted-bg);
  color: var(--ps-btn-muted-text);
  border-color: var(--ps-btn-muted-border);
}
.ps-btn--muted:hover {
  background: color-mix(in oklab, var(--ps-btn-muted-bg), #000 5%);
}
/* The jobs-listing-card and news-press-card rules were removed with their
   hardcoded template blocks (issue #44). Both now render through the generic
   card: the jobs CTA via `cta=Apply`, the press badge via `press_category:tax`.
   Verified free: neither block's classes are referenced anywhere on the site. */
/* ==== Report Card ==== */
.ps-card--report {
  position: relative;
}
.ps-card--report .ps-card-title > a::before {
  position: absolute;
  content: "";
  display: block;
  top: 0;
  right: 0;
  width: 100%;
  height: 100%;
}
.ps-card--report .ps-card-thumb {
  aspect-ratio: auto;
}
.ps-card--report .ps-card-thumb .ps-card-image {
  height: auto;
}
.ps-card--report .ps-btn {
  width: 100%;
}
.ps-card--report .ps-card-meta {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 4px;
}
.ps-card--report .ps-card-desc {
  font-size: 16px;
  line-height: 1.5;
  text-wrap: pretty;
  overflow: hidden;
  /*   display: -webkit-box;
  -webkit-line-clamp: 3; 
  -webkit-box-orient: vertical; */
}
/* =====================================
   PEOPLE CARD (template="people-card")
   ===================================== */
/* Make the People card inherit your default card look */
.ps-person-card {
  background: var(--ps-card-bg);
  border: 1px solid var(--ps-card-border);
  border-radius: var(--ps-card-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: var(--ps-space-5) var(--ps-space-4);
  transition: transform var(--ps-ease-med), box-shadow var(--ps-ease-med);
  /* tighten spacing between the module blocks */
  /* Center blocks that should read like a profile card */
}
.ps-person-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--ps-shadow-m);
}
.ps-person-card .et_pb_module {
  margin-bottom: var(--ps-space-3);
}
.ps-person-card .et_pb_module:last-child {
  margin-bottom: 0;
}
.ps-person-card .et_pb_de_mach_thumbnail, .ps-person-card .et_pb_de_mach_title, .ps-person-card .et_pb_de_mach_acf_item, .ps-person-card .ps-person-links, .ps-person-card .ps-person-bio {
  text-align: center;
}
/* Circle headshot crop */
.ps-person-card .ps-circle-crop img, .ps-person-card .ps-headshot img, .ps-person-card .featured-image {
  display: block;
  width: 100%;
  height: auto;
  max-width: 240px;
  margin: 0 auto var(--ps-space-2);
  border-radius: 50%;
  aspect-ratio: 1;
  object-fit: cover;
}
/* Name */
.ps-person-card .dmach-post-title, .ps-person-card .entry-title {
  margin: 0 0 var(--ps-space-1);
  line-height: 1.25;
  font-size: var(--ps-card-title-size);
}
.ps-person-card .dmach-post-title a, .ps-person-card .entry-title a {
  text-decoration: none;
  color: inherit;
}
.ps-person-card .dmach-post-title a:hover, .ps-person-card .entry-title a:hover {
  color: var(--ps-card-title-hover);
}
/* Main title or affiliations line */
.ps-person-card .ps-turq, .ps-person-card .dmach-acf-value {
  font-size: var(--ps-font-size-sm);
  color: var(--ps-color-text-muted);
}
/* The “Chair / role” line in your screenshot looks more like a label */
.ps-person-card .et_pb_de_mach_acf_item.ps-xs.ps-bold.ps-turq .dmach-acf-value {
  font-size: var(--ps-font-size-sm);
  font-weight: 700;
  color: color-mix(in oklab, var(--ps-color-primary), #000 10%);
}
/* Icon row */
.ps-person-links {
  display: flex;
  justify-content: center;
  gap: var(--ps-space-3);
  margin-top: var(--ps-space-2);
  margin-bottom: var(--ps-space-2);
}
/* Base icon button */
.ps-person-links a.ps-icon-acf {
  width: 38px;
  height: 38px;
  border-radius: var(--ps-radius-pill);
  border: 1px solid var(--ps-color-border-strong);
  background: var(--ps-color-bg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  box-shadow: var(--ps-shadow-s);
  transition: transform var(--ps-ease-fast), box-shadow var(--ps-ease-fast), border-color var(--ps-ease-fast);
}
.ps-person-links a.ps-icon-acf:hover {
  transform: translateY(-1px);
  border-color: var(--ps-color-primary);
  box-shadow: var(--ps-shadow-m);
}
/* If you already have icon CSS tied to these classes, keep it.
   If not, this adds simple fallback glyphs without needing Divi Machine. */
.ps-person-links a.ps-icon-acf::before {
  font-size: 16px;
  line-height: 1;
  color: var(--ps-color-primary);
  content: "↗";
}
.ps-person-links a.ps-icon-acf-linkedin::before {
  content: "in";
  font-weight: 800;
}
.ps-person-links a.ps-icon-acf-globe::before {
  content: "⌂";
}
/* =========================================================
   GENERIC FIELD-LIST CARD (issue #41)
   Reference copy — source of truth is ASE snippet 20778.
   The generic card reuses the .ps-card skeleton above, so a
   basic card needs no CSS; these style only the new per-field
   hooks it emits (.ps-field / labels / chips / repeater). No
   live layout uses template="generic" yet, so nothing here
   changes an existing render.
   ========================================================= */
.ps-card--generic .ps-field {
  font-size: var(--ps-font-size-sm);
  color: var(--ps-color-text);
  margin: 0 0 var(--ps-space-2);
}
.ps-card--generic .ps-field:last-child {
  margin-bottom: 0;
}
.ps-card--generic .ps-field-label {
  font-weight: 700;
  color: var(--ps-color-text-muted);
}
.ps-card--generic .ps-field--rich .ps-field-value--rich > :last-child {
  margin-bottom: 0;
}
.ps-card--generic .ps-field-image {
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: var(--ps-radius-s);
}
/* checkbox / radio chips */
.ps-card--generic .ps-field-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--ps-space-1);
}
.ps-card--generic .ps-chip {
  display: inline-block;
  padding: 2px var(--ps-space-2);
  font-size: var(--ps-font-size-xs);
  line-height: 1.6;
  border: 1px solid var(--ps-color-border-strong);
  border-radius: var(--ps-radius-pill);
  background: #f7f7f7;
}
/* post_object / relationship links */
.ps-card--generic .ps-field-link {
  color: var(--ps-color-primary);
  text-decoration: none;
}
.ps-card--generic .ps-field-link:hover {
  text-decoration: underline;
}
/* repeater rows (recurses to any depth) */
.ps-card--generic .ps-repeater {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--ps-space-2);
}
/* #161: BLOCK, not flex.
 *
 * This was `display:flex; flex-wrap:wrap`, so a row's fields flowed inline and
 * wrapped only when they no longer fit — which made the layout depend on how
 * long the LABEL happened to be:
 *
 *   /events/2024-signature-series...  "Key Resources"        147+959 =1106px -> FITS  -> 2 columns
 *                                     "Additional Resources" 212+1152=1364px -> wraps -> stacked
 *   /events/vop-summit-day1           (empty label)                          -> always stacked
 *
 * The same layout therefore rendered one column on one page and two on another,
 * purely on character count. Every repeater on this site carries exactly TWO
 * sub-fields per row (a label + its content), so there is nothing that wants
 * them side by side. */
.ps-card--generic .ps-repeater-row {
  display: block;
  padding: var(--ps-space-2) 0;
  border-bottom: 1px solid var(--ps-color-border);
}
.ps-card--generic .ps-repeater-row:last-child {
  border-bottom: 0;
}
/* nested repeater indents one step */
.ps-card--generic .ps-repeater .ps-repeater {
  margin-left: var(--ps-space-3);
  width: 100%;
}
/* `tag=` semantic wrapper (issue #44) — absorbed from the deleted testimonial
   block, which hardcoded a <blockquote>. Styles the quote case; the other
   allowlisted elements (q/cite/em/strong/small/mark/address) keep their UA
   defaults, which is the point of choosing a real element. */
.ps-card--generic blockquote.ps-field-tagged {
  margin: 0 0 var(--ps-space-2);
  padding-left: var(--ps-space-3);
  border-left: 3px solid var(--ps-color-accent);
  font-style: italic;
}
.ps-card--generic cite.ps-field-tagged {
  font-style: normal;
  opacity: 0.8;
}
/* NB — PRE-EXISTING DEFECT, found in #45 — NOT introduced by it, and NOT
   silently "fixed" by inventing content.
   This rule is TRUNCATED at `content: "` \2014  no closing quote, no brace, no
   trailing newline \2014  in the repo file AND in the live ASE snippet 20778, in
   every commit back to #40. The intended glyph is UNRECOVERABLE: the stored
   value ends mid-string (verified by hex dump of the live DB copy), so it was
   never saved anywhere.
   Because the rule never terminated, it swallowed everything appended after
   it: the whole facet block below parsed as part of THIS selector and applied
   to nothing (0 facet rules reached the CSSOM). Terminating it is what makes
   any later rule in this file reachable at all.
   Left as an EMPTY content string, which is what the file effectively already
   declared. No live page uses `ps-icon-acf-twitter` (0 occurrences across the
   site), so nothing visitor-visible changes either way. If the X/Twitter glyph
   is wanted, that is a deliberate content decision for Rafal, not a repair. */
.ps-person-links a.ps-icon-acf-twitter::before {
  content: "";
  font-weight: 800;
}
/* ==========================================================================
   AJAX FACET CONTROLS (issue #45)
   --------------------------------------------------------------------------
   The filter UI above a faceted loop. Reuses the existing tokens and the
   existing .ps-btn — a facet form introduces no new colour or spacing values.
   ========================================================================== */
.ps-facets {
  margin-bottom: var(--ps-space-5);
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--ps-space-4);
}
.ps-facets-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ps-space-4);
  flex: 1 1 auto;
}
.ps-facet {
  display: flex;
  flex-direction: column;
  gap: var(--ps-space-1);
  min-width: 12rem;
  flex: 1 1 12rem;
}
/* Every control keeps a VISIBLE label — a placeholder is not a label. */
.ps-facet-label {
  font-size: var(--ps-font-size-sm);
  font-weight: 600;
  color: var(--ps-color-text);
  line-height: var(--ps-line-tight);
}
.ps-facet-input, .ps-facet-select {
  /* 2.75rem clears the 24x24 minimum target with room to spare (WCAG 2.5.8). */
  min-height: 2.75rem;
  padding: var(--ps-space-2) var(--ps-space-3);
  font-size: var(--ps-font-size-base);
  color: var(--ps-color-text);
  background: var(--ps-color-surface);
  border: 1px solid var(--ps-color-border-strong);
  border-radius: var(--ps-radius-s);
  width: 100%;
}
.ps-facet-input:focus-visible, .ps-facet-select:focus-visible, .ps-facets .ps-btn:focus-visible {
  outline: 2px solid var(--ps-color-primary);
  outline-offset: 2px;
}
.ps-facets-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ps-space-2);
}
.ps-facets-actions .ps-btn {
  min-height: 2.75rem;
  min-width: auto;
  padding-inline: var(--ps-space-4);
  cursor: pointer;
}
.ps-facet-reset {
  background: transparent;
  color: var(--ps-color-text-muted);
  border-color: var(--ps-color-border-strong);
}
.ps-facet-reset:hover {
  color: var(--ps-color-text);
}
/* Loading state. Dimming alone would leave a reduced-motion user with no
   signal that anything is happening, so the results also announce themselves
   via aria-busy on the live region (see print_facet_js). */
.ps-loop-results.is-loading {
  opacity: 0.55;
  transition: opacity var(--ps-ease-fast);
}
@media (prefers-reduced-motion: reduce) {
  .ps-loop-results.is-loading {
    transition: none;
  }
}
/* Stack the controls on narrow screens rather than squeezing them. */
@media (max-width: 640px) {
  .ps-facet {
    flex-basis: 100%;
  }
  .ps-facets-actions {
    width: 100%;
  }
  .ps-facets-actions .ps-btn {
    flex: 1 1 auto;
  }
}
/* ---------------------------------------------------------------------------
   Preview list separators (issue #57 — the Newsroom cluster).

   Page 76's two preview loops carried DM's `module_class="ps-preview-list"`,
   whose theme rules (PlantedSky/style.css:762-773) are scoped to
   `.dmach-grid-item` — markup that no longer exists once the loop is a
   [ps_loop]. The separator border and the vertical rhythm between items are
   visible styling, so they are re-expressed here against the card the generic
   template emits, applied per-card via `class=ps-preview-item`.

   The theme's `.ps-preview-list .loop-grid` flex rule is NOT ported: `.ps-grid`
   with `columns-1` already lays out a single column, so it would be redundant.
   --------------------------------------------------------------------------- */
.ps-card.ps-preview-item {
  border-bottom: 1px solid var(--ahp-lightgray);
  padding-bottom: 1em;
}
.ps-card.ps-preview-item:not(:first-child) {
  padding-top: 1em;
}
/* ---------------------------------------------------------------------------
   PORTED FROM PRODUCTION (#159, 2026-08-20)
   ---------------------------------------------------------------------------
   These blocks exist in the LIVE production snippet 20778 and were missing from
   this repo copy. Rafal caught the symptom on the people cards: "Read Bio"
   rendered with the browser's default ▶ marker beside the intended ▾, because
   `.ps-bio-details` / `.ps-bio-summary` had no rules at all here.

   The repo copy is newer and larger overall — it gained the whole facet/field
   system (`ps-facet*`, `ps-field*`, `ps-card--generic`) — but regressed on
   these. Same shape as the engine gap on snippet 20776, where production has 7
   named card templates the repo engine lost.

   Copied verbatim from production's SCSS so the rendering matches the live site
   exactly rather than being re-derived.
   --------------------------------------------------------------------------- */
/* ==== Testimonial card (grid or slider) ==== */
.testimonial-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--ps-testimonial-bg);
  color: var(--ps-testimonial-text);
  border-radius: var(--ps-radius-l);
  padding: 28px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--ps-shadow-s);
}
.testimonial-card::after {
  content: "”";
  position: absolute;
  right: 24px;
  bottom: 8px;
  font-size: 96px;
  line-height: 1;
  opacity: 0.18;
  pointer-events: none;
}
.testimonial-card .t-content {
  margin: 0 0 24px 0;
  font-size: 18px;
  line-height: 1.6;
  font-weight: 500;
}
.testimonial-card blockquote {
  border: none;
  padding-left: 0;
}
.testimonial-card .t-meta {
  margin-top: auto;
  display: grid;
  gap: 2px;
}
.testimonial-card .t-meta .t-author {
  font-weight: 700;
  margin-bottom: 2px;
}
.testimonial-card .t-meta .t-position {
  font-size: 14px;
  font-weight: 600;
  opacity: 0.95;
}
.testimonial-card .t-meta .t-company-size {
  font-size: 14px;
  opacity: 0.9;
}
@media (max-width: 1023px) {
  .testimonial-card {
    padding: 24px;
  }
  .testimonial-card .t-content {
    font-size: 17px;
  }
}
@media (max-width: 600px) {
  .testimonial-card {
    padding: 20px;
  }
  .testimonial-card .t-content {
    font-size: 16px;
  }
}
/* ==== Jobs card (2/3 : 1/3 layout) ==== */
.ps-card--job {
  position: relative;
}
.ps-card--job .ps-card-body {
  display: flex;
  align-items: center;
  gap: var(--ps-space-4);
  flex-direction: row;
}
.ps-card--job .ps-job-left {
  flex: 2 1 0%;
  min-width: 0;
}
.ps-card--job .ps-job-right {
  flex: 1 1 0%;
  text-align: right;
}
.ps-card--job .ps-job-location {
  color: #444;
  font-size: 0.95rem;
  opacity: 0.9;
}
.ps-card--job .ps-btn:before {
  position: absolute;
  content: "";
  display: block;
  top: 0;
  right: 0;
  width: 100%;
  height: 100%;
}
@media (max-width: 600px) {
  .ps-card--job .ps-card-body {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--ps-space-3);
  }
  .ps-card--job .ps-job-right {
    width: 100%;
    text-align: left;
  }
}
/* ==== News / Press card ==== */
.ps-card--press {
  position: relative;
  padding-top: 32px;
  padding-bottom: 16px;
}
.ps-card--press .ps-card-body {
  display: flex;
}
.ps-card--press .ps-card-body > div:last-child {
  margin-top: auto;
}
.ps-card--press .ps-press-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  background: #6b7280;
  color: #fff;
  font-size: 12px;
  padding: 6px 8px;
  border-radius: var(--ps-radius-s);
  line-height: 1;
  pointer-events: none;
}
.ps-card--press .ps-press-logo {
  margin: 0.25rem 0 0.5rem;
  aspect-ratio: 1.7777777778;
  height: 140px;
}
.ps-card--press .ps-press-logo-img {
  display: block;
  max-width: 100%;
  height: 100%;
  object-fit: contain;
}
.ps-card--press .ps-card-meta {
  flex-direction: column;
  margin-top: unset !important;
}
.ps-card--press .ps-press-source {
  font-weight: 600;
  text-decoration: none;
  color: #0a58ca;
}
.ps-card--press .ps-press-source:hover {
  text-decoration: underline;
}
.ps-card--press .ps-press-date {
  color: var(--ps-color-text-muted);
  font-size: 0.9rem;
}
.ps-card--press .ps-card-actions {
  padding-top: 16px;
}
/* ==== People card: bio toggle ====
   The <details>/<summary> the engine emits (render_card, ~line 4013) had no
   styling here, so the browser painted its own ▶ marker next to the intended ▾. */
.ps-person-bio {
  margin-top: auto;
  padding-top: var(--ps-space-2);
  text-align: left;
}
/* Remove default marker styling */
.ps-person-bio .ps-bio-details summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.ps-person-bio .ps-bio-details summary::-webkit-details-marker {
  display: none;
}
.ps-person-bio .ps-bio-summary {
  display: inline-flex;
  align-items: center;
  gap: var(--ps-space-2);
  font-size: var(--ps-font-size-sm);
  font-weight: 700;
  color: var(--ps-color-primary);
  text-decoration: none;
  margin: 0 auto;
}
/* "Read Bio" centered */
.ps-person-bio .ps-bio-details {
  text-align: center;
}
.ps-person-bio .ps-bio-content {
  margin-top: var(--ps-space-3);
  text-align: left;
  font-size: var(--ps-font-size-sm);
  line-height: var(--ps-line-normal);
  color: var(--ps-color-text-muted);
}
/* Give the expanded bio some breathing room */
.ps-person-bio .ps-bio-content p:last-child {
  margin-bottom: 0;
}
/* ---------------------------------------------------------------------------
   DIVI 5 LINK-COLOUR OVERRIDE (#159, 2026-08-20)
   ---------------------------------------------------------------------------
   Divi 5 emits a global link rule that Divi 4 does not:

       a, .et-db #et-boc .et-l a { color: var(--gcid-link-color, #e02b20); }

   Its 3-part selector (0-3-1) outranks our single-class `.ps-btn--primary`
   (0-1-0), so every [ps_loop] button rendered its label in the theme red ON the
   button's red background -- red on red. Rafal caught it on /signature-series;
   D4 has ZERO `.et-l a` rules, so this is introduced by the D5 migration, not a
   pre-existing design choice.

   Matching Divi's own specificity is the minimal fix -- no !important, and it
   only applies inside a ps_loop button.
   --------------------------------------------------------------------------- */
.et-db #et-boc .et-l a.ps-btn--primary, a.ps-btn--primary {
  color: #fff;
}
.et-db #et-boc .et-l a.ps-btn--muted, a.ps-btn--muted {
  color: var(--ps-btn-muted-text);
}
/* The card title is a link too: Divi 5's rule would tint every card heading. */
.et-db #et-boc .et-l .ps-card-title a, .ps-card-title a {
  color: inherit;
}
.et-db #et-boc .et-l .ps-card-title a:hover, .ps-card-title a:hover {
  color: var(--ps-card-title-hover);
}
/* #161 — restore D4's spacing around the `|` separator in a linked post-object list.
 *
 * ps-post-object-dynamic-content.php joins each item with the separator the block
 * stores, and these blocks store a bare `|` (D4 stored no separator at all — its
 * spacing came from each audience being its own DM module). Result: D4 renders
 * `A | B | C` and the converted version renders `A|B|C`.
 *
 * Presentational only — same items, same links, same order. Measured on
 * /signature-series-2026 (.ps-audience-list, 3 linked items). */
.et-db #et-boc .et-l .linked_list_item + .linked_list_item::before, .linked_list_item + .linked_list_item::before {
  content: "";
  display: inline-block;
  width: 0.35em;
}
.et-db #et-boc .et-l .linked_list_item::after, .linked_list_item::after {
  content: "";
  display: inline-block;
  width: 0.35em;
}
.et-db #et-boc .et-l .linked_list_item:last-child::after, .linked_list_item:last-child::after {
  width: 0;
}
/* #161 — card titles must keep the card's own size, not Divi's global heading size.
 *
 * Divi emits `.et-db #et-boc .et-l h2 { font-size: 41px }` (and h3/h4 equivalents)
 * with an ID in the selector, so it outranks `.ps-card .ps-card-body .ps-card-title`
 * wherever Divi's page CSS happens to load AFTER the loop stylesheet. The result is
 * page-dependent: /reports rendered its H2 card titles at 18px while
 * /signature-series-2026 rendered the SAME markup at 35-41px.
 *
 * Measured 2026-08-26: identical card markup, identical `--ps-card-title-size`
 * (1.125rem), different computed size — the only difference was which stylesheet
 * won. Matching Divi's specificity settles it for every page.
 *
 * D4 renders these at 18px, so this restores parity rather than imposing a new look. */
.et-db #et-boc .et-l .ps-card .ps-card-body .ps-card-title, .et-db #et-boc .et-l .ps-card .ps-card-title, .ps-card .ps-card-body .ps-card-title, .ps-card .ps-card-title {
  font-size: var(--ps-card-title-size);
  line-height: 1.3;
}
/* #161 — sponsor tier headings + logo grid.
 *
 * D4 rendered this section through a dedicated repeater row layout (2604,
 * "Flexible Sponsorship Tier"), which gave the tier label
 * `module_class="ps-md ps-caps ps-turq ps-bold"` and `text_orientation="center"`,
 * and laid the logos out in a grid.
 *
 * The converted `[ps_loop … sponsors_flexible:repeater:sub=sponsorship_tier …]`
 * drops that row layout and falls back to `template="generic"`, so the tier
 * renders as a plain `.ps-field--sponsorship_tier` (14px, grey, left-aligned,
 * weight 300) and every logo stacks in one narrow column.
 *
 * Measured 2026-08-26 on /signature-series-2026: D4 shows a centered uppercase
 * turquoise "VISIONARY"; R4 showed tiny grey "Champion"/"Premier" with 13 logos
 * in a single column down the left third of the page.
 *
 * Values copied from the child theme's own utilities (.ps-md/.ps-caps/.ps-turq/
 * .ps-bold in PlantedSky/style.css), not invented. */
.et-db #et-boc .et-l .ps-field--sponsorship_tier, .ps-field--sponsorship_tier {
  display: block;
  text-align: center;
  margin: 2rem 0 1rem;
}
.et-db #et-boc .et-l .ps-field--sponsorship_tier .ps-field-value, .ps-field--sponsorship_tier .ps-field-value {
  display: block;
  text-align: center;
  text-transform: uppercase;
  font-weight: 700;
  /* #{} keeps SCSS from evaluating the rem+vw arithmetic inside clamp() */
  font-size: clamp(1.125rem, 1.0313rem + 0.4688vw, 1.5rem);
  color: var(--ahp-turquoise, #4bb3c3);
}
/* The logos under each tier: a centered responsive grid, matching D4.
 *
 * ⚠️ This only works once the sponsors loop carries `columns=1`. The loop returns
 * ONE item (the current post), and the default `columns-3` squeezed the whole
 * section into a 368px third of the row — 334px of usable width, so every logo
 * stacked in a single narrow column. With columns=1 the field is 1118px.
 *
 * NB: build2 has the SAME defect, so comparing against it "confirmed" the narrow
 * column as correct. D4 is the only valid reference here: it renders 12 logos
 * 100-200px wide, 3 across, centered, with a divider between tiers. */
.et-db #et-boc .et-l .ps-field--sponsor_flexible > .ps-field-value, .ps-field--sponsor_flexible > .ps-field-value {
  /* FLEX, not grid: a partial last row centres itself instead of leaving a hole,
   * and the logos reflow to fit any width. `repeat(3, 1fr)` forced three columns
   * at every breakpoint — measured 600px of logos inside a 312px section on a
   * 390px viewport, overflowing the viewport. */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 2.5rem 3rem;
  list-style: none;
  margin: 0 auto 2.5rem;
  padding: 0;
  /* 3 x 200px + 2 x 3rem gap = 696px. Capping here keeps D4's three-across;
   * a wider wrapper let a fourth logo squeeze onto the row. */
  max-width: 700px;
}
.et-db #et-boc .et-l .ps-field--sponsor_flexible .ps-repeater-row, .ps-field--sponsor_flexible .ps-repeater-row {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* a flex ITEM now: ~3 across at desktop, 2 at tablet, 1 on a phone */
  flex: 0 1 200px;
  max-width: 200px;
  margin: 0;
}
.et-db #et-boc .et-l .ps-field--sponsor_flexible .ps-field--sponsor_logo_flexible, .ps-field--sponsor_flexible .ps-field--sponsor_logo_flexible {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}
.et-db #et-boc .et-l .ps-field--sponsor_flexible img, .ps-field--sponsor_flexible img {
  max-width: 100%;
  max-height: 90px;
  width: auto;
  height: auto;
  object-fit: contain;
}
/* A rule between TIERS, as D4 has.
 * Scoped with `>` to the tier rows only — an unscoped descendant selector also
 * matched the nested LOGO rows and drew a line under every logo. */
.et-db #et-boc .et-l .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row, .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row {
  /* clear the engine's own border-bottom first — otherwise each tier shows TWO
   * rules: the engine's #eee bottom AND the divider added below. */
  border: 0;
}
.et-db #et-boc .et-l .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row + .ps-repeater-row, .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row + .ps-repeater-row {
  border-top: 1px solid rgba(0, 0, 0, 0.12);
  padding-top: 2.5rem;
  margin-top: 1rem;
}
/* and never on the logo rows themselves.
 * NB: the engine's default is `border-BOTTOM` on .ps-repeater-row — measured in
 * the DOM (1px solid #eee). Overriding border-top alone changed nothing. */
.et-db #et-boc .et-l .ps-field--sponsor_flexible .ps-repeater-row, .ps-field--sponsor_flexible .ps-repeater-row {
  border: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}
.et-db #et-boc .et-l .ps-field--sponsors_flexible > .ps-field-value, .ps-field--sponsors_flexible > .ps-field-value {
  list-style: none;
  margin: 0;
  padding: 0;
}
.et-db #et-boc .et-l .ps-field--sponsors_flexible .ps-repeater-row, .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row {
  display: block;
  width: 100%;
}
/* #161 — the sponsors block is a CONTENT SECTION, not a card.
 *
 * The loop returns one item (the current post) purely as a vehicle for the
 * repeater, so the generic card's chrome is all wrong here: it drew a bordered,
 * padded, hover-lifting card around a list of sponsor logos, plus the post's own
 * title and thumbnail.
 *
 * `-title` and `-thumb` (now INSIDE the `fields` attribute, where the parser
 * actually reads them) drop the heading and image; this strips the rest of the
 * card shell so the tiers and logos sit directly on the page, as D4 renders them. */
.et-db #et-boc .et-l .ps-card.ps-sponsors, .et-db #et-boc .et-l .ps-card.ps-sponsors-flexible, .et-db #et-boc .et-l .ps-card.ps-resources-repeater, .et-db #et-boc .et-l .ps-card.ps-presentation-repeater, .ps-card.ps-sponsors-flexible, .ps-card.ps-sponsors {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  padding: 0;
  margin: 0;
  transition: none;
}
.et-db #et-boc .et-l .ps-card.ps-sponsors:hover, .et-db #et-boc .et-l .ps-card.ps-sponsors-flexible:hover, .et-db #et-boc .et-l .ps-card.ps-resources-repeater:hover, .et-db #et-boc .et-l .ps-card.ps-presentation-repeater:hover, .ps-card.ps-sponsors-flexible:hover, .ps-card.ps-sponsors:hover {
  border: 0;
  box-shadow: none;
  transform: none;
  background: transparent;
}
.et-db #et-boc .et-l .ps-card.ps-sponsors .ps-card-body, .et-db #et-boc .et-l .ps-card.ps-sponsors-flexible .ps-card-body, .et-db #et-boc .et-l .ps-card.ps-resources-repeater .ps-card-body, .et-db #et-boc .et-l .ps-card.ps-presentation-repeater .ps-card-body, .ps-card.ps-sponsors-flexible .ps-card-body, .ps-card.ps-sponsors .ps-card-body {
  padding: 0;
}
/* no thumbnail slot, and no empty space where one would have been */
.et-db #et-boc .et-l .ps-card.ps-sponsors .ps-card-thumb, .et-db #et-boc .et-l .ps-card.ps-sponsors-flexible .ps-card-thumb, .et-db #et-boc .et-l .ps-card.ps-resources-repeater .ps-card-thumb, .et-db #et-boc .et-l .ps-card.ps-presentation-repeater .ps-card-thumb, .ps-card.ps-sponsors-flexible .ps-card-thumb, .ps-card.ps-sponsors .ps-card-thumb, .et-db #et-boc .et-l .ps-card.ps-sponsors .ps-card-title, .et-db #et-boc .et-l .ps-card.ps-sponsors-flexible .ps-card-title, .et-db #et-boc .et-l .ps-card.ps-resources-repeater .ps-card-title, .et-db #et-boc .et-l .ps-card.ps-presentation-repeater .ps-card-title, .ps-card.ps-sponsors .ps-card-title, .ps-card.ps-sponsors-flexible .ps-card-title {
  display: none;
}
/* #161 — sponsors on smaller screens. */
@media (max-width: 980px) {
  .et-db #et-boc .et-l .ps-field--sponsor_flexible > .ps-field-value, .ps-field--sponsor_flexible > .ps-field-value {
    gap: 2rem 2.5rem;
  }
}
@media (max-width: 767px) {
  /* two logos per row on a phone, never overflowing the viewport */
  .et-db #et-boc .et-l .ps-field--sponsor_flexible > .ps-field-value, .ps-field--sponsor_flexible > .ps-field-value {
    gap: 1.75rem 2rem;
    max-width: 100%;
  }
  .et-db #et-boc .et-l .ps-field--sponsor_flexible .ps-repeater-row, .ps-field--sponsor_flexible .ps-repeater-row {
    flex: 0 1 calc(50% - 1rem);
    max-width: calc(50% - 1rem);
    min-width: 0;
    /* let a wide logo shrink instead of forcing 1-up */
  }
  .et-db #et-boc .et-l .ps-field--sponsor_flexible img, .ps-field--sponsor_flexible img {
    max-height: 70px;
  }
  .et-db #et-boc .et-l .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row + .ps-repeater-row, .ps-field--sponsors_flexible > .ps-field-value > .ps-repeater-row + .ps-repeater-row {
    padding-top: 1.75rem;
    margin-top: 0.5rem;
  }
}
@media (max-width: 479px) {
  /* still TWO across on a phone — the logos scale down rather than stack.
   * A 1-up layout wasted most of the width and made the section very tall. */
  .et-db #et-boc .et-l .ps-field--sponsor_flexible > .ps-field-value, .ps-field--sponsor_flexible > .ps-field-value {
    gap: 1.5rem 1rem;
  }
  .et-db #et-boc .et-l .ps-field--sponsor_flexible .ps-repeater-row, .ps-field--sponsor_flexible .ps-repeater-row {
    flex: 0 1 calc(50% - 0.5rem);
    max-width: calc(50% - 0.5rem);
    min-width: 0;
  }
  .et-db #et-boc .et-l .ps-field--sponsor_flexible img, .ps-field--sponsor_flexible img {
    max-height: 56px;
  }
}
/* #161 — repeater GROUP LABELS look like D4's <h4>.
 *
 * D4 rendered a repeater's group label as `<h4 class="dmach-acf-value">`
 * (22.13px / 700 / #3d4356). The converted loop renders it as
 * `<span class="ps-field-value">` (14px / 300 / #111) — same text, no heading.
 *
 * NB: this is styling only. The engine's `titletag` control DOES exist and works,
 * but it applies to a card's TOP-LEVEL title slot; slots are resolved in
 * render_generic_card() and never reach a repeater's `sub=` fields, which
 * format_field() renders separately. Giving nested sub-fields a real heading tag
 * means adding a `tag=` option to the sub-field renderer (5+ wrapper sites in the
 * engine) — backlogged rather than done mid-replay.
 *
 * Values measured off D4 on /events/2024-signature-series-public-congressional-briefing. */
.et-db #et-boc .et-l .ps-field--resources_group_label > .ps-field-value, .ps-field--resources_group_label > .ps-field-value, .et-db #et-boc .et-l .ps-field--presentation_title > .ps-field-value, .ps-field--presentation_title > .ps-field-value {
  display: block;
  font-size: 22.13px;
  font-weight: 700;
  color: #3d4356;
  line-height: 1.3;
  margin: 1.5rem 0 0.5rem;
}
/* #161 — the parent-series link is a small red eyebrow, not a card.
 *
 * D4 rendered it through a DM title module carrying
 * `module_class="ps-sm ps-red ps-caps ps-bold ps-spaced"` — 16.75px, #e02b20,
 * uppercase, letter-spacing 1.675px, weight 700, NO border.
 *
 * The converted loop wrapped it in a generic card: 18px, #3d4356, no transform,
 * 1px border. Measured on
 * /events/2024-signature-series-public-congressional-briefing. */
.et-db #et-boc .et-l .ps-card.ps-series-link, .ps-card.ps-series-link {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  padding: 0;
  margin: 0 0 0.5rem;
}
.et-db #et-boc .et-l .ps-card.ps-series-link:hover, .ps-card.ps-series-link:hover {
  border: 0;
  box-shadow: none;
  transform: none;
}
.et-db #et-boc .et-l .ps-card.ps-series-link .ps-card-body, .ps-card.ps-series-link .ps-card-body {
  padding: 0;
}
.et-db #et-boc .et-l .ps-card.ps-series-link .ps-card-title, .ps-card.ps-series-link .ps-card-title, .et-db #et-boc .et-l .ps-card.ps-series-link .ps-card-title a, .ps-card.ps-series-link .ps-card-title a {
  font-size: 16.75px;
  font-weight: 700;
  color: #e02b20;
  text-transform: uppercase;
  letter-spacing: 1.675px;
  line-height: 1.3;
  margin: 0;
}
/* (The per-field overrides that used to sit here are gone: the default above now
 * stacks every repeater row, so `resources_repeater` and `presentation_repeater`
 * need no special case. #161) */
/* ---------------------------------------------------------------------------
 * Timeline: kill Divi's PERCENTAGE gutter margin on timeline items (#161)
 * ---------------------------------------------------------------------------
 * Rafal: "connector lines need to be responsive so they are always connected".
 *
 * The connector is `position:absolute; top:0; bottom:-24px`, and Divi's -24px
 * matches the track's `row-gap:24px`, which is CONSTANT at every breakpoint. So
 * the joins should just work. They did not, and this rule is why:
 *
 *     .et_pb_gutters3 ... .et_pb_module { margin-bottom: 2.75%; }
 *
 * NOTE: It is a PERCENTAGE, resolved against the container width, so the space
 * between items grows with the viewport while the connector's -24px does not.
 * Measured gap between a connector's end and the next marker, before this rule:
 *
 *     1440px  32px      1024px  23px      768px and below  0px
 *
 * That is also why the earlier `margin-bottom: -1.7383em` pull only ever matched
 * at one width: it was correcting a percentage with a fixed em.
 *
 * The module attribute `module.decoration.spacing.margin.bottom = 0px` IS being
 * written by style_timeline_native_159.php and stores correctly, but the gutter
 * selector carries three IDs and outranks it. Hence this rule, at matching
 * specificity.
 *
 * Browser-verified after this: gaps are 0 at 1440/1280/1024/768/600/480/360.
 */
.et_pb_gutters3 .et-db #et-boc .et-l .et_pb_timeline .et_pb_timeline_item.et_pb_module, .et-db #et-boc .et-l .et_pb_timeline .et_pb_timeline_item.et_pb_module, .et_pb_timeline .et_pb_timeline_item.et_pb_module {
  /* !important because Divi ships its gutter rule LATER in the cascade at equal
	 * specificity, so source order wins otherwise -- verified in the browser:
	 * without it the rule matches but still computes 31.67px at 1440. Divi uses
	 * !important for the same reason throughout its own module CSS. */
  margin-bottom: 0 !important;
}
/* ---------------------------------------------------------------------------
 * Timeline: the LAST connector must not trail past its marker (#161)
 * ---------------------------------------------------------------------------
 * Rafal: "the last one should have no line going bottom".
 *
 * Divi already ships
 *
 *     .et_pb_timeline .et_pb_timeline_item:last-child .et_pb_timeline_connector
 *         { bottom: 0 }
 *
 * but that is not enough on its own: the connector is `position:absolute;top:0`,
 * so `bottom:0` stretches it to the ITEM's full height, and the marker sits at
 * the TOP of that item. On a tall last card the line therefore ran 43px (1440)
 * to 263px (360) past the marker, straight down the empty card.
 *
 * The line has to END AT THE MARKER'S CENTRE instead, which is a fixed distance
 * from the top: half the marker. Marker is 50px (MARKER_PX in
 * style_timeline_native_159.php), so the last connector is exactly 25px tall.
 *
 * Browser-verified at 1440/1024/768/480/360: the line ends on the marker centre
 * to the pixel at every width, and the joins above stay at 0 gap.
 *
 * WHY THIS IS CSS AND NOT A MODULE SETTING: it targets ONE item by its position
 * in the list (`:last-child`). A Divi module attribute applies to every item
 * equally, so there is no per-item setting that can express "only the last one".
 * This is the one timeline rule that genuinely needs a stylesheet.
 *
 * It lives HERE, in the [ps_loop] styles snippet that the migration deploys, and
 * deliberately NOT in the child theme -- the child theme's .ps-timeline rules
 * were removed precisely so the timeline is defined by module settings plus this
 * one documented exception.
 *
 * Two IDs to clear Divi's own `body.et-db #page-container #et-boc .et-l` rules.
 */
body.et-db #et-boc .et-l .et_pb_timeline .et_pb_timeline_item:last-child .et_pb_timeline_connector, .et_pb_timeline .et_pb_timeline_item:last-child .et_pb_timeline_connector {
  bottom: auto;
  height: 25px;
  /* half of MARKER_PX (50px) -- keep in step with that constant */
}
