/* ─────────────────────────────────────────────────────────────────────────────
   PILLARS · QUICKSTART · PROVIDERS · DOCS

   THE FOUR CARDS
   One card per pillar, taken verbatim from the project's own README table, and
   each card's animation encodes the thing that pillar actually does. That is
   the whole discipline on this section: nothing here is a loading spinner or a
   decorative shimmer.

     Harness  four gateways converging on one loop   (the README's own claim)
     Loop     a dash travelling a three-stop cycle   (reason, act, repeat)
     Memory   one file filling in three kinds        (semantic, episodic, skills)
     Eval     a bar crossing a threshold into green  (the release gate)

   A visitor who reads nothing else still learns the architecture from these
   four moving parts, which is the only reason a card grid is allowed on this
   page at all. If a fifth card were added it would have to move something real;
   ornamental fifths are exactly what a features grid becomes the moment nobody
   is counting.

   THE TILT IS CSS-ONLY
   A pointer-tracked tilt is nicer, and it needs a rAF listener per card and a
   transform write on every move. A four-degree lift on hover gets 80% of the
   physicality for one line and cannot desync from the pointer. The rig in the
   hero is where the pointer budget went.
   ───────────────────────────────────────────────────────────────────────────── */

.pillars {
  display: grid;
  /* Explicit column counts, not auto-fit.
     `repeat(auto-fit, minmax(232px, 1fr))` needs 4x232 + 3x1px of gaps = 931px
     for four columns, and the content width at --page-max is 928 — three pixels
     short, so auto-fit wrapped to 3 + 1 and left the fourth cell showing the
     grid's own rule colour as a grey block. A pillar layout that is sometimes
     four and sometimes three is not a layout. Four cards, four columns, two at
     the middle breakpoint, one on a phone. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--rule-width);
  /* The gap IS the border: one background rule showing between four panels, so
     the grid has hairline separators without a single card owning a border. */
  background: var(--rule);
  border: var(--rule-width) solid var(--rule);
  border-radius: var(--radius);
}

@media (min-width: 560px) {
  .pillars {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 900px) {
  .pillars {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.pillar {
  position: relative;
  padding: var(--space-6) var(--space-6) var(--space-8);
  background: var(--surface-bg);
  transition: background var(--motion-fast) var(--motion-ease);
  overflow: hidden;
}

.pillar:hover {
  background: var(--surface-paper);
}

.pillar__h {
  font-size: var(--t-h3);
  margin-bottom: var(--space-3);
}

.pillar__p {
  font-size: var(--t-small);
  color: var(--text-muted);
  text-wrap: pretty;
}

/* The seam that runs down the left edge and lights on hover. It is the same
   --emissive token the android's plates use, at the same intensities, so the
   cards are made of the same material as the figure above them. */
.pillar::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 1px;
  background: linear-gradient(
    180deg,
    transparent,
    color-mix(in srgb, var(--accent) 55%, transparent) 30%,
    color-mix(in srgb, var(--accent) 55%, transparent) 70%,
    transparent
  );
  opacity: 0;
  transition: opacity var(--motion-fast) var(--motion-ease);
}

.pillar:hover::before {
  opacity: 1;
}

.pillar:hover .pillar__viz {
  transform: translateY(-2px);
  filter: brightness(1.18);
}

.pillar__viz {
  height: 96px;
  margin: var(--space-6) 0 var(--space-4);
  transition: transform var(--motion-base) var(--motion-ease),
    filter var(--motion-base) var(--motion-ease);
}

/* ── viz · harness — four gateways into one loop ──────────────────────────── */
.viz-harness {
  position: relative;
}

.viz-harness__ring {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 62px;
  height: 62px;
  translate: -50% -50%;
  border: 1px solid color-mix(in srgb, var(--info) 60%, transparent);
  border-radius: var(--shape-circle);
  box-shadow: var(--emissive-lift-1);
}

.viz-harness__node {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: var(--shape-circle);
  background: var(--info);
  box-shadow: 0 0 8px color-mix(in srgb, var(--info) 70%, transparent);
  top: 46%;
  animation: converge 3.4s var(--motion-ease) infinite;
}
.viz-harness__node:nth-of-type(1) {
  left: 6%;
  animation-delay: 0s;
}
.viz-harness__node:nth-of-type(2) {
  left: 26%;
  animation-delay: 0.45s;
}
.viz-harness__node:nth-of-type(3) {
  right: 26%;
  animation-delay: 0.9s;
}
.viz-harness__node:nth-of-type(4) {
  right: 6%;
  animation-delay: 1.35s;
}

/* Each node slides into the ring and fades as it arrives, so four gateways
   become one loop over 3.4s and the loop is visibly the destination.

   Rest is 0.34, not 0. At zero the whole card was empty for two thirds of its
   cycle and a screenshot of the page showed two dots out of four, which reads
   as a broken graphic rather than as a moment in an animation. A still frame
   of this card has to look like four gateways. */
@keyframes converge {
  0%,
  15% {
    translate: 0 0;
    opacity: 0.34;
  }
  34% {
    opacity: 1;
  }
  85% {
    translate: 34px 0;
    opacity: 0.34;
  }
  100% {
    translate: 0 0;
    opacity: 0.34;
  }
}

/* ── viz · loop — the dash travelling reason → act → repeat ─────────────────── */
.viz-loop {
  position: relative;
  display: grid;
  place-items: center;
}

.viz-loop__track {
  position: relative;
  width: 88px;
  height: 88px;
}

.viz-loop__track::before {
  /* A conic sweep standing in for the dashed circumference. Rotating it is the
     cheapest honest depiction of a cycle that repeats. */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--shape-circle);
  background: conic-gradient(
    from 0deg,
    transparent 0deg,
    color-mix(in srgb, var(--accent) 85%, transparent) 40deg,
    transparent 90deg,
    transparent 180deg,
    color-mix(in srgb, var(--accent) 85%, transparent) 220deg,
    transparent 270deg
  );
  -webkit-mask: radial-gradient(circle, transparent 0 60%, #000 61%);
  mask: radial-gradient(circle, transparent 0 60%, #000 61%);
  animation: turn 2.6s linear infinite;
}

@keyframes turn {
  to {
    rotate: 360deg;
  }
}

.viz-loop__stop {
  position: absolute;
  font: 500 9px / 1 var(--face-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.viz-loop__stop--a {
  top: -2px;
  left: 50%;
  translate: -50% 0;
}
.viz-loop__stop--b {
  bottom: 6px;
  right: -8px;
}
.viz-loop__stop--c {
  bottom: 6px;
  left: -8px;
}

.viz-loop__core {
  font: 500 10px / 1 var(--face-mono);
  color: var(--accent-fg);
  letter-spacing: 0.08em;
}

/* ── viz · memory — one file, three kinds ──────────────────────────────────── */
.viz-memory {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3);
}

.viz-memory__file {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font: 500 var(--t-micro) / 1 var(--face-mono);
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

.viz-memory__file::before {
  content: "";
  width: 10px;
  height: 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  border-radius: 1px;
  box-shadow: var(--emissive-lift-1);
}

.viz-memory__bar {
  display: flex;
  height: 6px;
  gap: 2px;
  border-radius: var(--radius);
  overflow: hidden;
}

.viz-memory__bar i {
  flex: 1;
  transform-origin: left center;
  animation: fill 3.6s var(--motion-ease) infinite alternate;
  background: color-mix(in srgb, var(--accent) 75%, transparent);
}

.viz-memory__bar i:nth-child(2) {
  animation-delay: 0.3s;
  background: color-mix(in srgb, var(--info) 75%, transparent);
}
.viz-memory__bar i:nth-child(3) {
  animation-delay: 0.6s;
  background: color-mix(in srgb, var(--ok) 70%, transparent);
}

@keyframes fill {
  from {
    scale: 0.18 1;
    opacity: 0.55;
  }
  to {
    scale: 1 1;
    opacity: 1;
  }
}

.viz-memory__key {
  display: flex;
  gap: var(--space-3);
  font: 400 9px / 1 var(--face-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ── viz · eval — the release gate ──────────────────────────────────────────── */
.viz-eval {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3);
}

.viz-eval__meter {
  position: relative;
  height: 8px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}

/* The threshold marker. A gate you cannot see the line of is not a gate. */
.viz-eval__meter::after {
  content: "";
  position: absolute;
  left: 82%;
  top: -2px;
  bottom: -2px;
  width: 1px;
  background: var(--text-faint);
}

.viz-eval__fill {
  /* display:block is load-bearing. These three elements are <span>s, and
     .viz-eval is a flex container so the METER gets blockified into a flex
     item — but nothing makes its CHILD a block. The fill stayed inline, where
     width and height do not apply, so the meter rendered as an empty box with a
     threshold line in it. An eval card showing no eval. */
  display: block;
  height: 100%;
  width: 100%;
  transform-origin: left center;
  background: linear-gradient(90deg, var(--info), var(--ok));
  animation: gate 4.2s var(--motion-ease) infinite alternate;
}

/* scaleX, not width. Animating `width` is a layout-then-paint property on every
   one of those frames; `transform: scaleX` is composited and costs nothing. The
   gradient compresses with the scale, which is invisible at this width, and it
   is the only way a bar can animate on the compositor at all. */
@keyframes gate {
  0%,
  55% {
    transform: scaleX(0.55);
  }
  100% {
    transform: scaleX(0.97);
  }
}

.viz-eval__key {
  display: flex;
  justify-content: space-between;
  font: 400 9px / 1 var(--face-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ── quickstart ───────────────────────────────────────────────────────────────
   An inset surface with a header row and a copy control. The surface is
   --surface-sunk, not a panel with a shadow: it is a hole cut into the page,
   which is what a terminal is, and cutting a hole needs no elevation. */
.steps {
  display: grid;
  gap: var(--space-4);
  max-width: 720px;
}

.step {
  background: var(--surface-sunk);
  border: var(--rule-width) solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color var(--motion-fast) var(--motion-ease);
}

.step:hover {
  border-color: var(--rule-hard);
}

.step__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: var(--rule-width) solid var(--rule);
}

.step__n {
  font: 500 var(--t-micro) / 1 var(--face-mono);
  color: var(--accent-fg);
  letter-spacing: 0.08em;
}

.step__what {
  flex: 1;
  font: 400 var(--t-micro) / 1 var(--face-mono);
  letter-spacing: 0.04em;
  color: var(--text-faint);
}

.step__code {
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4);
}

.step__code pre {
  flex: 1;
  margin: 0;
  font: 400 var(--t-small) / 1.7 var(--face-mono);
  color: var(--text-ink);
  overflow-x: auto;
  white-space: pre;
}

.step__code .c {
  color: var(--accent-fg);
}

.step__code .m {
  color: var(--text-faint);
}

/* ── providers ───────────────────────────────────────────────────────────────
   Ten real marks, in the project's own wordmark files. No "also supports"
   hedge and no invented partner — these are the providers names in the README,
   each with the file that already draws it. */
.providers {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.providers .chip {
  height: 34px;
  padding-inline: var(--space-3);
}

.providers .chip svg {
  width: 16px;
  height: 16px;
  opacity: 0.9;
  /* The marks are drawn for a light ground. On this one they need lifting to
     read at all, so they are brightened rather than inverted — inversion turns
     a coloured mark into a differently-wrong coloured mark. */
  filter: brightness(0.86) saturate(0.9);
}

.providers .chip:hover {
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  filter: none;
}

.providers .chip:hover svg {
  filter: brightness(1.1);
}

/* ── docs ─────────────────────────────────────────────────────────────────────
   A list of five, not a grid of nine. One row per document, separated by the
   page's single hairline, each saying what it is FOR rather than only naming
   itself. Depth order: getting started first. */
.docs {
  border-top: var(--rule-width) solid var(--rule);
}

.doc {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: var(--space-4);
  padding: var(--space-6) 0;
  border-bottom: var(--rule-width) solid var(--rule);
  text-decoration: none;
  transition: padding-left var(--motion-fast) var(--motion-ease);
}

.doc:hover {
  padding-left: var(--space-4);
}

.doc__name {
  font: 500 var(--t-body) / 1.3 var(--face-sans);
  color: var(--text-ink);
}

.doc__for {
  display: block;
  font-size: var(--t-small);
  color: var(--text-faint);
  margin-top: var(--space-2);
}

.doc:hover .doc__name {
  color: var(--accent-fg);
}

.doc__go {
  font: 400 var(--t-small) / 1 var(--face-mono);
  color: var(--text-faint);
  transition: color var(--motion-fast) var(--motion-ease);
}

.doc:hover .doc__go {
  color: var(--accent-fg);
}

@media (max-width: 700px) {
  .step__code {
    flex-direction: column;
    gap: var(--space-3);
  }

  .step__code .btn {
    align-self: flex-start;
  }
}

@media (prefers-reduced-motion: reduce) {
  .viz-harness__node,
  .viz-loop__track::before,
  .viz-memory__bar i,
  .viz-eval__fill {
    animation: none;
  }

  /* Land on the state each animation was travelling toward, not on its first
     frame — a still frame of "41% pass rate" would be a lie about the gate. */
  .viz-memory__bar i {
    scale: 1 1;
    opacity: 1;
  }

  .viz-eval__fill {
    transform: scaleX(0.97);
  }
}
