/* ==========================================================================
   Homepage "Recent go-lives": the real client page looping inside a
   browser frame, with a phone frame alongside on its own slower cycle.

   The pan is a plain compositor transform on a tall WebP. The travel is
   `-100% + 100cqh`: the whole image height, less the height of the window
   it sits in, so the reel always lands exactly on the foot of the capture
   whatever size the card renders at.
   ========================================================================== */

.gl-section {
  background: var(--rd-bg, #f4f0e8);
  padding-top: clamp(48px, 7vh, 88px);
  padding-bottom: clamp(24px, 4vh, 48px);
}

/* ---------- Header ---------- */

.gl-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px 32px;
}


/* Pause control. WCAG 2.2.2: the reels move for longer than five seconds
   and start on their own, so there has to be a way to stop them. */
/* `display` here would otherwise beat the UA rule for the hidden attribute,
   so the button stays on screen when JS hides it. */
.gl-toggle[hidden] {
  display: none;
}

/* Deliberately quiet: no border at rest, muted ink, small. It is a
   control people need to be able to find, not one the section should be
   selling. It earns its outline on hover and focus. */
.gl-toggle {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  margin-bottom: 6px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--rd-caption, #6a7379);
  cursor: pointer;
  transition:
    background 220ms var(--rd-ease),
    border-color 220ms var(--rd-ease),
    color 220ms var(--rd-ease);
}

.gl-toggle:hover,
.gl-toggle:focus-visible {
  background: var(--rd-surface, #ebe6dc);
  border-color: var(--rd-hairline, #d4cec4);
  color: var(--rd-ink);
}

.gl-toggle__icon {
  width: 7px;
  height: 9px;
  flex: none;
  background: currentColor;
  /* Two bars (pause) → one triangle (play) when the reels are stopped. */
  clip-path: polygon(0 0, 2.4px 0, 2.4px 100%, 0 100%, 4.6px 0, 7px 0, 7px 100%, 4.6px 100%);
}

.gl-section.is-paused .gl-toggle__icon {
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* ---------- Card ---------- */

.gl-list {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.gl-card {
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(28px, 4.5vw, 72px);
  align-items: center;
  padding: clamp(40px, 6vh, 76px) 0;
}

.gl-card--reverse {
  grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr);
}

.gl-card--reverse .gl-card__text {
  order: 2;
}

.gl-card--reverse .gl-card__media {
  order: 1;
}

/* ---------- Card copy ---------- */

.gl-card__status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 18px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--rd-green-deep, #3f8a67);
}

.gl-card__dot {
  position: relative;
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: 50%;
  background: var(--rd-green, #4ca378);
}

.gl-card__dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--rd-green, #4ca378);
  animation: gl-pulse 2.6s var(--rd-ease) infinite;
}

@keyframes gl-pulse {
  0% {
    transform: scale(1);
    opacity: 0.55;
  }
  100% {
    transform: scale(2.8);
    opacity: 0;
  }
}

.gl-card__title {
  margin: 0;
  font-family: var(--rd-font-display);
  font-size: clamp(30px, 3.6vw, 46px);
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.gl-card__title a {
  color: var(--rd-ink);
  text-decoration: none;
  transition: color 180ms var(--rd-ease);
}

.gl-card__title a:hover,
.gl-card__title a:focus-visible {
  color: var(--rd-green-deep);
}

.gl-card__meta {
  margin: 12px 0 0;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rd-muted);
}

.gl-card__desc {
  margin: clamp(16px, 2vw, 22px) 0 0;
  max-width: 44ch;
  font-size: clamp(15px, 1.4vw, 17px);
  line-height: 1.65;
  color: var(--rd-ink);
  text-wrap: pretty;
}

.gl-card__sites {
  margin: clamp(18px, 2.2vw, 24px) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
}

.gl-card__site {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  border: 1px solid var(--rd-hairline, #d4cec4);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  color: var(--rd-ink);
  transition:
    background 200ms var(--rd-ease),
    border-color 200ms var(--rd-ease);
}

.gl-card__site:hover,
.gl-card__site:focus-visible {
  background: var(--rd-surface, #ebe6dc);
  border-color: var(--rd-ink);
}

.gl-card__site svg {
  flex: none;
  opacity: 0.55;
}

.gl-card__case {
  display: inline-block;
  margin: clamp(18px, 2.2vw, 24px) 0 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--rd-ink);
  transition: color 180ms var(--rd-ease);
}

.gl-card__case:hover,
.gl-card__case:focus-visible {
  color: var(--rd-green-deep);
}

/* ---------- Frames ---------- */

.gl-card__media {
  position: relative;
  /* Room for the phone to hang past the foot of the browser frame. */
  padding-bottom: clamp(26px, 3.4vw, 46px);
}

.gl-browser {
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
  box-shadow:
    0 2px 4px rgba(26, 31, 34, 0.04),
    0 22px 56px -18px rgba(26, 31, 34, 0.26);
}

.gl-browser__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px;
  height: 30px;
  background: #e8e4dc;
  border-bottom: 1px solid rgba(26, 31, 34, 0.08);
}

.gl-browser__dots {
  display: inline-flex;
  gap: 5px;
  flex: none;
}

.gl-browser__dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(26, 31, 34, 0.18);
}

.gl-browser__url {
  flex: 1;
  min-width: 0;
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.72);
  font-family: var(--rd-font-body);
  font-size: 11px;
  letter-spacing: 0.01em;
  color: var(--rd-caption, #6a7379);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.gl-phone {
  position: absolute;
  bottom: 0;
  right: clamp(12px, 4%, 44px);
  width: clamp(84px, 13.5%, 128px);
  border-radius: 14px;
  padding: 5px;
  background: #1a1f22;
  box-shadow:
    0 2px 6px rgba(26, 31, 34, 0.12),
    0 20px 44px -14px rgba(26, 31, 34, 0.42);
}

.gl-card--reverse .gl-phone {
  right: auto;
  left: clamp(12px, 4%, 44px);
}

.gl-phone__inner {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  background: #fff;
}

.gl-phone__island {
  position: absolute;
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 5px;
  border-radius: 999px;
  background: #1a1f22;
  z-index: 2;
}

/* ---------- The reel ---------- */

.gl-port {
  /* `size` containment makes 100cqh below resolve to this window's height. */
  container-type: size;
  position: relative;
  overflow: hidden;
  background: #fff;
}

.gl-port--desktop {
  aspect-ratio: 16 / 10;
}

.gl-port--phone {
  aspect-ratio: 390 / 844;
}

.gl-reel {
  display: block;
  width: 100%;
  height: auto;
  transform: translateY(0);
  animation: gl-pan var(--gl-duration, 24s) linear infinite;
  animation-play-state: paused;
}

/* Only the cards actually on screen animate, and only while not paused. */
.gl-card.is-playing .gl-reel {
  animation-play-state: running;
  will-change: transform;
}

.gl-section.is-paused .gl-reel {
  animation-play-state: paused;
}

@keyframes gl-pan {
  0% {
    transform: translateY(0);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  7% {
    transform: translateY(0);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  47% {
    transform: translateY(calc(-100% + 100cqh));
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  57% {
    transform: translateY(calc(-100% + 100cqh));
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  97%,
  100% {
    transform: translateY(0);
  }
}

/* ---------- Drawer interaction ----------
   Some sites are better shown doing something than scrolled through. Here
   the reel stops at the drip menu and the treatment drawer plays over it:
   the panel and its scrim are separate layers sliding in on the same clock
   as the pan, so nothing is baked into a still. */

.gl-scrim,
.gl-drawer {
  position: absolute;
  animation-duration: var(--gl-duration, 24s);
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  animation-play-state: paused;
}

.gl-scrim {
  inset: 0;
  background: var(--gl-scrim, rgba(36, 30, 27, 0.38));
  opacity: 0;
  animation-name: gl-scrim-in;
}

.gl-drawer {
  top: 0;
  right: 0;
  height: 100%;
  width: var(--gl-drawer-w, 36%);
  transform: translateX(100%);
  animation-name: gl-drawer-in;
}

.gl-card.is-playing .gl-scrim,
.gl-card.is-playing .gl-drawer {
  animation-play-state: running;
}

.gl-card.is-playing .gl-drawer {
  will-change: transform;
}

.gl-section.is-paused .gl-scrim,
.gl-section.is-paused .gl-drawer {
  animation-play-state: paused;
}

/* The reel holds still at the menu while the drawer is out, instead of
   carrying on down the page. */
@keyframes gl-pan-to-stop {
  0% {
    transform: translateY(0);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  8% {
    transform: translateY(0);
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  30%,
  80% {
    transform: translateY(calc(-100% + 100cqh));
    animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  }
  94%,
  100% {
    transform: translateY(0);
  }
}

.gl-port--drawer .gl-reel {
  animation-name: gl-pan-to-stop;
}

@keyframes gl-drawer-in {
  0%,
  36% {
    transform: translateX(100%);
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }
  43%,
  70% {
    transform: translateX(0);
    animation-timing-function: cubic-bezier(0.55, 0, 0.68, 0.3);
  }
  77%,
  100% {
    transform: translateX(100%);
  }
}

@keyframes gl-scrim-in {
  0%,
  36% {
    opacity: 0;
  }
  43%,
  70% {
    opacity: 1;
  }
  77%,
  100% {
    opacity: 0;
  }
}

/* ---------- Footer link ---------- */

.gl-more {
  margin-top: clamp(16px, 2.6vw, 30px);
  text-align: center;
}

.gl-more a {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--rd-ink);
  border-bottom: 1px solid rgba(26, 31, 34, 0.24);
  padding-bottom: 3px;
  transition:
    color 180ms var(--rd-ease),
    border-color 180ms var(--rd-ease);
}

.gl-more a:hover,
.gl-more a:focus-visible {
  color: var(--rd-green-deep);
  border-color: var(--rd-green-deep);
}

/* ---------- Narrow ---------- */

@media (max-width: 900px) {
  .gl-card,
  .gl-card--reverse {
    grid-template-columns: minmax(0, 1fr);
    gap: clamp(24px, 5vw, 36px);
    padding: clamp(32px, 5vh, 48px) 0;
  }

  .gl-card__text,
  .gl-card--reverse .gl-card__text {
    order: 1;
  }

  .gl-card__media,
  .gl-card--reverse .gl-card__media {
    order: 2;
  }

  .gl-card__title {
    font-size: clamp(26px, 7vw, 36px);
  }

  .gl-phone,
  .gl-card--reverse .gl-phone {
    right: 10px;
    left: auto;
    width: clamp(72px, 19%, 104px);
  }

  .gl-head {
    align-items: flex-start;
  }
}

/* ---------- Motion off ---------- */

@media (prefers-reduced-motion: reduce) {
  /* Matches .gl-port--drawer .gl-reel too: a media query adds no
     specificity, so a bare .gl-reel here loses to it and the drawer card
     would keep its animation (paused, but only by luck). */
  .gl-reel,
  .gl-port--drawer .gl-reel {
    animation: none;
    transform: none;
  }

  /* Nothing plays, so the drawer would just sit over the shot. */
  .gl-scrim,
  .gl-drawer {
    display: none;
  }

  .gl-card__dot::after {
    animation: none;
    opacity: 0;
  }
}
