/* web/themes/techprosolutions/css/components/review-avatar-cloud.css */
/*
 * Review Avatar Cloud ("Wall of Love") — Attio-style ragged cluster.
 *
 * The organic silhouette is carved SERVER-SIDE: the preprocess emits flex rows
 * of avatar + empty spacer cells (a shape mask), so no CSS mask and no JS are
 * needed to build it. REAL, editor-entered reviews fill the dense centre and are
 * interactive (grayscale -> full colour on hover/focus/tap, driving one shared
 * ghost tooltip); the ragged rim is decorative, aria-hidden local identicons
 * (no external avatar service), depth-faded toward the edge.
 * Per the Attio spec: NO hover scaling, NO avatar borders — opacity + grayscale.
 *
 * Mobile-first: the default layout REFLOWS all avatars into a centred wrapping
 * cluster (spacers hidden) so it never h-scrolls; the fixed ragged shape only
 * switches on at >=992px, where the 50-column x 22px / 1px-gap silhouette is
 * laid out and a radial -webkit-mask-image dissolves the rim into the page.
 *
 * Brand tokens (locked): green #3CB944, accent #1D9E75, navy #1C3557,
 * heading #0A0A0A, body #45464F, light wash #E8F5E9, muted-on-dark #A9B2B8.
 * Font: Manrope (self-hosted; no Google Fonts / DPDP).
 *
 * Contrast (on #0A0A0A tooltip): white name 20:1, handle #A4ADBA ~8.9:1,
 * body rgba(255,255,255,0.82) ~13:1 — all AA+. Heading #0A0A0A on #FFFFFF 21:1.
 */

@font-face {
  font-family: 'Manrope';
  src: url('../../fonts/Manrope-VariableFont_wght.woff2?v=2') format('woff2-variations');
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

.review-cloud-section {
  /* Brand tokens exposed as variables. */
  --rac-green: #3CB944;
  --rac-navy: #1C3557;
  --rac-heading: #0A0A0A;
  --rac-body: #45464F;
  --rac-wash: #E8F5E9;
  --rac-cell: 44px;        /* mobile/touch hit target; desktop shrinks to 22px */
  --rac-gap: 8px;          /* 4px grid (was 6px); desktop query sets 4px */
  --rac-radius: 4px;       /* 4px grid (Attio spec said 5px — snapped) */

  position: relative;
  box-sizing: border-box;
  z-index: 50;
  width: 100%;
  /* UNIFIED section rhythm token (replaces the rogue 157px). Still PADDING,
     not margin: (1) padding can't margin-collapse with the previous section;
     (2) the gap stays INSIDE the section so the dot-grid texture (::before)
     can live in the band above the cloud — its height tracks this padding. */
  padding: var(--et-section-pad-y, 5rem) 1rem;
  background: #FFFFFF;
  font-family: 'Manrope', -apple-system, 'Segoe UI', Roboto, sans-serif;
  overflow: hidden; /* clip the decorative dot texture; the ghost tooltip is
                       position:fixed, re-parented to <body> by JS, and so
                       escapes both this clip and this stacking context */
}

.review-cloud-section *,
.review-cloud-section *::before,
.review-cloud-section *::after {
  box-sizing: border-box;
}

/* Subtle dot-grid texture filling the empty space ABOVE the cloud — i.e. the
   top padding band (height tracks the unified section padding token). Navy-10%
   dots on white at 24px spacing (brand-token colour, NOT a raw grey), softly
   fading out as they approach the avatars so the texture never clashes with
   the grid. Decorative only (pointer-events:none); confined to the top band by
   its height + the downward linear mask. */
.review-cloud-section::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--et-section-pad-y, 5rem);
  background-image: radial-gradient(rgba(28, 53, 87, 0.10) 1px, transparent 1.5px);
  background-size: 24px 24px;
  background-position: center top;
  -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent);
  mask-image: linear-gradient(to bottom, #000 55%, transparent);
  pointer-events: none;
}

.review-cloud-container {
  position: relative;
  max-width: 1240px;
  margin: 0 auto;
}

/* ---- Mobile-first: rows collapse, avatars reflow into one centred cluster ---- */
.review-cloud-grid {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  gap: var(--rac-gap);
  width: 100%;
}

/* display:contents lets every row's avatars participate in the single wrapping
   flow above (the row box disappears); the desktop media query re-enables it. */
.review-cloud-row {
  display: contents;
}

/* Spacers only shape the desktop silhouette — hidden in the reflow layout. */
.review-cloud-spacer {
  display: none;
}

.avatar-cell {
  flex: 0 0 var(--rac-cell);
  height: var(--rac-cell);
  position: relative;
  opacity: 1;
  transition: opacity 0.3s ease-out, transform 0.3s ease-out;
}

/* Staggered entrance: only when JS has armed the reveal and not yet revealed.
   Without JS the cells stay visible (opacity 1 default above). */
.review-cloud-grid.has-js-reveal:not(.is-revealed) .avatar-cell {
  opacity: 0;
  transform: translateY(8px);
}

/* ---- REAL interactive avatar (a single button, no nested interactives) ---- */
.avatar-interactive-group {
  display: block;
  width: var(--rac-cell);
  height: var(--rac-cell);
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  position: relative;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.avatar-interactive-group:focus {
  outline: none;
}

.avatar-interactive-group:focus-visible {
  outline: 2px solid var(--rac-green);
  outline-offset: 2px;
  border-radius: var(--rac-radius);
}

.cloud-avatar-img {
  display: block;
  width: var(--rac-cell);
  height: var(--rac-cell);
  border-radius: var(--rac-radius);
  object-fit: cover;
  border: 0;
  /* Attio: grayscale + dimmed at rest; opacity + grayscale only (no scale).
     Real reviews sit a touch brighter than decorative fillers so they read as
     the discoverable, interactive ones. */
  filter: grayscale(100%);
  opacity: 0.8;
  transition: filter 0.2s ease, opacity 0.2s ease;
}

.cloud-avatar-img--placeholder {
  background: linear-gradient(135deg, #E2E6EA, #C9CFD6);
  filter: none;
  opacity: 0.8;
}

/* Light up on hover (mouse), focus-within (keyboard) and tap (touch).
   No transform, no border change — opacity + grayscale only. */
.avatar-interactive-group:hover .cloud-avatar-img,
.avatar-interactive-group:focus-within .cloud-avatar-img,
.avatar-interactive-group.is-tapped .cloud-avatar-img {
  filter: grayscale(0);
  opacity: 1;
}

.avatar-interactive-group:hover,
.avatar-interactive-group:focus-within,
.avatar-interactive-group.is-tapped {
  z-index: 5;
}

/* ---- Decorative filler identicons (aria-hidden, never interactive) ---- */
.filler-cell {
  display: block;
  pointer-events: none;
}

.filler-identicon {
  display: block;
  width: var(--rac-cell);
  height: var(--rac-cell);
  border-radius: var(--rac-radius);
  background: #EEF1F4;
  filter: grayscale(100%);
}

/* Depth-faded rim: inner fillers are firmer, outer ones dissolve toward the
   ragged edge (replaces the old radial mask). */
.filler-cell--d0 .filler-identicon { opacity: 0.58; }
.filler-cell--d1 .filler-identicon { opacity: 0.46; }
.filler-cell--d2 .filler-identicon { opacity: 0.34; }
.filler-cell--d3 .filler-identicon { opacity: 0.24; }

.filler-identicon--c0 rect { fill: #1C3557; }
.filler-identicon--c1 rect { fill: #3CB944; }
.filler-identicon--c2 rect { fill: #1D9E75; }
.filler-identicon--c3 rect { fill: #45464F; }
.filler-identicon--c4 rect { fill: #8A94A6; }

/* ---- Desktop: switch on the fixed ragged silhouette (spacers + rows) ---- */
@media (min-width: 992px) {
  .review-cloud-section {
    --rac-cell: 22px;
    --rac-gap: 4px;        /* distinct individual tiles (was 1px) */
  }
  .review-cloud-grid {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: var(--rac-gap);
    /* The 50-col blob is wider than the viewport on smaller desktops; let it
       bleed and rely on the section's overflow:hidden to clip (never scroll),
       with this radial mask dissolving the rim softly into the white page. */
    max-width: none;
    -webkit-mask-image: radial-gradient(ellipse 78% 64% at 50% 50%, #000 50%, transparent 100%);
    mask-image: radial-gradient(ellipse 78% 64% at 50% 50%, #000 50%, transparent 100%);
  }
  .review-cloud-row {
    display: flex;
    justify-content: center;
    gap: var(--rac-gap);
  }
  .review-cloud-spacer {
    display: block;
    flex: 0 0 var(--rac-cell);
    height: var(--rac-cell);
  }
}

/* ---- Mobile density: thin the decorative rim so the reflow stays compact ---- */
@media (max-width: 991px) {
  .filler-cell--d2,
  .filler-cell--d3 {
    display: none;
  }
}

@media (max-width: 600px) {
  .filler-cell--d1 {
    display: none;
  }
}

/* Phones (2026-07-09 polish loop): even with d1-d3 culled the wall ran ~17
   rows at 390px — a monolith of gray faces. Two-part fix:
   1. Drop the last filler tier — only REAL review avatars remain.
   2. There are ~168 real avatars, so also clip the grid to ~5 rows with a
      bottom fade mask: the wall reads as a cloud that continues, instead of
      a wall the user must scroll through. (nth-child capping is unreliable
      here — the DOM interleaves hidden filler cells.) */
@media (max-width: 480px) {
  .filler-cell--d0 {
    display: none;
  }

  .review-cloud-grid {
    max-height: 384px;          /* ~5 rows, 8pt grid */
    overflow: hidden;
    -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
  }
}

/* ---- Single shared "ghost" tooltip (position:fixed, JS-driven) ----
   The JS re-parents this node to <body>: as a child of .review-cloud-section
   it is trapped in the section's stacking context (z-index 50), and the
   monitor sections lift their content to ROOT-level z-index 9995 — so the
   tooltip painted underneath them no matter how high its own z-index was.
   At <body> level its z-index resolves against the root, so 10000 out-paints
   the monitor lift (9995) and the blackout sheet (9990). Because it no longer
   sits inside the section, every token/font/box-sizing it needs is declared
   HERE — do not move these back onto the section. */
.rac-ghost-tooltip {
  --rac-tip-bg: #0A0A0A;
  --rac-tip-name: #FFFFFF;
  --rac-tip-handle: #A4ADBA;
  --rac-tip-text: rgba(255, 255, 255, 0.82);
  --rac-tip-hairline: rgba(255, 255, 255, 0.15);

  position: fixed;
  top: 0;
  left: 0;
  z-index: 10000; /* above the monitor sections' root-level lift (9995) */
  width: min(280px, calc(100vw - 24px));
  padding: 1rem; /* 16px — 4px grid (was 0.875rem 1rem) */
  font-family: 'Manrope', -apple-system, 'Segoe UI', Roboto, sans-serif;
  background: var(--rac-tip-bg);
  border: 1px solid var(--rac-tip-hairline);
  border-radius: 12px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.28);
  text-align: left;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(8px); /* 4px grid (was 6px) */
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s ease;
  will-change: transform, opacity;
}

.rac-ghost-tooltip,
.rac-ghost-tooltip *,
.rac-ghost-tooltip *::before,
.rac-ghost-tooltip *::after {
  box-sizing: border-box;
}

.rac-ghost-tooltip.is-visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* Little arrow; --rac-arrow-x is set by JS relative to the tooltip's left edge. */
.rac-ghost-tooltip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: var(--rac-arrow-x, 50%);
  transform: translateX(-50%);
  border: 8px solid transparent; /* arrow size — 4px grid (was 6px) */
  border-top-color: var(--rac-tip-bg);
}

.rac-ghost-tooltip.is-flipped::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: var(--rac-tip-bg);
}

/* Header row: cloned full-colour avatar + identity, then the quote below. */
.rac-tip-header {
  display: flex;
  align-items: center;
  gap: 0.5rem; /* 8px — 4px grid (was 0.625rem) */
  margin-bottom: 0.5rem;
}

/* The avatar img is cloned in by JS from the hovered cell (already a server-
   generated image-style URL). Shown full-colour + round, unlike the grid. */
.rac-tip-avatar {
  flex: 0 0 32px; /* 4px grid (was 34px) */
  width: 32px;
  height: 32px;
  border-radius: 50%;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.08);
}

.rac-tip-avatar:empty {
  display: none;
}

.rac-tip-avatar img,
.rac-tip-avatar span {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 0;
  object-fit: cover;
  /* Override the grid's grayscale/dim on the cloned node. */
  filter: none;
  opacity: 1;
}

.rac-tip-identity {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.25rem 0.5rem;
  min-width: 0;
}

.rac-tip-name {
  font-size: 0.875rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--rac-tip-name);
}

.rac-tip-handle {
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--rac-tip-handle);
}

.rac-tip-handle:empty {
  display: none;
}

.rac-tip-text {
  display: block;
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.45;
  color: var(--rac-tip-text);
}

/* ---- Heading (sits BELOW the cloud, so the gap is a margin-top) ---- */
.review-cloud-heading {
  margin-top: 0.25rem; /* 4px — nearest on-grid value to the hand-tuned 2px */
  text-align: center;
}

/* Unified H2 token — identical to every other section title. */
.review-cloud-title {
  margin: 0 auto;
  max-width: 800px;
  font-family: 'Manrope', sans-serif; /* beats the base theme's h1-h6 Roboto rule */
  font-size: var(--et-h2-size);
  font-weight: var(--et-h2-weight, 800);
  line-height: var(--et-h2-lh, 1.15);
  letter-spacing: var(--et-h2-track, -0.02em);
  color: var(--et-heading-color, #0a0a0a);
}

/* ---- Visually-hidden accessible description (mirrors the SPF utility) ---- */
.rac-visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- Reduced motion: no stagger, no entrance, instant tooltip ---- */
@media (prefers-reduced-motion: reduce) {
  .avatar-cell,
  .review-cloud-grid.has-js-reveal:not(.is-revealed) .avatar-cell {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .cloud-avatar-img,
  .rac-ghost-tooltip {
    transition: none !important;
  }
  .rac-ghost-tooltip {
    transform: none;
  }
}
