/* ==========================================================================
   Saez Automation — site styles

   Single stylesheet, no build step, no framework. Edited by hand.

   The palette comes from the LOGO ARTWORK, sampled pixel-for-pixel:
     cream #F9F6F3  background, site-wide — matches the logo's own background
     navy  #0B1B2D  all text and headlines
     gold  #E18C10  buttons and accents — never a large background area

   Gold is a fill colour, not a text colour: it only reaches AA contrast on
   cream once darkened to --gold-text. See the token block for the numbers.

   Mobile-first is mandatory (CLAUDE.md §10/§12): every rule below is written
   for narrow screens first, and widened inside min-width media queries. Real
   bugs have been caught this way before — form-field overflow on the Start
   page, empty placeholder blocks on the homepage.
   ========================================================================== */

/* --------------------------------------------------------------- tokens */

:root {
  /* ---------------------------------------------------------------- brand --
     SAMPLED FROM THE ACTUAL LOGO FILES, not from an earlier spec.

     docs/04 previously recorded navy #1E3A52 and amber #B8703F. The real logo
     artwork uses a much deeper navy and a brighter gold, and the two together
     read as a different brand — a brown terracotta beside a warm gold looks
     like a mistake. The logo is what a customer sees first, so the site was
     retuned to it rather than the other way round. Values below are pixel
     samples from assets/logo-lockup.png. */

  --cream: #f9f6f3;        /* exact logo background, so the lockup blends in */
  --navy: #0b1b2d;         /* deep logo navy — all text and headlines */
  --gold: #e18c10;         /* logo gold — button fills and accents */

  /* Gold is only legible as SMALL TEXT once it is this dark.
     #E18C10 on cream is 2.45:1 — fine as a shape, unreadable as a word.
     #8F5A0A on cream is 5.37:1 and passes AA. Used for eyebrows and small
     accents; never for large fills, which stay the true brand gold. */
  --gold-text: #8f5a0a;

  /* Buttons are GOLD WITH NAVY TEXT, not gold with white.
     White on gold measures 2.64:1 and fails badly. Navy on gold measures
     6.58:1 and passes comfortably — and dark-on-gold reads warmer and more
     confident than white-on-brown ever did. */
  --gold-hover: #c87a0b;

  /* Warm neutrals, mixed toward the paper rather than toward grey. The old
     tints were mixed toward navy, which is what made the whole page read cold.
     Kept as explicit hexes so text never lands on an unexpected backdrop. */
  --ink-70: #4a5d70;       /* secondary text — 6.31:1 on cream */
  --line: #e7ded3;         /* hairlines and card borders, warm not grey */
  --sand: #f3ece2;         /* tinted section background */
  --sand-deep: #ede3d6;    /* the warmer end, for stacked tints */

  --measure: 68ch;
  --radius: 14px;
  --radius-lg: 20px;
  --gutter: 1.25rem;

  /* Warm shadows. A neutral black shadow on a cream page reads as dirt; tinting
     it toward the navy keeps it feeling like the same light source. */
  --shadow-sm: 0 1px 2px rgba(11, 27, 45, 0.04), 0 2px 8px rgba(11, 27, 45, 0.04);
  --shadow-md: 0 2px 4px rgba(11, 27, 45, 0.04), 0 8px 24px rgba(11, 27, 45, 0.06);

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-display: ui-serif, Georgia, "Times New Roman", serif;
}

/* ----------------------------------------------------------------- base */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--cream);
  color: var(--navy);
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.2;
  margin: 0 0 0.5em;
  font-weight: 600;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2rem, 6vw, 3.25rem); }
h2 { font-size: clamp(1.5rem, 4vw, 2.125rem); }
h3 { font-size: 1.1875rem; font-family: var(--font); font-weight: 650; }

p { margin: 0 0 1rem; max-width: var(--measure); }

a { color: var(--navy); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--gold-text); }

/* A visible focus ring on every interactive element. Non-negotiable: without
   it the site is unusable by keyboard, and nothing about the brand requires
   hiding it. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

img, svg { max-width: 100%; height: auto; display: block; }

/* The [hidden] attribute only sets `display: none` via a low-specificity UA
   rule, so ANY `display` declaration in this file silently defeats it. That bit
   a real element: an empty "Phone" row on a portal lead stayed visible because
   `.lead__meta div { display: flex }` outranked it. Making it !important here
   means `el.hidden = true` reliably hides things, which is what every bit of JS
   in this project assumes. */
[hidden] { display: none !important; }

hr { border: 0; border-top: 1px solid var(--line); margin: 3rem 0; }

/* ------------------------------------------------------------- utilities */

.wrap {
  width: 100%;
  max-width: 68rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.wrap--narrow { max-width: 44rem; }

.section { padding-block: 3rem; }
@media (min-width: 48rem) { .section { padding-block: 4.5rem; } }

.section--tint { background: var(--sand); }

.eyebrow {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  /* --gold-text, not --gold: brand gold on cream is 2.45:1 and unreadable at
     this size. */
  color: var(--gold-text);
  margin: 0 0 0.75rem;
}

.lede { font-size: 1.1875rem; color: var(--ink-70); }

.center { text-align: center; }
.center p { margin-inline: auto; }

/* Screen-reader-only, but focusable — used by the skip link. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: 0.5rem;
  top: -4rem;
  z-index: 100;
  background: var(--navy);
  color: var(--cream);
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  transition: top 0.15s ease;
}
.skip-link:focus { top: 0.5rem; color: var(--cream); }

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8125rem 1.5rem;
  border-radius: var(--radius);
  font-weight: 650;
  font-size: 1rem;
  line-height: 1.2;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  /* 44px minimum touch target — thumbs, not mice (CLAUDE.md §10). */
  min-height: 44px;
}

/* Gold fill, NAVY text. Navy on gold is 6.58:1; white on gold is 2.64:1 and
   fails. The dark-on-gold pairing is also simply warmer to look at. */
.btn--primary {
  background: var(--gold);
  color: var(--navy);
  border-color: var(--gold);
  box-shadow: var(--shadow-sm);
}
.btn--primary:hover {
  background: var(--gold-hover);
  border-color: var(--gold-hover);
  color: var(--navy);
  box-shadow: var(--shadow-md);
}

.btn--secondary { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn--secondary:hover { background: var(--navy); color: var(--cream); }

.btn--block { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.btn-row--center { justify-content: center; }

/* ------------------------------------------------------------------- nav */

.site-header {
  border-bottom: 1px solid var(--line);
  background: var(--cream);
  position: sticky;
  top: 0;
  z-index: 50;
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 68px;
}

.nav__logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  flex-shrink: 0;
  /* The lockup PNG carries the logo's own background (#F9F6F3), which is
     exactly --cream — so it sits on the header with no visible edge. If the
     header colour ever changes, this image needs a transparent version or the
     box will show. */
  line-height: 0;
}

.nav__logo-img {
  /* Constrained by HEIGHT, not width. The lockup is 3:1, so sizing by width
     made it 77px tall inside a 68px nav — it overflowed and clipped, which read
     as a stray box around the logo. Height-first keeps it inside the bar
     whatever the artwork's aspect ratio turns out to be. */
  height: 34px;
  width: auto;
}

@media (min-width: 56rem) {
  .nav__logo-img { height: 42px; }
}

.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.5rem 0.75rem;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--navy);
  min-height: 44px;
}

.nav__links {
  display: none;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Mobile: the menu opens as a stacked panel below the bar. Driven by a
   data attribute set in JS, so with JS disabled the links stay visible via
   the no-js rule at the bottom of this file rather than being unreachable. */
.nav__links[data-open="true"] {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: var(--cream);
  border-bottom: 1px solid var(--line);
  padding: 0.5rem var(--gutter) 1.25rem;
}

.nav__links a {
  display: block;
  padding: 0.75rem 0;
  text-decoration: none;
  font-weight: 550;
  border-bottom: 1px solid var(--sand);
}

.nav__links .btn { margin-top: 0.75rem; }

@media (min-width: 56rem) {
  .nav__toggle { display: none; }
  .nav__links,
  .nav__links[data-open="true"] {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 1.75rem;
    position: static;
    padding: 0;
    border: 0;
    background: none;
  }
  .nav__links a { padding: 0; border: 0; }
  .nav__links .btn { margin-top: 0; padding: 0.625rem 1.25rem; }
}

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

/* A warm wash behind the hero rather than flat cream.
   Two very soft radial tints — gold from the top right, sand from the left —
   so the top of every page has some light in it. Subtle enough that it reads
   as paper warmth, not as a gradient. */
.hero {
  padding-block: 3rem 2.5rem;
  position: relative;
  background:
    radial-gradient(60rem 28rem at 88% -10%, rgba(225, 140, 16, 0.10), transparent 60%),
    radial-gradient(48rem 26rem at 0% 0%, rgba(237, 227, 214, 0.75), transparent 65%);
}
@media (min-width: 48rem) { .hero { padding-block: 5rem 4rem; } }

/* The three trailing dots from the logo mark, reused as a section accent.
   docs/04 endorses original graphics in brand colours over sourced imagery;
   this is the cheapest possible version of that — it is literally part of the
   logo, so it can never look off-brand. */
.dots {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1.25rem;
}
.dots span {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--gold);
}
.dots span:nth-child(2) { opacity: 0.66; }
.dots span:nth-child(3) { opacity: 0.36; }

.center .dots { justify-content: center; }

.hero h1 { max-width: 16ch; }
.hero .lede { max-width: 52ch; font-size: 1.25rem; }

/* ---------------------------------------------------- split hero + example */

/* Stacks on mobile, two columns from tablet up. The illustration goes BELOW
   the copy on small screens — the headline and the button are what matter on a
   phone, and pushing them down for a decorative element would be backwards. */
.hero__inner { display: grid; gap: 2.5rem; }

@media (min-width: 56rem) {
  .hero__inner {
    grid-template-columns: 1.05fr 0.95fr;
    align-items: center;
    gap: 3.5rem;
  }
}

/**
 * The example exchange.
 *
 * Deliberately typographic rather than a screenshot: the product's whole output
 * is an email, so showing an email is showing the product. Nothing here implies
 * an app, a dashboard, or any interface that does not exist.
 */
.exchange {
  margin: 0;
  display: grid;
  gap: 0.75rem;
  position: relative;
}

.exchange__label {
  align-self: end;
  justify-self: start;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-70);
  background: var(--sand-deep);
  border-radius: 999px;
  padding: 0.25rem 0.6875rem;
  margin-bottom: 0.25rem;
}

.exchange__msg {
  background: #fffdfb;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.125rem 1.25rem;
  box-shadow: var(--shadow-sm);
}

/* The reply is the product's output — marked with the brand gold so the two
   sides of the conversation are never confused at a glance. */
.exchange__msg--reply {
  border-left: 3px solid var(--gold);
  box-shadow: var(--shadow-md);
}

.exchange__from {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-70);
}

.exchange__body {
  margin: 0 0 0.625rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  max-width: none;
}
.exchange__body:last-child { margin-bottom: 0; }

/* Three descending dots between the two messages — the same motif as the logo's
   trailing dots, doing the job of "and then, moments later". */
.exchange__arrow {
  display: flex;
  gap: 0.375rem;
  justify-content: center;
  padding: 0.125rem 0;
}
.exchange__arrow span {
  width: 0.375rem;
  height: 0.375rem;
  border-radius: 50%;
  background: var(--gold);
}
.exchange__arrow span:nth-child(2) { opacity: 0.6; }
.exchange__arrow span:nth-child(3) { opacity: 0.3; }

/* ----------------------------------------------------------------- cards */

/* Shared base class. docs/04 records a hard Webflow lesson that carried over
   as a naming convention here: DO NOT add page-specific rules to `.card`.
   Scope them with a modifier (.card--pricing) so the change cannot bleed into
   every other page using the base. */
.card {
  /* Slightly lighter than the page so it lifts, with a warm shadow rather than
     a hard outline. A 1px grey box on every card is most of what made the old
     layout feel like a spreadsheet. */
  background: #fffdfb;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  box-shadow: var(--shadow-sm);
}
@media (min-width: 48rem) { .card { padding: 2rem; } }

.card h3 { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

.grid { display: grid; gap: 1.25rem; }
@media (min-width: 48rem) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------- pricing */

.card--pricing { display: flex; flex-direction: column; }

.card--pricing .price {
  font-family: var(--font-display);
  font-size: 2.75rem;
  font-weight: 600;
  line-height: 1;
  margin: 0.5rem 0 0.25rem;
}
.card--pricing .price span {
  font-family: var(--font);
  font-size: 1rem;
  font-weight: 500;
  color: var(--ink-70);
}

.card--pricing .price-alt {
  font-size: 0.9375rem;
  color: var(--ink-70);
  margin-bottom: 1.25rem;
}

.card--pricing ul {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  flex-grow: 1;
}
.card--pricing li {
  padding-left: 1.625rem;
  margin-bottom: 0.625rem;
  position: relative;
}
.card--pricing li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.6em;
  width: 0.75rem; height: 0.4rem;
  border-left: 2px solid var(--gold);
  border-bottom: 2px solid var(--gold);
  transform: rotate(-45deg);
}

/* Honest labelling for the tier that is not built yet (CLAUDE.md §0). */
.badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold);
  border: 1px solid var(--gold);
  border-radius: 999px;
  padding: 0.25rem 0.625rem;
  margin-bottom: 0.5rem;
}

/* -------------------------------------------------------- billing toggle */

.billing-toggle { border: 0; margin: 0 0 2rem; padding: 0; }

.billing-toggle__options {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px;
  background: var(--sand);
}

/* The radios themselves are visually hidden but still focusable and still the
   thing being clicked — the labels are the visible control. Keeps arrow-key
   navigation and screen-reader semantics for free. */
.billing-toggle input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.billing-toggle label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 1.125rem;
  border-radius: 999px;
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  min-height: 40px;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.billing-toggle label span {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--gold);
}

.billing-toggle input:checked + label {
  background: var(--cream);
  box-shadow: 0 1px 3px rgba(30, 58, 82, 0.12);
}
.billing-toggle input:checked + label span { color: var(--gold); }

/* The radio is invisible, so its focus ring has to be drawn on the label. */
.billing-toggle input:focus-visible + label {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
}

@media (max-width: 26rem) {
  /* Two full-width rows rather than a cramped pill on small phones. */
  .billing-toggle__options { display: flex; width: 100%; border-radius: var(--radius); }
  .billing-toggle label { flex: 1; justify-content: center; border-radius: calc(var(--radius) - 2px); }
}

/* ----------------------------------------------------------------- steps */

.steps { counter-reset: step; list-style: none; margin: 0; padding: 0; }

.step { counter-increment: step; position: relative; padding-left: 3.25rem; margin-bottom: 2rem; }
.step::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 2.25rem; height: 2.25rem;
  border-radius: 50%;
  border: 2px solid var(--gold);
  color: var(--gold);
  font-family: var(--font-display);
  font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.step h3 { margin-bottom: 0.25rem; }
.step p { margin-bottom: 0; }

/* ----------------------------------------------------------------- forms */

.form { display: grid; gap: 1.125rem; }

/* Honeypot — a field only a bot fills in (site/start.html, functions/_lib/spam.js).
   Deliberately NOT `display:none` or the `hidden` attribute: some bots skip
   fields hidden that way, and a honeypot a bot ignores is useless. Positioning
   it off-screen keeps it in the DOM and fillable while putting it nowhere a
   person can see or reach. aria-hidden and tabindex="-1" in the markup cover
   screen readers and keyboard navigation. */
.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.field { display: grid; gap: 0.375rem; }

.field label { font-weight: 600; font-size: 0.9375rem; }
.field .hint { font-size: 0.875rem; color: var(--ink-70); }

.field input,
.field select,
.field textarea {
  /* width:100% + border-box is what stops the overflow bug that mobile QA
     caught on this form before. Do not remove either half. */
  width: 100%;
  font: inherit;
  color: var(--navy);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 0.875rem;
  min-height: 44px;
}

.field textarea { min-height: 8rem; resize: vertical; }

.field input:focus,
.field select:focus,
.field textarea:focus { border-color: var(--gold); }

.form__note { font-size: 0.875rem; color: var(--ink-70); }

.form-status { border-radius: var(--radius); padding: 0.875rem 1rem; font-size: 0.9375rem; }
.form-status[hidden] { display: none; }
.form-status--ok { background: var(--sand); border: 1px solid var(--line); }
.form-status--error { background: #fdf3ee; border: 1px solid var(--gold); }

/* ------------------------------------------------------------------- faq */

.faq details {
  border-bottom: 1px solid var(--line);
  padding: 1.125rem 0;
}
.faq summary {
  cursor: pointer;
  font-weight: 650;
  font-size: 1.0625rem;
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: flex-start;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  color: var(--gold);
  font-size: 1.5rem;
  line-height: 1;
  flex-shrink: 0;
}
.faq details[open] summary::after { content: "\2212"; }
.faq details p { margin-top: 0.75rem; margin-bottom: 0; color: var(--ink-70); }

/* ---------------------------------------------------------------- prose */

/* Legal pages. Narrow measure, clear hierarchy, nothing decorative. */
.prose h2 { margin-top: 2.5rem; font-size: 1.375rem; }
.prose h3 { margin-top: 1.75rem; }
.prose ul, .prose ol { max-width: var(--measure); padding-left: 1.25rem; }
.prose li { margin-bottom: 0.5rem; }
.prose__meta { color: var(--ink-70); font-size: 0.9375rem; }

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

.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 2.5rem;
  margin-top: 1rem;
  font-size: 0.9375rem;
}

.site-footer__inner { display: grid; gap: 1.5rem; }
@media (min-width: 48rem) {
  .site-footer__inner { grid-template-columns: 2fr 1fr; align-items: start; }
}

.site-footer p { color: var(--ink-70); margin-bottom: 0.5rem; }

/* Legal links only. Blog/Docs/Guides/Careers/Press/News and social icons were
   deliberately removed from the old site because they pointed nowhere — dead
   links contradict the honesty brand value (docs/03, docs/05). Do not add a
   link here until the page it points at actually exists. */
.site-footer ul { list-style: none; margin: 0; padding: 0; display: flex; gap: 1.25rem; flex-wrap: wrap; }

/* ------------------------------------------------------------ flow figure */

.flow { margin: 2rem 0; }
.flow svg { width: 100%; height: auto; }
.flow figcaption { font-size: 0.9375rem; color: var(--ink-70); margin-top: 0.75rem; }

/* --------------------------------------------------------------- no-js */

/* If JS never runs, the mobile menu button cannot work — so hide the button
   and show the links inline instead. A visitor on a broken connection still
   gets a fully navigable site. */
.no-js .nav__toggle { display: none; }
.no-js .nav__links {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
}
.no-js .nav__links a { border: 0; padding: 0; }

/* ==========================================================================
   MOTION
   Added 2026-07-28. Driven by assets/js/motion.js.

   EVERYTHING HERE IS OPT-IN VIA A CLASS THAT JAVASCRIPT ADDS. Nothing below
   hides content on its own. If the script never runs, the page renders exactly
   as it would without this block — no invisible sections, no blank page.
   That is the whole reason the `.reveal` class is applied from JS rather than
   sitting in the markup.
   ========================================================================== */

/* ------------------------------------------------------------- reveals */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) var(--reveal-delay, 0ms),
    transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1) var(--reveal-delay, 0ms);
}

.reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------- rotating example stack */

.exchange-stack { position: relative; }

.exchange__industry {
  margin: 0 0 0.625rem;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold-text);
}

/**
 * The one-line "what this shows" caption under each example.
 *
 * It exists because four examples that all read the same way are worth about as
 * much as one. Each slide demonstrates a different behaviour — speed, chasing a
 * missing number, refusing to quote, admitting a limit — and without a caption a
 * visitor skims four polite emails and never notices the difference.
 *
 * ink-70 on cream is 6.3:1, so this passes AA at 13px. Do NOT lighten it to make
 * it recede; muted-grey captions are the single most common way small print
 * quietly drops below contrast minimums.
 */
.exchange__shows {
  margin: 0.25rem 0 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--line);
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--ink-70);
  max-width: none;
}
.exchange__shows strong { color: var(--navy); }

/* The two messages rise in one after the other on each swap, so the sequence
   reads as "enquiry, then reply" rather than both appearing at once. */
.exchange.is-swapping .exchange__msg {
  animation: exchange-in 0.5s cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.exchange.is-swapping .exchange__arrow { animation: exchange-in 0.5s ease both 0.16s; }
.exchange.is-swapping .exchange__msg--reply { animation-delay: 0.26s; }
/* Last in, after the reply it describes. */
.exchange.is-swapping .exchange__shows { animation: exchange-in 0.5s ease both 0.4s; }

@keyframes exchange-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.exchange__nav {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  margin-top: 1.125rem;
}

.exchange__dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border-radius: 50%;
  border: 0;
  background: var(--line);
  cursor: pointer;
  transition: background-color 0.2s ease, transform 0.2s ease;
}
.exchange__dot[aria-selected="true"] { background: var(--gold); transform: scale(1.25); }

/* The dot itself is 8px — far below a usable touch target. This grows the hit
   area to 44px without changing how it looks (CLAUDE.md §10). */
.exchange__dot::before {
  content: "";
  position: absolute;
  width: 44px;
  height: 44px;
  margin: -18px;
}
.exchange__nav { position: relative; }
.exchange__dot { position: relative; }

/* ------------------------------------------------------------------ demo */

.demo { margin: 0; }

.demo__stage {
  display: grid;
  gap: 0.75rem;
}

.demo__step {
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: 0.875rem;
  align-items: start;
  padding: 1rem 1.125rem;
  background: #fffdfb;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  /* TEXT IS NEVER DIMMED. An earlier version rested these at 0.45 opacity,
     which looked fine but pushed the body copy below AA contrast for anyone
     who arrived before the animation ran — or if it never ran at all. The
     progression is carried entirely by the border, the shadow and the number
     pill, none of which are load-bearing for reading. */
  transition: box-shadow 0.45s ease, border-color 0.45s ease,
              background-color 0.45s ease;
}

.demo__step.is-active {
  border-color: var(--gold);
  box-shadow: var(--shadow-md);
}
.demo__step.is-done { border-color: var(--line); }

.demo__num {
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--font-display);
  font-weight: 600;
  border: 2px solid var(--line);
  color: var(--ink-70);
  transition: background-color 0.35s ease, border-color 0.35s ease, color 0.35s ease;
}
.demo__step.is-active .demo__num,
.demo__step.is-done .demo__num {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--navy);
}

.demo__step h3 { margin: 0 0 0.25rem; font-size: 1rem; }
.demo__step p { margin: 0; font-size: 0.9375rem; color: var(--ink-70); max-width: none; }

.demo__replay {
  justify-self: center;
  margin-top: 1rem;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.5rem 1.125rem;
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink-70);
  cursor: pointer;
  min-height: 44px;
}
.demo__replay:hover { border-color: var(--gold); color: var(--navy); }

/* -------------------------------------------------- website build examples */

/* Screenshots of real builds from the client-site template, shown on
   /pricing#website. The frame is drawn in CSS rather than baked into the
   image so the screenshots stay plain page captures — retakeable with two
   commands when the template changes, no image editing involved.

   HONESTY CONSTRAINT (CLAUDE.md §0): these are labelled example builds of
   fictional businesses, in the caption visible on the page — not portfolio
   pieces, because no client site exists yet. When a real client site ships
   and the client agrees, a real screenshot replaces one of these and the
   caption changes to say so. */

.example-browser {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: #fff;
  box-shadow: var(--shadow-sm);
}

.example-browser__bar {
  display: flex;
  gap: 0.375rem;
  padding: 0.5rem 0.75rem;
  background: var(--sand);
  border-bottom: 1px solid var(--line);
}

.example-browser__dot {
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 50%;
  background: var(--line);
}

.example-browser img {
  display: block;
  width: 100%;
  height: auto;
}

/* The strip of remaining pages under each hero shot. Its job is to make the
   3-vs-5 difference *countable* at a glance — the thumbnails are evidence of
   page count, not detail to squint at. */
.example-thumbs {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
  margin-top: 0.75rem;
}

@media (min-width: 40rem) {
  .example-thumbs { grid-template-columns: repeat(4, 1fr); }
}

.example-thumb { margin: 0; }

.example-thumb .example-browser__bar { padding: 0.25rem 0.5rem; }
.example-thumb .example-browser__dot { width: 0.375rem; height: 0.375rem; }

.example-thumb figcaption {
  margin-top: 0.375rem;
  font-size: 0.8125rem;
  color: var(--ink-70);
  text-align: center;
}

/* The honesty line under each example. Slightly quieter than body text but
   still comfortably readable — it is a disclosure, not small print. */
.example-note {
  margin-top: 0.75rem;
  font-size: 0.875rem;
  color: var(--ink-70);
}

/* ------------------------------------------------------- reduced motion */

/* The base reset near the top of this file already kills durations. These two
   also strip the starting offsets, so nothing can be left mid-transition. */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1 !important; transform: none !important; }
  .demo__step { opacity: 1 !important; transform: none !important; }
}

/* ------------------------------------------------------------------ print */

/* Anything mid-reveal would print blank. Force every animated element to its
   finished state on paper, where there is no scrolling to trigger it. */
@media print {
  .reveal,
  .demo__step,
  .exchange { opacity: 1 !important; transform: none !important; }
  [data-exchange][hidden] { display: block !important; }
  .site-header, .exchange__nav, .demo__replay, .skip-link { display: none !important; }
}
