/* ═══════════════════════════════════════════════════════════════════════════
   SCROLLYTELLING — a pinned sequence, driven entirely by CSS
   ───────────────────────────────────────────────────────────────────────────
   The previous "animation" on this site was a fade-up on a few elements and a
   decorative canvas that referenced nothing. This is the real thing: a visual
   that PINS while the narrative steps past it, each step driven by its own
   position in the scrollport.

   No JavaScript. No scroll listener, no rAF loop, no IntersectionObserver —
   `animation-timeline: view()` runs the whole sequence on the compositor, so
   it is smooth under load in a way a scroll handler cannot be. Browsers
   without it get every step visible at once, stacked and readable, which is
   the correct fallback for a narrative.
   ═══════════════════════════════════════════════════════════════════════════ */

.scrolly {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(24px, 5vw, 100px);
  align-items: start;
}

/* The pinned half. Sticks for the whole run of the steps beside it. */
.scrolly__stage {
  position: sticky;
  top: 96px;
  height: min(74svh, 620px);
  border-radius: 2px;
  overflow: hidden;
  background: var(--bg-sunk);
}
.scrolly__stage img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0;
}
/* The first frame is the resting state so the stage is never empty. */
.scrolly__stage img:first-child { opacity: 1; }

.scrolly__steps { display: grid; }
.scrolly__step {
  min-height: 82svh;
  display: grid; align-content: center; gap: var(--s-4);
  max-width: 44ch;
}
.scrolly__n {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .2em;
  color: var(--signal-lift);
}
.scrolly__h {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.4vw, 52px); font-weight: 700;
  letter-spacing: -.034em; line-height: 1.02; color: var(--ink);
}
.scrolly__p { font-size: clamp(16px, 1.35vw, 19px); line-height: 1.65; color: var(--ink-3); }

@supports (animation-timeline: view()) {
  /* Each step dims at the edges of the scrollport and is full weight while it
     occupies the middle — so exactly one step reads as "current" at a time. */
  .scrolly__step {
    animation: step-focus linear both;
    animation-timeline: view();
    animation-range: cover 12% cover 88%;
  }
  @keyframes step-focus {
    0%   { opacity: .18; transform: translateY(14px); }
    28%, 72% { opacity: 1; transform: none; }
    100% { opacity: .18; transform: translateY(-14px); }
  }

  /* The frames must be driven by the progress of the STEPS through the
     scrollport — NOT by their own. They live inside the sticky stage, so once
     it pins they stop moving and their own view() progress freezes: the first
     build had frame four locked on for the entire section.
     `view-timeline-name` publishes the steps column's own progress, and
     `timeline-scope` on the shared ancestor makes it addressable from the
     stage, which is a sibling rather than a descendant. */
  .scrolly { timeline-scope: --seq; }
  .scrolly__steps { view-timeline-name: --seq; view-timeline-axis: block; }

  .scrolly__stage img {
    animation: frame linear both;
    animation-timeline: --seq;
    /* `cover`, not `contain`: the steps column is roughly three times the
       height of the scrollport, and `contain` on an element taller than the
       viewport is a degenerate range — it collapsed the whole sequence into
       its first two thirds and left frame four holding for the rest. */
    animation-range: cover 0% cover 100%;
  }
  @keyframes frame { from { opacity: 0 } to { opacity: 0 } }

  .scrolly__stage img:nth-child(1) { animation-name: f1 }
  .scrolly__stage img:nth-child(2) { animation-name: f2 }
  .scrolly__stage img:nth-child(3) { animation-name: f3 }
  .scrolly__stage img:nth-child(4) { animation-name: f4 }
  /* Four frames across the cover range, each holding through its own step and
     crossfading over roughly 6% of the scroll. */
  @keyframes f1 { 0%,26% {opacity:1} 32% {opacity:0} 100% {opacity:0} }
  @keyframes f2 { 0%,26% {opacity:0} 32%,48% {opacity:1} 54% {opacity:0} 100% {opacity:0} }
  @keyframes f3 { 0%,48% {opacity:0} 54%,70% {opacity:1} 76% {opacity:0} 100% {opacity:0} }
  @keyframes f4 { 0%,70% {opacity:0} 76%,100% {opacity:1} }
}

/* Without scroll-driven animation every step is simply visible and the stage
   shows its first frame. A narrative must never be hidden behind a capability. */
@supports not (animation-timeline: view()) {
  .scrolly__step { min-height: 0; padding-block: var(--s-7); }
  .scrolly__stage { position: static; height: auto; aspect-ratio: 4/5; }
}

@media (max-width: 880px) {
  .scrolly { grid-template-columns: 1fr; }
  .scrolly__stage { position: sticky; top: 76px; height: 42svh; }
  .scrolly__step { min-height: 68svh; max-width: none; }
}
@media (prefers-reduced-motion: reduce) {
  .scrolly__step, .scrolly__stage img { animation: none !important; opacity: 1 !important; transform: none !important; }
  .scrolly__stage { position: static; height: auto; aspect-ratio: 16/10; }
  .scrolly__stage img { position: relative; }
  .scrolly__stage img:not(:first-child) { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   COMMAND PALETTE
   ═══════════════════════════════════════════════════════════════════════════ */

.cmdk-trigger {
  display: inline-flex; align-items: center; gap: 7px;
  background: none; border: 1px solid var(--line-2); border-radius: 3px;
  padding: 5px 8px 5px 7px; color: var(--ink-3); cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-io), color var(--dur-1) var(--ease-io);
}
.cmdk-trigger:hover { border-color: var(--signal); color: var(--ink); }
.cmdk-trigger svg { width: 14px; height: 14px; }
.cmdk-trigger kbd {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
  color: var(--ink-4); border: 0; background: none; padding: 0;
}
@media (max-width: 620px) { .cmdk-trigger kbd { display: none; } }

.cmdk {
  width: min(640px, calc(100vw - 32px));
  max-height: min(70svh, 560px);
  padding: 0; border: 1px solid var(--line-2); border-radius: 6px;
  background: var(--panel); color: var(--ink);
  box-shadow: 0 40px 90px -30px rgba(0,0,0,.85), 0 4px 14px rgba(0,0,0,.5);
  margin: min(14svh, 120px) auto auto;
  overflow: hidden;
}
.cmdk::backdrop { background: rgba(4,7,14,.72); backdrop-filter: blur(3px); }

.cmdk__bar {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-4) var(--s-5); border-bottom: 1px solid var(--line);
}
.cmdk__icon { width: 17px; height: 17px; color: var(--ink-4); flex: none; }
.cmdk__input {
  flex: 1; background: none; border: 0; outline: none;
  font-family: var(--font-display); font-size: 16px; color: var(--ink);
}
.cmdk__input::placeholder { color: var(--ink-4); }
.cmdk__esc, .cmdk__foot kbd {
  font-family: var(--font-mono); font-size: 10px; color: var(--ink-4);
  border: 1px solid var(--line-2); border-radius: 3px; padding: 2px 5px;
}

.cmdk__list { list-style: none; margin: 0; padding: var(--s-2); overflow-y: auto; max-height: 46svh; }
.cmdk__list li a {
  display: grid; grid-template-columns: 84px minmax(0,1fr); gap: 2px var(--s-4);
  padding: 10px var(--s-3); border-radius: 4px; align-items: baseline;
}
.cmdk__list li[aria-selected="true"] a { background: var(--signal-wash); }
.cmdk__g {
  grid-row: 1 / span 2; align-self: center;
  font-family: var(--font-display); font-size: 9.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-4);
}
.cmdk__list li[aria-selected="true"] .cmdk__g { color: var(--signal-lift); }
.cmdk__t {
  font-family: var(--font-display); font-size: 15px; font-weight: 600;
  color: var(--ink); display: flex; align-items: center; gap: 8px;
}
.cmdk__s {
  font-style: normal; font-size: 8.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--live);
  border: 1px solid currentColor; border-radius: 2px; padding: 1px 5px;
}
.cmdk__d {
  font-size: 12.5px; color: var(--ink-3); line-height: 1.45;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cmdk__empty { margin: 0; padding: var(--s-7) var(--s-5); text-align: center; color: var(--ink-3); font-size: 14px; }
.cmdk__foot {
  display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-3) var(--s-5); border-top: 1px solid var(--line);
  font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-4);
}
.cmdk__foot span { display: inline-flex; align-items: center; gap: 5px; }
.cmdk__count { margin-left: auto; }

/* ── capabilities list ─────────────────────────────────────────────────── */
.caplist { list-style: none; margin: 0; padding: 0; display: grid; counter-reset: cap; }
.caplist > li { border-top: 1px solid var(--line); }
.caplist > li:last-child { border-bottom: 1px solid var(--line); }
.caplist a {
  display: grid; align-items: baseline;
  grid-template-columns: 3rem minmax(0, 1fr) minmax(0, 30ch) 2rem;
  gap: var(--s-3) clamp(20px, 3vw, 52px);
  padding-block: clamp(20px, 2.6vw, 42px);
  transition: background var(--dur-2) var(--ease-io);
}
.caplist a:hover { background: var(--bg-raised); }
.caplist__n { font-size: 11px; color: var(--ink-4); align-self: start; padding-top: .55em; }
.caplist__name {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(24px, 3.2vw, 46px); letter-spacing: -.034em; line-height: 1;
  color: var(--ink);
}
.caplist a:hover .caplist__name { color: var(--signal-lift); }
.caplist__note { font-size: 15px; line-height: 1.55; color: var(--ink-3); }
.caplist__go { font-size: 20px; color: var(--ink-4); justify-self: end;
  transition: transform var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-io); }
.caplist a:hover .caplist__go { transform: translateX(6px); color: var(--signal-lift); }
@media (max-width: 820px) {
  .caplist a { grid-template-columns: 2.4rem minmax(0,1fr); }
  .caplist__note { grid-column: 2; }
  .caplist__go { display: none; }
}
