/* ==========================================================================
   MASCATECH
   One screen. A terminal that types one answer at a time.
   No CSS framework — this file is the whole design system.
   ========================================================================== */

:root {
  /* Ink and ground */
  --void:      #010205;
  --void-2:    #04060b;
  --ink:       #eef2fa;
  --ink-2:     #b8c3d8;
  --muted:     #7d8ba5;

  /* Brand. --blue-core is the logo's exact blue; --blue is it lifted for dark. */
  --blue-core: #004aad;
  --blue:      #3b86f7;
  --cyan:      #2fd8ee;
  --accent:    linear-gradient(100deg, var(--blue), var(--cyan));

  /* Structure */
  --edge:      rgba(126, 164, 226, 0.14);
  --edge-hi:   rgba(90, 150, 255, 0.42);

  --sans: "Segoe UI Variable Display", "Segoe UI", system-ui, -apple-system,
          "Helvetica Neue", Arial, sans-serif;
  --mono: "Cascadia Mono", "Cascadia Code", ui-monospace, Consolas,
          "SF Mono", Menlo, monospace;

  --pad: 1.8rem;

  --bevel: polygon(0 0, calc(100% - 7px) 0, 100% 7px,
                   100% 100%, 7px 100%, 0 calc(100% - 7px));
}

/* Everything is sized in rem and the root scales with the viewport, so the
   design fills a 13" laptop and a 4K monitor alike without ever overflowing. */
html {
  font-size: clamp(14px, calc(0.85vh + 0.52vw), 21px);
  box-sizing: border-box;
}
*, *::before, *::after { box-sizing: inherit; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  background: var(--void);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--blue); color: #04070d; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ==========================================================================
   Background: mesh grid, two glows, one slow scan sweep
   ========================================================================== */

.bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

.bg-grid {
  position: absolute;
  inset: -2px;
  background-image:
    linear-gradient(to right,  rgba(126, 164, 226, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(126, 164, 226, 0.05) 1px, transparent 1px);
  background-size: 68px 68px;
  mask-image: radial-gradient(ellipse 92% 78% at 50% 45%, #000 18%, transparent 100%);
  animation: drift 70s linear infinite;
}

@keyframes drift { to { background-position: 68px 68px; } }

.bg-glow { position: absolute; border-radius: 50%; filter: blur(72px); }
.bg-glow-a {
  top: -30vh; left: -14vw;
  width: 66vw; height: 66vh;
  background: radial-gradient(circle, rgba(0, 74, 173, 0.32), transparent 68%);
}
.bg-glow-b {
  bottom: -36vh; right: -12vw;
  width: 58vw; height: 60vh;
  background: radial-gradient(circle, rgba(47, 216, 238, 0.08), transparent 68%);
}

.bg-scan {
  position: absolute;
  left: 0; right: 0;
  height: 34vh;
  background: linear-gradient(to bottom, transparent,
    rgba(59, 134, 247, 0.035) 45%, rgba(47, 216, 238, 0.022) 55%, transparent);
  animation: scan 11s linear infinite;
}

@keyframes scan {
  from { transform: translateY(-40vh); }
  to   { transform: translateY(105vh); }
}

/* ==========================================================================
   Page frame
   ========================================================================== */

.screen {
  position: relative;
  z-index: 1;
  height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding-bottom: env(safe-area-inset-bottom);
}

.screen::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--blue) 22%,
                              var(--cyan) 55%, transparent);
  opacity: 0.65;
}

/* ==========================================================================
   Top bar
   ========================================================================== */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.4rem;
  padding: 0.95rem var(--pad);
  border-bottom: 1px solid var(--edge);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

/* The wordmark sits in a HUD frame with light sweeping through the letterforms.
   The negative margin pulls the frame back so the brackets land on the page's
   left edge and the bar keeps the height it had before the frame existed. */
.brand {
  --brand-pad-x: 0.85rem;
  --brand-pad-y: 0.5rem;
  --bracket: 9px;

  position: relative;
  display: block;
  line-height: 0;
  padding: var(--brand-pad-y) var(--brand-pad-x);
  margin: calc(var(--brand-pad-y) * -1) 0
          calc(var(--brand-pad-y) * -1) calc(var(--brand-pad-x) * -1);
}

.brand::before,
.brand::after {
  content: "";
  position: absolute;
  width: var(--bracket);
  height: var(--bracket);
  border: 1px solid var(--blue);
  opacity: 0.8;
  transition: opacity 0.3s ease;
}
.brand::before { top: 0; left: 0; border-right: 0; border-bottom: 0; }
.brand::after { bottom: 0; right: 0; border-left: 0; border-top: 0; }
.brand:hover::before,
.brand:hover::after { opacity: 1; }
.brand:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

/* Fallback: the plain artwork, for anything without mask support. */
.brand-mark {
  display: block;
  height: 1.5rem;
  aspect-ratio: 2256 / 272;
  background: url("../img/logo-on-dark.e4d4f7e72cd9.png") center / contain no-repeat;
  filter: drop-shadow(0 0 12px rgba(59, 134, 247, 0.35));
  transition: filter 0.35s ease;
}
.brand:hover .brand-mark { filter: drop-shadow(0 0 20px rgba(59, 134, 247, 0.6)); }

/* With masks — every current browser — the mark becomes a window onto a moving
   gradient rather than a static image. The band of near-white in the middle is
   the light; the background is wider than the mark so it can travel across. */
@supports ((-webkit-mask-image: url("")) or (mask-image: url(""))) {
  .brand-mark {
    background: linear-gradient(
      100deg,
      var(--blue-core) 0%, var(--blue) 34%,
      #f2f8ff 48%, #f2f8ff 52%,
      var(--cyan) 66%, var(--blue) 100%
    );
    background-size: 260% 100%;
    -webkit-mask: url("../img/logo-mask.ee724f9d48ba.png") center / contain no-repeat;
            mask: url("../img/logo-mask.ee724f9d48ba.png") center / contain no-repeat;
    animation: brand-sweep 5.5s linear infinite;
  }
}

@keyframes brand-sweep {
  from { background-position: 170% 0; }
  to   { background-position: -70% 0; }
}

.ticker {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.75rem;
  border: 1px solid var(--edge);
  border-radius: 2px;
  background: #06080f;
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--ink-2);
  white-space: nowrap;
}
.ticker-prompt { color: var(--cyan); }
.ticker-label {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.58rem;
  color: var(--muted);
}
.ticker-caret {
  width: 0.4rem;
  height: 0.85em;
  background: var(--blue);
  animation: blink 1.1s steps(2, start) infinite;
}

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

/* ==========================================================================
   Stage
   ========================================================================== */

.stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.3rem;
  padding: 1.4rem var(--pad);
  min-height: 0;
}

/* The services line, in full, above the terminal. */
.services {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin: 0;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ink-2);
  text-align: center;
  flex-wrap: wrap;
  justify-content: center;
}
.services i {
  font-style: normal;
  background: var(--accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The site's thesis. It cannot out-shout the terminal — that thing moves — so
   it wins on separation instead: pushed well clear, given its own gradient rule,
   and set near-white at a readable size so it is the obvious second thing to
   look at once the terminal has had its moment. */
.stage-note {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  margin: 1.7rem 0 0;
  font-family: var(--mono);
  font-size: 0.95rem;
  letter-spacing: 0.005em;
  color: var(--ink-2);
  text-align: center;
  text-wrap: balance;
  max-width: 44rem;   /* wraps to two balanced lines rather than one long one */
}
.note-slash { color: var(--muted); opacity: 0.75; }
.note-rule {
  width: 2.4rem;
  height: 1px;
  background: var(--accent);
  opacity: 0.85;
}

/* ==========================================================================
   The terminal
   ========================================================================== */

.term {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 52rem;
  border: 1px solid var(--edge);
  border-radius: 5px;
  /* Opaque and near-black, like a real terminal. Semi-transparency let the
     page's glow bleed through and read as grey. */
  background: linear-gradient(180deg, #02040a, #000103);
  box-shadow:
    0 30px 90px -30px rgba(0, 0, 0, 0.95),
    0 0 70px -24px rgba(59, 134, 247, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.025);
  overflow: hidden;
}

/* Faint CRT banding across the whole window. */
.term::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.007) 0 1px,
    transparent 1px 3px
  );
  pointer-events: none;
}

.term-bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.55rem 0.85rem;
  border-bottom: 1px solid var(--edge);
  background: #06080f;   /* a hair lighter than the body, the way chrome is */
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--muted);   /* deliberately not uppercased — these read as a real
                            host and path, which is where the joke lives */
}
.term-lights { display: flex; gap: 0.4rem; }
.term-lights i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--edge-hi);
}
.term-lights i:nth-child(1) { background: var(--blue); box-shadow: 0 0 8px rgba(59,134,247,.8); }
.term-lights i:nth-child(2) { background: rgba(47, 216, 238, 0.6); }
.term-title { color: var(--ink-2); }
.term-path { color: var(--muted); }

/* Fixed, not min-height: the window must not resize as answers change length.
   Sized for the tallest thing that goes in it, which is the contact form, so
   short answers simply leave empty space below — as a real terminal would. */
.term-body {
  display: flex;
  align-items: flex-start;
  padding: 1.9rem 1.7rem 1.5rem;
  height: 16rem;
  overflow: hidden;
}

/* ==========================================================================
   A run: one command, its output, typed
   ========================================================================== */

.run {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
  cursor: pointer;
  outline: none;
}
.run:focus-visible { outline: 1px solid var(--edge-hi); outline-offset: 0.7rem; }

.run-cmd {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  margin: 0;
  font-family: var(--mono);
  font-size: 0.92rem;
  color: var(--ink-2);
}
.run-prompt { color: var(--cyan); font-weight: 700; }

.run-out {
  display: flex;
  flex-direction: column;
  gap: 0.1em;
}

/* The answer. Monospace, left aligned, as large as the box allows. */
.run-line {
  font-family: var(--mono);
  font-size: min(2.5rem, 4.6vw);
  font-weight: 500;
  line-height: 1.18;
  color: var(--ink);
}

/* The punchline carries the brand gradient. */
.run-line.punch {
  background: var(--accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 26px rgba(59, 134, 247, 0.3));
}

/* --- The typing itself ----------------------------------------------------
   1ch in a monospace face is exactly one glyph, so animating width from 0 to
   --ch characters walks the reveal across the line, one character at a time.
   If a browser rejects steps(var(--ch)) it falls back to a smooth wipe, which
   still reads correctly. -------------------------------------------------- */
.typed {
  display: block;
  flex: 0 0 auto;          /* never let flex shrink it below the text */
  letter-spacing: normal;  /* 1ch counts glyphs, not tracking — see below */
  width: calc(var(--ch) * 1ch + 0.3em);
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  animation: type var(--dur, 0.6s) steps(var(--ch), end) var(--delay, 0s) both;
}

/* Two things will clip the last character of a typed line, and both are silent:
   any letter-spacing (1ch measures the glyph, not the glyph plus tracking), and
   a fallback font whose "0" is narrower than its widest glyph. Hence the reset
   above and the 0.3em of slack in the width. Do not add letter-spacing to
   .run-cmd or .run-line. */

@keyframes type { from { width: 0; } }

.run-cursor {
  width: 0.55em;
  height: 1.05em;
  margin-top: 0.18em;
  background: var(--blue);
  box-shadow: 0 0 12px rgba(59, 134, 247, 0.85);
  opacity: 0;
  font-size: min(2.5rem, 4.6vw);
  animation: caret 1.05s steps(1, end) var(--cursor-delay, 2s) infinite;
}

@keyframes caret {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.run-note {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--muted);
  animation: rise 0.5s ease var(--delay, 0s) both;
}

/* ==========================================================================
   Agent demo — a recorded run replayed line by line
   ========================================================================== */

/* Used by .tr and .run-note. Keep it next to them — an undefined animation
   name is ignored silently, which shows up as everything appearing at once. */
@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
}

/* --- The drawer ----------------------------------------------------------
   Slides in over the right edge. The page keeps running underneath: the main
   terminal carries on with its cards, this is a second screen alongside it. */

.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  z-index: 40;
  width: min(31rem, 94vw);
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #02040a, #000103);
  border-left: 1px solid var(--edge-hi);
  box-shadow:
    -36px 0 90px -24px rgba(0, 0, 0, 0.94),
    -1px 0 44px -8px rgba(59, 134, 247, 0.22);
  animation: drawer-in 0.44s cubic-bezier(0.2, 0.8, 0.25, 1) both;
}

@keyframes drawer-in {
  from { transform: translateX(100%); opacity: 0.35; }
}

/* Same faint CRT banding as the main terminal, so it reads as one machine. */
.drawer::after {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.007) 0 1px,
    transparent 1px 3px
  );
  pointer-events: none;
}

.drawer-bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--edge);
  background: #06080f;
  font-family: var(--mono);
  font-size: 0.68rem;
  color: var(--ink-2);
}
.drawer-lights { display: flex; gap: 0.4rem; }
.drawer-lights i {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--edge-hi);
}
.drawer-lights i:nth-child(1) {
  background: var(--blue);
  box-shadow: 0 0 8px rgba(59, 134, 247, 0.8);
}
.drawer-lights i:nth-child(2) { background: rgba(47, 216, 238, 0.6); }

.drawer-close {
  appearance: none;
  background: transparent;
  border: 1px solid var(--edge);
  border-radius: 2px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.9rem;
  line-height: 1;
  padding: 0.15rem 0.45rem 0.25rem;
  cursor: pointer;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.drawer-close:hover { color: var(--blue); border-color: var(--blue); }
.drawer-close:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

.drawer-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 1.5rem 1.3rem;
  min-height: 0;
  overflow-y: auto;
}
.drawer-body .run-cmd { font-size: 0.82rem; }

.trace {
  display: flex;
  flex-direction: column;
  gap: 0.06rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.55;
}

/* A terminal prints whole lines, so these arrive line by line rather than
   character by character — only the command above is typed. */
.tr {
  display: flex;
  gap: 0.7rem;
  margin: 0;
  color: var(--ink-2);
  animation: rise 0.32s cubic-bezier(0.2, 0.7, 0.3, 1) var(--delay, 0s) both;
}
.tr-label {
  flex: 0 0 2.3rem;
  color: var(--muted);
  text-transform: lowercase;
}
.tr-text { min-width: 0; }

.tr-in .tr-text     { color: var(--muted); }
.tr-tool .tr-label  { color: var(--blue); }
.tr-tool .tr-text   { color: var(--ink); }
.tr-result .tr-text { color: var(--ink-2); padding-left: 0.9rem; }

/* The point of the whole demo: it found the ambiguity and refused to guess. */
.tr-ask .tr-label { color: var(--cyan); }
.tr-ask .tr-text {
  background: var(--accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.tr-done .tr-label { color: var(--blue); }
.tr-done .tr-text  { color: var(--ink); }

.demo-cta { white-space: nowrap; }

/* --- What the demo is for ------------------------------------------------ */

.drawer-outro {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  margin-top: 0.4rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--edge);
  animation: rise 0.5s cubic-bezier(0.2, 0.7, 0.3, 1) var(--delay, 0s) both;
}

.outro-line {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--ink);
  text-wrap: pretty;
}
/* The question is the hook — it gets the gradient, like every other punchline. */
.outro-ask {
  background: var(--accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  width: fit-content;
}

.outro-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.5rem;
}

/* ==========================================================================
   Buttons — bevelled, drawn so the glow follows the cut shape
   ========================================================================== */

.btn {
  position: relative;
  display: inline-block;
  padding: 0.62rem 1rem;
  border: 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  clip-path: var(--bevel);
  transition: filter 0.3s ease, background 0.3s ease, color 0.3s ease;
}
.btn-label { position: relative; }

.btn-solid {
  background: var(--accent);
  color: #04070d;
  font-weight: 600;
}
.btn-solid:hover {
  filter: drop-shadow(0 0 14px rgba(59, 134, 247, 0.55)) brightness(1.08);
}

/* The element's own background is the 1px edge; ::before paints the fill just
   inside it, so the bevel and the border stay in agreement. */
.btn-ghost { background: var(--edge-hi); color: var(--ink-2); }
.btn-ghost::before {
  content: "";
  position: absolute;
  inset: 1px;
  background: var(--void-2);
  clip-path: var(--bevel);
}
.btn-ghost:hover {
  background: var(--blue);
  color: var(--blue);
  filter: drop-shadow(0 0 12px rgba(59, 134, 247, 0.4));
}

.btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.btn[disabled] { opacity: 0.45; cursor: wait; }

/* The primary call to action breathes, so it reads as the live thing on a page
   where everything else is either typing or still. drop-shadow rather than
   box-shadow because the buttons are clipped to a bevel — a box-shadow would
   trace a rectangle the button does not have. */
.btn-glow { animation: cta-glow 3s ease-in-out infinite; }

@keyframes cta-glow {
  0%, 100% {
    filter: drop-shadow(0 0 5px rgba(59, 134, 247, 0.4));
  }
  50% {
    filter: drop-shadow(0 0 16px rgba(59, 134, 247, 0.85))
            drop-shadow(0 0 30px rgba(47, 216, 238, 0.35));
  }
}

/* An animation outranks the hover rule's filter, so the pulse has to stop for
   the hover state to be visible at all. */
.btn-glow:hover {
  animation: none;
  filter: drop-shadow(0 0 20px rgba(59, 134, 247, 0.9)) brightness(1.1);
}

/* ==========================================================================
   The one form — runs inside the terminal, in place of a card
   ========================================================================== */

.run-form { cursor: default; gap: 0.9rem; }
.run-cmd-text { color: var(--ink); }

.enq {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  width: 100%;
  animation: fade 0.4s ease both;
}

@keyframes fade { from { opacity: 0; transform: translateY(6px); } }

.enq-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}

.enq input[type="text"],
.enq input[type="email"],
.enq textarea {
  width: 100%;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink);
  background: #06080f;
  border: 1px solid var(--edge);
  border-radius: 2px;
  padding: 0.6rem 0.7rem;
  resize: none;
  transition: border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
}
.enq textarea { line-height: 1.5; }
.enq ::placeholder { color: var(--muted); opacity: 1; }
.enq input:focus,
.enq textarea:focus {
  outline: none;
  border-color: var(--blue);
  background: rgba(59, 134, 247, 0.07);
  box-shadow: 0 0 0 3px rgba(59, 134, 247, 0.13);
}

.enq-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.enq-mail {
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--edge);
  transition: color 0.25s ease, border-color 0.25s ease;
}
.enq-mail:hover { color: var(--blue); border-color: var(--blue); }

/* While the mail is actually going out, the buttons give way to a live line.
   htmx adds .htmx-request to the form for exactly the length of the request. */
.enq-sending {
  display: none;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0;
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--ink-2);
}
.enq.htmx-request .enq-actions { display: none; }
.enq.htmx-request .enq-sending { display: flex; }

/* Same face, size and position as .enq-sending, so the word resolves in place
   rather than the panel appearing to restart. */
.enq-sent {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.85rem;
  background: var(--accent);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  width: fit-content;
  animation: fade 0.35s ease both;
}

.enq-caret {
  width: 0.5em;
  height: 1em;
  background: var(--blue);
  box-shadow: 0 0 10px rgba(59, 134, 247, 0.8);
  animation: caret 1.05s steps(1, end) infinite;
}

.enq-err {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.68rem;
  color: #ff8f7d;
}

.htmx-request .btn[type="submit"] { opacity: 0.5; }

/* ==========================================================================
   Footer
   ========================================================================== */

.footbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 1rem;
  align-items: center;
  padding: 0.7rem var(--pad);
  border-top: 1px solid var(--edge);
  background: linear-gradient(0deg, rgba(255, 255, 255, 0.018), transparent);
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.foot-b {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--ink-2);
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.flag {
  width: 1.35em;
  height: 0.9em;
  border-radius: 1px;
  flex: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.16);
}
.foot-c {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
}
.foot-mail {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid var(--edge-hi);
  padding-bottom: 1px;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.foot-mail:hover { color: var(--blue); border-color: var(--blue); }

/* ==========================================================================
   Narrow screens
   ========================================================================== */

@media (max-width: 860px) {
  :root { --pad: 1.2rem; }

  .topbar { padding-block: 0.8rem; }
  .brand { --brand-pad-x: 0.7rem; --brand-pad-y: 0.42rem; --bracket: 8px; }
  .brand-mark { height: 1.3rem; }

  .stage { gap: 1rem; }
  .services { font-size: 0.66rem; letter-spacing: 0.2em; gap: 0.6rem; }
  .stage-note { margin-top: 1.1rem; gap: 0.7rem; font-size: 0.85rem; }

  .term-body { padding: 1.4rem 1.2rem 1.1rem; height: 15rem; }
  .run-line, .run-cursor { font-size: 5.6vw; }
  .run-cmd { font-size: 0.82rem; }

  .footbar {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 0.55rem;
    text-align: center;
  }
  .foot-a { display: none; }
  .foot-c { justify-content: center; }
}

/* The top bar can hold the logo, the ticker and the demo button, but not on a
   phone. The button wins — it is the one thing up there worth tapping. */
@media (max-width: 760px) {
  .ticker { display: none; }
}

@media (max-width: 520px) {
  .ticker-label { display: none; }

  /* 5.2vw is the largest that keeps a 24-character answer inside the terminal
     on a 320px screen, assuming the widest monospace fallback (0.6em advance).
     At 6vw the last word was being clipped on every phone. */
  .run-line, .run-cursor { font-size: 5.2vw; }

  /* Tall enough for the contact form, which is the tallest thing that goes in
     the box — at 13.5rem the send button fell outside it. */
  .term-body { height: 15.5rem; }

  /* Buy that height back from the surrounding space, so the page still fits a
     568px-tall screen. */
  .stage { padding-block: 0.9rem; gap: 0.8rem; }
  .stage-note { margin-top: 0.8rem; }

  .drawer-body { padding: 1.1rem 1rem; }
}

/* The narrowest phones still in use cannot hold the logo, its frame and the
   demo button side by side at full size. */
@media (max-width: 380px) {
  .topbar { gap: 0.5rem; }
  .brand { --brand-pad-x: 0.6rem; --brand-pad-y: 0.36rem; --bracket: 7px; }
  .brand-mark { height: 1.1rem; }
  .demo-cta { padding: 0.55rem 0.7rem; font-size: 0.64rem; }
}

/* Short landscape phones. There is not enough height for a fixed window that
   also fits the contact form, so here the window is allowed to size to its
   content rather than clip it. */
@media (max-height: 520px) and (orientation: landscape) {
  .stage { gap: 0.7rem; }
  .stage-note { display: none; }
  .term-body { height: auto; min-height: 7rem; padding: 1rem 1.2rem; }
  .run { gap: 0.6rem; }
  .run-line, .run-cursor { font-size: 3.4vw; }
}

/* ==========================================================================
   Motion preferences — show the finished state, skip the typing
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .bg-scan { display: none; }
  .bg-grid { animation: none; }
  .typed { animation: none; width: auto; }
  .run-cursor, .ticker-caret { animation: none; opacity: 1; }
  .enq, .tr, .run-note, .drawer-outro { animation: none; }
  /* Hold the sweep mid-travel rather than dropping to a bare gradient edge. */
  .brand-mark { animation: none; background-position: 50% 0; }
  .enq-caret { animation: none; }
  .btn-glow { animation: none; filter: drop-shadow(0 0 8px rgba(59, 134, 247, 0.5)); }
  .drawer { animation: none; }
  .btn { transition: none; }
}
