/* Hero demo — the animated scene that replaced simple_api_resized.mp4.
 *
 * ONE browser window showing qu4zr: the assistant panel on the left, the canvas and what it
 * published on the right. The chrome spans both panes on purpose — the story the hero has to tell
 * now is that none of this needs a client installed, so the frame itself has to say "this is the
 * page you are already on". (The MCP terminal it replaced said the opposite: a desktop app talking
 * to us from outside.)
 *
 * Built rather than recorded because the subject IS text: a 960px video of a prompt is unreadable
 * on a dense screen, weighs 1.6 MB in the LCP, and has to be re-shot every time a tool is renamed.
 *
 * Everything is scoped under .hero-scene and sized in cqw. The scope is not politeness: this file
 * shares a page with landing.css, and names like .node, .line, .dot and .canvas would collide the
 * day either side adds one.
 */

.hero-scene {
  /* Local tokens rather than landing.css's, so a rename over there can't silently restyle the
     scene — and so this file can be read on its own. Values are the landing palette. */
  --hd-bg: #0F1419;
  --hd-term-bg: #0B0F15;
  --hd-chrome-bg: #12171E;
  --hd-elevated: #151A21;
  --hd-hairline: #21262D;
  --hd-text: #F0F6FC;
  --hd-text-2: #C9D1D9;
  --hd-muted: #8B949E;
  --hd-accent: #60a5fa;
  --hd-zone: #38bdf8;
  --hd-violet: #a371f7;
  --hd-green: #3fb950;
  --hd-amber: #d29922;
  --hd-mono: ui-monospace, "SF Mono", "Cascadia Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--hd-bg);
  text-align: left;

  /* The scene scales with the FRAME, not the window — on this page it sits in a column beside the
     copy and is far narrower than the viewport. */
  container-type: inline-size;
  transition: opacity .4s ease;
}

.hero-scene.hd-fading { opacity: 0; }

/* ---------- browser chrome ---------- */

.hd-chrome {
  display: flex;
  align-items: center;
  gap: 0.85cqw;
  padding: 0.9cqw 1.25cqw;
  border-bottom: 1px solid var(--hd-hairline);
  background: var(--hd-chrome-bg);
}

.hd-dot { width: 0.94cqw; height: 0.94cqw; border-radius: 50%; flex-shrink: 0; }
.hd-dot-r { background: #ff5f57; }
.hd-dot-y { background: #febc2e; }
.hd-dot-g { background: #28c840; }

.hd-omni {
  margin-left: 0.9cqw;
  display: inline-flex;
  align-items: center;
  gap: 0.6cqw;
  min-width: 0;
  padding: 0.35cqw 1.1cqw;
  border: 1px solid var(--hd-hairline);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.03);
  font-family: var(--hd-mono);
  font-size: 1.15cqw;
  color: var(--hd-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hd-lock { width: 1.05cqw; height: 1.05cqw; flex-shrink: 0; fill: none; stroke: var(--hd-green); stroke-width: 2; }

.hd-body {
  display: grid;
  grid-template-columns: 57% 43%;
  min-height: 0;
}

/* A pane header, worn by both sides so they read as two panels of one app rather than as two
   screenshots side by side. */
.hd-pane-bar {
  display: flex;
  align-items: center;
  gap: 0.8cqw;
  padding: 0.9cqw 1.4cqw;
  border-bottom: 1px solid var(--hd-hairline);
  font-size: 1.05cqw;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--hd-muted);
  font-weight: 600;
}

.hd-mark { width: 2cqw; height: 2cqw; display: block; flex-shrink: 0; }

.hd-chip {
  margin-left: auto;
  flex-shrink: 0;
  padding: 0.15cqw 0.7cqw;
  border: 1px solid rgba(163, 113, 247, 0.35);
  background: rgba(163, 113, 247, 0.12);
  border-radius: 999px;
  font-size: 0.98cqw;
  letter-spacing: 0.06em;
  color: var(--hd-violet);
}

/* ---------- assistant panel ---------- */

.hd-term {
  background: var(--hd-term-bg);
  border-right: 1px solid var(--hd-hairline);
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.hd-term-body {
  flex: 1;
  padding: 1.35cqw 1.7cqw;
  font-family: var(--hd-mono);
  font-size: 1.55cqw;
  line-height: 1.62;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Every reveal below is written at the SAME specificity as the rule that hides it, plus its own
   class. Hiding through .hero-scene.hd-armed X (three classes) and revealing through X.hd-in (two)
   loses silently: the classes land, the JS runs, and nothing appears — which is exactly what
   shipped for ten minutes.

   Default is the FINISHED scene: with no JavaScript, or before it runs, a visitor sees the whole
   story rather than an empty panel. `hd-armed` is what hides it again so it can be played. */
.hero-scene.hd-armed .hd-line { opacity: 0; }
.hero-scene.hd-armed .hd-line.hd-in { opacity: 1; transition: opacity .18s ease; }

.hd-prompt { display: flex; gap: 0.8cqw; align-items: baseline; }
.hd-chev { color: var(--hd-accent); flex-shrink: 0; }
.hd-typed { color: var(--hd-text); white-space: pre-wrap; }

.hd-caret {
  display: none;
  width: 0.72cqw;
  height: 1.45cqw;
  translate: 0 0.2cqw;
  background: var(--hd-accent);
}
.hero-scene.hd-armed .hd-caret { display: inline-block; animation: hd-blink 1s steps(1) infinite; }
.hero-scene.hd-armed .hd-caret.hd-off { display: none; }
@keyframes hd-blink { 50% { opacity: 0; } }

/* The tool name column is fixed so six calls read as a list rather than as ragged prose — the one
   place in the scene where alignment carries meaning (same tool, same place, every run). */
.hd-tool { display: flex; gap: 0.8cqw; align-items: baseline; min-width: 0; }
.hd-bullet { color: var(--hd-green); flex-shrink: 0; }
.hd-name { color: var(--hd-accent); display: inline-block; min-width: 15cqw; }
.hd-arg { color: var(--hd-muted); }
.hd-ok { color: var(--hd-green); }
.hd-note { color: var(--hd-muted); }
.hd-said { color: var(--hd-text-2); }
.hd-said b { color: var(--hd-text); font-weight: 600; }

/* A call in flight, then its result. Everything landing green at once said "nothing was at stake";
   a beat of amber says work happened — and it did: test_block really runs the block before
   deploy_endpoint is offered. */
.hero-scene.hd-armed .hd-res { opacity: 0; transition: opacity .25s ease; }
.hero-scene.hd-armed .hd-line.hd-done .hd-res { opacity: 1; }
.hd-line.hd-pending .hd-bullet { color: var(--hd-amber); animation: hd-working .7s ease-in-out infinite; }
@keyframes hd-working { 50% { opacity: 0.3; } }

/* The composer never animates and is never hidden: it is the one part of the scene that says what
   a visitor is being invited to do, so it has to be legible in the first frame and in the last. */
.hd-composer {
  margin: 0 1.7cqw 1.5cqw;
  display: flex;
  align-items: center;
  gap: 0.8cqw;
  padding: 0.85cqw 0.9cqw 0.85cqw 1.2cqw;
  border: 1px solid var(--hd-hairline);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.025);
  font-family: var(--hd-mono);
  font-size: 1.3cqw;
  color: var(--hd-muted);
}

.hd-composer-send {
  margin-left: auto;
  flex-shrink: 0;
  width: 2.4cqw;
  height: 2.4cqw;
  border-radius: 7px;
  display: grid;
  place-items: center;
  background: rgba(96, 165, 250, 0.16);
  border: 1px solid rgba(96, 165, 250, 0.32);
  color: var(--hd-accent);
  font-size: 1.3cqw;
  line-height: 1;
}

/* ---------- canvas + what shipped ---------- */

.hd-app { background: var(--hd-bg); display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.hd-canvas {
  position: relative;
  flex: 1;
  min-height: 0;
  border-bottom: 1px solid var(--hd-hairline);
  background-image: linear-gradient(var(--hd-hairline) 1px, transparent 1px),
                    linear-gradient(90deg, var(--hd-hairline) 1px, transparent 1px);
  background-size: 3cqw 3cqw;
  background-position: -1px -1px;
  opacity: 1;
}
.hero-scene.hd-armed .hd-canvas { opacity: 0.55; }
.hero-scene.hd-armed .hd-canvas.hd-lit { opacity: 1; transition: opacity .5s ease; }

/* Positioned as a proportion and centred on that point, so the pair stays composed at any width —
   the link is measured from these, never hard-coded. */
/* A named area behind the blocks — the canvas draws zones between the grid and the blocks, never
   over them, so this sits under both and claims no clicks. */
.hd-zone {
  position: absolute;
  left: 3%;
  right: 3%;
  top: 18%;
  bottom: 22%;
  border: 1px solid color-mix(in srgb, var(--hd-zone) 45%, transparent);
  border-radius: 0.9cqw;
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--hd-zone) 16%, transparent),
              color-mix(in srgb, var(--hd-zone) 5%, transparent));
  pointer-events: none;
}
.hd-zone-mark {
  position: absolute;
  left: 1.2cqw;
  top: 0.8cqw;
  font-size: 1.4cqw;
  color: var(--hd-zone);
}
.hd-zone-name {
  position: absolute;
  left: 3.4cqw;
  top: 0.7cqw;
  font-size: 1.25cqw;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--hd-zone);
}
.hd-zone-sub {
  position: absolute;
  left: 3.4cqw;
  top: 2.3cqw;
  font-size: 1cqw;
  color: var(--hd-text-2);
}
.hero-scene.hd-armed .hd-zone { opacity: 0; }
.hero-scene.hd-armed .hd-zone.hd-in { opacity: 1; transition: opacity .4s ease; }

/* Blocks are CARDS, not circles: an icon saying which kind of thing this is, and the label INSIDE
   rather than floating above it. The canvas stopped drawing round nodes when labels stopped fitting
   beside them — a hero showing the old shape is a hero showing another product. */
.hd-node {
  position: absolute;
  top: 58%;
  translate: -50% -50%;
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  padding: 0.6cqw 0.8cqw;
  border: 1px solid color-mix(in srgb, var(--hd-node-accent) 55%, transparent);
  border-radius: 0.7cqw;
  background: rgba(13, 18, 30, 0.94);
  color: var(--hd-text-1);
  font-size: 1.1cqw;
  white-space: nowrap;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
}
.hero-scene.hd-armed .hd-node { transform: scale(0.86); opacity: 0; }
.hero-scene.hd-armed .hd-node.hd-in {
  transform: scale(1);
  opacity: 1;
  transition: transform .32s cubic-bezier(.2, 1.3, .4, 1), opacity .2s ease;
}
.hd-node-icon {
  display: grid;
  place-items: center;
  width: 2cqw;
  height: 2cqw;
  border-radius: 0.35cqw;
  background: color-mix(in srgb, var(--hd-node-accent) 22%, transparent);
  color: var(--hd-node-accent);
  font-size: 1.1cqw;
}
.hd-node-label { font-family: var(--hd-mono); }
/* Outlined rather than filled, like the canvas: a badge is a footnote on a card, not a second card. */
.hd-node-badge {
  padding: 0.15cqw 0.45cqw;
  border: 1px solid color-mix(in srgb, var(--hd-node-accent) 45%, transparent);
  border-radius: 0.3cqw;
  background: color-mix(in srgb, var(--hd-node-accent) 14%, transparent);
  color: var(--hd-node-accent);
  font-family: var(--hd-mono);
  font-size: 0.9cqw;
  letter-spacing: 0.06em;
}

/* The type colours the canvas uses: sky for a schedule, green for an endpoint. Positions live here
   rather than inline on the elements, so a narrower frame can move them — an inline `left` wins
   against every container query that tries. */
.hd-node-in { --hd-node-accent: #38bdf8; left: 25%; }
.hd-node-out { --hd-node-accent: #22c55e; left: 74%; }

/* No viewBox: the nodes are laid out in CSS pixels, so the link is drawn in the same coordinate
   space and its geometry is measured from them at runtime. */
.hd-wire { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.hd-wire-base { stroke: #64748b; stroke-width: 2; fill: none; }
.hero-scene.hd-armed .hd-wire-base { stroke-dasharray: 200; stroke-dashoffset: 200; }
.hero-scene.hd-armed .hd-wire-base.hd-in { stroke-dashoffset: 0; transition: stroke-dashoffset .45s ease; }

/* The real canvas animates dashed arrows along its links; this is what makes two circles read as
   a flow rather than as two circles. */
.hd-wire-flow {
  stroke: var(--hd-accent);
  stroke-width: 2.4;
  fill: none;
  stroke-dasharray: 6 9;
  opacity: 0.95;
  animation: hd-flow .9s linear infinite;
}
.hero-scene.hd-armed .hd-wire-flow { opacity: 0; animation: none; }
.hero-scene.hd-armed .hd-wire-flow.hd-in { opacity: 0.95; animation: hd-flow .9s linear infinite; transition: opacity .3s ease; }
@keyframes hd-flow { to { stroke-dashoffset: -14; } }

/* A stub whose only job is to carry the arrowhead, painted after everything else: on the base line
   the head sat under the travelling dashes and under the node, and the link read as a plain rule. */
.hd-wire-head { stroke: none; fill: none; }
.hero-scene.hd-armed .hd-wire-head { opacity: 0; }
.hero-scene.hd-armed .hd-wire-head.hd-in { opacity: 1; transition: opacity .25s ease; }

.hd-shipped { padding: 1.1cqw 1.4cqw 1.3cqw; display: flex; flex-direction: column; gap: 0.7cqw; min-width: 0; }

.hd-ep-head {
  font-size: 1.02cqw;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--hd-muted);
  font-weight: 600;
}

.hd-ep {
  display: flex;
  align-items: center;
  gap: 0.7cqw;
  min-width: 0;
  padding: 0.8cqw 0.95cqw;
  border: 1px solid var(--hd-hairline);
  border-radius: 8px;
  background: var(--hd-elevated);
}
.hero-scene.hd-armed .hd-ep { opacity: 0; translate: 0 8px; }
.hero-scene.hd-armed .hd-ep.hd-in { opacity: 1; translate: 0 0; transition: opacity .3s ease, translate .3s ease; }

/* The point of the whole scene is this line arriving. It gets a beat of its own. */
.hd-ep.hd-landed { animation: hd-land 1.4s ease-out; }
@keyframes hd-land {
  0%   { box-shadow: 0 0 0 0 rgba(63, 185, 80, 0.45); border-color: rgba(63, 185, 80, 0.65); }
  100% { box-shadow: 0 0 0 16px rgba(63, 185, 80, 0); border-color: var(--hd-hairline); }
}

.hd-verb {
  font-family: var(--hd-mono);
  font-size: 1cqw;
  font-weight: 700;
  color: var(--hd-green);
  border: 1px solid rgba(63, 185, 80, 0.35);
  background: rgba(63, 185, 80, 0.1);
  padding: 0.1cqw 0.45cqw;
  border-radius: 4px;
  flex-shrink: 0;
}
.hd-verb-clock {
  color: var(--hd-violet);
  border-color: rgba(163, 113, 247, 0.35);
  background: rgba(163, 113, 247, 0.12);
}

.hd-url {
  font-family: var(--hd-mono);
  font-size: 1.22cqw;
  color: var(--hd-text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.hd-live {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.45cqw;
  font-size: 1cqw;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--hd-green);
}
.hd-live-blue { color: var(--hd-accent); }
.hd-live-blue .hd-pulse { background: var(--hd-accent); }

.hd-pulse {
  width: 0.58cqw;
  height: 0.58cqw;
  border-radius: 50%;
  background: var(--hd-green);
  animation: hd-pulse 1.8s ease-in-out infinite;
}
@keyframes hd-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* The footnote is the SEO half of the story: the platform wrote these, nobody maintains them. */
.hd-foot {
  font-family: var(--hd-mono);
  font-size: 1.02cqw;
  color: var(--hd-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hd-foot .hd-ok { color: var(--hd-green); }
.hero-scene.hd-armed .hd-foot { opacity: 0; }
.hero-scene.hd-armed .hd-foot.hd-in { opacity: 1; transition: opacity .3s ease; }

/* A CONTAINER query, not a viewport one: what is narrow here is the frame. Keyed to the viewport,
   this would fire on a phone and never on the 700px slot it was written for — the same mistake
   that left the version-history title breaking one character per line. */
@container (max-width: 720px) {
  .hd-term-body { font-size: 2.05cqw; line-height: 1.55; }
  .hd-name { min-width: 19cqw; }
  .hd-omni, .hd-pane-bar { font-size: 1.42cqw; }
  .hd-chip { font-size: 1.25cqw; }
  .hd-composer { font-size: 1.7cqw; }
  .hd-url { font-size: 1.6cqw; }
  .hd-ep-head, .hd-verb, .hd-live, .hd-foot { font-size: 1.35cqw; }
  /* The cards do NOT grow with the rest of the type here: the canvas pane is 43% of the frame,
     and two cards sized like the prose collide in the middle of it. Width wins, so the badge
     goes — the label already says what the block is. */
  .hd-node { font-size: 1.25cqw; gap: 0.5cqw; padding: 0.55cqw 0.7cqw; }
  .hd-node-icon { width: 1.7cqw; height: 1.7cqw; font-size: 1cqw; }
  .hd-node-badge { display: none; }
  .hd-node-in { left: 25%; }
  .hd-node-out { left: 73%; }
  .hd-zone-name { font-size: 1.45cqw; }
  .hd-zone-sub { font-size: 1.2cqw; }
}

/* Below this the two panes cannot both hold their content side by side — and everything sized in
   cqw shrinks with the frame, so on a phone the scene was rendering at SEVEN pixels: present,
   pretty, and unreadable. Stack the panes and raise the type off the container floor. The frame
   itself grows taller to pay for it (`.video-container` aspect-ratio, landing.css). */
@container (max-width: 460px) {
  /* `auto` for the shipped list rather than a percentage: it is sized by its own three rows, and a
     split guessed as a fraction is what left the nodes sitting on top of their own pane header. */
  .hd-body { grid-template-columns: 1fr; grid-template-rows: minmax(0, 1fr) auto; }
  .hd-term { border-right: none; border-bottom: 1px solid var(--hd-hairline); }

  /* The canvas is the decorative half of the right pane and the shipped list is the payoff — a
     live address, a stream and a cron line. At this width only one of them fits, so the canvas
     goes, and with it the pane header that only labelled it. */
  .hd-canvas,
  .hd-app > .hd-pane-bar { display: none; }

  .hd-term-body { font-size: 3.05cqw; line-height: 1.5; padding: 2.4cqw 3cqw; }
  /* The tool-name column buys alignment at the cost of width; at this size width wins. */
  .hd-name { min-width: 0; }
  .hd-dot { width: 1.7cqw; height: 1.7cqw; }
  .hd-omni, .hd-pane-bar { font-size: 2.45cqw; }
  .hd-chip { font-size: 2.2cqw; }
  .hd-mark { width: 3.6cqw; height: 3.6cqw; }
  .hd-caret { width: 1.5cqw; height: 2.9cqw; }
  .hd-url { font-size: 2.7cqw; }
  .hd-ep-head, .hd-verb, .hd-live, .hd-foot { font-size: 2.3cqw; }
  .hd-shipped { padding: 2cqw 2.6cqw 2.4cqw; gap: 1.3cqw; }
  .hd-ep { padding: 1.5cqw 1.8cqw; }
  /* The composer's job is to say "you type here". On a phone the signup button says it louder and
     is two thumb-widths away, so the room goes to the transcript instead. */
  .hd-composer { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .hd-caret,
  .hd-pulse,
  .hd-wire-flow,
  .hd-wire-flow.hd-in,
  .hd-line.hd-pending .hd-bullet { animation: none; }
  .hd-ep.hd-landed { animation: none; }
  .hero-scene { transition: none; }
}
