/* ============================================================
   VEXT LABS · the pixel layer — vext-pixels.css
   Packet: VEXTLABS-BRAND-20260904

   Implements the Claude Design canvas (Main.dc.html / Mobile.dc.html,
   canvas.json) as real CSS. Every value below is lifted from those
   artboards; nothing here is invented.

   The three elements the founder asked for, in order:

   1. THE RULE. A line built out of the same pixels as the mosaic:
      elongated rounded dashes in orange and electric pink, running
      under the header. Three loose tiles drop into it from above and
      settle on the line, so it reads as CATCHING the pixels rather
      than merely separating two bands.
   2. THE MOSAIC. The brand's grid element: rounded squares on a fixed
      grid with equal gaps, landing in a diagonal cascade.
   3. THE FIELD. The orange-to-pink gradient band the brand uses behind
      a white statement card. It drifts, very slowly, and it is the only
      motion in the system that loops.

   Colour comes from vext-brand.css tokens (--vb-orange #FF5D1B,
   --vb-magenta #FF93FF, --vb-ink #101010). Spacing and type stay in
   proposal-a.css. This file adds shapes and motion only, and every
   animation is added only under prefers-reduced-motion: no-preference,
   so every element paints its final state with no motion at all.
   ============================================================ */

:root {
  /* Canvas: 62px tiles at 1440, 38px at 390. One fluid ramp covers both. */
  --vx-tile-size: clamp(34px, 4.3vw, 62px);
  --vx-tile-gap: clamp(7px, 0.7vw, 10px);
  --vx-tile-radius: clamp(7px, 0.63vw, 9px);
  --vx-orange: var(--vb-orange, #FF5D1B);
  --vx-pink: var(--vb-magenta, #FF93FF);
  --vx-ease: cubic-bezier(0.22, 0.9, 0.28, 1);
}

/* ---- 1. THE RULE ------------------------------------------------- */
/* Segment widths, colours and delays are the canvas sequence, fixed and
   not random, so the line renders identically every load.

   The canvas states the widths in absolute px on a 1440 artboard. Here
   each width becomes a flex-grow ratio on a zero basis (--vxw), which
   keeps the canvas rhythm exactly while letting the line span the full
   measure at any width. That matters for the founder's ask: the three
   caught pixels are positioned as a percentage of the rule, so unless
   the dashes reach the end of the rule the last one floats in space
   instead of landing ON the line. Same reason it never overflows a
   390px phone. */
.vx-rule {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  max-width: var(--pa-maxw, 1440px);
  margin-inline: auto;
  padding-inline: var(--pa-gutter, clamp(20px, 5vw, 88px));
}
.vx-rule__seg {
  height: 6px;
  border-radius: 3px;
  flex: var(--vxw, 1) 1 0;
  min-width: 2px;
  background: var(--vx-orange);
}
.vx-rule__seg--pink { background: var(--vx-pink); }

/* The caught pixels: they fall from above the line and land on it. */
.vx-rule__caught {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  border-radius: 5px;
  background: var(--vx-orange);
  transform: translate(-50%, -50%);
}
.vx-rule__caught--pink { background: var(--vx-pink); }
/* Where on the rule each one lands. Kept here rather than on a style
   attribute so no percentage figure ever appears in page copy. */
.vx-rule__caught--a { left: 18%; animation-delay: 780ms; }
.vx-rule__caught--b { left: 47%; animation-delay: 900ms; }
.vx-rule__caught--c { left: 79%; animation-delay: 1010ms; }

@keyframes vxSeg {
  from { opacity: 0; transform: scaleX(0.2); }
  to   { opacity: 1; transform: scaleX(1); }
}
@keyframes vxCatch {
  0%   { opacity: 0; transform: translate(-50%, -46px); }
  62%  { opacity: 1; transform: translate(-50%, -50%); }
  100% { opacity: 1; transform: translate(-50%, -50%); }
}

/* ---- 2. THE MOSAIC ----------------------------------------------- */
.vx-mos { display: flex; flex-direction: column; gap: var(--vx-tile-gap); }
.vx-mos__row { display: flex; gap: var(--vx-tile-gap); }
.vx-tile {
  width: var(--vx-tile-size);
  height: var(--vx-tile-size);
  border-radius: var(--vx-tile-radius);
  flex: none;
  background: transparent;
}
.vx-tile--o { background: var(--vx-orange); }
.vx-tile--p { background: var(--vx-pink); }
/* An empty cell holds its slot in the grid and never animates. */
.vx-tile--x { animation: none !important; opacity: 1 !important; }

@keyframes vxTile {
  from { opacity: 0; transform: scale(0.55) translateY(10px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---- 3. THE FIELD ------------------------------------------------ */
/* Orange to electric pink, exactly the canvas stops. The drifting layer
   is a separate absolutely-positioned child so the card above it never
   moves and the text never resamples. */
.vx-field { position: relative; overflow: hidden; isolation: isolate; }
.vx-field__bg {
  position: absolute;
  inset: -8%;
  z-index: 0;
  background:
    radial-gradient(48% 62% at 18% 30%, var(--vx-orange) 0%, rgba(255, 93, 27, 0) 62%),
    radial-gradient(52% 68% at 76% 26%, var(--vx-pink) 0%, rgba(255, 147, 255, 0) 60%),
    radial-gradient(60% 70% at 62% 88%, var(--vx-orange) 0%, rgba(255, 93, 27, 0) 58%),
    radial-gradient(46% 58% at 8% 84%, var(--vx-pink) 0%, rgba(255, 147, 255, 0) 62%),
    linear-gradient(104deg, #FF6A2B 0%, #FF4FA8 52%, var(--vx-pink) 100%);
}
.vx-field__in { position: relative; z-index: 1; }

@keyframes vxDrift {
  0%   { transform: scale(1.06) translate3d(0, 0, 0); }
  50%  { transform: scale(1.12) translate3d(-1.6%, 1.1%, 0); }
  100% { transform: scale(1.06) translate3d(0, 0, 0); }
}

/* The white card that sits on the field. */
.vx-card {
  background: var(--vb-white, #FFFFFF);
  color: var(--vb-ink, #101010);
  border-radius: 20px;
  padding: clamp(26px, 3vw, 40px) clamp(24px, 3.2vw, 46px);
}

/* ---- Homepage composition ---------------------------------------- */
.vx-ann {
  background: var(--vx-orange);
  color: var(--vb-white, #FFFFFF);
  min-height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 9px var(--pa-s4, 16px);
  font-size: clamp(11.5px, 0.9vw, 13px);
  letter-spacing: 0.01em;
  line-height: 1.4;
}
.vx-ann a { color: var(--vb-white, #FFFFFF); text-decoration: underline; text-underline-offset: 3px; }

.vx-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: start;
  gap: var(--pa-s7, 48px);
  padding-block: clamp(40px, 5.8vw, 84px) clamp(28px, 3vw, 40px);
}
.vx-hero__copy { position: relative; z-index: 2; max-width: 660px; }
/* The cascade bleeds off the right edge of the page, as on the artboard. */
.vx-hero__mos { justify-self: end; margin-right: calc(-1 * var(--pa-gutter, 40px)); padding-top: clamp(0px, 2vw, 40px); }
.vx-hand {
  font-family: var(--pa-font-script, cursive);
  font-size: clamp(23px, 2.1vw, 30px);
  color: var(--vb-ink, #101010);
  transform: rotate(-1.2deg);
  transform-origin: left center;
  margin: 0;
  opacity: 0.96;
}
@keyframes vxHand {
  from { opacity: 0; transform: translateY(8px) rotate(-1.2deg); }
  to   { opacity: 0.96; transform: translateY(0) rotate(-1.2deg); }
}
.vx-rise { }
@keyframes vxRise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* The two things we do: a bordered card and its ink twin. */
.vx-duo { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pa-s5, 24px); }
.vx-duo__card {
  position: relative;
  overflow: hidden;
  border-radius: 18px;
  padding: clamp(26px, 2.8vw, 40px);
  min-height: 320px;
  border: 1px solid var(--pa-hair, rgba(16, 16, 16, 0.12));
}
.vx-duo__card--ink {
  background: var(--vb-ink, #101010);
  color: var(--vb-white, #FFFFFF);
  border-color: transparent;
}
.vx-duo__card--ink .vx-duo__eyebrow { color: rgba(255, 255, 255, 0.55); }
.vx-duo__card--ink p { color: rgba(255, 255, 255, 0.72); }
.vx-duo__eyebrow {
  font-size: 12px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--pa-text-muted, #8A8A90);
  margin: 0;
}
.vx-duo__h {
  font-family: var(--pa-font-display, sans-serif);
  font-size: clamp(24px, 2.3vw, 32px);
  line-height: 1.14;
  letter-spacing: -0.025em;
  font-weight: 500;
  margin: 16px 0 0;
  max-width: 24ch;
}
.vx-duo__card p { font-size: clamp(15.5px, 1.15vw, 16px); line-height: 1.6; margin: 18px 0 0; max-width: 42ch; }
/* The rising curve, read bottom-left to top-right. The canvas writes it
   as columns side by side, so the outer axis is the row here. */
.vx-duo__curve { position: absolute; right: 26px; bottom: 26px; }
.vx-duo__curve .vx-mos { flex-direction: row; gap: 8px; }
.vx-duo__curve .vx-mos__row { flex-direction: column; gap: 8px; }
.vx-duo__curve .vx-tile { width: 30px; height: 30px; border-radius: 7px; }
/* The band along the bottom edge of the ink card, running off both ends. */
.vx-duo__card--ink { padding-bottom: 72px; }
.vx-duo__band {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; gap: 8px; padding: 0 8px 8px; margin: 0;
  overflow: hidden;
}
.vx-duo__band .vx-tile { width: 34px; height: 34px; border-radius: 7px; }

/* The composer card the brand uses for its positioning line. */
.vx-composer { max-width: 780px; margin-inline: auto; border-radius: 22px; padding: clamp(26px, 2.7vw, 38px) clamp(24px, 2.9vw, 40px) 26px; }
.vx-composer p { margin: 0; font-size: clamp(16px, 1.35vw, 19px); line-height: 1.62; color: var(--vb-ink, #101010); }
.vx-composer__row {
  display: flex; align-items: center; gap: 14px;
  margin-top: 30px; padding-top: 22px;
  border-top: 1px solid rgba(16, 16, 16, 0.09);
}
.vx-composer__hint { font-size: 15px; color: var(--pa-text-muted, #8A8A90); flex-grow: 1; }
.vx-composer__send {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  background: var(--vx-orange);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--vb-white, #FFFFFF);
}

/* Closing CTA: the same primary action, last thing before the footer. */
.vx-close { display: flex; align-items: flex-end; justify-content: space-between; gap: clamp(24px, 4vw, 60px); flex-wrap: wrap; }
.vx-close__h {
  font-family: var(--pa-font-display, sans-serif);
  font-size: clamp(32px, 3.9vw, 54px);
  line-height: 1.04;
  letter-spacing: -0.032em;
  font-weight: 500;
  margin: 0;
  max-width: 18ch;
  text-wrap: balance;
}

/* ---- Phone: the Mobile artboard ---------------------------------- */
@media (max-width: 860px) {
  .vx-hero { grid-template-columns: 1fr; gap: var(--pa-s6, 32px); }
  /* Full-bleed mosaic band, exactly as the phone artboard: it starts at
     the gutter and runs off the right edge inside a clipped strip. */
  .vx-hero__mos {
    justify-self: stretch;
    margin-inline: calc(-1 * var(--pa-gutter, 20px));
    padding-left: var(--pa-gutter, 20px);
    padding-top: 0;
    overflow: hidden;
  }
  .vx-duo { grid-template-columns: 1fr; }
  .vx-duo__card { min-height: 0; }
  .vx-duo__curve { position: static; margin-top: 22px; justify-content: flex-start; }
  .vx-close { display: block; }
  .vx-close__actions { margin-top: 24px; }
}

/* Container queries where the element, not the viewport, is the question. */
@supports (container-type: inline-size) {
  .vx-duo { container-type: inline-size; container-name: vxduo; }
  @container vxduo (max-width: 560px) {
    .vx-duo__curve { position: static; margin-top: 22px; }
  }
}

/* ---- Motion is opt-in, not opt-out ------------------------------- */
/* Every rule above already paints the FINAL state, so the page is
   complete and readable with no animation at all: in a print, in a
   crawler, in a background tab whose animations never start, and for
   anyone who asked their OS to reduce motion. The reveal is added only
   inside prefers-reduced-motion: no-preference, which is the one place
   it is safe for a headline to begin at opacity 0. */
@media (prefers-reduced-motion: no-preference) {
  .vx-rule__seg { opacity: 0; animation: vxSeg 0.5s var(--vx-ease) both; }
  .vx-rule__caught { opacity: 0; animation: vxCatch 0.78s cubic-bezier(0.34, 1.32, 0.5, 1) both; }
  .vx-tile { opacity: 0; animation: vxTile 0.52s var(--vx-ease) both; }
  .vx-rise { opacity: 0; animation: vxRise 0.74s var(--vx-ease) both; }
  .vx-hand { opacity: 0; animation: vxHand 0.8s ease-out 0.95s both; }
  .vx-field__bg { animation: vxDrift 26s ease-in-out infinite; }
}
