/* ==========================================================================
   WBI Portfolio
   Case studies section: title, subtitle and filter buttons over a divider,
   then a grid that repeats a featured card (two rows tall) next to two
   stacked cards. Every visual value is a `--wbi-pf-*` custom property, so
   the Bricks element only has to override variables.

   Tokens live in :where() (zero specificity) so any rule Bricks generates on
   the root (#brxe-xxx { --token: ... }) always wins, regardless of the order
   in which the stylesheets load.

   Sizes are in `em` against --wbi-pf-base (16px) or in px, never in rem:
   Bricks sets the root to 10px and the component would silently shrink.

   Default values reproduce the design at 1440, 1024 and 390 px.
   ========================================================================== */

:where(.wbi-portfolio) {
  /* --- Section --------------------------------------------------------- */
  --wbi-pf-bg: #EDEFF3;
  --wbi-pf-content-w: 1440px;
  --wbi-pf-pad-top: 34px;
  --wbi-pf-pad-bottom: 32px;
  --wbi-pf-pad-x: 0px;
  /* Mobile: container narrower than 640px */
  --wbi-pf-pad-top-m: 20px;
  --wbi-pf-pad-bottom-m: 32px;
  --wbi-pf-pad-x-m: 0px;

  --wbi-pf-base: 16px;
  /* Theme Styles > WBI Elements > Font (see wbi-fonts.css) */
  --wbi-pf-font: var(--wbi-font), system-ui, -apple-system, "Segoe UI", sans-serif;
  --wbi-pf-focus: #3E94B9;
  --wbi-pf-ease: cubic-bezier(0.22, 1, 0.36, 1); /* quick start, soft landing */

  /* --- Header ----------------------------------------------------------
     Text colors are defaults only: each Typography control writes `color`
     on its selector and wins over them.
     Also read with a fallback, never declared here (see "Undeclared
     tokens" below): --wbi-pf-title-gap, --wbi-pf-sub-w, --wbi-pf-bar-pad,
     --wbi-pf-head-inset-*. */
  /* cqi = 1% of the container (.wbi-portfolio) width: 20px at 390,
     28px at 1024 and 48px at 1440, as in the three artboards. */
  --wbi-pf-title-size: clamp(1.25em, 4.8cqi - 1.325em, 3em);
  --wbi-pf-title-weight: 800;
  --wbi-pf-title-lh: 1.2;
  --wbi-pf-title-color: #0B0E11;
  --wbi-pf-title-gap-m: 38px;

  --wbi-pf-sub-size: 1em;
  --wbi-pf-sub-weight: 400;
  --wbi-pf-sub-lh: 1.4;
  --wbi-pf-sub-color: #10161C;

  --wbi-pf-bar-gap: 32px;       /* subtitle · buttons, side by side */
  --wbi-pf-bar-row-gap: 21px;   /* subtitle · buttons, when they wrap below */
  --wbi-pf-divider-color: #CDCFD4;
  --wbi-pf-divider-w: 1px;
  --wbi-pf-head-gap: clamp(24px, 17.7px + 1.62cqi, 41px); /* divider · cards */

  /* --- Filter buttons -------------------------------------------------- */
  --wbi-pf-filter-size: 0.9375em;
  --wbi-pf-filter-weight: 400;
  --wbi-pf-filter-lh: 1.4;
  --wbi-pf-filter-color: #0E1216;
  --wbi-pf-filter-hover-color: #3A3C3F;
  --wbi-pf-filter-active-weight: 700;
  --wbi-pf-filter-active-color: #3A3C3F;
  --wbi-pf-filter-gap: 46px;
  --wbi-pf-all-extra: 28px;     /* "Show all" stands a little apart */
  --wbi-pf-filter-h: 44px;      /* touch target */
  --wbi-pf-indicator-color: #999EA8;
  --wbi-pf-indicator-h: 2px;
  --wbi-pf-indicator-w: 80px;   /* minimum: longer labels get a longer line */

  /* --- Grid ------------------------------------------------------------ */
  --wbi-pf-row-h: 340px;
  --wbi-pf-gap-x: 22px;
  --wbi-pf-gap-y: 25px;
  --wbi-pf-row-h-m: 335px;
  --wbi-pf-gap-m: 26px;

  /* --- Card ------------------------------------------------------------ */
  --wbi-pf-card-radius: 6px;
  --wbi-pf-card-bg: #D5D9E0;
  --wbi-pf-img-pos: 50% 50%;
  --wbi-pf-zoom: 1.04;
  --wbi-pf-img-overlay: rgb(0 0 0 / 0.2);

  /* --- Card text box ---------------------------------------------------
     Also read with a fallback: --wbi-pf-box-pad-*, --wbi-pf-box-pad-m-*,
     --wbi-pf-box-y-lg. */
  --wbi-pf-box-bg: #FFFFFF;
  --wbi-pf-box-radius: 9px;
  --wbi-pf-box-w: 255px;
  --wbi-pf-box-x: 34px;         /* stacked cards */
  --wbi-pf-box-y: 32px;
  --wbi-pf-box-x-lg: 40px;      /* featured, tall and wide cards */
  --wbi-pf-box-x-m: 28px;
  --wbi-pf-box-y-m: 32px;
  --wbi-pf-box-min-w-m: 153px;

  /* 15px at 390, 18px at 1024, 20px at 1440 */
  --wbi-pf-card-title-size: clamp(0.9375em, 0.82em + 0.476cqi, 1.25em);
  --wbi-pf-card-title-weight: 700;
  --wbi-pf-card-title-lh: 1.3;
  --wbi-pf-card-title-color: #080A0B;
  --wbi-pf-excerpt-size: 0.9375em;
  --wbi-pf-excerpt-weight: 400;
  --wbi-pf-excerpt-lh: 1.37;
  --wbi-pf-excerpt-color: #363636;
  --wbi-pf-excerpt-gap: 6px;
  --wbi-pf-excerpt-lines: 3;

  --wbi-pf-arrow-size: 14px;
  --wbi-pf-arrow-color: #0F1110;
  --wbi-pf-arrow-gap: 12px;
  --wbi-pf-arrow-size-m: 13px;
  --wbi-pf-arrow-gap-m: 10px;

  /* --- Filter transition ----------------------------------------------- */
  --wbi-pf-enter-dur: 480ms;
  --wbi-pf-enter-stagger: 60ms;
  --wbi-pf-enter-shift: 14px;
}

/* Undeclared tokens
   A few tokens are never declared above and are read as var(--x, default)
   instead:
   - `dimensions` controls (header inset, box padding) emit one token per
     side and only for the sides the editor fills in; declaring them would
     pin every side and the fallback would never apply.
   - --wbi-pf-title-gap, --wbi-pf-sub-w and --wbi-pf-bar-pad have their own
     defaults below a 1200px container (the tablet artboard is roomier);
     left undeclared, a value set in the builder applies at every width.
   - --wbi-pf-box-y-lg falls back to --wbi-pf-box-y, so the text box of a
     featured card lines up at the bottom with the one of the stacked card
     beside it, also when the builder changes only the stacked value. */

.wbi-portfolio {
  position: relative;
  /* Required, not cosmetic: `container-type: inline-size` stops the content
     from contributing intrinsic width, and Bricks containers are flex with
     `align-items: flex-start`. Without this it collapses to 0px in the builder. */
  width: 100%;
  container-type: inline-size;
  container-name: wbipf;
  font-family: var(--wbi-pf-font);
  font-size: var(--wbi-pf-base);
  color: var(--wbi-pf-sub-color);
  background-color: var(--wbi-pf-bg);
}

.wbi-portfolio *,
.wbi-portfolio *::before,
.wbi-portfolio *::after { box-sizing: border-box; }

.wbi-portfolio__inner {
  width: 100%;
  max-width: var(--wbi-pf-content-w);
  margin-inline: auto;
  padding: var(--wbi-pf-pad-top) var(--wbi-pf-pad-x) var(--wbi-pf-pad-bottom);
}

/* ==========================================================================
   Header
   ========================================================================== */

.wbi-portfolio__head {
  /* Resolved once here from the undeclared tokens and switched per container
     width below; the rules of the header only read these. */
  --_inset-l: var(--wbi-pf-head-inset-left, 52px);
  --_inset-r: var(--wbi-pf-head-inset-right, 96px);
  --_title-gap: var(--wbi-pf-title-gap, 37px);
  --_bar-pad: var(--wbi-pf-bar-pad, 13px);
  margin-bottom: var(--wbi-pf-head-gap);
}

.wbi-portfolio__title {
  margin: 0 0 var(--_title-gap);
  padding-inline: var(--_inset-l) var(--_inset-r);
  font-family: inherit;
  font-size: var(--wbi-pf-title-size);
  font-weight: var(--wbi-pf-title-weight);
  line-height: var(--wbi-pf-title-lh);
  color: var(--wbi-pf-title-color);
  text-wrap: balance;
}

.wbi-portfolio__title:last-child { margin-bottom: 0; }

/* Subtitle on the left, buttons on the right, centered on each other (a
   two-line subtitle keeps the buttons at its middle); when they no longer
   fit, the buttons wrap below and start at the left edge (space-between
   with a single item per line). The divider is drawn by the bar across its
   full width, insets included. */
.wbi-portfolio__bar {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--wbi-pf-bar-row-gap) var(--wbi-pf-bar-gap);
  padding-inline: var(--_inset-l) var(--_inset-r);
}

.wbi-portfolio__bar::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: var(--wbi-pf-divider-w);
  background-color: var(--wbi-pf-divider-color);
  pointer-events: none;
}

.wbi-portfolio__subtitle {
  flex: 1 1 auto;
  max-width: var(--wbi-pf-sub-w, 26em);
  margin: 0;
  padding-bottom: var(--_bar-pad);
  font-family: inherit;
  font-size: var(--wbi-pf-sub-size);
  font-weight: var(--wbi-pf-sub-weight);
  line-height: var(--wbi-pf-sub-lh);
  color: var(--wbi-pf-sub-color);
  text-wrap: pretty;
}

/* --- Filter buttons ----------------------------------------------------
   The row stretches to the height of the bar and each button with it, so
   the selected indicator at the bottom of the button always lands on the
   divider, while the label stays centered in the space above it. */

.wbi-portfolio__filters {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  flex: 0 1 auto;
  align-self: stretch;
  min-width: 0;
  max-width: 100%;
  gap: 0 var(--wbi-pf-filter-gap);
}

.wbi-portfolio__filter {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  flex: 0 0 auto;
  min-height: var(--wbi-pf-filter-h);
  margin: 0;
  padding: 0 0 var(--_bar-pad);
  border: 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
  font-family: inherit;
  font-size: var(--wbi-pf-filter-size);
  font-weight: var(--wbi-pf-filter-weight);
  line-height: var(--wbi-pf-filter-lh);
  letter-spacing: inherit;
  text-align: left;
  text-transform: none;
  color: var(--wbi-pf-filter-color);
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 200ms ease;
}

/* Invisible bold copy of the label: the button is always as wide as its
   selected state, so selecting it never shifts the buttons after it. */
.wbi-portfolio__filter::before {
  content: attr(data-label);
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: var(--wbi-pf-filter-active-weight);
  pointer-events: none;
}

.wbi-portfolio__filter--all { margin-inline-end: var(--wbi-pf-all-extra); }

.wbi-portfolio__filter:hover { color: var(--wbi-pf-filter-hover-color); }

.wbi-portfolio__filter[aria-pressed="true"] {
  font-weight: var(--wbi-pf-filter-active-weight);
  color: var(--wbi-pf-filter-active-color);
  cursor: default;
}

/* Selected indicator: sits on the divider, starts under the text and is at
   least --wbi-pf-indicator-w long (80px in the design). */
.wbi-portfolio__filter::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 1;
  width: 100%;
  min-width: var(--wbi-pf-indicator-w);
  height: var(--wbi-pf-indicator-h);
  background-color: var(--wbi-pf-indicator-color);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 320ms var(--wbi-pf-ease);
}

.wbi-portfolio__filter[aria-pressed="true"]::after { transform: scaleX(1); }

/* Inside the button box: the mobile scroller would clip an outer ring. */
.wbi-portfolio__filter:focus-visible {
  outline: 2px solid var(--wbi-pf-focus);
  outline-offset: -2px;
  border-radius: 4px;
}

/* ==========================================================================
   Grid
   Groups of three: a featured card two rows tall next to two stacked
   ones. An incomplete last group still fills the row: two cards become two
   tall ones and a single card spans both columns (the render decides each
   card's data-size). `dense` lets a flipped group (data-side="end") put its
   stacked cards back in the first column.
   ========================================================================== */

.wbi-portfolio__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: var(--wbi-pf-row-h);
  grid-auto-flow: row dense;
  gap: var(--wbi-pf-gap-y) var(--wbi-pf-gap-x);
  transition: opacity 200ms ease;
}

.wbi-portfolio__card[data-size="feature"],
.wbi-portfolio__card[data-size="tall"] { grid-row: span 2; }

.wbi-portfolio__card[data-size="wide"] {
  grid-column: 1 / -1;
  grid-row: span 2;
}

.wbi-portfolio__card[data-side="end"][data-size="feature"] { grid-column: 2; }
.wbi-portfolio__card[data-side="end"][data-size="small"] { grid-column: 1; }

/* While the filter waits for the server. The delay skips the dimming
   altogether when the answer is quick (or cached). */
.wbi-portfolio__grid[aria-busy="true"] {
  opacity: 0.45;
  pointer-events: none;
  transition-delay: 150ms;
}

.wbi-portfolio__empty {
  grid-column: 1 / -1;
  align-self: center;
  margin: 0;
  padding: 2em 1em;
  font-size: 1em;
  text-align: center;
  color: var(--wbi-pf-sub-color);
}

/* ==========================================================================
   Card
   ========================================================================== */

.wbi-portfolio__card {
  position: relative;
  isolation: isolate; /* keeps the zoomed image inside the rounded corners in Safari */
  min-width: 0;
  overflow: hidden;
  border-radius: var(--wbi-pf-card-radius);
  background-color: var(--wbi-pf-card-bg);
}

.wbi-portfolio__media {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.wbi-portfolio__img {
  display: block;
  width: 100%;
  max-width: none;
  height: 100%;
  object-fit: cover;
  object-position: var(--wbi-pf-img-pos);
  transition: transform 700ms var(--wbi-pf-ease);
}

/* Image overlay: over the image (later in the tree, so also above it while
   it zooms) and under the text box. The color is a token; the gradient
   control writes background-image here. The !important values undo what
   that control adds when its "Apply to" is not Background: Overlay sets
   `position: relative` and paints the gradient in a ::before (which then
   covers this node), Text clips the background to the text. */
.wbi-portfolio__shade {
  position: absolute !important;
  inset: 0;
  background-color: var(--wbi-pf-img-overlay);
  -webkit-background-clip: border-box !important;
  background-clip: border-box !important;
  pointer-events: none;
}

.wbi-portfolio__overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  padding: 0 var(--wbi-pf-box-x) var(--wbi-pf-box-y);
  pointer-events: none;
}

.wbi-portfolio__card[data-size="feature"] .wbi-portfolio__overlay,
.wbi-portfolio__card[data-size="tall"] .wbi-portfolio__overlay,
.wbi-portfolio__card[data-size="wide"] .wbi-portfolio__overlay {
  padding: 0 var(--wbi-pf-box-x-lg) var(--wbi-pf-box-y-lg, var(--wbi-pf-box-y));
}

.wbi-portfolio__box {
  width: var(--wbi-pf-box-w);
  max-width: 100%;
  padding:
    var(--wbi-pf-box-pad-top, 14px)
    var(--wbi-pf-box-pad-right, 13px)
    var(--wbi-pf-box-pad-bottom, 12px)
    var(--wbi-pf-box-pad-left, 13px);
  border-radius: var(--wbi-pf-box-radius);
  background-color: var(--wbi-pf-box-bg);
  pointer-events: auto;
}

/* The arrow repeats the title link; its hit area is larger than its ink. */
.wbi-portfolio__arrow {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--wbi-pf-arrow-size);
  height: var(--wbi-pf-arrow-size);
  margin: 0 0 var(--wbi-pf-arrow-gap) auto;
  font-size: var(--wbi-pf-arrow-size);
  line-height: 1;
  color: var(--wbi-pf-arrow-color);
}

.wbi-portfolio__arrow::before {
  content: "";
  position: absolute;
  inset: -12px;
}

.wbi-portfolio__arrow > * {
  display: block;
  width: 100%;
  height: 100%;
  transition: translate 320ms var(--wbi-pf-ease);
}

.wbi-portfolio__arrow > i { height: auto; text-align: center; }

.wbi-portfolio__card-title {
  margin: 0;
  font-family: inherit;
  font-size: var(--wbi-pf-card-title-size);
  font-weight: var(--wbi-pf-card-title-weight);
  line-height: var(--wbi-pf-card-title-lh);
  color: var(--wbi-pf-card-title-color);
  overflow-wrap: anywhere;
}

.wbi-portfolio__link {
  color: inherit;
  text-decoration: none;
}

.wbi-portfolio__link:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

.wbi-portfolio__link:focus-visible {
  outline: 2px solid var(--wbi-pf-focus);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Whole card clickable: the title link stretches over the card (the
   overlay is its containing block); the arrow stays above it. */
.wbi-portfolio--card-link .wbi-portfolio__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

.wbi-portfolio__excerpt {
  display: -webkit-box;
  margin: var(--wbi-pf-excerpt-gap) 0 0;
  overflow: hidden;
  font-family: inherit;
  font-size: var(--wbi-pf-excerpt-size);
  font-weight: var(--wbi-pf-excerpt-weight);
  line-height: var(--wbi-pf-excerpt-lh);
  color: var(--wbi-pf-excerpt-color);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--wbi-pf-excerpt-lines);
  line-clamp: var(--wbi-pf-excerpt-lines);
}

/* Hover, and the same for keyboard users on the title link. */
@media (hover: hover) {
  .wbi-portfolio__card:hover .wbi-portfolio__img { transform: scale(var(--wbi-pf-zoom)); }
  .wbi-portfolio__card:hover .wbi-portfolio__arrow > * { translate: 2px -2px; }
}

.wbi-portfolio__card:focus-within .wbi-portfolio__img { transform: scale(var(--wbi-pf-zoom)); }

/* ==========================================================================
   Filter transition: cards rise into place after the first filter change
   (the class is set by the script, so the first paint never animates).
   ========================================================================== */

.wbi-portfolio--filtered .wbi-portfolio__card {
  animation: wbi-pf-enter var(--wbi-pf-enter-dur) var(--wbi-pf-ease) both;
  animation-delay: calc(var(--wbi-pf-i, 0) * var(--wbi-pf-enter-stagger));
}

@keyframes wbi-pf-enter {
  from {
    opacity: 0;
    translate: 0 var(--wbi-pf-enter-shift);
  }
}

.wbi-portfolio--static .wbi-portfolio__card { animation: none; }

/* Live region: read by screen readers, never seen. */
.wbi-portfolio__status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .wbi-portfolio__card { animation: none !important; }

  .wbi-portfolio__img,
  .wbi-portfolio__arrow > *,
  .wbi-portfolio__filter::after,
  .wbi-portfolio__grid { transition: none; }

  .wbi-portfolio__card:hover .wbi-portfolio__img,
  .wbi-portfolio__card:focus-within .wbi-portfolio__img { transform: none; }
}

/* ==========================================================================
   Tablet artboard, below a 1200px container: the subtitle wraps after
   "idea" and the header is roomier, unless the builder sets these values.
   ========================================================================== */

@container wbipf (max-width: 1199px) {
  .wbi-portfolio__head {
    --_title-gap: var(--wbi-pf-title-gap, 43px);
    --_bar-pad: var(--wbi-pf-bar-pad, 27px);
  }

  .wbi-portfolio__subtitle { max-width: var(--wbi-pf-sub-w, 17em); }
}

/* ==========================================================================
   Mobile: the component reacts to ITS container, not to the viewport.
   These rules target descendants, never .wbi-portfolio: an element is not
   reached by the container query it defines itself.
   ========================================================================== */

@container wbipf (max-width: 639px) {
  .wbi-portfolio__inner {
    padding: var(--wbi-pf-pad-top-m) var(--wbi-pf-pad-x-m) var(--wbi-pf-pad-bottom-m);
  }

  .wbi-portfolio__head {
    --_inset-l: var(--wbi-pf-head-inset-m-left, 22px);
    --_inset-r: var(--wbi-pf-head-inset-m-right, 22px);
    --_title-gap: var(--wbi-pf-title-gap-m);
    --_bar-pad: var(--wbi-pf-bar-pad, 13px);
  }

  /* The subtitle and the buttons get the inset themselves, so the button
     row can scroll from edge to edge of the section. */
  .wbi-portfolio__bar { padding-inline: 0; }

  .wbi-portfolio__subtitle {
    margin-inline: var(--_inset-l) var(--_inset-r);
    padding-bottom: 0;
  }

  .wbi-portfolio__filters {
    flex: 1 0 100%;
    flex-wrap: nowrap;
    padding-inline: var(--_inset-l) var(--_inset-r);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-inline: var(--_inset-l) var(--_inset-r);
    scrollbar-width: none;
  }

  .wbi-portfolio__filters::-webkit-scrollbar { display: none; }

  .wbi-portfolio__filter { scroll-snap-align: start; }

  /* One card per row, all the same height. */
  .wbi-portfolio__grid {
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: var(--wbi-pf-row-h-m);
    gap: var(--wbi-pf-gap-m);
  }

  .wbi-portfolio__grid > .wbi-portfolio__card[data-size] {
    grid-column: auto;
    grid-row: auto;
  }

  .wbi-portfolio__card[data-size] .wbi-portfolio__overlay {
    padding: 0 var(--wbi-pf-box-x-m) var(--wbi-pf-box-y-m);
  }

  /* The box hugs the title: only the title and the arrow, as in the design. */
  .wbi-portfolio__box {
    width: auto;
    min-width: var(--wbi-pf-box-min-w-m);
    padding:
      var(--wbi-pf-box-pad-m-top, 10px)
      var(--wbi-pf-box-pad-m-right, 12px)
      var(--wbi-pf-box-pad-m-bottom, 7px)
      var(--wbi-pf-box-pad-m-left, 12px);
  }

  .wbi-portfolio__arrow {
    width: var(--wbi-pf-arrow-size-m);
    height: var(--wbi-pf-arrow-size-m);
    margin-bottom: var(--wbi-pf-arrow-gap-m);
    font-size: var(--wbi-pf-arrow-size-m);
  }

  .wbi-portfolio__excerpt { display: none; }
  .wbi-portfolio--excerpt-m .wbi-portfolio__excerpt { display: -webkit-box; }
}
