/* ==========================================================================
   CCL block-pattern styles
   Styling for the NATIVE-BLOCK rebuilds of prototype components (editable).
   Loaded on the front end and in the editor. Uses tokens from tokens.css.
   ========================================================================== */

/* ---- Stats: editable number grid ----------------------------------------
   Composable — just the numbers + their short labels. Add a heading, intro
   copy, or button separately when composing a fuller section. Styles are
   standalone (not scoped to a wrapper) so the grid works on its own. */
.ccl-stat-cols { gap: var(--spacing-lg, 24px); }

/* The number — single editable heading. The layered green offset from the
   prototype (.ccl-stat-n-shadow behind .ccl-stat-n-fg) is reproduced with a
   single text-shadow so the text stays editable. */
.ccl-stat-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(48px, 7vw, 88px);
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--ccl-black, #1a1a1a);
  text-shadow: 4px 4px 0 var(--brand, #9BC23B);
  margin: 0;
  text-align: center;
}
.ccl-stat-label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.35;
  color: var(--ccl-black, #1a1a1a);
  margin: var(--spacing-sm, 12px) 0 0;
  text-align: center;
}

/* ---- Team card: make core/image fill the fixed-height image area ---------
   site.css sizes .team-card__image (204px) and .team-card__image img, but
   core/image wraps the <img> in a <figure>, so the figure needs to stretch. */
.team-card__image .wp-block-image,
.team-card__image figure { height: 100%; margin: 0; }
.team-card__image img { width: 100%; height: 100%; object-fit: cover; }

/* ---- Pillar card: center core/image inside the green icon circle --------- */
.pillar-card .icon-circle .wp-block-image,
.pillar-card .icon-circle figure { margin: 0; }

/* ---- LEGACY: "Pull quote (framed)" pattern — retired ----------------------
   Inserted copies of the old patterns/pull-quote.php (core Group + Heading
   blocks with .conf-quote-block classes) still live in page content. The
   sizing rules for the Heading and the block-gap zeroing below keep them
   rendering; the "Quote — Large/Medium/Small" heading styles that fed the
   is-style-quote-* classes are no longer registered. New quotes are the
   ccl/quote block (site.css § QUOTES). Re-insert as a Quote block and delete. */
.conf-quote-block .quote-body .wp-block-heading {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--ccl-black, #1a1a1a);
  margin: 0;
  font-size: var(--fs-h4, 24px); /* the system's default; the old Medium (H2) is now --large */
  line-height: calc(var(--lh-h4) / var(--fs-h4));
}
.conf-quote-block .quote-body .wp-block-heading.is-style-quote-lg { font-size: var(--fs-h2, 40px); line-height: calc(var(--lh-h2) / var(--fs-h2)); }
.conf-quote-block .quote-body .wp-block-heading.is-style-quote-md { font-size: var(--fs-h3, 32px); line-height: calc(var(--lh-h3) / var(--fs-h3)); }
.conf-quote-block .quote-body .wp-block-heading.is-style-quote-sm { font-size: var(--fs-h4, 24px); line-height: calc(var(--lh-h4) / var(--fs-h4)); }
.conf-quote-block .quote-icon .wp-block-image,
.conf-quote-block .quote-icon figure { margin: 0; }
/* The editor's block-gap spacing between the three rows would cancel the
   negative-margin overlap the glyph and author rely on. */
.conf-quote-block > .quote-top,
.conf-quote-block > .quote-middle,
.conf-quote-block > .quote-bottom,
.conf-quote-block .quote-top > *,
.conf-quote-block .quote-bottom > * {
  margin-block-start: 0;
  margin-block-end: 0;
}

/* ---- Team blocks: .ccl scope wrapper ------------------------------------
   Our team blocks wrap output in `.ccl` so the .ccl-scoped tile rules
   (.ccl .leader__name, …) apply inside the editor canvas too. But tokens.css
   gives `.ccl` a page background, which would repaint white over the grey
   .team-panel. The `ccl-scope` modifier keeps the scoping, drops the paint. */
.ccl.ccl-scope { background: transparent; }

/* ---- Hero T1 (split) -----------------------------------------------------
   The photo is a core/image given the prototype .photo class; zero its default
   block margin so it fills the blue-offset media slot (site.css sizes it). */
.hero-t1__media .photo { margin: 0; }
/* Accent mark is a core/image (figure.accent-mark); site.css sizes/positions the
   figure (78px, pinned top-left, rotated). Zero its block margin and let the SVG
   fill it. (Was a Custom-HTML block before — that renders unstyled in the editor's
   sandboxed iframe, so it appeared huge and in-flow.) */
.hero-t1__media .accent-mark { margin: 0; }
.hero-t1__media .accent-mark img { width: 100%; height: auto; display: block; }

/* ---- Accordion (canonical, reusable) ------------------------------------
   ONE component for every accordion on the site (FAQ, bills/policy, etc.) — the
   single source of truth, so restyling all accordions is one edit here. Built on
   native core/details: an outer white card with a blue→green gradient rail on
   the left edge, an optional .ccl-accordion__title, and grey-bordered
   .ccl-accordion__item rows that turn blue on hover/open. Marker is a + that
   rotates into an × (grey→blue). No plugin, no extra markup.
   (Supersedes the prototype .bills-card/.bill-row — migrate those to this when
   the bills/policy accordion is rebuilt as a pattern.) */
.ccl-accordion {
  position: relative;
  overflow: hidden;                 /* clips the gradient rail to the rounded corners */
  background: #fff;
  border-radius: var(--radius-md, 16px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
  padding: var(--spacing-xl, 32px);
  max-width: 1140px;
  margin-inline: auto;
}
/* Blue→green gradient rail (blue top → green bottom). */
.ccl-accordion::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 11px;
  background: linear-gradient(180deg, var(--ccl-blue) 0%, var(--ccl-green) 100%);
}
.ccl-accordion__title {
  font-family: var(--font-display);
  font-weight: 600;
  margin: 0 0 var(--spacing-md, 16px);
}

/* Rows — grey-bordered <details>, blue on hover/open. */
.ccl-accordion__item {
  border: 1px solid var(--grey-300, #A7A8AA);
  border-radius: var(--radius-sm, 4px);
  background: #fff;
  margin-block-start: var(--spacing-sm, 12px);
  transition: border-color 0.12s ease;
}
.ccl-accordion__item:hover,
.ccl-accordion__item[open] { border-color: var(--ccl-blue); }

.ccl-accordion__item > summary {
  list-style: none;            /* Firefox marker */
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md, 16px);
  padding: var(--spacing-md, 16px) var(--spacing-lg, 24px);
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--grey-600, #333);
}
.ccl-accordion__item > summary::-webkit-details-marker { display: none; } /* Safari/Chrome */

/* Plus icon (two crossed gradients in one pseudo-element) that rotates 45° into
   an × when open and shifts grey→blue. */
.ccl-accordion__item > summary::after {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  background:
    linear-gradient(var(--grey-500, #474748) 0 0) center / 100% 2px no-repeat,
    linear-gradient(var(--grey-500, #474748) 0 0) center / 2px 100% no-repeat;
  transition: transform 0.2s ease;
}
.ccl-accordion__item[open] > summary::after {
  transform: rotate(45deg);
  background:
    linear-gradient(var(--ccl-blue, #0081C7) 0 0) center / 100% 2px no-repeat,
    linear-gradient(var(--ccl-blue, #0081C7) 0 0) center / 2px 100% no-repeat;
}

/* Body content sits below the summary with matching side padding. */
.ccl-accordion__item > :not(summary) {
  padding: 0 var(--spacing-lg, 24px) var(--spacing-md, 16px);
  margin-block: 0;
}
/* A list's left padding is also the room its bullets hang in, so the shared
   24px above put the bullets out in the gutter, left of the paragraph text.
   Indent lists by the body's list indent on top of it. Same (0,1,1) as the
   rule above; wins by coming after it. */
.ccl-accordion__item > :is(ul, ol) {
  padding-left: calc(var(--spacing-lg, 24px) + var(--spacing-xl, 32px));
}
.ccl-accordion__item :where(p, ul, ol):last-child { margin-block-end: 0; }

/* ---- Blog article (single post) -----------------------------------------
   Ported from the prototype's article styles so blog posts render on-brand.
   Body typography scopes to .article__body (the post-content wrapper in the
   single template); the CTA / gallery / tags are self-contained components used
   inside post content. The article pull-quote is the ccl/quote block in its
   "Pull quote" style (.pull-quote, site.css § QUOTES). */

/* Links: the design system underlines links with a border-bottom (tokens.css
   `.ccl a`), but theme.json ALSO adds text-decoration:underline on hover — two
   underlines. Standardize on the border-bottom; drop text-decoration in .ccl. */
.ccl a { text-decoration: none; }
.ccl a:hover { text-decoration: none; }
/* Pills / cards / share / CTA: no underline at all — kill the token border. */
a.tag,
.article-tags .wp-block-post-terms a,
.related-card,
.related-card a,
.article-cta,
.article-cta a,
.article-byline__share a { border-bottom: 0; }

/* Featured image + inline figures.
   The <figure> is emitted by the core Post Featured Image block. We round the
   <img> directly (border-radius clips a replaced element — no overflow/clip-path
   needed).

   NO FIXED RATIO — the hero takes the image's own shape. This used to be a hard
   3:2 box with object-fit:cover, for uniformity across posts. That uniformity is
   invisible (a reader sees one article at a time) and it wrecked anything that
   wasn't roughly 3:2: a bulk-imported press release whose hero is the 1652x269
   CCL letterhead rendered as a giant crop of the middle of the logo, and charts,
   screenshots and portraits fared no better. Same lesson as
   .event-spotlight__media in site.css — force a ratio only when items must line
   up with EACH OTHER (cards in a grid, related-post thumbs). A lone editorial
   image has nothing to line up with.

   max-height is the one guard left: a very tall portrait would otherwise push
   the article's first paragraph off the screen. object-fit:cover only matters
   when that cap bites, and it crops rather than squashing. Below the cap the box
   matches the image, so cover is a no-op and nothing is cropped at all.
   width/height attributes on the core block's <img> give the browser the ratio
   up front, so dropping aspect-ratio doesn't reintroduce layout shift. */
.article-figure.wp-block-post-featured-image,
.article-figure {
  margin: var(--spacing-2xl) 0;
}
.article-figure img,
.article-figure .wp-post-image {
  display: block;
  width: 100%;
  height: auto;
  max-height: min(70vh, 620px);
  object-fit: cover;
  border-radius: var(--radius-md, 16px);
}
.article-figure figcaption,
.state-hero__photo figcaption,
.story-timeline__caption { font-family: var(--font-body); font-style: italic; font-size: var(--fs-tiny); line-height: var(--lh-tiny); color: var(--grey-500); margin-top: var(--spacing-sm); }

/* Body copy rhythm (binds when post-content carries .article__body). Covers the
   standard HTML that BULK-IMPORTED posts bring — p, h2/h3/h4, lists, links,
   images, and plain blockquotes — so imported content looks right with no
   hand-editing. Hand-placed patterns (.article-cta, .pull-quote, .ccl-stats)
   style themselves on top of this. */
.article__body p { font-family: var(--font-body); font-size: 19px; line-height: 1.5; letter-spacing: -0.285px; color: var(--ccl-black); margin: 0 0 var(--spacing-lg); }
.article__body h2 { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-h4); line-height: var(--lh-h4); color: var(--ccl-black); margin: var(--spacing-2xl) 0 var(--spacing-sm); }
.article__body h3 { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-h5); line-height: var(--lh-h5); color: var(--ccl-black); margin: var(--spacing-xl) 0 var(--spacing-sm); }
.article__body h4 { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--text-md); line-height: 1.4; color: var(--ccl-black); margin: var(--spacing-lg) 0 var(--spacing-sm); }
.article__body a { color: var(--fg-link-strong); }
.article__body ul, .article__body ol { font-family: var(--font-body); font-size: 19px; line-height: 1.5; color: var(--ccl-black); margin: 0 0 var(--spacing-lg); padding-left: var(--spacing-xl); }
.article__body li { margin: 0 0 var(--spacing-2xs); }
.article__body li > ul, .article__body li > ol { margin: var(--spacing-2xs) 0 0; }
.article__body img { max-width: 100%; height: auto; border-radius: var(--radius-md); }
.article__body figure { margin: 0 0 var(--spacing-lg); }
.article__body figure figcaption { font-family: var(--font-body); font-style: italic; font-size: var(--fs-tiny); line-height: var(--lh-tiny); color: var(--grey-500); margin-top: var(--spacing-sm); }
/* Plain imported blockquotes (no .pull-quote class) still get the brand rule. */
.article__body blockquote:not([class]) { border-left: 3px solid var(--ccl-blue); padding-left: var(--spacing-lg); margin: var(--spacing-2xl) 0; font-style: italic; color: var(--ccl-black); }

/* Article CTA call-out card */
.article-cta { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--spacing-lg); background: var(--bg-info); border-radius: var(--radius-md); padding: var(--spacing-lg) var(--spacing-xl); margin: var(--spacing-2xl) 0; text-decoration: none; color: inherit; }
.article-cta__eyebrow { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-tiny); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ccl-blue); margin: 0 0 var(--spacing-2xs); }
.article-cta__title { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-h5); line-height: var(--lh-h5); color: var(--ccl-black); margin: 0 0 var(--spacing-2xs); }
.article-cta__sub { font-family: var(--font-body); font-size: var(--fs-tiny); color: var(--grey-500); margin: 0; }
.article-cta__arrow { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--fg-link-strong); line-height: 1; margin: 0; }
.article-cta:hover .article-cta__title { color: var(--fg-link-strong); }

/* Two-up image gallery */
.article-gallery { margin: var(--spacing-2xl) 0; }
.article-gallery__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--spacing-sm); }
.article-gallery__grid img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-xs); display: block; background: var(--grey-200); }
.article-gallery figcaption { font-family: var(--font-body); font-style: italic; font-size: var(--fs-tiny); color: var(--grey-500); margin-top: var(--spacing-sm); }

/* Tags row */
.article-tags { display: flex; flex-wrap: wrap; align-items: center; gap: var(--spacing-sm); padding-top: var(--spacing-xl); border-top: 1px solid var(--grey-200); margin-top: var(--spacing-2xl); }
.article-tags__label { font-family: var(--font-body); font-size: var(--fs-tiny); letter-spacing: 0.1em; text-transform: uppercase; color: var(--grey-400); font-weight: 700; }
/* Pill tags — apply to the .tag class AND to post-terms links (the single
   template renders tags via core/post-terms, whose <a>s have no .tag class).
   Written a.tag, never bare .tag: WordPress puts "tag" in body_class() on tag
   archives, and a bare .tag turned the whole <body> into an inline-block pill,
   which widened every tag page past the viewport on phones. */
a.tag,
.article-tags .wp-block-post-terms a { display: inline-block; padding: 5px 14px; border-radius: var(--radius-pill); background: var(--bg-info); color: var(--ccl-blue-dark); font-family: var(--font-body); font-weight: 700; font-size: var(--fs-tiny); text-decoration: none; }
a.tag:hover,
.article-tags .wp-block-post-terms a:hover { background: var(--ccl-blue); color: #fff; }
/* Lay the post-terms links out as a pill row and hide the comma separators. */
.article-tags .wp-block-post-terms { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--spacing-sm); }
.article-tags .wp-block-post-terms__separator { display: none; }

/* Article container + header (single-post reading column) */
.article { max-width: 720px; margin: var(--spacing-2xl) auto var(--spacing-4xl); padding: 0 var(--container-pad); }
.article__title { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-h2); line-height: var(--lh-h2); letter-spacing: -0.01em; color: var(--ccl-black); margin: var(--spacing-sm) 0 var(--spacing-lg); }
/* Category tag: the post's category as a meta-scale LINK above the title (and on
   related cards) — replaces the old .eyebrow-blue here. Rendered via
   core/post-terms, so style the wrapper AND its links. Ported from prototype
   .category-tag: uppercase, tiny, link ink, underline on hover. The global .ccl
   link border-bottom is neutralized so the hover underline doesn't double up. */
.category-tag { display: inline-block; margin: 0; font-family: var(--font-display); font-weight: 700; font-size: var(--fs-tiny); line-height: 1.2; letter-spacing: 0.04em; text-transform: uppercase; }
.category-tag, .category-tag a { color: var(--fg-link-strong); text-decoration: none; border-bottom: none; }
.category-tag a:hover { color: var(--ccl-navy); text-decoration: underline; }

/* Enriched byline: initials-avatar (derived from the author) + name/date/read-time
   + share icons (wired by scripts/apps/article-single.js). Every piece is derived
   from standard post data, so it renders for every post including bulk-imported
   ones. The avatar colour is fixed here because a Block Binding can only supply
   text (not a per-author style). */
.article-byline { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--spacing-md); padding-bottom: var(--spacing-lg); border-bottom: 1px solid var(--grey-200); margin: 0 0 var(--spacing-2xl); }
.article-byline__avatars { display: flex; flex: none; }
.article-byline__avatar {
  width: 44px; height: 44px; margin: 0; border-radius: var(--radius-pill, 999px);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 700; font-size: var(--fs-tiny);
  color: #fff; border: 2px solid #fff; background: var(--avatar-initials-1, #4A6E8A);
}
/* The same 44px circle as the initials, but holding the person's headshot when
   they have a team profile. object-fit keeps a non-square photo from squashing;
   the class is doubled onto the core image class because core sets height on
   images and would otherwise tie on specificity (see CLAUDE.md). */
.article-byline__avatar--photo,
.article-byline__avatar--photo.wp-post-image {
  object-fit: cover;
  object-position: 50% 30%;   /* faces sit high in a portrait crop */
  background: var(--grey-200);
  padding: 0;
}
.article-byline__meta { flex: 1; min-width: 0; }
.article-byline__name { font-family: var(--font-body); font-weight: 700; font-size: var(--text-md); color: var(--ccl-black); margin: 0; }
/* The credited name links to the author's team profile when one exists. It is
   set in the same ink as the surrounding line — this is a byline, not a call to
   action — and only announces itself on hover/focus.

   Scoped with .ccl deliberately. tokens.css styles prose links with
   `:where(.ccl) p > a:not([class])` — navy, underlined — and at (0,1,2) that
   beats a bare `.article-byline__name a` at (0,1,1), so the resting byline came
   out looking like body copy with a link in it. `.ccl` in front takes this to
   (0,2,1), which wins on class count rather than on load order; a tie would be
   decided by whichever stylesheet printed last, which is exactly the silent
   failure CLAUDE.md warns about. Front-end only, which is all this block is. */
.ccl .article-byline__name a { color: inherit; text-decoration: none; border-bottom: 0; }
.ccl .article-byline__name a:hover,
.ccl .article-byline__name a:focus-visible { color: var(--fg-link-strong); text-decoration: underline; text-underline-offset: 0.15em; }
.article-byline__detail { font-family: var(--font-body); font-size: var(--fs-tiny); color: var(--grey-500); margin: 2px 0 0; }
.article-byline__share { display: flex; gap: var(--spacing-md); color: var(--grey-400); flex: none; }
.article-byline__share a { color: inherit; display: inline-flex; }
.article-byline__share svg { width: 18px; height: 18px; }
.article-byline__share a:hover { color: var(--ccl-blue); }
.article-byline__share a.is-copied { color: var(--ccl-green, #6aa84f); }

/* Breadcrumb (dynamic ccl/breadcrumb block) — aligned to the 720px article box. */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: var(--spacing-xs); list-style: none; max-width: 720px; margin: var(--spacing-xl) auto 0; padding: 0 var(--container-pad); font-family: var(--font-body); font-size: var(--fs-tiny); line-height: var(--lh-tiny); color: var(--grey-500); }
.breadcrumb li { display: inline-flex; }
.breadcrumb a { color: var(--grey-500); text-decoration: none; }
.breadcrumb a:hover { color: var(--ccl-blue); }
.breadcrumb .sep { color: var(--grey-300); }

/* Subscribe banner — heading left, action right, balanced. */
.subscribe-banner { background: var(--ccl-navy); color: #fff; border-radius: var(--radius-md); padding: var(--spacing-2xl) var(--spacing-3xl); max-width: 1166px; margin: var(--spacing-2xl) auto; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--spacing-lg); }
.subscribe-banner h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-h4); line-height: var(--lh-h4); color: #fff; margin: 0; max-width: 30ch; }
.subscribe-banner .wp-block-buttons { margin: 0; }
/* Subscribe form (email + submit). UI is live; the submit endpoint is wired in
   article-single.js (currently a TODO placeholder — provider not yet chosen). */
.subscribe-banner__form { display: flex; gap: var(--spacing-md); justify-content: flex-end; align-items: center; margin: 0; }
.subscribe-banner__form input { flex: 1; max-width: 319px; height: 44px; padding: 0 12px; border: 1px solid var(--border-input, var(--grey-300)); border-radius: var(--radius-xs); background: #fff; font-family: var(--font-display); font-style: italic; font-size: 16px; color: var(--grey-500); }
.subscribe-banner__form input::placeholder { color: var(--grey-400); font-style: italic; }
.subscribe-banner__form button { height: 44px; padding: 0 var(--spacing-lg); border: 0; border-radius: var(--radius-xs); background: #fff; color: var(--ccl-navy); font-family: var(--font-display); font-weight: 700; font-size: 16px; line-height: 1; cursor: pointer; white-space: nowrap; }
.subscribe-banner__form button:hover { background: var(--grey-100); }
.subscribe-banner__form.is-submitted input { opacity: .6; }
@media (max-width: 600px) {
  .subscribe-banner__form { flex-direction: column; align-items: stretch; width: 100%; }
  /* flex: none — the desktop `flex: 1` (= 1 1 0%) is a WIDTH share in the row;
     once the form stacks, the same 0% basis applies to HEIGHT and overrides
     height: 44px, collapsing the field to one text line (~20px). */
  .subscribe-banner__form input { flex: none; max-width: none; width: 100%; }
  .article-byline__share { display: none; }
}

/* Related articles grid */
.related { max-width: 1166px; margin: var(--spacing-4xl) auto var(--spacing-5xl); padding: var(--spacing-3xl) var(--container-pad) 0; border-top: 1px solid var(--grey-200); }
.related__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--spacing-md); margin-bottom: var(--spacing-xl); }
.related__head h2 { font-family: var(--font-display); font-weight: var(--fw-strong-heading); font-size: var(--fs-h3); color: var(--ccl-black); margin: 0; }
.related__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--spacing-xl); }
/* The Query Loop's post-template renders with WordPress's FLOW layout class
   (is-layout-flow), whose stylesheet adds `> * + * { margin-block-start: 24px }`
   to space stacked items. We make the same element a grid, and gap already does
   that spacing — but the flow margin still applies, and it skips the first
   child. So every card except the first sat 24px lower than its neighbours: the
   images looked staggered even though every thumb is an identical 16/9 box.
   Cancel the inherited margin and let gap do the work. */
.related__grid > * + * { margin-block-start: 0; }
.related-card { display: flex; flex-direction: column; gap: var(--spacing-xs); text-decoration: none; color: inherit; }
.related-card__thumb { aspect-ratio: 16 / 9; border-radius: var(--radius-md); overflow: hidden; background: var(--grey-200); margin-bottom: var(--spacing-2xs); }
.related-card__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.related-card h3 { font-family: var(--font-display); font-weight: var(--fw-weak); font-size: 18px; line-height: 1.3; color: var(--ccl-black); margin: 0; }
/* The title is a post-title LINK; without this it takes the blue link colour
   instead of the card-title black. Inherit so it follows the h3 (incl. hover). */
.related-card h3 a { color: inherit; }
.related-card:hover h3 { color: var(--fg-link-strong); }
.related-card__meta { font-family: var(--font-body); font-size: var(--fs-tiny); color: var(--grey-500); margin: 0; }

/* Venue address call-out (pattern: conference-venue) — the hotel name and street
   set apart from the paragraph so it stays scannable. Same blue→green rail as the
   FAQ card; the prototype runs the address through the prose instead. */
.venue-address { border-left: 3px solid transparent; border-image: linear-gradient(180deg, var(--ccl-blue) 0%, var(--ccl-green) 100%) 1; padding-left: var(--spacing-md); margin: var(--spacing-md) 0 var(--spacing-lg); }
.venue-address p { margin: 0; }
.venue-address__name { font-family: var(--font-display); font-weight: var(--fw-strong-body); }
/* A map is whatever the editor pastes in — an Embed or a Custom HTML block. */
.split-feature__text iframe { width: 100%; aspect-ratio: 4 / 3; border: 0; border-radius: var(--radius-md); display: block; margin-top: var(--spacing-lg); }


/* Conference sponsors (patterns: conference-sponsors + -partner + -supporter) —
   a tier is a centred label with a rule either side over a row of white logo
   cards, and card size steps down by tier. Each tier is its OWN pattern and its
   own top-level block, so these rules hang off .sponsor-tier rather than a
   section wrapper: an editor inserts only the tiers they have sponsors for. */
.sponsor-tier { display: flex; flex-direction: column; align-items: center; gap: var(--spacing-lg); padding: var(--spacing-xl) 0; }
/* Tiers are siblings in the page flow, not children of a shared section, so the
   divider between them comes from the adjacent-sibling selector — which means
   it draws itself for whichever combination of tiers is inserted, and never
   above the first one. */
.sponsor-tier + .sponsor-tier { border-top: 1px solid var(--grey-200); }
.sponsor-tier__label { display: flex; align-items: center; justify-content: center; gap: var(--spacing-md); width: 100%; max-width: 32rem; margin: 0; font-family: var(--font-display); font-weight: var(--fw-strong-body); font-size: var(--fs-tiny); line-height: 1; letter-spacing: 0.08em; text-transform: uppercase; color: var(--grey-500); }
.sponsor-tier__label::before, .sponsor-tier__label::after { content: ""; flex: 1; height: 1px; background: var(--grey-300); }
.sponsor-tier .sponsor-logos { justify-content: center; gap: var(--spacing-lg); width: 100%; }
.sponsor-tier .sponsor-logos .wp-block-image { background: #fff; border-radius: var(--radius-md); box-shadow: var(--shadow-card); display: flex; align-items: center; justify-content: center; padding: var(--spacing-md) var(--spacing-lg); box-sizing: border-box; }
.sponsor-tier .sponsor-logos .wp-block-image img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; display: block; }
/* Card WIDTH has to out-specify core, which sizes nested gallery images from
   `.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image)`
   — the :not(#id) is a deliberate specificity hack (the same trap CLAUDE.md
   describes for core block styles, one level nastier). Core sizes by COUNT and
   gives a lone image the full row, which is wrong here: a sponsor card should be
   sized by its TIER, so one champion still reads as a champion and not a banner.
   Hence the long selectors — they mirror core's own trick to win. */
.sponsor-tier .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { width: auto; }
.sponsor-tier--champion .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex: 1 1 22rem; max-width: 26rem; min-height: 10rem; }
.sponsor-tier--partner .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex: 0 1 20rem; max-width: 20rem; min-height: 8rem; }
.sponsor-tier--supporter .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex: 0 1 15rem; max-width: 15rem; min-height: 6rem; }
@media (max-width: 700px) {
  .sponsor-tier--champion .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex-basis: 100%; max-width: none; min-height: 8rem; }
  .sponsor-tier--partner .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex-basis: 45%; min-height: 6rem; }
  .sponsor-tier--supporter .wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) { flex-basis: 30%; min-height: 4.5rem; }
}
