/**
 * Launch Special — removable sale layer.
 *
 * Ends Aug 1 2026. To remove: delete this file, launch-sale.js, the three
 * <link>/<script> lines, and the [data-ls] markup. Nothing else knows it existed.
 *
 * FAIL CLOSED: every sale element is display:none until launch-sale.js confirms
 * the window is open and stamps [data-ls-on] on <html>. If the script fails, the
 * site renders normally at list price — never a discount we can't honour.
 *
 * Two nav modes, because the pages genuinely differ:
 *   marketing.html   .nav is position:fixed  → ribbon is fixed, nav shifts down
 *   pricing / start  .nav is position:sticky → ribbon sits in flow, scrolls away
 */

:root {
  --ls-ribbon-h: 42px;
  --ls-ease: cubic-bezier(0.32, 0.72, 0, 1);
  --ls-ember: #e07a4a;
  --ls-ember-line: rgba(224, 122, 74, 0.42);
  --ls-ink: #f4f2ec;
  --ls-ink-soft: #d8dbd4;
  --ls-muted: #a8aea6;
  --ls-mute-2: #7a8078;
  --ls-bg-deep: #0c0d0a;
  --ls-mono: "Geist Mono", ui-monospace, Menlo, monospace;
  --ls-display: Newsreader, Georgia, serif;
}

[data-ls] { display: none; }

/* ─────────── ribbon ─────────── */

.ls-ribbon {
  position: relative;
  z-index: 110;
  height: var(--ls-ribbon-h);
  /* marketing.html has no global border-box, so without this the 1px border makes
     the ribbon 43px tall while the nav is offset by 42 — the nav then covers the
     ribbon's own bottom hairline. */
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 0 20px;
  background: var(--ls-bg-deep);
  border-bottom: 1px solid var(--ls-ember-line);
  font-family: var(--ls-mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ls-muted);
  white-space: nowrap;
  overflow: hidden;
}
[data-ls-on] .ls-ribbon[data-ls] { display: flex; }

/* Fixed-nav pages: ribbon is fixed, nav shifts down.
   Two body classes, because content offset lives in different places:
     body.ls-fixed-nav  — marketing.html (body padding-top owns the offset)
     body.ls-seo-fixed  — SEO shell pages (seo.css pads .page, not body)
   Sticky-nav pages (pricing, samples, check-your-name, start) never get either
   class — the ribbon sits in flow and scrolls away with the page.

   Sibling rules (`.ls-ribbon--fixed ~ .nav|~ .page`) support early paint: pages
   that ship the ribbon in HTML + set data-ls-on in a blocking head script do not
   need a body class for the first frame. Without that, every link click flashes
   as the deferred script injects the bar and shoves content down. */
.ls-ribbon--fixed { position: fixed; top: 0; left: 0; right: 0; }
[data-ls-on] body.ls-fixed-nav .nav,
[data-ls-on] body.ls-seo-fixed .nav,
[data-ls-on] .ls-ribbon--fixed ~ .nav,
[data-ls-on] .ls-ribbon--fixed ~ header.nav { top: var(--ls-ribbon-h); }
[data-ls-on] body.ls-fixed-nav { padding-top: calc(var(--site-nav-h, 72px) + var(--ls-ribbon-h)); }
[data-ls-on] body.ls-seo-fixed .page,
[data-ls-on] .ls-ribbon--fixed ~ .page {
  padding-top: calc(var(--site-nav-h, 72px) + var(--ls-ribbon-h));
}

.ls-ribbon .ls-pip { display: inline-flex; align-items: center; gap: 9px; color: var(--ls-ember); }
.ls-ribbon .ls-pip::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ls-ember);
  box-shadow: 0 0 0 3px rgba(224, 122, 74, 0.22);
  animation: ls-pulse 2.4s var(--ls-ease) infinite;
}
@keyframes ls-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(224, 122, 74, 0.22); }
  50%      { box-shadow: 0 0 0 7px rgba(224, 122, 74, 0); }
}
.ls-ribbon b { color: var(--ls-ember); font-weight: 700; }
.ls-ribbon i { color: var(--ls-mute-2); font-style: normal; margin: 0 2px; }
.ls-ribbon .ls-code { color: var(--ls-ink); letter-spacing: 0.18em; }
.ls-ribbon .ls-left { font-variant-numeric: tabular-nums; color: var(--ls-ink-soft); }
.ls-ribbon a {
  color: var(--ls-muted);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.24s var(--ls-ease), border-color 0.24s var(--ls-ease);
}
.ls-ribbon a:hover { color: var(--ls-ember); border-color: var(--ls-ember-line); }
.ls-ribbon a:focus-visible { outline: 2px solid var(--ls-ember); outline-offset: 3px; border-radius: 2px; }

/* The ribbon is nowrap+hidden, so it must never hold more than fits — a clipped
   ribbon eats the deadline. Shed content in two stages; the discount, the code
   and the deadline survive to 320px. */
@media (max-width: 1000px) {
  .ls-ribbon .ls-hide-s { display: none; }
  .ls-ribbon { gap: 12px; }
}
@media (max-width: 760px) {
  .ls-ribbon .ls-pip-t { display: none; }
  .ls-ribbon { font-size: 10px; gap: 8px; letter-spacing: 0.06em; padding: 0 12px; }
  .ls-ribbon i { margin: 0 1px; }
}

/* ─────────── hero console (marketing.html) ─────────── */

.ls-console {
  position: relative;
  z-index: 2;
  max-width: 720px;
  margin: 28px auto 0;
  border: 1px solid var(--ls-ember-line);
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(224, 122, 74, 0.1), rgba(224, 122, 74, 0.03) 60%, transparent);
  padding: 24px 28px 22px;
  grid-template-columns: auto 1px 1fr;
  gap: 0 28px;
  align-items: center;
  text-align: left;
}
/* Short laptop viewports: keep domain claim CTA in first screen */
@media (max-height: 900px) {
  .ls-console {
    margin-top: 14px;
    padding: 14px 18px 12px;
  }
  .ls-count .ls-n { font-size: 48px; }
  .ls-count .ls-u { margin-top: 4px; font-size: 10px; }
  .ls-count .ls-clock { margin-top: 4px; font-size: 11px; }
  .ls-pitch h2 { font-size: clamp(18px, 2.2vw, 24px); margin: 0; }
  .ls-pitch p { display: none; } /* ribbon + chip already carry the offer */
  .ls-row { margin-top: 10px; gap: 10px; }
  .ls-chip, .ls-go { min-height: 36px; }
}
@media (max-height: 760px) {
  .ls-console {
    margin-top: 10px;
    padding: 10px 14px;
    grid-template-columns: auto 1px 1fr;
  }
  .ls-count .ls-n { font-size: 40px; }
  .ls-count .ls-clock { display: none; }
}
[data-ls-on] .ls-console[data-ls] { display: grid; }
.ls-console::before {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: 16px;
  pointer-events: none;
  background: radial-gradient(120% 140% at 50% 0%, rgba(224, 122, 74, 0.16), transparent 60%);
  opacity: 0.7;
}
.ls-count { position: relative; text-align: center; min-width: 132px; }
.ls-count .ls-n {
  display: block;
  font-family: var(--ls-display);
  font-style: italic;
  font-weight: 500;
  font-size: 76px;
  line-height: 0.92;
  color: var(--ls-ember);
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.ls-count .ls-u {
  display: block;
  margin-top: 8px;
  font-family: var(--ls-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ls-muted);
}
.ls-count .ls-clock {
  display: block;
  margin-top: 12px;
  font-family: var(--ls-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--ls-ink-soft);
  font-variant-numeric: tabular-nums;
}
.ls-rule {
  background: linear-gradient(180deg, transparent, var(--ls-ember-line), transparent);
  width: 1px;
  height: 104px;
}
.ls-pitch { position: relative; }
.ls-pitch .ls-pip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--ls-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ls-ember);
  margin-bottom: 12px;
}
.ls-pitch .ls-pip::before {
  content: "";
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ls-ember);
  box-shadow: 0 0 0 3px rgba(224, 122, 74, 0.22);
  animation: ls-pulse 2.4s var(--ls-ease) infinite;
}
.ls-pitch h2 {
  margin: 0;
  font-family: var(--ls-display);
  font-weight: 500;
  font-size: 28px;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: var(--ls-ink);
}
/* Home hero console: center the whole pitch stack as one unit.
   Centering only the label/h2 (while body stays left + max-width) pushed the
   headline right of the copy block — equal pitch padding, uneven content mass. */
.ls-console:not(.ls-console--start) .ls-pitch {
  text-align: center;
}
.ls-console:not(.ls-console--start) .ls-pitch .ls-pip {
  display: flex;
  width: max-content;
  margin-inline: auto;
  margin-bottom: 12px;
}
.ls-console:not(.ls-console--start) .ls-pitch h2 {
  text-align: center;
}
.ls-console:not(.ls-console--start) .ls-pitch p {
  margin-inline: auto;
}
.ls-console:not(.ls-console--start) .ls-row {
  justify-content: center;
}
.ls-pitch h2 em { font-style: italic; color: var(--ls-ember); }
.ls-pitch p { margin: 12px 0 0; font-size: 15px; line-height: 1.6; color: var(--ls-muted); max-width: 40ch; }
.ls-row { display: flex; align-items: center; gap: 16px; margin-top: 20px; flex-wrap: wrap; }

.ls-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: 999px;
  border: 1px dashed var(--ls-ember-line);
  background: rgba(224, 122, 74, 0.07);
  font-family: var(--ls-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ls-ink);
  cursor: pointer;
  transition: background 0.24s var(--ls-ease), border-color 0.24s var(--ls-ease), transform 0.24s var(--ls-ease);
}
.ls-chip:hover { background: rgba(224, 122, 74, 0.14); border-color: var(--ls-ember); }
.ls-chip:active { transform: scale(0.98); }
.ls-chip:focus-visible { outline: 2px solid var(--ls-ember); outline-offset: 3px; }
.ls-chip .ls-k { color: var(--ls-muted); font-weight: 500; letter-spacing: 0.1em; }
.ls-chip .ls-copy { color: var(--ls-muted); font-size: 10px; letter-spacing: 0.08em; }

.ls-go {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  background: var(--ls-ember);
  color: #1a0f08;
  font-weight: 600;
  font-size: 14px;
  padding: 8px 8px 8px 20px;
  border-radius: 999px;
  text-decoration: none;
  transition: transform 0.24s var(--ls-ease), box-shadow 0.24s var(--ls-ease);
}
.ls-go .ls-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(26, 15, 8, 0.12);
  transition: transform 0.24s var(--ls-ease), background 0.24s var(--ls-ease);
}
.ls-go:hover { transform: translateY(-1px); box-shadow: 0 12px 28px -12px rgba(224, 122, 74, 0.6); }
.ls-go:hover .ls-ico { transform: translate(2px, -1px) scale(1.05); background: rgba(26, 15, 8, 0.2); }
.ls-go:active { transform: scale(0.98); }
.ls-go:focus-visible { outline: 2px solid var(--ls-ink); outline-offset: 3px; }

@media (max-width: 720px) {
  .ls-console { grid-template-columns: 1fr; gap: 24px; text-align: center; padding: 28px 24px; }
  .ls-rule { width: 100%; height: 1px; background: linear-gradient(90deg, transparent, var(--ls-ember-line), transparent); }
  .ls-pitch p { margin-inline: auto; }
  .ls-row { justify-content: center; }
  .ls-count .ls-n { font-size: 64px; }
}

/* ─────────── offer pill (pricing.html / start.html) ─────────── */

.ls-offer-wrap { justify-content: center; margin: 26px 0 44px; }
[data-ls-on] .ls-offer-wrap[data-ls] { display: flex; }
.ls-offer {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 11px 22px;
  border: 1px solid var(--ls-ember-line);
  border-radius: 999px;
  background: rgba(224, 122, 74, 0.07);
  font-family: var(--ls-mono);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ls-ink-soft);
  white-space: nowrap;
}
.ls-offer b { color: var(--ls-ember); font-weight: 700; }
.ls-offer i { color: var(--ls-mute-2); font-style: normal; }
@media (max-width: 560px) {
  .ls-offer { white-space: normal; text-align: center; letter-spacing: 0.08em; font-size: 11px; }
}

/* ─────────── price swap (pricing.html cards) ─────────── */

/* --ls-mute-2 measures 4.25:1 on the card surface — under the 4.5 floor. Small
   load-bearing text inside a card uses --ls-muted (7.59:1) instead. */
.ls-was {
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--ls-mute-2);
  text-decoration: line-through;
  text-decoration-color: rgba(224, 122, 74, 0.75);
  text-decoration-thickness: 1.5px;
  margin-right: 2px;
}
[data-ls-on] .ls-was[data-ls] { display: inline; }
.ls-save {
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  font-family: var(--ls-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ls-ember);
}
[data-ls-on] .ls-save[data-ls] { display: inline-flex; }
.ls-save::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--ls-ember); }
/* the instruction that earns the discount — never the faintest text on the page */
.ls-withcode {
  margin-top: 8px;
  font-family: var(--ls-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--ls-muted);
  text-transform: uppercase;
}
[data-ls-on] .ls-withcode[data-ls] { display: block; }
.ls-withcode b { color: var(--ls-ink); font-weight: 600; letter-spacing: 0.16em; }
.ls-cents { font-size: 0.58em; font-weight: 600; color: var(--ls-muted); }

/* The 25% comes off the one-time setup fee only. Hosting is not in the Stripe
   Session at all, so the coupon cannot reach it — but say so on the page, or a
   customer reasonably reads "25% off" as 25% off everything. */
.ls-un {
  margin-top: 4px;
  font-family: var(--ls-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ls-muted);
}
[data-ls-on] .ls-un[data-ls] { display: block; }

@media (prefers-reduced-motion: reduce) {
  .ls-ribbon .ls-pip::before,
  .ls-pitch .ls-pip::before { animation: none; }
  .ls-chip, .ls-go, .ls-go .ls-ico, .ls-ribbon a { transition: none; }
}
