/**
 * Block pattern styles.
 *
 * Loaded in BOTH contexts — wp_enqueue_style() on the frontend and add_editor_style()
 * in wp-admin — so a pattern cannot look different in the inserter than it does on the
 * page. That parity is the whole point: the client picks a pattern by looking at it.
 *
 * Depends on assets/css/design-tokens.css for var(--ink-900) etc. in the editor.
 *
 * CONVENTIONS
 * - Plain semantic classes (hapster-*), NOT is-style-* block styles. Gutenberg treats
 *   block styles as mutually exclusive: applying one strips the others, so a base class
 *   plus a modifier class cannot coexist on the same block.
 * - No Tailwind utilities. Tailwind only scans root src/**, so a novel utility used here
 *   would compile to nothing.
 * - Core layout is left to core. The card row is a real core/columns block using its own
 *   flex layout and responsive stacking; only the gap is themed. Overriding it with CSS
 *   grid would silently deaden the column-width controls the client can see.
 */

/* ---------------------------------------------------------------- section band */

.hapster-solution-intro {
  position: relative;
  overflow: hidden;
  background: #fff;
  color: var(--ink-900);
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  /* theme.json gives every core/group a 0.875rem radius; a full-bleed band needs square
     corners. Reset explicitly or the band renders with rounded edges. */
  border-radius: 0;
}

.hapster-solution-intro > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-solution-intro > * {
    padding-inline: 2rem;
  }
}

/* Core's global stylesheet sets `:root :where(.is-layout-flow) > * { margin-block-start:
   1.25rem }` (blockGap) and cancels it on `> :first-child`. That lands at (0,1,0) — from the
   `:root`, since `:where()` contributes nothing — so a bare class rule here would be decided
   by source order. Qualifying with the core block class wins outright.

   Belt-and-braces rather than load-bearing: every spacing rule below is already (0,2,0) or
   higher, and `margin-top` and `margin-block-start` are the same property, so they conflict
   rather than add. This keeps any child added later on our spacing instead of core's. */
.hapster-solution-intro.wp-block-group > * + *,
.hapster-solution-intro__header.wp-block-group > * + * {
  margin-block-start: 0;
}

/* ---------------------------------------------------------------- header */

.hapster-solution-intro__header {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-solution-intro .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent-strong);
}

.hapster-solution-intro .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

.hapster-solution-intro .hapster-lead {
  margin: 1.25rem 0 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

/* ---------------------------------------------------------------- card row */

/* Qualified with .wp-block-columns to outrank core's generated per-block layout gap
   (.wp-container-core-columns-is-layout-*), which is emitted inline and also (0,1,0). */
.hapster-solution-intro .hapster-solution-intro__cards.wp-block-columns {
  margin-top: 3rem;
  gap: 2.5rem;
}

.hapster-solution-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1rem;
  border-radius: 0;
}

/* Same reasoning as the group rule above: core's column flow layout would otherwise add
   its own margin on top of this flex gap. */
.hapster-solution-card.wp-block-column > * + * {
  margin-block-start: 0;
}

.hapster-solution-card .hapster-solution-card__title {
  margin: 0;
  font-size: clamp(1.02rem, 1.25vw, 1.2rem);
  font-weight: 700;
  line-height: 1.375;
  color: var(--ink-900);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.hapster-solution-card .hapster-solution-card__desc {
  margin: 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

/* ---------------------------------------------------------------- icons

   The source block renders inline Lucide SVGs, which core blocks cannot emit. These
   reproduce them as CSS masks: the mask supplies the glyph shape and background-color
   supplies the tint, so the icon inherits the design token rather than hard-coding a hex.
   One composite class per variant — see the mutually-exclusive note at the top. */

/* Scoped to the known variants on purpose. If the base class alone painted the box, a
   mistyped or deleted modifier would render a solid 30px brand-green square instead of
   simply omitting the icon — mask-image falls back to `none`, which masks nothing out. */
.hapster-solution-card--user::before,
.hapster-solution-card--sparkles::before,
.hapster-solution-card--bot::before {
  content: "";
  display: block;
  inline-size: 30px;
  block-size: 30px;
  flex: none;
  background-color: var(--brand-accent-strong);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-solution-card--user::before {
  -webkit-mask-image: var(--hapster-icon-user);
  mask-image: var(--hapster-icon-user);
}

.hapster-solution-card--sparkles::before {
  -webkit-mask-image: var(--hapster-icon-sparkles);
  mask-image: var(--hapster-icon-sparkles);
}

.hapster-solution-card--bot::before {
  -webkit-mask-image: var(--hapster-icon-bot);
  mask-image: var(--hapster-icon-bot);
}

:root,
.editor-styles-wrapper {
  --hapster-icon-user: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2'/%3E%3Ccircle cx='12' cy='7' r='4'/%3E%3C/svg%3E");
  --hapster-icon-sparkles: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z'/%3E%3Cpath d='M20 3v4'/%3E%3Cpath d='M22 5h-4'/%3E%3Cpath d='M4 17v2'/%3E%3Cpath d='M5 18H3'/%3E%3C/svg%3E");
  --hapster-icon-bot: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 8V4H8'/%3E%3Crect width='16' height='12' x='4' y='8' rx='2'/%3E%3Cpath d='M2 14h2'/%3E%3Cpath d='M20 14h2'/%3E%3Cpath d='M15 13v2'/%3E%3Cpath d='M9 13v2'/%3E%3C/svg%3E");

  /* action-cta button icons — stroke-width 2 in the source block, not 1.5 */
  --hapster-icon-phone: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E");
  --hapster-icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E");
  --hapster-icon-workflow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='8' height='8' x='3' y='3' rx='2'/%3E%3Cpath d='M7 11v4a2 2 0 0 0 2 2h4'/%3E%3Crect width='8' height='8' x='13' y='13' rx='2'/%3E%3C/svg%3E");
  --hapster-icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  --hapster-icon-x: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18'/%3E%3Cpath d='m6 6 12 12'/%3E%3C/svg%3E");
  --hapster-icon-linkedin: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z'/%3E%3Crect width='4' height='12' x='2' y='9'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E");
  --hapster-icon-linkedin-white: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z'/%3E%3Crect width='4' height='12' x='2' y='9'/%3E%3Ccircle cx='4' cy='4' r='2'/%3E%3C/svg%3E");
  --hapster-icon-arrow-up-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 7h10v10'/%3E%3Cpath d='M7 17 17 7'/%3E%3C/svg%3E");
  --hapster-icon-calculator: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='16' height='20' x='4' y='2' rx='2'/%3E%3Cline x1='8' x2='16' y1='6' y2='6'/%3E%3Cline x1='16' x2='16' y1='14' y2='18'/%3E%3Cpath d='M16 10h.01'/%3E%3Cpath d='M12 10h.01'/%3E%3Cpath d='M8 10h.01'/%3E%3Cpath d='M12 14h.01'/%3E%3Cpath d='M8 14h.01'/%3E%3Cpath d='M12 18h.01'/%3E%3Cpath d='M8 18h.01'/%3E%3C/svg%3E");
}

/* ================================================================ team founders */

.hapster-team {
  position: relative;
  background: #fff;
  color: var(--ink-900);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-team > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-team > * {
    padding-inline: 2rem;
  }
}

.hapster-team.wp-block-group > * + *,
.hapster-team__header.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-team__header {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-team .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent-strong);
}

.hapster-team .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

.hapster-team .hapster-lead {
  margin: 1.25rem 0 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

.hapster-team .hapster-team__grid.wp-block-columns {
  margin-top: 3.5rem;
  gap: 2rem;
}

/* KNOWN DIVERGENCE. The block steps 1 -> 2 -> 4 columns (sm:grid-cols-2 lg:grid-cols-4);
   core/columns does 1 -> 4, stacking below 782px and going four-across above it. The
   intermediate two-up band cannot be restored from CSS: core ships
   `@media (min-width:782px){ .wp-block-columns{ flex-wrap: nowrap !important } }`, and no
   selector outranks !important. Forcing it would mean !important of our own, which would then
   fight every future core change. Between 782px and 1024px the pattern therefore shows four
   narrower cards where the block shows two. Accepted rather than papered over. */

.hapster-team-card {
  border-radius: 0;
}

.hapster-team-card.wp-block-column > * + * {
  margin-block-start: 0;
}

.hapster-team-card__media {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-soft);
  aspect-ratio: 4 / 5;
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
}

.hapster-team-card__media .wp-block-image,
.hapster-team-card__media figure {
  margin: 0;
  block-size: 100%;
}

.hapster-team-card__media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  /* Matches the block's inline filter on every portrait. */
  filter: saturate(0.92) contrast(1.04);
  transition: transform 0.7s cubic-bezier(0, 0, 0.2, 1);
}

/* Hover zoom is on the whole card in the block (`group` + `group-hover:scale-[1.04]`), so
   hovering the role text zooms too. Matched here rather than scoping to the media box. */
.hapster-team-card:hover .hapster-team-card__media img {
  transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
  .hapster-team-card__media img {
    transition: none;
  }

  .hapster-team-card:hover .hapster-team-card__media img {
    transform: none;
  }
}

/* Gradient scrim so the overlaid name stays legible on light portraits. */
.hapster-team-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgb(11 15 20 / 0.55), transparent 50%, transparent);
}

.hapster-team-card .hapster-team-card__name {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 1;
  margin: 0;
  padding: 1rem;
  color: #fff;
  font-size: var(--fs-h3, clamp(1.125rem, 1.6vw, 1.5rem));
  font-weight: 700;
  line-height: 1.25;
}

.hapster-team-card .hapster-team-card__role {
  margin: 1rem 0 0;
  font-size: 0.875rem;
  line-height: 1.625;
  color: var(--ink-600);
}

/* ================================================================ action CTA */

.hapster-action {
  position: relative;
  overflow: hidden;
  background: var(--off-white);
  color: var(--ink-900);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-action > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-action > * {
    padding-inline: 2rem;
  }
}

.hapster-action.wp-block-group > * + *,
.hapster-action__body.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-action__body {
  max-width: 48rem;
  margin-inline: auto;
  text-align: center;
  border-radius: 0;
}

.hapster-action .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--brand-accent-strong);
}

.hapster-action .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

.hapster-action .hapster-lead {
  margin: 1.25rem 0 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

/* display:flex is set explicitly rather than relying on core. core/buttons only emits its
   is-layout-flex class when the block carries a `layout` attribute; without it the buttons
   stack vertically while justify-content and gap appear to be applied. The pattern markup
   sets the layout attribute too — this is the belt to that pair of braces. */
.hapster-action .hapster-action__ctas {
  display: flex;
  flex-wrap: wrap;
  margin-top: 2rem;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
}

/* Buttons. theme.json styles core/button with a 0.625rem radius and black fill; these are
   pill-shaped brand CTAs, so both are overridden explicitly. */
.hapster-action .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem 1.75rem;
  border-radius: 999px;
  font-size: 0.875rem;
  font-weight: 700;
  text-decoration: none;
  transition: background-color 0.2s, color 0.2s;
}

.hapster-action .hapster-cta-contact .wp-block-button__link {
  background: var(--hapster-orange, #FFC000);
  color: #000;
  border: 0;
}

/* Matches hapster/action-cta-static: `hover:bg-black hover:text-white`. */
.hapster-action .hapster-cta-contact .wp-block-button__link:hover {
  background: #000;
  color: #fff;
}

.hapster-action .hapster-cta-roi .wp-block-button__link {
  background: transparent;
  color: var(--ink-900);
  border: 1px solid var(--ink-900);
}

.hapster-action .hapster-cta-roi .wp-block-button__link:hover {
  background: var(--ink-900);
  color: #fff;
}

/* Button icons, same mask technique as the solution-intro cards. currentColor is used so the
   glyph inverts with the label on hover. */
.hapster-action .hapster-cta-contact .wp-block-button__link::before,
.hapster-action .hapster-cta-contact .wp-block-button__link::after,
.hapster-action .hapster-cta-roi .wp-block-button__link::before {
  content: "";
  inline-size: 16px;
  block-size: 16px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-action .hapster-cta-contact .wp-block-button__link::before {
  -webkit-mask-image: var(--hapster-icon-phone);
  mask-image: var(--hapster-icon-phone);
}

.hapster-action .hapster-cta-contact .wp-block-button__link::after {
  -webkit-mask-image: var(--hapster-icon-arrow-right);
  mask-image: var(--hapster-icon-arrow-right);
}

.hapster-action .hapster-cta-roi .wp-block-button__link::before {
  -webkit-mask-image: var(--hapster-icon-calculator);
  mask-image: var(--hapster-icon-calculator);
}

/* ================================================================ history timeline */

.hapster-history {
  position: relative;
  background: var(--off-white);
  color: var(--ink-900);
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-history > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-history > * {
    padding-inline: 2rem;
  }
}

.hapster-history.wp-block-group > * + *,
.hapster-history__header.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-history__header {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-history .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent-strong);
}

.hapster-history .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

.hapster-history .hapster-lead {
  margin: 1.25rem 0 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

/* The connector rail. In the block this is a separate absolutely-positioned <span>; core
   blocks cannot emit a decorative element, so it is a pseudo-element on the row instead.
   Only drawn at >=992px, matching the block's `hidden lg:block`. */
.hapster-history .hapster-history__items.wp-block-columns {
  position: relative;
  margin-top: 3.5rem;
  gap: 1.5rem;
}

@media (min-width: 992px) {
  .hapster-history .hapster-history__items.wp-block-columns::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    top: 2.25rem;
    block-size: 1px;
    background: color-mix(in srgb, var(--brand-accent) 40%, transparent);
  }
}

.hapster-history-item {
  position: relative;
  padding-top: 3rem;
  border-radius: 0;
}

.hapster-history-item.wp-block-column > * + * {
  margin-block-start: 0;
}

/* The timeline dot, likewise a <span> in the block. The ring is drawn with a box-shadow in
   the band colour so it reads as a break in the connector rail. */
.hapster-history-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.75rem;
  inline-size: 1rem;
  block-size: 1rem;
  border-radius: 999px;
  background: var(--brand-accent);
  box-shadow: 0 0 0 4px var(--off-white);
}

.hapster-history-item .hapster-history-item__year {
  margin: 0;
  font-size: clamp(1.5rem, 2.5vw, 2rem);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--brand-accent-strong);
}

.hapster-history-item .hapster-history-item__title {
  margin: 0.75rem 0 0;
  font-weight: 700;
  line-height: 1.375;
  color: var(--ink-900);
}

.hapster-history-item .hapster-history-item__desc {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.625;
  color: var(--ink-600);
}

/* ================================================================ diagram

   Unlike the other patterns this one is NOT a section band. hapster/diagram-static is a card
   that lives inside hapster/content-article (it is in that block's allowedBlocks), so the
   pattern is the card too. max-width keeps it sensible when inserted at the top level of a
   page, where nothing supplies the article measure; inside an article the parent is already
   narrower, so the cap never bites. */

.hapster-diagram {
  max-width: 57rem;
  margin-inline: auto;
  padding: 1.25rem;
  background: #fff;
  border: 1px solid var(--border-gray, #E6E8EC);
  border-radius: 1rem;
}

@media (min-width: 768px) {
  .hapster-diagram {
    padding: 1.5rem;
  }
}

.hapster-diagram.wp-block-group > * + * {
  margin-block-start: 0;
}

/* Counter lives on the card, not on a row, because the cards are split across two
   core/columns rows — resetting per row would restart the numbering at 01 on the second. */
.hapster-diagram {
  counter-reset: hapster-diagram-card;
}

/* ---------------------------------------------------------------- header */

.hapster-diagram .hapster-diagram__header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  color: var(--hapster-green, #7DC6AD);
  border-radius: 0;
}

/* The workflow icon is unconditional in the block — it renders even when the badge label is
   empty — so it hangs off the header rather than off the badge paragraph. */
.hapster-diagram .hapster-diagram__header::before {
  content: "";
  inline-size: 18px;
  block-size: 18px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-image: var(--hapster-icon-workflow);
  mask-image: var(--hapster-icon-workflow);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-diagram .hapster-diagram__badge {
  margin: 0;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: inherit;
}

.hapster-diagram .hapster-diagram__title {
  margin: 0.75rem 0 0;
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: normal;
  color: var(--deep-navy, #082033);
}

.hapster-diagram .hapster-diagram__lead {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.625;
  color: var(--text-gray, #4A5563);
}

/* ---------------------------------------------------------------- card grid

   The block is a CSS grid: one column, two from 768px. core/columns stacks below 782px on its
   own, so only the two-up band needs authoring. Qualified to (0,4,0) to beat core's own
   (0,3,0) flex-basis rule without !important. The 782 vs 768 breakpoint leaves a 14px window
   where the block is two-up and the pattern is still stacked. */

/* Two core/columns rows of two, rather than one row of four with flex-wrap. Core ships
   `@media (min-width:782px){ .wp-block-columns{ flex-wrap: nowrap !important } }`, so a
   single wrapping row is not achievable without !important of our own. Two rows is also what
   an editor would build by hand, and it keeps every column control meaningful. */
.hapster-diagram .hapster-diagram__grid.wp-block-columns {
  margin-top: 1.25rem;
  gap: 0.75rem;
}

.hapster-diagram .hapster-diagram__grid.wp-block-columns + .hapster-diagram__grid.wp-block-columns {
  margin-top: 0.75rem;
}

.hapster-diagram-card {
  padding: 1rem;
  background: var(--off-white);
  border: 1px solid var(--border-gray, #E6E8EC);
  border-radius: var(--radius-soft);
  min-width: 0;
  counter-increment: hapster-diagram-card;
}

.hapster-diagram-card.wp-block-column > * + * {
  margin-block-start: 0;
}

/* The ordinal is generated in save.js as String(index + 1).padStart(2, "0"). A CSS counter
   reproduces that exactly AND keeps it correct when an editor duplicates or deletes a card —
   hardcoding "01"…"04" into the markup would not. */
.hapster-diagram-card::before {
  content: counter(hapster-diagram-card, decimal-leading-zero);
  display: block;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--hapster-green, #7DC6AD);
}

.hapster-diagram-card .hapster-diagram-card__title {
  margin: 0.5rem 0 0;
  font-weight: 700;
  color: var(--deep-navy, #082033);
}

.hapster-diagram-card .hapster-diagram-card__desc {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  line-height: 1.625;
  color: var(--text-gray, #4A5563);
}

/* ================================================================ message separator */

.hapster-message {
  background: var(--off-white);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  border-radius: 0;
}

.hapster-message.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-message .hapster-message__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  max-width: var(--container-max);
  margin-inline: auto;
  padding: 3rem 1.5rem;
  border-radius: 0;
}

@media (min-width: 768px) {
  .hapster-message .hapster-message__inner {
    padding: 4rem 2rem;
  }
}

/* The short accent rule is a decorative <span> in the block; core blocks cannot emit one, so
   it becomes a pseudo-element on the flex row. flex:none reproduces flex-shrink-0. */
.hapster-message .hapster-message__inner::before {
  content: "";
  inline-size: 4rem;
  block-size: 1px;
  flex: none;
  background: var(--brand-accent);
}

.hapster-message .hapster-message__text {
  margin: 0;
  max-width: 48rem;
  font-size: 1rem;
  font-style: italic;
  line-height: 1.625;
  color: var(--ink-400);
}

/* ================================================================ final CTA proof */

.hapster-final-cta {
  position: relative;
  overflow: hidden;
  background: var(--ink-900);
  color: #fff;
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-final-cta > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-final-cta > * {
    padding-inline: 2rem;
  }
}

.hapster-final-cta.wp-block-group > * + *,
.hapster-final-cta__body.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-final-cta__body {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-final-cta .hapster-eyebrow {
  margin: 0 0 1.25rem;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent);
}

.hapster-final-cta .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -0.025em;
  color: #fff;
}

.hapster-final-cta .hapster-lead {
  margin: 1.25rem 0 0;
  max-width: 42rem;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: rgb(255 255 255 / 0.7);
}

/* The block's CTA row is `flex flex-col @md:flex-row items-start @md:items-center gap-5
   @md:gap-7` — no flex-wrap. core/buttons needs its layout attribute for flex at all, which
   the markup supplies; the column-to-row step is reproduced here. */
.hapster-final-cta .hapster-final-cta__ctas {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
  margin-top: 2rem;
}

@media (min-width: 768px) {
  .hapster-final-cta .hapster-final-cta__ctas {
    flex-direction: row;
    align-items: center;
    gap: 1.75rem;
  }
}

.hapster-final-cta .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.hapster-final-cta .hapster-cta-contact .wp-block-button__link {
  padding: 0.875rem 1.5rem;
  border-radius: var(--radius-soft);
  background: var(--brand-accent);
  color: var(--brand-accent-ink);
  border: 0;
}

.hapster-final-cta .hapster-cta-contact .wp-block-button__link:hover {
  background: #fff;
}

/* The secondary is a bare text button in the block — no fill, no padding, underline on hover
   with a brand-accent decoration. */
.hapster-final-cta .hapster-cta-roi .wp-block-button__link {
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: transparent;
  color: #fff;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--brand-accent);
}

.hapster-final-cta .hapster-cta-roi .wp-block-button__link:hover {
  background: transparent;
  text-decoration-line: underline;
}

.hapster-final-cta .hapster-cta-contact .wp-block-button__link::before,
.hapster-final-cta .hapster-cta-contact .wp-block-button__link::after,
.hapster-final-cta .hapster-cta-roi .wp-block-button__link::before,
.hapster-final-cta .hapster-cta-roi .wp-block-button__link::after {
  content: "";
  inline-size: 16px;
  block-size: 16px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.hapster-final-cta .hapster-cta-contact .wp-block-button__link::before {
  -webkit-mask-image: var(--hapster-icon-phone);
  mask-image: var(--hapster-icon-phone);
}

.hapster-final-cta .hapster-cta-roi .wp-block-button__link::before {
  -webkit-mask-image: var(--hapster-icon-calculator);
  mask-image: var(--hapster-icon-calculator);
}

.hapster-final-cta .wp-block-button__link::after {
  -webkit-mask-image: var(--hapster-icon-arrow-right);
  mask-image: var(--hapster-icon-arrow-right);
}

/* The arrow on the secondary is brand-accent in the block, not white. */
.hapster-final-cta .hapster-cta-roi .wp-block-button__link::after {
  background-color: var(--brand-accent);
}

/* `group-hover:translate-x-1` on both arrows. */
.hapster-final-cta .wp-block-button__link:hover::after {
  transform: translateX(0.25rem);
}

@media (prefers-reduced-motion: reduce) {
  .hapster-final-cta .wp-block-button__link::after,
  .hapster-final-cta .wp-block-button__link:hover::after {
    transition: none;
    transform: none;
  }
}

/* ================================================================ pricing proof */

.hapster-pricing {
  position: relative;
  overflow: hidden;
  background: #fff;
  color: var(--ink-900);
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-pricing > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-pricing > * {
    padding-inline: 2rem;
  }
}

.hapster-pricing.wp-block-group > * + *,
.hapster-pricing__header.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-pricing__header {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-pricing .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent-strong);
}

.hapster-pricing .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

.hapster-pricing .hapster-lead {
  margin: 1.25rem 0 0;
  font-size: var(--fs-lead);
  line-height: 1.625;
  color: var(--ink-600);
}

/* The block draws its plan dividers with `gap-px bg-[var(--hairline)]` — a 1px flex gap over a
   hairline background, so the gaps read as rules between white cards. Reproduced here. */
.hapster-pricing .hapster-pricing__plans.wp-block-columns {
  margin-top: 3rem;
  gap: 1px;
  background: var(--hairline);
  /* The row is a direct child of the band, so it carries the container's inline padding.
     Without this the hairline fill paints under that padding and shows as grey strips down
     the outer edges of the section. content-box keeps the fill behind the cards only. */
  background-clip: content-box;
}

.hapster-pricing-plan {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  padding: 1.75rem;
  background: #fff;
  border-radius: 0;
  /* transparent by default so the highlighted variant can swap the colour without shifting
     anything by 2px */
  border-top: 2px solid transparent;
}

@media (min-width: 768px) {
  .hapster-pricing-plan {
    padding: 2rem;
  }
}

.hapster-pricing-plan.wp-block-column > * + * {
  margin-block-start: 0;
}

.hapster-pricing-plan--highlighted {
  border-top-color: var(--brand-accent);
}

.hapster-pricing-plan .hapster-pricing-plan__label {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-400);
}

.hapster-pricing-plan .hapster-pricing-plan__price {
  margin: 0.25rem 0 0;
  font-size: var(--fs-h2);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--ink-900);
}

.hapster-pricing-plan .hapster-pricing-plan__subtitle {
  margin: 0.25rem 0 0;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--ink-400);
}

/* core/list, styled as the block's check list. The tick is a mask on the marker so the list
   stays a real core/list the editor can add items to. */
.hapster-pricing-plan .hapster-pricing-plan__features {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-700);
}

.hapster-pricing-plan .hapster-pricing-plan__features li {
  position: relative;
  padding-inline-start: 1.625rem;
}

.hapster-pricing-plan .hapster-pricing-plan__features li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 0.15em;
  inline-size: 1rem;
  block-size: 1rem;
  background-color: var(--ink-400);
  -webkit-mask-image: var(--hapster-icon-check);
  mask-image: var(--hapster-icon-check);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-pricing-plan--highlighted .hapster-pricing-plan__features li::before {
  background-color: var(--brand-accent-strong);
}

/* mt-auto in the block: the CTA is pinned to the bottom of the card so all three align. */
.hapster-pricing-plan .hapster-pricing-plan__cta {
  margin-top: auto;
}

.hapster-pricing-plan .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.625rem 1rem;
  border-radius: var(--radius-soft);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
  background: transparent;
  color: var(--ink-900);
  border: 1px solid var(--hairline);
  transition: border-color 0.15s, background-color 0.15s, color 0.15s;
}

.hapster-pricing-plan .wp-block-button__link:hover {
  border-color: var(--ink-900);
}

.hapster-pricing-plan--highlighted .wp-block-button__link {
  background: var(--brand-accent);
  color: var(--brand-accent-ink);
  border-color: var(--brand-accent);
}

.hapster-pricing-plan--highlighted .wp-block-button__link:hover {
  background: var(--brand-accent-strong);
  color: #fff;
  border-color: var(--brand-accent-strong);
}

.hapster-pricing-plan .wp-block-button__link::after {
  content: "";
  inline-size: 14px;
  block-size: 14px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-image: var(--hapster-icon-arrow-right);
  mask-image: var(--hapster-icon-arrow-right);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-pricing .hapster-pricing__footnote {
  margin: 1.5rem 0 0;
  font-size: 0.75rem;
  font-style: italic;
  color: var(--ink-400);
}

/* ================================================================ comparison table */

.hapster-comparison {
  position: relative;
  overflow: hidden;
  background: var(--off-white);
  color: var(--ink-900);
  border-top: 1px solid var(--hairline);
  padding-block: var(--space-section-y);
  scroll-margin-top: 5rem;
  border-radius: 0;
}

.hapster-comparison > * {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .hapster-comparison > * {
    padding-inline: 2rem;
  }
}

.hapster-comparison.wp-block-group > * + *,
.hapster-comparison__header.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-comparison__header {
  max-width: 48rem;
  border-radius: 0;
}

.hapster-comparison .hapster-eyebrow {
  margin: 0 0 1rem;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--brand-accent-strong);
}

.hapster-comparison .hapster-display {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--ink-900);
}

/* core/table ships its own figure/table wrapper; only the theming is added here. The block
   scrolls horizontally below its 640px min-width — core/table already provides overflow-x on
   .wp-block-table, so that behaviour comes for free. */
.hapster-comparison .hapster-comparison__table {
  margin-top: 3rem;
}

.hapster-comparison .hapster-comparison__table table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  text-align: left;
  background: transparent;
  /* The compat layer gives .wp-block-table a 1px outer border. The source block has none —
     its only rules are the per-row bottom borders set below. */
  border: 0;
}

.hapster-comparison .hapster-comparison__table :where(th, td) {
  border: 0;
  border-bottom: 1px solid var(--hairline);
  padding: 1.25rem 0 1.25rem 1.5rem;
  vertical-align: middle;
}

.hapster-comparison .hapster-comparison__table thead th {
  vertical-align: bottom;
}

/* First column is the row label — no left padding, and it carries the row heading weight. */
.hapster-comparison .hapster-comparison__table :where(th, td):first-child {
  padding-left: 0;
  padding-right: 1.5rem;
  font-size: var(--fs-lead);
  font-weight: 600;
  color: var(--ink-900);
}

.hapster-comparison .hapster-comparison__table thead th {
  font-size: var(--fs-h3, clamp(1.125rem, 1.6vw, 1.5rem));
  font-weight: 700;
  line-height: 1.25;
  color: var(--ink-900);
}

.hapster-comparison .hapster-comparison__table tbody td {
  color: var(--ink-700);
}

/* The highlighted column. core/table captures only content/tag/scope/align per cell, so a
   class on a <th> is dropped on re-serialisation and breaks validation — nth-child is the
   only hook available. Change the number if a column is added before Hapster. */
.hapster-comparison .hapster-comparison__table thead tr:first-child th:nth-child(4) {
  box-shadow: inset 0 -2px 0 0 var(--brand-accent);
}

/* Column subtitles are a second <thead> row rather than a <span>, for the same reason. */
.hapster-comparison .hapster-comparison__table thead tr:nth-child(2) th {
  padding-top: 0;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--ink-400);
  border-bottom: 0;
}

.hapster-comparison .hapster-comparison__table thead tr:first-child th {
  padding-bottom: 0.5rem;
  border-bottom: 0;
}

/* The bottom rule under the whole header belongs to the last head row. */
.hapster-comparison .hapster-comparison__table thead tr:last-child th {
  border-bottom: 1px solid var(--hairline);
}

/* Status glyphs are plain text (U+2713 / U+2715) because a cell cannot carry a class. Centred
   in their columns; the block tinted the check green and the cross grey, which is not
   reachable without a per-cell hook, so shape carries the meaning instead. */
.hapster-comparison .hapster-comparison__table tbody td:not(:first-child) {
  text-align: center;
  font-size: 1rem;
}

/* ================================================================ linkedin community CTA */

.hapster-linkedin {
  position: relative;
  overflow: hidden;
  background: var(--deep-navy, #082033);
  padding-block: 4rem;
  border-radius: 0;
}

@media (min-width: 768px) {
  .hapster-linkedin {
    padding-block: 5rem;
  }
}

/* The two decorative blobs are empty <span>s in the block; core blocks cannot emit those, so
   they become pseudo-elements. ::before is the LinkedIn-blue top-right blob, ::after the
   brand-green bottom-left one. Both are pointer-events:none, as in the source. */
.hapster-linkedin::before,
.hapster-linkedin::after {
  content: "";
  position: absolute;
  pointer-events: none;
  border-radius: 999px;
}

.hapster-linkedin::before {
  top: -8rem;
  right: -6rem;
  inline-size: 480px;
  block-size: 480px;
  opacity: 0.2;
  background: radial-gradient(circle, rgb(0, 119, 181) 0%, transparent 70%);
}

.hapster-linkedin::after {
  bottom: -6rem;
  left: -4rem;
  inline-size: 320px;
  block-size: 320px;
  opacity: 0.1;
  background: radial-gradient(circle, var(--brand-accent) 0%, transparent 70%);
}

.hapster-linkedin > * {
  position: relative;
  z-index: 1;
  max-width: 1100px;
  margin-inline: auto;
  padding-inline: 1rem;
}

@media (min-width: 768px) {
  .hapster-linkedin > * {
    padding-inline: 2rem;
  }
}

.hapster-linkedin.wp-block-group > * + *,
.hapster-linkedin__body.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-linkedin__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2rem;
  text-align: center;
  border-radius: 0;
}

/* The LinkedIn badge is an icon tile in the block. Reproduced as a pseudo-element on the body
   so no empty core block is needed to carry it. */
.hapster-linkedin__body::before {
  content: "";
  inline-size: 3.5rem;
  block-size: 3.5rem;
  flex: none;
  border-radius: 1rem;
  background-color: #0077B5;
  box-shadow: 0 8px 32px rgb(0 119 181 / 0.45);
  -webkit-mask: none;
  mask: none;
  background-image: var(--hapster-icon-linkedin-white);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 28px 28px;
}

.hapster-linkedin .hapster-eyebrow {
  margin: 0;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--brand-accent);
}

.hapster-linkedin .hapster-display {
  margin: 0;
  max-width: 36rem;
  font-size: clamp(1.75rem, 4vw, 3rem);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.025em;
  color: #fff;
}

.hapster-linkedin .hapster-lead {
  margin: 0;
  max-width: 42rem;
  font-size: 0.875rem;
  line-height: 1.625;
  color: rgb(255 255 255 / 0.68);
}

@media (min-width: 768px) {
  .hapster-linkedin .hapster-lead {
    font-size: 1rem;
  }
}

/* Chips are a core/list styled as a horizontal pill row, so an editor can add or remove one
   the same way they would edit any list. */
.hapster-linkedin .hapster-linkedin__chips {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}

.hapster-linkedin .hapster-linkedin__chips li {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.375rem 0.875rem;
  border: 1px solid rgb(255 255 255 / 0.15);
  border-radius: 999px;
  background: rgb(255 255 255 / 0.08);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgb(255 255 255 / 0.72);
}

.hapster-linkedin .hapster-linkedin__chips li::before {
  content: "";
  inline-size: 0.375rem;
  block-size: 0.375rem;
  flex: none;
  border-radius: 999px;
  background: var(--brand-accent);
}

.hapster-linkedin .hapster-linkedin__cta .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.75rem 1.5rem;
  border: 0;
  border-radius: 999px;
  background: #0077B5;
  color: #fff;
  font-size: 0.875rem;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 4px 24px rgb(0 119 181 / 0.5);
  transition: background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.hapster-linkedin .hapster-linkedin__cta .wp-block-button__link:hover {
  background: #005e8f;
  box-shadow: 0 6px 32px rgb(0 119 181 / 0.65);
}

.hapster-linkedin .hapster-linkedin__cta .wp-block-button__link::before {
  content: "";
  inline-size: 16px;
  block-size: 16px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-image: var(--hapster-icon-linkedin);
  mask-image: var(--hapster-icon-linkedin);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}

.hapster-linkedin .hapster-linkedin__cta .wp-block-button__link::after {
  content: "";
  inline-size: 14px;
  block-size: 14px;
  flex: none;
  background-color: currentColor;
  -webkit-mask-image: var(--hapster-icon-arrow-up-right);
  mask-image: var(--hapster-icon-arrow-up-right);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.hapster-linkedin .hapster-linkedin__cta .wp-block-button__link:hover::after {
  transform: translate(0.125rem, -0.125rem);
}

@media (prefers-reduced-motion: reduce) {
  .hapster-linkedin .hapster-linkedin__cta .wp-block-button__link::after,
  .hapster-linkedin .hapster-linkedin__cta .wp-block-button__link:hover::after {
    transition: none;
    transform: none;
  }
}

.hapster-linkedin .hapster-linkedin__audience {
  margin: 0;
  font-size: 0.75rem;
  color: rgb(255 255 255 / 0.42);
}

/* ================================================================ cas clients
 *
 * Sections for the "Cas client" story, shared by hapster/use-case-complete and the
 * individual section patterns it composes. The PHP single template owns only the
 * breadcrumb and a neutral alignment shell; hero, results, testimonials and every
 * other story section are ordinary Gutenberg content.
 *
 * Two constraints shape everything below.
 *
 * 1. COUNT-AGNOSTIC. The result and testimonial collections must absorb one item or
 *    six without a per-count pattern variant, because real cases differ: one client
 *    reports two metrics and two quotes, another reports four of each. Both grids are
 *    `auto-fit` + `minmax(min(100%, …), 1fr)` — the min() is what stops a fixed track
 *    minimum from overflowing a 320px viewport.
 *
 * 2. LIST SEMANTICS SURVIVE. Results and client facts are real <ul>/<li>, and the
 *    markers are suppressed with `::marker { content: "" }` rather than
 *    `list-style: none`. Setting list-style-type to none makes Safari/VoiceOver stop
 *    announcing the element as a list; emptying the marker's content does not. The
 *    breadcrumb can use list-style:none because its markup is ours and carries an
 *    explicit role="list".
 *
 * French copy runs long — "8 semaines au lieu de 6 mois", "Responsable des tuteurs et
 * de la transmission" — so nothing here sets a fixed height and every card wraps.
 */

/* ---------------------------------------------------------------- breadcrumb */

.hapster-use-case-breadcrumb-shell {
  width: min(calc(100% - 2rem), var(--container-max, 80rem));
  margin-inline: auto;
  padding-block-start: clamp(1.25rem, 3vw, 2.5rem);
}

.hapster-uc-breadcrumb {
  margin-block-end: clamp(1.5rem, 3vw, 2.5rem);
}

.hapster-uc-breadcrumb__list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  line-height: 1.4;
}

.hapster-uc-breadcrumb__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
}

/* Separator as a pseudo-element: decorative, and never announced or copied as text. */
.hapster-uc-breadcrumb__item + .hapster-uc-breadcrumb__item::before {
  content: "";
  flex: 0 0 auto;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--ink-400, #6B7585);
  opacity: 0.5;
}

/* --ink-600, not the --ink-400 used for muted text elsewhere: single-use_case.php paints
   this section with --off-white (#FAFAF8), and --ink-400 on that background measures
   4.46:1 — just under the 4.5:1 WCAG AA floor for text this size. --ink-600 gives 12.2:1. */
.hapster-uc-breadcrumb__link {
  color: var(--ink-600, #2A3340);
  text-decoration: none;
}

.hapster-uc-breadcrumb__link:hover,
.hapster-uc-breadcrumb__link:focus-visible {
  color: var(--ink-900, #0B0F14);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.hapster-uc-breadcrumb__current {
  color: var(--ink-700, #1B2330);
  font-weight: 600;
}

/* ---------------------------------------------------------------- hero figure */

.hapster-uc-hero.wp-block-group {
  padding: clamp(1.5rem, 4vw, 3.5rem);
  background: #FFFFFF;
  border: 1px solid var(--hairline, #ECEEF1);
  border-radius: var(--radius-soft, 14px);
}

.hapster-uc-hero__eyebrow {
  margin: 0 0 1rem;
  color: var(--brand-accent-strong, #5FAE94);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.hapster-uc-hero .hapster-uc-hero__title {
  max-width: 18ch;
  margin: 0;
  color: var(--ink-900, #0B0F14);
  font-size: var(--fs-h1, clamp(2.25rem, 5vw, 4.5rem));
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.035em;
}

.hapster-uc-hero__lead {
  max-width: 44rem;
  margin-block: clamp(1rem, 2vw, 1.5rem) 0;
  color: var(--ink-600, #2A3340);
  font-size: var(--fs-lead, clamp(1.05rem, 2vw, 1.35rem));
  line-height: 1.6;
}

.hapster-uc-hero .wp-block-buttons {
  margin-block-start: 1.5rem;
}

.hapster-uc-hero__figure {
  margin: clamp(1.75rem, 3.5vw, 2.75rem) 0 0;
  overflow: hidden;
  border-radius: var(--radius-soft, 14px);
}

/* width/height come from wp_get_attachment_image() so the box is reserved before the
   image decodes; the ratio here crops consistently without reintroducing layout shift. */
.hapster-uc-hero__image,
.hapster-uc-hero__figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

/* ---------------------------------------------------------------- section rhythm */

.hapster-uc-section.wp-block-group,
.hapster-uc-profile.wp-block-group {
  margin-block-start: clamp(2rem, 4.5vw, 3.5rem);
}

/* An optional image the editor never filled in serialises as <img> with no src. Without
   this it paints as an empty box (or a broken-image glyph) on the published page. */
.hapster-uc-section .wp-block-image img:not([src]),
.hapster-uc-profile .wp-block-image img:not([src]) {
  display: none;
}

.hapster-uc-solution__media {
  margin-block-start: clamp(1.25rem, 2.5vw, 2rem);
}

.hapster-uc-solution__media img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-soft, 14px);
}

/* ---------------------------------------------------------------- client facts */

.wp-block-list.hapster-uc-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  column-gap: clamp(1rem, 3vw, 2.5rem);
  margin: clamp(1rem, 2vw, 1.5rem) 0 0;
  padding-inline-start: 0;
  border-block-start: 1px solid var(--hairline, #ECEEF1);
}

.wp-block-list.hapster-uc-facts > li {
  margin: 0;
  padding-block: 0.8rem;
  border-block-end: 1px solid var(--hairline, #ECEEF1);
  color: var(--ink-600, #2A3340);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.wp-block-list.hapster-uc-facts > li::marker {
  content: "";
}

.wp-block-list.hapster-uc-facts > li > strong {
  color: var(--ink-900, #0B0F14);
  font-weight: 700;
}

/* ---------------------------------------------------------------- results */

.wp-block-list.hapster-uc-results {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  align-items: stretch;
  gap: clamp(0.875rem, 2vw, 1.25rem);
  margin: clamp(1.25rem, 2.5vw, 2rem) 0 0;
  padding-inline-start: 0;
}

.wp-block-list.hapster-uc-results > li {
  position: relative;
  min-width: 0;
  margin: 0;
  padding: clamp(1.15rem, 2.2vw, 1.5rem);
  background: #FFFFFF;
  border: 1px solid var(--hairline, #ECEEF1);
  border-radius: var(--radius-soft, 14px);
  color: var(--ink-600, #2A3340);
  font-size: clamp(0.975rem, 1.2vw, 1.075rem);
  line-height: 1.5;
  overflow-wrap: break-word;
  word-break: normal;
}

.wp-block-list.hapster-uc-results > li::before {
  content: "";
  display: block;
  width: 2rem;
  height: 3px;
  margin-block-end: 1rem;
  background: var(--brand-accent, #7DC6AD);
  border-radius: 999px;
}

.wp-block-list.hapster-uc-results > li::marker {
  content: "";
}

/* Current patterns use explicit value/label classes. The first-strong fallback keeps
   previously published use cases consistent until editors normalize their copy. */
.wp-block-list.hapster-uc-results > li > .hapster-uc-result__value,
.wp-block-list.hapster-uc-results
  > li:not(.hapster-uc-result)
  > strong:first-of-type {
  display: block;
  margin: 0 0 0.5rem;
  font-size: clamp(1.75rem, 2.2vw, 2.25rem);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--ink-900, #0B0F14);
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
  text-wrap: balance;
}

.wp-block-list.hapster-uc-results > li > strong:not(:first-of-type) {
  display: inline;
  margin: 0;
  color: var(--ink-900, #0B0F14);
  font-size: inherit;
  font-weight: 700;
  line-height: inherit;
  letter-spacing: normal;
}

.wp-block-list.hapster-uc-results > li > .hapster-uc-result__label {
  display: block;
  color: var(--ink-600, #2A3340);
  font-size: inherit;
  line-height: inherit;
}

.wp-block-list.hapster-uc-results
  > li.hapster-uc-result--text
  > .hapster-uc-result__label {
  color: var(--ink-900, #0B0F14);
  font-size: clamp(1.125rem, 1.5vw, 1.35rem);
  font-weight: 700;
  line-height: 1.35;
  text-wrap: balance;
}

/* ---------------------------------------------------------------- testimonials */

/* core/group ships .is-layout-flow, whose `> * + *` rule would fight the grid's own
   gap; zeroing it here is the same technique the sections above use. */
.hapster-uc-quotes.wp-block-group > * + * {
  margin-block-start: 0;
}

.hapster-uc-quotes.wp-block-group {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
  margin-block-start: clamp(1.25rem, 2.5vw, 2rem);
}

.hapster-uc-quotes .wp-block-quote {
  margin: 0;
  padding: clamp(1.1rem, 2vw, 1.6rem);
  background: var(--off-white, #FAFAF8);
  border: 0;
  border-inline-start: 3px solid var(--brand-accent, #7DC6AD);
  border-radius: var(--radius-soft, 14px);
  color: var(--ink-700, #1B2330);
  font-style: normal;
}

.hapster-uc-quotes .wp-block-quote p {
  margin: 0;
  line-height: 1.55;
  overflow-wrap: anywhere;
}

.hapster-uc-quotes .wp-block-quote p + p {
  margin-block-start: 0.75rem;
}

/* Name and role. Kept inside <cite> so the attribution stays bound to the quotation. */
.hapster-uc-quotes .wp-block-quote cite {
  display: block;
  margin-block-start: 0.9rem;
  font-style: normal;
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  /* Same reason as the breadcrumb link: --ink-400 on the quote's --off-white ground is
     4.46:1, below the AA floor. Uppercase at 0.75rem is the hardest text on the page to
     read, so it gets the darker ink rather than the lighter one. */
  color: var(--ink-600, #2A3340);
  overflow-wrap: anywhere;
}

.hapster-uc-quote-avatar.wp-block-image {
  width: 4rem;
  margin: 0;
}

.hapster-uc-quote-avatar img {
  display: block;
  width: 4rem;
  height: 4rem;
  object-fit: cover;
  border: 1px solid var(--hairline, #ECEEF1);
  border-radius: 999px;
}

@media (max-width: 480px) {
  .hapster-use-case-breadcrumb-shell {
    width: min(calc(100% - 1.25rem), var(--container-max, 80rem));
  }

  .hapster-uc-hero.wp-block-group {
    padding: 1.25rem;
  }
}
