
/* ── Blueprint canvas ───────────────────────────────────────────────
   The faint dotted graph paper Laravel uses behind its bento grid. */
.v2-grid-bg {
  background-image: radial-gradient(circle, color-mix(in srgb, var(--foreground) 16%, transparent) 1px, transparent 1px);
  background-size: 22px 22px;
}

/* Small square marker pinned to a cell corner — the "measured drawing" feel
   the original gets from its crop marks. */
.v2-mark { position: absolute; width: 7px; height: 7px; background: var(--primary); }
.v2-mark-tl { top: -4px; left: -4px; }
.v2-mark-tr { top: -4px; right: -4px; }
.v2-mark-bl { bottom: -4px; left: -4px; }
.v2-mark-br { bottom: -4px; right: -4px; }

/* ── Endless logo rail ──────────────────────────────────────────────
   The track holds the client list twice, so translating -50% loops
   with no visible seam. */
.v2-rail { animation: v2-rail 38s linear infinite; will-change: transform; }
.v2-railwrap:hover .v2-rail,
.v2-railwrap:focus-within .v2-rail { animation-play-state: paused; }
@keyframes v2-rail {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ── Interactive pill toggle in the statement headline ───────────
   The halo belongs to the ON state only; switching off leaves a plain
   grey pill, the way the original does. */
.v2-toggle { cursor: pointer; box-shadow: none; transition: box-shadow 300ms ease, background-color 300ms ease; }
.v2-toggle-on {
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--primary) 45%, transparent),
    0 0 26px 4px color-mix(in srgb, var(--primary) 45%, transparent),
    0 0 60px 12px color-mix(in srgb, var(--primary) 22%, transparent);
  animation: v2-glow 3.2s ease-in-out infinite;
}
@keyframes v2-glow {
  0%, 100% { filter: saturate(1); }
  50%      { filter: saturate(1.35) brightness(1.08); }
}

/* ── Load reveal ────────────────────────────────────────────────────
   The hero resolves out of a soft blur instead of just appearing. The
   text blurs and rises; the illustration only fades, so it never looks
   like a smeared photo mid-load. */
.v2-in { animation: v2-in 900ms cubic-bezier(0.22, 1, 0.36, 1) both; }
.v2-in-1 { animation-delay: 40ms; }
.v2-in-2 { animation-delay: 130ms; }
.v2-in-3 { animation-delay: 220ms; }
.v2-in-visual { animation: v2-in-visual 1100ms cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: 160ms; }

@keyframes v2-in {
  from { opacity: 0; filter: blur(12px); transform: translateY(12px); }
  to   { opacity: 1; filter: blur(0); transform: none; }
}
@keyframes v2-in-visual {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── Hero fit ───────────────────────────────────────────────────────
   The hero and the client rail are meant to share one screen. On genuinely
   short viewports there isn't room at full size, so the video gives way
   first: switching width to auto lets max-height drive it, and the intrinsic
   aspect ratio keeps it undistorted. Headline scales back a step too.

   The threshold used to be 740px, which caught ordinary laptops rather than
   short windows: Chrome's tab and bookmark bars take roughly 140px, so a 13"
   screen lands near 720px and the video was shrunk to a third of the height —
   while the same machine in Safari, whose chrome is slimmer, stayed above the
   threshold and looked correct. Hence "fine in Safari, small in Chrome".
   660px now means a genuinely short window, and 46svh keeps the video
   legible when it does apply. */
@media (max-height: 660px) {
  .v2-hero-video { width: auto; max-height: 46svh; }
  .v2-hero-title { font-size: clamp(1.9rem, 7vw, 2.6rem); }
  .v2-hero-pad { padding-top: 1rem; padding-bottom: 1rem; }
  .v2-hero-lede { margin-top: 1rem; font-size: 1rem; }
}

/* ── Hero badge shimmer ─────────────────────────────────────────────
   A soft light bar that crosses the pill every few seconds. Sits under
   the text (z-index) so the label never washes out. */
.v2-shimmer {
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--foreground) 10%, transparent), transparent);
  transform: translateX(-100%);
  animation: v2-shimmer 2.6s ease-in-out infinite;
}
@keyframes v2-shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(200%); }
}

/* ── Card lift ──────────────────────────────────────────────────── */
.v2-lift { transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1), box-shadow 500ms ease; }
.v2-lift:hover { transform: translateY(-4px); }

/* ── Terminal / preview chrome ──────────────────────────────────── */
.v2-mono {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-variant-ligatures: none;
}

/* Respect the visitor's motion preference across the whole page. */
@media (prefers-reduced-motion: reduce) {
  .v2-toggle-on, .v2-rail, .v2-shimmer { animation: none !important; }
  /* The reveal still runs, but as a plain fade — no blur, no movement. */
  .v2-in, .v2-in-visual { animation: v2-in-visual 400ms linear both; }
}
