/*
 * Cuemark's website: dark like the app, quiet, and readable at arm's length
 * on a phone in a corridor — which is where a lot of theatre reading happens.
 */
:root {
  --bg: #0f1115;
  --bg-raised: #171a21;
  --bg-sunken: #0a0c10;
  --line: #262b36;
  --text: #e8ebf2;
  --text-dim: #9aa3b2;
  --text-faint: #6b7483;
  --accent: #ffb020;
  --accent-ink: #1a1205;
  --ok: #4fd07a;
  --danger: #ff6b6b;
  --radius: 10px;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, system-ui, sans-serif;
  /* The logo's face, used for everything that carries the brand: headings,
     the price, the numbers. Body copy stays on the system stack, which is what
     people actually read comfortably at length. */
  --display: 'Manrope', var(--font);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* The departments, straight out of the app. Using the same colours on the
     website as the badges in the booth is the cheapest kind of honesty. */
  --lx: #ffb020;
  --snd: #45c8d8;
  --av: #a98cff;
  --fly: #4fd07a;
  --sm: #6ea8ff;
}

/* Manrope, self-hosted: one 24 KB variable subset covering every weight, and
   no third party told who reads this site. */
@font-face {
  font-family: 'Manrope';
  font-style: normal;
  font-weight: 500 800;
  font-display: swap;
  src: url(fonts/manrope-latin.woff2) format('woff2');
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: #ffc555; }

.wrap { width: min(1080px, 92vw); margin: 0 auto; }
.narrow { width: min(720px, 92vw); margin: 0 auto; }

/* ---------- header ---------- */

header.top {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg-sunken) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.top .wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  height: 58px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'Manrope', var(--font);
  font-weight: 800;
  letter-spacing: 0.16em;
  font-size: 13px;
  color: var(--accent);
  text-decoration: none;
}

/* The wordmark's own tracking leaves a gap after the last letter; pulling it
   back keeps the mark and the word optically even. */
.brand span {
  margin-right: -0.16em;
}

.brand .mark {
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--text);
}

.top nav { margin-left: auto; display: flex; gap: 18px; align-items: center; }
.top nav a { color: var(--text-dim); text-decoration: none; font-size: 14px; }
.top nav a:hover, .top nav a[aria-current] { color: var(--text); }

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 15px;
  cursor: pointer;
  text-decoration: none;
}

.btn:hover { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); }

.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 650;
}

.btn.primary:hover { background: #ffc555; color: var(--accent-ink); }
.btn:disabled { opacity: 0.5; cursor: default; }
.btn.small { padding: 6px 12px; font-size: 13px; }

/* ---------- hero ---------- */

h1, h2, h3, .price-card .amount { font-family: var(--display); }

/* The little uppercase label above a heading. It is where the accent first
   appears on each section, so the colour threads down the page rather than
   sitting in one block at the top. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 14px;
  font-family: var(--display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.eyebrow::before {
  content: '';
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  padding: clamp(56px, 9vw, 104px) 0 clamp(40px, 6vw, 72px);
  text-align: center;
  overflow: hidden;
}

/* A wash of the accent behind the headline — the stage wash, not a gradient
   for its own sake. Kept very low so the type stays the brightest thing. */
.hero::before {
  content: '';
  position: absolute;
  top: -40%;
  left: 50%;
  width: min(1100px, 130vw);
  aspect-ratio: 1;
  transform: translateX(-50%);
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 13%, transparent) 0%, transparent 62%);
  pointer-events: none;
}

.hero > * { position: relative; }

.hero h1 {
  font-size: clamp(38px, 7.2vw, 76px);
  font-weight: 800;
  line-height: 1.04;
  margin: 0 0 18px;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

/* The one phrase the whole business rests on, marked the way a cue is. */
.hero h1 em {
  font-style: normal;
  color: var(--accent);
  position: relative;
  white-space: nowrap;
}

.hero h1 em::after {
  content: '';
  position: absolute;
  left: -0.06em;
  right: -0.06em;
  bottom: 0.06em;
  height: 0.09em;
  border-radius: 99px;
  background: color-mix(in srgb, var(--accent) 45%, transparent);
}

.hero p.lede {
  font-size: clamp(17px, 2.2vw, 22px);
  color: var(--text-dim);
  margin: 0 auto 30px;
  max-width: 32em;
  text-wrap: pretty;
}

.hero .actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }
.hero .btn { padding: 13px 24px; font-size: 16px; }
.hero .under { margin-top: 16px; font-size: 14px; color: var(--text-faint); }

figure.shot { margin: 40px 0 0; }

figure.shot img {
  width: 100%;
  height: auto;
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
}

figure.shot figcaption {
  margin-top: 10px;
  font-size: 13px;
  color: var(--text-faint);
  text-align: center;
}

/* ---------- features ---------- */

section { padding: 56px 0; border-top: 1px solid var(--line); }
section h2 { font-size: clamp(22px, 3vw, 30px); margin: 0 0 8px; letter-spacing: -0.01em; }
section p.sub { color: var(--text-dim); margin: 0 0 32px; max-width: 46em; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 22px;
}

/* A set of four reads as two rows of two. Left to auto-fit it breaks three and
   one, and the gap at the end looks like a mistake rather than a layout. */
.grid.pairs { grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr)); }

.card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}

.card h3 { margin: 0 0 8px; font-size: 17px; }
.card p { margin: 0; color: var(--text-dim); font-size: 15px; }

.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  align-items: center;
}

@media (max-width: 800px) { .split { grid-template-columns: 1fr; } }

/* ---------- price ---------- */

.price-card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 28px;
  text-align: center;
  max-width: 460px;
  margin: 0 auto;
}

.price-card .amount { font-size: 46px; font-weight: 800; letter-spacing: -0.02em; }
.price-card .terms { color: var(--text-dim); margin: 4px 0 20px; }
.price-card ul { text-align: left; margin: 0 0 22px; padding-left: 20px; color: var(--text-dim); }
/* The form inside the price card reads left-aligned, like every other form. */
.price-card form { text-align: left; }
.price-card li { margin: 6px 0; }

/* ---------- forms and the account area ---------- */

.field { display: block; margin: 0 0 14px; }
.field span { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 6px; }

.input {
  width: 100%;
  padding: 11px 12px;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  font: inherit;
}

.input:focus { outline: none; border-color: color-mix(in srgb, var(--accent) 60%, var(--line)); }

.note { font-size: 14px; color: var(--text-faint); }
.error { color: var(--danger); }
.ok { color: var(--ok); }

table.licences { width: 100%; border-collapse: collapse; font-size: 14px; }
table.licences th { text-align: left; color: var(--text-faint); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; padding: 8px 10px; }
table.licences td { padding: 10px; border-top: 1px solid var(--line); vertical-align: top; }
code.key { font-family: var(--mono); font-size: 13px; color: var(--accent); user-select: all; }

/* ---------- footer ---------- */

footer.bottom {
  border-top: 1px solid var(--line);
  padding: 32px 0 48px;
  color: var(--text-faint);
  font-size: 14px;
}

footer.bottom .wrap { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
footer.bottom nav { margin-left: auto; display: flex; gap: 16px; }
footer.bottom a { color: var(--text-dim); text-decoration: none; }
footer.bottom a:hover { color: var(--text); }

/* ---------- the mobile menu ----------------------------------------------
 *
 * The nav collapses to a button below 760px. The panel is a real <nav> that
 * gets hidden, not a separate copy of the links, so there is one list of pages
 * to keep right.
 */

.nav-toggle {
  display: none;
  margin-left: auto;
  width: 42px;
  height: 42px;
  padding: 0;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--text);
  cursor: pointer;
}

.nav-toggle:hover { background: color-mix(in srgb, var(--text) 8%, transparent); }

.nav-toggle .bars {
  position: relative;
  width: 18px;
  height: 12px;
}

.nav-toggle .bars span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.22s ease, opacity 0.15s ease;
}

.nav-toggle .bars span:nth-child(1) { top: 0; }
.nav-toggle .bars span:nth-child(2) { top: 5px; }
.nav-toggle .bars span:nth-child(3) { top: 10px; }

/* Open: the bars become a cross, so the button says what it will do next. */
.nav-toggle[aria-expanded='true'] .bars span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] .bars span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded='true'] .bars span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 760px) {
  .nav-toggle { display: inline-flex; }

  .top nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 6px 4vw 14px;
    background: var(--bg-sunken);
    border-bottom: 1px solid var(--line);
    box-shadow: 0 24px 40px rgba(0, 0, 0, 0.5);
  }

  /* [hidden] alone loses to the display above, and the panel must really be
     gone from the tab order when it is shut. */
  .top nav[hidden] { display: none; }

  .top nav a {
    padding: 13px 4px;
    font-size: 17px;
    border-bottom: 1px solid var(--line);
  }

  .top nav a:last-child { border-bottom: 0; }
  .top nav a[aria-current] { color: var(--accent); }
}

@media (min-width: 761px) {
  /* Above the breakpoint the panel is always the row of links, whatever the
     button last set. */
  .top nav[hidden] { display: flex; }
}

/* ---------- the app, animated --------------------------------------------
 *
 * These are not screenshots and not video: they are the app's own furniture
 * rebuilt in a few hundred bytes of CSS, running the interaction it is
 * describing. A recording would be megabytes, blurry on a retina screen, and
 * stale the moment the app changed. This loads instantly on theatre wifi.
 *
 * Every sequence shares one duration so the parts stay in step; each element
 * takes its turn through keyframe percentages rather than delays.
 */

.demo {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: linear-gradient(180deg, var(--bg-raised), var(--bg-sunken));
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
  overflow: hidden;
  font-size: 13px;
}

.demo-bar {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  color: var(--text-faint);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.demo-bar .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.demo-bar .dot:nth-child(2) { background: #2f3542; }
.demo-bar .dot:nth-child(3) { background: #2f3542; }
.demo-bar .where { margin-left: auto; text-transform: none; letter-spacing: 0; }

.demo-body { display: grid; grid-template-columns: 1fr 232px; align-items: stretch; }

/* A grid item's min-width is auto, so the script column grows to fit its
   longest line instead of wrapping it, and the text runs off under the cue
   list. This is the line that makes it wrap. */
.demo-body > * { min-width: 0; }
@media (max-width: 720px) { .demo-body { grid-template-columns: 1fr; } }

/* ---- the script page ---- */

.script {
  position: relative;
  padding: 20px 18px 20px 76px;
  background: var(--bg-sunken);
}

@media (max-width: 720px) {
  /* The margin only has to hold a badge, and on a phone it is competing with
     the words for a column that is already narrow. */
  /* Wide enough for the longest badge and a gap: at 58px a "SND 4" reached
     the first word. */
  .script { padding-left: 68px; font-size: 12px; }
  .line.who { margin-left: 40px; --indent: 40px; }
  .badge { --gutter-pull: 56px; font-size: 10px; height: 18px; padding: 0 5px; }
  .reader { left: 62px; }
}

.line { position: relative; margin: 0 0 13px; color: var(--text-dim); line-height: 1.5; }

/* A line being marked shrinks to its words, so the selection hugs the text the
   way a real drag does rather than painting the whole column. */
/* Short of the full width, because the selection paints a few pixels wider
   than the words and the panel clips what hangs over. */
.line:has(.pick) { width: max-content; max-width: calc(100% - 8px); }
.line.who { color: var(--text); font-weight: 650; letter-spacing: 0.06em; margin-left: 74px; --indent: 74px; }
.line.stage { color: var(--text-faint); font-style: italic; margin-left: 26px; --indent: 26px; }

/* A line being picked: the selection sweeps across it, as a drag would. */
.line .pick {
  position: absolute;
  inset: -3px -6px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  transform-origin: left center;
  transform: scaleX(0);
}

/* The badge that lands in the margin, and the rule that ties it to the line. */
.badge {
  position: absolute;
  /* Every badge in one column, like the gutter of a marked-up prompt copy —
     hanging each off its own line put a stage direction's badge 26px right of
     a dialogue line's, and a column of cue numbers that does not line up is
     the first thing a stage manager sees. The pull is the script's left
     padding less the width of the gutter margin. */
  right: auto;
  left: calc(-1 * (var(--gutter-pull, 62px) + var(--indent, 0px)));
  top: 50%;
  translate: 0 -50%;
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: 6px;
  background: var(--lx);
  color: #17140a;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.02em;
  white-space: nowrap;
  opacity: 0;
}

.badge.snd { background: var(--snd); color: #062329; }
.badge.av { background: var(--av); color: #16103a; }

/* The rule tying the badge to its line, drawn across the gap it now hangs
   over. */
.badge::after {
  content: '';
  position: absolute;
  left: 100%;
  top: 50%;
  /* Reaches from whatever width the number came out to across to the words.
     The percentage is of the badge itself, which is exactly the unknown. */
  width: calc(var(--gutter-pull, 62px) + var(--indent, 0px) - 100% - 8px);
  height: 1px;
  background: currentColor;
  opacity: 0.45;
}

/* ---- the cue list beside it ---- */

.cuelist {
  padding: 14px 14px 18px;
  border-left: 1px solid var(--line);
  background: var(--bg-raised);
}

@media (max-width: 720px) { .cuelist { border-left: 0; border-top: 1px solid var(--line); } }

.cuelist h4 {
  margin: 0 0 12px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.cue-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 9px;
  margin-bottom: 7px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-sunken);
  opacity: 0;
  translate: 12px 0;
}

.cue-row .tag {
  flex: none;
  padding: 2px 6px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--lx) 20%, transparent);
  color: var(--lx);
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.cue-row.snd .tag { background: color-mix(in srgb, var(--snd) 20%, transparent); color: var(--snd); }
.cue-row.av .tag { background: color-mix(in srgb, var(--av) 20%, transparent); color: var(--av); }
.cue-row .what { color: var(--text-dim); font-size: 12.5px; }

/* ---- sequence one: marking up ---- */

@keyframes pick-line { 0%, 4% { transform: scaleX(0); } 10%, 96% { transform: scaleX(1); } 100% { transform: scaleX(0); } }
@keyframes land-badge {
  0%, 10% { opacity: 0; translate: -8px -50%; }
  16%, 96% { opacity: 1; translate: 0 -50%; }
  100% { opacity: 0; translate: -8px -50%; }
}
@keyframes slide-row {
  0%, 16% { opacity: 0; translate: 12px 0; }
  24%, 96% { opacity: 1; translate: 0 0; }
  100% { opacity: 0; translate: 12px 0; }
}

.demo.marking .pick { animation: pick-line 9s cubic-bezier(0.3, 0.8, 0.3, 1) infinite; }
.demo.marking .badge { animation: land-badge 9s cubic-bezier(0.2, 0.9, 0.3, 1) infinite; }
.demo.marking .cue-row { animation: slide-row 9s cubic-bezier(0.2, 0.9, 0.3, 1) infinite; }

/* The second and third cues follow, a beat apart. Negative delays would start
   them mid-sequence on load, so the offsets are positive and the sequence
   simply takes a moment to fill. */
.demo.marking [data-step='2'] { animation-delay: 1.5s; }
.demo.marking [data-step='3'] { animation-delay: 3s; }

/* ---- sequence two: calling the show ----
 *
 * The line highlight steps down the page and the call panel counts the next
 * cue in. This is the thing people buy it for, so it gets the bigger demo.
 */

.callpanel {
  padding: 16px 14px;
  border-left: 1px solid var(--line);
  background: var(--bg-raised);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

@media (max-width: 720px) { .callpanel { border-left: 0; border-top: 1px solid var(--line); } }

.on-deck {
  border: 1px solid color-mix(in srgb, var(--accent) 40%, var(--line));
  border-radius: 10px;
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  padding: 13px;
}

.on-deck .label {
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.on-deck .cue {
  font-family: var(--display);
  font-size: 27px;
  font-weight: 800;
  letter-spacing: -0.01em;
  line-height: 1.15;
  margin-top: 2px;
}

.on-deck .what { color: var(--text-dim); font-size: 12.5px; }

.standby {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 11px;
  border: 1px dashed color-mix(in srgb, var(--text-dim) 45%, transparent);
  border-radius: 8px;
  color: var(--text-dim);
  font-size: 12.5px;
  opacity: 0;
}

.standby::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-dim);
}

/* The reading line: a bar that steps from line to line rather than sliding,
   because that is how it moves in the app — one line at a time, on a key. */
.reader {
  position: absolute;
  left: 52px;
  right: 14px;
  height: 25px;
  border-radius: 6px;
  border-left: 3px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  top: 16px;
}

@keyframes step-down {
  0%, 12% { transform: translateY(0); }
  16%, 28% { transform: translateY(31px); }
  32%, 44% { transform: translateY(62px); }
  48%, 60% { transform: translateY(93px); }
  64%, 76% { transform: translateY(124px); }
  80%, 100% { transform: translateY(155px); }
}

@keyframes show-standby { 0%, 44% { opacity: 0; } 52%, 100% { opacity: 1; } }

/* The cue number flips over when the previous one is taken. */
@keyframes flip-cue {
  0%, 74% { opacity: 1; translate: 0 0; }
  78% { opacity: 0; translate: 0 -8px; }
  82%, 100% { opacity: 0; translate: 0 -8px; }
}
@keyframes flip-next {
  0%, 78% { opacity: 0; translate: 0 8px; }
  84%, 100% { opacity: 1; translate: 0 0; }
}

.demo.calling .reader { animation: step-down 10s cubic-bezier(0.6, 0, 0.2, 1) infinite; }
.demo.calling .standby { animation: show-standby 10s ease infinite; }
.demo.calling .on-deck .cue.first { animation: flip-cue 10s ease infinite; }
.demo.calling .on-deck .cue.second {
  position: absolute;
  animation: flip-next 10s ease infinite;
}
.demo.calling .on-deck { position: relative; }

/* The cues already gone, under the one on deck. */
.taken { margin-top: auto; }

.taken h4 {
  margin: 0 0 8px;
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.taken-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--text-faint);
}

.taken-row .tag {
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 800;
  color: var(--snd);
  opacity: 0.75;
}

.taken-row.lx .tag { color: var(--lx); }
.taken-row.av .tag { color: var(--av); }
.taken-row .at { margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---- sequence three: triggers ----
 *
 * A pulse arrives from outside — a pedal, a desk, Companion — and the cue is
 * taken. The point is that Cuemark does not have to be the thing you touch.
 */

.wires { display: grid; gap: 10px; padding: 18px; }

.wire {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-sunken);
}

.wire .kind {
  flex: none;
  width: 108px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: var(--text-dim);
}

/* What is actually on the end of the wire. "MIDI" means nothing to somebody
   deciding whether this fits their booth; "foot pedal" does. */
.wire .kind small {
  display: block;
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--text-faint);
}

@media (max-width: 520px) {
  .wire .kind { width: 84px; }
  .wire .lands b { display: none; }
}

.wire .track {
  position: relative;
  flex: 1;
  height: 2px;
  border-radius: 2px;
  background: var(--line);
  overflow: hidden;
}

/* The pulse itself: a short bright run down the wire. */
.wire .track::after {
  content: '';
  position: absolute;
  top: -1px;
  left: -30%;
  width: 30%;
  height: 4px;
  border-radius: 4px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
}

@keyframes pulse-along { 0% { left: -30%; } 26%, 100% { left: 100%; } }

.wire .lands {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  color: var(--accent);
  opacity: 0;
}

/* The cue the pulse took, in the badge the app would show. */
.wire .lands b {
  padding: 2px 7px;
  border-radius: 5px;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  letter-spacing: 0.02em;
}

@keyframes land-take { 0%, 18% { opacity: 0; } 24%, 46% { opacity: 1; } 56%, 100% { opacity: 0; } }

.demo.triggers .wire .track::after { animation: pulse-along 6s linear infinite; }
.demo.triggers .wire .lands { animation: land-take 6s ease infinite; }
.demo.triggers .wire:nth-child(2) .track::after,
.demo.triggers .wire:nth-child(2) .lands { animation-delay: 1.1s; }
.demo.triggers .wire:nth-child(3) .track::after,
.demo.triggers .wire:nth-child(3) .lands { animation-delay: 2.2s; }

/* ---- anybody who has asked for less movement gets less, not nothing ----
 *
 * These demos used to freeze under prefers-reduced-motion, which on an iPhone
 * is one switch in Accessibility that a lot of people have on without
 * remembering — and a frozen demo is a picture that says nothing about what
 * the app does. So they still run. What goes is the movement: nothing slides,
 * sweeps or travels. Each state still takes its turn, but by fading in where
 * it ends up, and the reading line jumps from line to line as a key would
 * move it rather than gliding.
 */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  @keyframes pick-line-fade { 0%, 4% { opacity: 0; } 10%, 96% { opacity: 1; } 100% { opacity: 0; } }
  @keyframes land-badge-fade { 0%, 10% { opacity: 0; } 16%, 96% { opacity: 1; } 100% { opacity: 0; } }
  @keyframes slide-row-fade { 0%, 16% { opacity: 0; } 24%, 96% { opacity: 1; } 100% { opacity: 0; } }
  @keyframes flip-cue-fade { 0%, 74% { opacity: 1; } 78%, 100% { opacity: 0; } }
  @keyframes flip-next-fade { 0%, 78% { opacity: 0; } 84%, 100% { opacity: 1; } }
  @keyframes pulse-fade { 0% { opacity: 0; } 8%, 20% { opacity: 1; } 28%, 100% { opacity: 0; } }
  @keyframes beam-fade { 0%, 14% { opacity: 0; } 18%, 42% { opacity: 1; } 48%, 100% { opacity: 0; } }
  @keyframes typed-fade { 0%, 16% { opacity: 0; } 46%, 100% { opacity: 1; } }

  .demo.marking .pick { transform: scaleX(1); animation-name: pick-line-fade; }
  .demo.marking .badge { translate: 0 -50%; animation-name: land-badge-fade; }
  .demo.marking .cue-row { translate: 0 0; animation-name: slide-row-fade; }
  .demo.calling .reader { animation-timing-function: steps(1, end); }
  .demo.calling .on-deck .cue.first { translate: 0 0; animation-name: flip-cue-fade; }
  .demo.calling .on-deck .cue.second { translate: 0 0; animation-name: flip-next-fade; }
  .demo.triggers .wire .track::after { left: 0; width: 100%; animation-name: pulse-fade; }
  .demo.scanned .beam { translate: 0 0; animation-name: beam-fade; }
  .demo.scanned .typed { clip-path: none; animation-name: typed-fade; }
  .demo.scanned .paper { rotate: 0deg; }
}

/* ---- sequence four: a photocopy becomes a script ----
 *
 * The page comes in as a scan — grey, speckled, a degree off square. A beam
 * passes down it and the words come up crisp behind it, with the panel
 * counting what was found. Then the clean copy: the same words, black on
 * white, square, with a cue in the margin to show it is a script again.
 */

.demo.scanned .demo-body { grid-template-columns: 1fr 232px; }

.scanwrap {
  position: relative;
  padding: 18px 18px 18px 18px;
  background: var(--bg-sunken);
  overflow: hidden;
}

.paper {
  position: relative;
  padding: 18px 20px 18px 56px;
  min-height: 196px;
  border-radius: 3px;
  background: #cfcbc1;
  color: #3d3a35;
  rotate: -1.4deg;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  font-family: Georgia, 'Times New Roman', serif;
  font-size: 12.5px;
  line-height: 1.55;
  animation: paper-clean 13s ease infinite;
}

/* The photocopier's contribution: toner speckle and a grey wash. */
.paper .noise {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(rgba(40, 36, 30, 0.55) 0.6px, transparent 0.9px),
    radial-gradient(rgba(40, 36, 30, 0.35) 0.5px, transparent 0.8px),
    linear-gradient(180deg, rgba(0, 0, 0, 0.12), transparent 40%, rgba(0, 0, 0, 0.1));
  background-size: 7px 9px, 11px 13px, 100% 100%;
  background-position: 0 0, 3px 5px, 0 0;
  animation: noise-clean 13s ease infinite;
}

.paper .scanned-text,
.paper .typed {
  margin: 0;
}

.paper .scanned-text {
  filter: blur(0.45px) contrast(0.8);
  opacity: 0.78;
}

.paper .typed {
  position: absolute;
  inset: 18px 20px 18px 56px;
  color: #1c1a17;
  /* The sides are left open so the badge in the margin is not clipped off. */
  clip-path: inset(0 -80px 100% -80px);
  animation: typed-reveal 13s linear infinite;
}

.paper p { margin: 0 0 9px; }
.paper .who { font-weight: 700; letter-spacing: 0.06em; margin-left: 48px; font-size: 11.5px; }
.paper .stage { font-style: italic; margin-left: 18px; }

/* The reading beam. */
.beam {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 26px;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--accent) 45%, transparent) 55%, var(--accent));
  box-shadow: 0 2px 0 var(--accent);
  opacity: 0;
  animation: beam-down 13s linear infinite;
}

/* The badge the clean copy carries, to say it is still a script. */
.paper .badge.clean { opacity: 0; --gutter-pull: 44px; left: -44px; animation: clean-badge 13s ease infinite; }
.paper .badge.clean::after { width: calc(44px - 100% - 8px); }

@keyframes typed-reveal {
  0%, 16% { clip-path: inset(0 -80px 100% -80px); }
  44%, 100% { clip-path: inset(0 -80px 0 -80px); }
}
@keyframes beam-down {
  0%, 14% { translate: 0 -30px; opacity: 0; }
  17% { opacity: 1; }
  44% { translate: 0 200px; opacity: 1; }
  47%, 100% { translate: 0 230px; opacity: 0; }
}
@keyframes paper-clean {
  0%, 66% { background: #cfcbc1; rotate: -1.4deg; }
  72%, 94% { background: #fbfaf7; rotate: 0deg; }
  100% { background: #cfcbc1; rotate: -1.4deg; }
}
@keyframes noise-clean {
  0%, 66% { opacity: 1; }
  72%, 94% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes clean-badge {
  0%, 70% { opacity: 0; }
  76%, 94% { opacity: 1; }
  100% { opacity: 0; }
}

/* The panel: what was read, as it is read. */
.scanpanel {
  padding: 16px 14px;
  border-left: 1px solid var(--line);
  background: var(--bg-raised);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

@media (max-width: 720px) { .scanpanel { border-left: 0; border-top: 1px solid var(--line); } }

.scanpanel h4 {
  margin: 0 0 4px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.scanpanel .step {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-sunken);
  font-size: 12.5px;
  color: var(--text-dim);
  opacity: 0;
  animation: step-in 13s ease infinite;
}

.scanpanel .step b { color: var(--text); font-weight: 650; }
.scanpanel .step.on { border-color: color-mix(in srgb, var(--accent) 50%, transparent); color: var(--accent); }
.scanpanel .step.on b { color: var(--accent); }
.scanpanel .step[data-step='1'] { animation-name: step-in-1; }
.scanpanel .step[data-step='2'] { animation-name: step-in-2; }
.scanpanel .step[data-step='3'] { animation-name: step-in-3; }
.scanpanel .step[data-step='4'] { animation-name: step-in-4; }

@keyframes step-in-1 { 0%, 14% { opacity: 0; } 18%, 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes step-in-2 { 0%, 30% { opacity: 0; } 34%, 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes step-in-3 { 0%, 46% { opacity: 0; } 50%, 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes step-in-4 { 0%, 68% { opacity: 0; } 72%, 94% { opacity: 1; } 100% { opacity: 0; } }
@keyframes step-in { 0% { opacity: 0; } 100% { opacity: 1; } }

@media (max-width: 720px) {
  .demo.scanned .demo-body { grid-template-columns: 1fr; }
  .paper { padding-left: 46px; font-size: 11.5px; min-height: 0; }
  .paper .typed { inset: 18px 20px 18px 46px; }
  .paper .who { margin-left: 24px; }
}

/* ---------- the longer homepage ---------- */

/* A screenshot across the full column, with a line under it saying what it
   shows. The ones inside .split keep their own rules. */
/* figure.shot already draws the image with its border and shadow; a wide one
   only sits closer to the text above it. */
.shot.wide { margin: 28px 0 0; }

/* A show night, as four moments. Numbered by the browser, so the markup is a
   plain ordered list and reads as one without the stylesheet. */
.steps { list-style: none; counter-reset: step; margin: 24px 0 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.steps li { counter-increment: step; background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--radius); padding: 20px 20px 18px; }
.steps li::before { content: counter(step); display: inline-block; width: 26px; height: 26px; line-height: 26px; text-align: center; border-radius: 50%; background: var(--accent, #ffb020); color: #0b0b0b; font-weight: 800; font-size: 13px; margin-bottom: 10px; }
.steps h3 { margin: 0 0 6px; font-size: 16px; }
.steps p { margin: 0; color: var(--text-dim); font-size: 15px; }

/* Questions, closed until asked. Native disclosure: no script, works with the
   keyboard, and the answer is in the page for anyone searching it. */
.faq details { border-top: 1px solid var(--line); padding: 14px 0; }
.faq details:last-of-type { border-bottom: 1px solid var(--line); }
.faq summary { cursor: pointer; font-weight: 650; font-size: 16px; list-style: none; display: flex; justify-content: space-between; gap: 16px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; color: var(--text-dim); font-weight: 400; flex: none; }
.faq details[open] summary::after { content: '–'; }
.faq details p { margin: 10px 0 0; color: var(--text-dim); font-size: 15px; }

/* The price card on the homepage carries buttons and a line under them. */
.price-card .actions { justify-content: center; margin: 0 0 14px; }
.price-card .note { margin: 0; font-size: 14px; }

/* Two headings in the right-hand half of a split read as two short
   paragraphs, not one. */
.split h3 { margin: 0 0 6px; font-size: 17px; }
.split h3 + .sub { margin-bottom: 18px; }
