/*
 * WP Salesforce Portal — front-end styles.
 *
 * All visual choices are exposed as CSS Custom Properties on :root so themes
 * (or the admin's Custom CSS textarea on the Appearance tab) can override
 * any of them with a single rule. Defaults fall through to WordPress
 * `--wp--preset--color--*` theme-token values where the theme provides them,
 * so block themes get aligned colors without any admin work.
 *
 * Override examples for theme developers:
 *
 *   :root {
 *     --wsp-primary:    #c4302b;        // override plugin's primary blue
 *     --wsp-card-radius: 12px;          // squarer cards
 *     --wsp-card-shadow: none;          // flat
 *   }
 */
:root {
  /* Brand */
  --wsp-primary: var(--wp--preset--color--primary, #2271b1);
  --wsp-primary-hover: var(--wp--preset--color--primary, #135e96);
  --wsp-primary-text: #ffffff;

  /* Neutrals */
  --wsp-text: var(--wp--preset--color--foreground, #1d2327);
  --wsp-muted: #50575e;
  --wsp-faint: #6c7781;

  /* Surfaces */
  --wsp-card-bg: var(--wp--preset--color--background, #ffffff);
  --wsp-card-border: #e0e0e0;
  --wsp-card-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  --wsp-card-shadow-hover: 0 6px 18px rgba(0, 0, 0, 0.08);
  --wsp-card-radius: 8px;
  --wsp-bg-subtle: #fafafa;

  /* Spacing */
  --wsp-gap: 1rem;
  --wsp-gap-lg: 1.5rem;

  /* Status pill palette */
  --wsp-status-ok-bg: #e6f4ea;
  --wsp-status-ok-fg: #1e7e34;
  --wsp-status-warn-bg: #fff4e5;
  --wsp-status-warn-fg: #8a4a00;
  --wsp-status-danger-bg: #fdecea;
  --wsp-status-danger-fg: #b32d2e;

  /* Inline messages */
  --wsp-msg-success: #1e7e34;
  --wsp-msg-error: #b32d2e;
}

/* =================================================================
 * Profile — `/sf-profile/` page (read-only contact view)
 * =================================================================
 * Visual language mirrors `.wsp-program-single` + `.wsp-auth`:
 *   - 720px content column
 *   - 2.25rem bold heading at the top
 *   - Light-gray rounded "facts" card holding the field grid
 *   - Eyebrow (uppercase 0.82rem) dt + 1.05rem 600-weight dd
 * Same `--wsp-prog-*` design tokens as the rest of the portal so
 * theme-level overrides re-skin profile alongside cards and forms.
 *
 * Body class `wsp-profile-page` is added by Profile\Shortcode when
 * the [wsp_profile] shortcode is on the page; demotes the theme's
 * H1 into a centered eyebrow above the shortcode's H2 greeting. */
.wsp-profile {
  max-width: 720px;
  margin: 2.5rem auto 3rem;
  padding: 0 1.5rem;
  color: var(--wsp-text, #1a1a1a);
}

.wsp-profile__heading {
  margin: 0 0 0.5rem;
  font-size: 2.25rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-profile__lede {
  margin: 0 0 1.5rem;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
}

/* Field grid wrapped in the same `--wsp-prog-card-bg` surface as
   `.wsp-program-single__facts` so the profile reads as a sibling
   panel. */
.wsp-profile__fields {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin: 0;
  padding: 2rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
}
@media (min-width: 560px) {
  .wsp-profile__fields {
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem 2.5rem;
  }
}
@media (min-width: 880px) {
  .wsp-profile__fields {
    grid-template-columns: repeat(3, 1fr);
  }
}
.wsp-profile__field { display: block; margin: 0; }
.wsp-profile__field dt {
  margin: 0 0 0.3rem;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-profile__field dd {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--wsp-text, #1a1a1a);
  line-height: 1.4;
  /* Long emails / mailing addresses wrap rather than overflow the
     card on narrow viewports. */
  word-break: break-word;
}

.wsp-profile__footnote {
  margin: 1.25rem 0 0;
  font-size: 0.95rem;
  color: var(--wsp-muted, #5a5a5a);
  font-style: italic;
  text-align: center;
}

/* Empty fields kept visible (show_empty="yes") render their dd in a
   softer color so the page reads as "these slots exist but aren't
   filled in" rather than "the data is broken". */
.wsp-profile__field--empty dd {
  color: var(--wsp-faint, #6c7781);
  font-weight: 500;
}

/* Friendly fallback when the admin hasn't selected any fields in
   Settings → Salesforce Object → Contact AND every default field is
   also missing. Avoids a blank slate that looks broken. */
.wsp-profile__empty {
  padding: 2.5rem 2rem;
  text-align: center;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
  color: var(--wsp-muted, #5a5a5a);
  font-size: 1.05rem;
  line-height: 1.55;
}

/* Guest / error variants — centered, gray, friendly card. */
.wsp-profile--guest,
.wsp-profile--error {
  text-align: center;
  padding: 2.5rem 2rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-profile--guest p,
.wsp-profile--error p {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.55;
}
.wsp-profile--guest a {
  color: var(--wsp-prog-cta-bg, #14bcbc);
  font-weight: 700;
  text-decoration: none;
}
.wsp-profile--guest a:hover { text-decoration: underline; }

/* Demote the theme's H1 to an eyebrow on the profile page — same
   treatment as `.wsp-auth-page` so the two surfaces feel like
   siblings, and the shortcode's "Hi, {FirstName}!" H2 stays
   dominant. */
body.wsp-profile-page .entry-title,
body.wsp-profile-page .wp-block-post-title {
  max-width: 720px;
  margin: 2.5rem auto 0;
  padding: 0 1.5rem 1.25rem;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  color: var(--wsp-muted, #5a5a5a);
  border-bottom: 1px solid #e0e0e0;
}
body.wsp-profile-page .wsp-profile {
  margin-top: 2rem;
}

/* Profile actions row — currently just the "Log out" pill below
   the fields card. Centered single button by default; flex-wrap
   future-proofs adding a second action (e.g. "Edit details") later
   without restructuring. */
.wsp-profile__actions {
  margin: 1.5rem 0 0;
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}
/* Outlined teal pill — same dimensions as `.wsp-prog-card__cta`
   but a "step-back" tone (transparent + border) so the logout
   button doesn't compete visually with primary CTAs elsewhere on
   the site. Hover swaps to the filled state. */
.wsp-profile__logout {
  display: inline-block;
  padding: calc(0.95rem - 2px) calc(1.5rem - 2px);
  background: transparent;
  color: var(--wsp-prog-cta-bg, #14bcbc);
  border: 2px solid var(--wsp-prog-cta-bg, #14bcbc);
  border-radius: var(--wsp-prog-cta-radius, 60px);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
}
.wsp-profile__logout:hover,
.wsp-profile__logout:focus {
  background: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
}

/* =================================================================
 * Programs archive + cards (Phase 7)
 * ================================================================= */

.wsp-programs-archive {
  max-width: 1100px;
  margin: 2rem auto;
  padding: 0 1.25rem;
}
.wsp-programs-archive__header {
  margin-bottom: 1.5rem;
  text-align: center;
}
.wsp-programs-archive__title {
  margin: 0 0 0.5rem;
  font-size: 1.85rem;
  line-height: 1.2;
}
.wsp-programs-archive__lede {
  margin: 0;
  color: var(--wsp-muted);
  font-size: 1rem;
}
.wsp-programs-archive__pagination {
  margin-top: 2rem;
  text-align: center;
}

/* Age-group filter — rendered by ListShortcode::renderAgeGroupTabs() above
   the grid. URL-driven (?age_group=...). Styled to match the HSTF site's
   existing "Program Filters" chips: chunky pills with a lime background,
   black active state, no visible border.

   Colors expose CSS variables so a theme / Appearance tab override can
   re-skin without editing the plugin:
       --wsp-filter-bg          inactive pill background
       --wsp-filter-bg-hover    hover/focus background
       --wsp-filter-text        inactive pill text color
       --wsp-filter-active-bg   active pill background
       --wsp-filter-active-text active pill text color
*/
:root {
  --wsp-filter-bg: #E5FB8B; /* lime green */
  --wsp-filter-bg-hover: #000; /* slightly darker on hover */
  --wsp-filter-text: #676767;
  --wsp-filter-active-bg: #000000;
  --wsp-filter-active-text: #ffffff;
}
.wsp-programs__filter {
  /* Gap above so the chip row sits clear of whatever container precedes
       it on the page (a hero block, Elementor section title, etc.). The
       bottom margin separates chips from the category items below. */
  margin: 2.5rem 0 2rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
}
.wsp-programs__filter-label {
  font-family: 'Poppins', sans-serif !important;
  font-weight: 700;
  font-size: 16px;
  color: #000000;
  white-space: nowrap;
}
.wsp-programs__filter-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  align-items: center;
}
.wsp-programs__filter-item {
  margin: 0;
}
.wsp-programs__filter-item a {
  font-family: 'Inter', sans-serif !important;
  display: inline-block;
  padding: 12px 24px;
  border-radius: 60px;
  border: none;
  background: var(--wsp-filter-bg);
  color: var(--wsp-filter-text);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.3em;
  text-decoration: none;
  transition:
    background-color 0.15s,
    color 0.15s,
    transform 0.05s;
}
.wsp-programs__filter-item a:hover,
.wsp-programs__filter-item a:focus {
  background: var(--wsp-filter-bg-hover);
  color: #fff;
}
.wsp-programs__filter-item a:active {
  transform: translateY(1px);
}
.wsp-programs__filter-item--active a,
.wsp-programs__filter-item--active a:hover,
.wsp-programs__filter-item--active a:focus {
  background: var(--wsp-filter-active-bg);
  color: var(--wsp-filter-active-text);
  cursor: default;
}

.wsp-programs__empty {
  margin: 3rem auto;
  padding: 2rem;
  max-width: 480px;
  text-align: center;
  border: 1px dashed #c3c4c7;
  border-radius: 8px;
  color: var(--wsp-muted);
  background: var(--wsp-bg-subtle);
}

/* ─── [wsp_programs_by_category] — grouped layout ─────────────────────
   Sections stack vertically. Each section has a header (image + text)
   followed by the standard wsp-programs__grid of cards.
   The header stacks on narrow viewports and goes side-by-side at >= 760px. */
.wsp-programs-by-category {
  display: flex;
  flex-direction: column;
  gap: 3rem;
}
.wsp-programs-by-category__items {
  display: flex;
  flex-direction: column;
  gap: inherit;
  transition: opacity 0.18s ease;
}
.wsp-programs-by-category__items--loading {
  opacity: 0.35;
  pointer-events: none;
}
.wsp-category {
  border-top: 1px solid var(--wsp-card-border, #c3c4c7);
  padding-top: 2rem;
}
.wsp-category:first-of-type {
  border-top: none;
  padding-top: 0;
}
.wsp-category__header {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-bottom: 1.75rem;
  align-items: start;
}
@media (min-width: 760px) {
  .wsp-category__header {
    grid-template-columns: 280px 1fr;
    gap: 2rem;
  }
}
.wsp-category__image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--wsp-card-radius, 8px);
  object-fit: cover;
  aspect-ratio: 4 / 3;
}
.wsp-category__name {
  margin: 0 0 0.5rem;
  font-size: 1.6rem;
  line-height: 1.2;
  color: var(--wsp-text, #1d2327);
}
.wsp-category__description {
  color: var(--wsp-muted, #50575e);
  line-height: 1.55;
  margin-bottom: 1rem;
}
.wsp-category__description p:first-child {
  margin-top: 0;
}
.wsp-category__description p:last-child {
  margin-bottom: 0;
}
.wsp-category__good-fit h3 {
  margin: 0.75rem 0 0.5rem;
  font-size: 1rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--wsp-muted, #50575e);
}
.wsp-category__good-fit p:first-child {
  margin-top: 0;
}
.wsp-category__good-fit p:last-child {
  margin-bottom: 0;
}
.wsp-category__empty {
  color: var(--wsp-muted, #50575e);
  font-style: italic;
  padding: 0.75rem 1rem;
  background: var(--wsp-bg-subtle, #f6f7f7);
  border-radius: 4px;
  margin: 0;
}

/* ─── Categories-only mode (show_programs="no") ─────────────────────
   Matches the HSTF "Programs" page design:
     - Alternating gray/white card backgrounds (odd/even)
     - Small green age label tag above the category name
     - Image positioned on the RIGHT at desktop width
     - Bulleted "Good Fit For" list
     - Orange Learn More CTA pill */

:root {
  --wsp-cat-bg-alt: #ececec; /* alternating gray background */
  --wsp-cat-radius: 24px;
  --wsp-cat-age-color: #798F1D; /* green age-label text */
  --wsp-cta-bg: #FA8804; /* orange Learn More */
  --wsp-cta-bg-hover: #14BCBC;
  --wsp-cta-text: #ffffff;
  /* Small decorative image rendered in the top-right corner of each
       category card. Override per-customer in Appearance → Custom CSS,
       or set to `none` to remove. Default points at HSTF's brand sparkle;
       relative URL so it works on any domain that has the uploads dir. */
  --wsp-cat-decoration: url('/wp-content/uploads/2026/04/fi_18432318.png');
  --wsp-cat-decoration-size: 60px;
  --wsp-cat-decoration-offset: 1.5rem;
}

.wsp-programs-by-category--info-only {
  gap: 2rem;
}
.wsp-programs-by-category--info-only .wsp-category {
  position: relative; /* anchor for the ::before decoration */
  border: none;
  padding: 3.5rem 4rem;
  background: transparent;
  border-radius: var(--wsp-cat-radius);
  overflow: hidden;
}
/* Green sparkle decoration in the top-right corner of every card.
   Hidden when `--wsp-cat-decoration: none;` is set. */
.wsp-programs-by-category--info-only .wsp-category::before {
  content: '';
  position: absolute;
  top: var(--wsp-cat-decoration-offset);
  right: var(--wsp-cat-decoration-offset);
  width: var(--wsp-cat-decoration-size);
  height: var(--wsp-cat-decoration-size);
  background-image: var(--wsp-cat-decoration);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: top right;
  pointer-events: none;
  z-index: 1;
}
/* Alternating backgrounds — odd cards gray, even cards transparent.
   Targets children of the items wrapper (AJAX-swappable container).
   Each child is either a bare <section.wsp-category> or a
   <a.wsp-category-link> wrapping one. The selector handles both. */
.wsp-programs-by-category--info-only
  .wsp-programs-by-category__items
  > :nth-child(odd)
  .wsp-category,
.wsp-programs-by-category--info-only
  .wsp-programs-by-category__items
  > .wsp-category:nth-child(odd) {
  background: var(--wsp-cat-bg-alt);
}
.wsp-programs-by-category--info-only
  .wsp-programs-by-category__items
  > :nth-child(even)
  .wsp-category,
.wsp-programs-by-category--info-only
  .wsp-programs-by-category__items
  > .wsp-category:nth-child(even) {
  background: transparent;
}

/* Header: image on the right at desktop, stacked on mobile. */
.wsp-programs-by-category--info-only .wsp-category__header {
  margin-bottom: 0;
  grid-template-columns: 1fr;
  gap: 2rem;
}
@media (min-width: 760px) {
  .wsp-programs-by-category--info-only .wsp-category__header {
    grid-template-columns: 1fr 420px; /* intro left · image right */
    gap: 3rem;
    align-items: center;
  }
}

/* Image area — stacked base + top images. Top image is positioned on top
   of the base via absolute positioning. Designed for the customer's
   "star-shape mask" pattern: base is the photo, top is a transparent PNG
   that creates the framing/clipping effect. */
.wsp-programs-by-category--info-only .wsp-category__image {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 16px;
}
.wsp-programs-by-category--info-only .wsp-category__image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.wsp-programs-by-category--info-only .wsp-category__image-base {
  position: absolute;
  inset: 0;
  border-radius: 16px;
}
.wsp-programs-by-category--info-only .wsp-category__image-top {
  position: absolute;
  inset: 0;
  object-fit: contain;
  z-index: 2;
  pointer-events: none;
}

/* Tiny green age label above the headline. */
.wsp-category__age-label {
  font-family: 'Poppins', sans-serif !important;
  display: block;
  margin-bottom: 0.6rem;
  color: var(--wsp-cat-age-color);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
}

/* Headline — large and bold. */
.wsp-programs-by-category--info-only .wsp-category__name {
  font-family: 'Momo Trust Display', sans-serif !important;
  margin: 0 0 1.5rem;
  font-size: 32px;
  font-weight: 400;
  line-height: 1.3em;
  color: #000000;
}
.wsp-programs-by-category--info-only .wsp-category__description {
  font-family: 'Poppins', sans-serif !important;
  font-size: 16px;
  line-height: 1.6;
  color: #000000;
  margin: 0 0 2rem;
  max-width: 540px;
}
.wsp-programs-by-category--info-only .wsp-category__description p:first-child {
  margin-top: 0;
}
.wsp-programs-by-category--info-only .wsp-category__description p:last-child {
  margin-bottom: 0;
}

/* "Good Fit For" block — bold label, bulleted list. */
.wsp-programs-by-category--info-only .wsp-category__good-fit {
  margin-bottom: 0.5rem;
}
.wsp-programs-by-category--info-only .wsp-category__good-fit h3 {
  font-family: 'Poppins', sans-serif !important;
  margin: 0 0 0.75rem;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: #000000;
}
.wsp-programs-by-category--info-only .wsp-category__good-fit ul {
  margin: 0;
  padding-left: 1.35rem;
  list-style: disc;
}
.wsp-programs-by-category--info-only .wsp-category__good-fit li {
  font-family: 'Poppins', sans-serif !important;
  font-size: 16px;
  line-height: 1.6em;
  color: #000000;
}
.wsp-programs-by-category--info-only .wsp-category__good-fit li:last-child {
  margin-bottom: 0;
}

/* Orange Learn More CTA pill. Matches the size of the filter chips. */
.wsp-category__cta {
  font-family: 'Inter', sans-serif !important;
  display: inline-flex;
  align-items: center;
  margin-top: 2rem;
  padding: 12px 24px;
  background: var(--wsp-cta-bg);
  color: var(--wsp-cta-text);
  border-radius: 60px;
  font-weight: 700;
  font-size: 13px;
  line-height: 1.3em;
  text-decoration: none;
  transition:
    background-color 0.15s,
    transform 0.05s;
}

/* Linkable wrapper — entire card is an anchor. Strip default link styling
   so the child <section> styling controls everything.
   Cards stay STATIC on hover (matching the HSTF production design); only
   the Learn More CTA pill changes color so the link affordance is clear.
   Keyboard focus still draws an outline for accessibility. */
.wsp-category-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.wsp-category-link:hover .wsp-category__cta {
  background: var(--wsp-cta-bg-hover);
}
.wsp-category-link:focus {
  outline: none;
}
.wsp-category-link:focus-visible .wsp-category {
  outline: 3px solid var(--wsp-filter-bg, #E5FB8B);
  outline-offset: 3px;
}

.wsp-programs__grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}
@media (min-width: 640px) {
  .wsp-programs__grid {
    grid-template-columns: 1fr 1fr;
    gap: 1.25rem;
  }
}
@media (min-width: 980px) {
  .wsp-programs__grid {
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1.5rem;
  }
}

.wsp-program-card {
  display: flex;
  flex-direction: column;
  padding: 1.25rem;
  border: 1px solid var(--wsp-card-border);
  border-radius: 10px;
  background: var(--wsp-card-bg);
  box-shadow: var(--wsp-card-shadow);
  transition:
    box-shadow 120ms ease,
    transform 120ms ease;
}
.wsp-program-card:hover {
  box-shadow: var(--wsp-card-shadow-hover);
  transform: translateY(-2px);
}

.wsp-program-card__top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 0.75rem;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.wsp-program-card__status {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: 999px;
  background: #e0e7ec;
  color: var(--wsp-text);
}
.wsp-program-card--enrolling .wsp-program-card__status {
  background: var(--wsp-status-ok-bg);
  color: var(--wsp-msg-success);
}
.wsp-program-card--pre-enrollment .wsp-program-card__status {
  background: var(--wsp-status-warn-bg);
  color: var(--wsp-status-warn-fg);
}
.wsp-program-card--waitlist-only .wsp-program-card__status {
  background: var(--wsp-status-danger-bg);
  color: var(--wsp-msg-error);
}

.wsp-program-card__year {
  font-size: 0.78rem;
  color: var(--wsp-faint);
}

.wsp-program-card__title {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
  line-height: 1.3;
}
.wsp-program-card__title a {
  color: var(--wsp-text);
  text-decoration: none;
}
.wsp-program-card__title a:hover {
  text-decoration: underline;
}

.wsp-program-card__tags {
  list-style: none;
  padding: 0;
  margin: 0 0 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.wsp-program-card__tag {
  padding: 0.1rem 0.55rem;
  font-size: 0.78rem;
  border-radius: 999px;
  background: #f0f2f4;
  color: #404040;
}

.wsp-program-card__schedule {
  margin: 0.25rem 0;
  color: var(--wsp-muted);
  font-size: 0.92rem;
}

.wsp-program-card__availability {
  margin: 0.4rem 0 1rem;
  color: var(--wsp-muted);
  font-size: 0.88rem;
  min-height: 1.4em;
}

.wsp-program-card__cta {
  margin-top: auto;
  align-self: flex-start;
  padding: 0.45rem 0.9rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: #fff;
  background: var(--wsp-primary);
  border-radius: 6px;
  text-decoration: none;
}
.wsp-program-card__cta:hover {
  background: var(--wsp-primary-hover);
}

/* =================================================================
 * Single program (Phase 7)
 * ================================================================= */

/* ─── Single program page (/ta-programs/{slug}/) ──────────────────────
   Styled to match the customer's system design: light gray rounded
   container, bold typography, lime / teal accent palette, generous
   padding. Mirrors the spacing + scale of the program cards on the
   category pages. */

/* Single-page layout shared between programs and events. Every rule
   below targets BOTH `.wsp-program-single*` and `.wsp-event-single*`
   so the two templates render identically without duplicating CSS.
   Add an event-only override by appending a rule below this block
   that targets `.wsp-event-single` only. */
.wsp-program-single,
.wsp-event-single {
  max-width: 1100px;
  margin: 2.5rem auto 3rem;
  padding: 0 1.5rem;
  color: var(--wsp-text, #1a1a1a);
}

.wsp-program-single__back,
.wsp-event-single__back {
  margin: 0 0 1.5rem;
  font-size: 1rem;
  font-weight: 600;
}
.wsp-program-single__back a,
.wsp-event-single__back a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--wsp-text, #1a1a1a);
  text-decoration: none;
  transition: color 0.15s;
}
.wsp-program-single__back a:hover,
.wsp-event-single__back a:hover {
  color: var(--wsp-prog-cta-bg, #14bcbc);
  text-decoration: none;
}

/* Main article container — flat layout, no border, no shadow.
   The content sits directly on the page background like other system pages. */
.wsp-program-single__article,
.wsp-event-single__article {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  box-shadow: none;
}

/* Header: image on the left (desktop), title/chips on the right. */
.wsp-program-single__header,
.wsp-event-single__header {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-bottom: 2.5rem;
  align-items: center;
}
@media (min-width: 760px) {
  .wsp-program-single__header,
  .wsp-event-single__header {
    grid-template-columns: 480px 1fr;
    gap: 3rem;
  }
}

.wsp-program-single__media,
.wsp-event-single__media {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 24px;
  overflow: hidden;
  background: var(--wsp-prog-card-bg, #f4f4f4);
}
.wsp-program-single__media img,
.wsp-event-single__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.wsp-program-single__media--placeholder,
.wsp-event-single__media--placeholder {
  background:
    var(--wsp-prog-placeholder-icon, none) center/64px 64px no-repeat,
    var(
      --wsp-prog-placeholder-bg,
      linear-gradient(135deg, #e6e6e6 0%, #f0f0f0 60%, #f7f7f7 100%)
    );
  background-blend-mode: normal;
}
.wsp-program-single__media--placeholder::after,
.wsp-event-single__media--placeholder::after {
  /* Brand opacity overlay on placeholder so it doesn't feel empty. */
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  background: var(--wsp-prog-placeholder-icon, none) center/64px 64px no-repeat;
  opacity: 0.35;
}

.wsp-program-single__intro,
.wsp-event-single__intro {
  /* sits right of the image at desktop, below at mobile */
}

/* Chips row above the title — category + age + status. */
.wsp-program-single__chips,
.wsp-event-single__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1rem;
}
.wsp-program-single__chip,
.wsp-event-single__chip {
  display: inline-block;
  padding: 0.4rem 0.95rem;
  background: var(--wsp-filter-bg, #E5FB8B);
  color: var(--wsp-filter-text, #676767);
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
}
.wsp-program-single__chip--category,
.wsp-event-single__chip--category {
  background: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
}
.wsp-program-single__chip--status,
.wsp-event-single__chip--status {
  background: #ececec;
  color: #1a1a1a;
}
.wsp-program-single__chip--enrolling,
.wsp-event-single__chip--enrolling {
  background: var(--wsp-filter-bg, #E5FB8B);
  color: #1a1a1a;
}
.wsp-program-single__chip--pre-enrollment,
.wsp-event-single__chip--pre-enrollment {
  background: #fff1c4;
  color: #6f5300;
}
.wsp-program-single__chip--waitlist-only,
.wsp-event-single__chip--waitlist-only {
  background: #ffd5d5;
  color: #8a1f1f;
}
/* Event-only status variants (use the customer's SF picklist values). */
.wsp-event-single__chip--registration-open {
  background: var(--wsp-filter-bg, #E5FB8B);
  color: #1a1a1a;
}
.wsp-event-single__chip--registration-closed {
  background: #ffd5d5;
  color: #8a1f1f;
}

.wsp-program-single__title,
.wsp-event-single__title {
  margin: 0 0 0.75rem;
  font-size: 2.5rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-program-single__code {
  margin: 0;
  color: var(--wsp-muted, #5a5a5a);
  font-size: 0.95rem;
}
.wsp-program-single__code code {
  padding: 0.15rem 0.5rem;
  border-radius: 6px;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  font-size: 0.85rem;
  font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}

/* Facts grid — clean card with rounded corners + bigger spacing. */
.wsp-program-single__facts,
.wsp-event-single__facts {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin: 0 0 2.5rem;
  padding: 2rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: 24px;
}
@media (min-width: 640px) {
  .wsp-program-single__facts,
  .wsp-event-single__facts {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem 2.5rem;
  }
}
@media (min-width: 980px) {
  .wsp-program-single__facts,
  .wsp-event-single__facts {
    grid-template-columns: repeat(3, 1fr);
  }
}
.wsp-program-single__fact dt,
.wsp-event-single__fact dt {
  margin: 0 0 0.3rem;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-program-single__fact dd,
.wsp-event-single__fact dd {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--wsp-text, #1a1a1a);
  line-height: 1.4;
}
.wsp-program-single__enrolled {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--wsp-muted, #5a5a5a);
}

.wsp-program-single__body,
.wsp-event-single__body {
  margin: 0 0 2.5rem;
  font-size: 1.05rem;
  line-height: 1.65;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-program-single__body p:first-child,
.wsp-event-single__body p:first-child {
  margin-top: 0;
}
.wsp-program-single__body p:last-child,
.wsp-event-single__body p:last-child {
  margin-bottom: 0;
}
.wsp-program-single__body h2,
.wsp-program-single__body h3,
.wsp-event-single__body h2,
.wsp-event-single__body h3 {
  margin: 1.75rem 0 0.5rem;
  font-weight: 800;
}

.wsp-program-single__apply,
.wsp-event-single__apply {
  margin-top: 2.5rem;
}

/* =================================================================
 * Apply — iframe wrapper + non-iframe status cards
 * =================================================================
 * Visual language matches `.wsp-program-single__facts` and
 * `.wsp-auth-form`: light-gray rounded card on `--wsp-prog-card-bg`,
 * 24px radius, generous padding, no border. CTAs use the canonical
 * `--wsp-prog-cta-*` pill. Variants (config / closed / missing /
 * pre-enrollment / etc.) share the same surface — they only differ
 * in a small accent strip on the left so the visitor gets a status
 * hint without the card screaming a different color at them. */

.wsp-apply {
  margin: 2rem 0 0;
  padding: 2rem 2.5rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
  color: var(--wsp-text, #1a1a1a);
  position: relative;
}
.wsp-apply__heading {
  margin: 0 0 0.75rem;
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-apply__msg {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
}
/* CTA — pill identical to `.wsp-prog-card__cta` (used by the
   logged-out "Log in" link inside the guest variant, kept for
   custom templates that still emit one). */
.wsp-apply__cta {
  display: inline-block;
  margin-top: 1rem;
  padding: 0.95rem 1.5rem;
  background-color: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
  border: none;
  border-radius: var(--wsp-prog-cta-radius, 60px);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  text-decoration: none;
  transition: background-color 0.15s;
}
.wsp-apply__cta:hover,
.wsp-apply__cta:focus {
  background-color: var(--wsp-prog-cta-bg-hover, #0fa3a3);
  color: var(--wsp-prog-cta-text, #fff);
}

/* Status variants — same card body, distinguished by a 4px accent
   strip on the left edge. Subtle, decorative — the card is the
   focus, the strip is a glance-able status hint.
     config / no-link / missing → teal (matches CTA tokens — "this
       is informational, action is on the staff side")
     closed                     → muted gray ("this is final")
     pre-enrollment             → warm amber ("check back later") */
.wsp-apply--config,
.wsp-apply--no-link,
.wsp-apply--missing,
.wsp-apply--closed,
.wsp-apply--pre-enrollment {
  padding-left: calc(2.5rem - 4px);
  border-left: 4px solid var(--wsp-prog-cta-bg, #14bcbc);
}
.wsp-apply--closed { border-left-color: #c4c4c4; }
.wsp-apply--pre-enrollment { border-left-color: #dba617; }

/* Iframe wrapper — same card surface, just sized to host the FA form
   without scroll-trapping the visitor. */
.wsp-apply--form {
  padding: 2rem;
}
.wsp-apply__frame-wrap {
  position: relative;
  width: 100%;
  min-height: 800px;
  border-radius: 16px;
  overflow: hidden;
  background: #fff;
}
.wsp-apply__iframe {
  width: 100%;
  height: 1200px;
  border: 0;
  display: block;
}

.wsp-apply__newtab {
  margin: 1rem 0 0;
  font-size: 0.95rem;
  color: var(--wsp-muted, #5a5a5a);
  text-align: right;
}
.wsp-apply__newtab a {
  color: var(--wsp-prog-cta-bg, #14bcbc);
  font-weight: 700;
  text-decoration: none;
}
.wsp-apply__newtab a:hover { text-decoration: underline; }

.wsp-apply--newtab { text-align: center; }
.wsp-apply--newtab .wsp-apply__cta {
  margin-top: 1rem;
}

/* =================================================================
 * Generic error panel (Phase 9)
 * Used by templates/error.php — keeps SF-down / contact-missing /
 * link-missing failure modes visually consistent.
 * ================================================================= */

.wsp-error {
  max-width: 640px;
  margin: 2rem auto;
  padding: 1rem 1.25rem;
  background: #fcfaf2;
  border: 1px solid #efe7c8;
  border-left-width: 4px;
  border-radius: 4px;
  color: var(--wsp-muted);
}
.wsp-error__msg {
  margin: 0;
  font-size: 0.95rem;
}

/* ─── [wsp_events_by_category] — event-category cards ──────────────────
   Distinct design from program-category cards: white card with subtle
   border, green "FREE" badge top-left, bold black title, gray copy,
   orange Learn More CTA. Cards stack on mobile, 3 cols on desktop. */
:root {
  --wsp-event-card-bg: #ffffff;
  --wsp-event-card-border: #ebebeb;
  --wsp-event-card-radius: 24px;
  --wsp-event-img-radius: 18px;
  --wsp-event-badge-bg: #ffffff;
  --wsp-event-badge-text: #14a85a; /* green "FREE" text */
  --wsp-event-cta-bg: var(--wsp-cta-bg, #FA8804);
  --wsp-event-cta-bg-hover: var(--wsp-cta-bg-hover, #14BCBC);
  --wsp-event-cta-text: #ffffff;
}

.wsp-event-cats {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
  margin: 2rem 0;
}
@media (min-width: 640px) {
  .wsp-event-cats {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.75rem;
  }
}
@media (min-width: 980px) {
  .wsp-event-cats {
    gap: 2rem;
  }
  .wsp-event-cats--cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }
  .wsp-event-cats--cols-4 {
    grid-template-columns: repeat(4, 1fr);
  }
  .wsp-event-cats--cols-2 {
    grid-template-columns: repeat(2, 1fr);
  }
  .wsp-event-cats--cols-1 {
    grid-template-columns: 1fr;
  }
}

/* Match the SEM plugin's .sem-event-card shape exactly so our event-
   category cards look like the same component family as the actual
   event cards on /events-page/ — flush-to-edge image, 16:9 ratio,
   18/20/20 body padding, 18px / 700-weight title. */
.wsp-event-cat-card {
  background: var(--wsp-event-card-bg);
  border: 1px solid var(--wsp-event-card-border);
  border-radius: var(--wsp-event-card-radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
  padding: 0;
}

.wsp-event-cat-card__media {
  display: block;
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: #f4f5f6;
}
.wsp-event-cat-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.wsp-event-cat-card__placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #e8e8e8 0%, #f5f5f5 100%);
}

/* FREE badge — pill in top-left corner of the image, white background,
   green text, uppercase. Matches the reference screenshot exactly. */
.wsp-event-cat-card__badge {
  position: absolute;
  top: 12px;
  left: 12px;
  padding: 6px 14px;
  background: var(--wsp-event-badge-bg);
  color: var(--wsp-event-badge-text);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
  z-index: 2;
}

.wsp-event-cat-card__body {
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1;
}

.wsp-event-cat-card__title {
  margin: 0;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-event-cat-card__title a {
  color: inherit;
  text-decoration: none;
}
.wsp-event-cat-card__title a:hover {
  color: var(--wsp-event-cta-bg);
}

/* Date/meta line under the title (only used by individual event cards
   rendered by [wsp_events_for_category]; category cards skip it). */
.wsp-event-cat-card__meta {
  margin: 0;
  color: var(--wsp-event-cta-bg);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.wsp-event-cat-card__desc {
  margin: 0;
  color: var(--wsp-muted, #4a5568);
  font-size: 14px;
  line-height: 1.55;
  flex: 1;
}
.wsp-event-cat-card__desc p:first-child {
  margin-top: 0;
}
.wsp-event-cat-card__desc p:last-child {
  margin-bottom: 0;
}

/* Orange CTA pill spanning full card width. Padding matches the SEM
   primary button size; margin-top adds a small breathing gap above. */
.wsp-event-cat-card__cta {
  display: block;
  width: 100%;
  margin-top: 6px;
  text-align: center;
  padding: 14px 20px;
  background: var(--wsp-event-cta-bg);
  color: var(--wsp-event-cta-text);
  border-radius: 999px;
  font-weight: 700;
  font-size: 15px;
  line-height: 1.15;
  text-decoration: none;
  transition: background-color 0.15s;
}
.wsp-event-cat-card__cta:hover,
.wsp-event-cat-card__cta:focus {
  background: var(--wsp-event-cta-bg-hover);
  color: var(--wsp-event-cta-text);
}

.wsp-event-cats__empty {
  margin: 2rem 0;
  padding: 2rem;
  text-align: center;
  color: var(--wsp-muted, #4a5568);
  background: #fafafa;
  border-radius: var(--wsp-event-card-radius);
  border: 1px solid var(--wsp-event-card-border);
}
.wsp-event-cats__empty-title {
  margin: 0 0 8px;
  font-size: 18px;
  font-weight: 700;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-event-cats__empty-subtitle {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
}

/* ─── [wsp_programs_for_category] — program cards ──────────────────
   Designed to match the customer's "Featured Annual Events" reference:
   light gray rounded card, rounded image at top, bold title, gray
   excerpt, orange Learn More pill. Reuses the orange CTA tokens from
   the category cards above so brand colors stay consistent. */
:root {
  --wsp-prog-card-bg: #f4f4f4; /* light gray card background */
  --wsp-prog-card-radius: 24px;
  --wsp-prog-card-img-radius: 18px;
}

.wsp-prog-cards-wrap {
  margin: 0 0 2rem;
}

.wsp-prog-cards {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 1fr;
}
@media (min-width: 640px) {
  .wsp-prog-cards {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.75rem;
  }
}
@media (min-width: 980px) {
  .wsp-prog-cards {
    gap: 2rem;
  }
  .wsp-prog-cards--cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }
  .wsp-prog-cards--cols-4 {
    grid-template-columns: repeat(4, 1fr);
  }
  .wsp-prog-cards--cols-2 {
    grid-template-columns: repeat(2, 1fr);
  }
  .wsp-prog-cards--cols-1 {
    grid-template-columns: 1fr;
  }
}

.wsp-prog-card {
  background: var(--wsp-prog-card-bg);
  border-radius: var(--wsp-prog-card-radius);
  display: flex;
  flex-direction: column;
}

.wsp-prog-card__media {
  position: relative;
  display: block;
  border-radius: 24px 24px 0px 0px;
  overflow: hidden;
  aspect-ratio: 16/9;
  margin-bottom: 1.5rem;
  background: #f4f5f6;
}
.wsp-prog-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Placeholder — applied to .wsp-prog-card__media when no featured image
   is set. A soft brand-tinted gradient with a centered photo icon, so
   the card keeps the same 4:3 visual rhythm as cards that have images.

   Customer can override:
     --wsp-prog-placeholder-bg     → swap to a solid color or different gradient
     --wsp-prog-placeholder-icon   → swap to a brand glyph SVG data URL
     --wsp-prog-placeholder-image  → set to url(...) to use a real fallback image
                                     (overrides both bg + icon when set) */
:root {
  --wsp-prog-placeholder-bg: linear-gradient(
    135deg,
    #e6e6e6 0%,
    #f0f0f0 60%,
    #f7f7f7 100%
  );
  --wsp-prog-placeholder-image: none;
  --wsp-prog-placeholder-icon: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231a1a1a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='3' width='18' height='18' rx='2'/><circle cx='8.5' cy='8.5' r='1.5'/><path d='M21 15l-5-5L5 21'/></svg>");
}
.wsp-prog-card__media--placeholder {
  background:
    var(--wsp-prog-placeholder-image) center/cover no-repeat,
    var(--wsp-prog-placeholder-bg);
}
.wsp-prog-card__media--placeholder::after {
  /* The icon only renders when no custom placeholder IMAGE is set
       (the cover-sized image would visually overpower the icon anyway). */
  content: '';
  position: absolute;
  inset: 0;
  background: var(--wsp-prog-placeholder-icon) center/64px 64px no-repeat;
  opacity: 0.35;
  pointer-events: none;
}
/* If admin has set a real image via the variable, hide the icon. */
.wsp-prog-card__media--placeholder[style*='--wsp-prog-placeholder-image']::after {
  display: none;
}

/* Optional status pill overlay on the image (top-right corner). */
.wsp-prog-card__pill {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  padding: 0.35rem 0.85rem;
  background: var(--wsp-cta-bg, #FA8804);
  color: #fff;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}

.wsp-prog-card__body {
  display: flex;
  flex-direction: column;
  padding: 0 0.5rem;
  flex: 1;
}

/* Age-range chip above the title. Container ALWAYS rendered (with
   min-height) so cards without a chip reserve the same vertical space
   and the Learn More button stays at a consistent height across the row. */
.wsp-prog-card__chips {
  margin-bottom: 0.6rem;
  min-height: 1.6rem; /* matches the chip's outer height */
  line-height: 1;
}
.wsp-prog-card__chip {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  background: var(--wsp-filter-bg, #E5FB8B);
  color: var(--wsp-filter-text, #676767);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
}

.wsp-prog-card__title {
  margin: 0 0 0.75rem;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-prog-card__title a {
  color: inherit;
  text-decoration: none;
}
.wsp-prog-card__title a:hover {
  color: var(--wsp-cta-bg, #FA8804);
}

.wsp-prog-card__excerpt {
  margin: 0 0 1.5rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
  flex: 1;
}

/* CTA pill — matches the customer's site-wide button style:
   teal background (#14BCBC), white text, subtle drop shadow,
   60px fully-rounded corners. Reuses the same shape as Elementor
   buttons elsewhere on the page so the design is consistent. */
:root {
  --wsp-prog-cta-bg: #14bcbc;
  --wsp-prog-cta-bg-hover: #0fa3a3; /* ~10% darker on hover */
  --wsp-prog-cta-text: #ffffff;
  --wsp-prog-cta-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* matches Elementor text-shadow */
  --wsp-prog-cta-radius: 60px;
}
.wsp-prog-card__cta {
  align-self: stretch;
  text-align: center;
  padding: 14px 20px;
  margin-top: 10px;
  margin-bottom: 20px;
  background-color: #FA8804;
  color: var(--wsp-prog-cta-text);
  text-shadow: var(--wsp-prog-cta-shadow);
  fill: var(--wsp-prog-cta-text);
  border-radius: var(--wsp-prog-cta-radius);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  text-decoration: none;
  transition: background-color 0.15s;
}
.wsp-prog-card__cta:hover,
.wsp-prog-card__cta:focus {
  background-color: var(--wsp-prog-cta-bg-hover);
  color: var(--wsp-prog-cta-text);
}

/* "Coming Soon" empty state for [wsp_programs_for_category].
   A friendly, visually rich card with a centered icon, bold title,
   and subtitle copy. Uses the brand lime + teal palette so it feels
   like part of the system rather than a fallback.
   Override per customer via the shortcode attributes
       [wsp_programs_for_category ... empty_message="Stay tuned!"
        empty_subtitle="We'll publish this season's lineup in August."] */
.wsp-prog-cards__empty {
  margin: 2rem 0;
  padding: 2.5rem 1.5rem;
  text-align: center;
  background: var(--wsp-prog-card-bg);
  border-radius: var(--wsp-prog-card-radius);
  color: var(--wsp-text);
  overflow: hidden;
  position: relative;
}
.wsp-prog-cards__empty-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: 0 auto 1rem;
  background: var(--wsp-prog-cta-bg);
  color: var(--wsp-prog-cta-text);
  border-radius: 999px;
}
.wsp-prog-cards__empty-icon svg {
  width: 22px;
  height: 22px;
}
.wsp-prog-cards__empty-title {
  margin: 0 0 0.5rem;
  font-size: 1.35rem;
  font-weight: 800;
  line-height: 1.25;
  color: var(--wsp-text);
}
.wsp-prog-cards__empty-subtitle {
  margin: 0 auto;
  max-width: 440px;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--wsp-muted);
}

/* =================================================================
 * Auth — register + login forms, two-option gate panel
 * =================================================================
 * Visual language mirrors `.wsp-program-single`: light-gray rounded
 * "facts card" wrapping the form, bold black headings at the same
 * scale, teal pill CTA matching `.wsp-prog-card__cta` exactly
 * (uses the canonical --wsp-prog-cta-* tokens), 24px card radius.
 *
 * On /register/ + /login/ the plugin adds a `wsp-auth-page` body
 * class so we can demote the theme's `.entry-title` H1 from a
 * "competing" heading into a centered eyebrow label — the H2
 * inside the shortcode is the dominant heading. */

/* Demote the theme's page H1 on auth pages — centered, smaller,
   muted, with a hairline divider so it reads as a section label
   above the shortcode card rather than the page's main title. */
body.wsp-auth-page .entry-title,
body.wsp-auth-page .wp-block-post-title {
  max-width: 720px;
  margin: 2.5rem auto 0;
  padding: 0 1.5rem 1.25rem;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  color: var(--wsp-muted, #5a5a5a);
  border-bottom: 1px solid #e0e0e0;
}
body.wsp-auth-page .wsp-auth {
  margin-top: 2rem;
}
 *
 * Used by:
 *   - AuthGate     → `.wsp-apply--gate` on Apply shortcodes
 *   - RegisterShortcode + LoginShortcode → `.wsp-auth` page wrappers
 *
 * Override any token from a theme; the design tokens live with the
 * program card definitions so all three surfaces (cards, single
 * pages, auth) re-skin together.
 */

/* ---- Two-option gate panel (replaces the single "Log in" card) ----
   Two side-by-side cards that match the program-card aesthetic:
   same `--wsp-prog-card-bg` surface, 24px radius, bold title, gray
   copy, teal pill CTA at the bottom. The "Log in" card uses an
   outline variant so the two CTAs have visual hierarchy without
   competing for attention. */
.wsp-apply--gate {
  max-width: 880px;
  margin: 2rem auto 0;
}
.wsp-apply--gate .wsp-apply__heading {
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.15;
  margin: 0 0 0.5rem;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-auth-gate__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 1.25rem;
}
@media (min-width: 760px) {
  .wsp-auth-gate__grid {
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
  }
}
.wsp-auth-gate__card {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 2rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
}
.wsp-auth-gate__title {
  margin: 0;
  font-size: 1.4rem;
  font-weight: 800;
  line-height: 1.2;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-auth-gate__copy {
  margin: 0;
  flex: 1;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
}
/* Gate buttons — clone of `.wsp-prog-card__cta` so they read as the
   same component visitors see on the program/event listing cards.
   Both variants share identical padding, radius, font, transition;
   only colors differ.

   --primary: solid teal pill identical to every other portal CTA.
   --secondary: outlined sibling (same dimensions thanks to a
   transparent border on --primary so the two cards align perfectly
   in the grid). Hover swaps --secondary to the filled state. */
.wsp-auth-gate__cta {
  display: block;
  align-self: stretch;
  text-align: center;
  margin-top: 0.5rem;
  padding: 0.95rem 1.5rem;
  border: 2px solid transparent; /* dimensional parity with --secondary */
  border-radius: var(--wsp-prog-cta-radius, 60px);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.wsp-auth-gate__cta--primary {
  background: var(--wsp-prog-cta-bg, #14bcbc);
  border-color: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
}
.wsp-auth-gate__cta--primary:hover,
.wsp-auth-gate__cta--primary:focus {
  background: var(--wsp-prog-cta-bg-hover, #0fa3a3);
  border-color: var(--wsp-prog-cta-bg-hover, #0fa3a3);
  color: var(--wsp-prog-cta-text, #fff);
}
.wsp-auth-gate__cta--secondary {
  background: transparent;
  border-color: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-bg, #14bcbc);
}
.wsp-auth-gate__cta--secondary:hover,
.wsp-auth-gate__cta--secondary:focus {
  background: var(--wsp-prog-cta-bg, #14bcbc);
  border-color: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
}
.wsp-apply__lede {
  margin: 0 0 0.5rem;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
}

/* ---- Standalone /register/ and /login/ pages ----
   Page width + spacing matches `.wsp-program-single` so the auth
   pages feel like sibling templates rather than orphan forms. */
.wsp-auth {
  max-width: 720px;
  margin: 2.5rem auto 3rem;
  padding: 0 1.5rem;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-auth__heading {
  margin: 0 0 0.6rem;
  font-size: 2.25rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-auth__lede {
  margin: 0 0 1.5rem;
  font-size: 1.05rem;
  line-height: 1.55;
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-auth__alt {
  margin: 1.5rem 0 0;
  font-size: 1rem;
  text-align: center;
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-auth__alt a {
  color: var(--wsp-prog-cta-bg, #14bcbc);
  font-weight: 700;
  text-decoration: none;
}
.wsp-auth__alt a:hover { text-decoration: underline; }
.wsp-auth__note {
  margin: 1.25rem 0 0;
  padding: 1.5rem 1.75rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
  font-size: 1rem;
  color: var(--wsp-muted, #5a5a5a);
  line-height: 1.55;
}

/* ---- Form: wraps in a `--wsp-prog-card-bg` rounded card so it
   visually mirrors `.wsp-program-single__facts`. ---- */
.wsp-auth-form {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  padding: 2rem;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
}
@media (min-width: 640px) {
  .wsp-auth-form { padding: 2.5rem; gap: 1.25rem; }
}
.wsp-auth-form__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.1rem;
}
@media (min-width: 560px) {
  .wsp-auth-form__row { grid-template-columns: 1fr 1fr; gap: 1.25rem; }
}
.wsp-auth-form__label {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
.wsp-auth-form__label > span {
  /* Eyebrow label — same scale + uppercase as
     `.wsp-program-single__fact dt` so the form fields read like
     the program facts list. */
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wsp-muted, #5a5a5a);
}
.wsp-auth-form input[type="text"],
.wsp-auth-form input[type="email"],
.wsp-auth-form input[type="password"] {
  padding: 0.85rem 1rem;
  border: 1.5px solid #e0e0e0;
  border-radius: 12px;
  font-size: 1.05rem;
  font-weight: 500;
  background: #fff;
  color: var(--wsp-text, #1a1a1a);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.wsp-auth-form input::placeholder { color: #a0a0a0; }
.wsp-auth-form input:focus {
  outline: none;
  border-color: var(--wsp-prog-cta-bg, #14bcbc);
  box-shadow: 0 0 0 3px rgba(20, 188, 188, 0.18);
}
/* Submit: literal clone of `.wsp-prog-card__cta` — same padding,
   radius, font, shadow, transition. No border (solid pill) so it
   reads identical to every other primary CTA in the portal. */
.wsp-auth-form__submit {
  align-self: stretch;
  margin-top: 0.5rem;
  padding: 0.95rem 1.5rem;
  background-color: var(--wsp-prog-cta-bg, #14bcbc);
  color: var(--wsp-prog-cta-text, #fff);
  text-shadow: var(--wsp-prog-cta-shadow, 0 0 10px rgba(0, 0, 0, 0.3));
  border: none;
  border-radius: var(--wsp-prog-cta-radius, 60px);
  font-weight: 700;
  font-size: 0.95rem;
  line-height: 1.15;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s;
}
.wsp-auth-form__submit:hover,
.wsp-auth-form__submit:focus {
  background-color: var(--wsp-prog-cta-bg-hover, #0fa3a3);
  color: var(--wsp-prog-cta-text, #fff);
}
.wsp-auth-form__notice {
  padding: 1rem 1.25rem;
  border-radius: 12px;
  font-size: 1rem;
  line-height: 1.5;
}
.wsp-auth-form__notice--error {
  background: #fde6e6;
  color: #8a1f1f;
  border: 1px solid #f5c2c2;
}
.wsp-auth-form__error {
  margin: -0.5rem 0 0;
  font-size: 0.9rem;
  color: #8a1f1f;
  font-weight: 700;
}

/* Success card — same surface treatment as the form card so the
   transition from form → success feels seamless. */
.wsp-auth--register-success .wsp-auth__heading {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.wsp-auth--register-success .wsp-auth__heading::before {
  content: "";
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--wsp-prog-cta-bg, #14bcbc)
              url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>")
              center / 60% 60% no-repeat;
  flex-shrink: 0;
}

/* =================================================================
 * Artists — `[wsp_artists]` shortcode
 * =================================================================
 * Layout mirrors the BLQ Murals page's "WHAT YOU'LL FIND" section:
 * an eyebrow + display heading at the top, then a column of items
 * with image on one side and body text + CTA on the other.
 *
 * Each row alternates image-left ↔ image-right via `:nth-child(even)`,
 * giving the section a kinetic feel without any per-row markup
 * differences. On mobile both stack to image-on-top.
 */
/* Background image lives on a CSS var so the customer can rebrand
   via Settings → Appearance → Custom CSS without editing the plugin:
       :root { --wsp-artists-bg: url('/path/to/my-image.png'); }
   The default points at the BLQ-provided Rectangle-31-1 hero image. */
:root {
  --wsp-artists-bg: url('/wp-content/uploads/2026/05/Rectangle-31-1.png');
}

.wsp-artists {
  position: relative;
  /* Fills the parent Elementor section edge-to-edge. No
     border-radius (admin doesn't want a rounded box — the section
     should read as a flat band). Inner header + list cap
     themselves at 1100px via their own `margin: 0 auto`. */
  width: 100%;
  max-width: 100%;
  margin: 0;
  padding: 4rem clamp(1.25rem, 4vw, 3rem);
  background-image: var(--wsp-artists-bg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  color: #ffffff;
  box-sizing: border-box;
}
/* Centered header to match the BLQ reference design. The eyebrow
   sits on a tighter scale (uppercase tracking), then a much larger
   yellow display heading in Nanum Pen Script, then an optional
   short intro line ("Tour stops include:" in the BLQ original). */
.wsp-artists__header {
  margin: 0 auto 2.5rem;
  max-width: 800px;
  text-align: center;
}
/* Frame-29.png is a 300×20 ornamental bar shipped at the top of
   the BLQ section as a visual opener. We render at its native
   width up to a soft cap so it doesn't pixelate on small viewports.
   `display: inline-block` lets the parent's `text-align: center`
   center it horizontally without needing margin: 0 auto. */
.wsp-artists__header-image {
  display: inline-block;
  height: auto;
  max-width: min(300px, 80%);
  margin: 0 0 1rem;
  vertical-align: middle;
}
/* Bottom-bracketing copy of the ornament — flips the margin so it
   sits BELOW the heading with the same gap above as the top
   ornament has below it. Symmetry: top ornament gap is `1rem`
   under itself; bottom ornament gap is `1rem` above itself. */
.wsp-artists__header-image--bottom {
  margin: 1rem 0 1rem;
}
.wsp-artists__eyebrow {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.92);
}
/* Display heading. Sizing + color taken straight from the
   Elementor "Meet our Afro-Latin Artists" rule on
   .elementor-element-2a8537b so the shortcode matches the design
   system exactly: 40px / 54px line-height, weight 400, uppercase,
   yellow-green (#E5FB8B). Font family stays Nanum Pen Script
   (script display face Elementor preloads on every page). */
.wsp-artists__heading {
  margin: 0 0 0.75rem;
  /* Porter Sans Block is the chunky display face used on the BLQ
     reference pages. Loaded by the theme/Elementor at the page
     level — we just reference it here. `!important` mirrors the
     Elementor rule we're matching, so theme-level overrides on
     generic `h2` selectors can't reset it. */
  font-family: 'Porter Sans Block', sans-serif !important;
  font-size: 40px;
  font-weight: 400;
  line-height: 54px;
  text-transform: uppercase;
  color: #E5FB8B;
}
.wsp-artists__intro {
  margin: 0.5rem 0 0;
  font-size: 1.05rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.92);
}

/* 3-column numbered card grid (matches the BLQ "PUBLIC ART STOPS"
   reference). Each card:
     - Full-bleed image background (square)
     - Yellow numeric badge top-right (auto-counted via CSS counter)
     - Yellow title ribbon bottom-left with script font
     - Whole card is clickable via an invisible CTA overlay
   Existing PHP markup unchanged — only the visual treatment differs. */
.wsp-artists__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  /* Reading-width cap, centered. The OUTER `.wsp-artists` is
     full-width so its background fills the parent container; the
     grid inside stays comfortably read-width. */
  max-width: 1100px;
  margin: 0 auto;
  /* Reset the counter at the list level so each [wsp_artists] block
     starts at 1, even when the page has multiple sections. */
  counter-reset: wsp-artist-num;
}
@media (min-width: 560px) {
  .wsp-artists__list { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 880px) {
  .wsp-artists__list {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.75rem;
  }
}

/* Card shell — white background, flex column so the image sits on
   top and the info body fills the rest. Counter-increment drives
   the numbered badge inside the media zone. Hover lifts the card
   a few pixels — the only motion in the section. */
.wsp-artists__item {
  position: relative;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border-radius: 18px;
  overflow: hidden;
  isolation: isolate;
  counter-increment: wsp-artist-num;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  transition: transform 0.2s ease-out, box-shadow 0.2s ease-out;
}
.wsp-artists__item:hover,
.wsp-artists__item:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.18);
}

/* Numbered badge — yellow circle in Porter Sans Block-adjacent
   weight against the photo. Position absolute relative to the
   media zone (which is also positioned for stacking) so the badge
   floats above the image regardless of natural image dimensions. */
/* Numbered badge removed per BLQ direction. Counter setup left in
   place on the list/item so a future variant can opt the badge
   back in via a `.wsp-artists--numbered` modifier without re-wiring. */

/* Media is the top portion of the card — square aspect ratio so
   portrait + landscape photos crop predictably. Anchor link so the
   whole image is clickable to the artist profile. */
.wsp-artists__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--wsp-prog-card-bg, #f4f4f4);
}
.wsp-artists__media img,
.wsp-artists__placeholder,
.wsp-artists__placeholder-img,
.wsp-artists__placeholder-svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease-out;
}
.wsp-artists__item:hover .wsp-artists__media img,
.wsp-artists__item:hover .wsp-artists__placeholder-img {
  transform: scale(1.04);  /* gentle ken-burns effect on hover */
}
/* SVG fallback doesn't ken-burns — it's flat by design, so the
   transform would feel weird on a vector. */
.wsp-artists__placeholder {
  background: linear-gradient(135deg, #d8d8d8 0%, #ebebeb 60%, #f4f4f4 100%);
}

/* Info body — flex column with consistent gap. Padding scales
   with viewport so cards on mobile still feel airy. */
.wsp-artists__body {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 1.25rem 1.25rem 1rem;
  flex: 1; /* fills remaining card height so social row sits at bottom */
  color: #1a1a1a;
}

/* Name — Porter Sans Block to match the section heading style. */
.wsp-artists__name {
  margin: 0;
  font-family: 'Porter Sans Block', sans-serif;
  font-size: 1.25rem;
  font-weight: 400;
  line-height: 1.15;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
.wsp-artists__name a {
  color: inherit;
  text-decoration: none;
}
.wsp-artists__name a:hover,
.wsp-artists__name a:focus {
  color: #b48a17; /* deeper version of the yellow accent */
}

/* Title chip — yellow pill, compact. */
.wsp-artists__chip {
  margin: 0;
  align-self: flex-start;
  padding: 0.25rem 0.7rem;
  background: #E5FB8B;
  color: #1a1a1a;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* Disciplines — secondary metadata line under the chip. */
.wsp-artists__disciplines {
  margin: 0;
  font-size: 0.85rem;
  color: #6b6b6b;
  line-height: 1.4;
}

/* Bio snippet — small, soft body color, 3-line clamp so long bios
   don't push the card height around unpredictably. */
.wsp-artists__bio {
  margin: 0.25rem 0 0;
  font-size: 0.92rem;
  line-height: 1.5;
  color: #4a4a4a;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Footer row pushed to the bottom of the body via margin-top: auto.
   Holds the social icons on the left and the "Learn more →" link on
   the right. */
.wsp-artists__footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 0.85rem;
  border-top: 1px solid #ececec;
  gap: 0.75rem;
  flex-wrap: wrap;
}

/* Social icon row — 0.4rem gap between, icons size to the
   touch-target minimum (~36×36). Stroke uses currentColor so a
   single color change cascades through every icon. */
.wsp-artists__social {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.wsp-artists__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  color: #4a4a4a;
  transition: background-color 0.15s, color 0.15s;
}
.wsp-artists__social-link:hover,
.wsp-artists__social-link:focus {
  background: #E5FB8B;
  color: #1a1a1a;
  outline: none;
}
.wsp-artists__social-link svg {
  width: 1.05rem;
  height: 1.05rem;
}

/* Footer CTA — small inline text+arrow link, distinct from the
   social pills so the eye lands on it as the primary action. */
.wsp-artists__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.88rem;
  font-weight: 700;
  color: #1a1a1a;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  transition: gap 0.15s, color 0.15s;
}
.wsp-artists__cta:hover,
.wsp-artists__cta:focus {
  gap: 0.55rem;
  color: #b48a17;
}
.wsp-artists__cta-arrow {
  display: inline-block;
  font-weight: 800;
}

/* Empty state. */
.wsp-artists--empty {
  padding: 2.5rem 2rem;
  text-align: center;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: var(--wsp-prog-card-radius, 24px);
  color: var(--wsp-muted, #5a5a5a);
}

/* Load-more footer for [wsp_artists]. The button matches the
   `.wsp-prog-card__cta` pill so it feels native to the design
   system — same teal, same radius, same hover swap. Centered
   with breathing room below the last row. */
.wsp-artists__footer {
  /* Centered with the same reading-width cap as the list so the
     Load-more pill sits visually beneath the last row of cards on
     wide viewports rather than drifting to the edge. */
  max-width: 1100px;
  margin: 3rem auto 0;
  display: flex;
  justify-content: center;
}
/* BLQ Load More button — orange #FF6B43, Roboto 500, 25px padding.
   `!important` on the brand props so Elementor's `.elementor-button`
   defaults and the theme's generic `button {}` rule can't override
   them (which was making the button blend invisibly into the page).
   Hover keeps the same orange — the affordance is felt through a
   small lift + stronger shadow instead of a color shift. */
.wsp-artists__load-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  /* Big presence — sized to sit as the primary CTA on a wide pink
     section without disappearing into the visual noise. */
  padding: 48px 110px;
  min-width: 420px;
  min-height: 90px;
  background-color: #FF6B43 !important;
  color: #ffffff !important;
  border: none;
  border-radius: 4px;
  font-family: "Roboto", sans-serif !important;
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 1.15;
  text-transform: none;
  letter-spacing: 0.03em;
  cursor: pointer;
  box-shadow: 0 6px 14px rgba(255, 107, 67, 0.35);
  transition: transform 0.15s, box-shadow 0.15s, opacity 0.25s;
}
/* On narrow mobile viewports, scale the button down to fit edge
   gutters — keeps it readable without forcing horizontal scroll. */
@media (max-width: 560px) {
  .wsp-artists__load-more {
    padding: 32px 40px;
    min-width: 0;
    width: 100%;
    font-size: 1.15rem;
  }
}
.wsp-artists__load-more:hover:not(:disabled),
.wsp-artists__load-more:focus:not(:disabled) {
  background-color: #FF6B43 !important;
  color: #ffffff !important;
  transform: translateY(-2px);
  box-shadow: 0 6px 14px rgba(255, 107, 67, 0.4);
}
.wsp-artists__load-more:disabled {
  cursor: wait;
}
/* While loading: dim the label and show a small spinner next to it. */
.wsp-artists__load-more.is-loading .wsp-artists__load-more-label {
  opacity: 0.7;
}
.wsp-artists__load-more-spinner {
  display: none;
  width: 1rem;
  height: 1rem;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: wsp-spin 0.7s linear infinite;
}
.wsp-artists__load-more.is-loading .wsp-artists__load-more-spinner {
  display: inline-block;
}
.wsp-artists__load-more.is-done {
  opacity: 0;
  pointer-events: none;
}
.wsp-artists__load-more.is-error {
  background-color: #b32d2e;
}
@keyframes wsp-spin {
  to { transform: rotate(360deg); }
}

/* =================================================================
 * Single artist page (templates/artist-single.php)
 * =================================================================
 * Layout: back link → header (image + intro) → bio → info grid → contact.
 * Uses the same design tokens as the artist cards so the single page
 * feels like a zoom-in of one card rather than a parallel design.
 */
.wsp-artist-single {
  max-width: 1100px;
  margin: 2.5rem auto 4rem;
  padding: 0 1.5rem;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-artist-single__back {
  margin: 0 0 1.5rem;
  font-size: 1rem;
  font-weight: 600;
}
.wsp-artist-single__back a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--wsp-text, #1a1a1a);
  text-decoration: none;
  transition: color 0.15s;
}
.wsp-artist-single__back a:hover {
  color: #FF6B43;
}

/* Header — image left, intro right on desktop. Stack on mobile. */
.wsp-artist-single__header {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-bottom: 3rem;
  align-items: start;
}
@media (min-width: 760px) {
  .wsp-artist-single__header {
    grid-template-columns: 360px 1fr;
    gap: 3rem;
  }
}

.wsp-artist-single__media {
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: 18px;
  background: #ede8e0;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.12);
}
.wsp-artist-single__media img,
.wsp-artist-single__placeholder svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.wsp-artist-single__intro {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.wsp-artist-single__name {
  margin: 0;
  font-family: 'Porter Sans Block', sans-serif;
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--wsp-text, #1a1a1a);
}
.wsp-artist-single__title {
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: #4a4a4a;
}
.wsp-artist-single__disciplines {
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  list-style: none;
}
.wsp-artist-single__disciplines li {
  padding: 0.35rem 0.85rem;
  background: #E5FB8B;
  color: #1a1a1a;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

.wsp-artist-single__social {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.wsp-artist-single__social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  background: #f5f5f5;
  color: #1a1a1a;
  transition: background-color 0.15s, transform 0.15s, color 0.15s;
}
.wsp-artist-single__social-link:hover,
.wsp-artist-single__social-link:focus {
  background: #FF6B43;
  color: #fff;
  transform: translateY(-2px);
  outline: none;
}
.wsp-artist-single__social-link svg {
  width: 1.25rem;
  height: 1.25rem;
}

/* Section blocks — bio gets full width, others sit in the info
   grid below. */
.wsp-artist-single__section {
  margin-bottom: 2.5rem;
}
.wsp-artist-single__section > h2 {
  margin: 0 0 1rem;
  padding-bottom: 0.5rem;
  font-family: 'Porter Sans Block', sans-serif;
  font-size: 1.4rem;
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 2px solid #1a1a1a;
}
.wsp-artist-single__bio {
  font-size: 1.05rem;
  line-height: 1.7;
  color: #1a1a1a;
}

/* Three-up grid of optional info blocks (Education, Awards,
   Associations, Languages, Contribution). Cards self-collapse if
   their SF field is empty (handled in PHP) so the grid only
   contains populated content. */
.wsp-artist-single__info-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}
@media (min-width: 600px) {
  .wsp-artist-single__info-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 920px) {
  .wsp-artist-single__info-grid { grid-template-columns: repeat(3, 1fr); }
}
.wsp-artist-single__info-card {
  padding: 1.5rem;
  background: #fafafa;
  border-radius: 12px;
  border-left: 4px solid #FF6B43;
}
.wsp-artist-single__info-card h3 {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #4a4a4a;
}
.wsp-artist-single__info-card > div {
  font-size: 0.98rem;
  line-height: 1.55;
  color: #1a1a1a;
}

/* Contact block — definition list, two columns at desktop. */
.wsp-artist-single__contact {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem 2rem;
  margin: 0;
}
@media (min-width: 600px) {
  .wsp-artist-single__contact { grid-template-columns: 1fr 1fr; }
}
.wsp-artist-single__contact dt {
  margin: 0 0 0.25rem;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #4a4a4a;
}
.wsp-artist-single__contact dd {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}
.wsp-artist-single__contact dd a {
  color: #1a1a1a;
  text-decoration: none;
  border-bottom: 2px solid #FF6B43;
  transition: color 0.15s;
}
.wsp-artist-single__contact dd a:hover {
  color: #FF6B43;
}

/* =================================================================
 * BLQ [wsp_events] — rich event grid with category filter pills
 * =================================================================
 * Mirrors the [wsp_artists] section's visual language so the two
 * BLQ surfaces feel like siblings:
 *   - Pink watercolor background banner (uses --wsp-artists-bg)
 *   - Ornaments above + below the heading
 *   - 3-col card grid, white cards with rounded corners
 *   - Orange Roboto load-more pill (#FF6B43)
 * New for events: a date badge in the top-right of each card and
 * a filter-pill row above the grid.
 */
.wsp-events {
  position: relative;
  width: 100%;
  max-width: 100%;
  margin: 0;
  padding: 4rem clamp(1.25rem, 4vw, 3rem);
  background-image: var(--wsp-artists-bg);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  color: #ffffff;
  box-sizing: border-box;
}
.wsp-events__header {
  margin: 0 auto 2rem;
  max-width: 800px;
  text-align: center;
}
.wsp-events__header-image {
  display: inline-block;
  height: auto;
  max-width: min(300px, 80%);
  margin: 0 0 1rem;
  vertical-align: middle;
}
.wsp-events__header-image--bottom {
  margin: 1rem 0 1rem;
}
.wsp-events__eyebrow {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.92);
}
.wsp-events__heading {
  margin: 0 0 0.75rem;
  font-family: 'Porter Sans Block', sans-serif !important;
  font-size: 40px;
  font-weight: 400;
  line-height: 54px;
  text-transform: uppercase;
  color: #E5FB8B;
}
.wsp-events__intro {
  margin: 0.5rem 0 0;
  font-size: 1.05rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.92);
}

/* Category-filter pill row above the grid. Pills are click
   targets; the JS swaps the cards without a page reload. */
.wsp-events__filter {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  max-width: 1100px;
  margin: 0 auto 2rem;
}
.wsp-events__filter-pill {
  padding: 0.6rem 1.4rem;
  background: rgba(255, 255, 255, 0.18);
  color: #ffffff;
  border: 2px solid rgba(255, 255, 255, 0.5);
  border-radius: 999px;
  font-family: "Roboto", sans-serif;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s, border-color 0.15s, transform 0.05s;
}
.wsp-events__filter-pill:hover,
.wsp-events__filter-pill:focus {
  background: rgba(255, 255, 255, 0.35);
  border-color: #ffffff;
  outline: none;
}
.wsp-events__filter-pill.is-active {
  background: #E5FB8B;
  color: #1a1a1a;
  border-color: #E5FB8B;
}
.wsp-events__filter-pill:active { transform: translateY(1px); }

/* Card grid — 1 / 2 / 3 columns at 0 / 560 / 880px. */
.wsp-events__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  max-width: 1100px;
  margin: 0 auto;
  transition: opacity 0.15s;
}
.wsp-events__list.is-loading { opacity: 0.5; pointer-events: none; }
@media (min-width: 560px) {
  .wsp-events__list { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 880px) {
  .wsp-events__list {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.75rem;
  }
}

.wsp-events__item {
  position: relative;
  display: flex;
  flex-direction: column;
  background: #ffffff;
  border-radius: 18px;
  overflow: hidden;
  isolation: isolate;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s ease-out, box-shadow 0.2s ease-out;
}
.wsp-events__item:hover,
.wsp-events__item:focus-within {
  transform: translateY(-4px);
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.2);
}

.wsp-events__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #ede8e0;
}
.wsp-events__media img,
.wsp-events__placeholder-img,
.wsp-events__placeholder-svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease-out;
}
.wsp-events__item:hover .wsp-events__media img,
.wsp-events__item:hover .wsp-events__placeholder-img {
  transform: scale(1.04);
}

/* Date badge in the top-right corner. Two-line: big day number
   over the abbreviated month, all in Porter Sans Block. */
.wsp-events__date-badge {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0.4rem 0.85rem 0.5rem;
  background: #FF6B43;
  color: #ffffff;
  border-radius: 8px;
  font-family: 'Porter Sans Block', sans-serif;
  line-height: 1;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
}
.wsp-events__date-day {
  font-size: 1.4rem;
  letter-spacing: 0.02em;
}
.wsp-events__date-month {
  margin-top: 0.15rem;
  font-size: 0.7rem;
  letter-spacing: 0.12em;
}

.wsp-events__body {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 1.25rem 1.25rem 1rem;
  flex: 1;
  color: #1a1a1a;
}
.wsp-events__name {
  margin: 0;
  font-family: 'Porter Sans Block', sans-serif;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1.2;
  text-transform: uppercase;
}
.wsp-events__name a { color: inherit; text-decoration: none; }
.wsp-events__name a:hover, .wsp-events__name a:focus { color: #FF6B43; }
.wsp-events__chip {
  margin: 0;
  align-self: flex-start;
  padding: 0.22rem 0.7rem;
  background: #E5FB8B;
  color: #1a1a1a;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.wsp-events__facts {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.88rem;
  color: #4a4a4a;
}
.wsp-events__facts li {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  line-height: 1.35;
}
.wsp-events__bio {
  margin: 0.15rem 0 0;
  font-size: 0.92rem;
  line-height: 1.5;
  color: #4a4a4a;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.wsp-events__footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: auto;
  padding-top: 0.85rem;
  border-top: 1px solid #ececec;
  gap: 0.5rem;
}
.wsp-events__status {
  display: inline-block;
  padding: 0.18rem 0.6rem;
  background: #ececec;
  color: #4a4a4a;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.wsp-events__status--registration-open {
  background: rgba(229, 251, 139, 0.65);
  color: #1a1a1a;
}
.wsp-events__status--registration-closed,
.wsp-events__status--cancelled {
  background: #fde6e6;
  color: #8a1f1f;
}
.wsp-events__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.85rem;
  font-weight: 700;
  color: #1a1a1a;
  text-decoration: none;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  transition: gap 0.15s, color 0.15s;
}
.wsp-events__cta:hover, .wsp-events__cta:focus {
  gap: 0.55rem;
  color: #FF6B43;
}

/* Load-more footer — same orange Roboto pill as the artists
   section so the two surfaces match. */
.wsp-events__footer {
  max-width: 1100px;
  margin: 3rem auto 0;
  display: flex;
  justify-content: center;
}
.wsp-events__load-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 48px 110px;
  min-width: 420px;
  min-height: 90px;
  background-color: #FF6B43 !important;
  color: #ffffff !important;
  border: none;
  border-radius: 4px;
  font-family: "Roboto", sans-serif !important;
  font-weight: 500;
  font-size: 1.5rem;
  line-height: 1.15;
  letter-spacing: 0.03em;
  cursor: pointer;
  box-shadow: 0 6px 14px rgba(255, 107, 67, 0.35);
  transition: transform 0.15s, box-shadow 0.15s, opacity 0.25s;
}
.wsp-events__load-more:hover:not(:disabled),
.wsp-events__load-more:focus:not(:disabled) {
  background-color: #FF6B43 !important;
  color: #ffffff !important;
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(255, 107, 67, 0.45);
}
@media (max-width: 560px) {
  .wsp-events__load-more {
    padding: 32px 40px;
    min-width: 0;
    width: 100%;
    font-size: 1.15rem;
  }
}
.wsp-events__load-more:disabled { cursor: wait; }
.wsp-events__load-more.is-loading .wsp-events__load-more-label { opacity: 0.7; }
.wsp-events__load-more-spinner {
  display: none;
  width: 1rem;
  height: 1rem;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: wsp-spin 0.7s linear infinite;
}
.wsp-events__load-more.is-loading .wsp-events__load-more-spinner { display: inline-block; }
.wsp-events__load-more.is-done { opacity: 0; pointer-events: none; }
.wsp-events__load-more.is-error { background-color: #b32d2e !important; }

.wsp-events--empty {
  padding: 2.5rem 2rem;
  text-align: center;
  background: var(--wsp-prog-card-bg, #f4f4f4);
  border-radius: 18px;
  color: var(--wsp-muted, #5a5a5a);
}
