.ccg-cards__list { margin: 0; padding: 0; list-style: none; }
.ccg-cards__list > li { margin: 0; display: flex; }
.ccg-cards__list > li > .ccg-card { width: 100%; }

/* Full-card click target without wrapping the card in an anchor, which would
   nest the heading inside a link and flatten the accessibility tree. */
.ccg-card--link { position: relative; }

.ccg-card__anchor { color: inherit; text-decoration: none; }
.ccg-card__anchor::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}
.ccg-card__anchor:focus-visible { outline: none; }
.ccg-card--link:has(.ccg-card__anchor:focus-visible) {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}

.ccg-card--link .ccg-link { color: var(--brand); }

/* Section-level background, driven by tokens rather than a hardcoded
   dnd_section color so child themes inherit correctly. */
.ccg-cards { padding-block: var(--section-space); }
.ccg-cards--sunken { background: var(--surface-sunken); }
.ccg-cards--tinted { background: var(--surface-tint); }

/* Dark surface — meant to sit directly under the proof strip with no visible
   seam between them. Confirmed against ccg-proof-strip's own module.css:
   .ccg-proof--inverse uses this same flat token, not the hero's gradient, so
   this reuses it exactly rather than approximating it. */
.ccg-cards--dark {
  background: var(--surface-inverse);
}

/* Only the section head goes ccg-on-dark here, not the whole section — a
   white surface card sitting in a dark section still needs its own normal
   (dark) ink, or its text would flip light and vanish against its own white
   background. Photo cards handle their own light-text case independently,
   below. */

/* The inner .ccg-wrap handles the measure. Never apply margin-inline:auto to
   a descendant that also carries a max-width — it centers instead of aligning. */
.ccg-cards > .ccg-wrap > .ccg-section-head { margin-inline: 0; }

/* --- Column count -------------------------------------------------------
   Driven by --cards-per-row from the module, not auto-fit. auto-fit resolved
   18rem and 22rem minimums to the same three columns at content width, so the
   editor's card-size control had no visible effect and four cards always broke
   three-plus-one. */
.ccg-cards__list {
  grid-template-columns: repeat(var(--cards-per-row, 3), minmax(0, 1fr));
}

@media (max-width: 1023px) {
  .ccg-cards__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .ccg-cards__list { grid-template-columns: minmax(0, 1fr); }
}

/* The stretched anchor's own outline is suppressed because it would frame only
   the heading text; the :has() rule above outlines the whole card instead.
   Where :has() is unsupported, restore the anchor outline so keyboard focus is
   never invisible. */
@supports not selector(:has(*)) {
  .ccg-card__anchor:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: 2px;
  }
}

/* ==========================================================================
   Photo cards — full-bleed image, always its own light-text scope.
   The card carries ccg-on-dark itself, independent of the section's surface,
   because a photo card needs light text over its own photo whether it sits
   in a plain, sunken, tinted, or dark section.
   ========================================================================== */

.ccg-card--photo {
  position: relative;
  overflow: hidden; /* clips the image to whatever radius .ccg-card already sets */
  aspect-ratio: var(--card-photo-ratio, 4 / 5);
}

.ccg-card--photo .ccg-card__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focal, center);
}

/* Scrim lives under the text, not the whole card, so the top of a tall
   portrait photo stays clean and only the text-bearing area is darkened. */
.ccg-card--photo .ccg-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--scrim) 0%, transparent 60%);
  pointer-events: none;
}

.ccg-card--photo .ccg-card__body {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  padding: var(--space-5);
  display: grid;
  gap: var(--space-2);
}
.ccg-card--photo .ccg-card__title,
.ccg-card--photo .ccg-card__body p { margin: 0; }

/* Nameplate treatment for the category label — a bordered chip rather than
   plain small-caps text floating on the photo, closer to an actual equipment
   rating plate than a generic overlay tag. */
.ccg-card--photo .ccg-card__meta--plate {
  display: inline-block;
  width: fit-content;
  border: 1px solid var(--line);
  padding: 0.2em 0.65em;
  background: var(--scrim-soft);
}

.ccg-card--photo .ccg-link { color: inherit; }

/* Restrained hover: the photo breathes slightly, nothing else moves. Gated
   behind reduced-motion so it never needs its own opt-in flag. */
@media (prefers-reduced-motion: no-preference) {
  .ccg-card--photo .ccg-card__photo { transition: transform 0.5s ease; }
  .ccg-card--photo.ccg-card--link:hover .ccg-card__photo,
  .ccg-card--photo.ccg-card--link:has(.ccg-card__anchor:focus-visible) .ccg-card__photo {
    transform: scale(1.04);
  }
}
