/* The marketing page's layout. Colours, type, radii and components come from brand/. */

/* The page is the backdrop (pure black), so its windows and cards read as lit. */
:root {
  --openbelt-color-neutral: var(--openbelt-color-backdrop);
}

body {
  overflow-x: clip;
}

main > section,
footer {
  width: min(1080px, 100% - 48px);
  margin-inline: auto;
}

/* The header stays at the top as the page scrolls; its translucent paper runs edge to edge. */
html {
  scroll-padding-top: 64px;
}

.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  height: 64px;
  padding-inline: max(24px, (100% - 1080px) / 2);
  background: color-mix(in srgb, var(--openbelt-color-neutral) 80%, transparent);
  backdrop-filter: blur(12px);
}

/* The header's links are quiet pills, their text lined up with the content's right edge. */
.nav nav {
  display: flex;
  align-items: center;
  gap: var(--openbelt-space-2xs);
  margin-right: -10px;
}

.nav nav a:not(.btn) {
  padding: 6px 10px;
  border-radius: var(--openbelt-radius-sm);
  color: var(--openbelt-color-muted);
  text-decoration: none;
}

/* Sections: 192px apart (two 96px paddings), headings left aligned and 16px from their line. */
main > section:not(.hero, .stage) {
  padding-block: var(--openbelt-space-4xl);
}

/* Below 1200px the lowest pair would reach the prompt box, so they go first. */
@media (max-width: 1200px) {
  .mark.low {
    display: none;
  }
}

/* The hero, centred: the headline, one line, and Copy prompt. */
/* It fills the first screen but for the demo's top, which peeks up from the fold, up to 800px: on a
   taller screen (or zoomed out) it stops growing, so the headline, its icons and the demo stay
   together instead of drifting apart. */
.hero {
  --peek: 160px;

  position: relative;
  isolation: isolate;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--openbelt-space-lg);
  min-height: min(calc(100svh - 64px - var(--peek)), 800px);
  padding: var(--openbelt-space-3xl) 0 var(--openbelt-space-2xl);
  text-align: center;
}

/* Marks of the apps your tools reach (Gmail, GitHub, Linear…), floating around the hero. Each flies in, then drifts on its own
   slow loop; the pointer nudges them by depth (site.js). Decoration only. The bottom pair sits a
   set distance above the hero's bottom (--y: calc(100% - …)), so a taller or shorter hero never
   pushes them onto the demo. Below 960px the headline is too wide for them, so they go. */
.marks {
  --px: 0px;
  --py: 0px;
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.mark {
  position: absolute;
  top: var(--y);
  left: calc(50% + var(--x));
  width: var(--s);
  height: var(--s);
  margin-left: calc(var(--s) / -2);
  translate: calc(var(--px) * var(--depth)) calc(var(--py) * var(--depth));
  transition: translate 600ms var(--openbelt-ease);
}

.mark-card {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  transform: rotate(var(--rot));
  animation:
    mark-in 1s var(--openbelt-ease) var(--d) both,
    mark-drift var(--dur) ease-in-out calc(var(--d) + 1s) infinite;
}

.marks.resting .mark-card {
  animation-play-state: running, paused;
}

/* The logo alone, no tile behind it. */
.mark-card img {
  width: 64%;
  height: 64%;
}

@keyframes mark-in {
  from {
    opacity: 0;
    transform: translate(var(--fx), var(--fy)) rotate(calc(var(--rot) + 24deg)) scale(0.6);
  }

  to {
    opacity: 1;
    transform: rotate(var(--rot));
  }
}

@keyframes mark-drift {
  0%,
  100% {
    transform: rotate(var(--rot));
  }

  50% {
    transform: translate(var(--dx), var(--dy)) rotate(calc(var(--rot) + var(--wob)));
  }
}

@media (prefers-reduced-motion: reduce) {
  .mark-card {
    animation: none;
  }

  .mark {
    translate: none;
  }
}

.hero h1 {
  font: var(--openbelt-type-hero);
  font-size: clamp(48px, 8vw, 104px);
  letter-spacing: var(--openbelt-tracking-hero);
}

.lede {
  max-width: 56ch;
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-body-lg);
}

.hero .lede {
  font-size: clamp(18px, 1.6vw, 21px);
}

/* Each sentence starts its own line, so neither breaks across the other's. */
.hero .lede span {
  display: block;
  text-wrap: balance;
}

/* Copy prompt: a squircle slab with the agents' marks in it, the hero's one control. The marks sit
   close and tilted like stickers; under a pointer they spread, straighten and take their colours.
   A press sinks it; a copy pops it and swaps the label for Copied, centred, at the same width. */
.copy-prompt {
  position: relative;
  display: inline-grid;
  place-items: center;
  height: 60px;
  margin-top: var(--openbelt-space-xs);
  padding: 0 26px 0 22px;
  border-radius: var(--openbelt-radius-full);
  corner-shape: squircle;
  background: var(--openbelt-color-primary);
  box-shadow:
    inset 0 -2px 0 color-mix(in srgb, var(--openbelt-color-neutral) 10%, transparent),
    0 10px 30px -12px color-mix(in srgb, var(--openbelt-color-primary) 22%, transparent);
  color: var(--openbelt-color-on-primary);
  font: 550 17px/1 var(--openbelt-font-body);
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 0.25s var(--openbelt-ease),
    box-shadow 0.2s var(--openbelt-ease),
    background-color 0.15s var(--openbelt-ease);
}

.copy-idle,
.copy-done {
  grid-area: 1 / 1;
  display: inline-flex;
  align-items: center;
  transition:
    opacity 0.2s,
    transform 0.35s var(--openbelt-ease),
    filter 0.2s;
}

.copy-idle {
  gap: var(--openbelt-space-md);
}

.copy-done {
  opacity: 0;
  filter: blur(3px);
  transform: translateY(10px);
}

.copy-prompt.copied .copy-idle {
  opacity: 0;
  filter: blur(3px);
  transform: translateY(-10px);
}

.copy-prompt.copied .copy-done {
  opacity: 1;
  filter: none;
  transform: none;
}

.copy-prompt.copied {
  animation: copy-pop 0.45s var(--openbelt-ease);
}

@keyframes copy-pop {
  0% {
    transform: scale(0.96);
  }

  45% {
    transform: scale(1.03);
  }
}

.copy-marks {
  display: inline-flex;
  gap: var(--openbelt-space-2xs);
  transition: gap 0.3s var(--openbelt-ease);
}

/* Each mark is its SVG as a mask over the button's ink, so one file serves every colour. */
.copy-marks i {
  width: 22px;
  height: 22px;
  background: currentcolor;
  mask: var(--mark) center / contain no-repeat;
  transform: rotate(-7deg);
  transition:
    transform 0.3s var(--openbelt-ease),
    background-color 0.2s;
}

.copy-marks i:nth-child(even) {
  transform: rotate(7deg) translateY(1px);
}

/* After a copy, what to do with it; its line is kept empty until then, so nothing moves. */
.copy-next {
  display: inline-flex;
  align-items: center;
  gap: var(--openbelt-space-xs);
  min-height: 24px;
  margin-top: calc(var(--openbelt-space-xs) * -1);
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-body-md);
}

.copy-next .icon {
  color: var(--openbelt-color-success);
}

.copy-next:not(:empty) {
  animation: copy-next-in 0.45s var(--openbelt-ease);
}

@keyframes copy-next-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

/* Without the floating marks (below 960px) the hero sits at the top instead of filling the first
   screen, which left a gap above and below it. */
@media (max-width: 960px) {
  .hero {
    min-height: 0;
    padding: var(--openbelt-space-3xl) 0 var(--openbelt-space-2xl);
  }
}

/* A phone: the headline grows with the width so it stays two lines from 320px up, the lede flows
   as one paragraph, and the button spans the column. */
@media (max-width: 720px) {
  .hero {
    gap: var(--openbelt-space-md);
    padding: var(--openbelt-space-2xl) 0 var(--openbelt-space-xl);
  }

  .hero h1 {
    font-size: clamp(38px, 12.4vw, 60px);
    line-height: 1.02;
  }

  .hero .lede {
    max-width: 34ch;
    font-size: 16px;
    text-wrap: balance;
  }

  .hero .lede span {
    display: inline;
  }

  .copy-prompt {
    width: 100%;
    height: 56px;
    margin-top: var(--openbelt-space-2xs);
    font-size: 16px;
  }

  .copy-marks i {
    width: 19px;
    height: 19px;
  }

  .copy-next {
    min-height: 20px;
    margin-top: calc(var(--openbelt-space-2xs) * -1);
    font: var(--openbelt-type-body-sm);
    font-size: 13px;
  }
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--openbelt-space-sm);
}

/* The demo, under the prompt: one app, two people, two agents. Jun builds it in Codex, Ana changes
   it the next day in Claude Code, and both point at the same browser. Each agent is its own terminal
   window, titled by the tool the way macOS titles it, so it reads as your agent and not OpenBelt's. */
main > section.stage {
  padding-block: 0 var(--openbelt-space-4xl);
}

.demo {
  display: grid;
  grid-template-columns: minmax(0, 5fr) 76px minmax(0, 7fr);
  grid-template-rows: auto auto;
  row-gap: var(--openbelt-space-lg);
  align-items: center;
}

.demo .s1 {
  grid-area: 1 / 1;
}

.demo .s2 {
  grid-area: 2 / 1;
}

.demo .r1 {
  grid-area: 1 / 2;
}

.demo .r2 {
  grid-area: 2 / 2;
}

.demo .rm {
  display: none;
}

.demo .app-window {
  grid-area: 1 / 3 / 3 / 4;
  align-self: stretch;
}

/* A window: one border, a quiet bar. */
.window {
  overflow: hidden;
  border: 1px solid var(--openbelt-color-border-strong);
  border-radius: var(--openbelt-radius-lg);
  background: var(--openbelt-color-surface);
}

.window-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 12px;
  border-bottom: 1px solid var(--openbelt-color-border);
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-body-sm);
}

.lights {
  display: flex;
  flex: none;
  gap: 6px;
}

.lights i {
  width: 9px;
  height: 9px;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-border-strong);
}

/* An agent's window: its name in the middle of the bar, whose machine it is on the right. */
.agent-window {
  background: var(--openbelt-color-neutral);
  transition: opacity 0.5s var(--openbelt-ease);
}

.agent-window .window-bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  background: var(--openbelt-color-surface);
}

.agent-window.idle {
  opacity: 0.4;
}

.who {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--openbelt-color-primary);
  font: var(--openbelt-type-label);
  font-size: 14px;
  white-space: nowrap;
}

.who img {
  width: 16px;
  height: 16px;
}

.by {
  display: inline-flex;
  justify-self: end;
  align-items: center;
  gap: 8px;
}

.by img {
  width: 24px;
  height: 24px;
  border-radius: var(--openbelt-radius-sm);
  image-rendering: pixelated;
}

.url {
  display: inline-flex;
  flex: 1;
  align-items: center;
  gap: 6px;
  min-width: 0;
  height: 24px;
  margin-left: 4px;
  padding: 0 8px;
  border-radius: var(--openbelt-radius-sm);
  background: var(--openbelt-color-subtle);
  font: var(--openbelt-type-mono-sm);
  font-size: 11px;
  white-space: nowrap;
}

.url .icon {
  width: 11px;
  height: 11px;
}

/* The agent's side: the prompt, then one line saying what it's doing, then where it's live. */
.terminal {
  display: grid;
  gap: 10px;
  padding: 18px 20px;
  font: var(--openbelt-type-mono-sm);
  font-size: 13px;
}

.t-prompt {
  display: flex;
  gap: 10px;
  min-height: 20px;
  color: var(--openbelt-color-primary);
}

.t-prompt::before {
  color: var(--openbelt-color-muted);
  content: ">";
}

.t-cursor {
  display: none;
  width: 7px;
  height: 15px;
  margin-left: 2px;
  vertical-align: -3px;
  background: var(--openbelt-color-primary);
}

.typing .t-cursor {
  display: inline-block;
}

.t-status {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 18px;
  color: var(--openbelt-color-primary);
  font-size: 12px;
}

.t-status .icon {
  width: 12px;
  height: 12px;
  color: var(--openbelt-color-success);
  stroke-width: 2.5;
}

.t-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.t-spin {
  display: none;
  flex: none;
  width: 11px;
  height: 11px;
  border: 1.5px solid var(--openbelt-color-border-strong);
  border-top-color: var(--openbelt-color-primary);
  border-radius: var(--openbelt-radius-full);
}

.t-status.working {
  color: var(--openbelt-color-muted);
}

.t-status.working .t-spin {
  display: block;
}

.t-status.working .icon,
.t-status.blank > * {
  display: none;
}

/* The relay: dots between an agent and the browser. While the agent ships, light runs along them
   toward the browser; at rest they're a faint dotted line. */
.relay {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
}

.relay i {
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-border-strong);
  transition: background-color 0.4s var(--openbelt-ease);
}

.relay i:first-child,
.relay i:last-child {
  width: 8px;
  height: 8px;
  border: 1px solid var(--openbelt-color-border-strong);
  background: var(--openbelt-color-backdrop);
}

.relay.arrived i:last-child {
  border-color: var(--openbelt-color-primary);
  background: var(--openbelt-color-primary);
}

/* The app: open support tickets grouped by theme, from Zendesk; once Ana's change is live, each
   theme also names the Sentry error behind it. */
.app {
  padding: 22px 24px 24px;
  transition:
    opacity 0.5s var(--openbelt-ease),
    filter 0.5s var(--openbelt-ease);
}

.app.empty {
  opacity: 0;
  filter: blur(6px);
}

.app-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}

.app-icon {
  display: grid;
  flex: none;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--openbelt-radius-md);
  background: var(--openbelt-color-primary);
  color: var(--openbelt-color-on-primary);
}

.app-icon .icon {
  width: 18px;
  height: 18px;
}

.app-title {
  flex: 1;
  min-width: 0;
}

.app-title b {
  display: block;
  font: var(--openbelt-type-h4);
  font-size: 20px;
  letter-spacing: var(--openbelt-tracking-h4);
}

.app-title small {
  display: block;
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-body-sm);
}

.sources {
  display: flex;
  flex: none;
  gap: 6px;
}

.source {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0 10px 0 8px;
  border: 1px solid var(--openbelt-color-border-strong);
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-neutral);
  font: var(--openbelt-type-label);
  font-size: 12px;
}

.source img {
  width: 13px;
  height: 13px;
}

.themes {
  display: grid;
  gap: 8px;
}

.theme {
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--openbelt-color-border);
  border-radius: var(--openbelt-radius-lg);
  background: var(--openbelt-color-neutral);
}

.theme-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.theme-top b {
  min-width: 0;
  font: var(--openbelt-type-label);
  font-size: 14px;
}

.theme-top span {
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-mono-sm);
  white-space: nowrap;
}

.meter {
  height: 6px;
  overflow: hidden;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-subtle);
}

.meter i {
  display: block;
  transform-origin: left;
  width: var(--w);
  height: 100%;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-muted);
}

.trace {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-mono-sm);
  font-size: 11.5px;
}

.trace img {
  width: 13px;
  height: 13px;
}

.trace b {
  color: var(--openbelt-color-error);
  font-weight: 500;
}

/* Before Ana's change, Sentry's parts keep their room but don't show, so nothing moves. */
.demo:not(.linked) .sentry,
.demo:not(.linked) .trace {
  visibility: hidden;
}

/* What's new lights up for a moment. */
.lit {
  animation: lit 2.4s var(--openbelt-ease);
}

@keyframes lit {
  0%,
  30% {
    border-color: var(--openbelt-color-highlight);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .t-cursor {
    animation: blink 1s steps(1) infinite;
  }

  .t-spin {
    animation: spin 0.8s linear infinite;
  }

  .relay.sending i:not(:first-child, :last-child) {
    animation: relay 1.1s ease-in-out infinite;
    animation-delay: calc(var(--i) * 0.11s);
  }

  .relay.sending i:first-child {
    border-color: var(--openbelt-color-primary);
    background: var(--openbelt-color-primary);
  }
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes relay {
  0%,
  100% {
    background: var(--openbelt-color-border-strong);
    transform: none;
  }

  30% {
    background: var(--openbelt-color-primary);
    transform: scale(1.6);
  }

  60% {
    background: var(--openbelt-color-border-strong);
    transform: none;
  }
}

/* On a tablet or phone the windows stack: both agents, one relay down into the app. */
@media (max-width: 960px) {
  .demo {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    row-gap: 8px;
  }

  .demo .s1,
  .demo .s2,
  .demo .app-window {
    grid-area: auto;
  }

  .demo .r1,
  .demo .r2 {
    display: none;
  }

  .demo .rm {
    display: flex;
    flex-direction: column;
    gap: 5px;
    height: 36px;
  }
}

@media (max-width: 720px) {
  .window-bar {
    height: 34px;
  }

  .by span {
    display: none;
  }

  .by img {
    width: 22px;
    height: 22px;
  }

  .terminal {
    gap: 6px;
    padding: 12px 14px;
    font-size: 12px;
  }

  .app {
    padding: 14px;
  }

  .app-head {
    gap: 10px;
    margin-bottom: 10px;
  }

  .app-icon {
    width: 28px;
    height: 28px;
  }

  .app-icon .icon {
    width: 15px;
    height: 15px;
  }

  .app-title b {
    font-size: 17px;
  }

  /* The sources keep their marks; their names go. */
  .source {
    width: 26px;
    padding: 0;
    justify-content: center;
    font-size: 0;
  }

  .theme {
    gap: 6px;
    padding: 10px 12px;
  }

  .theme-top b {
    font-size: 13px;
  }
}

/* The narrowest phones: the longest prompt still takes one line. */
@media (max-width: 380px) {
  .terminal {
    font-size: 11px;
  }
}

/* A section's lede under its heading. */
.works .intro,
.pieces .intro,
.story .intro {
  max-width: 64ch;
  margin-top: var(--openbelt-space-md);
  font: var(--openbelt-type-body-lg);
}

/* The story: a minute-long film, its poster until someone presses play. It never plays by itself:
   it's narrated. Its controls sit in a bar under the frame, never over the film's captions. */
.film {
  margin: var(--openbelt-space-2xl) 0 0;
}

.film-frame {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--openbelt-color-border);
  border-radius: var(--openbelt-radius-lg);
  background: var(--openbelt-color-surface);
  aspect-ratio: 16 / 9;
}

.film video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.film-play {
  position: absolute;
  left: var(--openbelt-space-lg);
  bottom: var(--openbelt-space-lg);
  display: inline-flex;
  align-items: center;
  gap: var(--openbelt-space-sm);
  height: 52px;
  padding: 0 var(--openbelt-space-lg) 0 6px;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-on-primary);
  color: var(--openbelt-color-primary);
  font: var(--openbelt-type-label);
  font-size: 15px;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.16s var(--openbelt-ease),
    transform 0.16s var(--openbelt-ease),
    opacity 0.3s var(--openbelt-ease);
}

.film-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-primary);
  color: var(--openbelt-color-on-primary);
}

.film-icon .icon {
  width: 16px;
  height: 16px;
  margin-left: 2px;
  fill: currentColor;
}

.film-time {
  color: var(--openbelt-color-muted);
  font-weight: 400;
}

@media (hover: hover) {
  .film-play:hover {
    background: color-mix(
      in srgb,
      var(--openbelt-color-on-primary) 86%,
      var(--openbelt-color-primary)
    );
  }
}

.film-play:active {
  transform: scale(0.96);
  transition-duration: 0.06s;
}

/* Once it starts, the big button goes for good and the bar runs it. */
.film.started .film-play {
  opacity: 0;
  pointer-events: none;
}

.film.started video {
  cursor: pointer;
}

/* The bar: play, the time, the seek line, sound, full screen. Hidden (but its room kept) until the
   film starts, so nothing below moves. Every button is a 44px target, for thumbs. */
.film-bar {
  display: flex;
  align-items: center;
  gap: var(--openbelt-space-xs);
  margin-top: var(--openbelt-space-xs);
  visibility: hidden;
  opacity: 0;
  transition:
    opacity 0.3s var(--openbelt-ease),
    visibility 0s 0.3s;
}

.film.started .film-bar {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.3s var(--openbelt-ease);
}

.film-bar button {
  display: grid;
  flex: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--openbelt-radius-full);
  color: var(--openbelt-color-primary);
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.16s var(--openbelt-ease),
    transform 0.16s var(--openbelt-ease);
}

.film-bar button:focus-visible {
  outline: 2px solid var(--openbelt-color-primary);
  outline-offset: -4px;
}

/* The icons line up with the frame's edges; the 44px targets reach past them. */
.film-toggle {
  margin-left: -13px;
}

.film-full {
  margin-right: -13px;
}

.film-bar .icon {
  width: 18px;
  height: 18px;
}

.film-toggle .icon {
  fill: currentColor;
}

.film-toggle .pause,
.film.playing .film-toggle .play,
.film-mute .off,
.film.muted .film-mute .on {
  display: none;
}

.film.playing .film-toggle .pause,
.film.muted .film-mute .off {
  display: block;
}

@media (hover: hover) {
  .film-bar button:hover {
    background: var(--openbelt-color-subtle);
  }
}

.film-bar button:active {
  transform: scale(0.92);
  transition-duration: 0.06s;
}

.film-clock {
  flex: none;
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-mono-sm);
  font-variant-numeric: tabular-nums;
}

.film-now {
  color: var(--openbelt-color-primary);
}

/* The seek line: 4px to see, the whole 44px row to grab. */
.film-seek {
  --p: 0%;
  flex: 1;
  min-width: 0;
  height: 44px;
  margin: 0 var(--openbelt-space-xs);
  background: transparent;
  cursor: pointer;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
}

.film-seek::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--openbelt-radius-full);
  background: linear-gradient(
    to right,
    var(--openbelt-color-primary) var(--p),
    var(--openbelt-color-border-strong) var(--p)
  );
}

.film-seek::-moz-range-track {
  height: 4px;
  border-radius: var(--openbelt-radius-full);
  background: linear-gradient(
    to right,
    var(--openbelt-color-primary) var(--p),
    var(--openbelt-color-border-strong) var(--p)
  );
}

.film-seek::-webkit-slider-thumb {
  width: 14px;
  height: 14px;
  margin-top: -5px;
  border: 0;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-primary);
  appearance: none;
  transition: transform 0.16s var(--openbelt-ease);
}

.film-seek::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 0;
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-primary);
}

.film-seek:active::-webkit-slider-thumb {
  transform: scale(1.3);
}

/* Phones: the seek line gets the whole width on its own row, the buttons sit under it. */
@media (max-width: 560px) {
  .film-bar {
    flex-wrap: wrap;
    gap: 0;
  }

  .film-seek {
    order: -1;
    flex-basis: 100%;
    margin: 0;
    height: 28px;
  }

  .film-clock {
    margin-right: auto;
  }
}

/* How it fits: the words on the left, the orbit on the right. */
.flow {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: center;
  gap: var(--openbelt-space-2xl);
}

.flow .text {
  display: grid;
  gap: var(--openbelt-space-md);
  align-content: start;
}

.flow .text p {
  font: var(--openbelt-type-body-lg);
}

/* The orbit: OpenBelt in the middle, its pieces turning slowly on the inner ring, your agents and tools
   on the outer one. Laid out in a 600x420 box; everything is sized in cqw so it scales as one. */
.orbit {
  position: relative;
  width: 100%;
  aspect-ratio: 600 / 420;
  container-type: inline-size;
}

.orbit-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.orbit .ring {
  fill: none;
  stroke: var(--openbelt-color-border);
  stroke-dasharray: 2 5;
  vector-effect: non-scaling-stroke;
}

.orbit .ring.inner {
  stroke: var(--openbelt-color-border-strong);
  stroke-dasharray: none;
  opacity: 0.6;
}

.orbit .spoke {
  fill: none;
  stroke: var(--openbelt-color-border);
  vector-effect: non-scaling-stroke;
}

/* A light along each spoke, toward OpenBelt: from your agents and from your tools. */
.orbit .beam {
  fill: none;
  stroke: var(--openbelt-color-primary);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-dasharray: 14 86;
  stroke-dashoffset: 14;
  vector-effect: non-scaling-stroke;
  opacity: 0;
  filter: drop-shadow(0 0 3px color-mix(in srgb, var(--openbelt-color-primary) 55%, transparent));
}

.orbit-node,
.orbit-core {
  position: absolute;
  transform: translate(-50%, -50%);
}

.orbit-node {
  display: grid;
  place-items: center;
  width: 9cqw;
  height: 9cqw;
  border: 1px solid var(--openbelt-color-border);
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-neutral);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--openbelt-color-on-primary) 35%, transparent);
}

.orbit-node img {
  width: 4.2cqw;
  height: 4.2cqw;
}

.orbit-core {
  top: 47.62%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 15cqw;
  height: 15cqw;
  border-radius: var(--openbelt-tile-radius);
  background: var(--openbelt-color-primary);
  color: var(--openbelt-color-on-primary);
  box-shadow:
    0 0 0 1.4cqw color-mix(in srgb, var(--openbelt-color-primary) 4%, transparent),
    0 0 60px color-mix(in srgb, var(--openbelt-color-primary) 12%, transparent);
}

.orbit-core .slot {
  font-size: 7cqw;
}

/* Each piece hangs off a zero-size pivot at the centre, turned to its place (--start); the piece
   turns back by the same amount, so its icon stays upright. */
.orbit-piece {
  position: absolute;
  top: 47.62%;
  left: 50%;
  width: 0;
  height: 0;
  rotate: var(--start);
}

.orbit-piece > span {
  position: absolute;
  top: calc(-15.33cqw - 3.2cqw);
  left: -3.2cqw;
  display: grid;
  place-items: center;
  width: 6.4cqw;
  height: 6.4cqw;
  border: 1px solid var(--openbelt-color-border-strong);
  border-radius: var(--openbelt-radius-full);
  background: var(--openbelt-color-surface);
  color: var(--openbelt-color-primary);
  rotate: calc(-1 * var(--start));
}

.orbit-piece .icon {
  width: 2.8cqw;
  height: 2.8cqw;
}

@media (prefers-reduced-motion: no-preference) {
  .orbit .beam {
    opacity: 0.9;
    animation: orbit-beam 3.2s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  }

  .orbit-piece {
    animation: orbit-turn 60s linear infinite;
  }

  .orbit-piece > span {
    animation: orbit-upright 60s linear infinite;
  }
}

@keyframes orbit-beam {
  to {
    stroke-dashoffset: -86;
  }
}

@keyframes orbit-turn {
  from {
    rotate: var(--start);
  }

  to {
    rotate: calc(var(--start) + 360deg);
  }
}

@keyframes orbit-upright {
  from {
    rotate: calc(-1 * var(--start));
  }

  to {
    rotate: calc(-1 * var(--start) - 360deg);
  }
}

/* The logo rows keep 26px under themselves for the names shown on hover, so the section ends 96px
   below their marks like every other. */
main > section.works {
  padding-bottom: calc(var(--openbelt-space-4xl) - 26px);
}

/* Connect once: each row is a label and a strip of marks in their own colours, nameless until pointed at. site.js
   doubles each strip and sets it moving; without it, or for people who'd rather have less motion,
   the strip stays still and scrolls sideways. */
.ledger-row {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  align-items: center;
  gap: var(--openbelt-space-lg);
  margin-top: var(--openbelt-space-lg);
}

.works .intro + .ledger-row {
  margin-top: var(--openbelt-space-2xl);
}

.ledger-row h3 {
  font: var(--openbelt-type-h5);
  letter-spacing: var(--openbelt-tracking-h5);
}

.ledger-row small {
  display: block;
  margin-top: 2px;
  color: var(--openbelt-color-muted);
  font: var(--openbelt-type-body-md);
}

.marquee {
  overflow-x: auto;
  padding-block: 6px 26px;
  scrollbar-width: none;
  mask-image: linear-gradient(90deg, transparent, black 8%, black 92%, transparent);
}

.marquee::-webkit-scrollbar {
  display: none;
}

.marquee ul {
  display: flex;
  gap: var(--openbelt-space-2xl);
  width: max-content;
  margin: 0;
  padding: 0 var(--openbelt-space-2xl);
  list-style: none;
}

.marquee li {
  position: relative;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
}

.marquee img {
  width: 28px;
  height: 28px;
  transition: transform 0.2s;
}

.marquee span {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  font: var(--openbelt-type-body-sm);
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -4px);
  pointer-events: none;
  transition:
    opacity 0.2s,
    transform 0.2s;
}

/* Only where a pointer hovers: a tap on a phone leaves :hover stuck, the mark lit and the row paused. */
@media (hover: hover) {
  .marquee li:hover img {
    transform: scale(1.1);
  }

  .marquee li:hover span {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .marquee.moving {
    overflow: hidden;
  }

  .marquee.moving ul {
    padding: 0;
    padding-right: var(--openbelt-space-2xl);
    animation: marquee 45s linear infinite;
  }

  .marquee.moving[data-direction="right"] ul {
    animation-direction: reverse;
  }

  @media (hover: hover) {
    .marquee.moving:hover ul {
      animation-play-state: paused;
    }
  }
}

/* The list is two copies, the second hidden from screen readers, so half its width is one lap. */
@keyframes marquee {
  to {
    transform: translateX(-50%);
  }
}

/* What a tool gets. */
.pieces .grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--openbelt-space-md);
  margin-top: var(--openbelt-space-2xl);
}

.piece {
  display: grid;
  gap: var(--openbelt-space-xs);
  align-content: start;
  padding: var(--openbelt-space-lg);
  transition: border-color 0.2s;
}

.piece.on {
  border-color: var(--openbelt-color-border-strong);
}

/* Each piece's drawing: line art in the text colours, straight on the card. */
.piece .art {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: var(--openbelt-space-md);
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-width: 1.25;
}

.art .panel {
  fill: var(--openbelt-color-surface);
  stroke: var(--openbelt-color-border-strong);
}

.art .panel.strong,
.art .row.on,
.art .tag {
  fill: var(--openbelt-color-subtle);
  stroke: var(--openbelt-color-muted);
}

.art .head {
  fill: var(--openbelt-color-subtle);
}

.art .line {
  stroke: var(--openbelt-color-border-strong);
}

.art .ink,
.art .shield {
  stroke: var(--openbelt-color-primary);
  stroke-width: 1.5;
}

.art .shield {
  fill: var(--openbelt-color-subtle);
}

.art .dash {
  stroke-dasharray: 3 4;
}

.art .bar,
.art .dot {
  fill: var(--openbelt-color-border-strong);
}

.art .bar.strong,
.art .bar.on,
.art .fill,
.art .seg.on {
  fill: var(--openbelt-color-primary);
}

.art .seg {
  fill: var(--openbelt-color-surface);
  stroke: var(--openbelt-color-border-strong);
}

.art .seg.half {
  fill: var(--openbelt-color-muted);
}

.art text {
  font: var(--openbelt-type-mono-sm);
  fill: var(--openbelt-color-muted);
  stroke: none;
}

.art text.ink {
  fill: var(--openbelt-color-primary);
  stroke: none;
}

/* A light that runs along a wire on hover. */
.art .spark {
  stroke: var(--openbelt-color-primary);
  stroke-width: 1.75;
  stroke-dasharray: 14 100;
  stroke-dashoffset: 14;
  opacity: 0;
}

/* Data's last task gets its check on hover. */
.art .draw {
  stroke-dasharray: 1 2;
  stroke-linecap: butt;
  stroke-dashoffset: 1;
}

.art .todo {
  transition: opacity 0.2s;
}

.art .grow,
.art .drop,
.art .beat {
  transform-box: fill-box;
  transform-origin: center;
}

/* Data's last task is part done, and finishes on hover. */
.art .grow {
  transform: scaleX(0.45);
  transform-origin: left;
  transition: transform 0.5s ease-out;
}

.art .hand {
  transform-box: view-box;
  transform-origin: 52px 58px;
}

/* Users: the secret's field is part typed, and fills in on hover. */
.art .typed {
  opacity: 0;
  transition: opacity 0.15s;
  /* Typed left to right, deleted right to left. */
  transition-delay: calc((5 - var(--i)) * 0.07s);
}

.art .fills,
.art .next {
  transition: fill 0.3s;
}

/* A card is .on while hovered, or on a touch screen while it crosses the middle of the screen (site.js).
   Its changes are transitions, which reverse smoothly. Loops run while a card is .live,
   and each loop starts and ends on the resting picture. */
@media (prefers-reduced-motion: no-preference) {
  .piece.live .spark {
    opacity: 1;
    animation: art-spark 1.4s linear infinite;
  }

  .piece.live .spark.later {
    animation-delay: 0.45s;
  }

  .piece.live .spark.last {
    animation-delay: 0.9s;
  }

  .piece.live .flow {
    animation: art-flow 0.8s linear infinite;
  }

  .piece.on .grow {
    transform: none;
  }

  .piece.on .todo {
    opacity: 0;
  }

  .piece.on .draw {
    stroke-dashoffset: 0;
    transition: stroke-dashoffset 0.35s 0.45s ease-out;
  }

  /* Realtime: a change leaves the database, then lands as a new row on top. */
  .piece.live .ping {
    animation: art-ping 3.2s linear infinite;
  }

  .piece.live .drop {
    animation: art-drop 3.2s ease-in-out infinite;
  }

  .piece.live .push {
    animation: art-push 3.2s ease-in-out infinite;
  }

  .piece.on .typed {
    opacity: 1;
    transition-delay: calc(var(--i) * 0.07s);
  }

  .piece.live .beat {
    animation: art-beat 1.4s ease-in-out infinite;
  }

  .piece.live .hand {
    animation: art-turn 2s linear infinite;
  }

  .piece.on .fills {
    fill: var(--openbelt-color-primary);
  }

  .piece.on .next {
    fill: var(--openbelt-color-muted);
    transition-delay: 0.4s;
  }
}

@keyframes art-spark {
  to {
    stroke-dashoffset: -100;
  }
}

@keyframes art-flow {
  to {
    stroke-dashoffset: -7;
  }
}

/* Realtime's loop starts and ends on the resting picture, so hovering never jumps: hold, the new
   row goes, a change travels from the database, the row lands again. */
@keyframes art-ping {
  0%,
  34% {
    stroke-dashoffset: 14;
    opacity: 0;
  }
  35% {
    stroke-dashoffset: 14;
    opacity: 1;
  }
  58% {
    stroke-dashoffset: -100;
    opacity: 1;
  }
  59%,
  100% {
    stroke-dashoffset: -100;
    opacity: 0;
  }
}

@keyframes art-drop {
  0%,
  12% {
    opacity: 1;
    transform: none;
  }
  24%,
  58% {
    opacity: 0;
    transform: translateY(-8px) scale(0.96);
  }
  72%,
  100% {
    opacity: 1;
    transform: none;
  }
}

@keyframes art-push {
  0%,
  14% {
    transform: none;
  }
  28%,
  58% {
    transform: translateY(-30px);
  }
  72%,
  100% {
    transform: none;
  }
}

@keyframes art-beat {
  50% {
    transform: scale(1.06);
  }
}

@keyframes art-turn {
  to {
    transform: rotate(360deg);
  }
}

.art text.big {
  font: 600 22px var(--openbelt-font-mono);
  fill: var(--openbelt-color-primary);
}

.piece h3 {
  font: var(--openbelt-type-h5);
  letter-spacing: var(--openbelt-tracking-h5);
}

/* The closing call to action. */
.final {
  display: grid;
  justify-items: center;
  gap: var(--openbelt-space-lg);
  text-align: center;
}

.final h2 {
  max-width: 16ch;
  font-size: clamp(36px, 6vw, 67px);
}

footer {
  display: flex;
  align-items: center;
  gap: var(--openbelt-space-xs);
  padding: var(--openbelt-space-xl) 0;
  border-top: 1px solid var(--openbelt-color-border);
  font: var(--openbelt-type-body-sm);
}

footer nav {
  display: flex;
  gap: var(--openbelt-space-md);
  margin-left: auto;
}

footer a {
  color: var(--openbelt-color-muted);
  text-decoration: none;
}

footer .logo {
  --logo-size: 16px;
}

@media (max-width: 960px) {
  .pieces .grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .marks {
    display: none;
  }

  .flow {
    grid-template-columns: minmax(0, 1fr);
  }

  .film-play {
    left: var(--openbelt-space-md);
    bottom: var(--openbelt-space-md);
    height: 44px;
    padding-right: var(--openbelt-space-md);
    font-size: 14px;
  }

  .film-icon {
    width: 34px;
    height: 34px;
  }

  .orbit {
    max-width: 560px;
    margin-inline: auto;
  }
}

@media (max-width: 560px) {
  main > section,
  footer {
    width: calc(100% - 32px);
  }

  .ledger-row {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--openbelt-space-sm);
  }

  .nav {
    padding-inline: 16px;
  }

  /* On a phone the header keeps Sign in; the links within the page go. */
  .nav nav a[href^="#"] {
    display: none;
  }

  .hero {
    padding-top: var(--openbelt-space-3xl);
  }

  main > section:not(.hero, .stage) {
    padding-block: var(--openbelt-space-3xl);
  }

  main > section.stage {
    padding-bottom: var(--openbelt-space-3xl);
  }

  main > section.works {
    padding-bottom: calc(var(--openbelt-space-3xl) - 26px);
  }

  .pieces .grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Both states (icon and label) share one cell, each centred, so the button keeps the wider one's width. */
.copy-states {
  display: inline-grid;
}

.copy-states > span {
  grid-area: 1 / 1;
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: var(--openbelt-space-xs);
}

/* Just copied: a bolder green check on the light button. */
.copy-states .done .icon {
  color: color-mix(in oklab, var(--openbelt-color-success) 62%, var(--openbelt-color-on-primary));
  stroke-width: 3;
}

.copy-states > span:last-child,
.btn.copied .copy-states > span:first-child {
  visibility: hidden;
}

.btn.copied .copy-states > span:last-child {
  visibility: visible;
}

/* Hover and press, on every control: under the pointer a control lifts its tone; under a press it
   gives a little and darkens, quickly, so every click feels answered. Hover only where a pointer
   hovers, so a tap on a phone doesn't leave it stuck. */
.btn,
.nav nav a,
footer a,
.logo {
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color 0.16s var(--openbelt-ease),
    border-color 0.16s var(--openbelt-ease),
    color 0.16s var(--openbelt-ease),
    opacity 0.16s var(--openbelt-ease),
    transform 0.16s var(--openbelt-ease);
}

@media (hover: hover) {
  .btn-primary:hover {
    background: color-mix(
      in srgb,
      var(--openbelt-color-primary) 88%,
      var(--openbelt-color-neutral)
    );
  }

  .copy-prompt:hover {
    box-shadow:
      inset 0 -2px 0 color-mix(in srgb, var(--openbelt-color-neutral) 10%, transparent),
      0 14px 36px -12px color-mix(in srgb, var(--openbelt-color-primary) 30%, transparent);
    transform: translateY(-1px);
  }

  .copy-prompt:hover .copy-marks {
    gap: 10px;
  }

  .copy-prompt:hover .copy-marks i {
    transform: none;
  }

  .copy-prompt:hover .copy-marks i:nth-child(2) {
    transition-delay: 0.02s;
  }

  .copy-prompt:hover .copy-marks i:nth-child(3) {
    transition-delay: 0.04s;
  }

  .copy-prompt:hover .copy-marks i:nth-child(4) {
    transition-delay: 0.06s;
  }

  .copy-prompt:hover .copy-marks i:nth-child(5) {
    transition-delay: 0.08s;
  }

  /* The two marks with a colour of their own show it: the SVG itself painted inside its own mask, so
     the ink under it never shows past the mark's shape. */
  .copy-prompt:hover .copy-marks .claude,
  .copy-prompt:hover .copy-marks .gemini {
    background: var(--mark) center / contain no-repeat;
  }

  .btn-secondary:hover {
    border-color: var(--openbelt-color-muted);
    background: var(--openbelt-color-subtle);
  }

  .nav nav a:not(.btn):hover {
    background: color-mix(in srgb, var(--openbelt-color-primary) 7%, transparent);
    color: var(--openbelt-color-primary);
  }

  footer a:hover {
    color: var(--openbelt-color-primary);
  }

  .logo:hover {
    opacity: 0.8;
  }
}

.btn:active,
.nav nav a:active,
footer a:active,
.logo:active {
  transform: scale(0.96);
  transition-duration: 0.06s;
}

.copy-prompt:active {
  background: color-mix(in srgb, var(--openbelt-color-primary) 90%, var(--openbelt-color-neutral));
  box-shadow: inset 0 2px 3px color-mix(in srgb, var(--openbelt-color-neutral) 14%, transparent);
  transform: scale(0.96);
  transition-duration: 0.06s;
}

.copy-prompt:focus:not(:focus-visible) {
  outline: none;
}

.btn-primary:active {
  background: color-mix(in srgb, var(--openbelt-color-primary) 76%, var(--openbelt-color-neutral));
}

.btn-secondary:active {
  border-color: var(--openbelt-color-muted);
  background: var(--openbelt-color-sidebar-selected);
}

.nav nav a:not(.btn):active {
  background: color-mix(in srgb, var(--openbelt-color-primary) 12%, transparent);
  color: var(--openbelt-color-primary);
}

footer a:active,
.logo:active {
  opacity: 0.6;
}
