.element-28.version-2 .review-cards {
  /* gap after the heading/content block, same convention as
     .element-17.version-2 .categories-container */
  margin: 2em 0 0;
}

.element-28 .review-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.element-28 .review-cards.column-1 .review-card {
  flex: 0 0 100%;
}

.element-28 .review-cards.column-2 .review-card {
  flex: 0 0 calc(50% - 12px);
}

.element-28 .review-cards.column-3 .review-card {
  flex: 0 0 calc(33.333% - 16px);
}

.element-28 .review-card {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  background: #fff;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

.element-28 .review-card__rating {
  /* colour comes from the ccp-color-* class / inline style (see nb_display_review_card()) —
     no color rule here, or it would out-specificity both.
     Card is a column flex, cards in a row stretch to equal height (default
     align-items: stretch) — pin rating to the bottom regardless of content length. */
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 16px;
  margin-top: auto;
}

.element-28 .review-card__header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.element-28 .review-card__avatar,
.element-28 .review-card__initials {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border-radius: 50%;
}

.element-28 .review-card__avatar {
  object-fit: cover;
}

.element-28 .review-card__initials {
  /* background comes from the ccp-bg-* class / inline style (see
     nb_display_review_card()) — same pairing as __rating, no color rule here. */
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 600;
  font-size: 16px;
}

.element-28 .review-card__identity {
  min-width: 0;
}

.element-28.version-2 .review-card__guest-label {
  font-size: 16px;
  color: #666;
  margin: 2px 0 0;
}

.element-28 .review-card__content-wrap {
  margin-bottom: 12px;
}

.element-28 .review-card__content {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.element-28 .review-card__content p {
  font-size: 16px;
}

.element-28 .review-card__content-wrap.is-expanded .review-card__content {
  display: block;
  -webkit-line-clamp: unset;
  overflow: visible;
}

.element-28.version-2 .review-card__more {
  display: none;
  margin-top: 4px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font-weight: 600;
  cursor: pointer;
  font-size: 16px;
}

.element-28 .review-card__content-wrap.has-more .review-card__more {
  display: inline;
}

.element-28 .no-reviews {
  text-align: center;
}

.element-28.version-2 .review-card__identity .review-card__name {
  /* extra .review-card__identity ancestor bumps specificity past
     custom.css's [class^="element-"].version-2 p:not(:last-of-type)
     (0,3,1), which otherwise forces margin-bottom:1rem back in since
     this <p> isn't last-of-type in its parent. */
  font-size: 16px;
  font-weight: 600;
  margin: 0;
}

.element-28.version-2 .review-card__park {
  font-size: 16px;
  color: #666;
  margin: 0 0 12px;
}

.element-28.version-2 .review-card__park a {
  color: inherit;
  text-decoration: underline;
}

.element-28.version-2 .review-card__park a:hover,
.element-28.version-2 .review-card__park a:focus {
  text-decoration: none;
}

@media (max-width: 768px) {
  .element-28 .review-cards.column-2 .review-card,
  .element-28 .review-cards.column-3 .review-card {
    flex: 0 0 100%;
  }
}

/* Card style: Bordered:
   - colour comes from the ccp-border-* class / inline style on .review-card
     itself (see nb_display_review_card()) — same class+fallback pairing as
     __rating/__initials.
   - position toggles which edge carries the accent; border-radius already
     follows the border round the corner, nothing extra needed there.
   - editor context has some default non-zero border-width (block-editor/
     admin reset) on the sides we don't touch, painting a border on all 4
     sides even with border-style:none — zero the other 3 sides explicitly
     rather than relying on the initial value. */
.element-28 .review-card.border-position-top {
  border-top-width: 4px;
  border-top-style: solid;
  border-right-width: 0;
  border-bottom-width: 0;
  border-left-width: 0;
}

.element-28 .review-card.border-position-left {
  border-left-width: 4px;
  border-left-style: solid;
  border-top-width: 0;
  border-right-width: 0;
  border-bottom-width: 0;
}

/* Bordered: avatar is a left column, top-aligned (not vertically centered
   against the whole right column) — mockup has the photo level with the
   star row, not the card's full height. */
.element-28 .review-card__header--bordered {
  align-items: flex-start;
}

/* Right column beside the avatar — holds rating, content and name (see
   review-card.php's bordered branch). Needs its own width so the clamped
   content can actually shrink instead of pushing the card wider. */
.element-28 .review-card__bordered-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
}

/* Rating sits inline at the top of that column instead of pinned to the
   card's bottom (the other styles' use for margin-top:auto), with a small
   gap before the content below it. */
.element-28 .review-card__header--bordered .review-card__rating {
  margin-top: 0;
  margin-bottom: 8px;
}

/* Bordered has no separate headline field — review_content just renders at
   the same size as every other card style; name moves below it with no
   "Guest" label (see review-card.php). */
.element-28.version-2 .review-card__content-wrap--bordered + .review-card__identity .review-card__name {
  margin-bottom: 12px;
}

/* Whichever block ends up last (name or park, depending on data) has its
   own margin-bottom (__name via the rule above, __park unconditionally) —
   strip it so it doesn't stack on top of the card's own bottom padding.
   Matches the specificity of those rules (5 classes) and comes after them
   in source order so this is the one that actually wins, regardless of
   which one is last. */
.element-28.version-2 .review-card__bordered-body > *:last-child .review-card__name,
.element-28.version-2 .review-card__bordered-body > *:last-child .review-card__park {
  margin-bottom: 0;
}

/* Card style: Quote — decorative mark replaces the avatar/rating header;
   colour comes from the same ccp-color-* / inline-style pairing as the star
   rating (see nb_display_review_card()). */
.element-28 .review-card__quote-icon {
  font-size: 32px;
  line-height: 1;
  margin-bottom: 12px;
}

.element-28.version-2 .review-card__footer--quote {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

/* Card style: Split Image — side-by-side text/photo. A 33%/50%-width card
   can't fit both readably, so it always takes the full row regardless of
   "reviews per row" or Slider mode. */
.element-28 .review-cards .review-card.card-style-split,
.element-28.layout-style-slider .review-cards .review-card.card-style-split {
  flex: 0 0 100% !important;
}

/* Split card drops its own padding — the image needs to bleed to the card's
   top/right/bottom edges, so padding moves onto the text column instead
   (nothing sits left of it) and overflow:hidden clips the image back to
   the card's existing 8px corner radius. */
.element-28 .review-card.card-style-split {
  padding: 0;
  overflow: hidden;
}

.element-28 .review-card__split {
  display: flex;
  gap: 24px;
  /* .review-card is already a column flex box (see .review-card above) —
     this row needs to fill it so the image column can stretch full height. */
  flex: 1 1 auto;
}

.element-28 .review-card__split-text {
  flex: 1 1 50%;
  min-width: 0;
  display: flex;
  flex-direction: column;
  padding: 24px 0 24px 24px;
}

.element-28 .review-card__split-image {
  /* - align-self:stretch matches this column to the row's height.
     - the <img> is taken out of flow (position:absolute below) rather than
       sized via height:100% — in Slider mode slick measures each slide's
       height once on init/resize, often before the photo has loaded, so a
       photo that later loads to its own intrinsic height would grow this
       column out of sync with the sibling slides slick already measured
       (see screenshot: mismatched card heights).
     - absolute positioning means the image can never affect this box's
       height, so all cards stay equal regardless of load timing. */
  position: relative;
  flex: 1 1 50%;
  align-self: stretch;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.03);
}

.element-28 .review-card__split-image img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No photo on this review — same initials-circle fallback the other
   styles use (see review-card.php), just centred in the space the photo
   would have filled instead of hidden. */
.element-28 .review-card__split-image .review-card__initials {
  width: 64px;
  height: 64px;
  font-size: 20px;
}

@media (max-width: 768px) {
  .element-28 .review-card__split-text {
    padding: 24px;
  }

  .element-28 .review-card__split {
    flex-direction: column;
  }

  .element-28 .review-card__split-image {
    flex: 0 0 auto;
    height: 200px;
  }
}

/* Rows layout — simple full-width stacked cards, regardless of the
   "reviews per row" column count. */
.element-28.layout-style-rows .review-cards .review-card {
  flex: 0 0 100%;
}

/* Slider layout — hand off card layout to slick. */
.element-28.layout-style-slider .review-cards {
  display: block !important;
  position: relative;
}

.element-28.layout-style-slider .review-cards .slick-list {
  /* flush the outer edges back out — the 12px padding added by each
     .review-slide below would otherwise leave a 12px gap the Columns
     layout doesn't have. */
  margin: 0 -12px;
}

/* Slick sizes/positions .slick-slide itself (inline width + translate3d)
   assuming zero margin on that node, so the gutter has to live on this
   wrapper as padding — which slick's math does account for — rather than
   as margin on .review-card. .review-card keeps its border/shadow/radius
   completely untouched by slick's sizing across all three layout modes. */
.element-28.layout-style-slider .review-cards .review-slide {
  box-sizing: border-box;
  padding: 0 12px;
  height: unset;
  display: flex;
}

.element-28.layout-style-slider .review-cards .review-card {
  flex: 1 1 auto;
  width: 100%;
}

.element-28.layout-style-slider .review-cards .slick-track {
  display: flex;
  align-items: stretch;
}

.element-28.layout-style-slider .slick-arrow {
  /* Box itself was already centered (top:50%/translateY(-50%)) — the offset
     was the <i> glyph inside it: a bare inline icon inherits the button's
     default line-height, whose leading (font-metric space above/below the
     glyph) skews the icon low within its own line box. flex + line-height:1
     drops that leading so the glyph itself sits on the box's true center,
     same fix already applied to .review-cards__playpause below. */
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font-size: 28px;
  line-height: 1;
  opacity: 0.5;
}

/* Our markup supplies its own <i> glyph (fa-chevron-*) -- kill slick-theme's
   own ::before arrow glyph so it doesn't render a second, overlapping icon. */
.element-28.layout-style-slider .slick-prev::before,
.element-28.layout-style-slider .slick-next::before {
  content: none;
}

.element-28.layout-style-slider .slick-prev {
  left: -30px;
}

.element-28.layout-style-slider .slick-next {
  right: -30px;
}

/* Pre-init/no-JS fallback: stack the slides instead of hiding them outright
   (no-JS, slow CDN, ad-blocker, script error) -- slick fully overrides this
   once .slick-initialized is added. */
.element-28.layout-style-slider .review-cards:not(.slick-initialized) {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.element-28.layout-style-slider .review-cards:not(.slick-initialized) .review-slide {
  width: 100%;
}

/* Play/pause toggle for the autoplaying slider (WCAG 2.2.2), sitting as a
   leading item in the same row as slick's own dots rather than a separate
   control below them. .review-cards__controls wraps the button plus the
   dots <ul> slick already appended — override the dots' own absolute
   positioning (slick-theme.css) so flex can actually lay the row out. */
.element-28.layout-style-slider .review-cards__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin: 24px 0 0;
}

.element-28.layout-style-slider .review-cards__controls .slick-dots {
  position: static;
  width: auto;
}

.element-28.layout-style-slider .review-cards__playpause {
  /* flex + centered content, not just the parent row's align-items, so the
     icon glyph itself lands centered in the button box regardless of the
     icon font's own line-height/baseline quirks. */
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  background: none;
  border: none;
  padding: 6px;
  cursor: pointer;
  color: inherit;
  font-size: 16px;
  opacity: 0.6;
}

.element-28.layout-style-slider .review-cards__playpause:hover,
.element-28.layout-style-slider .review-cards__playpause:focus {
  opacity: 1;
}
