/* ============================================================
   AMALAB — saas-field.css
   "Le constat" band: the SaaS-tool landscape drifts past while
   one statement holds still. Icons are shown at native shape —
   no card, no border, just a layered drop-shadow. Motion is
   built up from three layers, all moving the same direction at
   any given moment (a single uniform current — like a school
   of fish passing left to right, never drifting in opposite
   directions):
     1. Scroll: per-column `--py` driven by data-speed in
        saas-field.js (edge columns faster, all positive).
     2. Idle: section-wide `--idle-y-shared` sine written once
        per frame; each column multiplies by its own
        `--idle-amp-mul` so edges drift more than the inner
        pair while still sharing the wave (same phase, same
        direction, same period).
     3. Per-tile floating: each `.saas-tile` bobs on its own
        `@keyframes saas-drift` with a random `--drift-dur`
        and `--drift-delay` inline, so individual icons appear
        to float independently of the shared column current.
   The clip is `.saas-field` itself — every column extends
   10% past the section edges so tiles emerge from / sink
   into a window onto a larger field. With 4 tiles per
   column distributed via `justify-content: space-between`
   and `overflow: clip` on the section, the heavy-scroll
   ceiling keeps ≥ 2 tiles per column visible at all times
   — the band never reads as empty.
   Columns share identical top/bottom offsets so tiles line up
   on the same horizontal rows at rest, and each tile keeps a
   fixed x position (no horizontal jitter) so columns read as
   clean vertical lines. Tiles are decorative (aria-hidden);
   the h2 is the content.
   ============================================================ */

.saas-field {
  --saas-tile: clamp(56px, 7vw, 100px);
  /* Halo half-width — the text-safe boundary each column must stay
     outside of. Single source of truth: the ::before halo below
     reads its own width from this same variable. */
  --saas-halo-half: min(460px, 50vw);
  /* Usable band, per side, between the section edge and the halo
     boundary. Two tiles + three equal gaps (margin · inter-column ·
     to-halo) divide this band evenly. */
  --saas-boundary: calc(50vw - var(--saas-halo-half));
  --saas-gap: max(0px, calc((var(--saas-boundary) - 2 * var(--saas-tile)) / 3));
  /* Pulls both rows 45% of --saas-gap closer to the text than the
     even split alone would place them. */
  --saas-shift: calc(var(--saas-gap) * 0.45);
  position: relative;
  overflow: clip;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(372px, 52vh, 505px);
  background: var(--bg);
  /* hairlines frame the crop — without them tiles would appear
     to slice off against an invisible boundary */
  border-block: 1px solid var(--border);
}

/* ---------- Statement ---------- */
.saas-field-copy {
  position: relative;
  z-index: 1;
  width: 100%;
  text-align: center;
}
.saas-field-copy::before {
  /* paper halo — keeps the statement readable whatever passes behind it */
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(var(--saas-halo-half) * 2);
  aspect-ratio: 2.3 / 1;
  transform: translate(-50%, -50%);
  background: radial-gradient(
    closest-side,
    var(--paper) 46%,
    rgba(251, 250, 248, 0.82) 68%,
    rgba(251, 250, 248, 0) 100%
  );
  pointer-events: none;
}
.saas-field-copy h2 {
  position: relative;
  margin-inline: auto;
  max-width: 21ch;
  font-size: clamp(2.1rem, 1.43rem + 2.64vw, 3.4rem);
  line-height: 1.14;
}

/* ---------- Columns of drifting tiles ---------- */
.saas-field-columns {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.saas-col {
  position: absolute;
  /* identical top/bottom on every column: tiles distribute at the
     same row heights, so columns line up at rest */
  top: -10%;
  bottom: -10%;
  width: var(--saas-tile);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  /* total Y = scroll (per-column, --py) + shared idle wave
     (--idle-y-shared from the section, scaled by this column's
     --idle-amp-mul so edges drift more than inner without ever
     breaking the same-direction read) + per-tile float (handled
     by .saas-tile's own keyframes below).
     Idle defaults to 0px so the column renders correctly before
     saas-field.js hydrates; the per-column multiplier defaults
     to 1 if a column forgets to set one. */
  transform: translate3d(
    0,
    calc(
      var(--py, 0px) +
      var(--idle-y-shared, 0px) * var(--idle-amp-mul, 1)
    ),
    0
  );
  will-change: transform;
}
/* Per-column idle multiplier — keeps the edge-vs-inner hierarchy
   while reading as one shared wave (every column moves the same
   direction at the same instant). */
.saas-col--1 { --idle-amp-mul: 1.0; }
.saas-col--2 { --idle-amp-mul: 0.55; }
.saas-col--3 { --idle-amp-mul: 0.55; }
.saas-col--4 { --idle-amp-mul: 1.0; }
/* Even three-way spread (margin = inter-column gap = gap-to-halo,
   all --saas-gap) as the baseline, then both rows are shifted
   together toward the text by --saas-shift (15% of --saas-gap):
   the margin grows by that amount, the gap-to-text shrinks by
   that amount, and the two rows keep the same distance from each
   other throughout. */
.saas-col--1 { left: calc(var(--saas-gap) + var(--saas-shift)); }
.saas-col--2 { left: calc(var(--saas-gap) * 2 + var(--saas-tile) + var(--saas-shift)); }
.saas-col--3 { right: calc(var(--saas-gap) * 2 + var(--saas-tile) + var(--saas-shift)); }
.saas-col--4 { right: calc(var(--saas-gap) + var(--saas-shift)); }

/* Default idle wave (overridden by saas-field.js at runtime).
   Lives on .saas-field so all .saas-col's can read the same value
   via --idle-y-shared. */
.saas-field { --idle-y-shared: 0px; }

/* ---------- Tile ---------- */
/* No card, no border, no background — the icons already carry their
   own shape and colour. A three-layer drop-shadow (hugs the icon
   outline, not a bounding box) is the only surface treatment, plus
   a per-tile floating bobble driven by @keyframes saas-drift on
   each .saas-tile's own --drift-dur / --drift-delay (set inline
   in index.html). The bobble is intentionally chaotic — each tile
   floats on its own timeline — so the icons read as living within
   the shared column current, not rigidly locked to it. Bounded to
   ±3.5px peak (Anthony pass 3: cut from ±7px so the bobble reads
   as a gentle breathe, not a noticeable per-tile drift on top
   of the shared wave). */
.saas-tile {
  width: var(--saas-tile);
  aspect-ratio: 1;
  animation: saas-drift var(--drift-dur, 10s) ease-in-out
    var(--drift-delay, 0s) infinite alternate;
}
.saas-tile img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Three layers stacked from tight to soft:
     - 0 1px 2px / 0.09: contact shadow at the icon's outline
       (visible on thin transparent marks like Claude, Notion).
     - 0 5px 10px / 0.16: mid-distance lift — the layer that
       reads on dense colored squircles (OpenAI, HubSpot,
       Salesforce, Stripe, AWS, Google, CoPilot, Mistral,
       Gemini, Microsoft, SAP, Shopify).
     - 0 14px 26px / 0.14: soft ambient haze grounding the
       icon on the paper without darkening it.
     Same rgba(10,26,32,…) token family as --shadow-card etc. */
  filter:
    drop-shadow(0 1px 2px rgba(10, 26, 32, 0.09))
    drop-shadow(0 5px 10px rgba(10, 26, 32, 0.16))
    drop-shadow(0 14px 26px rgba(10, 26, 32, 0.14));
}
@keyframes saas-drift {
  from { transform: translateY(-3.5px); }
  to   { transform: translateY(3.5px); }
}

/* ---------- Responsive ---------- */
@media (max-width: 1360px) {
  /* below this width the even three-way spread has no room left for
     a second tile per side (--saas-gap floors at 0) — the edge pair
     alone carries the idea */
  .saas-col--2,
  .saas-col--3 { display: none; }
}
@media (max-width: 640px) {
  .saas-field {
    --saas-tile: 48px;
    min-height: clamp(293px, 43vh, 372px);
  }
  /* half-cropped at the edges: the field continues beyond the frame */
  .saas-col--1 { left: calc(var(--saas-tile) * -0.35); }
  .saas-col--4 { right: calc(var(--saas-tile) * -0.35); }
}

/* ---------- Reduced motion ----------
   base.css already freezes the drift keyframes; the JS driver
   also holds --py at 0 (and never writes --idle-y-shared).
   The static field keeps full meaning; the shadow remains
   (structural, not motion). */
@media (prefers-reduced-motion: reduce) {
  .saas-tile { animation: none; }
  .saas-col { transform: none; will-change: auto; }
}
